diff --git a/include/wx/msw/listbox.h b/include/wx/msw/listbox.h index 4a78e165a2..54a53b1c58 100644 --- a/include/wx/msw/listbox.h +++ b/include/wx/msw/listbox.h @@ -145,6 +145,8 @@ public: // returns true if the platform should explicitly apply a theme border virtual bool CanApplyThemeBorder() const { return false; } + virtual void OnInternalIdle(); + protected: virtual wxSize DoGetBestClientSize() const; @@ -164,8 +166,8 @@ protected: // this can't be called DoHitTest() because wxWindow already has this method virtual int DoHitTestList(const wxPoint& point) const; - bool m_updateHorizontalExtent; - virtual void OnInternalIdle(); + // free memory (common part of Clear() and dtor) + void Free(); unsigned int m_noItems; @@ -175,6 +177,14 @@ protected: #endif private: + // call this when items are added to or deleted from the listbox or an + // items text changes + void MSWOnItemsChanged(); + + // flag indicating whether the max horizontal extent should be updated, + // i.e. if we need to call SetHorizontalExtent() from OnInternalIdle() + bool m_updateHorizontalExtent; + DECLARE_DYNAMIC_CLASS_NO_COPY(wxListBox) }; diff --git a/src/msw/listbox.cpp b/src/msw/listbox.cpp index 78d76fdfab..d36f5ab109 100644 --- a/src/msw/listbox.cpp +++ b/src/msw/listbox.cpp @@ -186,7 +186,6 @@ bool wxListBox::Create(wxWindow *parent, } // now we can compute our best size correctly, so do it again - InvalidateBestSize(); SetInitialSize(size); return true; @@ -269,6 +268,22 @@ void wxListBox::OnInternalIdle() } } +void wxListBox::MSWOnItemsChanged() +{ + // we need to do two things when items change: update their max horizontal + // extent so that horizontal scrollbar could be shown or hidden as + // appropriate and also invlaidate the best size + // + // updating the max extent is slow (it's an O(N) operation) and so we defer + // it until the idle time but the best size should be invalidated + // immediately doing it in idle time is too late -- layout using incorrect + // old best size will have been already done by then + + m_updateHorizontalExtent = true; + + InvalidateBestSize(); +} + // ---------------------------------------------------------------------------- // implementation of wxListBoxBase methods // ---------------------------------------------------------------------------- @@ -297,8 +312,7 @@ void wxListBox::DoDeleteOneItem(unsigned int n) SendMessage(GetHwnd(), LB_DELETESTRING, n, 0); m_noItems--; - // SetHorizontalExtent(wxEmptyString); can be slow - m_updateHorizontalExtent = true; + MSWOnItemsChanged(); UpdateOldSelections(); } @@ -328,7 +342,7 @@ void wxListBox::DoClear() ListBox_ResetContent(GetHwnd()); m_noItems = 0; - m_updateHorizontalExtent = true; + MSWOnItemsChanged(); UpdateOldSelections(); } @@ -486,7 +500,7 @@ int wxListBox::DoInsertItems(const wxArrayStringsAdapter & items, AssignNewItemClientData(n, clientData, i, type); } - m_updateHorizontalExtent = true; + MSWOnItemsChanged(); UpdateOldSelections(); @@ -537,7 +551,7 @@ void wxListBox::SetString(unsigned int n, const wxString& s) if ( wasSelected ) Select(n); - m_updateHorizontalExtent = true; + MSWOnItemsChanged(); } unsigned int wxListBox::GetCount() const @@ -551,9 +565,6 @@ unsigned int wxListBox::GetCount() const void wxListBox::SetHorizontalExtent(const wxString& s) { - // in any case, our best size could have changed - InvalidateBestSize(); - // the rest is only necessary if we want a horizontal scrollbar if ( !HasFlag(wxHSCROLL) ) return;