From 40aa1a7e60f74bfc732f9184c67c82b540f324f8 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Tue, 20 Nov 2012 12:49:53 +0000 Subject: [PATCH] Implement GetSizeFromTextSize() for wxSpinCtrl. Implement it for the native MSW and GTK versions and the generic one used in the other ports and also for wxSpinCtrlDouble under MSW. Also test this function in the spin page of the widgets sample. Closes #14840. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@72995 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/generic/spinctlg.h | 1 + include/wx/gtk/spinctrl.h | 1 + include/wx/msw/spinctrl.h | 1 + samples/widgets/spinbtn.cpp | 13 ++++++++++++ samples/widgets/widgets.cpp | 4 ++++ src/generic/spinctlg.cpp | 22 ++++++++++++++++++--- src/gtk/spinctrl.cpp | 37 +++++++++++++++++++++++++++++++---- src/msw/spinctrl.cpp | 21 +++++++++++--------- 8 files changed, 84 insertions(+), 16 deletions(-) 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)