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