1 ///////////////////////////////////////////////////////////////////////////////
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 // ============================================================================
17 #pragma implementation "checklst.h"
22 #if wxUSE_CHECKLISTBOX
24 #include "wx/checklst.h"
26 #include "wx/mac/uma.h"
27 #include "Appearance.h"
29 // ============================================================================
30 // implementation of wxCheckListBoxBase
31 // ============================================================================
33 wxCheckListBoxBase::wxCheckListBoxBase()
37 // ============================================================================
38 // implementation of wxCheckListBox
39 // ============================================================================
41 IMPLEMENT_DYNAMIC_CLASS(wxCheckListBox
, wxListBox
)
43 const short kwxMacListWithVerticalScrollbar
= 128 ;
44 const short kwxMacListItemHeight
= 14 ;
45 const short kwxMacListCheckboxWidth
= 14 ;
47 #if PRAGMA_STRUCT_ALIGN
48 #pragma options align=mac68k
49 #elif PRAGMA_STRUCT_PACKPUSH
51 #elif PRAGMA_STRUCT_PACK
56 unsigned short instruction
;
58 } ldefRec
, *ldefPtr
, **ldefHandle
;
60 #if PRAGMA_STRUCT_ALIGN
61 #pragma options align=reset
62 #elif PRAGMA_STRUCT_PACKPUSH
64 #elif PRAGMA_STRUCT_PACK
70 static pascal void wxMacCheckListDefinition( short message
, Boolean isSelected
, Rect
*drawRect
,
71 Cell cell
, short dataOffset
, short dataLength
,
72 ListHandle listHandle
) ;
75 static pascal void wxMacCheckListDefinition( short message
, Boolean isSelected
, Rect
*drawRect
,
76 Cell cell
, short dataOffset
, short dataLength
,
77 ListHandle listHandle
)
81 RgnHandle savedClipRegion
;
85 SetPort((**listHandle
).port
);
86 grafPtr
= (**listHandle
).port
;
87 // typecast our refCon
88 list
= (wxCheckListBox
*) GetControlReference( (ControlHandle
) GetListRefCon(listHandle
) );
90 // Calculate the cell rect.
101 const wxString text
= list
->m_stringArray
[cell
.v
] ;
102 int checked
= list
->m_checks
[cell
.v
] ;
104 // Save the current clip region, and set the clip region to the area we are about
107 savedClipRegion
= NewRgn();
108 GetClip( savedClipRegion
);
110 ClipRect( drawRect
);
111 EraseRect( drawRect
);
113 const wxFont
& font
= list
->GetFont();
116 ::TextFont( font
.GetMacFontNum() ) ;
117 ::TextSize( font
.GetMacFontSize()) ;
118 ::TextFace( font
.GetMacFontStyle() ) ;
121 ThemeButtonDrawInfo info
;
122 info
.state
= kThemeStateActive
;
123 info
.value
= checked
? kThemeButtonOn
: kThemeButtonOff
;
124 info
.adornment
= kThemeAdornmentNone
;
125 Rect checkRect
= *drawRect
;
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);
135 MoveTo(drawRect
->left
+ 2 + list
->m_checkBoxWidth
+2, drawRect
->top
+ list
->m_TextBaseLineOffset
);
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.
142 savedPenMode
= GetPortPenMode( (CGrafPtr
) grafPtr
);
143 SetPortPenMode( (CGrafPtr
) grafPtr
, hilitetransfermode
);
144 PaintRect( drawRect
);
145 SetPortPenMode( (CGrafPtr
) grafPtr
, savedPenMode
);
148 // Restore the saved clip region.
150 SetClip( savedClipRegion
);
151 DisposeRgn( savedClipRegion
);
156 // Hilite or unhilite the cell. Paint the cell contents with the
157 // appropriate QuickDraw transform mode.
160 savedPenMode
= GetPortPenMode( (CGrafPtr
) grafPtr
);
161 SetPortPenMode( (CGrafPtr
) grafPtr
, hilitetransfermode
);
162 PaintRect( drawRect
);
163 SetPortPenMode( (CGrafPtr
) grafPtr
, savedPenMode
);
171 extern "C" void MacDrawStringCell(Rect
*cellRect
, Cell lCell
, ListHandle theList
, long refCon
) ;
173 static ListDefUPP macCheckListDefUPP
= NULL
;
175 // ----------------------------------------------------------------------------
177 // ----------------------------------------------------------------------------
179 void wxCheckListBox::Init()
183 bool wxCheckListBox::Create(wxWindow
*parent
,
188 const wxString choices
[],
190 const wxValidator
& validator
,
191 const wxString
&name
)
193 if ( !wxCheckListBoxBase::Create(parent
, id
, pos
, size
,
194 n
, choices
, style
, validator
, name
) )
197 m_noItems
= 0 ; // this will be increased by our append command
200 m_checkBoxWidth
= 12;
201 m_checkBoxHeight
= 10;
203 long h
= m_checkBoxHeight
;
205 GetThemeMetric(kThemeMetricCheckBoxWidth
,(long *)&m_checkBoxWidth
);
206 GetThemeMetric(kThemeMetricCheckBoxHeight
,&h
);
209 const wxFont
& font
= GetFont();
212 FetchFontInfo(font
.GetMacFontNum(),font
.GetMacFontSize(),font
.GetMacFontStyle(),&finfo
);
214 m_TextBaseLineOffset
= finfo
.leading
+finfo
.ascent
;
215 m_checkBoxHeight
= finfo
.leading
+finfo
.ascent
+finfo
.descent
;
217 if (m_checkBoxHeight
<h
)
219 m_TextBaseLineOffset
+= (h
-m_checkBoxHeight
)/2;
226 MacPreControlCreate( parent
, id
, wxEmptyString
, pos
, size
,style
, validator
, name
, &bounds
, title
) ;
229 listDef
.defType
= kListDefUserProcType
;
230 if ( macCheckListDefUPP
== NULL
)
232 macCheckListDefUPP
= NewListDefUPP( wxMacCheckListDefinition
);
234 listDef
.u
.userProc
= macCheckListDefUPP
;
240 CreateListBoxControl( MAC_WXHWND(parent
->MacGetRootWindow()), &bounds
, false, 0, 1, false, true,
241 m_checkBoxHeight
+2, 14, false, &listDef
, (ControlRef
*)&m_macControl
);
243 GetControlData( (ControlHandle
) m_macControl
, kControlNoPart
, kControlListBoxListHandleTag
,
244 sizeof(ListHandle
), (Ptr
) &m_macList
, &asize
);
246 SetControlReference( (ControlHandle
) m_macControl
, (long) this);
247 SetControlVisibility( (ControlHandle
) m_macControl
, false, false);
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
) ;
260 HLock( (Handle
) m_macList
) ;
262 ldef
= (ldefHandle
) NewHandle( sizeof(ldefRec
) ) ;
263 if ( (**(ListHandle
)m_macList
).listDefProc
!= NULL
)
265 (**ldef
).instruction
= 0x4EF9; /* JMP instruction */
266 (**ldef
).function
= (void(*)()) listDef
.u
.userProc
;
267 (**(ListHandle
)m_macList
).listDefProc
= (Handle
) ldef
;
270 Point pt
= (**(ListHandle
)m_macList
).cellSize
;
272 LCellSize( pt
, (ListHandle
)m_macList
) ;
273 LAddColumn( 1 , 0 , (ListHandle
)m_macList
) ;
275 OptionBits options
= 0;
276 if ( style
& wxLB_MULTIPLE
)
278 options
+= lNoExtend
;
280 else if ( style
& wxLB_EXTENDED
)
282 options
+= lExtendDrag
;
286 options
= (OptionBits
) lOnlyOne
;
288 SetListSelectionFlags((ListHandle
)m_macList
, options
);
290 MacPostControlCreate() ;
292 for ( int i
= 0 ; i
< n
; i
++ )
294 Append( choices
[i
] ) ;
297 LSetDrawingMode( true , (ListHandle
) m_macList
) ;
302 // ----------------------------------------------------------------------------
303 // wxCheckListBox functions
304 // ----------------------------------------------------------------------------
306 bool wxCheckListBox::IsChecked(size_t item
) const
308 wxCHECK_MSG( item
< m_checks
.GetCount(), FALSE
,
309 _T("invalid index in wxCheckListBox::IsChecked") );
311 return m_checks
[item
] != 0;
314 void wxCheckListBox::Check(size_t item
, bool check
)
316 wxCHECK_RET( item
< m_checks
.GetCount(),
317 _T("invalid index in wxCheckListBox::Check") );
319 // intermediate var is needed to avoid compiler warning with VC++
320 bool isChecked
= m_checks
[item
] != 0;
321 if ( check
!= isChecked
)
323 m_checks
[item
] = check
;
329 // ----------------------------------------------------------------------------
330 // methods forwarded to wxListBox
331 // ----------------------------------------------------------------------------
333 void wxCheckListBox::Delete(int n
)
335 wxCHECK_RET( n
< GetCount(), _T("invalid index in wxListBox::Delete") );
337 wxListBox::Delete(n
);
339 m_checks
.RemoveAt(n
);
342 int wxCheckListBox::DoAppend(const wxString
& item
)
344 LSetDrawingMode( false , (ListHandle
) m_macList
) ;
345 int pos
= wxListBox::DoAppend(item
);
347 // the item is initially unchecked
348 m_checks
.Insert(FALSE
, pos
);
349 LSetDrawingMode( true , (ListHandle
) m_macList
) ;
354 void wxCheckListBox::DoInsertItems(const wxArrayString
& items
, int pos
)
356 wxListBox::DoInsertItems(items
, pos
);
358 size_t count
= items
.GetCount();
359 for ( size_t n
= 0; n
< count
; n
++ )
361 m_checks
.Insert(FALSE
, pos
+ n
);
365 void wxCheckListBox::DoSetItems(const wxArrayString
& items
, void **clientData
)
367 // call it first as it does DoClear()
368 wxListBox::DoSetItems(items
, clientData
);
370 size_t count
= items
.GetCount();
371 for ( size_t n
= 0; n
< count
; n
++ )
377 void wxCheckListBox::DoClear()
382 BEGIN_EVENT_TABLE(wxCheckListBox
, wxListBox
)
383 EVT_CHAR(wxCheckListBox::OnChar
)
384 EVT_LEFT_DOWN(wxCheckListBox::OnLeftClick
)
387 // this will only work as soon as
389 void wxCheckListBox::OnChar(wxKeyEvent
& event
)
391 if ( event
.GetKeyCode() == WXK_SPACE
)
393 int index
= GetSelection() ;
396 Check(index
, !IsChecked(index
) ) ;
397 wxCommandEvent
event(wxEVT_COMMAND_CHECKLISTBOX_TOGGLED
, GetId());
399 event
.SetEventObject(this);
400 GetEventHandler()->ProcessEvent(event
);
407 void wxCheckListBox::OnLeftClick(wxMouseEvent
& event
)
409 // clicking on the item selects it, clicking on the checkmark toggles
410 if ( event
.GetX() <= 20 /*check width*/ ) {
415 GetListCellSize( (ListHandle
)m_macList
, &pt
) ;
418 GetListVisibleCells( (ListHandle
)m_macList
, &visible
) ;
419 topcell
= visible
.top
;
421 lineheight
= (**(ListHandle
)m_macList
).cellSize
.v
;
422 topcell
= (**(ListHandle
)m_macList
).visible
.top
;
424 size_t nItem
= ((size_t)event
.GetY()) / lineheight
+ topcell
;
426 if ( nItem
< (size_t)m_noItems
)
428 Check(nItem
, !IsChecked(nItem
) ) ;
429 wxCommandEvent
event(wxEVT_COMMAND_CHECKLISTBOX_TOGGLED
, GetId());
431 event
.SetEventObject(this);
432 GetEventHandler()->ProcessEvent(event
);
434 //else: it's not an error, just click outside of client zone
437 // implement default behaviour: clicking on the item selects it
442 #endif // wxUSE_CHECKLISTBOX