+#include "wx/mac/uma.h"
+
+#ifndef __DARWIN__
+#include <Appearance.h>
+#endif
+
+IMPLEMENT_DYNAMIC_CLASS(wxCheckListBox, wxListBox)
+
+BEGIN_EVENT_TABLE(wxCheckListBox, wxListBox)
+END_EVENT_TABLE()
+
+const short kTextColumnId = 1024;
+const short kCheckboxColumnId = 1025;
+
+
+void wxCheckListBox::Init()
+{
+}
+
+bool wxCheckListBox::Create(
+ wxWindow *parent,
+ wxWindowID id,
+ const wxPoint &pos,
+ const wxSize &size,
+ const wxArrayString& choices,
+ long style,
+ const wxValidator& validator,
+ const wxString &name )
+{
+ wxCArrayString chs( choices );
+
+ return Create( parent, id, pos, size, chs.GetCount(), chs.GetStrings(), style, validator, name );
+}
+
+#if TARGET_API_MAC_OSX
+static pascal void DataBrowserItemNotificationProc(
+ ControlRef browser,
+ DataBrowserItemID itemID,
+ DataBrowserItemNotification message,
+ DataBrowserItemDataRef itemData )
+#else
+static pascal void DataBrowserItemNotificationProc(
+ ControlRef browser,
+ DataBrowserItemID itemID,
+ DataBrowserItemNotification message )
+#endif
+{
+ long ref = GetControlReference( browser );
+ if (ref != 0)
+ {
+ wxCheckListBox* list = wxDynamicCast( (wxObject*)ref, wxCheckListBox );
+ int i = itemID - 1;
+ if ((i >= 0) && (i < (int)list->GetCount()))
+ {
+ bool trigger = false;
+ wxCommandEvent event( wxEVT_COMMAND_LISTBOX_SELECTED, list->GetId() );
+ switch ( message )
+ {
+ case kDataBrowserItemDeselected:
+ if ( list->HasMultipleSelection() )
+ trigger = true;
+ break;
+
+ case kDataBrowserItemSelected:
+ trigger = true;
+ break;
+
+ case kDataBrowserItemDoubleClicked:
+ event.SetEventType( wxEVT_COMMAND_LISTBOX_DOUBLECLICKED );
+ trigger = true;
+ break;
+
+ default:
+ break;
+ }
+
+ if ( trigger )
+ {
+ event.SetEventObject( list );
+ if ( list->HasClientObjectData() )
+ event.SetClientObject( list->GetClientObject( i ) );
+ else if ( list->HasClientUntypedData() )
+ event.SetClientData( list->GetClientData( i ) );
+ event.SetString( list->GetString( i ) );
+ event.SetInt( i );
+ event.SetExtraLong( list->HasMultipleSelection() ? message == kDataBrowserItemSelected : true );
+ wxPostEvent( list->GetEventHandler(), event );
+
+ // direct notification is not always having the listbox GetSelection() having in sync with event
+ // list->GetEventHandler()->ProcessEvent( event );
+ }
+ }
+ }
+}
+
+static pascal OSStatus ListBoxGetSetItemData(
+ ControlRef browser,
+ DataBrowserItemID itemID,
+ DataBrowserPropertyID property,
+ DataBrowserItemDataRef itemData,
+ Boolean changeValue )
+{
+ OSStatus err = errDataBrowserPropertyNotSupported;
+
+ if ( !changeValue )
+ {
+ switch (property)
+ {
+ case kTextColumnId:
+ {
+ long ref = GetControlReference( browser );
+ if (ref != 0)
+ {
+ wxCheckListBox* list = wxDynamicCast( (wxObject*) ref, wxCheckListBox );
+ int i = itemID - 1;
+ if ((i >= 0) && (i < (int)list->GetCount()))
+ {
+ wxMacCFStringHolder cf( list->GetString( i ), list->GetFont().GetEncoding() );
+ verify_noerr( ::SetDataBrowserItemDataText( itemData, cf ) );
+ err = noErr;
+ }
+ }
+ }
+ break;
+
+ case kCheckboxColumnId:
+ {
+ long ref = GetControlReference( browser );
+ if (ref != 0)
+ {
+ wxCheckListBox* list = wxDynamicCast( (wxObject*)ref, wxCheckListBox );
+ int i = itemID - 1;
+ if ((i >= 0) && (i < (int)list->GetCount()))
+ {
+ verify_noerr( ::SetDataBrowserItemDataButtonValue( itemData, list->IsChecked( i ) ? kThemeButtonOn : kThemeButtonOff ) );
+ err = noErr;
+ }
+ }
+ }
+ break;
+
+ case kDataBrowserItemIsEditableProperty:
+ {
+ err = ::SetDataBrowserItemDataBooleanValue( itemData, true );
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ else
+ {
+ switch ( property )
+ {
+ case kCheckboxColumnId:
+ {
+ long ref = GetControlReference( browser );
+ if (ref != 0)
+ {
+ wxCheckListBox* list = wxDynamicCast( (wxObject*) ref, wxCheckListBox );
+ int i = itemID - 1;
+ if ((i >= 0) && (i < (int)list->GetCount()))
+ {
+ // we have to change this behind the back, since Check() would be triggering another update round
+ bool newVal = !list->IsChecked( i );
+ verify_noerr( ::SetDataBrowserItemDataButtonValue( itemData, newVal ? kThemeButtonOn : kThemeButtonOff ) );
+ err = noErr;
+ list->m_checks[i] = newVal;
+
+ wxCommandEvent event(wxEVT_COMMAND_CHECKLISTBOX_TOGGLED, list->GetId());
+ event.SetInt( i );
+ event.SetEventObject( list );
+ list->GetEventHandler()->ProcessEvent( event );
+ }
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return err;
+}
+
+bool wxCheckListBox::Create(
+ wxWindow *parent,
+ wxWindowID id,
+ const wxPoint& pos,
+ const wxSize& size,
+ int n,
+ const wxString choices[],
+ long style,
+ const wxValidator& validator,
+ const wxString& name )
+{
+ m_macIsUserPane = false;
+
+ wxASSERT_MSG( !(style & wxLB_MULTIPLE) || !(style & wxLB_EXTENDED),
+ wxT("only one of listbox selection modes can be specified") );
+
+ if ( !wxListBoxBase::Create( parent, id, pos, size, style & ~(wxHSCROLL | wxVSCROLL), validator, name ) )
+ return false;