From 44446940434aa0c0e4a34876b12441df09b55a08 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Wed, 13 Nov 2019 02:43:44 +0100 Subject: [PATCH 1/6] Move private wxSpinCtrl helpers into a private header Np real changes, just don't put these functions in the public wx/spinctrl.h, they have nothing to do there. --- include/wx/private/spinctrl.h | 27 +++++++++++++++++++++++++++ include/wx/spinctrl.h | 13 ------------- src/common/spinctrlcmn.cpp | 2 ++ src/generic/spinctlg.cpp | 2 ++ src/gtk/spinctrl.cpp | 2 ++ src/gtk1/spinctrl.cpp | 2 ++ src/msw/spinctrl.cpp | 2 ++ 7 files changed, 37 insertions(+), 13 deletions(-) create mode 100644 include/wx/private/spinctrl.h diff --git a/include/wx/private/spinctrl.h b/include/wx/private/spinctrl.h new file mode 100644 index 0000000000..685e8faf69 --- /dev/null +++ b/include/wx/private/spinctrl.h @@ -0,0 +1,27 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: wx/private/spinctrl.h +// Purpose: Private functions used in wxSpinCtrl implementation. +// Author: Vadim Zeitlin +// Created: 2019-11-13 +// Copyright: (c) 2019 Vadim Zeitlin +// Licence: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _WX_PRIVATE_SPINCTRL_H_ +#define _WX_PRIVATE_SPINCTRL_H_ + +namespace wxPrivate +{ + +// This is an internal helper function currently used by all ports: return the +// string containing hexadecimal representation of the given number. +extern wxString wxSpinCtrlFormatAsHex(long val, long maxVal); + +// The helper function to determine the best size for the given control. +// We can't implement this function in the wxSpinCtrlBase because MSW implementation +// of wxSpinCtrl is derived from wxSpinButton but uses the same algorithm. +extern wxSize wxSpinCtrlGetBestSize(const wxControl* spin, int minVal, int maxVal, int base); + +} // namespace wxPrivate + +#endif // _WX_PRIVATE_SPINCTRL_H_ diff --git a/include/wx/spinctrl.h b/include/wx/spinctrl.h index 0051737fbc..775672f97b 100644 --- a/include/wx/spinctrl.h +++ b/include/wx/spinctrl.h @@ -136,19 +136,6 @@ typedef void (wxEvtHandler::*wxSpinDoubleEventFunction)(wxSpinDoubleEvent&); #if !defined(wxHAS_NATIVE_SPINCTRL) || !defined(wxHAS_NATIVE_SPINCTRLDOUBLE) #include "wx/generic/spinctlg.h" #endif -namespace wxPrivate -{ - -// This is an internal helper function currently used by all ports: return the -// string containing hexadecimal representation of the given number. -extern wxString wxSpinCtrlFormatAsHex(long val, long maxVal); - -// The helper function to determine the best size for the given control. -// We can't implement this function in the wxSpinCtrlBase because MSW implementation -// of wxSpinCtrl is derived from wxSpinButton but uses the same algorithm. -extern wxSize wxSpinCtrlGetBestSize(const wxControl* spin, int minVal, int maxVal, int base); - -} // namespace wxPrivate // old wxEVT_COMMAND_* constants #define wxEVT_COMMAND_SPINCTRL_UPDATED wxEVT_SPINCTRL diff --git a/src/common/spinctrlcmn.cpp b/src/common/spinctrlcmn.cpp index 9598ef829d..076e68d15d 100644 --- a/src/common/spinctrlcmn.cpp +++ b/src/common/spinctrlcmn.cpp @@ -25,6 +25,8 @@ #include "wx/spinbutt.h" #include "wx/spinctrl.h" +#include "wx/private/spinctrl.h" + #if wxUSE_SPINCTRL wxDEFINE_EVENT(wxEVT_SPINCTRL, wxSpinEvent); diff --git a/src/generic/spinctlg.cpp b/src/generic/spinctlg.cpp index b49c5db77b..3a53802889 100644 --- a/src/generic/spinctlg.cpp +++ b/src/generic/spinctlg.cpp @@ -32,6 +32,8 @@ #if wxUSE_SPINCTRL +#include "wx/private/spinctrl.h" + wxIMPLEMENT_DYNAMIC_CLASS(wxSpinDoubleEvent, wxNotifyEvent); // There are port-specific versions for the wxSpinCtrl, so exclude the diff --git a/src/gtk/spinctrl.cpp b/src/gtk/spinctrl.cpp index eaeeea8b3c..ec65588bf5 100644 --- a/src/gtk/spinctrl.cpp +++ b/src/gtk/spinctrl.cpp @@ -20,6 +20,8 @@ #include "wx/wxcrtvararg.h" #endif +#include "wx/private/spinctrl.h" + #include "wx/gtk/private.h" //----------------------------------------------------------------------------- diff --git a/src/gtk1/spinctrl.cpp b/src/gtk1/spinctrl.cpp index d462dbe0ca..6c416de7b4 100644 --- a/src/gtk1/spinctrl.cpp +++ b/src/gtk1/spinctrl.cpp @@ -21,6 +21,8 @@ #include "wx/crt.h" #endif +#include "wx/private/spinctrl.h" + #include "wx/gtk1/private.h" //----------------------------------------------------------------------------- diff --git a/src/msw/spinctrl.cpp b/src/msw/spinctrl.cpp index 321f6b11c5..72c8cfbb30 100644 --- a/src/msw/spinctrl.cpp +++ b/src/msw/spinctrl.cpp @@ -35,6 +35,8 @@ #include "wx/wxcrtvararg.h" #endif +#include "wx/private/spinctrl.h" + #include "wx/msw/private.h" #include "wx/msw/private/winstyle.h" From eb3d8395c220e319357be91615158fbe21b959e1 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Wed, 13 Nov 2019 02:51:00 +0100 Subject: [PATCH 2/6] Rename wxSpinCtrl helper functions Put them in wxSpinCtrlImpl namespace and remove "wxSpinCtrl" prefix from the function names themselves, this was ugly. No real changes. --- include/wx/private/spinctrl.h | 8 ++++---- src/common/spinctrlcmn.cpp | 12 +++++++----- src/generic/spinctlg.cpp | 3 +-- src/gtk/spinctrl.cpp | 4 ++-- src/gtk1/spinctrl.cpp | 2 +- src/msw/spinctrl.cpp | 4 ++-- 6 files changed, 17 insertions(+), 16 deletions(-) diff --git a/include/wx/private/spinctrl.h b/include/wx/private/spinctrl.h index 685e8faf69..7784c0f0da 100644 --- a/include/wx/private/spinctrl.h +++ b/include/wx/private/spinctrl.h @@ -10,18 +10,18 @@ #ifndef _WX_PRIVATE_SPINCTRL_H_ #define _WX_PRIVATE_SPINCTRL_H_ -namespace wxPrivate +namespace wxSpinCtrlImpl { // This is an internal helper function currently used by all ports: return the // string containing hexadecimal representation of the given number. -extern wxString wxSpinCtrlFormatAsHex(long val, long maxVal); +extern wxString FormatAsHex(long val, long maxVal); // The helper function to determine the best size for the given control. // We can't implement this function in the wxSpinCtrlBase because MSW implementation // of wxSpinCtrl is derived from wxSpinButton but uses the same algorithm. -extern wxSize wxSpinCtrlGetBestSize(const wxControl* spin, int minVal, int maxVal, int base); +extern wxSize GetBestSize(const wxControl* spin, int minVal, int maxVal, int base); -} // namespace wxPrivate +} // namespace wxSpinCtrlImpl #endif // _WX_PRIVATE_SPINCTRL_H_ diff --git a/src/common/spinctrlcmn.cpp b/src/common/spinctrlcmn.cpp index 076e68d15d..7d67eec9c2 100644 --- a/src/common/spinctrlcmn.cpp +++ b/src/common/spinctrlcmn.cpp @@ -104,7 +104,9 @@ wxCONSTRUCTOR_6( wxSpinCtrl, wxWindow*, Parent, wxWindowID, Id, \ wxSize, Size, long, WindowStyle ) -wxString wxPrivate::wxSpinCtrlFormatAsHex(long val, long maxVal) +using namespace wxSpinCtrlImpl; + +wxString wxSpinCtrlImpl::FormatAsHex(long val, long maxVal) { // We format the value like this is for compatibility with (native // behaviour of) wxMSW @@ -117,14 +119,14 @@ wxString wxPrivate::wxSpinCtrlFormatAsHex(long val, long maxVal) return text; } -wxSize wxPrivate::wxSpinCtrlGetBestSize(const wxControl* spin, - int minVal, int maxVal, int base) +wxSize wxSpinCtrlImpl::GetBestSize(const wxControl* spin, + int minVal, int maxVal, int base) { const int lenMin = (base == 16 ? - wxSpinCtrlFormatAsHex(minVal, maxVal) : + FormatAsHex(minVal, maxVal) : wxString::Format("%d", minVal)).length(); const int lenMax = (base == 16 ? - wxSpinCtrlFormatAsHex(maxVal, maxVal) : + FormatAsHex(maxVal, maxVal) : wxString::Format("%d", maxVal)).length(); const wxString largestString('8', wxMax(lenMin, lenMax)); return spin->GetSizeFromText(largestString); diff --git a/src/generic/spinctlg.cpp b/src/generic/spinctlg.cpp index 3a53802889..0620948741 100644 --- a/src/generic/spinctlg.cpp +++ b/src/generic/spinctlg.cpp @@ -656,8 +656,7 @@ wxString wxSpinCtrl::DoValueToText(double val) switch ( GetBase() ) { case 16: - return wxPrivate::wxSpinCtrlFormatAsHex(static_cast(val), - GetMax()); + return wxSpinCtrlImpl::FormatAsHex(static_cast(val), GetMax()); default: wxFAIL_MSG( wxS("Unsupported spin control base") ); diff --git a/src/gtk/spinctrl.cpp b/src/gtk/spinctrl.cpp index ec65588bf5..76711360f9 100644 --- a/src/gtk/spinctrl.cpp +++ b/src/gtk/spinctrl.cpp @@ -359,7 +359,7 @@ wxSize wxSpinCtrlGTKBase::DoGetBestSize() const { const int minVal = static_cast(DoGetMin()); const int maxVal = static_cast(DoGetMax()); - return wxPrivate::wxSpinCtrlGetBestSize(this, minVal, maxVal, GetBase()); + return wxSpinCtrlImpl::GetBestSize(this, minVal, maxVal, GetBase()); } wxSize wxSpinCtrlGTKBase::DoGetSizeFromTextSize(int xlen, int ylen) const @@ -433,7 +433,7 @@ wx_gtk_spin_output(GtkSpinButton* spin, wxSpinCtrl* win) gtk_entry_set_text ( GTK_ENTRY(spin), - wxPrivate::wxSpinCtrlFormatAsHex(val, win->GetMax()).utf8_str() + wxSpinCtrlImpl::FormatAsHex(val, win->GetMax()).utf8_str() ); return TRUE; diff --git a/src/gtk1/spinctrl.cpp b/src/gtk1/spinctrl.cpp index 6c416de7b4..98934ec791 100644 --- a/src/gtk1/spinctrl.cpp +++ b/src/gtk1/spinctrl.cpp @@ -71,7 +71,7 @@ wx_gtk_spin_output(GtkSpinButton* spin, wxSpinCtrl* win) gtk_entry_set_text ( GTK_ENTRY(spin), - wxPrivate::wxSpinCtrlFormatAsHex(val, win->GetMax()).utf8_str() + wxSpinCtrlImpl::FormatAsHex(val, win->GetMax()).utf8_str() ); return TRUE; diff --git a/src/msw/spinctrl.cpp b/src/msw/spinctrl.cpp index 72c8cfbb30..f5f7c442f1 100644 --- a/src/msw/spinctrl.cpp +++ b/src/msw/spinctrl.cpp @@ -476,7 +476,7 @@ void wxSpinCtrl::SetValue(int val) (text[1] != 'x' && text[1] != 'X')) ) { ::SetWindowText(GetBuddyHwnd(), - wxPrivate::wxSpinCtrlFormatAsHex(val, m_max).t_str()); + wxSpinCtrlImpl::FormatAsHex(val, m_max).t_str()); } m_oldValue = GetValue(); @@ -743,7 +743,7 @@ int wxSpinCtrl::GetOverlap() const wxSize wxSpinCtrl::DoGetBestSize() const { - return wxPrivate::wxSpinCtrlGetBestSize(this, GetMin(), GetMax(), GetBase()); + return wxSpinCtrlImpl::GetBestSize(this, GetMin(), GetMax(), GetBase()); } wxSize wxSpinCtrl::DoGetSizeFromTextSize(int xlen, int ylen) const From b891ffe8d0b0b769e7298227882300c28c348905 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Wed, 13 Nov 2019 02:51:42 +0100 Subject: [PATCH 3/6] Factor out another wxSpinCtrl helper for getting its max length This will be used in wxGTK implementation. For now no real changes yet. --- include/wx/private/spinctrl.h | 4 ++++ src/common/spinctrlcmn.cpp | 11 ++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/include/wx/private/spinctrl.h b/include/wx/private/spinctrl.h index 7784c0f0da..af2ae47270 100644 --- a/include/wx/private/spinctrl.h +++ b/include/wx/private/spinctrl.h @@ -17,6 +17,10 @@ namespace wxSpinCtrlImpl // string containing hexadecimal representation of the given number. extern wxString FormatAsHex(long val, long maxVal); +// Another helper returning the maximum length of a string representing a value +// valid in the given control. +extern int GetMaxValueLength(int minVal, int maxVal, int base); + // The helper function to determine the best size for the given control. // We can't implement this function in the wxSpinCtrlBase because MSW implementation // of wxSpinCtrl is derived from wxSpinButton but uses the same algorithm. diff --git a/src/common/spinctrlcmn.cpp b/src/common/spinctrlcmn.cpp index 7d67eec9c2..7098ff1d04 100644 --- a/src/common/spinctrlcmn.cpp +++ b/src/common/spinctrlcmn.cpp @@ -119,8 +119,7 @@ wxString wxSpinCtrlImpl::FormatAsHex(long val, long maxVal) return text; } -wxSize wxSpinCtrlImpl::GetBestSize(const wxControl* spin, - int minVal, int maxVal, int base) +int wxSpinCtrlImpl::GetMaxValueLength(int minVal, int maxVal, int base) { const int lenMin = (base == 16 ? FormatAsHex(minVal, maxVal) : @@ -128,7 +127,13 @@ wxSize wxSpinCtrlImpl::GetBestSize(const wxControl* spin, const int lenMax = (base == 16 ? FormatAsHex(maxVal, maxVal) : wxString::Format("%d", maxVal)).length(); - const wxString largestString('8', wxMax(lenMin, lenMax)); + return wxMax(lenMin, lenMax); +} + +wxSize wxSpinCtrlImpl::GetBestSize(const wxControl* spin, + int minVal, int maxVal, int base) +{ + const wxString largestString('8', GetMaxValueLength(minVal, maxVal, base)); return spin->GetSizeFromText(largestString); } From 7f368872d79055902148ca76e74b11dae72fe65a Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Wed, 13 Nov 2019 02:52:42 +0100 Subject: [PATCH 4/6] Adjust entry width of wxSpinCtrl in wxGTK to its range Ensure that the entry is always (just) big enough to show any value valid in this spin control. This also ensures that GetBestSize() doesn't need to be overridden to use GetSizeFromTextSize() any longer as the best size will be determined correctly by GTK itself. --- include/wx/gtk/spinctrl.h | 4 +++- src/gtk/spinctrl.cpp | 15 +++++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/include/wx/gtk/spinctrl.h b/include/wx/gtk/spinctrl.h index be7e1013eb..0b96827dd6 100644 --- a/include/wx/gtk/spinctrl.h +++ b/include/wx/gtk/spinctrl.h @@ -71,7 +71,9 @@ protected: void GtkDisableEvents() const; void GtkEnableEvents() const; - virtual wxSize DoGetBestSize() const wxOVERRIDE; + // Update the number of digits used to match our range (and base). + void GtkSetEntryWidth(); + virtual wxSize DoGetSizeFromTextSize(int xlen, int ylen = -1) const wxOVERRIDE; virtual GdkWindow *GTKGetWindow(wxArrayGdkWindows& windows) const wxOVERRIDE; diff --git a/src/gtk/spinctrl.cpp b/src/gtk/spinctrl.cpp index 76711360f9..6ed8512381 100644 --- a/src/gtk/spinctrl.cpp +++ b/src/gtk/spinctrl.cpp @@ -137,6 +137,8 @@ bool wxSpinCtrlGTKBase::Create(wxWindow *parent, wxWindowID id, gtk_entry_set_alignment(GTK_ENTRY(m_widget), align); + GtkSetEntryWidth(); + gtk_spin_button_set_wrap( GTK_SPIN_BUTTON(m_widget), (int)(m_windowStyle & wxSP_WRAP) ); @@ -271,6 +273,8 @@ void wxSpinCtrlGTKBase::DoSetRange(double minVal, double maxVal) gtk_spin_button_set_range( GTK_SPIN_BUTTON(m_widget), minVal, maxVal); InvalidateBestSize(); + + GtkSetEntryWidth(); } void wxSpinCtrlGTKBase::DoSetIncrement(double inc) @@ -355,11 +359,16 @@ GdkWindow *wxSpinCtrlGTKBase::GTKGetWindow(wxArrayGdkWindows& windows) const return NULL; } -wxSize wxSpinCtrlGTKBase::DoGetBestSize() const +void wxSpinCtrlGTKBase::GtkSetEntryWidth() { const int minVal = static_cast(DoGetMin()); const int maxVal = static_cast(DoGetMax()); - return wxSpinCtrlImpl::GetBestSize(this, minVal, maxVal, GetBase()); + + gtk_entry_set_width_chars + ( + GTK_ENTRY(m_widget), + wxSpinCtrlImpl::GetMaxValueLength(minVal, maxVal, GetBase()) + ); } wxSize wxSpinCtrlGTKBase::DoGetSizeFromTextSize(int xlen, int ylen) const @@ -476,6 +485,8 @@ bool wxSpinCtrl::SetBase(int base) InvalidateBestSize(); + GtkSetEntryWidth(); + // Update the displayed text after changing the base it uses. SetValue(GetValue()); From b472a791c1978f3e56649f94b2d1c45f171267ac Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 11 Nov 2019 23:54:09 +0100 Subject: [PATCH 5/6] Return fitting size from wxSpinCtrl::GetSizeFromTextSize() in GTK Previously we added the extent of the text to the preferred size of a spin button with 0 digits, but this didn't account for the fact that the control still reserved enough space for 3 digits in this case, and so the returned size was always too big than the required size by the width needed to show 3 digits. Fix this by directly asking for the size required to show the number of digits corresponding to the given text size. Note that ideal would be to provide GTK API at wx level directly, i.e. allow to just specify the number of digits instead of the text extent. But we still need to fix the already existing GetSizeFromTextSize() anyhow, so do this for now. See #18568. --- src/gtk/spinctrl.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/gtk/spinctrl.cpp b/src/gtk/spinctrl.cpp index 6ed8512381..e58e527f9e 100644 --- a/src/gtk/spinctrl.cpp +++ b/src/gtk/spinctrl.cpp @@ -16,6 +16,7 @@ #ifndef WX_PRECOMP #include "wx/textctrl.h" // for wxEVT_TEXT + #include "wx/math.h" // wxRound() #include "wx/utils.h" #include "wx/wxcrtvararg.h" #endif @@ -375,18 +376,24 @@ wxSize wxSpinCtrlGTKBase::DoGetSizeFromTextSize(int xlen, int ylen) const { wxASSERT_MSG( m_widget, wxS("GetSizeFromTextSize called before creation") ); + // This is a bit stupid as we typically compute xlen by measuring some + // string of digits in the first place, but there doesn't seem to be + // anything better to do (unless we add some GetSizeFromNumberOfDigits()). + const double widthDigit = GetTextExtent("0123456789").GetWidth() / 10.0; + const int numDigits = wxRound(xlen / widthDigit); + const gint widthChars = gtk_entry_get_width_chars(GTK_ENTRY(m_widget)); - gtk_entry_set_width_chars(GTK_ENTRY(m_widget), 0); + gtk_entry_set_width_chars(GTK_ENTRY(m_widget), numDigits); #if GTK_CHECK_VERSION(3,12,0) gint maxWidthChars = 0; if ( gtk_check_version(3,12,0) == NULL ) { maxWidthChars = gtk_entry_get_max_width_chars(GTK_ENTRY(m_widget)); - gtk_entry_set_max_width_chars(GTK_ENTRY(m_widget), 0); + gtk_entry_set_max_width_chars(GTK_ENTRY(m_widget), numDigits); } #endif // GTK+ 3.12+ - wxSize totalS = GTKGetPreferredSize(m_widget); + wxSize tsize = GTKGetPreferredSize(m_widget); #if GTK_CHECK_VERSION(3,12,0) if ( gtk_check_version(3,12,0) == NULL ) @@ -394,8 +401,6 @@ wxSize wxSpinCtrlGTKBase::DoGetSizeFromTextSize(int xlen, int ylen) const #endif // GTK+ 3.12+ gtk_entry_set_width_chars(GTK_ENTRY(m_widget), widthChars); - wxSize tsize(xlen + totalS.x, totalS.y); - // Check if the user requested a non-standard height. if ( ylen > 0 ) tsize.IncBy(0, ylen - GetCharHeight()); From 34f26bd18f026f8ef92dfb9744a6c14976e5fa02 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 11 Nov 2019 23:59:08 +0100 Subject: [PATCH 6/6] Don't change max number of digits in wxSpinCtrl code This doesn't seem to affect anything, i.e. the function returns the same results whether we do it or not, so just don't. --- src/gtk/spinctrl.cpp | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/gtk/spinctrl.cpp b/src/gtk/spinctrl.cpp index e58e527f9e..a341b79752 100644 --- a/src/gtk/spinctrl.cpp +++ b/src/gtk/spinctrl.cpp @@ -384,21 +384,9 @@ wxSize wxSpinCtrlGTKBase::DoGetSizeFromTextSize(int xlen, int ylen) const const gint widthChars = gtk_entry_get_width_chars(GTK_ENTRY(m_widget)); gtk_entry_set_width_chars(GTK_ENTRY(m_widget), numDigits); -#if GTK_CHECK_VERSION(3,12,0) - gint maxWidthChars = 0; - if ( gtk_check_version(3,12,0) == NULL ) - { - maxWidthChars = gtk_entry_get_max_width_chars(GTK_ENTRY(m_widget)); - gtk_entry_set_max_width_chars(GTK_ENTRY(m_widget), numDigits); - } -#endif // GTK+ 3.12+ wxSize tsize = GTKGetPreferredSize(m_widget); -#if GTK_CHECK_VERSION(3,12,0) - if ( gtk_check_version(3,12,0) == NULL ) - gtk_entry_set_max_width_chars(GTK_ENTRY(m_widget), maxWidthChars); -#endif // GTK+ 3.12+ gtk_entry_set_width_chars(GTK_ENTRY(m_widget), widthChars); // Check if the user requested a non-standard height.