1 /////////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     implementation of wxCheckListBox class 
   8 // Copyright:   (c) AUTHOR 
   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 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 
) 
  73     RgnHandle savedClipRegion
; 
  77   SetPort((**listHandle
).port
); 
  78   grafPtr 
= (**listHandle
).port 
; 
  79     // typecast our refCon 
  80     list 
= (wxCheckListBox
*) GetControlReference( (ControlHandle
) GetListRefCon(listHandle
) ); 
  82     //  Calculate the cell rect. 
  93             const wxString text 
= list
->m_stringArray
[cell
.v
] ; 
  94             int checked 
= list
->m_checks
[cell
.v
] ; 
  96             //  Save the current clip region, and set the clip region to the area we are about 
  99             savedClipRegion 
= NewRgn(); 
 100             GetClip( savedClipRegion 
); 
 102             ClipRect( drawRect 
); 
 103             EraseRect( drawRect 
); 
 105             ::TextFont( kFontIDMonaco 
) ; 
 108             ThemeButtonDrawInfo info 
; 
 109             info
.state 
= kThemeStateActive 
; 
 110             info
.value 
= checked 
? kThemeButtonOn 
: kThemeButtonOff 
; 
 111             info
.adornment 
= kThemeAdornmentNone 
; 
 112             Rect checkRect 
= *drawRect 
; 
 115             checkRect
.right 
= checkRect
.left 
+ 12 ; 
 116             checkRect
.bottom 
= checkRect
.top 
+ 10 ; 
 117             DrawThemeButton(&checkRect
,kThemeCheckBox
, 
 118               &info
,NULL
,NULL
, NULL
,0); 
 120         MoveTo(drawRect
->left 
+ 4 + kwxMacListCheckboxWidth
, drawRect
->top 
+ 10 ); 
 122         DrawText(text
, 0 , text
.Length()); 
 123             //  If the cell is hilited, do the hilite now. Paint the cell contents with the 
 124             //  appropriate QuickDraw transform mode. 
 127                 savedPenMode 
= GetPortPenMode( (CGrafPtr
) grafPtr 
); 
 128                 SetPortPenMode( (CGrafPtr
) grafPtr
, hilitetransfermode 
); 
 129                 PaintRect( drawRect 
); 
 130                 SetPortPenMode( (CGrafPtr
) grafPtr
, savedPenMode 
); 
 133             //  Restore the saved clip region. 
 135             SetClip( savedClipRegion 
); 
 136             DisposeRgn( savedClipRegion 
); 
 141             //  Hilite or unhilite the cell. Paint the cell contents with the 
 142             //  appropriate QuickDraw transform mode. 
 145             savedPenMode 
= GetPortPenMode( (CGrafPtr
) grafPtr 
); 
 146             SetPortPenMode( (CGrafPtr
) grafPtr
, hilitetransfermode 
); 
 147             PaintRect( drawRect 
); 
 148             SetPortPenMode( (CGrafPtr
) grafPtr
, savedPenMode 
); 
 156 extern "C" void MacDrawStringCell(Rect 
*cellRect
, Cell lCell
, ListHandle theList
, long refCon
) ; 
 158 static ListDefUPP macCheckListDefUPP 
= NULL 
; 
 160 // ---------------------------------------------------------------------------- 
 162 // ---------------------------------------------------------------------------- 
 164 void wxCheckListBox::Init() 
 168 bool wxCheckListBox::Create(wxWindow 
*parent
, 
 173                             const wxString choices
[], 
 175                             const wxValidator
& validator
, 
 176                             const wxString 
&name
) 
 178     m_noItems 
= 0 ; // this will be increased by our append command 
 184     MacPreControlCreate( parent 
, id 
,  "" , pos 
, size 
,style
, validator 
, name 
, &bounds 
, title 
) ; 
 187     listDef
.defType 
= kListDefUserProcType
; 
 188     if ( macCheckListDefUPP 
== NULL 
) 
 190       macCheckListDefUPP 
= NewListDefUPP( wxMacCheckListDefinition 
);  
 192         listDef
.u
.userProc 
= macCheckListDefUPP 
; 
 198     CreateListBoxControl( MAC_WXHWND(parent
->MacGetRootWindow()), &bounds
, false, 0, 1, false, true, 
 199                           14, 14, false, &listDef
, (ControlRef 
*)&m_macControl 
); 
 201     GetControlData( (ControlHandle
) m_macControl
, kControlNoPart
, kControlListBoxListHandleTag
, 
 202                    sizeof(ListHandle
), (Ptr
) &m_macList
, &asize
); 
 204     SetControlReference( (ControlHandle
) m_macControl
, (long) this); 
 205     SetControlVisibility( (ControlHandle
) m_macControl
, false, false); 
 211     wxStAppResource resload 
; 
 212     m_macControl 
= ::NewControl( MAC_WXHWND(parent
->MacGetRootWindow()) , &bounds 
, title 
, false , 
 213                   kwxMacListWithVerticalScrollbar 
, 0 , 0,  
 214                   kControlListBoxProc 
, (long) this ) ; 
 215     ::GetControlData( (ControlHandle
) m_macControl 
, kControlNoPart 
, kControlListBoxListHandleTag 
, 
 216                sizeof( ListHandle 
) , (char*) &m_macList  
, &result 
) ; 
 218     HLock( (Handle
) m_macList 
) ; 
 220     ldef 
= (ldefHandle
) NewHandle( sizeof(ldefRec
) ) ; 
 221     if (  (**(ListHandle
)m_macList
).listDefProc 
!= NULL 
) 
 223       (**ldef
).instruction 
= 0x4EF9;  /* JMP instruction */ 
 224       (**ldef
).function 
= (void(*)()) listDef
.u
.userProc
; 
 225       (**(ListHandle
)m_macList
).listDefProc 
= (Handle
) ldef 
; 
 228     Point pt 
= (**(ListHandle
)m_macList
).cellSize 
; 
 230     LCellSize( pt 
, (ListHandle
)m_macList 
) ; 
 231     LAddColumn( 1 , 0 , (ListHandle
)m_macList 
) ; 
 233     OptionBits  options 
= 0; 
 234     if ( style 
& wxLB_MULTIPLE 
) 
 236         options 
+= lNoExtend 
; 
 238     else if ( style 
& wxLB_EXTENDED 
) 
 240         options 
+= lExtendDrag 
; 
 246     SetListSelectionFlags((ListHandle
)m_macList
, options
); 
 248     MacPostControlCreate() ; 
 250     for ( int i 
= 0 ; i 
< n 
; i
++ ) 
 252         Append( choices
[i
] ) ; 
 255     LSetDrawingMode( true , (ListHandle
) m_macList 
) ; 
 260 // ---------------------------------------------------------------------------- 
 261 // wxCheckListBox functions 
 262 // ---------------------------------------------------------------------------- 
 264 bool wxCheckListBox::IsChecked(size_t item
) const 
 266     wxCHECK_MSG( item 
< m_checks
.GetCount(), FALSE
, 
 267                  _T("invalid index in wxCheckListBox::IsChecked") ); 
 269     return m_checks
[item
] != 0; 
 272 void wxCheckListBox::Check(size_t item
, bool check
) 
 274     wxCHECK_RET( item 
< m_checks
.GetCount(), 
 275                  _T("invalid index in wxCheckListBox::Check") ); 
 277     // intermediate var is needed to avoid compiler warning with VC++ 
 278     bool isChecked 
= m_checks
[item
] != 0; 
 279     if ( check 
!= isChecked 
) 
 281         m_checks
[item
] = check
; 
 287 // ---------------------------------------------------------------------------- 
 288 // methods forwarded to wxListBox 
 289 // ---------------------------------------------------------------------------- 
 291 void wxCheckListBox::Delete(int n
) 
 293     wxCHECK_RET( n 
< GetCount(), _T("invalid index in wxListBox::Delete") ); 
 295     wxListBox::Delete(n
); 
 297     m_checks
.RemoveAt(n
); 
 300 int wxCheckListBox::DoAppend(const wxString
& item
) 
 302     int pos 
= wxListBox::DoAppend(item
); 
 304     // the item is initially unchecked 
 305     m_checks
.Insert(FALSE
, pos
); 
 310 void wxCheckListBox::DoInsertItems(const wxArrayString
& items
, int pos
) 
 312     wxListBox::DoInsertItems(items
, pos
); 
 314     size_t count 
= items
.GetCount(); 
 315     for ( size_t n 
= 0; n 
< count
; n
++ ) 
 317         m_checks
.Insert(FALSE
, pos 
+ n
); 
 321 void wxCheckListBox::DoSetItems(const wxArrayString
& items
, void **clientData
) 
 323     // call it first as it does DoClear() 
 324     wxListBox::DoSetItems(items
, clientData
); 
 326     size_t count 
= items
.GetCount(); 
 327     for ( size_t n 
= 0; n 
< count
; n
++ ) 
 333 void wxCheckListBox::DoClear() 
 338 BEGIN_EVENT_TABLE(wxCheckListBox
, wxListBox
) 
 339   EVT_CHAR(wxCheckListBox::OnChar
) 
 340   EVT_LEFT_DOWN(wxCheckListBox::OnLeftClick
) 
 343 // this will only work as soon as  
 345 void wxCheckListBox::OnChar(wxKeyEvent
& event
) 
 347   if ( event
.KeyCode() == WXK_SPACE 
) 
 349     int index 
= GetSelection() ; 
 352       Check(index
, !IsChecked(index
) ) ; 
 353       wxCommandEvent 
event(wxEVT_COMMAND_CHECKLISTBOX_TOGGLED
, GetId()); 
 355       event
.SetEventObject(this); 
 356       GetEventHandler()->ProcessEvent(event
); 
 363 void wxCheckListBox::OnLeftClick(wxMouseEvent
& event
) 
 365   // clicking on the item selects it, clicking on the checkmark toggles 
 366   if ( event
.GetX() <= 20 /*check width*/ ) { 
 371     GetListCellSize( (ListHandle
)m_macList 
, &pt 
) ; 
 374     GetListVisibleCells( (ListHandle
)m_macList 
, &visible 
) ; 
 375     topcell 
= visible
.top 
; 
 377     lineheight 
=  (**(ListHandle
)m_macList
).cellSize
.v 
; 
 378     topcell 
= (**(ListHandle
)m_macList
).visible
.top 
; 
 380     size_t nItem 
= ((size_t)event
.GetY()) / lineheight 
+ topcell 
; 
 382     if ( nItem 
< (size_t)m_noItems 
) 
 384       Check(nItem
, !IsChecked(nItem
) ) ; 
 385       wxCommandEvent 
event(wxEVT_COMMAND_CHECKLISTBOX_TOGGLED
, GetId()); 
 387       event
.SetEventObject(this); 
 388       GetEventHandler()->ProcessEvent(event
); 
 390     //else: it's not an error, just click outside of client zone 
 393     // implement default behaviour: clicking on the item selects it 
 398 #endif // wxUSE_CHECKLISTBOX