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