X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/ad9835c97c10c0d7de345e3a7a7c0fc2776eb2cb..2debe2b120a2b376a57d3f8ec24eb418a23b2710:/src/common/lboxcmn.cpp diff --git a/src/common/lboxcmn.cpp b/src/common/lboxcmn.cpp index 6350c107f2..5d7abb469f 100644 --- a/src/common/lboxcmn.cpp +++ b/src/common/lboxcmn.cpp @@ -26,12 +26,15 @@ #if wxUSE_LISTBOX +#include "wx/listbox.h" + #ifndef WX_PRECOMP #include "wx/dynarray.h" - #include "wx/listbox.h" #include "wx/arrstr.h" #endif +#include "wx/log.h" + // ============================================================================ // implementation // ============================================================================ @@ -41,48 +44,29 @@ wxListBoxBase::~wxListBoxBase() // this destructor is required for Darwin } -// ---------------------------------------------------------------------------- -// adding items -// ---------------------------------------------------------------------------- - -void wxListBoxBase::InsertItems(unsigned int nItems, const wxString *items, unsigned int pos) -{ - wxArrayString aItems; - for ( unsigned int n = 0; n < nItems; n++ ) - { - aItems.Add(items[n]); - } - - DoInsertItems(aItems, pos); -} - - -void wxListBoxBase::Set(int nItems, const wxString* items, void **clientData) -{ - wxArrayString aItems; - for ( int n = 0; n < nItems; n++ ) - { - aItems.Add(items[n]); - } - - DoSetItems(aItems, clientData); -} - // ---------------------------------------------------------------------------- // selection // ---------------------------------------------------------------------------- bool wxListBoxBase::SetStringSelection(const wxString& s, bool select) { - int sel = FindString(s); - wxCHECK_MSG( sel != wxNOT_FOUND, false, - wxT("invalid string in SetStringSelection") ); + const int sel = FindString(s); + if ( sel == wxNOT_FOUND ) + return false; SetSelection(sel, select); return true; } +void wxListBoxBase::SetSelection(int n) +{ + if ( !HasMultipleSelection() ) + DoChangeSingleSelection(n); + + DoSetSelection(n, true); +} + void wxListBoxBase::DeselectAll(int itemToLeaveSelected) { if ( HasMultipleSelection() ) @@ -108,6 +92,139 @@ void wxListBoxBase::DeselectAll(int itemToLeaveSelected) } } +void wxListBoxBase::UpdateOldSelections() +{ + // We need to remember the selection even in single-selection case on + // Windows, so that we don't send an event when the user clicks on an + // already selected item. +#ifndef __WXMSW__ + if (HasFlag(wxLB_MULTIPLE) || HasFlag(wxLB_EXTENDED)) +#endif + { + GetSelections( m_oldSelections ); + } +} + +bool wxListBoxBase::SendEvent(wxEventType evtType, int item, bool selected) +{ + wxCommandEvent event(evtType, GetId()); + event.SetEventObject(this); + + event.SetInt(item); + event.SetString(GetString(item)); + event.SetExtraLong(selected); + + if ( HasClientObjectData() ) + event.SetClientObject(GetClientObject(item)); + else if ( HasClientUntypedData() ) + event.SetClientData(GetClientData(item)); + + return HandleWindowEvent(event); +} + +bool wxListBoxBase::DoChangeSingleSelection(int item) +{ + // As we don't use m_oldSelections in single selection mode, we store the + // last item that we notified the user about in it in this case because we + // need to remember it to be able to filter out the dummy selection changes + // that we get when the user clicks on an already selected item. + if ( !m_oldSelections.empty() && *m_oldSelections.begin() == item ) + { + // Same item as the last time. + return false; + } + + m_oldSelections.clear(); + m_oldSelections.push_back(item); + + return true; +} + +bool wxListBoxBase::CalcAndSendEvent() +{ + wxArrayInt selections; + GetSelections(selections); + bool selected = true; + + if ( selections.empty() && m_oldSelections.empty() ) + { + // nothing changed, just leave + return false; + } + + const size_t countSel = selections.size(), + countSelOld = m_oldSelections.size(); + if ( countSel == countSelOld ) + { + bool changed = false; + for ( size_t idx = 0; idx < countSel; idx++ ) + { + if (selections[idx] != m_oldSelections[idx]) + { + changed = true; + break; + } + } + + // nothing changed, just leave + if ( !changed ) + return false; + } + + int item = wxNOT_FOUND; + if ( selections.empty() ) + { + selected = false; + item = m_oldSelections[0]; + } + else // we [still] have some selections + { + // Now test if any new item is selected + bool any_new_selected = false; + for ( size_t idx = 0; idx < countSel; idx++ ) + { + item = selections[idx]; + if ( m_oldSelections.Index(item) == wxNOT_FOUND ) + { + any_new_selected = true; + break; + } + } + + if ( !any_new_selected ) + { + // No new items selected, now test if any new item is deselected + bool any_new_deselected = false; + for ( size_t idx = 0; idx < countSelOld; idx++ ) + { + item = m_oldSelections[idx]; + if ( selections.Index(item) == wxNOT_FOUND ) + { + any_new_deselected = true; + break; + } + } + + if ( any_new_deselected ) + { + // indicate that this is a selection + selected = false; + } + else + { + item = wxNOT_FOUND; // this should be impossible + } + } + } + + wxASSERT_MSG( item != wxNOT_FOUND, + "Logic error in wxListBox selection event generation code" ); + + m_oldSelections = selections; + + return SendEvent(wxEVT_COMMAND_LISTBOX_SELECTED, item, selected); +} + // ---------------------------------------------------------------------------- // misc // ---------------------------------------------------------------------------- @@ -115,7 +232,7 @@ void wxListBoxBase::DeselectAll(int itemToLeaveSelected) void wxListBoxBase::Command(wxCommandEvent& event) { SetSelection(event.GetInt(), event.GetExtraLong() != 0); - (void)ProcessEvent(event); + (void)GetEventHandler()->ProcessEvent(event); } // ----------------------------------------------------------------------------