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