]> git.saurik.com Git - wxWidgets.git/blob - src/os2/checklst.cpp
fix for bug 1371386, with some minor mods and cleanup
[wxWidgets.git] / src / os2 / checklst.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/os2/checklst.cpp
3 // Purpose: implementation of wxCheckListBox class
4 // Author: David Webster
5 // Modified by:
6 // Created: 10/13/99
7 // RCS-ID: $Id$
8 // Copyright: (c) David Webster
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // headers & declarations
14 // ============================================================================
15
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
18
19 #if wxUSE_CHECKLISTBOX && wxUSE_OWNER_DRAWN
20
21 #include "wx/object.h"
22 #include "wx/colour.h"
23 #include "wx/font.h"
24 #include "wx/bitmap.h"
25 #include "wx/window.h"
26 #include "wx/listbox.h"
27 #include "wx/ownerdrw.h"
28 #include "wx/settings.h"
29 #include "wx/dcmemory.h"
30 #include "wx/dcscreen.h"
31 #include "wx/checklst.h"
32 #include "wx/log.h"
33
34 #define INCL_PM
35 #include <os2.h>
36
37 // ----------------------------------------------------------------------------
38 // private functions
39 // ----------------------------------------------------------------------------
40
41 // get item (converted to right type)
42 #define GetItem(n) ((wxCheckListBoxItem *)(GetItem(n)))
43
44 // ============================================================================
45 // implementation
46 // ============================================================================
47
48 IMPLEMENT_DYNAMIC_CLASS(wxCheckListBox, wxListBox)
49
50 // ----------------------------------------------------------------------------
51 // declaration and implementation of wxCheckListBoxItem class
52 // ----------------------------------------------------------------------------
53
54 class wxCheckListBoxItem : public wxOwnerDrawn
55 {
56 friend class wxCheckListBox;
57 public:
58 //
59 // ctor
60 //
61 wxCheckListBoxItem( wxCheckListBox* pParent,
62 size_t nIndex
63 );
64
65 //
66 // Drawing functions
67 //
68 virtual bool OnDrawItem( wxDC& rDc,
69 const wxRect& rRect,
70 wxODAction eAct,
71 wxODStatus eStat
72 );
73
74 //
75 // Simple accessors
76 //
77 bool IsChecked(void) const { return m_bChecked; }
78 void Check(bool bCheck);
79 void Toggle(void) { Check(!IsChecked()); }
80
81 private:
82 bool m_bChecked;
83 wxCheckListBox* m_pParent;
84 size_t m_nIndex;
85 }; // end of CLASS wxCheckListBoxItem
86
87
88
89 wxCheckListBoxItem::wxCheckListBoxItem ( wxCheckListBox* pParent,
90 size_t nIndex)
91 :wxOwnerDrawn( wxEmptyString, true /* checkable */ )
92 {
93 m_bChecked = false;
94 m_pParent = pParent;
95 m_nIndex = nIndex;
96
97 //
98 // We don't initialize m_nCheckHeight/Width vars because it's
99 // done in OnMeasure while they are used only in OnDraw and we
100 // know that there will always be OnMeasure before OnDraw
101 //
102 SetMarginWidth(GetDefaultMarginWidth());
103 } // end of wxCheckListBoxItem::wxCheckListBoxItem
104
105
106
107 bool wxCheckListBoxItem::OnDrawItem ( wxDC& rDc,
108 const wxRect& rRect,
109 wxODAction eAct,
110 wxODStatus eStat )
111 {
112 wxRect vRect = rRect;
113
114 ::WinQueryWindowRect( m_pParent->GetHWND(), &rDc.m_vRclPaint );
115 if (IsChecked())
116 eStat = (wxOwnerDrawn::wxODStatus)(eStat | wxOwnerDrawn::wxODChecked);
117
118 //
119 // Unfortunately PM doesn't quite get the text position exact. We need to alter
120 // it down and to the right, just a little bit. The coords in rRect are OS/2
121 // coords not wxWidgets coords.
122 //
123 vRect.x += 5;
124 vRect.y -= 3;
125 if (wxOwnerDrawn::OnDrawItem( rDc, vRect, eAct, eStat))
126 {
127 size_t nCheckWidth = GetDefaultMarginWidth();
128 size_t nCheckHeight = m_pParent->GetItemHeight();
129 int nParentHeight;
130 int nX = rRect.GetX();
131 int nY = rRect.GetY();
132 int nOldY = nY;
133 wxColour vColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
134 wxPen vPenBack;
135 wxPen vPenPrev;
136
137 m_pParent->GetSize( NULL, &nParentHeight);
138
139 nY = nParentHeight - nY - nCheckHeight;
140 vPenBack = wxPen(vColour, 1, wxSOLID);
141
142 //
143 // Erase the 1-pixel border
144 //
145 rDc.SetPen(vPenBack);
146 rDc.DrawRectangle( nX, nY, nCheckWidth, nCheckHeight );
147
148 //
149 // Now we draw the smaller rectangle
150 //
151 nY++;
152 nCheckWidth -= 2;
153 nCheckHeight -= 2;
154
155 //
156 // Draw hollow gray rectangle
157 //
158 rDc.SetPen(*wxGREY_PEN);
159 rDc.DrawRectangle( nX, nY, nCheckWidth, nCheckHeight );
160
161 nX++;
162 if (IsChecked())
163 {
164 //
165 // Draw the check by loading the sys standard bitmap and drawing it
166 //
167 HBITMAP hChkBmp = ::WinGetSysBitmap( HWND_DESKTOP, SBMP_MENUCHECK );
168 POINTL vPoint = {nX, nOldY + 3};
169
170 ::WinDrawBitmap( rDc.GetHPS(),
171 hChkBmp,
172 NULL,
173 &vPoint,
174 NULL,
175 NULL,
176 DBM_NORMAL
177 );
178 }
179 return true;
180 }
181 return false;
182 } // end of wxCheckListBoxItem::OnDrawItem
183
184 //
185 // Change the state of the item and redraw it
186 //
187 void wxCheckListBoxItem::Check ( bool bCheck )
188 {
189 m_bChecked = bCheck;
190
191 //
192 // Index may be chanegd because new items were added/deleted
193 //
194 if (m_pParent->GetItemIndex(this) != (int)m_nIndex)
195 {
196 //
197 // Update it
198 //
199 int nIndex = m_pParent->GetItemIndex(this);
200
201 wxASSERT_MSG(nIndex != wxNOT_FOUND, wxT("what does this item do here?"));
202
203 m_nIndex = (size_t)nIndex;
204 }
205
206
207 wxCommandEvent vEvent( wxEVT_COMMAND_CHECKLISTBOX_TOGGLED,m_pParent->GetId());
208
209 vEvent.SetInt(m_nIndex);
210 vEvent.SetEventObject(m_pParent);
211 m_pParent->ProcessCommand(vEvent);
212 } // end of wxCheckListBoxItem::Check
213
214
215 // ----------------------------------------------------------------------------
216 // implementation of wxCheckListBox class
217 // ----------------------------------------------------------------------------
218
219 // define event table
220 // ------------------
221 BEGIN_EVENT_TABLE(wxCheckListBox, wxListBox)
222 EVT_CHAR(wxCheckListBox::OnChar)
223 EVT_LEFT_DOWN(wxCheckListBox::OnLeftClick)
224 END_EVENT_TABLE()
225
226
227
228 //
229 // Control creation
230 // ----------------
231 //
232
233 //
234 // Default ctor: use Create() to really create the control
235 //
236 wxCheckListBox::wxCheckListBox()
237 :wxCheckListBoxBase()
238 {
239 } // end of wxCheckListBox::wxCheckListBox
240
241 //
242 // Ctor which creates the associated control
243 //
244 wxCheckListBox::wxCheckListBox ( wxWindow* pParent,
245 wxWindowID vId,
246 const wxPoint& rPos,
247 const wxSize& rSize,
248 int nStrings,
249 const wxString asChoices[],
250 long lStyle,
251 const wxValidator& rVal,
252 const wxString& rsName)
253 :wxCheckListBoxBase()
254 {
255 Create( pParent, vId, rPos, rSize, nStrings, asChoices, lStyle | wxLB_OWNERDRAW, rVal, rsName );
256 } // end of wxCheckListBox::wxCheckListBox
257
258 wxCheckListBox::wxCheckListBox ( wxWindow* pParent,
259 wxWindowID vId,
260 const wxPoint& rPos,
261 const wxSize& rSize,
262 const wxArrayString& asChoices,
263 long lStyle,
264 const wxValidator& rVal,
265 const wxString& rsName )
266 :wxCheckListBoxBase()
267 {
268 wxCArrayString chs(asChoices);
269 Create( pParent, vId, rPos, rSize, chs.GetCount(), chs.GetStrings(),
270 lStyle | wxLB_OWNERDRAW, rVal, rsName );
271 } // end of wxCheckListBox::wxCheckListBox
272
273 void wxCheckListBox::Delete( int n )
274 {
275 wxCHECK_RET( n >= 0 && n < m_nNumItems,
276 wxT("invalid index in wxCheckListBox::Delete") );
277 wxListBox::Delete(n);
278
279 //
280 // Free memory
281 //
282 delete m_aItems[n];
283 m_aItems.RemoveAt(n);
284 } // end of wxCheckListBox::Delete
285
286 void wxCheckListBox::DoInsertItems(const wxArrayString& items, int pos)
287 {
288 // pos is validated in wxListBox
289 wxListBox::DoInsertItems( items, pos );
290 int n = items.GetCount();
291 for (int i = 0; i < n; i++)
292 {
293 wxOwnerDrawn* pNewItem = CreateItem((size_t)(pos + i));
294
295 pNewItem->SetName(items[i]);
296 m_aItems.Insert(pNewItem, (size_t)(pos + i));
297 ::WinSendMsg( (HWND)GetHWND(),
298 LM_SETITEMHANDLE,
299 (MPARAM)(i + pos),
300 MPFROMP(pNewItem)
301 );
302 }
303 } // end of wxCheckListBox::InsertItems
304
305 bool wxCheckListBox::SetFont ( const wxFont& rFont )
306 {
307 for (size_t i = 0; i < m_aItems.GetCount(); i++)
308 m_aItems[i]->SetFont(rFont);
309 wxListBox::SetFont(rFont);
310 return true;
311 } // end of wxCheckListBox::SetFont
312
313
314
315 //
316 // Create/retrieve item
317 // --------------------
318 //
319
320 //
321 // Create a check list box item
322 //
323 wxOwnerDrawn* wxCheckListBox::CreateItem ( size_t nIndex )
324 {
325 wxCheckListBoxItem* pItem = new wxCheckListBoxItem( this, nIndex );
326 return pItem;
327 } // end of wxCheckListBox::CreateItem
328
329
330
331 //
332 // Return item size
333 // ----------------
334 //
335 long wxCheckListBox::OS2OnMeasure ( WXMEASUREITEMSTRUCT* pItem )
336 {
337 if (!pItem)
338 pItem = (WXMEASUREITEMSTRUCT*)new OWNERITEM;
339 if (wxListBox::OS2OnMeasure(pItem))
340 {
341 POWNERITEM pStruct = (POWNERITEM)pItem;
342
343 //
344 // Save item height
345 //
346 m_nItemHeight = pStruct->rclItem.yTop - pStruct->rclItem.yBottom;
347
348 //
349 // Add place for the check mark
350 //
351 pStruct->rclItem.xRight += wxOwnerDrawn::GetDefaultMarginWidth();
352 return long(MRFROM2SHORT((USHORT)m_nItemHeight, (USHORT)(pStruct->rclItem.xRight - pStruct->rclItem.xLeft)));
353 }
354 return 0L;
355 } // end of wxCheckListBox::CreateItem
356
357
358
359 //
360 // Check items
361 // -----------
362 //
363 bool wxCheckListBox::IsChecked ( size_t uiIndex) const
364 {
365 return GetItem(uiIndex)->IsChecked();
366 } // end of wxCheckListBox::IsChecked
367
368 void wxCheckListBox::Check ( size_t uiIndex, bool bCheck )
369 {
370 GetItem(uiIndex)->Check(bCheck);
371 } // end of wxCheckListBox::Check
372
373
374
375 //
376 // Process events
377 // --------------
378 //
379 void wxCheckListBox::OnChar ( wxKeyEvent& rEvent )
380 {
381 if (rEvent.GetKeyCode() == WXK_SPACE)
382 GetItem(GetSelection())->Toggle();
383 else
384 rEvent.Skip();
385 } // end of wxCheckListBox::OnChar
386
387 void wxCheckListBox::OnLeftClick ( wxMouseEvent& rEvent )
388 {
389 //
390 // Clicking on the item selects it, clicking on the checkmark toggles
391 //
392 if (rEvent.GetX() <= wxOwnerDrawn::GetDefaultMarginWidth())
393 {
394 int nParentHeight;
395 wxScreenDC vDc;
396 wxCoord vHeight;
397
398 GetSize( NULL, &nParentHeight );
399 vDc.SetFont(GetFont());
400 vHeight = (wxCoord)(vDc.GetCharHeight() * 2.5);
401
402 //
403 // This, of course, will not work if the LB is scrolled
404 //
405 int nY = rEvent.GetY();
406
407 nY = nParentHeight - (nY + vHeight);
408
409 size_t nItem = (size_t)(nY / vHeight);
410
411 if (nItem < (size_t)m_nNumItems)
412 GetItem(nItem)->Toggle();
413 //
414 // else: it's not an error, just click outside of client zone
415 //
416 }
417 else
418 {
419 //
420 // Implement default behaviour: clicking on the item selects it
421 //
422 rEvent.Skip();
423 }
424 } // end of wxCheckListBox::OnLeftClick
425
426 #endif // wxUSE_CHECKLISTBOX && wxUSE_OWNER_DRAWN