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
This commit is contained in:
Vadim Zeitlin
2012-11-01 17:15:28 +00:00
parent c236dbaed2
commit 7eb0acefc2
5 changed files with 42 additions and 80 deletions

View File

@@ -58,6 +58,13 @@ public:
// override wxItemContainer::IsSorted // override wxItemContainer::IsSorted
virtual bool IsSorted() const { return HasFlag(wxCB_SORT); } 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: private:
wxDECLARE_NO_COPY_CLASS(wxChoiceBase); wxDECLARE_NO_COPY_CLASS(wxChoiceBase);
}; };

View File

@@ -28,6 +28,8 @@
#include "wx/choice.h" #include "wx/choice.h"
#include "wx/private/textmeasure.h"
#ifndef WX_PRECOMP #ifndef WX_PRECOMP
#endif #endif
@@ -103,6 +105,21 @@ wxChoiceBase::~wxChoiceBase()
// this destructor is required for Darwin // 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 // misc
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

View File

@@ -343,35 +343,13 @@ GdkWindow *wxChoice::GTKGetWindow(wxArrayGdkWindows& WXUNUSED(windows)) const
return gtk_widget_get_window(m_widget); 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 wxSize wxChoice::DoGetBestSize() const
{ {
// strangely, this returns a width of 188 pixels from GTK+ (?) // Get the height of the control from GTK+ itself, but use our own version
wxSize ret( wxControl::DoGetBestSize() ); // to compute the width large enough to show all our strings as GTK+
// doesn't seem to take the control contents into account.
// we know better our horizontal extent: it depends on the longest string return wxSize(wxChoiceBase::DoGetBestSize().x + 40,
// in the combobox wxControl::DoGetBestSize().y);
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;
} }
void wxChoice::DoApplyWidgetStyle(GtkRcStyle *style) void wxChoice::DoApplyWidgetStyle(GtkRcStyle *style)

View File

@@ -587,34 +587,18 @@ void wxChoice::DoSetSize(int x, int y,
wxSize wxChoice::DoGetBestSize() const wxSize wxChoice::DoGetBestSize() const
{ {
// find the widest string // The base version returns the size of the largest string
int wChoice = 0; wxSize best( wxChoiceBase::DoGetBestSize() );
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;
}
// give it some reasonable default value if there are no strings in the // We just need to adjust it to account for the arrow width.
// list best.x += 5*GetCharWidth();
if ( wChoice == 0 )
wChoice = 100;
// the combobox should be slightly larger than the widest string // set height on our own
wChoice += 5*GetCharWidth();
if( HasFlag( wxCB_SIMPLE ) ) if( HasFlag( wxCB_SIMPLE ) )
{ best.y = SetHeightSimpleComboBox(GetCount());
hChoice = SetHeightSimpleComboBox( nItems );
}
else else
hChoice = EDIT_HEIGHT_FROM_CHAR_HEIGHT(GetCharHeight()); best.y = EDIT_HEIGHT_FROM_CHAR_HEIGHT(GetCharHeight());
wxSize best(wChoice, hChoice);
CacheBestSize(best);
return best; return best;
} }

View File

@@ -259,37 +259,13 @@ bool wxChoice::OSXHandleClicked( double WXUNUSED(timestampsec) )
wxSize wxChoice::DoGetBestSize() const wxSize wxChoice::DoGetBestSize() const
{ {
int lbWidth = GetCount() > 0 ? 20 : 100; // some defaults // We use the base window size for the height (which is wrong as it doesn't
wxSize baseSize = wxWindow::DoGetBestSize(); // take the font into account -- TODO) and add some margins to the width
int lbHeight = baseSize.y; // computed by the base class method to account for the arrow.
int wLine; const int lbHeight = wxWindow::DoGetBestSize().y;
{ return wxSize(wxChoiceBase::DoGetBestSize().x + 2*lbHeight + GetCharWidth(),
wxClientDC dc(const_cast<wxChoice*>(this)); lbHeight);
// 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 );
} }
#endif // wxUSE_CHOICE #endif // wxUSE_CHOICE