1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/mac/classic/checklst.cpp
3 // Purpose: implementation of wxCheckListBox class
4 // Author: Stefan Csomor
8 // Copyright: (c) Stefan Csomor
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
13 // headers & declarations
14 // ============================================================================
16 #include "wx/wxprec.h"
18 #if wxUSE_CHECKLISTBOX
20 #include "wx/checklst.h"
23 #include "wx/arrstr.h"
26 #include "wx/mac/uma.h"
27 #include <Appearance.h>
29 // ============================================================================
30 // implementation of wxCheckListBox
31 // ============================================================================
33 IMPLEMENT_DYNAMIC_CLASS(wxCheckListBox
, wxListBox
)
35 const short kwxMacListWithVerticalScrollbar
= 128 ;
36 const short kwxMacListItemHeight
= 14 ;
37 const short kwxMacListCheckboxWidth
= 14 ;
39 #if PRAGMA_STRUCT_ALIGN
40 #pragma options align=mac68k
41 #elif PRAGMA_STRUCT_PACKPUSH
43 #elif PRAGMA_STRUCT_PACK
48 unsigned short instruction
;
50 } ldefRec
, *ldefPtr
, **ldefHandle
;
52 #if PRAGMA_STRUCT_ALIGN
53 #pragma options align=reset
54 #elif PRAGMA_STRUCT_PACKPUSH
56 #elif PRAGMA_STRUCT_PACK
62 static pascal void wxMacCheckListDefinition( short message
, Boolean isSelected
, Rect
*drawRect
,
63 Cell cell
, short dataOffset
, short dataLength
,
64 ListHandle listHandle
) ;
67 static pascal void wxMacCheckListDefinition( short message
, Boolean isSelected
, Rect
*drawRect
,
68 Cell cell
, short dataOffset
, short dataLength
,
69 ListHandle listHandle
)
72 list
= (wxCheckListBox
*) GetControlReference( (ControlHandle
) GetListRefCon(listHandle
) );
78 RgnHandle savedClipRegion
;
81 SetPort((**listHandle
).port
);
82 grafPtr
= (**listHandle
).port
;
83 // typecast our refCon
85 // Calculate the cell rect.
96 const wxString text
= list
->m_stringArray
[cell
.v
] ;
97 int checked
= list
->m_checks
[cell
.v
] ;
99 // Save the current clip region, and set the clip region to the area we are about
102 savedClipRegion
= NewRgn();
103 GetClip( savedClipRegion
);
105 ClipRect( drawRect
);
106 EraseRect( drawRect
);
108 const wxFont
& font
= list
->GetFont();
111 ::TextFont( font
.GetMacFontNum() ) ;
112 ::TextSize( font
.GetMacFontSize()) ;
113 ::TextFace( font
.GetMacFontStyle() ) ;
116 ThemeButtonDrawInfo info
;
117 info
.state
= kThemeStateActive
;
118 info
.value
= checked
? kThemeButtonOn
: kThemeButtonOff
;
119 info
.adornment
= kThemeAdornmentNone
;
120 Rect checkRect
= *drawRect
;
125 checkRect
.right
= checkRect
.left
+ list
->m_checkBoxWidth
;
126 checkRect
.bottom
= checkRect
.top
+ list
->m_checkBoxHeight
;
127 DrawThemeButton(&checkRect
,kThemeCheckBox
,
128 &info
,NULL
,NULL
, NULL
,0);
130 MoveTo(drawRect
->left
+ 2 + list
->m_checkBoxWidth
+2, drawRect
->top
+ list
->m_TextBaseLineOffset
);
132 DrawText(text
, 0 , text
.length());
133 // If the cell is hilited, do the hilite now. Paint the cell contents with the
134 // appropriate QuickDraw transform mode.
137 savedPenMode
= GetPortPenMode( (CGrafPtr
) grafPtr
);
138 SetPortPenMode( (CGrafPtr
) grafPtr
, hilitetransfermode
);
139 PaintRect( drawRect
);
140 SetPortPenMode( (CGrafPtr
) grafPtr
, savedPenMode
);
143 // Restore the saved clip region.
145 SetClip( savedClipRegion
);
146 DisposeRgn( savedClipRegion
);
151 // Hilite or unhilite the cell. Paint the cell contents with the
152 // appropriate QuickDraw transform mode.
155 savedPenMode
= GetPortPenMode( (CGrafPtr
) grafPtr
);
156 SetPortPenMode( (CGrafPtr
) grafPtr
, hilitetransfermode
);
157 PaintRect( drawRect
);
158 SetPortPenMode( (CGrafPtr
) grafPtr
, savedPenMode
);
166 extern "C" void MacDrawStringCell(Rect
*cellRect
, Cell lCell
, ListHandle theList
, long refCon
) ;
168 static ListDefUPP macCheckListDefUPP
= NULL
;
170 // ----------------------------------------------------------------------------
172 // ----------------------------------------------------------------------------
174 void wxCheckListBox::Init()
178 bool wxCheckListBox::Create(wxWindow
*parent
,
182 const wxArrayString
& choices
,
184 const wxValidator
& validator
,
185 const wxString
&name
)
187 wxCArrayString
chs(choices
);
189 return Create(parent
, id
, pos
, size
, chs
.GetCount(), chs
.GetStrings(),
190 style
, validator
, name
);
193 bool wxCheckListBox::Create(wxWindow
*parent
,
198 const wxString choices
[],
200 const wxValidator
& validator
,
201 const wxString
&name
)
203 if ( !wxCheckListBoxBase::Create(parent
, id
, pos
, size
,
204 n
, choices
, style
, validator
, name
) )
207 m_noItems
= 0 ; // this will be increased by our append command
210 m_checkBoxWidth
= 12;
211 m_checkBoxHeight
= 10;
213 long h
= m_checkBoxHeight
;
215 GetThemeMetric(kThemeMetricCheckBoxWidth
,(long *)&m_checkBoxWidth
);
216 GetThemeMetric(kThemeMetricCheckBoxHeight
,&h
);
219 const wxFont
& font
= GetFont();
222 FetchFontInfo(font
.GetMacFontNum(),font
.GetMacFontSize(),font
.GetMacFontStyle(),&finfo
);
224 m_TextBaseLineOffset
= finfo
.leading
+finfo
.ascent
;
225 m_checkBoxHeight
= finfo
.leading
+finfo
.ascent
+finfo
.descent
;
227 if (m_checkBoxHeight
<h
)
229 m_TextBaseLineOffset
+= (h
-m_checkBoxHeight
)/2;
236 MacPreControlCreate( parent
, id
, wxEmptyString
, pos
, size
,style
, validator
, name
, &bounds
, title
) ;
239 listDef
.defType
= kListDefUserProcType
;
240 if ( macCheckListDefUPP
== NULL
)
242 macCheckListDefUPP
= NewListDefUPP( wxMacCheckListDefinition
);
244 listDef
.u
.userProc
= macCheckListDefUPP
;
250 CreateListBoxControl( MAC_WXHWND(parent
->MacGetRootWindow()), &bounds
, false, 0, 1, false, true,
251 m_checkBoxHeight
+2, 14, false, &listDef
, (ControlRef
*)&m_macControl
);
253 GetControlData( (ControlHandle
) m_macControl
, kControlNoPart
, kControlListBoxListHandleTag
,
254 sizeof(ListHandle
), (Ptr
) &m_macList
, &asize
);
256 SetControlReference( (ControlHandle
) m_macControl
, (long) this);
257 SetControlVisibility( (ControlHandle
) m_macControl
, false, false);
263 wxStAppResource resload
;
264 m_macControl
= (WXWidget
) ::NewControl( MAC_WXHWND(parent
->MacGetRootWindow()) , &bounds
, title
, false ,
265 kwxMacListWithVerticalScrollbar
, 0 , 0,
266 kControlListBoxProc
, (long) this ) ;
267 ::GetControlData( (ControlHandle
) m_macControl
, kControlNoPart
, kControlListBoxListHandleTag
,
268 sizeof( ListHandle
) , (char*) &m_macList
, &result
) ;
270 HLock( (Handle
) m_macList
) ;
272 ldef
= (ldefHandle
) NewHandle( sizeof(ldefRec
) ) ;
273 if ( (**(ListHandle
)m_macList
).listDefProc
!= NULL
)
275 (**ldef
).instruction
= 0x4EF9; /* JMP instruction */
276 (**ldef
).function
= (void(*)()) listDef
.u
.userProc
;
277 (**(ListHandle
)m_macList
).listDefProc
= (Handle
) ldef
;
280 Point pt
= (**(ListHandle
)m_macList
).cellSize
;
282 LCellSize( pt
, (ListHandle
)m_macList
) ;
283 LAddColumn( 1 , 0 , (ListHandle
)m_macList
) ;
285 OptionBits options
= 0;
286 if ( style
& wxLB_MULTIPLE
)
288 options
+= lNoExtend
;
290 else if ( style
& wxLB_EXTENDED
)
292 options
+= lExtendDrag
;
296 options
= (OptionBits
) lOnlyOne
;
298 SetListSelectionFlags((ListHandle
)m_macList
, options
);
300 MacPostControlCreate() ;
302 for ( int i
= 0 ; i
< n
; i
++ )
304 Append( choices
[i
] ) ;
307 LSetDrawingMode( true , (ListHandle
) m_macList
) ;
312 // ----------------------------------------------------------------------------
313 // wxCheckListBox functions
314 // ----------------------------------------------------------------------------
316 bool wxCheckListBox::IsChecked(unsigned int item
) const
318 wxCHECK_MSG( IsValid(item
), false,
319 _T("invalid index in wxCheckListBox::IsChecked") );
321 return m_checks
[item
] != 0;
324 void wxCheckListBox::Check(unsigned int item
, bool check
)
326 wxCHECK_RET( IsValid(item
),
327 _T("invalid index in wxCheckListBox::Check") );
329 // intermediate var is needed to avoid compiler warning with VC++
330 bool isChecked
= m_checks
[item
] != 0;
331 if ( check
!= isChecked
)
333 m_checks
[item
] = check
;
339 // ----------------------------------------------------------------------------
340 // methods forwarded to wxListBox
341 // ----------------------------------------------------------------------------
343 void wxCheckListBox::Delete(unsigned int n
)
345 wxCHECK_RET( IsValid(n
), _T("invalid index in wxListBox::Delete") );
347 wxListBox::Delete(n
);
349 m_checks
.RemoveAt(n
);
352 int wxCheckListBox::DoAppend(const wxString
& item
)
354 LSetDrawingMode( false , (ListHandle
) m_macList
) ;
355 int pos
= wxListBox::DoAppend(item
);
357 // the item is initially unchecked
358 m_checks
.Insert(false, pos
);
359 LSetDrawingMode( true , (ListHandle
) m_macList
) ;
364 void wxCheckListBox::DoInsertItems(const wxArrayString
& items
, unsigned int pos
)
366 wxListBox::DoInsertItems(items
, pos
);
368 unsigned int count
= items
.GetCount();
369 for ( unsigned int n
= 0; n
< count
; n
++ )
371 m_checks
.Insert(false, pos
+ n
);
375 void wxCheckListBox::DoSetItems(const wxArrayString
& items
, void **clientData
)
377 // call it first as it does DoClear()
378 wxListBox::DoSetItems(items
, clientData
);
380 unsigned int count
= items
.GetCount();
381 for ( unsigned int n
= 0; n
< count
; n
++ )
387 void wxCheckListBox::DoClear()
392 BEGIN_EVENT_TABLE(wxCheckListBox
, wxListBox
)
393 EVT_CHAR(wxCheckListBox::OnChar
)
394 EVT_LEFT_DOWN(wxCheckListBox::OnLeftClick
)
397 // this will only work as soon as
399 void wxCheckListBox::OnChar(wxKeyEvent
& event
)
401 if ( event
.GetKeyCode() == WXK_SPACE
)
403 int index
= GetSelection() ;
406 Check(index
, !IsChecked(index
) ) ;
407 wxCommandEvent
event(wxEVT_COMMAND_CHECKLISTBOX_TOGGLED
, GetId());
409 event
.SetEventObject(this);
410 GetEventHandler()->ProcessEvent(event
);
417 void wxCheckListBox::OnLeftClick(wxMouseEvent
& event
)
419 // clicking on the item selects it, clicking on the checkmark toggles
420 if ( event
.GetX() <= 20 /*check width*/ ) {
425 GetListCellSize( (ListHandle
)m_macList
, &pt
) ;
428 GetListVisibleCells( (ListHandle
)m_macList
, &visible
) ;
429 topcell
= visible
.top
;
431 lineheight
= (**(ListHandle
)m_macList
).cellSize
.v
;
432 topcell
= (**(ListHandle
)m_macList
).visible
.top
;
434 size_t nItem
= ((size_t)event
.GetY()) / lineheight
+ topcell
;
436 if ( nItem
< m_noItems
)
438 Check(nItem
, !IsChecked(nItem
) ) ;
439 wxCommandEvent
event(wxEVT_COMMAND_CHECKLISTBOX_TOGGLED
, GetId());
441 event
.SetEventObject(this);
442 GetEventHandler()->ProcessEvent(event
);
444 //else: it's not an error, just click outside of client zone
447 // implement default behaviour: clicking on the item selects it
452 #endif // wxUSE_CHECKLISTBOX