From 7eb0acefc26f0e728411739b66672e6fd090463e Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Thu, 1 Nov 2012 17:15:28 +0000 Subject: [PATCH] Refactor and simplify wxChoice::DoGetBestSize(). Use wxTextMeasure instead of duplicating its code and also reuse the code between different ports. Closes #14706. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@72848 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/choice.h | 7 +++++++ src/common/choiccmn.cpp | 17 +++++++++++++++++ src/gtk/choice.cpp | 32 +++++--------------------------- src/msw/choice.cpp | 30 +++++++----------------------- src/osx/choice_osx.cpp | 36 ++++++------------------------------ 5 files changed, 42 insertions(+), 80 deletions(-) diff --git a/include/wx/choice.h b/include/wx/choice.h index 46f27b9d8a..369dbb517a 100644 --- a/include/wx/choice.h +++ b/include/wx/choice.h @@ -58,6 +58,13 @@ public: // override wxItemContainer::IsSorted virtual bool IsSorted() const { return HasFlag(wxCB_SORT); } +protected: + // The generic implementation doesn't determine the height correctly and + // doesn't account for the width of the arrow but does take into account + // the string widths, so the derived classes should override it and set the + // height and add the arrow width to the size returned by this version. + virtual wxSize DoGetBestSize() const; + private: wxDECLARE_NO_COPY_CLASS(wxChoiceBase); }; diff --git a/src/common/choiccmn.cpp b/src/common/choiccmn.cpp index dc925335a2..31b0a2df06 100644 --- a/src/common/choiccmn.cpp +++ b/src/common/choiccmn.cpp @@ -28,6 +28,8 @@ #include "wx/choice.h" +#include "wx/private/textmeasure.h" + #ifndef WX_PRECOMP #endif @@ -103,6 +105,21 @@ wxChoiceBase::~wxChoiceBase() // this destructor is required for Darwin } +wxSize wxChoiceBase::DoGetBestSize() const +{ + // a reasonable width for an empty choice list + wxSize best(80, -1); + + const unsigned int nItems = GetCount(); + if ( nItems > 0 ) + { + wxTextMeasure txm(this); + best.x = txm.GetLargestStringExtent(GetStrings()).x; + } + + return best; +} + // ---------------------------------------------------------------------------- // misc // ---------------------------------------------------------------------------- diff --git a/src/gtk/choice.cpp b/src/gtk/choice.cpp index dbc8579872..28832ef3e4 100644 --- a/src/gtk/choice.cpp +++ b/src/gtk/choice.cpp @@ -343,35 +343,13 @@ GdkWindow *wxChoice::GTKGetWindow(wxArrayGdkWindows& WXUNUSED(windows)) const return gtk_widget_get_window(m_widget); } -// Notice that this method shouldn't be necessary, because GTK calculates -// properly size of the combobox but for unknown reasons it doesn't work -// correctly in wx without this. wxSize wxChoice::DoGetBestSize() const { - // strangely, this returns a width of 188 pixels from GTK+ (?) - wxSize ret( wxControl::DoGetBestSize() ); - - // we know better our horizontal extent: it depends on the longest string - // in the combobox - if ( m_widget ) - { - ret.x = GetCount() > 0 ? 0 : 60; // start with something "sensible" - int width; - unsigned int count = GetCount(); - for ( unsigned int n = 0; n < count; n++ ) - { - GetTextExtent(GetString(n), &width, NULL, NULL, NULL ); - if ( width + 40 > ret.x ) // 40 for drop down arrow and space around text - ret.x = width + 40; - } - } - - // empty combobox should have some reasonable default size too - if ((GetCount() == 0) && (ret.x < 80)) - ret.x = 80; - - CacheBestSize(ret); - return ret; + // Get the height of the control from GTK+ itself, but use our own version + // to compute the width large enough to show all our strings as GTK+ + // doesn't seem to take the control contents into account. + return wxSize(wxChoiceBase::DoGetBestSize().x + 40, + wxControl::DoGetBestSize().y); } void wxChoice::DoApplyWidgetStyle(GtkRcStyle *style) diff --git a/src/msw/choice.cpp b/src/msw/choice.cpp index ea922c9e41..5ad9416212 100644 --- a/src/msw/choice.cpp +++ b/src/msw/choice.cpp @@ -587,34 +587,18 @@ void wxChoice::DoSetSize(int x, int y, wxSize wxChoice::DoGetBestSize() const { - // find the widest string - int wChoice = 0; - int hChoice; - const unsigned int nItems = GetCount(); - for ( unsigned int i = 0; i < nItems; i++ ) - { - int wLine; - GetTextExtent(GetString(i), &wLine, NULL); - if ( wLine > wChoice ) - wChoice = wLine; - } + // The base version returns the size of the largest string + wxSize best( wxChoiceBase::DoGetBestSize() ); - // give it some reasonable default value if there are no strings in the - // list - if ( wChoice == 0 ) - wChoice = 100; + // We just need to adjust it to account for the arrow width. + best.x += 5*GetCharWidth(); - // the combobox should be slightly larger than the widest string - wChoice += 5*GetCharWidth(); + // set height on our own if( HasFlag( wxCB_SIMPLE ) ) - { - hChoice = SetHeightSimpleComboBox( nItems ); - } + best.y = SetHeightSimpleComboBox(GetCount()); else - hChoice = EDIT_HEIGHT_FROM_CHAR_HEIGHT(GetCharHeight()); + best.y = EDIT_HEIGHT_FROM_CHAR_HEIGHT(GetCharHeight()); - wxSize best(wChoice, hChoice); - CacheBestSize(best); return best; } diff --git a/src/osx/choice_osx.cpp b/src/osx/choice_osx.cpp index d26812a571..2bf2c10253 100644 --- a/src/osx/choice_osx.cpp +++ b/src/osx/choice_osx.cpp @@ -259,37 +259,13 @@ bool wxChoice::OSXHandleClicked( double WXUNUSED(timestampsec) ) wxSize wxChoice::DoGetBestSize() const { - int lbWidth = GetCount() > 0 ? 20 : 100; // some defaults - wxSize baseSize = wxWindow::DoGetBestSize(); - int lbHeight = baseSize.y; - int wLine; + // We use the base window size for the height (which is wrong as it doesn't + // take the font into account -- TODO) and add some margins to the width + // computed by the base class method to account for the arrow. + const int lbHeight = wxWindow::DoGetBestSize().y; - { - wxClientDC dc(const_cast(this)); - - // Find the widest line - for(unsigned int i = 0; i < GetCount(); i++) - { - wxString str(GetString(i)); - - wxCoord width, height ; - dc.GetTextExtent( str , &width, &height); - wLine = width ; - - lbWidth = wxMax( lbWidth, wLine ) ; - } - - // Add room for the popup arrow - lbWidth += 2 * lbHeight ; - - wxCoord width, height ; - dc.GetTextExtent( wxT("X"), &width, &height); - int cx = width ; - - lbWidth += cx ; - } - - return wxSize( lbWidth, lbHeight ); + return wxSize(wxChoiceBase::DoGetBestSize().x + 2*lbHeight + GetCharWidth(), + lbHeight); } #endif // wxUSE_CHOICE -- 2.47.2