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
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);
};

View File

@ -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
// ----------------------------------------------------------------------------

View File

@ -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)

View File

@ -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;
}

View File

@ -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<wxChoice*>(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