]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/os2/checklst.cpp
Allow wx parents a chance to handle events fired by non-wx children. (i.e. wxActiveX...
[wxWidgets.git] / src / os2 / checklst.cpp
... / ...
CommitLineData
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
48IMPLEMENT_DYNAMIC_CLASS(wxCheckListBox, wxListBox)
49
50// ----------------------------------------------------------------------------
51// declaration and implementation of wxCheckListBoxItem class
52// ----------------------------------------------------------------------------
53
54class wxCheckListBoxItem : public wxOwnerDrawn
55{
56 friend class wxCheckListBox;
57public:
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
81private:
82 bool m_bChecked;
83 wxCheckListBox* m_pParent;
84 size_t m_nIndex;
85}; // end of CLASS wxCheckListBoxItem
86
87
88
89wxCheckListBoxItem::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
107bool 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//
187void 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// ------------------
221BEGIN_EVENT_TABLE(wxCheckListBox, wxListBox)
222 EVT_CHAR(wxCheckListBox::OnChar)
223 EVT_LEFT_DOWN(wxCheckListBox::OnLeftClick)
224END_EVENT_TABLE()
225
226
227
228//
229// Control creation
230// ----------------
231//
232
233//
234// Default ctor: use Create() to really create the control
235//
236wxCheckListBox::wxCheckListBox()
237 :wxCheckListBoxBase()
238{
239} // end of wxCheckListBox::wxCheckListBox
240
241//
242// Ctor which creates the associated control
243//
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()
254{
255 Create( pParent, vId, rPos, rSize, nStrings, asChoices, lStyle | wxLB_OWNERDRAW, rVal, rsName );
256} // end of wxCheckListBox::wxCheckListBox
257
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()
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
273void 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
286void 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
305bool 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//
323wxOwnerDrawn* 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//
335long 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//
363bool wxCheckListBox::IsChecked ( size_t uiIndex) const
364{
365 return GetItem(uiIndex)->IsChecked();
366} // end of wxCheckListBox::IsChecked
367
368void 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//
379void 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
387void 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