]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/checklst.cpp
using const GetPen
[wxWidgets.git] / src / mac / carbon / 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 #include "wx/arrstr.h"
26
27 #include "wx/mac/uma.h"
28 #include <Appearance.h>
29
30 // ============================================================================
31 // implementation of wxCheckListBox
32 // ============================================================================
33
34 IMPLEMENT_DYNAMIC_CLASS(wxCheckListBox, wxListBox)
35
36 const short kwxMacListWithVerticalScrollbar = 128 ;
37 const short kwxMacListItemHeight = 14 ;
38 const short kwxMacListCheckboxWidth = 14 ;
39
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
48 typedef struct {
49 unsigned short instruction;
50 void (*function)();
51 } ldefRec, *ldefPtr, **ldefHandle;
52
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
61 extern "C"
62 {
63 static pascal void wxMacCheckListDefinition( short message, Boolean isSelected, Rect *drawRect,
64 Cell cell, short dataOffset, short dataLength,
65 ListHandle listHandle ) ;
66 }
67
68 static pascal void wxMacCheckListDefinition( short message, Boolean isSelected, Rect *drawRect,
69 Cell cell, short dataOffset, short dataLength,
70 ListHandle listHandle )
71 {
72 wxCheckListBox* list;
73 list = (wxCheckListBox*) GetControlReference( (ControlRef) GetListRefCon(listHandle) );
74 if ( list == NULL )
75 return ;
76
77 GrafPtr savePort;
78 GrafPtr grafPtr;
79 RgnHandle savedClipRegion;
80 SInt32 savedPenMode;
81 GetPort(&savePort);
82 SetPort((**listHandle).port);
83 grafPtr = (**listHandle).port ;
84 // typecast our refCon
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
109 const wxFont& font = list->GetFont();
110 if ( font.Ok() )
111 {
112 ::TextFont( font.MacGetFontNum() ) ;
113 ::TextSize( font.MacGetFontSize()) ;
114 ::TextFace( font.MacGetFontStyle() ) ;
115 }
116
117 ThemeButtonDrawInfo info ;
118 info.state = kThemeStateActive ;
119 info.value = checked ? kThemeButtonOn : kThemeButtonOff ;
120 info.adornment = kThemeAdornmentNone ;
121 Rect checkRect = *drawRect ;
122
123
124 checkRect.left +=0 ;
125 checkRect.top +=0 ;
126 checkRect.right = checkRect.left + list->m_checkBoxWidth ;
127 checkRect.bottom = checkRect.top + list->m_checkBoxHeight ;
128 DrawThemeButton(&checkRect,kThemeCheckBox,
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());
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 ) {
138 savedPenMode = GetPortPenMode( (CGrafPtr) grafPtr );
139 SetPortPenMode( (CGrafPtr) grafPtr, hilitetransfermode );
140 PaintRect( drawRect );
141 SetPortPenMode( (CGrafPtr) grafPtr, savedPenMode );
142 }
143
144 // Restore the saved clip region.
145
146 SetClip( savedClipRegion );
147 DisposeRgn( savedClipRegion );
148 }
149 break;
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 );
156 savedPenMode = GetPortPenMode( (CGrafPtr) grafPtr );
157 SetPortPenMode( (CGrafPtr) grafPtr, hilitetransfermode );
158 PaintRect( drawRect );
159 SetPortPenMode( (CGrafPtr) grafPtr, savedPenMode );
160 break;
161 default :
162 break ;
163 }
164 SetPort(savePort);
165 }
166
167 extern "C" void MacDrawStringCell(Rect *cellRect, Cell lCell, ListHandle theList, long refCon) ;
168
169 static ListDefUPP macCheckListDefUPP = NULL ;
170
171 // ----------------------------------------------------------------------------
172 // creation
173 // ----------------------------------------------------------------------------
174
175 void wxCheckListBox::Init()
176 {
177 }
178
179 bool 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
194 bool 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 {
204 m_macIsUserPane = FALSE ;
205
206 if ( !wxCheckListBoxBase::Create(parent, id, pos, size,
207 n, choices, style, validator, name) )
208 return false;
209
210 m_noItems = 0 ; // this will be increased by our append command
211 m_selected = 0;
212
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
221
222 const wxFont& font = GetFont();
223
224 FontInfo finfo;
225 FetchFontInfo(font.MacGetFontNum(),font.MacGetFontSize(),font.MacGetFontStyle(),&finfo);
226
227 m_TextBaseLineOffset= finfo.leading+finfo.ascent;
228 m_checkBoxHeight= finfo.leading+finfo.ascent+finfo.descent;
229
230 if (m_checkBoxHeight<h)
231 {
232 m_TextBaseLineOffset+= (h-m_checkBoxHeight)/2;
233 m_checkBoxHeight= h;
234 }
235
236
237 Rect bounds = wxMacGetBoundsForControl( this , pos , size ) ;
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 Size asize;
248
249
250 CreateListBoxControl( MAC_WXHWND(parent->MacGetTopLevelWindowRef()), &bounds, false, 0, 1, false, true,
251 m_checkBoxHeight+2, 14, false, &listDef, (ControlRef *)&m_macControl );
252
253 GetControlData( (ControlRef) m_macControl, kControlNoPart, kControlListBoxListHandleTag,
254 sizeof(ListHandle), (Ptr) &m_macList, &asize);
255
256 SetControlReference( (ControlRef) m_macControl, (long) this);
257 SetControlVisibility( (ControlRef) m_macControl, false, false);
258
259
260 OptionBits options = 0;
261 if ( style & wxLB_MULTIPLE )
262 {
263 options += lNoExtend ;
264 }
265 else if ( style & wxLB_EXTENDED )
266 {
267 options += lExtendDrag ;
268 }
269 else
270 {
271 options = (OptionBits) lOnlyOne ;
272 }
273 SetListSelectionFlags((ListHandle)m_macList, options);
274
275 MacPostControlCreate(pos,size) ;
276
277 for ( int i = 0 ; i < n ; i++ )
278 {
279 Append( choices[i] ) ;
280 }
281
282 LSetDrawingMode( true , (ListHandle) m_macList ) ;
283
284 return TRUE;
285 }
286
287 // ----------------------------------------------------------------------------
288 // wxCheckListBox functions
289 // ----------------------------------------------------------------------------
290
291 bool wxCheckListBox::IsChecked(size_t item) const
292 {
293 wxCHECK_MSG( item < m_checks.GetCount(), FALSE,
294 _T("invalid index in wxCheckListBox::IsChecked") );
295
296 return m_checks[item] != 0;
297 }
298
299 void wxCheckListBox::Check(size_t item, bool check)
300 {
301 wxCHECK_RET( item < m_checks.GetCount(),
302 _T("invalid index in wxCheckListBox::Check") );
303
304 // intermediate var is needed to avoid compiler warning with VC++
305 bool isChecked = m_checks[item] != 0;
306 if ( check != isChecked )
307 {
308 m_checks[item] = check;
309
310 MacRedrawControl() ;
311 }
312 }
313
314 // ----------------------------------------------------------------------------
315 // methods forwarded to wxListBox
316 // ----------------------------------------------------------------------------
317
318 void wxCheckListBox::Delete(int n)
319 {
320 wxCHECK_RET( n < GetCount(), _T("invalid index in wxListBox::Delete") );
321
322 wxListBox::Delete(n);
323
324 m_checks.RemoveAt(n);
325 }
326
327 int wxCheckListBox::DoAppend(const wxString& item)
328 {
329 LSetDrawingMode( false , (ListHandle) m_macList ) ;
330 int pos = wxListBox::DoAppend(item);
331
332 // the item is initially unchecked
333 m_checks.Insert(FALSE, pos);
334 LSetDrawingMode( true , (ListHandle) m_macList ) ;
335
336 return pos;
337 }
338
339 void wxCheckListBox::DoInsertItems(const wxArrayString& items, int pos)
340 {
341 wxListBox::DoInsertItems(items, pos);
342
343 size_t count = items.GetCount();
344 for ( size_t n = 0; n < count; n++ )
345 {
346 m_checks.Insert(FALSE, pos + n);
347 }
348 }
349
350 void wxCheckListBox::DoSetItems(const wxArrayString& items, void **clientData)
351 {
352 // call it first as it does DoClear()
353 wxListBox::DoSetItems(items, clientData);
354
355 size_t count = items.GetCount();
356 for ( size_t n = 0; n < count; n++ )
357 {
358 m_checks.Add(FALSE);
359 }
360 }
361
362 void wxCheckListBox::DoClear()
363 {
364 m_checks.Empty();
365 }
366
367 BEGIN_EVENT_TABLE(wxCheckListBox, wxListBox)
368 EVT_CHAR(wxCheckListBox::OnChar)
369 EVT_LEFT_DOWN(wxCheckListBox::OnLeftClick)
370 END_EVENT_TABLE()
371
372 // this will only work as soon as
373
374 void wxCheckListBox::OnChar(wxKeyEvent& event)
375 {
376 if ( event.GetKeyCode() == WXK_SPACE )
377 {
378 int index = GetSelection() ;
379 if ( index >= 0 )
380 {
381 Check(index, !IsChecked(index) ) ;
382 wxCommandEvent event(wxEVT_COMMAND_CHECKLISTBOX_TOGGLED, GetId());
383 event.SetInt(index);
384 event.SetEventObject(this);
385 GetEventHandler()->ProcessEvent(event);
386 }
387 }
388 else
389 event.Skip();
390 }
391
392 void wxCheckListBox::OnLeftClick(wxMouseEvent& event)
393 {
394 // clicking on the item selects it, clicking on the checkmark toggles
395 if ( event.GetX() <= 20 /*check width*/ ) {
396 int lineheight ;
397 int topcell ;
398 #if TARGET_CARBON
399 Point pt ;
400 GetListCellSize( (ListHandle)m_macList , &pt ) ;
401 lineheight = pt.v ;
402 ListBounds visible ;
403 GetListVisibleCells( (ListHandle)m_macList , &visible ) ;
404 topcell = visible.top ;
405 #else
406 lineheight = (**(ListHandle)m_macList).cellSize.v ;
407 topcell = (**(ListHandle)m_macList).visible.top ;
408 #endif
409 size_t nItem = ((size_t)event.GetY()) / lineheight + topcell ;
410
411 if ( nItem < (size_t)m_noItems )
412 {
413 Check(nItem, !IsChecked(nItem) ) ;
414 wxCommandEvent event(wxEVT_COMMAND_CHECKLISTBOX_TOGGLED, GetId());
415 event.SetInt(nItem);
416 event.SetEventObject(this);
417 GetEventHandler()->ProcessEvent(event);
418 }
419 //else: it's not an error, just click outside of client zone
420 }
421 else {
422 // implement default behaviour: clicking on the item selects it
423 event.Skip();
424 }
425 }
426
427 #endif // wxUSE_CHECKLISTBOX