Merge branch 'gtk-spin-width-from-text'

Fixes for wxSpinCtrl::GetSizeFromTextSize() and best size in wxGTK.

Closes #18568.

See https://github.com/wxWidgets/wxWidgets/pull/1645
This commit is contained in:
Vadim Zeitlin
2019-11-14 16:07:05 +01:00
8 changed files with 84 additions and 44 deletions

View File

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

View File

@@ -0,0 +1,31 @@
///////////////////////////////////////////////////////////////////////////////
// Name: wx/private/spinctrl.h
// Purpose: Private functions used in wxSpinCtrl implementation.
// Author: Vadim Zeitlin
// Created: 2019-11-13
// Copyright: (c) 2019 Vadim Zeitlin <vadim@wxwidgets.org>
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
#ifndef _WX_PRIVATE_SPINCTRL_H_
#define _WX_PRIVATE_SPINCTRL_H_
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 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.
extern wxSize GetBestSize(const wxControl* spin, int minVal, int maxVal, int base);
} // namespace wxSpinCtrlImpl
#endif // _WX_PRIVATE_SPINCTRL_H_

View File

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

View File

@@ -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);
@@ -102,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
@@ -115,16 +119,21 @@ wxString wxPrivate::wxSpinCtrlFormatAsHex(long val, long maxVal)
return text;
}
wxSize wxPrivate::wxSpinCtrlGetBestSize(const wxControl* spin,
int minVal, int maxVal, int base)
int wxSpinCtrlImpl::GetMaxValueLength(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 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);
}

View File

@@ -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
@@ -654,8 +656,7 @@ wxString wxSpinCtrl::DoValueToText(double val)
switch ( GetBase() )
{
case 16:
return wxPrivate::wxSpinCtrlFormatAsHex(static_cast<long>(val),
GetMax());
return wxSpinCtrlImpl::FormatAsHex(static_cast<long>(val), GetMax());
default:
wxFAIL_MSG( wxS("Unsupported spin control base") );

View File

@@ -16,10 +16,13 @@
#ifndef WX_PRECOMP
#include "wx/textctrl.h" // for wxEVT_TEXT
#include "wx/math.h" // wxRound()
#include "wx/utils.h"
#include "wx/wxcrtvararg.h"
#endif
#include "wx/private/spinctrl.h"
#include "wx/gtk/private.h"
//-----------------------------------------------------------------------------
@@ -135,6 +138,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) );
@@ -269,6 +274,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)
@@ -353,38 +360,35 @@ GdkWindow *wxSpinCtrlGTKBase::GTKGetWindow(wxArrayGdkWindows& windows) const
return NULL;
}
wxSize wxSpinCtrlGTKBase::DoGetBestSize() const
void wxSpinCtrlGTKBase::GtkSetEntryWidth()
{
const int minVal = static_cast<int>(DoGetMin());
const int maxVal = static_cast<int>(DoGetMax());
return wxPrivate::wxSpinCtrlGetBestSize(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
{
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);
#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);
}
#endif // GTK+ 3.12+
gtk_entry_set_width_chars(GTK_ENTRY(m_widget), numDigits);
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 )
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);
wxSize tsize(xlen + totalS.x, totalS.y);
// Check if the user requested a non-standard height.
if ( ylen > 0 )
tsize.IncBy(0, ylen - GetCharHeight());
@@ -431,7 +435,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;
@@ -474,6 +478,8 @@ bool wxSpinCtrl::SetBase(int base)
InvalidateBestSize();
GtkSetEntryWidth();
// Update the displayed text after changing the base it uses.
SetValue(GetValue());

View File

@@ -21,6 +21,8 @@
#include "wx/crt.h"
#endif
#include "wx/private/spinctrl.h"
#include "wx/gtk1/private.h"
//-----------------------------------------------------------------------------
@@ -69,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;

View File

@@ -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"
@@ -474,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();
@@ -741,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