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( (ControlHandle
) 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
.GetMacFontNum() ) ; 
 113                 ::TextSize( font
.GetMacFontSize())  ; 
 114                 ::TextFace( font
.GetMacFontStyle() ) ; 
 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     if ( !wxCheckListBoxBase::Create(parent
, id
, pos
, size
, 
 205                                      n
, choices
, style
, validator
, name
) ) 
 208     m_noItems 
= 0 ; // this will be increased by our append command 
 211     m_checkBoxWidth 
= 12; 
 212     m_checkBoxHeight
= 10; 
 214     long h 
= m_checkBoxHeight 
; 
 216     GetThemeMetric(kThemeMetricCheckBoxWidth
,(long *)&m_checkBoxWidth
);     
 217     GetThemeMetric(kThemeMetricCheckBoxHeight
,&h
); 
 220     const wxFont
& font 
= GetFont(); 
 223     FetchFontInfo(font
.GetMacFontNum(),font
.GetMacFontSize(),font
.GetMacFontStyle(),&finfo
); 
 225     m_TextBaseLineOffset
= finfo
.leading
+finfo
.ascent
; 
 226     m_checkBoxHeight
= finfo
.leading
+finfo
.ascent
+finfo
.descent
; 
 228     if (m_checkBoxHeight
<h
) 
 230         m_TextBaseLineOffset
+= (h
-m_checkBoxHeight
)/2; 
 237     MacPreControlCreate( parent 
, id 
,  wxEmptyString 
, pos 
, size 
,style
, validator 
, name 
, &bounds 
, title 
) ; 
 240     listDef
.defType 
= kListDefUserProcType
; 
 241     if ( macCheckListDefUPP 
== NULL 
) 
 243       macCheckListDefUPP 
= NewListDefUPP( wxMacCheckListDefinition 
);  
 245         listDef
.u
.userProc 
= macCheckListDefUPP 
; 
 251     CreateListBoxControl( MAC_WXHWND(parent
->MacGetRootWindow()), &bounds
, false, 0, 1, false, true, 
 252                           m_checkBoxHeight
+2, 14, false, &listDef
, (ControlRef 
*)&m_macControl 
); 
 254     GetControlData( (ControlHandle
) m_macControl
, kControlNoPart
, kControlListBoxListHandleTag
, 
 255                    sizeof(ListHandle
), (Ptr
) &m_macList
, &asize
); 
 257     SetControlReference( (ControlHandle
) m_macControl
, (long) this); 
 258     SetControlVisibility( (ControlHandle
) m_macControl
, false, false); 
 264     wxStAppResource resload 
; 
 265     m_macControl 
= (WXWidget
) ::NewControl( MAC_WXHWND(parent
->MacGetRootWindow()) , &bounds 
, title 
, false , 
 266                   kwxMacListWithVerticalScrollbar 
, 0 , 0,  
 267                   kControlListBoxProc 
, (long) this ) ; 
 268     ::GetControlData( (ControlHandle
) m_macControl 
, kControlNoPart 
, kControlListBoxListHandleTag 
, 
 269                sizeof( ListHandle 
) , (char*) &m_macList  
, &result 
) ; 
 271     HLock( (Handle
) m_macList 
) ; 
 273     ldef 
= (ldefHandle
) NewHandle( sizeof(ldefRec
) ) ; 
 274     if (  (**(ListHandle
)m_macList
).listDefProc 
!= NULL 
) 
 276       (**ldef
).instruction 
= 0x4EF9;  /* JMP instruction */ 
 277       (**ldef
).function 
= (void(*)()) listDef
.u
.userProc
; 
 278       (**(ListHandle
)m_macList
).listDefProc 
= (Handle
) ldef 
; 
 281     Point pt 
= (**(ListHandle
)m_macList
).cellSize 
; 
 283     LCellSize( pt 
, (ListHandle
)m_macList 
) ; 
 284     LAddColumn( 1 , 0 , (ListHandle
)m_macList 
) ; 
 286     OptionBits  options 
= 0; 
 287     if ( style 
& wxLB_MULTIPLE 
) 
 289         options 
+= lNoExtend 
; 
 291     else if ( style 
& wxLB_EXTENDED 
) 
 293         options 
+= lExtendDrag 
; 
 297         options 
= (OptionBits
) lOnlyOne 
; 
 299     SetListSelectionFlags((ListHandle
)m_macList
, options
); 
 301     MacPostControlCreate() ; 
 303     for ( int i 
= 0 ; i 
< n 
; i
++ ) 
 305         Append( choices
[i
] ) ; 
 308     LSetDrawingMode( true , (ListHandle
) m_macList 
) ; 
 313 // ---------------------------------------------------------------------------- 
 314 // wxCheckListBox functions 
 315 // ---------------------------------------------------------------------------- 
 317 bool wxCheckListBox::IsChecked(size_t item
) const 
 319     wxCHECK_MSG( item 
< m_checks
.GetCount(), FALSE
, 
 320                  _T("invalid index in wxCheckListBox::IsChecked") ); 
 322     return m_checks
[item
] != 0; 
 325 void wxCheckListBox::Check(size_t item
, bool check
) 
 327     wxCHECK_RET( item 
< m_checks
.GetCount(), 
 328                  _T("invalid index in wxCheckListBox::Check") ); 
 330     // intermediate var is needed to avoid compiler warning with VC++ 
 331     bool isChecked 
= m_checks
[item
] != 0; 
 332     if ( check 
!= isChecked 
) 
 334         m_checks
[item
] = check
; 
 340 // ---------------------------------------------------------------------------- 
 341 // methods forwarded to wxListBox 
 342 // ---------------------------------------------------------------------------- 
 344 void wxCheckListBox::Delete(int n
) 
 346     wxCHECK_RET( n 
< GetCount(), _T("invalid index in wxListBox::Delete") ); 
 348     wxListBox::Delete(n
); 
 350     m_checks
.RemoveAt(n
); 
 353 int wxCheckListBox::DoAppend(const wxString
& item
) 
 355     LSetDrawingMode( false , (ListHandle
) m_macList 
) ; 
 356     int pos 
= wxListBox::DoAppend(item
); 
 358     // the item is initially unchecked 
 359     m_checks
.Insert(FALSE
, pos
); 
 360     LSetDrawingMode( true , (ListHandle
) m_macList 
) ; 
 365 void wxCheckListBox::DoInsertItems(const wxArrayString
& items
, int pos
) 
 367     wxListBox::DoInsertItems(items
, pos
); 
 369     size_t count 
= items
.GetCount(); 
 370     for ( size_t n 
= 0; n 
< count
; n
++ ) 
 372         m_checks
.Insert(FALSE
, pos 
+ n
); 
 376 void wxCheckListBox::DoSetItems(const wxArrayString
& items
, void **clientData
) 
 378     // call it first as it does DoClear() 
 379     wxListBox::DoSetItems(items
, clientData
); 
 381     size_t count 
= items
.GetCount(); 
 382     for ( size_t n 
= 0; n 
< count
; n
++ ) 
 388 void wxCheckListBox::DoClear() 
 393 BEGIN_EVENT_TABLE(wxCheckListBox
, wxListBox
) 
 394   EVT_CHAR(wxCheckListBox::OnChar
) 
 395   EVT_LEFT_DOWN(wxCheckListBox::OnLeftClick
) 
 398 // this will only work as soon as  
 400 void wxCheckListBox::OnChar(wxKeyEvent
& event
) 
 402     if ( event
.GetKeyCode() == WXK_SPACE 
) 
 404         int index 
= GetSelection() ; 
 407             Check(index
, !IsChecked(index
) ) ; 
 408             wxCommandEvent 
event(wxEVT_COMMAND_CHECKLISTBOX_TOGGLED
, GetId()); 
 410             event
.SetEventObject(this); 
 411             GetEventHandler()->ProcessEvent(event
); 
 418 void wxCheckListBox::OnLeftClick(wxMouseEvent
& event
) 
 420     // clicking on the item selects it, clicking on the checkmark toggles 
 421     if ( event
.GetX() <= 20 /*check width*/ ) { 
 426         GetListCellSize( (ListHandle
)m_macList 
, &pt 
) ; 
 429         GetListVisibleCells( (ListHandle
)m_macList 
, &visible 
) ; 
 430         topcell 
= visible
.top 
; 
 432         lineheight 
=  (**(ListHandle
)m_macList
).cellSize
.v 
; 
 433         topcell 
= (**(ListHandle
)m_macList
).visible
.top 
; 
 435         size_t nItem 
= ((size_t)event
.GetY()) / lineheight 
+ topcell 
; 
 437         if ( nItem 
< (size_t)m_noItems 
) 
 439             Check(nItem
, !IsChecked(nItem
) ) ; 
 440             wxCommandEvent 
event(wxEVT_COMMAND_CHECKLISTBOX_TOGGLED
, GetId()); 
 442             event
.SetEventObject(this); 
 443             GetEventHandler()->ProcessEvent(event
); 
 445         //else: it's not an error, just click outside of client zone 
 448         // implement default behaviour: clicking on the item selects it 
 453 #endif // wxUSE_CHECKLISTBOX