diff --git a/include/wx/generic/spinctlg.h b/include/wx/generic/spinctlg.h index 8ceedf767a..f5f52a56bb 100644 --- a/include/wx/generic/spinctlg.h +++ b/include/wx/generic/spinctlg.h @@ -108,6 +108,7 @@ public: protected: // override the base class virtuals involved into geometry calculations virtual wxSize DoGetBestSize() const; + virtual wxSize DoGetSizeFromTextSize(int xlen, int ylen = -1) const; virtual void DoMoveWindow(int x, int y, int width, int height); #ifdef __WXMSW__ diff --git a/include/wx/gtk/spinctrl.h b/include/wx/gtk/spinctrl.h index 5e50fd8a80..8890030a4b 100644 --- a/include/wx/gtk/spinctrl.h +++ b/include/wx/gtk/spinctrl.h @@ -73,6 +73,7 @@ protected: void GtkEnableEvents() const; virtual wxSize DoGetBestSize() const; + virtual wxSize DoGetSizeFromTextSize(int xlen, int ylen = -1) const; virtual GdkWindow *GTKGetWindow(wxArrayGdkWindows& windows) const; // Widgets that use the style->base colour for the BG colour should diff --git a/include/wx/msw/spinctrl.h b/include/wx/msw/spinctrl.h index dd74f55649..a9163a3901 100644 --- a/include/wx/msw/spinctrl.h +++ b/include/wx/msw/spinctrl.h @@ -116,6 +116,7 @@ protected: virtual void DoGetPosition(int *x, int *y) const; virtual void DoMoveWindow(int x, int y, int width, int height); virtual wxSize DoGetBestSize() const; + virtual wxSize DoGetSizeFromTextSize(int xlen, int ylen = -1) const; virtual void DoGetSize(int *width, int *height) const; virtual void DoGetClientSize(int *x, int *y) const; #if wxUSE_TOOLTIPS diff --git a/samples/widgets/spinbtn.cpp b/samples/widgets/spinbtn.cpp index b037345b02..2c039ee279 100644 --- a/samples/widgets/spinbtn.cpp +++ b/samples/widgets/spinbtn.cpp @@ -460,6 +460,19 @@ void SpinBtnWidgetsPage::OnButtonSetMinAndMax(wxCommandEvent& WXUNUSED(event)) m_min = minNew; m_max = maxNew; + wxString smax('9', m_textMax->GetValue().length()); + wxSize + size = m_spinctrl->GetSizeFromTextSize(m_spinctrl->GetTextExtent(smax)); + + m_spinctrl->SetMinSize(size); + m_spinctrl->SetSize(size); + + smax += ".0"; + size = m_spinctrldbl->GetSizeFromTextSize( + m_spinctrldbl->GetTextExtent(smax) + ); + m_spinctrldbl->SetMinSize(size); + m_spinctrldbl->SetSize(size); m_spinbtn->SetRange(minNew, maxNew); m_spinctrl->SetRange(minNew, maxNew); diff --git a/samples/widgets/widgets.cpp b/samples/widgets/widgets.cpp index ca970c9c55..9d08c992c3 100644 --- a/samples/widgets/widgets.cpp +++ b/samples/widgets/widgets.cpp @@ -875,6 +875,10 @@ void WidgetsFrame::OnSetFont(wxCommandEvent& WXUNUSED(event)) (*it)->SetFont(m_font); (*it)->Refresh(); } + + // The best size of the widget could have changed after changing its font, + // so re-layout to show it correctly. + page->Layout(); #else wxLogMessage(wxT("Font selection dialog not available in current build.")); #endif diff --git a/src/generic/spinctlg.cpp b/src/generic/spinctlg.cpp index 0041895fd3..f5495046f2 100644 --- a/src/generic/spinctlg.cpp +++ b/src/generic/spinctlg.cpp @@ -283,10 +283,26 @@ wxWindowList wxSpinCtrlGenericBase::GetCompositeWindowParts() const wxSize wxSpinCtrlGenericBase::DoGetBestSize() const { - wxSize sizeBtn = m_spinButton->GetBestSize(), - sizeText = m_textCtrl->GetBestSize(); + return DoGetSizeFromTextSize(m_textCtrl->GetBestSize().x, -1); +} - return wxSize(sizeBtn.x + sizeText.x + MARGIN, sizeText.y); +wxSize wxSpinCtrlGenericBase::DoGetSizeFromTextSize(int xlen, int ylen) const +{ + wxSize sizeBtn = m_spinButton->GetBestSize(); + wxSize totalS( m_textCtrl->GetBestSize() ); + + wxSize tsize(xlen + sizeBtn.x + MARGIN, totalS.y); +#if defined(__WXMSW__) + tsize.IncBy(0.4 * totalS.y + 4, 0); +#elif defined(__WXGTK__) + tsize.IncBy(totalS.y + 10, 0); +#endif // MSW GTK + + // Check if the user requested a non-standard height. + if ( ylen > 0 ) + tsize.IncBy(0, ylen - GetCharHeight()); + + return tsize; } void wxSpinCtrlGenericBase::DoMoveWindow(int x, int y, int width, int height) diff --git a/src/gtk/spinctrl.cpp b/src/gtk/spinctrl.cpp index e7b798197a..9bfe5a9b0b 100644 --- a/src/gtk/spinctrl.cpp +++ b/src/gtk/spinctrl.cpp @@ -337,10 +337,39 @@ GdkWindow *wxSpinCtrlGTKBase::GTKGetWindow(wxArrayGdkWindows& windows) const wxSize wxSpinCtrlGTKBase::DoGetBestSize() const { - wxSize ret( wxControl::DoGetBestSize() ); - wxSize best(95, ret.y); // FIXME: 95? - CacheBestSize(best); - return best; + return DoGetSizeFromTextSize(95); // TODO: 95 is completely arbitrary +} + +wxSize wxSpinCtrlGTKBase::DoGetSizeFromTextSize(int xlen, int ylen) const +{ + wxASSERT_MSG( m_widget, wxS("GetSizeFromTextSize called before creation") ); + + // Set an as small as possible size for the control, so preferred sizes + // return "natural" sizes, not taking into account the previous ones (which + // seems to be GTK+3 behaviour) + gtk_widget_set_size_request(m_widget, 0, 0); + + // Both Gtk+2 and Gtk+3 use current value/range to measure control's width. + // So, we can't ask Gtk+ for its width. Instead, we used hardcoded values. + + // Returned height is OK + wxSize totalS = GTKGetPreferredSize(m_widget); + +#if GTK_CHECK_VERSION(3,4,0) + // two buttons in horizontal + totalS.x = 46 + 15; // margins included +#else + // two small buttons in vertical + totalS.x = GetFont().GetPixelSize().y + 13; // margins included +#endif + + wxSize tsize(xlen + totalS.x, totalS.y); + + // Check if the user requested a non-standard height. + if ( ylen > 0 ) + tsize.IncBy(0, ylen - GetCharHeight()); + + return tsize; } // static diff --git a/src/msw/spinctrl.cpp b/src/msw/spinctrl.cpp index ea503b4c41..4625a25b49 100644 --- a/src/msw/spinctrl.cpp +++ b/src/msw/spinctrl.cpp @@ -717,26 +717,29 @@ bool wxSpinCtrl::MSWOnNotify(int WXUNUSED(idCtrl), WXLPARAM lParam, WXLPARAM *re // ---------------------------------------------------------------------------- wxSize wxSpinCtrl::DoGetBestSize() const +{ + return DoGetSizeFromTextSize(DEFAULT_ITEM_WIDTH); +} + +wxSize wxSpinCtrl::DoGetSizeFromTextSize(int xlen, int ylen) const { wxSize sizeBtn = wxSpinButton::DoGetBestSize(); - sizeBtn.x += DEFAULT_ITEM_WIDTH + MARGIN_BETWEEN; int y; wxGetCharSize(GetHWND(), NULL, &y, GetFont()); - y = EDIT_HEIGHT_FROM_CHAR_HEIGHT(y); - // JACS: we should always use the height calculated // from above, because otherwise we'll get a spin control // that's too big. So never use the height calculated // from wxSpinButton::DoGetBestSize(). - // if ( sizeBtn.y < y ) - { - // make the text tall enough - sizeBtn.y = y; - } + wxSize tsize(xlen + sizeBtn.x + MARGIN_BETWEEN + 0.3 * y + 10, + EDIT_HEIGHT_FROM_CHAR_HEIGHT(y)); - return sizeBtn; + // Check if the user requested a non-standard height. + if ( ylen > 0 ) + tsize.IncBy(0, ylen - y); + + return tsize; } void wxSpinCtrl::DoMoveWindow(int x, int y, int width, int height)