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