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"
25 #include "wx/arrstr.h"
27 #include "wx/mac/uma.h"
28 #include <Appearance.h>
30 // ============================================================================
31 // implementation of wxCheckListBox
32 // ============================================================================
34 IMPLEMENT_DYNAMIC_CLASS(wxCheckListBox
, wxListBox
)
36 const short kwxMacListWithVerticalScrollbar
= 128 ;
37 const short kwxMacListItemHeight
= 14 ;
38 const short kwxMacListCheckboxWidth
= 14 ;
40 #if PRAGMA_STRUCT_ALIGN
41 #pragma options align=mac68k
42 #elif PRAGMA_STRUCT_PACKPUSH
44 #elif PRAGMA_STRUCT_PACK
49 unsigned short instruction
;
51 } ldefRec
, *ldefPtr
, **ldefHandle
;
53 #if PRAGMA_STRUCT_ALIGN
54 #pragma options align=reset
55 #elif PRAGMA_STRUCT_PACKPUSH
57 #elif PRAGMA_STRUCT_PACK
63 static pascal void wxMacCheckListDefinition( short message
, Boolean isSelected
, Rect
*drawRect
,
64 Cell cell
, short dataOffset
, short dataLength
,
65 ListHandle listHandle
) ;
68 static pascal void wxMacCheckListDefinition( short message
, Boolean isSelected
, Rect
*drawRect
,
69 Cell cell
, short dataOffset
, short dataLength
,
70 ListHandle listHandle
)
73 list
= (wxCheckListBox
*) GetControlReference( (ControlRef
) GetListRefCon(listHandle
) );
79 RgnHandle savedClipRegion
;
82 SetPort((**listHandle
).port
);
83 grafPtr
= (**listHandle
).port
;
84 // typecast our refCon
86 // Calculate the cell rect.
97 const wxString text
= list
->m_stringArray
[cell
.v
] ;
98 int checked
= list
->m_checks
[cell
.v
] ;
100 // Save the current clip region, and set the clip region to the area we are about
103 savedClipRegion
= NewRgn();
104 GetClip( savedClipRegion
);
106 ClipRect( drawRect
);
107 EraseRect( drawRect
);
109 const wxFont
& font
= list
->GetFont();
112 ::TextFont( font
.MacGetFontNum() ) ;
113 ::TextSize( font
.MacGetFontSize()) ;
114 ::TextFace( font
.MacGetFontStyle() ) ;
117 ThemeButtonDrawInfo info
;
118 info
.state
= kThemeStateActive
;
119 info
.value
= checked
? kThemeButtonOn
: kThemeButtonOff
;
120 info
.adornment
= kThemeAdornmentNone
;
121 Rect checkRect
= *drawRect
;
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);
131 MoveTo(drawRect
->left
+ 2 + list
->m_checkBoxWidth
+2, drawRect
->top
+ list
->m_TextBaseLineOffset
);
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.
138 savedPenMode
= GetPortPenMode( (CGrafPtr
) grafPtr
);
139 SetPortPenMode( (CGrafPtr
) grafPtr
, hilitetransfermode
);
140 PaintRect( drawRect
);
141 SetPortPenMode( (CGrafPtr
) grafPtr
, savedPenMode
);
144 // Restore the saved clip region.
146 SetClip( savedClipRegion
);
147 DisposeRgn( savedClipRegion
);
152 // Hilite or unhilite the cell. Paint the cell contents with the
153 // appropriate QuickDraw transform mode.
156 savedPenMode
= GetPortPenMode( (CGrafPtr
) grafPtr
);
157 SetPortPenMode( (CGrafPtr
) grafPtr
, hilitetransfermode
);
158 PaintRect( drawRect
);
159 SetPortPenMode( (CGrafPtr
) grafPtr
, savedPenMode
);
167 extern "C" void MacDrawStringCell(Rect
*cellRect
, Cell lCell
, ListHandle theList
, long refCon
) ;
169 static ListDefUPP macCheckListDefUPP
= NULL
;
171 // ----------------------------------------------------------------------------
173 // ----------------------------------------------------------------------------
175 void wxCheckListBox::Init()
179 bool wxCheckListBox::Create(wxWindow
*parent
,
183 const wxArrayString
& choices
,
185 const wxValidator
& validator
,
186 const wxString
&name
)
188 wxCArrayString
chs(choices
);
190 return Create(parent
, id
, pos
, size
, chs
.GetCount(), chs
.GetStrings(),
191 style
, validator
, name
);
194 bool wxCheckListBox::Create(wxWindow
*parent
,
199 const wxString choices
[],
201 const wxValidator
& validator
,
202 const wxString
&name
)
204 m_macIsUserPane
= FALSE
;
206 if ( !wxCheckListBoxBase::Create(parent
, id
, pos
, size
,
207 n
, choices
, style
, validator
, name
) )
210 m_noItems
= 0 ; // this will be increased by our append command
213 m_checkBoxWidth
= 12;
214 m_checkBoxHeight
= 10;
216 long h
= m_checkBoxHeight
;
218 GetThemeMetric(kThemeMetricCheckBoxWidth
,(long *)&m_checkBoxWidth
);
219 GetThemeMetric(kThemeMetricCheckBoxHeight
,&h
);
222 const wxFont
& font
= GetFont();
225 FetchFontInfo(font
.MacGetFontNum(),font
.MacGetFontSize(),font
.MacGetFontStyle(),&finfo
);
227 m_TextBaseLineOffset
= finfo
.leading
+finfo
.ascent
;
228 m_checkBoxHeight
= finfo
.leading
+finfo
.ascent
+finfo
.descent
;
230 if (m_checkBoxHeight
<h
)
232 m_TextBaseLineOffset
+= (h
-m_checkBoxHeight
)/2;
237 Rect bounds
= wxMacGetBoundsForControl( this , pos
, size
) ;
240 listDef
.defType
= kListDefUserProcType
;
241 if ( macCheckListDefUPP
== NULL
)
243 macCheckListDefUPP
= NewListDefUPP( wxMacCheckListDefinition
);
245 listDef
.u
.userProc
= macCheckListDefUPP
;
250 CreateListBoxControl( MAC_WXHWND(parent
->MacGetTopLevelWindowRef()), &bounds
, false, 0, 1, false, true,
251 m_checkBoxHeight
+2, 14, false, &listDef
, (ControlRef
*)&m_macControl
);
253 GetControlData( (ControlRef
) m_macControl
, kControlNoPart
, kControlListBoxListHandleTag
,
254 sizeof(ListHandle
), (Ptr
) &m_macList
, &asize
);
256 SetControlReference( (ControlRef
) m_macControl
, (long) this);
257 SetControlVisibility( (ControlRef
) m_macControl
, false, false);
260 OptionBits options
= 0;
261 if ( style
& wxLB_MULTIPLE
)
263 options
+= lNoExtend
;
265 else if ( style
& wxLB_EXTENDED
)
267 options
+= lExtendDrag
;
271 options
= (OptionBits
) lOnlyOne
;
273 SetListSelectionFlags((ListHandle
)m_macList
, options
);
275 MacPostControlCreate(pos
,size
) ;
277 for ( int i
= 0 ; i
< n
; i
++ )
279 Append( choices
[i
] ) ;
282 LSetDrawingMode( true , (ListHandle
) m_macList
) ;
287 // ----------------------------------------------------------------------------
288 // wxCheckListBox functions
289 // ----------------------------------------------------------------------------
291 bool wxCheckListBox::IsChecked(size_t item
) const
293 wxCHECK_MSG( item
< m_checks
.GetCount(), FALSE
,
294 _T("invalid index in wxCheckListBox::IsChecked") );
296 return m_checks
[item
] != 0;
299 void wxCheckListBox::Check(size_t item
, bool check
)
301 wxCHECK_RET( item
< m_checks
.GetCount(),
302 _T("invalid index in wxCheckListBox::Check") );
304 // intermediate var is needed to avoid compiler warning with VC++
305 bool isChecked
= m_checks
[item
] != 0;
306 if ( check
!= isChecked
)
308 m_checks
[item
] = check
;
314 // ----------------------------------------------------------------------------
315 // methods forwarded to wxListBox
316 // ----------------------------------------------------------------------------
318 void wxCheckListBox::Delete(int n
)
320 wxCHECK_RET( n
< GetCount(), _T("invalid index in wxListBox::Delete") );
322 wxListBox::Delete(n
);
324 m_checks
.RemoveAt(n
);
327 int wxCheckListBox::DoAppend(const wxString
& item
)
329 LSetDrawingMode( false , (ListHandle
) m_macList
) ;
330 int pos
= wxListBox::DoAppend(item
);
332 // the item is initially unchecked
333 m_checks
.Insert(FALSE
, pos
);
334 LSetDrawingMode( true , (ListHandle
) m_macList
) ;
339 void wxCheckListBox::DoInsertItems(const wxArrayString
& items
, int pos
)
341 wxListBox::DoInsertItems(items
, pos
);
343 size_t count
= items
.GetCount();
344 for ( size_t n
= 0; n
< count
; n
++ )
346 m_checks
.Insert(FALSE
, pos
+ n
);
350 void wxCheckListBox::DoSetItems(const wxArrayString
& items
, void **clientData
)
352 // call it first as it does DoClear()
353 wxListBox::DoSetItems(items
, clientData
);
355 size_t count
= items
.GetCount();
356 for ( size_t n
= 0; n
< count
; n
++ )
362 void wxCheckListBox::DoClear()
367 BEGIN_EVENT_TABLE(wxCheckListBox
, wxListBox
)
368 EVT_CHAR(wxCheckListBox::OnChar
)
369 EVT_LEFT_DOWN(wxCheckListBox::OnLeftClick
)
372 // this will only work as soon as
374 void wxCheckListBox::OnChar(wxKeyEvent
& event
)
376 if ( event
.GetKeyCode() == WXK_SPACE
)
378 int index
= GetSelection() ;
381 Check(index
, !IsChecked(index
) ) ;
382 wxCommandEvent
event(wxEVT_COMMAND_CHECKLISTBOX_TOGGLED
, GetId());
384 event
.SetEventObject(this);
385 GetEventHandler()->ProcessEvent(event
);
392 void wxCheckListBox::OnLeftClick(wxMouseEvent
& event
)
394 // clicking on the item selects it, clicking on the checkmark toggles
395 if ( event
.GetX() <= 20 /*check width*/ ) {
400 GetListCellSize( (ListHandle
)m_macList
, &pt
) ;
403 GetListVisibleCells( (ListHandle
)m_macList
, &visible
) ;
404 topcell
= visible
.top
;
406 lineheight
= (**(ListHandle
)m_macList
).cellSize
.v
;
407 topcell
= (**(ListHandle
)m_macList
).visible
.top
;
409 size_t nItem
= ((size_t)event
.GetY()) / lineheight
+ topcell
;
411 if ( nItem
< (size_t)m_noItems
)
413 Check(nItem
, !IsChecked(nItem
) ) ;
414 wxCommandEvent
event(wxEVT_COMMAND_CHECKLISTBOX_TOGGLED
, GetId());
416 event
.SetEventObject(this);
417 GetEventHandler()->ProcessEvent(event
);
419 //else: it's not an error, just click outside of client zone
422 // implement default behaviour: clicking on the item selects it
427 #endif // wxUSE_CHECKLISTBOX