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