Merge branch 'spinctrl-fixes'
Various improvements to wxSpinCtrl and wxGridCellNumberEditor, using it. Closes https://github.com/wxWidgets/wxWidgets/pull/1588
This commit is contained in:
@@ -115,6 +115,11 @@ public:
|
|||||||
wxSize GetSizeFromTextSize(const wxSize& tsize) const
|
wxSize GetSizeFromTextSize(const wxSize& tsize) const
|
||||||
{ return DoGetSizeFromTextSize(tsize.x, tsize.y); }
|
{ return DoGetSizeFromTextSize(tsize.x, tsize.y); }
|
||||||
|
|
||||||
|
wxSize GetSizeFromText(const wxString& text) const
|
||||||
|
{
|
||||||
|
return GetSizeFromTextSize(GetTextExtent(text).GetWidth());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// static utilities for mnemonics char (&) handling
|
// static utilities for mnemonics char (&) handling
|
||||||
// ------------------------------------------------
|
// ------------------------------------------------
|
||||||
|
@@ -116,6 +116,8 @@ public:
|
|||||||
wxWindowID id,
|
wxWindowID id,
|
||||||
wxEvtHandler* evtHandler) wxOVERRIDE;
|
wxEvtHandler* evtHandler) wxOVERRIDE;
|
||||||
|
|
||||||
|
virtual void SetSize(const wxRect& rect) wxOVERRIDE;
|
||||||
|
|
||||||
virtual bool IsAcceptedKey(wxKeyEvent& event) wxOVERRIDE;
|
virtual bool IsAcceptedKey(wxKeyEvent& event) wxOVERRIDE;
|
||||||
virtual void BeginEdit(int row, int col, wxGrid* grid) wxOVERRIDE;
|
virtual void BeginEdit(int row, int col, wxGrid* grid) wxOVERRIDE;
|
||||||
virtual bool EndEdit(int row, int col, const wxGrid* grid,
|
virtual bool EndEdit(int row, int col, const wxGrid* grid,
|
||||||
|
@@ -168,6 +168,9 @@ private:
|
|||||||
// (up-down control) and the text control (buddy window).
|
// (up-down control) and the text control (buddy window).
|
||||||
int GetOverlap() const;
|
int GetOverlap() const;
|
||||||
|
|
||||||
|
// Calculate the best size for the number with the given number of digits.
|
||||||
|
wxSize GetBestSizeFromDigitsCount(int digitsCount) const;
|
||||||
|
|
||||||
wxDECLARE_DYNAMIC_CLASS(wxSpinCtrl);
|
wxDECLARE_DYNAMIC_CLASS(wxSpinCtrl);
|
||||||
wxDECLARE_EVENT_TABLE();
|
wxDECLARE_EVENT_TABLE();
|
||||||
wxDECLARE_NO_COPY_CLASS(wxSpinCtrl);
|
wxDECLARE_NO_COPY_CLASS(wxSpinCtrl);
|
||||||
|
@@ -143,6 +143,11 @@ namespace wxPrivate
|
|||||||
// string containing hexadecimal representation of the given number.
|
// string containing hexadecimal representation of the given number.
|
||||||
extern wxString wxSpinCtrlFormatAsHex(long val, long maxVal);
|
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
|
} // namespace wxPrivate
|
||||||
|
|
||||||
// old wxEVT_COMMAND_* constants
|
// old wxEVT_COMMAND_* constants
|
||||||
|
@@ -140,6 +140,27 @@ public:
|
|||||||
*/
|
*/
|
||||||
wxSize GetSizeFromTextSize(const wxSize& tsize) const;
|
wxSize GetSizeFromTextSize(const wxSize& tsize) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Determine the minimum size needed by the control to display the given text.
|
||||||
|
|
||||||
|
The helper function that uses combination of GetSizeFromTextSize() and
|
||||||
|
GetTextExtent() which used together pretty often:
|
||||||
|
@code
|
||||||
|
wxSize GetSizeFromText(const wxString& text) const
|
||||||
|
{
|
||||||
|
return GetSizeFromTextSize(GetTextExtent(text).GetWidth());
|
||||||
|
}
|
||||||
|
@endcode
|
||||||
|
|
||||||
|
@param text The given text.
|
||||||
|
@return The size that the control should have to leave the area of the
|
||||||
|
specified text. May return wxDefaultSize if this method is not
|
||||||
|
implemented for this particular control under the current platform.
|
||||||
|
|
||||||
|
@since 3.1.3
|
||||||
|
*/
|
||||||
|
wxSize GetSizeFromText(const wxString& text) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Sets the control's label.
|
Sets the control's label.
|
||||||
|
|
||||||
|
@@ -115,4 +115,17 @@ wxString wxPrivate::wxSpinCtrlFormatAsHex(long val, long maxVal)
|
|||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wxSize wxPrivate::wxSpinCtrlGetBestSize(const wxControl* spin,
|
||||||
|
int minVal, int maxVal, int base)
|
||||||
|
{
|
||||||
|
const int lenMin = (base == 16 ?
|
||||||
|
wxSpinCtrlFormatAsHex(minVal, maxVal) :
|
||||||
|
wxString::Format("%d", minVal)).length();
|
||||||
|
const int lenMax = (base == 16 ?
|
||||||
|
wxSpinCtrlFormatAsHex(maxVal, maxVal) :
|
||||||
|
wxString::Format("%d", maxVal)).length();
|
||||||
|
const wxString largestString('8', wxMax(lenMin, lenMax));
|
||||||
|
return spin->GetSizeFromText(largestString);
|
||||||
|
}
|
||||||
|
|
||||||
#endif // wxUSE_SPINCTRL
|
#endif // wxUSE_SPINCTRL
|
||||||
|
@@ -683,10 +683,14 @@ void wxGridCellNumberEditor::Create(wxWindow* parent,
|
|||||||
#if wxUSE_SPINCTRL
|
#if wxUSE_SPINCTRL
|
||||||
if ( HasRange() )
|
if ( HasRange() )
|
||||||
{
|
{
|
||||||
|
long style = wxSP_ARROW_KEYS |
|
||||||
|
wxTE_PROCESS_ENTER |
|
||||||
|
wxTE_PROCESS_TAB;
|
||||||
|
|
||||||
// create a spin ctrl
|
// create a spin ctrl
|
||||||
m_control = new wxSpinCtrl(parent, wxID_ANY, wxEmptyString,
|
m_control = new wxSpinCtrl(parent, wxID_ANY, wxEmptyString,
|
||||||
wxDefaultPosition, wxDefaultSize,
|
wxDefaultPosition, wxDefaultSize,
|
||||||
wxSP_ARROW_KEYS,
|
style,
|
||||||
m_min, m_max);
|
m_min, m_max);
|
||||||
|
|
||||||
wxGridCellEditor::Create(parent, id, evtHandler);
|
wxGridCellEditor::Create(parent, id, evtHandler);
|
||||||
@@ -703,6 +707,48 @@ void wxGridCellNumberEditor::Create(wxWindow* parent,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void wxGridCellNumberEditor::SetSize(const wxRect& rectCell)
|
||||||
|
{
|
||||||
|
#if wxUSE_SPINCTRL
|
||||||
|
if ( HasRange() )
|
||||||
|
{
|
||||||
|
wxASSERT_MSG(m_control, "The wxSpinCtrl must be created first!");
|
||||||
|
|
||||||
|
wxSize size = Spin()->GetBestSize();
|
||||||
|
|
||||||
|
// Extend the control to fill the entire cell horizontally.
|
||||||
|
if ( size.x < rectCell.GetWidth() )
|
||||||
|
size.x = rectCell.GetWidth();
|
||||||
|
|
||||||
|
// Ensure it uses a reasonable height even if wxSpinCtrl::GetBestSize()
|
||||||
|
// didn't return anything useful.
|
||||||
|
if ( size.y <= 0 )
|
||||||
|
size.y = rectCell.GetHeight();
|
||||||
|
|
||||||
|
wxRect rectSpin(rectCell.GetPosition(), size);
|
||||||
|
|
||||||
|
// If possible, i.e. if we're not editing the topmost or leftmost cell,
|
||||||
|
// center the control rectangle in the cell.
|
||||||
|
if ( rectCell.GetTop() > 0 )
|
||||||
|
{
|
||||||
|
rectSpin.SetTop(rectCell.GetTop() -
|
||||||
|
(rectSpin.GetHeight() - rectCell.GetHeight()) / 2);
|
||||||
|
}
|
||||||
|
if ( rectCell.GetLeft() > 0 )
|
||||||
|
{
|
||||||
|
rectSpin.SetLeft(rectCell.GetLeft() -
|
||||||
|
(rectSpin.GetWidth() - rectCell.GetWidth()) / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
wxGridCellEditor::SetSize(rectSpin);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif // wxUSE_SPINCTRL
|
||||||
|
{
|
||||||
|
wxGridCellTextEditor::SetSize(rectCell);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void wxGridCellNumberEditor::BeginEdit(int row, int col, wxGrid* grid)
|
void wxGridCellNumberEditor::BeginEdit(int row, int col, wxGrid* grid)
|
||||||
{
|
{
|
||||||
// first get the value
|
// first get the value
|
||||||
|
@@ -267,6 +267,8 @@ void wxSpinCtrlGTKBase::DoSetRange(double minVal, double maxVal)
|
|||||||
|
|
||||||
wxSpinCtrlEventDisabler disable(this);
|
wxSpinCtrlEventDisabler disable(this);
|
||||||
gtk_spin_button_set_range( GTK_SPIN_BUTTON(m_widget), minVal, maxVal);
|
gtk_spin_button_set_range( GTK_SPIN_BUTTON(m_widget), minVal, maxVal);
|
||||||
|
|
||||||
|
InvalidateBestSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxSpinCtrlGTKBase::DoSetIncrement(double inc)
|
void wxSpinCtrlGTKBase::DoSetIncrement(double inc)
|
||||||
@@ -354,15 +356,8 @@ GdkWindow *wxSpinCtrlGTKBase::GTKGetWindow(wxArrayGdkWindows& windows) const
|
|||||||
wxSize wxSpinCtrlGTKBase::DoGetBestSize() const
|
wxSize wxSpinCtrlGTKBase::DoGetBestSize() const
|
||||||
{
|
{
|
||||||
const int minVal = static_cast<int>(DoGetMin());
|
const int minVal = static_cast<int>(DoGetMin());
|
||||||
const int lenMin = wxString::Format("%d", minVal).length();
|
|
||||||
|
|
||||||
const int maxVal = static_cast<int>(DoGetMax());
|
const int maxVal = static_cast<int>(DoGetMax());
|
||||||
const int lenMax = wxString::Format("%d", maxVal).length();
|
return wxPrivate::wxSpinCtrlGetBestSize(this, minVal, maxVal, GetBase());
|
||||||
|
|
||||||
wxString longestText(wxMax(lenMin, lenMax), '9');
|
|
||||||
if ( minVal < 0 )
|
|
||||||
longestText.insert(0, "-");
|
|
||||||
return DoGetSizeFromTextSize(GetTextExtent(longestText).x, -1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wxSize wxSpinCtrlGTKBase::DoGetSizeFromTextSize(int xlen, int ylen) const
|
wxSize wxSpinCtrlGTKBase::DoGetSizeFromTextSize(int xlen, int ylen) const
|
||||||
@@ -477,6 +472,11 @@ bool wxSpinCtrl::SetBase(int base)
|
|||||||
this);
|
this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
InvalidateBestSize();
|
||||||
|
|
||||||
|
// Update the displayed text after changing the base it uses.
|
||||||
|
SetValue(GetValue());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -348,39 +348,6 @@ bool wxSpinCtrl::Create(wxWindow *parent,
|
|||||||
if (!m_hasFont)
|
if (!m_hasFont)
|
||||||
SetFont(GetDefaultAttributes().font);
|
SetFont(GetDefaultAttributes().font);
|
||||||
|
|
||||||
// Finally deal with the size: notice that this can only be done now both
|
|
||||||
// windows are created and the text one is set up as buddy because
|
|
||||||
// UDM_SETBUDDY changes its size using some unknown algorithm, so setting
|
|
||||||
// the sizes earlier is useless.
|
|
||||||
const int bestSpinWidth = wxSpinButton::DoGetBestSize().x;
|
|
||||||
const int effectiveSpinWidth = bestSpinWidth - GetOverlap();
|
|
||||||
wxSize sizeCtrl(size);
|
|
||||||
if ( sizeCtrl.x <= 0 )
|
|
||||||
{
|
|
||||||
// DEFAULT_ITEM_WIDTH is the default width for the text control
|
|
||||||
sizeCtrl.x = FromDIP(DEFAULT_ITEM_WIDTH) + effectiveSpinWidth;
|
|
||||||
}
|
|
||||||
else if ( sizeCtrl.x <= effectiveSpinWidth )
|
|
||||||
{
|
|
||||||
wxLogDebug(wxS("wxSpinCtrl \"%s\": initial width %d is too small, ")
|
|
||||||
wxS("at least %d pixels needed."),
|
|
||||||
name, size.x, effectiveSpinWidth);
|
|
||||||
}
|
|
||||||
|
|
||||||
// adjust an invalid height for text control
|
|
||||||
if ( sizeCtrl.y <= 0 )
|
|
||||||
{
|
|
||||||
int cx, cy;
|
|
||||||
wxGetCharSize(GetHWND(), &cx, &cy, GetFont());
|
|
||||||
|
|
||||||
sizeCtrl.y = EDIT_HEIGHT_FROM_CHAR_HEIGHT(cy);
|
|
||||||
}
|
|
||||||
|
|
||||||
// This will call our DoMoveWindow() and lay out the windows correctly.
|
|
||||||
SetInitialSize(sizeCtrl);
|
|
||||||
|
|
||||||
(void)::ShowWindow(GetBuddyHwnd(), SW_SHOW);
|
|
||||||
|
|
||||||
// If the initial text value is actually a number, it overrides the
|
// If the initial text value is actually a number, it overrides the
|
||||||
// "initial" argument specified later.
|
// "initial" argument specified later.
|
||||||
long initialFromText;
|
long initialFromText;
|
||||||
@@ -400,6 +367,22 @@ bool wxSpinCtrl::Create(wxWindow *parent,
|
|||||||
SetValue(value);
|
SetValue(value);
|
||||||
m_blockEvent = false;
|
m_blockEvent = false;
|
||||||
|
|
||||||
|
// Finally deal with the size: notice that this can only be done now both
|
||||||
|
// windows are created and the text one is set up as buddy because
|
||||||
|
// UDM_SETBUDDY changes its size using some unknown algorithm, so setting
|
||||||
|
// the sizes earlier is useless. Do it after setting the range and the base
|
||||||
|
// because GetBestSize() uses them.
|
||||||
|
if ( size.x > 0 && size.x < GetBestSize().x )
|
||||||
|
{
|
||||||
|
wxLogDebug(wxS("wxSpinCtrl \"%s\": initial width %d is too small, ")
|
||||||
|
wxS("at least %d pixels needed."),
|
||||||
|
name, size.x, GetBestSize().x);
|
||||||
|
}
|
||||||
|
|
||||||
|
SetInitialSize(size);
|
||||||
|
|
||||||
|
(void)::ShowWindow(GetBuddyHwnd(), SW_SHOW);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -439,10 +422,16 @@ bool wxSpinCtrl::SetBase(int base)
|
|||||||
if ( !::SendMessage(GetHwnd(), UDM_SETBASE, base, 0) )
|
if ( !::SendMessage(GetHwnd(), UDM_SETBASE, base, 0) )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// DoGetBestSize uses the base.
|
||||||
|
InvalidateBestSize();
|
||||||
|
|
||||||
// Whether we need to be able enter "x" or not influences whether we should
|
// Whether we need to be able enter "x" or not influences whether we should
|
||||||
// use ES_NUMBER for the buddy control.
|
// use ES_NUMBER for the buddy control.
|
||||||
UpdateBuddyStyle();
|
UpdateBuddyStyle();
|
||||||
|
|
||||||
|
// Update the displayed text after changing the base it uses.
|
||||||
|
SetValue(GetValue());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -559,6 +548,8 @@ void wxSpinCtrl::SetRange(int minVal, int maxVal)
|
|||||||
|
|
||||||
wxSpinButton::SetRange(minVal, maxVal);
|
wxSpinButton::SetRange(minVal, maxVal);
|
||||||
|
|
||||||
|
InvalidateBestSize();
|
||||||
|
|
||||||
UpdateBuddyStyle();
|
UpdateBuddyStyle();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -748,7 +739,7 @@ int wxSpinCtrl::GetOverlap() const
|
|||||||
|
|
||||||
wxSize wxSpinCtrl::DoGetBestSize() const
|
wxSize wxSpinCtrl::DoGetBestSize() const
|
||||||
{
|
{
|
||||||
return DoGetSizeFromTextSize(FromDIP(DEFAULT_ITEM_WIDTH));
|
return wxPrivate::wxSpinCtrlGetBestSize(this, GetMin(), GetMax(), GetBase());
|
||||||
}
|
}
|
||||||
|
|
||||||
wxSize wxSpinCtrl::DoGetSizeFromTextSize(int xlen, int ylen) const
|
wxSize wxSpinCtrl::DoGetSizeFromTextSize(int xlen, int ylen) const
|
||||||
|
Reference in New Issue
Block a user