]> git.saurik.com Git - wxWidgets.git/blame - src/os2/checklst.cpp
Don't crash when laying out wxGridBagSizer with only hidden elements.
[wxWidgets.git] / src / os2 / checklst.cpp
CommitLineData
0e320a79 1///////////////////////////////////////////////////////////////////////////////
84882850 2// Name: src/os2/checklst.cpp
0e320a79 3// Purpose: implementation of wxCheckListBox class
37f214d5 4// Author: David Webster
0616b838 5// Modified by:
37f214d5 6// Created: 10/13/99
37f214d5 7// Copyright: (c) David Webster
65571936 8// Licence: wxWindows licence
0e320a79
DW
9///////////////////////////////////////////////////////////////////////////////
10
11// ============================================================================
12// headers & declarations
13// ============================================================================
14
37f214d5
DW
15// For compilers that support precompilation, includes "wx.h".
16#include "wx/wxprec.h"
17
84882850 18#if wxUSE_CHECKLISTBOX && wxUSE_OWNER_DRAWN
37f214d5 19
e4db172a
WS
20#include "wx/checklst.h"
21
8e3f3880
WS
22#ifndef WX_PRECOMP
23 #include "wx/object.h"
e4db172a 24 #include "wx/log.h"
cdccdfab 25 #include "wx/window.h"
f38924e8 26 #include "wx/dcmemory.h"
11dbb4bf 27 #include "wx/dcscreen.h"
9eddec69 28 #include "wx/settings.h"
2a673eb1 29 #include "wx/listbox.h"
0bca0373 30 #include "wx/bitmap.h"
7cf41a5d 31 #include "wx/colour.h"
48a1108e 32 #include "wx/font.h"
8e3f3880
WS
33#endif
34
38400bb4 35#include "wx/os2/dc.h"
37f214d5 36#include "wx/ownerdrw.h"
0e320a79 37
37f214d5
DW
38#define INCL_PM
39#include <os2.h>
40
98fbab9e
VZ
41// ----------------------------------------------------------------------------
42// constants for base class
43// ----------------------------------------------------------------------------
44
45static const int CHECK_MARK_WIDTH = 15;
46
37f214d5
DW
47// ----------------------------------------------------------------------------
48// private functions
49// ----------------------------------------------------------------------------
50
51// get item (converted to right type)
52#define GetItem(n) ((wxCheckListBoxItem *)(GetItem(n)))
0e320a79
DW
53
54// ============================================================================
6463b9f5 55// implementation
0e320a79
DW
56// ============================================================================
57
37f214d5
DW
58// ----------------------------------------------------------------------------
59// declaration and implementation of wxCheckListBoxItem class
60// ----------------------------------------------------------------------------
61
62class wxCheckListBoxItem : public wxOwnerDrawn
63{
1de4baa3 64 friend class wxCheckListBox;
37f214d5 65public:
1de4baa3
DW
66 //
67 // ctor
68 //
aa61d352 69 wxCheckListBoxItem(wxCheckListBox* pParent, size_t nIndex);
1de4baa3
DW
70
71 //
72 // Drawing functions
73 //
84882850
WS
74 virtual bool OnDrawItem( wxDC& rDc,
75 const wxRect& rRect,
76 wxODAction eAct,
77 wxODStatus eStat
1de4baa3
DW
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()); }
37f214d5 86
98fbab9e
VZ
87 virtual wxString GetName() const { return m_pParent->GetString(m_nIndex); }
88
37f214d5 89private:
84882850
WS
90 bool m_bChecked;
91 wxCheckListBox* m_pParent;
92 size_t m_nIndex;
1de4baa3
DW
93}; // end of CLASS wxCheckListBoxItem
94
84882850
WS
95
96
aa61d352 97wxCheckListBoxItem::wxCheckListBoxItem(wxCheckListBox* pParent, size_t nIndex)
84882850 98 :wxOwnerDrawn( wxEmptyString, true /* checkable */ )
37f214d5 99{
84882850 100 m_bChecked = false;
1de4baa3
DW
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 //
98fbab9e 109 SetMarginWidth(CHECK_MARK_WIDTH);
1de4baa3
DW
110} // end of wxCheckListBoxItem::wxCheckListBoxItem
111
84882850
WS
112
113
114bool wxCheckListBoxItem::OnDrawItem ( wxDC& rDc,
115 const wxRect& rRect,
116 wxODAction eAct,
117 wxODStatus eStat )
37f214d5 118{
84882850 119 wxRect vRect = rRect;
1de4baa3 120
38400bb4
SN
121
122 wxPMDCImpl *impl = (wxPMDCImpl*) rDc.GetImpl();
123 ::WinQueryWindowRect( m_pParent->GetHWND(), &impl->m_vRclPaint );
1de4baa3
DW
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
77ffb593 130 // coords not wxWidgets coords.
1de4baa3
DW
131 //
132 vRect.x += 5;
133 vRect.y -= 3;
84882850 134 if (wxOwnerDrawn::OnDrawItem( rDc, vRect, eAct, eStat))
1de4baa3 135 {
98fbab9e 136 size_t nCheckWidth = CHECK_MARK_WIDTH;
84882850
WS
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);
1de4baa3
DW
147
148 nY = nParentHeight - nY - nCheckHeight;
149 vPenBack = wxPen(vColour, 1, wxSOLID);
1de4baa3
DW
150
151 //
152 // Erase the 1-pixel border
153 //
154 rDc.SetPen(vPenBack);
84882850 155 rDc.DrawRectangle( nX, nY, nCheckWidth, nCheckHeight );
1de4baa3
DW
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 //
84882850
WS
167 rDc.SetPen(*wxGREY_PEN);
168 rDc.DrawRectangle( nX, nY, nCheckWidth, nCheckHeight );
1de4baa3
DW
169
170 nX++;
171 if (IsChecked())
172 {
173 //
174 // Draw the check by loading the sys standard bitmap and drawing it
175 //
84882850
WS
176 HBITMAP hChkBmp = ::WinGetSysBitmap( HWND_DESKTOP, SBMP_MENUCHECK );
177 POINTL vPoint = {nX, nOldY + 3};
38400bb4
SN
178 wxPMDCImpl *impl = (wxPMDCImpl*) rDc.GetImpl();
179 ::WinDrawBitmap( impl->GetHPS(),
84882850
WS
180 hChkBmp,
181 NULL,
182 &vPoint,
183 NULL,
184 NULL,
185 DBM_NORMAL
1de4baa3
DW
186 );
187 }
84882850 188 return true;
37f214d5 189 }
84882850 190 return false;
1de4baa3 191} // end of wxCheckListBoxItem::OnDrawItem
37f214d5 192
37f214d5 193//
1de4baa3 194// Change the state of the item and redraw it
37f214d5 195//
aa61d352 196void wxCheckListBoxItem::Check( bool bCheck )
37f214d5 197{
1de4baa3 198 m_bChecked = bCheck;
37f214d5 199
1de4baa3
DW
200 //
201 // Index may be chanegd because new items were added/deleted
202 //
203 if (m_pParent->GetItemIndex(this) != (int)m_nIndex)
37f214d5 204 {
1de4baa3
DW
205 //
206 // Update it
207 //
84882850 208 int nIndex = m_pParent->GetItemIndex(this);
37f214d5 209
1de4baa3 210 wxASSERT_MSG(nIndex != wxNOT_FOUND, wxT("what does this item do here?"));
37f214d5 211
1de4baa3 212 m_nIndex = (size_t)nIndex;
37f214d5
DW
213 }
214
37f214d5 215
ce7fe42e 216 wxCommandEvent vEvent( wxEVT_CHECKLISTBOX,m_pParent->GetId());
37f214d5 217
1de4baa3
DW
218 vEvent.SetInt(m_nIndex);
219 vEvent.SetEventObject(m_pParent);
220 m_pParent->ProcessCommand(vEvent);
221} // end of wxCheckListBoxItem::Check
37f214d5 222
84882850 223
0e320a79
DW
224// ----------------------------------------------------------------------------
225// implementation of wxCheckListBox class
226// ----------------------------------------------------------------------------
227
228// define event table
229// ------------------
230BEGIN_EVENT_TABLE(wxCheckListBox, wxListBox)
84882850
WS
231 EVT_CHAR(wxCheckListBox::OnChar)
232 EVT_LEFT_DOWN(wxCheckListBox::OnLeftClick)
0e320a79
DW
233END_EVENT_TABLE()
234
84882850
WS
235
236
1de4baa3
DW
237//
238// Control creation
0e320a79 239// ----------------
1de4baa3 240//
0e320a79 241
1de4baa3
DW
242//
243// Default ctor: use Create() to really create the control
244//
245wxCheckListBox::wxCheckListBox()
84882850 246 :wxCheckListBoxBase()
0e320a79 247{
1de4baa3 248} // end of wxCheckListBox::wxCheckListBox
0e320a79 249
1de4baa3
DW
250//
251// Ctor which creates the associated control
252//
84882850
WS
253wxCheckListBox::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()
0e320a79 263{
84882850 264 Create( pParent, vId, rPos, rSize, nStrings, asChoices, lStyle | wxLB_OWNERDRAW, rVal, rsName );
1de4baa3 265} // end of wxCheckListBox::wxCheckListBox
37f214d5 266
84882850
WS
267wxCheckListBox::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()
584ad2a3
MB
276{
277 wxCArrayString chs(asChoices);
84882850
WS
278 Create( pParent, vId, rPos, rSize, chs.GetCount(), chs.GetStrings(),
279 lStyle | wxLB_OWNERDRAW, rVal, rsName );
584ad2a3
MB
280} // end of wxCheckListBox::wxCheckListBox
281
aa61d352 282void wxCheckListBox::Delete(unsigned int n)
37f214d5 283{
8228b893 284 wxCHECK_RET( IsValid(n),
84882850
WS
285 wxT("invalid index in wxCheckListBox::Delete") );
286 wxListBox::Delete(n);
37f214d5 287
1de4baa3
DW
288 //
289 // Free memory
290 //
84882850
WS
291 delete m_aItems[n];
292 m_aItems.RemoveAt(n);
1de4baa3 293} // end of wxCheckListBox::Delete
37f214d5 294
84882850 295bool wxCheckListBox::SetFont ( const wxFont& rFont )
37f214d5 296{
aa61d352 297 for (unsigned int i = 0; i < m_aItems.GetCount(); i++)
1de4baa3
DW
298 m_aItems[i]->SetFont(rFont);
299 wxListBox::SetFont(rFont);
84882850 300 return true;
1de4baa3 301} // end of wxCheckListBox::SetFont
37f214d5 302
84882850
WS
303
304
1de4baa3
DW
305//
306// Create/retrieve item
37f214d5 307// --------------------
1de4baa3 308//
37f214d5 309
1de4baa3
DW
310//
311// Create a check list box item
312//
aa61d352 313wxOwnerDrawn* wxCheckListBox::CreateItem(size_t nIndex)
37f214d5 314{
84882850 315 wxCheckListBoxItem* pItem = new wxCheckListBoxItem( this, nIndex );
1de4baa3
DW
316 return pItem;
317} // end of wxCheckListBox::CreateItem
0e320a79 318
84882850
WS
319
320
1de4baa3
DW
321//
322// Return item size
37f214d5 323// ----------------
1de4baa3 324//
84882850 325long wxCheckListBox::OS2OnMeasure ( WXMEASUREITEMSTRUCT* pItem )
37f214d5 326{
1de4baa3
DW
327 if (!pItem)
328 pItem = (WXMEASUREITEMSTRUCT*)new OWNERITEM;
84882850 329 if (wxListBox::OS2OnMeasure(pItem))
1de4baa3 330 {
84882850 331 POWNERITEM pStruct = (POWNERITEM)pItem;
1de4baa3
DW
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 //
98fbab9e 341 pStruct->rclItem.xRight += CHECK_MARK_WIDTH;
f5ea767e 342 return long(MRFROM2SHORT((USHORT)m_nItemHeight, (USHORT)(pStruct->rclItem.xRight - pStruct->rclItem.xLeft)));
1de4baa3 343 }
f5ea767e 344 return 0L;
1de4baa3 345} // end of wxCheckListBox::CreateItem
37f214d5 346
84882850
WS
347
348
1de4baa3
DW
349//
350// Check items
0e320a79 351// -----------
1de4baa3 352//
aa61d352 353bool wxCheckListBox::IsChecked(unsigned int uiIndex) const
37f214d5 354{
1de4baa3
DW
355 return GetItem(uiIndex)->IsChecked();
356} // end of wxCheckListBox::IsChecked
37f214d5 357
aa61d352 358void wxCheckListBox::Check(unsigned int uiIndex, bool bCheck)
0e320a79 359{
1de4baa3
DW
360 GetItem(uiIndex)->Check(bCheck);
361} // end of wxCheckListBox::Check
0e320a79 362
84882850
WS
363
364
1de4baa3
DW
365//
366// Process events
37f214d5 367// --------------
1de4baa3 368//
84882850 369void wxCheckListBox::OnChar ( wxKeyEvent& rEvent )
0e320a79 370{
9923c37d 371 if (rEvent.GetKeyCode() == WXK_SPACE)
1de4baa3
DW
372 GetItem(GetSelection())->Toggle();
373 else
374 rEvent.Skip();
375} // end of wxCheckListBox::OnChar
376
84882850 377void wxCheckListBox::OnLeftClick ( wxMouseEvent& rEvent )
37f214d5 378{
1de4baa3
DW
379 //
380 // Clicking on the item selects it, clicking on the checkmark toggles
381 //
98fbab9e 382 if (rEvent.GetX() <= CHECK_MARK_WIDTH)
1de4baa3
DW
383 {
384 int nParentHeight;
385 wxScreenDC vDc;
386 wxCoord vHeight;
387
84882850 388 GetSize( NULL, &nParentHeight );
1de4baa3 389 vDc.SetFont(GetFont());
9923c37d 390 vHeight = (wxCoord)(vDc.GetCharHeight() * 2.5);
1de4baa3
DW
391
392 //
393 // This, of course, will not work if the LB is scrolled
394 //
84882850 395 int nY = rEvent.GetY();
1de4baa3
DW
396
397 nY = nParentHeight - (nY + vHeight);
398
84882850 399 size_t nItem = (size_t)(nY / vHeight);
1de4baa3 400
8228b893 401 if (nItem < m_nNumItems)
1de4baa3
DW
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
37f214d5 415
84882850 416#endif // wxUSE_CHECKLISTBOX && wxUSE_OWNER_DRAWN