X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/a9711a4deb97504db860a136df11077fbc56eeee..8fdbcf4de8eeff67ccfaf3deec833d203f112629:/src/common/ctrlsub.cpp diff --git a/src/common/ctrlsub.cpp b/src/common/ctrlsub.cpp index 93de1562da..7f35cfa947 100644 --- a/src/common/ctrlsub.cpp +++ b/src/common/ctrlsub.cpp @@ -1,11 +1,11 @@ /////////////////////////////////////////////////////////////////////////////// -// Name: common/ctrlsub.cpp +// Name: src/common/ctrlsub.cpp // Purpose: wxItemContainer implementation // Author: Vadim Zeitlin // Modified by: // Created: 22.10.99 // RCS-ID: $Id$ -// Copyright: (c) wxWindows team +// Copyright: (c) wxWidgets team // Licence: wxWindows licence /////////////////////////////////////////////////////////////////////////////// @@ -17,10 +17,6 @@ // headers // ---------------------------------------------------------------------------- -#ifdef __GNUG__ - #pragma implementation "controlwithitems.h" -#endif - // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" @@ -35,11 +31,13 @@ #include "wx/arrstr.h" #endif +IMPLEMENT_ABSTRACT_CLASS(wxControlWithItems, wxControl) + // ============================================================================ -// implementation +// wxItemContainerImmutable implementation // ============================================================================ -wxItemContainer::~wxItemContainer() +wxItemContainerImmutable::~wxItemContainerImmutable() { // this destructor is required for Darwin } @@ -48,103 +46,265 @@ wxItemContainer::~wxItemContainer() // selection // ---------------------------------------------------------------------------- -wxString wxItemContainer::GetStringSelection() const +wxString wxItemContainerImmutable::GetStringSelection() const { wxString s; + int sel = GetSelection(); - if ( sel != -1 ) - s = GetString(sel); + if ( sel != wxNOT_FOUND ) + s = GetString((unsigned int)sel); return s; } +bool wxItemContainerImmutable::SetStringSelection(const wxString& s) +{ + const int sel = FindString(s); + if ( sel == wxNOT_FOUND ) + return false; + + SetSelection(sel); + + return true; +} + +wxArrayString wxItemContainerImmutable::GetStrings() const +{ + wxArrayString result; + + const unsigned int count = GetCount(); + result.Alloc(count); + for ( unsigned int n = 0; n < count; n++ ) + result.Add(GetString(n)); + + return result; +} + +// ============================================================================ +// wxItemContainer implementation +// ============================================================================ + +wxItemContainer::~wxItemContainer() +{ + // this destructor is required for Darwin +} + // ---------------------------------------------------------------------------- -// appending items +// deleting items // ---------------------------------------------------------------------------- -void wxItemContainer::Append(const wxArrayString& strings) +void wxItemContainer::Clear() { - size_t count = strings.GetCount(); - for ( size_t n = 0; n < count; n++ ) + if ( HasClientObjectData() ) { - Append(strings[n]); + const unsigned count = GetCount(); + for ( unsigned i = 0; i < count; ++i ) + ResetItemClientObject(i); } + + SetClientDataType(wxClientData_None); + + DoClear(); } -int wxItemContainer::Insert(const wxString& item, int pos, void *clientData) +void wxItemContainer::Delete(unsigned int pos) { - int n = DoInsert(item, pos); - if ( n != wxNOT_FOUND ) - SetClientData(n, clientData); + wxCHECK_RET( pos < GetCount(), wxT("invalid index") ); + + if ( HasClientObjectData() ) + ResetItemClientObject(pos); + + DoDeleteOneItem(pos); + + if ( IsEmpty() ) + { + SetClientDataType(wxClientData_None); + } +} + +// ---------------------------------------------------------------------------- +// +// ---------------------------------------------------------------------------- + +int wxItemContainer::DoInsertItemsInLoop(const wxArrayStringsAdapter& items, + unsigned int pos, + void **clientData, + wxClientDataType type) +{ + int n = wxNOT_FOUND; + + const unsigned int count = items.GetCount(); + for ( unsigned int i = 0; i < count; ++i ) + { + n = DoInsertOneItem(items[i], pos++); + if ( n == wxNOT_FOUND ) + break; + + AssignNewItemClientData(n, clientData, i, type); + } return n; } int -wxItemContainer::Insert(const wxString& item, int pos, wxClientData *clientData) +wxItemContainer::DoInsertOneItem(const wxString& WXUNUSED(item), + unsigned int WXUNUSED(pos)) { - int n = DoInsert(item, pos); - if ( n != wxNOT_FOUND ) - SetClientObject(n, clientData); + wxFAIL_MSG( wxT("Must be overridden if DoInsertItemsInLoop() is used") ); - return n; + return wxNOT_FOUND; } + // ---------------------------------------------------------------------------- // client data // ---------------------------------------------------------------------------- -void wxItemContainer::SetClientObject(int n, wxClientData *data) +void wxItemContainer::SetClientObject(unsigned int n, wxClientData *data) { - wxASSERT_MSG( m_clientDataItemsType != wxClientData_Void, + wxASSERT_MSG( !HasClientUntypedData(), wxT("can't have both object and void client data") ); - // when we call SetClientObject() for the first time, m_clientDataItemsType - // is still wxClientData_None and so calling DoGetItemClientObject() would - // fail (in addition to being useless) - don't do it - if ( m_clientDataItemsType == wxClientData_Object ) + wxCHECK_RET( IsValid(n), "Invalid index passed to SetClientObject()" ); + + if ( HasClientObjectData() ) { - wxClientData *clientDataOld = DoGetItemClientObject(n); + wxClientData * clientDataOld + = static_cast(DoGetItemClientData(n)); if ( clientDataOld ) delete clientDataOld; } - else // m_clientDataItemsType == wxClientData_None + else // didn't have any client data so far { // now we have object client data - m_clientDataItemsType = wxClientData_Object; + DoInitItemClientData(); + + SetClientDataType(wxClientData_Object); } - DoSetItemClientObject(n, data); + DoSetItemClientData(n, data); } -wxClientData *wxItemContainer::GetClientObject(int n) const +wxClientData *wxItemContainer::GetClientObject(unsigned int n) const { - wxASSERT_MSG( m_clientDataItemsType == wxClientData_Object, + wxCHECK_MSG( HasClientObjectData(), NULL, wxT("this window doesn't have object client data") ); - return DoGetItemClientObject(n); + wxCHECK_MSG( IsValid(n), NULL, + "Invalid index passed to GetClientObject()" ); + + return static_cast(DoGetItemClientData(n)); +} + +wxClientData *wxItemContainer::DetachClientObject(unsigned int n) +{ + wxClientData * const data = GetClientObject(n); + if ( data ) + { + // reset the pointer as we don't own it any more + DoSetItemClientData(n, NULL); + } + + return data; } -void wxItemContainer::SetClientData(int n, void *data) +void wxItemContainer::SetClientData(unsigned int n, void *data) { - wxASSERT_MSG( m_clientDataItemsType != wxClientData_Object, + if ( !HasClientData() ) + { + DoInitItemClientData(); + SetClientDataType(wxClientData_Void); + } + + wxASSERT_MSG( HasClientUntypedData(), wxT("can't have both object and void client data") ); + wxCHECK_RET( IsValid(n), "Invalid index passed to SetClientData()" ); + DoSetItemClientData(n, data); - m_clientDataItemsType = wxClientData_Void; } -void *wxItemContainer::GetClientData(int n) const +void *wxItemContainer::GetClientData(unsigned int n) const { - wxASSERT_MSG( m_clientDataItemsType == wxClientData_Void, + wxCHECK_MSG( HasClientUntypedData(), NULL, wxT("this window doesn't have void client data") ); + wxCHECK_MSG( IsValid(n), NULL, + "Invalid index passed to GetClientData()" ); + return DoGetItemClientData(n); } -wxControlWithItems::~wxControlWithItems() +void wxItemContainer::AssignNewItemClientData(unsigned int pos, + void **clientData, + unsigned int n, + wxClientDataType type) { - // this destructor is required for Darwin + switch ( type ) + { + case wxClientData_Object: + SetClientObject + ( + pos, + (reinterpret_cast(clientData))[n] + ); + break; + + case wxClientData_Void: + SetClientData(pos, clientData[n]); + break; + + default: + wxFAIL_MSG( wxT("unknown client data type") ); + // fall through + + case wxClientData_None: + // nothing to do + break; + } +} + +void wxItemContainer::ResetItemClientObject(unsigned int n) +{ + wxClientData * const data = GetClientObject(n); + if ( data ) + { + delete data; + DoSetItemClientData(n, NULL); + } +} + +// ============================================================================ +// wxControlWithItems implementation +// ============================================================================ + +void +wxControlWithItemsBase::InitCommandEventWithItems(wxCommandEvent& event, int n) +{ + InitCommandEvent(event); + + if ( n != wxNOT_FOUND ) + { + if ( HasClientObjectData() ) + event.SetClientObject(GetClientObject(n)); + else if ( HasClientUntypedData() ) + event.SetClientData(GetClientData(n)); + } +} + +void wxControlWithItemsBase::SendSelectionChangedEvent(wxEventType eventType) +{ + const int n = GetSelection(); + if ( n == wxNOT_FOUND ) + return; + + wxCommandEvent event(eventType, m_windowId); + event.SetInt(n); + event.SetEventObject(this); + event.SetString(GetStringSelection()); + InitCommandEventWithItems(event, n); + + HandleWindowEvent(event); } #endif // wxUSE_CONTROLS