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