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