]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/checklst.cpp
mouse handling fixed, skipping if we have no native control handling
[wxWidgets.git] / src / mac / carbon / checklst.cpp
CommitLineData
e9576ca5
SC
1///////////////////////////////////////////////////////////////////////////////
2// Name: checklst.cpp
3// Purpose: implementation of wxCheckListBox class
a31a5f85 4// Author: Stefan Csomor
e9576ca5 5// Modified by:
a31a5f85 6// Created: 1998-01-01
e9576ca5 7// RCS-ID: $Id$
a31a5f85 8// Copyright: (c) Stefan Csomor
e9576ca5
SC
9// Licence: wxWindows licence
10///////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// headers & declarations
14// ============================================================================
15
16#ifdef __GNUG__
17#pragma implementation "checklst.h"
18#endif
19
b698c8e9 20#include "wx/defs.h"
e9576ca5 21
55d60746
GD
22#if wxUSE_CHECKLISTBOX
23
b698c8e9 24#include "wx/checklst.h"
584ad2a3 25#include "wx/arrstr.h"
b698c8e9 26
dbfc5b97 27#include "wx/mac/uma.h"
7f0c3a63 28#include <Appearance.h>
dbfc5b97 29
e9576ca5 30// ============================================================================
dbfc5b97 31// implementation of wxCheckListBox
e9576ca5
SC
32// ============================================================================
33
dbfc5b97
SC
34IMPLEMENT_DYNAMIC_CLASS(wxCheckListBox, wxListBox)
35
36const short kwxMacListWithVerticalScrollbar = 128 ;
37const short kwxMacListItemHeight = 14 ;
38const short kwxMacListCheckboxWidth = 14 ;
39
573ac9dc
SC
40#if PRAGMA_STRUCT_ALIGN
41 #pragma options align=mac68k
42#elif PRAGMA_STRUCT_PACKPUSH
43 #pragma pack(push, 2)
44#elif PRAGMA_STRUCT_PACK
45 #pragma pack(2)
46#endif
47
dbfc5b97
SC
48typedef struct {
49 unsigned short instruction;
50 void (*function)();
51} ldefRec, *ldefPtr, **ldefHandle;
52
573ac9dc
SC
53#if PRAGMA_STRUCT_ALIGN
54 #pragma options align=reset
55#elif PRAGMA_STRUCT_PACKPUSH
56 #pragma pack(pop)
57#elif PRAGMA_STRUCT_PACK
58 #pragma pack()
59#endif
60
dbfc5b97
SC
61extern "C"
62{
63static pascal void wxMacCheckListDefinition( short message, Boolean isSelected, Rect *drawRect,
64 Cell cell, short dataOffset, short dataLength,
65 ListHandle listHandle ) ;
66}
67
68static pascal void wxMacCheckListDefinition( short message, Boolean isSelected, Rect *drawRect,
69 Cell cell, short dataOffset, short dataLength,
70 ListHandle listHandle )
71{
bcce8f75 72 wxCheckListBox* list;
facd6764 73 list = (wxCheckListBox*) GetControlReference( (ControlRef) GetListRefCon(listHandle) );
bcce8f75
SC
74 if ( list == NULL )
75 return ;
76
dbfc5b97
SC
77 GrafPtr savePort;
78 GrafPtr grafPtr;
79 RgnHandle savedClipRegion;
80 SInt32 savedPenMode;
e40298d5
JS
81 GetPort(&savePort);
82 SetPort((**listHandle).port);
83 grafPtr = (**listHandle).port ;
dbfc5b97 84 // typecast our refCon
dbfc5b97
SC
85
86 // Calculate the cell rect.
87
88 switch( message ) {
89 case lInitMsg:
90 break;
91
92 case lCloseMsg:
93 break;
94
95 case lDrawMsg:
96 {
97 const wxString text = list->m_stringArray[cell.v] ;
98 int checked = list->m_checks[cell.v] ;
99
100 // Save the current clip region, and set the clip region to the area we are about
101 // to draw.
102
103 savedClipRegion = NewRgn();
104 GetClip( savedClipRegion );
105
106 ClipRect( drawRect );
107 EraseRect( drawRect );
108
fcb35beb
VZ
109 const wxFont& font = list->GetFont();
110 if ( font.Ok() )
e40298d5 111 {
facd6764
SC
112 ::TextFont( font.MacGetFontNum() ) ;
113 ::TextSize( font.MacGetFontSize()) ;
114 ::TextFace( font.MacGetFontStyle() ) ;
50b30d83
SC
115 }
116
dbfc5b97
SC
117 ThemeButtonDrawInfo info ;
118 info.state = kThemeStateActive ;
119 info.value = checked ? kThemeButtonOn : kThemeButtonOff ;
120 info.adornment = kThemeAdornmentNone ;
121 Rect checkRect = *drawRect ;
50b30d83
SC
122
123
dbfc5b97 124 checkRect.left +=0 ;
50b30d83
SC
125 checkRect.top +=0 ;
126 checkRect.right = checkRect.left + list->m_checkBoxWidth ;
127 checkRect.bottom = checkRect.top + list->m_checkBoxHeight ;
dbfc5b97 128 DrawThemeButton(&checkRect,kThemeCheckBox,
e40298d5
JS
129 &info,NULL,NULL, NULL,0);
130
131 MoveTo(drawRect->left + 2 + list->m_checkBoxWidth+2, drawRect->top + list->m_TextBaseLineOffset );
132
133 DrawText(text, 0 , text.Length());
dbfc5b97
SC
134 // If the cell is hilited, do the hilite now. Paint the cell contents with the
135 // appropriate QuickDraw transform mode.
136
137 if( isSelected ) {
76a5e5d2
SC
138 savedPenMode = GetPortPenMode( (CGrafPtr) grafPtr );
139 SetPortPenMode( (CGrafPtr) grafPtr, hilitetransfermode );
dbfc5b97 140 PaintRect( drawRect );
76a5e5d2 141 SetPortPenMode( (CGrafPtr) grafPtr, savedPenMode );
dbfc5b97
SC
142 }
143
144 // Restore the saved clip region.
145
146 SetClip( savedClipRegion );
147 DisposeRgn( savedClipRegion );
e40298d5
JS
148 }
149 break;
dbfc5b97
SC
150 case lHiliteMsg:
151
152 // Hilite or unhilite the cell. Paint the cell contents with the
153 // appropriate QuickDraw transform mode.
154
155 GetPort( &grafPtr );
76a5e5d2
SC
156 savedPenMode = GetPortPenMode( (CGrafPtr) grafPtr );
157 SetPortPenMode( (CGrafPtr) grafPtr, hilitetransfermode );
dbfc5b97 158 PaintRect( drawRect );
76a5e5d2 159 SetPortPenMode( (CGrafPtr) grafPtr, savedPenMode );
dbfc5b97
SC
160 break;
161 default :
162 break ;
163 }
164 SetPort(savePort);
165}
166
167extern "C" void MacDrawStringCell(Rect *cellRect, Cell lCell, ListHandle theList, long refCon) ;
168
169static ListDefUPP macCheckListDefUPP = NULL ;
170
171// ----------------------------------------------------------------------------
172// creation
173// ----------------------------------------------------------------------------
174
175void wxCheckListBox::Init()
176{
177}
178
584ad2a3
MB
179bool wxCheckListBox::Create(wxWindow *parent,
180 wxWindowID id,
181 const wxPoint &pos,
182 const wxSize &size,
183 const wxArrayString& choices,
184 long style,
185 const wxValidator& validator,
186 const wxString &name)
187{
188 wxCArrayString chs(choices);
189
190 return Create(parent, id, pos, size, chs.GetCount(), chs.GetStrings(),
191 style, validator, name);
192}
193
dbfc5b97
SC
194bool wxCheckListBox::Create(wxWindow *parent,
195 wxWindowID id,
196 const wxPoint &pos,
197 const wxSize &size,
198 int n,
199 const wxString choices[],
200 long style,
201 const wxValidator& validator,
202 const wxString &name)
203{
facd6764
SC
204 m_macIsUserPane = FALSE ;
205
b45ed7a2
VZ
206 if ( !wxCheckListBoxBase::Create(parent, id, pos, size,
207 n, choices, style, validator, name) )
208 return false;
209
dbfc5b97
SC
210 m_noItems = 0 ; // this will be increased by our append command
211 m_selected = 0;
212
50b30d83
SC
213 m_checkBoxWidth = 12;
214 m_checkBoxHeight= 10;
215
216 long h = m_checkBoxHeight ;
217#if TARGET_CARBON
218 GetThemeMetric(kThemeMetricCheckBoxWidth,(long *)&m_checkBoxWidth);
219 GetThemeMetric(kThemeMetricCheckBoxHeight,&h);
220#endif
fcb35beb
VZ
221
222 const wxFont& font = GetFont();
50b30d83
SC
223
224 FontInfo finfo;
facd6764 225 FetchFontInfo(font.MacGetFontNum(),font.MacGetFontSize(),font.MacGetFontStyle(),&finfo);
50b30d83
SC
226
227 m_TextBaseLineOffset= finfo.leading+finfo.ascent;
228 m_checkBoxHeight= finfo.leading+finfo.ascent+finfo.descent;
229
e40298d5
JS
230 if (m_checkBoxHeight<h)
231 {
232 m_TextBaseLineOffset+= (h-m_checkBoxHeight)/2;
233 m_checkBoxHeight= h;
234 }
235
facd6764
SC
236
237 Rect bounds = wxMacGetBoundsForControl( this , pos , size ) ;
dbfc5b97
SC
238
239 ListDefSpec listDef;
240 listDef.defType = kListDefUserProcType;
241 if ( macCheckListDefUPP == NULL )
242 {
243 macCheckListDefUPP = NewListDefUPP( wxMacCheckListDefinition );
244 }
245 listDef.u.userProc = macCheckListDefUPP ;
246
247#if TARGET_CARBON
248 Size asize;
249
250
facd6764 251 CreateListBoxControl( MAC_WXHWND(parent->MacGetTopLevelWindowRef()), &bounds, false, 0, 1, false, true,
50b30d83 252 m_checkBoxHeight+2, 14, false, &listDef, (ControlRef *)&m_macControl );
dbfc5b97 253
facd6764 254 GetControlData( (ControlRef) m_macControl, kControlNoPart, kControlListBoxListHandleTag,
dbfc5b97
SC
255 sizeof(ListHandle), (Ptr) &m_macList, &asize);
256
facd6764
SC
257 SetControlReference( (ControlRef) m_macControl, (long) this);
258 SetControlVisibility( (ControlRef) m_macControl, false, false);
dbfc5b97
SC
259
260#else
261
262 long result ;
263
fe3fcb05 264 wxStAppResource resload ;
facd6764 265 m_macControl = (WXWidget) ::NewControl( MAC_WXHWND(parent->MacGetTopLevelWindowRef()) , &bounds , "\p" , true ,
dbfc5b97
SC
266 kwxMacListWithVerticalScrollbar , 0 , 0,
267 kControlListBoxProc , (long) this ) ;
facd6764 268 ::GetControlData( (ControlRef) m_macControl , kControlNoPart , kControlListBoxListHandleTag ,
dbfc5b97
SC
269 sizeof( ListHandle ) , (char*) &m_macList , &result ) ;
270
271 HLock( (Handle) m_macList ) ;
272 ldefHandle ldef ;
273 ldef = (ldefHandle) NewHandle( sizeof(ldefRec) ) ;
76a5e5d2 274 if ( (**(ListHandle)m_macList).listDefProc != NULL )
dbfc5b97
SC
275 {
276 (**ldef).instruction = 0x4EF9; /* JMP instruction */
277 (**ldef).function = (void(*)()) listDef.u.userProc;
76a5e5d2 278 (**(ListHandle)m_macList).listDefProc = (Handle) ldef ;
dbfc5b97
SC
279 }
280
76a5e5d2 281 Point pt = (**(ListHandle)m_macList).cellSize ;
dbfc5b97 282 pt.v = 14 ;
76a5e5d2
SC
283 LCellSize( pt , (ListHandle)m_macList ) ;
284 LAddColumn( 1 , 0 , (ListHandle)m_macList ) ;
2f1ae414 285#endif
dbfc5b97
SC
286 OptionBits options = 0;
287 if ( style & wxLB_MULTIPLE )
288 {
289 options += lNoExtend ;
290 }
291 else if ( style & wxLB_EXTENDED )
292 {
293 options += lExtendDrag ;
294 }
295 else
296 {
2b5f62a0 297 options = (OptionBits) lOnlyOne ;
dbfc5b97 298 }
76a5e5d2 299 SetListSelectionFlags((ListHandle)m_macList, options);
dbfc5b97 300
facd6764 301 MacPostControlCreate(pos,size) ;
dbfc5b97
SC
302
303 for ( int i = 0 ; i < n ; i++ )
304 {
305 Append( choices[i] ) ;
306 }
307
76a5e5d2 308 LSetDrawingMode( true , (ListHandle) m_macList ) ;
dbfc5b97
SC
309
310 return TRUE;
311}
e9576ca5
SC
312
313// ----------------------------------------------------------------------------
dbfc5b97 314// wxCheckListBox functions
e9576ca5
SC
315// ----------------------------------------------------------------------------
316
dbfc5b97
SC
317bool wxCheckListBox::IsChecked(size_t item) const
318{
319 wxCHECK_MSG( item < m_checks.GetCount(), FALSE,
320 _T("invalid index in wxCheckListBox::IsChecked") );
321
322 return m_checks[item] != 0;
323}
324
325void wxCheckListBox::Check(size_t item, bool check)
326{
327 wxCHECK_RET( item < m_checks.GetCount(),
328 _T("invalid index in wxCheckListBox::Check") );
329
330 // intermediate var is needed to avoid compiler warning with VC++
331 bool isChecked = m_checks[item] != 0;
332 if ( check != isChecked )
333 {
334 m_checks[item] = check;
335
336 MacRedrawControl() ;
337 }
338}
339
340// ----------------------------------------------------------------------------
341// methods forwarded to wxListBox
342// ----------------------------------------------------------------------------
343
344void wxCheckListBox::Delete(int n)
345{
346 wxCHECK_RET( n < GetCount(), _T("invalid index in wxListBox::Delete") );
e9576ca5 347
dbfc5b97 348 wxListBox::Delete(n);
e9576ca5 349
dbfc5b97
SC
350 m_checks.RemoveAt(n);
351}
352
353int wxCheckListBox::DoAppend(const wxString& item)
e9576ca5 354{
50b30d83 355 LSetDrawingMode( false , (ListHandle) m_macList ) ;
dbfc5b97
SC
356 int pos = wxListBox::DoAppend(item);
357
358 // the item is initially unchecked
359 m_checks.Insert(FALSE, pos);
50b30d83 360 LSetDrawingMode( true , (ListHandle) m_macList ) ;
dbfc5b97
SC
361
362 return pos;
e9576ca5
SC
363}
364
dbfc5b97 365void wxCheckListBox::DoInsertItems(const wxArrayString& items, int pos)
e9576ca5 366{
dbfc5b97
SC
367 wxListBox::DoInsertItems(items, pos);
368
369 size_t count = items.GetCount();
370 for ( size_t n = 0; n < count; n++ )
371 {
372 m_checks.Insert(FALSE, pos + n);
373 }
e9576ca5
SC
374}
375
dbfc5b97
SC
376void wxCheckListBox::DoSetItems(const wxArrayString& items, void **clientData)
377{
378 // call it first as it does DoClear()
379 wxListBox::DoSetItems(items, clientData);
380
381 size_t count = items.GetCount();
382 for ( size_t n = 0; n < count; n++ )
383 {
384 m_checks.Add(FALSE);
385 }
386}
e9576ca5 387
dbfc5b97 388void wxCheckListBox::DoClear()
e9576ca5 389{
dbfc5b97 390 m_checks.Empty();
e9576ca5
SC
391}
392
dbfc5b97
SC
393BEGIN_EVENT_TABLE(wxCheckListBox, wxListBox)
394 EVT_CHAR(wxCheckListBox::OnChar)
395 EVT_LEFT_DOWN(wxCheckListBox::OnLeftClick)
396END_EVENT_TABLE()
397
398// this will only work as soon as
399
400void wxCheckListBox::OnChar(wxKeyEvent& event)
e9576ca5 401{
e40298d5 402 if ( event.GetKeyCode() == WXK_SPACE )
dbfc5b97 403 {
e40298d5
JS
404 int index = GetSelection() ;
405 if ( index >= 0 )
406 {
407 Check(index, !IsChecked(index) ) ;
408 wxCommandEvent event(wxEVT_COMMAND_CHECKLISTBOX_TOGGLED, GetId());
409 event.SetInt(index);
410 event.SetEventObject(this);
411 GetEventHandler()->ProcessEvent(event);
412 }
dbfc5b97 413 }
e40298d5
JS
414 else
415 event.Skip();
e9576ca5
SC
416}
417
dbfc5b97
SC
418void wxCheckListBox::OnLeftClick(wxMouseEvent& event)
419{
e40298d5
JS
420 // clicking on the item selects it, clicking on the checkmark toggles
421 if ( event.GetX() <= 20 /*check width*/ ) {
422 int lineheight ;
423 int topcell ;
dbfc5b97 424#if TARGET_CARBON
e40298d5
JS
425 Point pt ;
426 GetListCellSize( (ListHandle)m_macList , &pt ) ;
427 lineheight = pt.v ;
428 ListBounds visible ;
429 GetListVisibleCells( (ListHandle)m_macList , &visible ) ;
430 topcell = visible.top ;
dbfc5b97 431#else
e40298d5
JS
432 lineheight = (**(ListHandle)m_macList).cellSize.v ;
433 topcell = (**(ListHandle)m_macList).visible.top ;
dbfc5b97 434#endif
e40298d5
JS
435 size_t nItem = ((size_t)event.GetY()) / lineheight + topcell ;
436
437 if ( nItem < (size_t)m_noItems )
438 {
439 Check(nItem, !IsChecked(nItem) ) ;
440 wxCommandEvent event(wxEVT_COMMAND_CHECKLISTBOX_TOGGLED, GetId());
441 event.SetInt(nItem);
442 event.SetEventObject(this);
443 GetEventHandler()->ProcessEvent(event);
444 }
445 //else: it's not an error, just click outside of client zone
446 }
447 else {
448 // implement default behaviour: clicking on the item selects it
449 event.Skip();
dbfc5b97 450 }
dbfc5b97 451}
e9576ca5 452
dbfc5b97 453#endif // wxUSE_CHECKLISTBOX