1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/mac/carbon/checklst.cpp
3 // Purpose: implementation of wxCheckListBox class
4 // Author: Stefan Csomor
8 // Copyright: (c) Stefan Csomor
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
12 // new DataBrowser-based version
15 #include "wx/wxprec.h"
17 #if wxUSE_CHECKLISTBOX
19 #include "wx/checklst.h"
20 #include "wx/arrstr.h"
22 #include "wx/mac/uma.h"
25 #include <Appearance.h>
28 IMPLEMENT_DYNAMIC_CLASS(wxCheckListBox
, wxListBox
)
30 BEGIN_EVENT_TABLE(wxCheckListBox
, wxListBox
)
33 const short kTextColumnId
= 1024;
34 const short kCheckboxColumnId
= 1025;
37 void wxCheckListBox::Init()
41 bool wxCheckListBox::Create(
46 const wxArrayString
& choices
,
48 const wxValidator
& validator
,
49 const wxString
&name
)
51 wxCArrayString
chs( choices
);
53 return Create( parent
, id
, pos
, size
, chs
.GetCount(), chs
.GetStrings(), style
, validator
, name
);
56 #if TARGET_API_MAC_OSX
57 static pascal void DataBrowserItemNotificationProc(
59 DataBrowserItemID itemID
,
60 DataBrowserItemNotification message
,
61 DataBrowserItemDataRef itemData
)
63 static pascal void DataBrowserItemNotificationProc(
65 DataBrowserItemID itemID
,
66 DataBrowserItemNotification message
)
69 long ref
= GetControlReference( browser
);
72 wxCheckListBox
* list
= wxDynamicCast( (wxObject
*)ref
, wxCheckListBox
);
74 if ((i
>= 0) && (i
< (int)list
->GetCount()))
77 wxCommandEvent
event( wxEVT_COMMAND_LISTBOX_SELECTED
, list
->GetId() );
80 case kDataBrowserItemDeselected
:
81 if ( list
->HasMultipleSelection() )
85 case kDataBrowserItemSelected
:
89 case kDataBrowserItemDoubleClicked
:
90 event
.SetEventType( wxEVT_COMMAND_LISTBOX_DOUBLECLICKED
);
100 event
.SetEventObject( list
);
101 if ( list
->HasClientObjectData() )
102 event
.SetClientObject( list
->GetClientObject( i
) );
103 else if ( list
->HasClientUntypedData() )
104 event
.SetClientData( list
->GetClientData( i
) );
105 event
.SetString( list
->GetString( i
) );
107 event
.SetExtraLong( list
->HasMultipleSelection() ? message
== kDataBrowserItemSelected
: true );
108 wxPostEvent( list
->GetEventHandler(), event
);
110 // direct notification is not always having the listbox GetSelection() having in sync with event
111 // list->GetEventHandler()->ProcessEvent( event );
117 static pascal OSStatus
ListBoxGetSetItemData(
119 DataBrowserItemID itemID
,
120 DataBrowserPropertyID property
,
121 DataBrowserItemDataRef itemData
,
122 Boolean changeValue
)
124 OSStatus err
= errDataBrowserPropertyNotSupported
;
132 long ref
= GetControlReference( browser
);
135 wxCheckListBox
* list
= wxDynamicCast( (wxObject
*) ref
, wxCheckListBox
);
137 if ((i
>= 0) && (i
< (int)list
->GetCount()))
139 wxMacCFStringHolder
cf( list
->GetString( i
), list
->GetFont().GetEncoding() );
140 verify_noerr( ::SetDataBrowserItemDataText( itemData
, cf
) );
147 case kCheckboxColumnId
:
149 long ref
= GetControlReference( browser
);
152 wxCheckListBox
* list
= wxDynamicCast( (wxObject
*)ref
, wxCheckListBox
);
154 if ((i
>= 0) && (i
< (int)list
->GetCount()))
156 verify_noerr( ::SetDataBrowserItemDataButtonValue( itemData
, list
->IsChecked( i
) ? kThemeButtonOn
: kThemeButtonOff
) );
163 case kDataBrowserItemIsEditableProperty
:
165 err
= ::SetDataBrowserItemDataBooleanValue( itemData
, true );
177 case kCheckboxColumnId
:
179 long ref
= GetControlReference( browser
);
182 wxCheckListBox
* list
= wxDynamicCast( (wxObject
*) ref
, wxCheckListBox
);
184 if ((i
>= 0) && (i
< (int)list
->GetCount()))
186 // we have to change this behind the back, since Check() would be triggering another update round
187 bool newVal
= !list
->IsChecked( i
);
188 verify_noerr( ::SetDataBrowserItemDataButtonValue( itemData
, newVal
? kThemeButtonOn
: kThemeButtonOff
) );
190 list
->m_checks
[i
] = newVal
;
192 wxCommandEvent
event(wxEVT_COMMAND_CHECKLISTBOX_TOGGLED
, list
->GetId());
194 event
.SetEventObject( list
);
195 list
->GetEventHandler()->ProcessEvent( event
);
209 bool wxCheckListBox::Create(
215 const wxString choices
[],
217 const wxValidator
& validator
,
218 const wxString
& name
)
220 m_macIsUserPane
= false;
222 wxASSERT_MSG( !(style
& wxLB_MULTIPLE
) || !(style
& wxLB_EXTENDED
),
223 wxT("only one of listbox selection modes can be specified") );
225 if ( !wxListBoxBase::Create( parent
, id
, pos
, size
, style
& ~(wxHSCROLL
| wxVSCROLL
), validator
, name
) )
228 // this will be increased by our Append command
232 Rect bounds
= wxMacGetBoundsForControl( this, pos
, size
);
234 m_peer
= new wxMacControl( this );
235 OSStatus err
= ::CreateDataBrowserControl(
236 MAC_WXHWND(parent
->MacGetTopLevelWindowRef()),
237 &bounds
, kDataBrowserListView
, m_peer
->GetControlRefAddr() );
240 DataBrowserSelectionFlags options
= kDataBrowserDragSelect
;
241 if ( style
& wxLB_MULTIPLE
)
243 options
|= kDataBrowserAlwaysExtendSelection
| kDataBrowserCmdTogglesSelection
;
245 else if ( style
& wxLB_EXTENDED
)
251 options
|= kDataBrowserSelectOnlyOne
;
254 err
= m_peer
->SetSelectionFlags( options
);
257 DataBrowserListViewColumnDesc columnDesc
;
258 columnDesc
.headerBtnDesc
.titleOffset
= 0;
259 columnDesc
.headerBtnDesc
.version
= kDataBrowserListViewLatestHeaderDesc
;
261 columnDesc
.headerBtnDesc
.btnFontStyle
.flags
=
262 kControlUseFontMask
| kControlUseJustMask
;
264 columnDesc
.headerBtnDesc
.btnContentInfo
.contentType
= kControlNoContent
;
265 columnDesc
.headerBtnDesc
.btnFontStyle
.just
= teFlushDefault
;
266 columnDesc
.headerBtnDesc
.btnFontStyle
.font
= kControlFontViewSystemFont
;
267 columnDesc
.headerBtnDesc
.btnFontStyle
.style
= normal
;
268 columnDesc
.headerBtnDesc
.titleString
= NULL
; // CFSTR( "" );
272 columnDesc
.headerBtnDesc
.minimumWidth
= 30;
273 columnDesc
.headerBtnDesc
.maximumWidth
= 30;
275 columnDesc
.propertyDesc
.propertyID
= kCheckboxColumnId
;
276 columnDesc
.propertyDesc
.propertyType
= kDataBrowserCheckboxType
;
277 columnDesc
.propertyDesc
.propertyFlags
=
278 kDataBrowserPropertyIsMutable
279 | kDataBrowserTableViewSelectionColumn
280 | kDataBrowserDefaultPropertyFlags
;
281 err
= m_peer
->AddListViewColumn( &columnDesc
, kDataBrowserListViewAppendColumn
);
286 columnDesc
.headerBtnDesc
.minimumWidth
= 0;
287 columnDesc
.headerBtnDesc
.maximumWidth
= 10000;
289 columnDesc
.propertyDesc
.propertyID
= kTextColumnId
;
290 columnDesc
.propertyDesc
.propertyType
= kDataBrowserTextType
;
291 columnDesc
.propertyDesc
.propertyFlags
= kDataBrowserTableViewSelectionColumn
292 #if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2
293 | kDataBrowserListViewTypeSelectColumn
297 verify_noerr( m_peer
->AddListViewColumn( &columnDesc
, kDataBrowserListViewAppendColumn
) );
299 verify_noerr( m_peer
->AutoSizeListViewColumns() );
300 verify_noerr( m_peer
->SetHasScrollBars( false, true ) );
301 verify_noerr( m_peer
->SetTableViewHiliteStyle( kDataBrowserTableViewFillHilite
) );
302 verify_noerr( m_peer
->SetListViewHeaderBtnHeight( 0 ) );
304 DataBrowserCallbacks callbacks
;
305 callbacks
.version
= kDataBrowserLatestCallbacks
;
306 InitDataBrowserCallbacks( &callbacks
);
307 callbacks
.u
.v1
.itemDataCallback
= NewDataBrowserItemDataUPP( &ListBoxGetSetItemData
);
308 callbacks
.u
.v1
.itemNotificationCallback
=
309 #if TARGET_API_MAC_OSX
310 (DataBrowserItemNotificationUPP
) NewDataBrowserItemNotificationWithItemUPP( &DataBrowserItemNotificationProc
);
312 NewDataBrowserItemNotificationUPP( &DataBrowserItemNotificationProc
);
314 m_peer
->SetCallbacks( &callbacks
);
317 // shouldn't be necessary anymore under 10.2
318 m_peer
->SetData( kControlNoPart
, kControlDataBrowserIncludesFrameAndFocusTag
, (Boolean
)false );
319 m_peer
->SetNeedsFocusRect( true );
322 MacPostControlCreate( pos
, size
);
324 for ( int i
= 0; i
< n
; i
++ )
326 Append( choices
[i
] );
329 // Needed because it is a wxControlWithItems
335 // ----------------------------------------------------------------------------
336 // wxCheckListBox functions
337 // ----------------------------------------------------------------------------
339 bool wxCheckListBox::IsChecked(size_t item
) const
341 wxCHECK_MSG( item
< m_checks
.GetCount(), false,
342 wxT("invalid index in wxCheckListBox::IsChecked") );
344 return m_checks
[item
] != 0;
347 void wxCheckListBox::Check(size_t item
, bool check
)
349 wxCHECK_RET( item
< m_checks
.GetCount(),
350 wxT("invalid index in wxCheckListBox::Check") );
352 bool isChecked
= m_checks
[item
] != 0;
353 if ( check
!= isChecked
)
355 m_checks
[item
] = check
;
356 UInt32 id
= item
+ 1;
357 OSStatus err
= m_peer
->UpdateItems(
358 kDataBrowserNoItem
, 1, &id
,
359 kDataBrowserItemNoProperty
, kDataBrowserItemNoProperty
);
364 // ----------------------------------------------------------------------------
365 // methods forwarded to wxCheckListBox
366 // ----------------------------------------------------------------------------
368 void wxCheckListBox::Delete(int n
)
370 wxCHECK_RET( (size_t)n
< GetCount(), wxT("invalid index in wxCheckListBox::Delete") );
372 wxListBox::Delete( n
);
373 m_checks
.RemoveAt( n
);
376 int wxCheckListBox::DoAppend(const wxString
& item
)
378 int pos
= wxListBox::DoAppend( item
);
380 // the item is initially unchecked
381 m_checks
.Insert( false, pos
);
386 void wxCheckListBox::DoInsertItems(const wxArrayString
& items
, int pos
)
388 wxListBox::DoInsertItems( items
, pos
);
390 size_t count
= items
.GetCount();
391 for ( size_t n
= 0; n
< count
; n
++ )
393 m_checks
.Insert( false, pos
+ n
);
397 void wxCheckListBox::DoSetItems(const wxArrayString
& items
, void **clientData
)
399 // call it first as it does DoClear()
400 wxListBox::DoSetItems( items
, clientData
);
402 size_t count
= items
.GetCount();
403 for ( size_t n
= 0; n
< count
; n
++ )
405 m_checks
.Add( false );
409 void wxCheckListBox::DoClear()
414 #endif // wxUSE_CHECKLISTBOX