]> git.saurik.com Git - wxWidgets.git/blame - src/os2/checklst.cpp
Fixed #1338966.
[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
0e320a79 7// RCS-ID: $Id$
37f214d5 8// Copyright: (c) David Webster
65571936 9// Licence: wxWindows licence
0e320a79
DW
10///////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// headers & declarations
14// ============================================================================
15
37f214d5
DW
16// For compilers that support precompilation, includes "wx.h".
17#include "wx/wxprec.h"
18
84882850 19#if wxUSE_CHECKLISTBOX && wxUSE_OWNER_DRAWN
37f214d5
DW
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"
1a75e76f 30#include "wx/dcscreen.h"
84882850 31#include "wx/checklst.h"
37f214d5 32#include "wx/log.h"
0e320a79 33
37f214d5
DW
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)))
0e320a79
DW
43
44// ============================================================================
6463b9f5 45// implementation
0e320a79
DW
46// ============================================================================
47
1de4baa3 48IMPLEMENT_DYNAMIC_CLASS(wxCheckListBox, wxListBox)
0e320a79 49
37f214d5
DW
50// ----------------------------------------------------------------------------
51// declaration and implementation of wxCheckListBoxItem class
52// ----------------------------------------------------------------------------
53
54class wxCheckListBoxItem : public wxOwnerDrawn
55{
1de4baa3 56 friend class wxCheckListBox;
37f214d5 57public:
1de4baa3
DW
58 //
59 // ctor
60 //
84882850
WS
61 wxCheckListBoxItem( wxCheckListBox* pParent,
62 size_t nIndex
1de4baa3
DW
63 );
64
65 //
66 // Drawing functions
67 //
84882850
WS
68 virtual bool OnDrawItem( wxDC& rDc,
69 const wxRect& rRect,
70 wxODAction eAct,
71 wxODStatus eStat
1de4baa3
DW
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()); }
37f214d5
DW
80
81private:
84882850
WS
82 bool m_bChecked;
83 wxCheckListBox* m_pParent;
84 size_t m_nIndex;
1de4baa3
DW
85}; // end of CLASS wxCheckListBoxItem
86
84882850
WS
87
88
89wxCheckListBoxItem::wxCheckListBoxItem ( wxCheckListBox* pParent,
90 size_t nIndex)
91 :wxOwnerDrawn( wxEmptyString, true /* checkable */ )
37f214d5 92{
84882850 93 m_bChecked = false;
1de4baa3
DW
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
84882850
WS
105
106
107bool wxCheckListBoxItem::OnDrawItem ( wxDC& rDc,
108 const wxRect& rRect,
109 wxODAction eAct,
110 wxODStatus eStat )
37f214d5 111{
84882850 112 wxRect vRect = rRect;
1de4baa3 113
84882850 114 ::WinQueryWindowRect( m_pParent->GetHWND(), &rDc.m_vRclPaint );
1de4baa3
DW
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
77ffb593 121 // coords not wxWidgets coords.
1de4baa3
DW
122 //
123 vRect.x += 5;
124 vRect.y -= 3;
84882850 125 if (wxOwnerDrawn::OnDrawItem( rDc, vRect, eAct, eStat))
1de4baa3 126 {
84882850
WS
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);
1de4baa3
DW
138
139 nY = nParentHeight - nY - nCheckHeight;
140 vPenBack = wxPen(vColour, 1, wxSOLID);
1de4baa3
DW
141
142 //
143 // Erase the 1-pixel border
144 //
145 rDc.SetPen(vPenBack);
84882850 146 rDc.DrawRectangle( nX, nY, nCheckWidth, nCheckHeight );
1de4baa3
DW
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 //
84882850
WS
158 rDc.SetPen(*wxGREY_PEN);
159 rDc.DrawRectangle( nX, nY, nCheckWidth, nCheckHeight );
1de4baa3
DW
160
161 nX++;
162 if (IsChecked())
163 {
164 //
165 // Draw the check by loading the sys standard bitmap and drawing it
166 //
84882850
WS
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
1de4baa3
DW
177 );
178 }
84882850 179 return true;
37f214d5 180 }
84882850 181 return false;
1de4baa3 182} // end of wxCheckListBoxItem::OnDrawItem
37f214d5 183
37f214d5 184//
1de4baa3 185// Change the state of the item and redraw it
37f214d5 186//
84882850 187void wxCheckListBoxItem::Check ( bool bCheck )
37f214d5 188{
1de4baa3 189 m_bChecked = bCheck;
37f214d5 190
1de4baa3
DW
191 //
192 // Index may be chanegd because new items were added/deleted
193 //
194 if (m_pParent->GetItemIndex(this) != (int)m_nIndex)
37f214d5 195 {
1de4baa3
DW
196 //
197 // Update it
198 //
84882850 199 int nIndex = m_pParent->GetItemIndex(this);
37f214d5 200
1de4baa3 201 wxASSERT_MSG(nIndex != wxNOT_FOUND, wxT("what does this item do here?"));
37f214d5 202
1de4baa3 203 m_nIndex = (size_t)nIndex;
37f214d5
DW
204 }
205
37f214d5 206
84882850 207 wxCommandEvent vEvent( wxEVT_COMMAND_CHECKLISTBOX_TOGGLED,m_pParent->GetId());
37f214d5 208
1de4baa3
DW
209 vEvent.SetInt(m_nIndex);
210 vEvent.SetEventObject(m_pParent);
211 m_pParent->ProcessCommand(vEvent);
212} // end of wxCheckListBoxItem::Check
37f214d5 213
84882850 214
0e320a79
DW
215// ----------------------------------------------------------------------------
216// implementation of wxCheckListBox class
217// ----------------------------------------------------------------------------
218
219// define event table
220// ------------------
221BEGIN_EVENT_TABLE(wxCheckListBox, wxListBox)
84882850
WS
222 EVT_CHAR(wxCheckListBox::OnChar)
223 EVT_LEFT_DOWN(wxCheckListBox::OnLeftClick)
0e320a79
DW
224END_EVENT_TABLE()
225
84882850
WS
226
227
1de4baa3
DW
228//
229// Control creation
0e320a79 230// ----------------
1de4baa3 231//
0e320a79 232
1de4baa3
DW
233//
234// Default ctor: use Create() to really create the control
235//
236wxCheckListBox::wxCheckListBox()
84882850 237 :wxCheckListBoxBase()
0e320a79 238{
1de4baa3 239} // end of wxCheckListBox::wxCheckListBox
0e320a79 240
1de4baa3
DW
241//
242// Ctor which creates the associated control
243//
84882850
WS
244wxCheckListBox::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()
0e320a79 254{
84882850 255 Create( pParent, vId, rPos, rSize, nStrings, asChoices, lStyle | wxLB_OWNERDRAW, rVal, rsName );
1de4baa3 256} // end of wxCheckListBox::wxCheckListBox
37f214d5 257
84882850
WS
258wxCheckListBox::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()
584ad2a3
MB
267{
268 wxCArrayString chs(asChoices);
84882850
WS
269 Create( pParent, vId, rPos, rSize, chs.GetCount(), chs.GetStrings(),
270 lStyle | wxLB_OWNERDRAW, rVal, rsName );
584ad2a3
MB
271} // end of wxCheckListBox::wxCheckListBox
272
84882850 273void wxCheckListBox::Delete( int n )
37f214d5 274{
84882850
WS
275 wxCHECK_RET( n >= 0 && n < m_nNumItems,
276 wxT("invalid index in wxCheckListBox::Delete") );
277 wxListBox::Delete(n);
37f214d5 278
1de4baa3
DW
279 //
280 // Free memory
281 //
84882850
WS
282 delete m_aItems[n];
283 m_aItems.RemoveAt(n);
1de4baa3 284} // end of wxCheckListBox::Delete
37f214d5 285
84882850 286void wxCheckListBox::DoInsertItems(const wxArrayString& items, int pos)
37f214d5 287{
84882850
WS
288 // pos is validated in wxListBox
289 wxListBox::DoInsertItems( items, pos );
290 int n = items.GetCount();
291 for (int i = 0; i < n; i++)
1de4baa3 292 {
84882850
WS
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)
1de4baa3 301 );
37f214d5 302 }
1de4baa3 303} // end of wxCheckListBox::InsertItems
37f214d5 304
84882850 305bool wxCheckListBox::SetFont ( const wxFont& rFont )
37f214d5 306{
84882850 307 for (size_t i = 0; i < m_aItems.GetCount(); i++)
1de4baa3
DW
308 m_aItems[i]->SetFont(rFont);
309 wxListBox::SetFont(rFont);
84882850 310 return true;
1de4baa3 311} // end of wxCheckListBox::SetFont
37f214d5 312
84882850
WS
313
314
1de4baa3
DW
315//
316// Create/retrieve item
37f214d5 317// --------------------
1de4baa3 318//
37f214d5 319
1de4baa3
DW
320//
321// Create a check list box item
322//
84882850 323wxOwnerDrawn* wxCheckListBox::CreateItem ( size_t nIndex )
37f214d5 324{
84882850 325 wxCheckListBoxItem* pItem = new wxCheckListBoxItem( this, nIndex );
1de4baa3
DW
326 return pItem;
327} // end of wxCheckListBox::CreateItem
0e320a79 328
84882850
WS
329
330
1de4baa3
DW
331//
332// Return item size
37f214d5 333// ----------------
1de4baa3 334//
84882850 335long wxCheckListBox::OS2OnMeasure ( WXMEASUREITEMSTRUCT* pItem )
37f214d5 336{
1de4baa3
DW
337 if (!pItem)
338 pItem = (WXMEASUREITEMSTRUCT*)new OWNERITEM;
84882850 339 if (wxListBox::OS2OnMeasure(pItem))
1de4baa3 340 {
84882850 341 POWNERITEM pStruct = (POWNERITEM)pItem;
1de4baa3
DW
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();
f5ea767e 352 return long(MRFROM2SHORT((USHORT)m_nItemHeight, (USHORT)(pStruct->rclItem.xRight - pStruct->rclItem.xLeft)));
1de4baa3 353 }
f5ea767e 354 return 0L;
1de4baa3 355} // end of wxCheckListBox::CreateItem
37f214d5 356
84882850
WS
357
358
1de4baa3
DW
359//
360// Check items
0e320a79 361// -----------
1de4baa3 362//
84882850 363bool wxCheckListBox::IsChecked ( size_t uiIndex) const
37f214d5 364{
1de4baa3
DW
365 return GetItem(uiIndex)->IsChecked();
366} // end of wxCheckListBox::IsChecked
37f214d5 367
84882850 368void wxCheckListBox::Check ( size_t uiIndex, bool bCheck )
0e320a79 369{
1de4baa3
DW
370 GetItem(uiIndex)->Check(bCheck);
371} // end of wxCheckListBox::Check
0e320a79 372
84882850
WS
373
374
1de4baa3
DW
375//
376// Process events
37f214d5 377// --------------
1de4baa3 378//
84882850 379void wxCheckListBox::OnChar ( wxKeyEvent& rEvent )
0e320a79 380{
9923c37d 381 if (rEvent.GetKeyCode() == WXK_SPACE)
1de4baa3
DW
382 GetItem(GetSelection())->Toggle();
383 else
384 rEvent.Skip();
385} // end of wxCheckListBox::OnChar
386
84882850 387void wxCheckListBox::OnLeftClick ( wxMouseEvent& rEvent )
37f214d5 388{
1de4baa3
DW
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
84882850 398 GetSize( NULL, &nParentHeight );
1de4baa3 399 vDc.SetFont(GetFont());
9923c37d 400 vHeight = (wxCoord)(vDc.GetCharHeight() * 2.5);
1de4baa3
DW
401
402 //
403 // This, of course, will not work if the LB is scrolled
404 //
84882850 405 int nY = rEvent.GetY();
1de4baa3
DW
406
407 nY = nParentHeight - (nY + vHeight);
408
84882850 409 size_t nItem = (size_t)(nY / vHeight);
1de4baa3
DW
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
37f214d5 425
84882850 426#endif // wxUSE_CHECKLISTBOX && wxUSE_OWNER_DRAWN