X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/e9576ca53db96b462ed4c0b4bdf47d64c40203e4..fdd74b41b0a94b214aab4b7b03e75b60e877bd4e:/src/mac/carbon/checklst.cpp diff --git a/src/mac/carbon/checklst.cpp b/src/mac/carbon/checklst.cpp index 2f43152c2a..bad85ae455 100644 --- a/src/mac/carbon/checklst.cpp +++ b/src/mac/carbon/checklst.cpp @@ -1,11 +1,11 @@ /////////////////////////////////////////////////////////////////////////////// // Name: checklst.cpp // Purpose: implementation of wxCheckListBox class -// Author: AUTHOR +// Author: Stefan Csomor // Modified by: -// Created: ??/??/98 +// Created: 1998-01-01 // RCS-ID: $Id$ -// Copyright: (c) AUTHOR +// Copyright: (c) Stefan Csomor // Licence: wxWindows licence /////////////////////////////////////////////////////////////////////////////// @@ -17,58 +17,385 @@ #pragma implementation "checklst.h" #endif +#include "wx/defs.h" + +#if wxUSE_CHECKLISTBOX + #include "wx/checklst.h" +#include "wx/arrstr.h" + +#include "wx/mac/uma.h" +#include // ============================================================================ -// implementation +// implementation of wxCheckListBox // ============================================================================ -#if !USE_SHARED_LIBRARY - IMPLEMENT_DYNAMIC_CLASS(wxCheckListBox, wxListBox) +IMPLEMENT_DYNAMIC_CLASS(wxCheckListBox, wxListBox) + +BEGIN_EVENT_TABLE(wxCheckListBox, wxListBox) +END_EVENT_TABLE() + +const short kTextColumnId = 1024 ; +const short kCheckboxColumnId = 1025 ; + +// new databrowser based version + +// Listbox item +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 ) + { + wxCheckListBox* list = wxDynamicCast( (wxObject*) ref , wxCheckListBox ) ; + for ( size_t i = 0 ; i < list->m_idArray.GetCount() ; ++i ) + if ( list->m_idArray[i] == (long) itemID ) + { + 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 synch with event + // list->GetEventHandler()->ProcessEvent(event) ; + } + + break ; + } + } +} + + +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 ) + { + wxCheckListBox* list = wxDynamicCast( (wxObject*) ref , wxCheckListBox ) ; + for ( size_t i = 0 ; i < list->m_idArray.GetCount() ; ++i ) + if ( list->m_idArray[i] == (long) itemID ) + { + wxMacCFStringHolder cf( list->GetString(i) , list->GetFont().GetEncoding() ) ; + verify_noerr( ::SetDataBrowserItemDataText( itemData , cf ) ) ; + err = noErr ; + break ; + } + } + } + break; + case kCheckboxColumnId : + { + long ref = GetControlReference( browser ) ; + if ( ref ) + { + wxCheckListBox* list = wxDynamicCast( (wxObject*) ref , wxCheckListBox ) ; + for ( size_t i = 0 ; i < list->m_idArray.GetCount() ; ++i ) + if ( list->m_idArray[i] == (long) itemID ) + { + verify_noerr( ::SetDataBrowserItemDataButtonValue( itemData , list->IsChecked( i ) ? kThemeButtonOn : kThemeButtonOff ) ) ; + err = noErr ; + break ; + } + } + } + break ; + case kDataBrowserItemIsEditableProperty: + { + err = ::SetDataBrowserItemDataBooleanValue(itemData, true); + } + break; + + default: + break; + } + } + else + { + switch( property ) + { + case kCheckboxColumnId : + { + long ref = GetControlReference( browser ) ; + if ( ref ) + { + wxCheckListBox* list = wxDynamicCast( (wxObject*) ref , wxCheckListBox ) ; + for ( size_t i = 0 ; i < list->m_idArray.GetCount() ; ++i ) + if ( list->m_idArray[i] == (long) itemID ) + { + // 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 ; + } + } + + } + 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), + _T("only one of listbox selection modes can be specified") ); + + if ( !wxListBoxBase::Create(parent, id, pos, size, style & ~(wxHSCROLL|wxVSCROLL), validator, name) ) + return false; + + m_noItems = 0 ; // this will be increased by our append command + m_selected = 0; + m_nextId = 1 ; + + + Rect bounds = wxMacGetBoundsForControl( this , pos , size ) ; + + m_peer = new wxMacControl() ; + verify_noerr( ::CreateDataBrowserControl( MAC_WXHWND(parent->MacGetTopLevelWindowRef()), &bounds, kDataBrowserListView , *m_peer ) ); + + + DataBrowserSelectionFlags options = kDataBrowserDragSelect ; + if ( style & wxLB_MULTIPLE ) + { + options += kDataBrowserAlwaysExtendSelection + kDataBrowserCmdTogglesSelection ; + } + else if ( style & wxLB_EXTENDED ) + { + // default behaviour + } + else + { + options += kDataBrowserSelectOnlyOne ; + } + verify_noerr(SetDataBrowserSelectionFlags (*m_peer, options ) ); + + DataBrowserListViewColumnDesc columnDesc ; + columnDesc.headerBtnDesc.titleOffset = 0; + columnDesc.headerBtnDesc.version = kDataBrowserListViewLatestHeaderDesc; + + columnDesc.headerBtnDesc.btnFontStyle.flags = + kControlUseFontMask | kControlUseJustMask; + + columnDesc.headerBtnDesc.btnContentInfo.contentType = kControlNoContent; + columnDesc.headerBtnDesc.btnFontStyle.just = teFlushDefault; + columnDesc.headerBtnDesc.btnFontStyle.font = kControlFontViewSystemFont; + columnDesc.headerBtnDesc.btnFontStyle.style = normal; + columnDesc.headerBtnDesc.titleString = NULL ; // CFSTR( "" ); + + // check column + + columnDesc.headerBtnDesc.minimumWidth = 30 ; + columnDesc.headerBtnDesc.maximumWidth = 30; + + columnDesc.propertyDesc.propertyID = kCheckboxColumnId; + columnDesc.propertyDesc.propertyType = kDataBrowserCheckboxType; + columnDesc.propertyDesc.propertyFlags = kDataBrowserPropertyIsMutable | kDataBrowserTableViewSelectionColumn | + kDataBrowserDefaultPropertyFlags; + verify_noerr(::AddDataBrowserListViewColumn(*m_peer, &columnDesc, kDataBrowserListViewAppendColumn) ) ; + + // text column + + columnDesc.headerBtnDesc.minimumWidth = 0; + columnDesc.headerBtnDesc.maximumWidth = 10000; + + columnDesc.propertyDesc.propertyID = kTextColumnId; + columnDesc.propertyDesc.propertyType = kDataBrowserTextType; + columnDesc.propertyDesc.propertyFlags = kDataBrowserTableViewSelectionColumn +#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2 + | kDataBrowserListViewTypeSelectColumn +#endif + ; + + + verify_noerr(::AddDataBrowserListViewColumn(*m_peer, &columnDesc, kDataBrowserListViewAppendColumn) ) ; + + verify_noerr(::AutoSizeDataBrowserListViewColumns( *m_peer ) ) ; + verify_noerr(::SetDataBrowserHasScrollBars( *m_peer , false , true ) ) ; + verify_noerr(::SetDataBrowserTableViewHiliteStyle( *m_peer, kDataBrowserTableViewFillHilite ) ) ; + verify_noerr(::SetDataBrowserListViewHeaderBtnHeight( *m_peer , 0 ) ) ; + + DataBrowserCallbacks callbacks ; + callbacks.version = kDataBrowserLatestCallbacks; + InitDataBrowserCallbacks(&callbacks); + callbacks.u.v1.itemDataCallback = NewDataBrowserItemDataUPP(ListBoxGetSetItemData); + callbacks.u.v1.itemNotificationCallback = +#if TARGET_API_MAC_OSX + (DataBrowserItemNotificationUPP) NewDataBrowserItemNotificationWithItemUPP(DataBrowserItemNotificationProc) ; +#else + NewDataBrowserItemNotificationUPP(DataBrowserItemNotificationProc) ; +#endif + SetDataBrowserCallbacks(*m_peer, &callbacks); + + MacPostControlCreate(pos,size) ; + + for ( int i = 0 ; i < n ; i++ ) + { + Append( choices[i] ) ; + } + + SetBestSize(size); // Needed because it is a wxControlWithItems + + return TRUE; +} // ---------------------------------------------------------------------------- -// implementation of wxCheckListBox class +// wxCheckListBox functions // ---------------------------------------------------------------------------- -// define event table -// ------------------ -BEGIN_EVENT_TABLE(wxCheckListBox, wxListBox) -END_EVENT_TABLE() +bool wxCheckListBox::IsChecked(size_t item) const +{ + wxCHECK_MSG( item < m_checks.GetCount(), FALSE, + _T("invalid index in wxCheckListBox::IsChecked") ); -// control creation -// ---------------- + return m_checks[item] != 0; +} -// def ctor: use Create() to really create the control -wxCheckListBox::wxCheckListBox() : wxListBox() +void wxCheckListBox::Check(size_t item, bool check) { + wxCHECK_RET( item < m_checks.GetCount(), + _T("invalid index in wxCheckListBox::Check") ); + + // intermediate var is needed to avoid compiler warning with VC++ + bool isChecked = m_checks[item] != 0; + if ( check != isChecked ) + { + m_checks[item] = check; + UInt32 id = m_idArray[item] ; + verify_noerr( ::UpdateDataBrowserItems( *m_peer , kDataBrowserNoItem , 1 , &id , kDataBrowserItemNoProperty , kDataBrowserItemNoProperty ) ) ; + } } -// ctor which creates the associated control -wxCheckListBox::wxCheckListBox(wxWindow *parent, wxWindowID id, - const wxPoint& pos, const wxSize& size, - int nStrings, const wxString choices[], - long style, const wxValidator& val, - const wxString& name) - : wxListBox() +// ---------------------------------------------------------------------------- +// methods forwarded to wxCheckListBox +// ---------------------------------------------------------------------------- + +void wxCheckListBox::Delete(int n) { - // TODO: you'll probably need a separate Create instead of using - // the wxListBox one as here. - Create(parent, id, pos, size, nStrings, choices, style|wxLB_OWNERDRAW, val, name); + wxCHECK_RET( n < GetCount(), _T("invalid index in wxCheckListBox::Delete") ); + + wxListBox::Delete(n); + + m_checks.RemoveAt(n); } -// check items -// ----------- +int wxCheckListBox::DoAppend(const wxString& item) +{ + int pos = wxListBox::DoAppend(item); + + // the item is initially unchecked + m_checks.Insert(FALSE, pos); + + return pos; +} -bool wxCheckListBox::IsChecked(size_t uiIndex) const +void wxCheckListBox::DoInsertItems(const wxArrayString& items, int pos) { - // TODO - return FALSE; + wxListBox::DoInsertItems(items, pos); + + size_t count = items.GetCount(); + for ( size_t n = 0; n < count; n++ ) + { + m_checks.Insert(FALSE, pos + n); + } } -void wxCheckListBox::Check(size_t uiIndex, bool bCheck) +void wxCheckListBox::DoSetItems(const wxArrayString& items, void **clientData) { - // TODO + // call it first as it does DoClear() + wxListBox::DoSetItems(items, clientData); + + size_t count = items.GetCount(); + for ( size_t n = 0; n < count; n++ ) + { + m_checks.Add(FALSE); + } } +void wxCheckListBox::DoClear() +{ + m_checks.Empty(); +} +#endif // wxUSE_CHECKLISTBOX