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
|
||||
{ return DoGetSizeFromTextSize(tsize.x, tsize.y); }
|
||||
|
||||
wxSize GetSizeFromText(const wxString& text) const
|
||||
{
|
||||
return GetSizeFromTextSize(GetTextExtent(text).GetWidth());
|
||||
}
|
||||
|
||||
|
||||
// static utilities for mnemonics char (&) handling
|
||||
// ------------------------------------------------
|
||||
|
@@ -116,6 +116,8 @@ public:
|
||||
wxWindowID id,
|
||||
wxEvtHandler* evtHandler) wxOVERRIDE;
|
||||
|
||||
virtual void SetSize(const wxRect& rect) wxOVERRIDE;
|
||||
|
||||
virtual bool IsAcceptedKey(wxKeyEvent& event) wxOVERRIDE;
|
||||
virtual void BeginEdit(int row, int col, wxGrid* grid) wxOVERRIDE;
|
||||
virtual bool EndEdit(int row, int col, const wxGrid* grid,
|
||||
|
@@ -168,6 +168,9 @@ private:
|
||||
// (up-down control) and the text control (buddy window).
|
||||
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_EVENT_TABLE();
|
||||
wxDECLARE_NO_COPY_CLASS(wxSpinCtrl);
|
||||
|
@@ -143,6 +143,11 @@ namespace wxPrivate
|
||||
// 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
|
||||
|
@@ -140,6 +140,27 @@ public:
|
||||
*/
|
||||
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.
|
||||
|
||||
|
@@ -115,4 +115,17 @@ wxString wxPrivate::wxSpinCtrlFormatAsHex(long val, long maxVal)
|
||||
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
|
||||
|
@@ -683,10 +683,14 @@ void wxGridCellNumberEditor::Create(wxWindow* parent,
|
||||
#if wxUSE_SPINCTRL
|
||||
if ( HasRange() )
|
||||
{
|
||||
long style = wxSP_ARROW_KEYS |
|
||||
wxTE_PROCESS_ENTER |
|
||||
wxTE_PROCESS_TAB;
|
||||
|
||||
// create a spin ctrl
|
||||
m_control = new wxSpinCtrl(parent, wxID_ANY, wxEmptyString,
|
||||
wxDefaultPosition, wxDefaultSize,
|
||||
wxSP_ARROW_KEYS,
|
||||
style,
|
||||
m_min, m_max);
|
||||
|
||||
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)
|
||||
{
|
||||
// first get the value
|
||||
|
@@ -267,6 +267,8 @@ void wxSpinCtrlGTKBase::DoSetRange(double minVal, double maxVal)
|
||||
|
||||
wxSpinCtrlEventDisabler disable(this);
|
||||
gtk_spin_button_set_range( GTK_SPIN_BUTTON(m_widget), minVal, maxVal);
|
||||
|
||||
InvalidateBestSize();
|
||||
}
|
||||
|
||||
void wxSpinCtrlGTKBase::DoSetIncrement(double inc)
|
||||
@@ -354,15 +356,8 @@ GdkWindow *wxSpinCtrlGTKBase::GTKGetWindow(wxArrayGdkWindows& windows) const
|
||||
wxSize wxSpinCtrlGTKBase::DoGetBestSize() const
|
||||
{
|
||||
const int minVal = static_cast<int>(DoGetMin());
|
||||
const int lenMin = wxString::Format("%d", minVal).length();
|
||||
|
||||
const int maxVal = static_cast<int>(DoGetMax());
|
||||
const int lenMax = wxString::Format("%d", maxVal).length();
|
||||
|
||||
wxString longestText(wxMax(lenMin, lenMax), '9');
|
||||
if ( minVal < 0 )
|
||||
longestText.insert(0, "-");
|
||||
return DoGetSizeFromTextSize(GetTextExtent(longestText).x, -1);
|
||||
return wxPrivate::wxSpinCtrlGetBestSize(this, minVal, maxVal, GetBase());
|
||||
}
|
||||
|
||||
wxSize wxSpinCtrlGTKBase::DoGetSizeFromTextSize(int xlen, int ylen) const
|
||||
@@ -477,6 +472,11 @@ bool wxSpinCtrl::SetBase(int base)
|
||||
this);
|
||||
}
|
||||
|
||||
InvalidateBestSize();
|
||||
|
||||
// Update the displayed text after changing the base it uses.
|
||||
SetValue(GetValue());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@@ -348,39 +348,6 @@ bool wxSpinCtrl::Create(wxWindow *parent,
|
||||
if (!m_hasFont)
|
||||
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
|
||||
// "initial" argument specified later.
|
||||
long initialFromText;
|
||||
@@ -400,6 +367,22 @@ bool wxSpinCtrl::Create(wxWindow *parent,
|
||||
SetValue(value);
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -439,10 +422,16 @@ bool wxSpinCtrl::SetBase(int base)
|
||||
if ( !::SendMessage(GetHwnd(), UDM_SETBASE, base, 0) )
|
||||
return false;
|
||||
|
||||
// DoGetBestSize uses the base.
|
||||
InvalidateBestSize();
|
||||
|
||||
// Whether we need to be able enter "x" or not influences whether we should
|
||||
// use ES_NUMBER for the buddy control.
|
||||
UpdateBuddyStyle();
|
||||
|
||||
// Update the displayed text after changing the base it uses.
|
||||
SetValue(GetValue());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -559,6 +548,8 @@ void wxSpinCtrl::SetRange(int minVal, int maxVal)
|
||||
|
||||
wxSpinButton::SetRange(minVal, maxVal);
|
||||
|
||||
InvalidateBestSize();
|
||||
|
||||
UpdateBuddyStyle();
|
||||
}
|
||||
|
||||
@@ -748,7 +739,7 @@ int wxSpinCtrl::GetOverlap() 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
|
||||
|
Reference in New Issue
Block a user