From 995c6e6df5b58703bfb448a3874c0e8aaa4559f2 Mon Sep 17 00:00:00 2001 From: oneeyeman1 Date: Sat, 15 Jan 2022 18:13:48 -0600 Subject: [PATCH] Add wxSpinCtrl::SetIncrement() and implement it for all ports SetIncrement() was already available in wxSpinCtrlDouble and GTK version of wxSpinCtrl, now implement support for it in wxMSW and wxOSX as well. In fact, in wxMSW, implement it at wxSpinButton level, so that both this class and wxSpinCtrl inheriting from it (in wxMSW only) support setting custom increment now. Also add support for it to XRC, show it in the sample and add a unit test verifying that it works. Closes #2597. --- docs/doxygen/overviews/xrc_format.h | 2 ++ include/wx/msw/spinbutt.h | 2 ++ include/wx/osx/cocoa/private.h | 2 ++ include/wx/osx/core/private.h | 2 ++ include/wx/osx/iphone/private.h | 2 ++ include/wx/osx/spinbutt.h | 2 ++ include/wx/spinbutt.h | 3 ++- interface/wx/spinbutt.h | 28 +++++++++++++++++++++- interface/wx/spinctrl.h | 25 ++++++++++++++++++++ misc/schema/xrc_schema.rnc | 6 +++-- samples/widgets/spinbtn.cpp | 36 ++++++++++++++++++++++++++--- samples/xrc/rc/controls.xrc | 2 ++ src/msw/spinbutt.cpp | 20 ++++++++++++++++ src/msw/spinctrl.cpp | 1 - src/osx/cocoa/spinbutt.mm | 12 ++++++++++ src/osx/cocoa/window.mm | 19 +++++++++++++++ src/osx/spinbutt_osx.cpp | 10 ++++++++ src/xrc/xh_spin.cpp | 3 +++ tests/controls/spinctrltest.cpp | 26 +++++++++++++++++++++ 19 files changed, 195 insertions(+), 8 deletions(-) diff --git a/docs/doxygen/overviews/xrc_format.h b/docs/doxygen/overviews/xrc_format.h index 42fb8f73d4..fa222b0f34 100644 --- a/docs/doxygen/overviews/xrc_format.h +++ b/docs/doxygen/overviews/xrc_format.h @@ -2057,6 +2057,8 @@ exactly one non-toplevel window as its child. Minimum allowed value (default: 0).} @row3col{max, integer, Maximum allowed value (default: 100).} +@row3col{inc, integer, + Increment (default: 1). Available since wxWidgets 3.1.6.} @endTable diff --git a/include/wx/msw/spinbutt.h b/include/wx/msw/spinbutt.h index 494cc38f2e..64fb1fb1ad 100644 --- a/include/wx/msw/spinbutt.h +++ b/include/wx/msw/spinbutt.h @@ -58,6 +58,8 @@ public: // returns true if the platform should explicitly apply a theme border virtual bool CanApplyThemeBorder() const wxOVERRIDE { return false; } + virtual void SetIncrement(int value) wxOVERRIDE; + virtual int GetIncrement() const wxOVERRIDE; protected: virtual wxSize DoGetBestSize() const wxOVERRIDE; diff --git a/include/wx/osx/cocoa/private.h b/include/wx/osx/cocoa/private.h index bd4657b146..cbe2b4aa21 100644 --- a/include/wx/osx/cocoa/private.h +++ b/include/wx/osx/cocoa/private.h @@ -149,8 +149,10 @@ public : bool ButtonClickDidStateChange() wxOVERRIDE { return true; } void SetMinimum( wxInt32 v ) wxOVERRIDE; void SetMaximum( wxInt32 v ) wxOVERRIDE; + void SetIncrement(int value) wxOVERRIDE; wxInt32 GetMinimum() const wxOVERRIDE; wxInt32 GetMaximum() const wxOVERRIDE; + int GetIncrement() const wxOVERRIDE; void PulseGauge() wxOVERRIDE; void SetScrollThumb( wxInt32 value, wxInt32 thumbSize ) wxOVERRIDE; diff --git a/include/wx/osx/core/private.h b/include/wx/osx/core/private.h index ffbcb1312f..bf56446f69 100644 --- a/include/wx/osx/core/private.h +++ b/include/wx/osx/core/private.h @@ -347,8 +347,10 @@ public : virtual void Enable( bool enable ) = 0; virtual void SetMinimum( wxInt32 v ) = 0; virtual void SetMaximum( wxInt32 v ) = 0; + virtual void SetIncrement(int value) = 0; virtual wxInt32 GetMinimum() const = 0; virtual wxInt32 GetMaximum() const = 0; + virtual int GetIncrement() const = 0; virtual void PulseGauge() = 0; virtual void SetScrollThumb( wxInt32 value, wxInt32 thumbSize ) = 0; diff --git a/include/wx/osx/iphone/private.h b/include/wx/osx/iphone/private.h index e4225e8086..011434fbcc 100644 --- a/include/wx/osx/iphone/private.h +++ b/include/wx/osx/iphone/private.h @@ -100,8 +100,10 @@ public : bool ButtonClickDidStateChange() { return true ;} void SetMinimum( wxInt32 v ); void SetMaximum( wxInt32 v ); + void SetIncrement(int WXUNUSED(value)) { } wxInt32 GetMinimum() const; wxInt32 GetMaximum() const; + int GetIncrement() const { return 1; } void PulseGauge(); void SetScrollThumb( wxInt32 value, wxInt32 thumbSize ); diff --git a/include/wx/osx/spinbutt.h b/include/wx/osx/spinbutt.h index 8b7c5b843c..645f52f34c 100644 --- a/include/wx/osx/spinbutt.h +++ b/include/wx/osx/spinbutt.h @@ -54,6 +54,8 @@ public: virtual void SetRange(int minVal, int maxVal) wxOVERRIDE; virtual int GetValue() const wxOVERRIDE; virtual void SetValue(int val) wxOVERRIDE; + virtual void SetIncrement(int value) wxOVERRIDE; + virtual int GetIncrement() const wxOVERRIDE; // implementation diff --git a/include/wx/spinbutt.h b/include/wx/spinbutt.h index 7370ebf600..5204b95261 100644 --- a/include/wx/spinbutt.h +++ b/include/wx/spinbutt.h @@ -61,12 +61,13 @@ public: // is this spin button vertically oriented? bool IsVertical() const { return (m_windowStyle & wxSP_VERTICAL) != 0; } + virtual void SetIncrement(int WXUNUSED(value)) { } + virtual int GetIncrement() const { return 1; } protected: // the range value int m_min; int m_max; - wxDECLARE_NO_COPY_CLASS(wxSpinButtonBase); }; diff --git a/interface/wx/spinbutt.h b/interface/wx/spinbutt.h index 7acf76a5bb..67fe44b421 100644 --- a/interface/wx/spinbutt.h +++ b/interface/wx/spinbutt.h @@ -54,7 +54,7 @@ public: A wxSpinButton has two small up and down (or left and right) arrow buttons. - It is often used next to a text control for increment and decrementing a value. + It is often used next to a text control for incrementing and decrementing a value. Portable programs should try to use wxSpinCtrl instead as wxSpinButton is not implemented for all platforms but wxSpinCtrl is as it degenerates to a simple wxTextCtrl on such platforms. @@ -146,6 +146,15 @@ public: long style = wxSP_VERTICAL, const wxString& name = "wxSpinButton"); + /** + Get the value for increment for a spin control. + + The default value is 1 but it can be changed using SetIncrement(). + + @since 3.1.6 + */ + int GetIncrement() const; + /** Returns the maximum permissible value. @@ -167,6 +176,23 @@ public: */ virtual int GetValue() const; + /** + Sets the increment for the control. + + The increment is the number by which the value changes when the up or + down arrow is used. + + The default is 1. + + This function is currently implemented only in wxMSW and does nothing + under the other platforms. + + @since 3.1.6 + + @see wxSpinCtrl::SetIncrement() + */ + void SetIncrement(int value); + /** Sets the range of the spin button. diff --git a/interface/wx/spinctrl.h b/interface/wx/spinctrl.h index bb41ccd909..1786768ac6 100644 --- a/interface/wx/spinctrl.h +++ b/interface/wx/spinctrl.h @@ -145,6 +145,15 @@ public: */ int GetValue() const; + /** + Get the value for increment for a spin control. + + The default value is 1 but it can be changed using SetIncrement(). + + @since 3.1.6 + */ + int GetIncrement() const; + /** Sets the base to use for the numbers in this control. @@ -214,6 +223,22 @@ public: Calling this method doesn't generate any @c wxEVT_SPINCTRL events. */ void SetValue(int value); + + /** + Sets the increment for the control. + + The increment is the number by which the value changes when the up or + down arrow is used. + + The default is 1, but it can be useful to set it to a higher value when + using the control for bigger numbers. + + Note that it is still possible to enter any value (in the valid range) + into the control manually, whatever is the value of the increment. + + @since 3.1.6 + */ + void SetIncrement(int value); }; /** diff --git a/misc/schema/xrc_schema.rnc b/misc/schema/xrc_schema.rnc index 49f56405f8..7d490ae7c8 100644 --- a/misc/schema/xrc_schema.rnc +++ b/misc/schema/xrc_schema.rnc @@ -1482,7 +1482,8 @@ wxSpinButton = stdWindowProperties & [xrc:p="o"] element value {_, t_integer }* & [xrc:p="o"] element min {_, t_integer }* & - [xrc:p="o"] element max {_, t_integer }* + [xrc:p="o"] element max {_, t_integer }* & + [xrc:p="o"] element inc {_, t_integer }* } @@ -1494,7 +1495,8 @@ wxSpinCtrl = [xrc:p="o"] element value {_, t_integer }* & [xrc:p="o"] element min {_, t_integer }* & [xrc:p="o"] element max {_, t_integer }* & - [xrc:p="o"] element base {_, ("10" | "16") }* + [xrc:p="o"] element base {_, ("10" | "16") }* & + [xrc:p="o"] element inc {_, t_integer }* } diff --git a/samples/widgets/spinbtn.cpp b/samples/widgets/spinbtn.cpp index 609fc36ada..65780f4b73 100644 --- a/samples/widgets/spinbtn.cpp +++ b/samples/widgets/spinbtn.cpp @@ -55,11 +55,13 @@ enum SpinBtnPage_SetValue, SpinBtnPage_SetMinAndMax, SpinBtnPage_SetBase, + SpinBtnPage_SetIncrement, SpinBtnPage_CurValueText, SpinBtnPage_ValueText, SpinBtnPage_MinText, SpinBtnPage_MaxText, SpinBtnPage_BaseText, + SpinBtnPage_SetIncrementText, SpinBtnPage_SpinBtn, SpinBtnPage_SpinCtrl, SpinBtnPage_SpinCtrlDouble @@ -103,7 +105,7 @@ protected: void OnButtonSetValue(wxCommandEvent& event); void OnButtonSetMinAndMax(wxCommandEvent& event); void OnButtonSetBase(wxCommandEvent& event); - + void OnButtonSetIncrement(wxCommandEvent &event); void OnCheckOrRadioBox(wxCommandEvent& event); void OnSpinBtn(wxSpinEvent& event); @@ -138,6 +140,9 @@ protected: // and numeric base int m_base; + // the increment + int m_increment; + // the controls // ------------ @@ -159,7 +164,8 @@ protected: wxTextCtrl *m_textValue, *m_textMin, *m_textMax, - *m_textBase; + *m_textBase, + *m_textIncrement; private: wxDECLARE_EVENT_TABLE(); @@ -175,6 +181,7 @@ wxBEGIN_EVENT_TABLE(SpinBtnWidgetsPage, WidgetsPage) EVT_BUTTON(SpinBtnPage_SetValue, SpinBtnWidgetsPage::OnButtonSetValue) EVT_BUTTON(SpinBtnPage_SetMinAndMax, SpinBtnWidgetsPage::OnButtonSetMinAndMax) EVT_BUTTON(SpinBtnPage_SetBase, SpinBtnWidgetsPage::OnButtonSetBase) + EVT_BUTTON(SpinBtnPage_SetIncrement, SpinBtnWidgetsPage::OnButtonSetIncrement) EVT_UPDATE_UI(SpinBtnPage_SetValue, SpinBtnWidgetsPage::OnUpdateUIValueButton) EVT_UPDATE_UI(SpinBtnPage_SetMinAndMax, SpinBtnWidgetsPage::OnUpdateUIMinMaxButton) @@ -227,12 +234,14 @@ SpinBtnWidgetsPage::SpinBtnWidgetsPage(WidgetsBookCtrl *book, m_textValue = m_textMin = m_textMax = - m_textBase = NULL; + m_textBase = + m_textIncrement = NULL; m_min = 0; m_max = 10; m_base = 10; + m_increment = 1; m_sizerSpin = NULL; } @@ -311,6 +320,13 @@ void SpinBtnWidgetsPage::CreateContent() m_textBase->SetValue("10"); sizerMiddle->Add(sizerRow, 0, wxALL | wxGROW, 5); + sizerRow = CreateSizerWithTextAndButton( SpinBtnPage_SetIncrement, + "Set Increment", + SpinBtnPage_SetIncrementText, + &m_textIncrement ); + m_textIncrement->SetValue( "1" ); + sizerMiddle->Add( sizerRow, 0, wxALL | wxGROW, 5 ); + // right pane wxSizer *sizerRight = new wxBoxSizer(wxVERTICAL); sizerRight->SetMinSize(150, 0); @@ -481,6 +497,20 @@ void SpinBtnWidgetsPage::OnButtonSetBase(wxCommandEvent& WXUNUSED(event)) m_sizerSpin->Layout(); } +void SpinBtnWidgetsPage::OnButtonSetIncrement(wxCommandEvent& WXUNUSED (event)) +{ + int increment = wxAtoi( m_textIncrement->GetValue() ); + if ( !increment ) + { + wxLogWarning("Invalid increment value."); + return; + } + + m_increment = increment; + m_spinctrl->SetIncrement(m_increment); + wxLogWarning("Setting increment to %d.", m_increment); +} + void SpinBtnWidgetsPage::OnButtonSetValue(wxCommandEvent& WXUNUSED(event)) { if ( m_textValue->IsEmpty() ) diff --git a/samples/xrc/rc/controls.xrc b/samples/xrc/rc/controls.xrc index 16853bffa9..ed0cadffc9 100644 --- a/samples/xrc/rc/controls.xrc +++ b/samples/xrc/rc/controls.xrc @@ -962,6 +962,7 @@ lay them out using wxSizers, absolute positioning, everything you like! 100 0 + 2 @@ -985,6 +986,7 @@ lay them out using wxSizers, absolute positioning, everything you like! 100 17 16 + 2 diff --git a/src/msw/spinbutt.cpp b/src/msw/spinbutt.cpp index b22d2965df..a6f69cced4 100644 --- a/src/msw/spinbutt.cpp +++ b/src/msw/spinbutt.cpp @@ -288,4 +288,24 @@ bool wxSpinButton::MSWCommand(WXUINT WXUNUSED(cmd), WXWORD WXUNUSED(id)) return false; } +void wxSpinButton::SetIncrement(int value) +{ + UDACCEL accel; + accel.nSec = 0; + accel.nInc = value; + ::SendMessage(GetHwnd(), UDM_SETACCEL, 1, (LPARAM) &accel); +} + +int wxSpinButton::GetIncrement() const +{ + UDACCEL accel; + + // If the message is unsupported, this default value won't be modified and + // will be returned below. + accel.nInc = 1; + + ::SendMessage(GetHwnd(), UDM_GETACCEL, 1, (LPARAM) &accel); + + return accel.nInc; +} #endif // wxUSE_SPINBTN diff --git a/src/msw/spinctrl.cpp b/src/msw/spinctrl.cpp index 2fd2525a67..202351ed4f 100644 --- a/src/msw/spinctrl.cpp +++ b/src/msw/spinctrl.cpp @@ -877,5 +877,4 @@ void wxSpinCtrl::DoClientToScreen(int *x, int *y) const { wxWindow::MSWDoClientToScreen(GetBuddyHwnd(), x, y); } - #endif // wxUSE_SPINCTRL diff --git a/src/osx/cocoa/spinbutt.mm b/src/osx/cocoa/spinbutt.mm index 6649a31e4b..3689ff129c 100644 --- a/src/osx/cocoa/spinbutt.mm +++ b/src/osx/cocoa/spinbutt.mm @@ -51,6 +51,8 @@ public : virtual void SetValue(wxInt32 v) wxOVERRIDE; virtual void SetMinimum(wxInt32 v) wxOVERRIDE; virtual void SetMaximum(wxInt32 v) wxOVERRIDE; + virtual void SetIncrement(int value) wxOVERRIDE; + virtual int GetIncrement() const wxOVERRIDE; virtual void controlAction(WXWidget slf, void* _cmd, void *sender) wxOVERRIDE; virtual void mouseEvent(WX_NSEvent event, WXWidget slf, void* _cmd) wxOVERRIDE; private: @@ -123,6 +125,16 @@ void wxSpinButtonCocoaImpl::controlAction( WXWidget WXUNUSED(slf), void *WXUNUSE } } +void wxSpinButtonCocoaImpl::SetIncrement(int value) +{ + [(NSStepper*)m_osxView setIncrement:value]; +} + +int wxSpinButtonCocoaImpl::GetIncrement() const +{ + return [(NSStepper *) m_osxView increment]; +} + wxWidgetImplType* wxWidgetImpl::CreateSpinButton( wxWindowMac* wxpeer, wxWindowMac* WXUNUSED(parent), wxWindowID WXUNUSED(id), diff --git a/src/osx/cocoa/window.mm b/src/osx/cocoa/window.mm index 82efa9ae54..be92a9b632 100644 --- a/src/osx/cocoa/window.mm +++ b/src/osx/cocoa/window.mm @@ -181,8 +181,10 @@ NSRect wxOSXGetFrameForControl( wxWindowMac* window , const wxPoint& pos , const - (double)minValue; - (double)maxValue; +- (int)increment; - (void)setMinValue:(double)aDouble; - (void)setMaxValue:(double)aDouble; +- (void)setIncrement:(int)value; - (void)sizeToFit; @@ -3420,6 +3422,23 @@ wxInt32 wxWidgetCocoaImpl::GetMinimum() const return 0; } +void wxWidgetCocoaImpl::SetIncrement(int value) +{ + if ( [m_osxView respondsToSelector:@selector(setIncrement:)] ) + { + [m_osxView setIncrement:value]; + } +} + +int wxWidgetCocoaImpl::GetIncrement() const +{ + if( [m_osxView respondsToSelector:@selector(increment)] ) + { + return (int) [m_osxView increment]; + } + return 0; +} + wxInt32 wxWidgetCocoaImpl::GetMaximum() const { if ( [m_osxView respondsToSelector:@selector(maxValue)] ) diff --git a/src/osx/spinbutt_osx.cpp b/src/osx/spinbutt_osx.cpp index 306576705b..ec06f25e06 100644 --- a/src/osx/spinbutt_osx.cpp +++ b/src/osx/spinbutt_osx.cpp @@ -142,4 +142,14 @@ void wxSpinButton::TriggerScrollEvent(wxEventType scrollEvent) SendThumbTrackEvent() ; } +void wxSpinButton::SetIncrement(int value) +{ + GetPeer()->SetIncrement( value ); +} + +int wxSpinButton::GetIncrement() const +{ + return GetPeer()->GetIncrement(); +} + #endif // wxUSE_SPINBTN diff --git a/src/xrc/xh_spin.cpp b/src/xrc/xh_spin.cpp index 70a5700330..6bd3c4a9e9 100644 --- a/src/xrc/xh_spin.cpp +++ b/src/xrc/xh_spin.cpp @@ -22,6 +22,7 @@ static const long DEFAULT_VALUE = 0; static const long DEFAULT_MIN = 0; static const long DEFAULT_MAX = 100; +static const int DEFAULT_INCREMENT = 1; wxIMPLEMENT_DYNAMIC_CLASS(wxSpinButtonXmlHandler, wxXmlResourceHandler); @@ -48,6 +49,7 @@ wxObject *wxSpinButtonXmlHandler::DoCreateResource() control->SetValue(GetLong( wxT("value"), DEFAULT_VALUE)); control->SetRange(GetLong( wxT("min"), DEFAULT_MIN), GetLong(wxT("max"), DEFAULT_MAX)); + control->SetValue(GetLong(wxT( "inc" ), DEFAULT_INCREMENT)); SetupWindow(control); return control; @@ -98,6 +100,7 @@ wxObject *wxSpinCtrlXmlHandler::DoCreateResource() GetLong(wxT("max"), DEFAULT_MAX), GetLong(wxT("value"), DEFAULT_VALUE), GetName()); + control->SetIncrement(GetLong(wxT("inc"), DEFAULT_INCREMENT)); const long base = GetLong(wxS("base"), 10); if ( base != 10 ) diff --git a/tests/controls/spinctrltest.cpp b/tests/controls/spinctrltest.cpp index e7262e83ed..5c22c62817 100644 --- a/tests/controls/spinctrltest.cpp +++ b/tests/controls/spinctrltest.cpp @@ -368,4 +368,30 @@ TEST_CASE_METHOD(SpinCtrlTestCase3, "SpinCtrl::SetValueInsideEventHandler", "[sp #endif // wxUSE_UIACTIONSIMULATOR } +TEST_CASE_METHOD(SpinCtrlTestCase1, "SpinCtrl::Increment", "[spinctrl]") +{ +#if wxUSE_UIACTIONSIMULATOR + m_spin->Create(wxTheApp->GetTopWindow(), wxID_ANY, "", + wxDefaultPosition, wxDefaultSize, + wxSP_ARROW_KEYS | wxSP_WRAP); + + wxUIActionSimulator sim; + + CHECK( m_spin->GetIncrement() == 1 ); + + m_spin->SetFocus(); + wxYield(); + m_spin->SetIncrement( 5 ); + sim.Char(WXK_UP); + + wxYield(); + + CHECK(m_spin->GetValue() == 5); + + int increment = m_spin->GetIncrement(); + + CHECK( increment == 5 ); +#endif +} + #endif