added wxSpinCtrlDouble (slightly modified patch 1835864)

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@52612 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2008-03-18 14:04:19 +00:00
parent 04edbb2343
commit 8cd6a9ad50
10 changed files with 947 additions and 353 deletions

View File

@@ -239,6 +239,7 @@ All (GUI):
- Added wxNotificationMessage class for non-intrusive notifications - Added wxNotificationMessage class for non-intrusive notifications
- Added wxWindow::Show/HideWithEffect() - Added wxWindow::Show/HideWithEffect()
- Added wxWrapSizer (Arne Steinarson) - Added wxWrapSizer (Arne Steinarson)
- Added wxSpinCtrlDouble (John Labenski)
- Added wxNativeContainerWindow to allow embedding wx into native windows - Added wxNativeContainerWindow to allow embedding wx into native windows
- Added custom controls support to wxFileDialog (Diaa Sami and Marcin Wojdyr) - Added custom controls support to wxFileDialog (Diaa Sami and Marcin Wojdyr)
- Added wxDC::StretchBlit() for wxMac and wxMSW (Vince Harron). - Added wxDC::StretchBlit() for wxMac and wxMSW (Vince Harron).

View File

@@ -99,6 +99,7 @@ extern WXDLLIMPEXP_CORE const wxEventType wxEVT_COMMAND_TOOL_RCLICKED;
extern WXDLLIMPEXP_CORE const wxEventType wxEVT_COMMAND_TOOL_DROPDOWN_CLICKED; extern WXDLLIMPEXP_CORE const wxEventType wxEVT_COMMAND_TOOL_DROPDOWN_CLICKED;
extern WXDLLIMPEXP_CORE const wxEventType wxEVT_COMMAND_TOOL_ENTER; extern WXDLLIMPEXP_CORE const wxEventType wxEVT_COMMAND_TOOL_ENTER;
extern WXDLLIMPEXP_CORE const wxEventType wxEVT_COMMAND_SPINCTRL_UPDATED; extern WXDLLIMPEXP_CORE const wxEventType wxEVT_COMMAND_SPINCTRL_UPDATED;
extern WXDLLIMPEXP_CORE const wxEventType wxEVT_COMMAND_SPINCTRLDOUBLE_UPDATED;
// Sockets and timers send events, too // Sockets and timers send events, too
extern WXDLLIMPEXP_BASE const wxEventType wxEVT_SOCKET; extern WXDLLIMPEXP_BASE const wxEventType wxEVT_SOCKET;

View File

@@ -25,27 +25,25 @@
class WXDLLIMPEXP_FWD_CORE wxSpinButton; class WXDLLIMPEXP_FWD_CORE wxSpinButton;
class WXDLLIMPEXP_FWD_CORE wxTextCtrl; class WXDLLIMPEXP_FWD_CORE wxTextCtrl;
class wxSpinCtrlText; // wxTextCtrl used for the wxSpinCtrlGenericBase
// The !wxUSE_SPINBTN version's GetValue() function conflicts with the
// wxTextCtrl's GetValue() and so you have to input a dummy int value.
#define wxSPINCTRL_GETVALUE_FIX
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// wxSpinCtrl is a combination of wxTextCtrl and wxSpinButton // wxSpinCtrlGeneric is a combination of wxTextCtrl and wxSpinButton
//
// This class manages a double valued generic spinctrl through the DoGet/SetXXX
// functions that are made public as Get/SetXXX functions for int or double
// for the wxSpinCtrl and wxSpinCtrlDouble classes respectively to avoid
// function ambiguity.
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
class WXDLLEXPORT wxSpinCtrl : public wxControl class WXDLLEXPORT wxSpinCtrlGenericBase : public wxSpinCtrlBase
{ {
public: public:
wxSpinCtrl() { Init(); } wxSpinCtrlGenericBase() { Init(); }
wxSpinCtrl(wxWindow *parent,
wxWindowID id = wxID_ANY,
const wxString& value = wxEmptyString,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxSP_ARROW_KEYS,
int min = 0, int max = 100, int initial = 0,
const wxString& name = _T("wxSpinCtrl"))
{
Init();
Create(parent, id, value, pos, size, style, min, max, initial, name);
}
bool Create(wxWindow *parent, bool Create(wxWindow *parent,
wxWindowID id = wxID_ANY, wxWindowID id = wxID_ANY,
@@ -53,21 +51,29 @@ public:
const wxPoint& pos = wxDefaultPosition, const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize, const wxSize& size = wxDefaultSize,
long style = wxSP_ARROW_KEYS, long style = wxSP_ARROW_KEYS,
int min = 0, int max = 100, int initial = 0, double min = 0, double max = 100, double initial = 0, double inc = 1,
const wxString& name = _T("wxSpinCtrl")); const wxString& name = _T("wxSpinCtrl"));
virtual ~wxSpinCtrl(); virtual ~wxSpinCtrlGenericBase();
// operations
void SetValue(int val);
void SetValue(const wxString& text);
void SetRange(int min, int max);
void SetSelection(long from, long to);
// accessors // accessors
int GetValue() const; // T GetValue() const
int GetMin() const; // T GetMin() const
int GetMax() const; // T GetMax() const
// T GetIncrement() const
virtual bool GetSnapToTicks() const { return m_snap_to_ticks; }
// unsigned GetDigits() const - wxSpinCtrlDouble only
// operations
virtual void SetValue(const wxString& text);
// void SetValue(T val)
// void SetRange(T minVal, T maxVal)
// void SetIncrement(T inc)
virtual void SetSnapToTicks(bool snap_to_ticks);
// void SetDigits(unsigned digits) - wxSpinCtrlDouble only
// Select text in the textctrl
void SetSelection(long from, long to);
// implementation from now on // implementation from now on
@@ -77,47 +83,145 @@ public:
virtual bool Reparent(wxWindow *newParent); virtual bool Reparent(wxWindow *newParent);
// get the subcontrols // get the subcontrols
wxTextCtrl *GetText() const { return m_text; } wxTextCtrl *GetText() const { return m_textCtrl; }
wxSpinButton *GetSpinButton() const { return m_btn; } wxSpinButton *GetSpinButton() const { return m_spinButton; }
// set the value of the text (only) // forwarded events from children windows
void SetTextValue(int val); void OnSpinButton(wxSpinEvent& event);
void OnTextEnter(wxCommandEvent& event);
void OnTextChar(wxKeyEvent& event);
// put the numeric value of the string in the text ctrl into val and return friend class wxSpinCtrlText;
// true or return false if the text ctrl doesn't contain a number or if the
// number is out of range
bool GetTextValue(int *val) const;
protected: protected:
// override the base class virtuals involved into geometry calculations // override the base class virtuals involved into geometry calculations
virtual wxSize DoGetBestSize() const; virtual wxSize DoGetBestSize() const;
virtual void DoMoveWindow(int x, int y, int width, int height); virtual void DoMoveWindow(int x, int y, int width, int height);
// generic double valued functions
double DoGetValue() const { return m_value; }
bool DoSetValue(double val);
void DoSetRange(double min_val, double max_val);
void DoSetIncrement(double inc);
// Ensure that the textctrl shows correct value
void SyncSpinToText();
// Send the correct event type
virtual void DoSendEvent() = 0;
bool InRange(double n) const { return (n >= m_min) && (n <= m_max); }
double m_value;
double m_min;
double m_max;
double m_increment;
bool m_snap_to_ticks;
wxString m_format;
int m_spin_value;
// the subcontrols
wxTextCtrl *m_textCtrl;
wxSpinButton *m_spinButton;
private:
// common part of all ctors // common part of all ctors
void Init(); void Init();
private:
// the subcontrols
wxTextCtrl *m_text;
wxSpinButton *m_btn;
private:
DECLARE_DYNAMIC_CLASS(wxSpinCtrl)
}; };
#else // !wxUSE_SPINBTN #else // !wxUSE_SPINBTN
#define wxSPINCTRL_GETVALUE_FIX int = 1
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// wxSpinCtrl is just a text control // wxSpinCtrl is just a text control
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
#include "wx/textctrl.h" #include "wx/textctrl.h"
class WXDLLEXPORT wxSpinCtrl : public wxTextCtrl class WXDLLEXPORT wxSpinCtrlGenericBase : public wxTextCtrl
{ {
public: public:
wxSpinCtrl() { Init(); } wxSpinCtrlGenericBase() : m_value(0), m_min(0), m_max(100),
m_increment(1), m_snap_to_ticks(false),
m_format(wxT("%g")) { }
bool Create(wxWindow *parent,
wxWindowID id = wxID_ANY,
const wxString& value = wxEmptyString,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxSP_ARROW_KEYS,
double min = 0, double max = 100, double initial = 0, double inc = 1,
const wxString& name = _T("wxSpinCtrl"))
{
m_min = min;
m_max = max;
m_value = initial;
m_increment = inc;
bool ok = wxTextCtrl::Create(parent, id, value, pos, size, style,
wxDefaultValidator, name);
DoSetValue(initial);
return ok;
}
// accessors
// T GetValue() const
// T GetMin() const
// T GetMax() const
// T GetIncrement() const
virtual bool GetSnapToTicks() const { return m_snap_to_ticks; }
// unsigned GetDigits() const - wxSpinCtrlDouble only
// operations
virtual void SetValue(const wxString& text) { wxTextCtrl::SetValue(text); }
// void SetValue(T val)
// void SetRange(T minVal, T maxVal)
// void SetIncrement(T inc)
virtual void SetSnapToTicks(bool snap_to_ticks) { m_snap_to_ticks = snap_to_ticks; }
// void SetDigits(unsigned digits) - wxSpinCtrlDouble only
// Select text in the textctrl
//void SetSelection(long from, long to);
protected:
// generic double valued
double DoGetValue() const
{
double n;
if ( (wxSscanf(wxTextCtrl::GetValue(), wxT("%lf"), &n) != 1) )
n = INT_MIN;
return n;
}
bool DoSetValue(double val) { wxTextCtrl::SetValue(wxString::Format(m_format.c_str(), val)); return true; }
void DoSetRange(double min_val, double max_val) { m_min = min_val; m_max = max_val; }
void DoSetIncrement(double inc) { m_increment = inc; } // Note: unused
double m_value;
double m_min;
double m_max;
double m_increment;
bool m_snap_to_ticks;
wxString m_format;
};
#endif // wxUSE_SPINBTN/!wxUSE_SPINBTN
#if !defined(wxHAS_NATIVE_SPINCTRL)
//-----------------------------------------------------------------------------
// wxSpinCtrl
//-----------------------------------------------------------------------------
class WXDLLIMPEXP_CORE wxSpinCtrl : public wxSpinCtrlGenericBase
{
public:
wxSpinCtrl() {}
wxSpinCtrl(wxWindow *parent, wxSpinCtrl(wxWindow *parent,
wxWindowID id = wxID_ANY, wxWindowID id = wxID_ANY,
const wxString& value = wxEmptyString, const wxString& value = wxEmptyString,
@@ -139,45 +243,84 @@ public:
int min = 0, int max = 100, int initial = 0, int min = 0, int max = 100, int initial = 0,
const wxString& name = _T("wxSpinCtrl")) const wxString& name = _T("wxSpinCtrl"))
{ {
SetRange(min, max); return wxSpinCtrlGenericBase::Create(parent, id, value, pos, size, style, min, max, initial, 1, name);
bool ok = wxTextCtrl::Create(parent, id, value, pos, size, style,
wxDefaultValidator, name);
SetValue(initial);
return ok;
} }
// accessors // accessors
int GetValue(int WXUNUSED(dummy) = 1) const int GetValue(wxSPINCTRL_GETVALUE_FIX) const { return int(DoGetValue() + 0.5); }
{ int GetMin() const { return int(m_min + 0.5); }
int n; int GetMax() const { return int(m_max + 0.5); }
if ( (wxSscanf(wxTextCtrl::GetValue(), wxT("%d"), &n) != 1) ) int GetIncrement() const { return int(m_increment + 0.5); }
n = INT_MIN;
return n;
}
int GetMin() const { return m_min; }
int GetMax() const { return m_max; }
// operations // operations
void SetValue(const wxString& value) { wxTextCtrl::SetValue(value); } void SetValue(const wxString& value) { wxSpinCtrlGenericBase::SetValue(value); } // visibility problem w/ gcc
void SetValue(int val) { wxString s; s << val; wxTextCtrl::SetValue(s); } void SetValue( int value ) { DoSetValue(value); }
void SetRange(int min, int max) { m_min = min; m_max = max; } void SetRange( int minVal, int maxVal ) { DoSetRange(minVal, maxVal); }
void SetIncrement( double inc ) { DoSetIncrement(inc); }
protected: protected:
// initialize m_min/max with the default values virtual void DoSendEvent();
void Init() { SetRange(0, 100); }
int m_min;
int m_max;
private: private:
DECLARE_DYNAMIC_CLASS(wxSpinCtrl) DECLARE_DYNAMIC_CLASS(wxSpinCtrl)
}; };
#endif // wxUSE_SPINBTN/!wxUSE_SPINBTN #endif // wxHAS_NATIVE_SPINCTRL
//-----------------------------------------------------------------------------
// wxSpinCtrlDouble
//-----------------------------------------------------------------------------
class WXDLLIMPEXP_CORE wxSpinCtrlDouble : public wxSpinCtrlGenericBase
{
public:
wxSpinCtrlDouble() : m_digits(0) { }
wxSpinCtrlDouble(wxWindow *parent,
wxWindowID id = wxID_ANY,
const wxString& value = wxEmptyString,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxSP_ARROW_KEYS,
double min = 0, double max = 100, double initial = 0, double inc = 1,
const wxString& name = _T("wxSpinCtrlDouble"))
{
m_digits = 0;
Create(parent, id, value, pos, size, style, min, max, initial, inc, name);
}
bool Create(wxWindow *parent,
wxWindowID id = wxID_ANY,
const wxString& value = wxEmptyString,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxSP_ARROW_KEYS,
double min = 0, double max = 100, double initial = 0, double inc = 1,
const wxString& name = _T("wxSpinCtrlDouble"))
{
return wxSpinCtrlGenericBase::Create(parent, id, value, pos, size, style, min, max, initial, inc, name);
}
// accessors
double GetValue(wxSPINCTRL_GETVALUE_FIX) const { return DoGetValue(); }
double GetMin() const { return m_min; }
double GetMax() const { return m_max; }
double GetIncrement() const { return m_increment; }
unsigned GetDigits() const { return m_digits; }
// operations
void SetValue(const wxString& value) { wxSpinCtrlGenericBase::SetValue(value); } // visibility problem w/ gcc
void SetValue(double value) { DoSetValue(value); }
void SetRange(double minVal, double maxVal) { DoSetRange(minVal, maxVal); }
void SetIncrement(double inc) { DoSetIncrement(inc); }
void SetDigits(unsigned digits);
protected:
virtual void DoSendEvent();
unsigned m_digits;
private:
DECLARE_DYNAMIC_CLASS(wxSpinCtrlDouble)
};
#endif // _WX_GENERIC_SPINCTRL_H_ #endif // _WX_GENERIC_SPINCTRL_H_

View File

@@ -12,52 +12,67 @@
#define _WX_GTK_SPINCTRL_H_ #define _WX_GTK_SPINCTRL_H_
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// wxSpinCtrl // wxSpinCtrlGTKBase - Base class for GTK versions of the wxSpinCtrl[Double]
//
// This class manages a double valued GTK spinctrl through the DoGet/SetXXX
// functions that are made public as Get/SetXXX functions for int or double
// for the wxSpinCtrl and wxSpinCtrlDouble classes respectively to avoid
// function ambiguity.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
class WXDLLIMPEXP_CORE wxSpinCtrl : public wxControl class WXDLLIMPEXP_CORE wxSpinCtrlGTKBase : public wxSpinCtrlBase
{ {
public: public:
wxSpinCtrl(); wxSpinCtrlGTKBase() : m_value(0) {}
wxSpinCtrl(wxWindow *parent,
wxWindowID id = -1,
const wxString& value = wxEmptyString,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxSP_ARROW_KEYS,
int min = 0, int max = 100, int initial = 0,
const wxString& name = _T("wxSpinCtrl"))
{
Create(parent, id, value, pos, size, style, min, max, initial, name);
}
bool Create(wxWindow *parent, bool Create(wxWindow *parent,
wxWindowID id = -1, wxWindowID id = wxID_ANY,
const wxString& value = wxEmptyString, const wxString& value = wxEmptyString,
const wxPoint& pos = wxDefaultPosition, const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize, const wxSize& size = wxDefaultSize,
long style = wxSP_ARROW_KEYS, long style = wxSP_ARROW_KEYS,
int min = 0, int max = 100, int initial = 0, double min = 0, double max = 100, double initial = 0, double inc = 1,
const wxString& name = _T("wxSpinCtrl")); const wxString& name = _T("wxSpinCtrlGTKBase"));
void SetValue(const wxString& text); // wxSpinCtrl(Double) methods call DoXXX functions of the same name
// accessors
// T GetValue() const
// T GetMin() const
// T GetMax() const
// T GetIncrement() const
virtual bool GetSnapToTicks() const;
// operations
virtual void SetValue(const wxString& value);
// void SetValue(T val)
// void SetRange(T minVal, T maxVal)
// void SetIncrement(T inc)
void SetSnapToTicks( bool snap_to_ticks );
// Select text in the textctrl
void SetSelection(long from, long to); void SetSelection(long from, long to);
virtual int GetValue() const;
virtual void SetValue( int value );
virtual void SetRange( int minVal, int maxVal );
virtual int GetMin() const;
virtual int GetMax() const;
static wxVisualAttributes static wxVisualAttributes
GetClassDefaultAttributes(wxWindowVariant variant = wxWINDOW_VARIANT_NORMAL); GetClassDefaultAttributes(wxWindowVariant variant = wxWINDOW_VARIANT_NORMAL);
// implementation // implementation
void OnChar( wxKeyEvent &event ); void OnChar( wxKeyEvent &event );
int m_pos; double m_value; // public for GTK callback function
protected: protected:
double DoGetValue() const;
double DoGetMin() const;
double DoGetMax() const;
double DoGetIncrement() const;
void DoSetValue(double val);
void DoSetValue(const wxString& strValue);
void DoSetRange(double min_val, double max_val);
void DoSetIncrement(double inc);
void GtkDisableEvents() const; void GtkDisableEvents() const;
void GtkEnableEvents() const; void GtkEnableEvents() const;
@@ -69,8 +84,106 @@ protected:
virtual bool UseGTKStyleBase() const { return true; } virtual bool UseGTKStyleBase() const { return true; }
private: private:
DECLARE_DYNAMIC_CLASS(wxSpinCtrl) DECLARE_DYNAMIC_CLASS(wxSpinCtrlGTKBase)
DECLARE_EVENT_TABLE() DECLARE_EVENT_TABLE()
}; };
//-----------------------------------------------------------------------------
// wxSpinCtrl - An integer valued spin control
//-----------------------------------------------------------------------------
class WXDLLIMPEXP_CORE wxSpinCtrl : public wxSpinCtrlGTKBase
{
public:
wxSpinCtrl() {}
wxSpinCtrl(wxWindow *parent,
wxWindowID id = wxID_ANY,
const wxString& value = wxEmptyString,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxSP_ARROW_KEYS,
int min = 0, int max = 100, int initial = 0,
const wxString& name = _T("wxSpinCtrl"))
{
Create(parent, id, value, pos, size, style, min, max, initial, name);
}
bool Create(wxWindow *parent,
wxWindowID id = wxID_ANY,
const wxString& value = wxEmptyString,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxSP_ARROW_KEYS,
int min = 0, int max = 100, int initial = 0,
const wxString& name = _T("wxSpinCtrl"))
{
return wxSpinCtrlGTKBase::Create(parent, id, value, pos, size, style, min, max, initial, 1, name);
}
// accessors
int GetValue() const { return int(DoGetValue() + 0.5); }
int GetMin() const { return int(DoGetMin() + 0.5); }
int GetMax() const { return int(DoGetMax() + 0.5); }
int GetIncrement() const { return int(DoGetIncrement() + 0.5); }
// operations
void SetValue(const wxString& value) { wxSpinCtrlGTKBase::SetValue(value); } // visibility problem w/ gcc
void SetValue( int value ) { DoSetValue(value); }
void SetRange( int minVal, int maxVal ) { DoSetRange(minVal, maxVal); }
void SetIncrement( double inc ) { DoSetIncrement(inc); }
private:
DECLARE_DYNAMIC_CLASS(wxSpinCtrl)
};
//-----------------------------------------------------------------------------
// wxSpinCtrlDouble - a double valued spin control
//-----------------------------------------------------------------------------
class WXDLLIMPEXP_CORE wxSpinCtrlDouble : public wxSpinCtrlGTKBase
{
public:
wxSpinCtrlDouble() {}
wxSpinCtrlDouble(wxWindow *parent,
wxWindowID id = wxID_ANY,
const wxString& value = wxEmptyString,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxSP_ARROW_KEYS,
double min = 0, double max = 100, double initial = 0, double inc = 1,
const wxString& name = _T("wxSpinCtrlDouble"))
{
Create(parent, id, value, pos, size, style, min, max, initial, inc, name);
}
bool Create(wxWindow *parent,
wxWindowID id = wxID_ANY,
const wxString& value = wxEmptyString,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxSP_ARROW_KEYS,
double min = 0, double max = 100, double initial = 0, double inc = 1,
const wxString& name = _T("wxSpinCtrlDouble"))
{
return wxSpinCtrlGTKBase::Create(parent, id, value, pos, size, style, min, max, initial, inc, name);
}
// accessors
double GetValue() const { return DoGetValue(); }
double GetMin() const { return DoGetMin(); }
double GetMax() const { return DoGetMax(); }
double GetIncrement() const { return DoGetIncrement(); }
unsigned GetDigits() const;
// operations
void SetValue(const wxString& value) { wxSpinCtrlGTKBase::SetValue(value); } // visibility problem w/ gcc
void SetValue(double value) { DoSetValue(value); }
void SetRange(double minVal, double maxVal) { DoSetRange(minVal, maxVal); }
void SetIncrement(double inc) { DoSetIncrement(inc); }
void SetDigits(unsigned digits);
private:
DECLARE_DYNAMIC_CLASS(wxSpinCtrlDouble)
};
#endif // _WX_GTK_SPINCTRL_H_ #endif // _WX_GTK_SPINCTRL_H_

View File

@@ -102,12 +102,19 @@ public:
{ {
} }
wxSpinEvent(const wxSpinEvent& event) : wxNotifyEvent(event) {}
// get the current value of the control // get the current value of the control
int GetValue() const { return m_commandInt; }
void SetValue(int value) { m_commandInt = value; }
int GetPosition() const { return m_commandInt; } int GetPosition() const { return m_commandInt; }
void SetPosition(int pos) { m_commandInt = pos; } void SetPosition(int pos) { m_commandInt = pos; }
virtual wxEvent *Clone() const { return new wxSpinEvent(*this); }
private: private:
DECLARE_DYNAMIC_CLASS_NO_COPY(wxSpinEvent) DECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxSpinEvent)
}; };
typedef void (wxEvtHandler::*wxSpinEventFunction)(wxSpinEvent&); typedef void (wxEvtHandler::*wxSpinEventFunction)(wxSpinEvent&);

View File

@@ -19,64 +19,119 @@
#include "wx/spinbutt.h" // should make wxSpinEvent visible to the app #include "wx/spinbutt.h" // should make wxSpinEvent visible to the app
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// a spin ctrl is a text control with a spin button which is usually used to // A spin ctrl is a text control with a spin button which is usually used to
// prompt the user for a numeric input // prompt the user for a numeric input.
// There are two kinds for number types T=integer or T=double.
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
/* there is no generic base class for this control because it's imlpemented
very differently under MSW and other platforms
class WXDLLEXPORT wxSpinCtrlBase : public wxControl class WXDLLEXPORT wxSpinCtrlBase : public wxControl
{ {
public: public:
wxSpinCtrlBase() { Init(); } wxSpinCtrlBase() {}
// accessors // accessor functions that derived classes are expected to have
virtual int GetValue() const = 0; // T GetValue() const
virtual int GetMin() const { return m_min; } // T GetMin() const
virtual int GetMax() const { return m_max; } // T GetMax() const
// T GetIncrement() const
virtual bool GetSnapToTicks() const = 0;
// unsigned GetDigits() const - wxSpinCtrlDouble only
// operations // operation functions that derived classes are expected to have
virtual void SetValue(const wxString& value) = 0; virtual void SetValue(const wxString& value) = 0;
virtual void SetValue(int val) = 0; // void SetValue(T val)
virtual void SetRange(int minVal, int maxVal) = 0; // void SetRange(T minVal, T maxVal)
// void SetIncrement(T inc)
virtual void SetSnapToTicks(bool snap_to_ticks) = 0;
// void SetDigits(unsigned digits) - wxSpinCtrlDouble only
// as the wxTextCtrl method // Select text in the textctrl
virtual void SetSelection(long from, long to) = 0; virtual void SetSelection(long from, long to) = 0;
protected: private:
// initialize m_min/max with the default values DECLARE_NO_COPY_CLASS(wxSpinCtrlBase)
void Init() { m_min = 0; m_max = 100; }
int m_min;
int m_max;
}; };
*/
// ----------------------------------------------------------------------------
// wxSpinDoubleEvent - a wxSpinEvent for double valued controls
// ----------------------------------------------------------------------------
class WXDLLEXPORT wxSpinDoubleEvent : public wxNotifyEvent
{
public:
wxSpinDoubleEvent(wxEventType commandType = wxEVT_NULL, int winid = 0,
double value = 0)
: wxNotifyEvent(commandType, winid), m_value(value)
{
}
wxSpinDoubleEvent(const wxSpinDoubleEvent& event)
: wxNotifyEvent(event), m_value(event.GetValue())
{
}
double GetValue() const { return m_value; }
void SetValue(double value) { m_value = value; }
virtual wxEvent *Clone() const { return new wxSpinDoubleEvent(*this); }
protected:
double m_value;
private:
DECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxSpinDoubleEvent)
};
// ----------------------------------------------------------------------------
// wxSpinDoubleEvent event type, see also wxSpinEvent in wx/spinbutt.h
// ----------------------------------------------------------------------------
typedef void (wxEvtHandler::*wxSpinDoubleEventFunction)(wxSpinDoubleEvent&);
#define wxSpinDoubleEventHandler(func) \
(wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxSpinDoubleEventFunction, &func)
// macros for handling spinctrl events
#define EVT_SPINCTRL(id, fn) \
wx__DECLARE_EVT1(wxEVT_COMMAND_SPINCTRL_UPDATED, id, wxSpinEventHandler(fn))
#define EVT_SPINCTRLDOUBLE(id, fn) \
wx__DECLARE_EVT1(wxEVT_COMMAND_SPINCTRLDOUBLE_UPDATED, id, wxSpinDoubleEventHandler(fn))
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// include the platform-dependent class implementation // include the platform-dependent class implementation
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
#if defined(__WXUNIVERSAL__) // we may have a native wxSpinCtrl implementation, native wxSpinCtrl and
#include "wx/generic/spinctlg.h" // wxSpinCtrlDouble implementations or neither, define the appropriate symbols
// and include the generic version if necessary to provide the missing class(es)
#if defined(__WXUNIVERSAL__) || \
defined(__WXMOTIF__) || \
defined(__WXCOCOA__)
// nothing, use generic controls
#elif defined(__WXMSW__) #elif defined(__WXMSW__)
#define wxHAS_NATIVE_SPINCTRL
#include "wx/msw/spinctrl.h" #include "wx/msw/spinctrl.h"
#elif defined(__WXPM__) #elif defined(__WXPM__)
#define wxHAS_NATIVE_SPINCTRL
#include "wx/os2/spinctrl.h" #include "wx/os2/spinctrl.h"
#elif defined(__WXGTK20__) #elif defined(__WXGTK20__)
#define wxHAS_NATIVE_SPINCTRL
#define wxHAS_NATIVE_SPINCTRLDOUBLE
#include "wx/gtk/spinctrl.h" #include "wx/gtk/spinctrl.h"
#elif defined(__WXGTK__) #elif defined(__WXGTK__)
#define wxHAS_NATIVE_SPINCTRL
#include "wx/gtk1/spinctrl.h" #include "wx/gtk1/spinctrl.h"
#elif defined(__WXMOTIF__)
#include "wx/generic/spinctlg.h"
#elif defined(__WXMAC__) #elif defined(__WXMAC__)
#define wxHAS_NATIVE_SPINCTRL
#include "wx/mac/spinctrl.h" #include "wx/mac/spinctrl.h"
#elif defined(__WXCOCOA__)
#include "wx/generic/spinctlg.h"
#endif // platform #endif // platform
#define EVT_SPINCTRL(id, fn) \ #if !defined(wxHAS_NATIVE_SPINCTRL) || !defined(wxHAS_NATIVE_SPINCTRLDOUBLE)
wx__DECLARE_EVT1(wxEVT_COMMAND_SPINCTRL_UPDATED, id, wxSpinEventHandler(fn)) #include "wx/generic/spinctlg.h"
#endif
#endif // wxUSE_SPINCTRL #endif // wxUSE_SPINCTRL

View File

@@ -63,7 +63,8 @@ enum
SpinBtnPage_MinText, SpinBtnPage_MinText,
SpinBtnPage_MaxText, SpinBtnPage_MaxText,
SpinBtnPage_SpinBtn, SpinBtnPage_SpinBtn,
SpinBtnPage_SpinCtrl SpinBtnPage_SpinCtrl,
SpinBtnPage_SpinCtrlDouble
}; };
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@@ -78,6 +79,7 @@ public:
virtual wxControl *GetWidget() const { return m_spinbtn; } virtual wxControl *GetWidget() const { return m_spinbtn; }
virtual wxControl *GetWidget2() const { return m_spinctrl; } virtual wxControl *GetWidget2() const { return m_spinctrl; }
virtual wxControl *GetWidget3() const { return m_spinctrldbl; }
virtual void RecreateWidget() { CreateSpin(); } virtual void RecreateWidget() { CreateSpin(); }
// lazy creation of the content // lazy creation of the content
@@ -96,6 +98,7 @@ protected:
void OnSpinBtnUp(wxSpinEvent& event); void OnSpinBtnUp(wxSpinEvent& event);
void OnSpinBtnDown(wxSpinEvent& event); void OnSpinBtnDown(wxSpinEvent& event);
void OnSpinCtrl(wxSpinEvent& event); void OnSpinCtrl(wxSpinEvent& event);
void OnSpinCtrlDouble(wxSpinDoubleEvent& event);
void OnSpinText(wxCommandEvent& event); void OnSpinText(wxCommandEvent& event);
void OnUpdateUIValueButton(wxUpdateUIEvent& event); void OnUpdateUIValueButton(wxUpdateUIEvent& event);
@@ -128,6 +131,7 @@ protected:
// the spinbtn and the spinctrl and the sizer containing them // the spinbtn and the spinctrl and the sizer containing them
wxSpinButton *m_spinbtn; wxSpinButton *m_spinbtn;
wxSpinCtrl *m_spinctrl; wxSpinCtrl *m_spinctrl;
wxSpinCtrlDouble *m_spinctrldbl;
wxSizer *m_sizerSpin; wxSizer *m_sizerSpin;
@@ -161,7 +165,9 @@ BEGIN_EVENT_TABLE(SpinBtnWidgetsPage, WidgetsPage)
EVT_SPIN_UP(SpinBtnPage_SpinBtn, SpinBtnWidgetsPage::OnSpinBtnUp) EVT_SPIN_UP(SpinBtnPage_SpinBtn, SpinBtnWidgetsPage::OnSpinBtnUp)
EVT_SPIN_DOWN(SpinBtnPage_SpinBtn, SpinBtnWidgetsPage::OnSpinBtnDown) EVT_SPIN_DOWN(SpinBtnPage_SpinBtn, SpinBtnWidgetsPage::OnSpinBtnDown)
EVT_SPINCTRL(SpinBtnPage_SpinCtrl, SpinBtnWidgetsPage::OnSpinCtrl) EVT_SPINCTRL(SpinBtnPage_SpinCtrl, SpinBtnWidgetsPage::OnSpinCtrl)
EVT_SPINCTRLDOUBLE(SpinBtnPage_SpinCtrlDouble, SpinBtnWidgetsPage::OnSpinCtrlDouble)
EVT_TEXT(SpinBtnPage_SpinCtrl, SpinBtnWidgetsPage::OnSpinText) EVT_TEXT(SpinBtnPage_SpinCtrl, SpinBtnWidgetsPage::OnSpinText)
EVT_TEXT(SpinBtnPage_SpinCtrlDouble, SpinBtnWidgetsPage::OnSpinText)
EVT_CHECKBOX(wxID_ANY, SpinBtnWidgetsPage::OnCheckOrRadioBox) EVT_CHECKBOX(wxID_ANY, SpinBtnWidgetsPage::OnCheckOrRadioBox)
EVT_RADIOBOX(wxID_ANY, SpinBtnWidgetsPage::OnCheckOrRadioBox) EVT_RADIOBOX(wxID_ANY, SpinBtnWidgetsPage::OnCheckOrRadioBox)
@@ -189,6 +195,7 @@ SpinBtnWidgetsPage::SpinBtnWidgetsPage(WidgetsBookCtrl *book,
m_chkWrap = NULL; m_chkWrap = NULL;
m_spinbtn = NULL; m_spinbtn = NULL;
m_spinctrl = NULL; m_spinctrl = NULL;
m_spinctrldbl = NULL;
m_textValue = NULL; m_textValue = NULL;
m_textMin = NULL; m_textMin = NULL;
m_textMax = NULL; m_textMax = NULL;
@@ -304,14 +311,17 @@ void SpinBtnWidgetsPage::CreateSpin()
m_sizerSpin->Detach( m_spinbtn ); m_sizerSpin->Detach( m_spinbtn );
m_sizerSpin->Detach( m_spinctrl ); m_sizerSpin->Detach( m_spinctrl );
m_sizerSpin->Detach( m_spinctrldbl );
// there are 3 spacers left // there are 4 spacers left
m_sizerSpin->Remove( 0 );
m_sizerSpin->Remove( 0 ); m_sizerSpin->Remove( 0 );
m_sizerSpin->Remove( 0 ); m_sizerSpin->Remove( 0 );
m_sizerSpin->Remove( 0 ); m_sizerSpin->Remove( 0 );
delete m_spinbtn; delete m_spinbtn;
delete m_spinctrl; delete m_spinctrl;
delete m_spinctrldbl;
} }
m_spinbtn = new wxSpinButton(this, SpinBtnPage_SpinBtn, m_spinbtn = new wxSpinButton(this, SpinBtnPage_SpinBtn,
@@ -327,11 +337,19 @@ void SpinBtnWidgetsPage::CreateSpin()
flags, flags,
m_min, m_max, val); m_min, m_max, val);
m_spinctrldbl = new wxSpinCtrlDouble(this, SpinBtnPage_SpinCtrlDouble,
wxString::Format(_T("%d"), val),
wxDefaultPosition, wxDefaultSize,
flags,
m_min, m_max, val, 0.1);
m_sizerSpin->Add(0, 0, 1); m_sizerSpin->Add(0, 0, 1);
m_sizerSpin->Add(m_spinbtn, 0, wxALIGN_CENTRE | wxALL, 5); m_sizerSpin->Add(m_spinbtn, 0, wxALIGN_CENTRE | wxALL, 5);
m_sizerSpin->Add(0, 0, 1); m_sizerSpin->Add(0, 0, 1);
m_sizerSpin->Add(m_spinctrl, 0, wxALIGN_CENTRE | wxALL, 5); m_sizerSpin->Add(m_spinctrl, 0, wxALIGN_CENTRE | wxALL, 5);
m_sizerSpin->Add(0, 0, 1); m_sizerSpin->Add(0, 0, 1);
m_sizerSpin->Add(m_spinctrldbl, 0, wxALIGN_CENTRE | wxALL, 5);
m_sizerSpin->Add(0, 0, 1);
m_sizerSpin->Layout(); m_sizerSpin->Layout();
} }
@@ -365,6 +383,7 @@ void SpinBtnWidgetsPage::OnButtonSetMinAndMax(wxCommandEvent& WXUNUSED(event))
m_spinbtn->SetRange(minNew, maxNew); m_spinbtn->SetRange(minNew, maxNew);
m_spinctrl->SetRange(minNew, maxNew); m_spinctrl->SetRange(minNew, maxNew);
m_spinctrldbl->SetRange(minNew, maxNew);
} }
void SpinBtnWidgetsPage::OnButtonSetValue(wxCommandEvent& WXUNUSED(event)) void SpinBtnWidgetsPage::OnButtonSetValue(wxCommandEvent& WXUNUSED(event))
@@ -379,6 +398,7 @@ void SpinBtnWidgetsPage::OnButtonSetValue(wxCommandEvent& WXUNUSED(event))
m_spinbtn->SetValue(val); m_spinbtn->SetValue(val);
m_spinctrl->SetValue(val); m_spinctrl->SetValue(val);
m_spinctrldbl->SetValue(val);
} }
void SpinBtnWidgetsPage::OnUpdateUIValueButton(wxUpdateUIEvent& event) void SpinBtnWidgetsPage::OnUpdateUIValueButton(wxUpdateUIEvent& event)
@@ -442,6 +462,13 @@ void SpinBtnWidgetsPage::OnSpinCtrl(wxSpinEvent& event)
wxLogMessage(_T("Spin control value changed, now %d"), value); wxLogMessage(_T("Spin control value changed, now %d"), value);
} }
void SpinBtnWidgetsPage::OnSpinCtrlDouble(wxSpinDoubleEvent& event)
{
double value = event.GetValue();
wxLogMessage(_T("Spin control value changed, now %g"), value);
}
void SpinBtnWidgetsPage::OnSpinText(wxCommandEvent& event) void SpinBtnWidgetsPage::OnSpinText(wxCommandEvent& event)
{ {
wxLogMessage(_T("Text changed in spin control, now \"%s\""), wxLogMessage(_T("Text changed in spin control, now \"%s\""),

View File

@@ -183,6 +183,7 @@ DEFINE_EVENT_TYPE(wxEVT_COMMAND_COMBOBOX_SELECTED)
DEFINE_EVENT_TYPE(wxEVT_COMMAND_TOOL_RCLICKED) DEFINE_EVENT_TYPE(wxEVT_COMMAND_TOOL_RCLICKED)
DEFINE_EVENT_TYPE(wxEVT_COMMAND_TOOL_ENTER) DEFINE_EVENT_TYPE(wxEVT_COMMAND_TOOL_ENTER)
DEFINE_EVENT_TYPE(wxEVT_COMMAND_SPINCTRL_UPDATED) DEFINE_EVENT_TYPE(wxEVT_COMMAND_SPINCTRL_UPDATED)
DEFINE_EVENT_TYPE(wxEVT_COMMAND_SPINCTRLDOUBLE_UPDATED)
DEFINE_EVENT_TYPE(wxEVT_COMMAND_TOOL_DROPDOWN_CLICKED) DEFINE_EVENT_TYPE(wxEVT_COMMAND_TOOL_DROPDOWN_CLICKED)
// Mouse event types // Mouse event types

View File

@@ -24,19 +24,23 @@
#pragma hdrstop #pragma hdrstop
#endif #endif
// There are port-specific versions for MSW, GTK, OS/2 and Mac, so exclude the
// contents of this file in those cases
#if !(defined(__WXMSW__) || defined(__WXGTK__) || defined(__WXPM__) || \
defined(__WXMAC__)) || defined(__WXUNIVERSAL__)
#ifndef WX_PRECOMP #ifndef WX_PRECOMP
#include "wx/textctrl.h" #include "wx/textctrl.h"
#endif //WX_PRECOMP #endif //WX_PRECOMP
#include "wx/spinctrl.h"
#if wxUSE_SPINCTRL #if wxUSE_SPINCTRL
IMPLEMENT_DYNAMIC_CLASS(wxSpinDoubleEvent, wxNotifyEvent)
// There are port-specific versions for the wxSpinCtrl, so exclude the
// contents of this file in those cases
#if !defined(wxHAS_NATIVE_SPINCTRL) || !defined(wxHAS_NATIVE_SPINCTRLDOUBLE)
#include "wx/spinbutt.h" #include "wx/spinbutt.h"
#include "wx/spinctrl.h"
#if wxUSE_SPINBTN
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// constants // constants
@@ -45,6 +49,8 @@
// the margin between the text control and the spin // the margin between the text control and the spin
static const wxCoord MARGIN = 2; static const wxCoord MARGIN = 2;
#define SPINCTRLBUT_MAX 32000 // large to avoid wrap around trouble
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// wxSpinCtrlText: text control used by spin control // wxSpinCtrlText: text control used by spin control
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@@ -52,44 +58,60 @@ static const wxCoord MARGIN = 2;
class wxSpinCtrlText : public wxTextCtrl class wxSpinCtrlText : public wxTextCtrl
{ {
public: public:
wxSpinCtrlText(wxSpinCtrl *spin, const wxString& value) wxSpinCtrlText(wxSpinCtrlGenericBase *spin, const wxString& value)
: wxTextCtrl(spin->GetParent(), wxID_ANY, value) : wxTextCtrl(spin->GetParent(), wxID_ANY, value, wxDefaultPosition,
wxDefaultSize, wxTE_NOHIDESEL|wxTE_PROCESS_ENTER)
{ {
m_spin = spin; m_spin = spin;
// remove the default minsize, the spinctrl will have one instead // remove the default minsize, the spinctrl will have one instead
SetSizeHints(wxDefaultCoord,wxDefaultCoord); SetSizeHints(wxDefaultCoord, wxDefaultCoord);
} }
protected: virtual ~wxSpinCtrlText()
void OnTextChange(wxCommandEvent& event)
{ {
int val; // MSW sends extra kill focus event on destroy
if ( m_spin->GetTextValue(&val) ) if (m_spin)
m_spin->m_textCtrl = NULL;
m_spin = NULL;
}
void OnTextEnter(wxCommandEvent& event)
{ {
m_spin->GetSpinButton()->SetValue(val); if (m_spin)
m_spin->OnTextEnter(event);
}
void OnChar( wxKeyEvent &event )
{
if (m_spin)
m_spin->OnTextChar(event);
}
void OnKillFocus(wxFocusEvent& event)
{
if (m_spin)
{
m_spin->SyncSpinToText();
m_spin->DoSendEvent();
} }
event.Skip(); event.Skip();
} }
bool ProcessEvent(wxEvent &event) wxSpinCtrlGenericBase *m_spin;
{
// Hand button down events to wxSpinCtrl. Doesn't work.
if (event.GetEventType() == wxEVT_LEFT_DOWN && m_spin->ProcessEvent( event ))
return true;
return wxTextCtrl::ProcessEvent( event );
}
private: private:
wxSpinCtrl *m_spin;
DECLARE_EVENT_TABLE() DECLARE_EVENT_TABLE()
}; };
BEGIN_EVENT_TABLE(wxSpinCtrlText, wxTextCtrl) BEGIN_EVENT_TABLE(wxSpinCtrlText, wxTextCtrl)
EVT_TEXT(wxID_ANY, wxSpinCtrlText::OnTextChange) EVT_TEXT_ENTER(wxID_ANY, wxSpinCtrlText::OnTextEnter)
EVT_CHAR(wxSpinCtrlText::OnChar)
EVT_KILL_FOCUS(wxSpinCtrlText::OnKillFocus)
END_EVENT_TABLE() END_EVENT_TABLE()
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@@ -99,90 +121,100 @@ END_EVENT_TABLE()
class wxSpinCtrlButton : public wxSpinButton class wxSpinCtrlButton : public wxSpinButton
{ {
public: public:
wxSpinCtrlButton(wxSpinCtrl *spin, int style) wxSpinCtrlButton(wxSpinCtrlGenericBase *spin, int style)
: wxSpinButton(spin->GetParent()) : wxSpinButton(spin->GetParent(), wxID_ANY, wxDefaultPosition,
wxDefaultSize, style | wxSP_VERTICAL)
{ {
m_spin = spin; m_spin = spin;
SetWindowStyle(style | wxSP_VERTICAL); SetRange(-SPINCTRLBUT_MAX, SPINCTRLBUT_MAX);
// remove the default minsize, the spinctrl will have one instead // remove the default minsize, the spinctrl will have one instead
SetSizeHints(wxDefaultCoord,wxDefaultCoord); SetSizeHints(wxDefaultCoord, wxDefaultCoord);
} }
protected: void OnSpinButton(wxSpinEvent& event)
void OnSpinButton(wxSpinEvent& eventSpin)
{ {
m_spin->SetTextValue(eventSpin.GetPosition()); if (m_spin)
m_spin->OnSpinButton(event);
wxCommandEvent event(wxEVT_COMMAND_SPINCTRL_UPDATED, m_spin->GetId());
event.SetEventObject(m_spin);
event.SetInt(eventSpin.GetPosition());
m_spin->GetEventHandler()->ProcessEvent(event);
eventSpin.Skip();
} }
wxSpinCtrlGenericBase *m_spin;
private: private:
wxSpinCtrl *m_spin;
DECLARE_EVENT_TABLE() DECLARE_EVENT_TABLE()
}; };
BEGIN_EVENT_TABLE(wxSpinCtrlButton, wxSpinButton) BEGIN_EVENT_TABLE(wxSpinCtrlButton, wxSpinButton)
EVT_SPIN(wxID_ANY, wxSpinCtrlButton::OnSpinButton) EVT_SPIN_UP( wxID_ANY, wxSpinCtrlButton::OnSpinButton)
EVT_SPIN_DOWN(wxID_ANY, wxSpinCtrlButton::OnSpinButton)
END_EVENT_TABLE() END_EVENT_TABLE()
IMPLEMENT_DYNAMIC_CLASS(wxSpinCtrl, wxControl)
// ============================================================================ // ============================================================================
// implementation // wxSpinCtrlGenericBase
// ============================================================================ // ============================================================================
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// wxSpinCtrl creation // wxSpinCtrlGenericBase creation
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void wxSpinCtrl::Init() void wxSpinCtrlGenericBase::Init()
{ {
m_text = NULL; m_value = 0;
m_btn = NULL; m_min = 0;
m_max = 100;
m_increment = 1;
m_snap_to_ticks = false;
m_format = wxS("%g");
m_spin_value = 0;
m_textCtrl = NULL;
m_spinButton = NULL;
} }
bool wxSpinCtrl::Create(wxWindow *parent, bool wxSpinCtrlGenericBase::Create(wxWindow *parent,
wxWindowID id, wxWindowID id,
const wxString& value, const wxString& value,
const wxPoint& pos, const wxPoint& pos, const wxSize& size,
const wxSize& size,
long style, long style,
int min, double min, double max, double initial,
int max, double increment,
int initial,
const wxString& name) const wxString& name)
{ {
if ( !wxControl::Create(parent, id, wxDefaultPosition, wxDefaultSize, style, // don't use borders for this control itself, it wouldn't look good with
wxDefaultValidator, name) ) // the text control borders (but we might want to use style border bits to
// select the text control style)
if ( !wxControl::Create(parent, id, wxDefaultPosition, wxDefaultSize,
wxBORDER_NONE, wxDefaultValidator, name) )
{ {
return false; return false;
} }
m_value = initial;
m_min = min;
m_max = max;
m_increment = increment;
m_textCtrl = new wxSpinCtrlText(this, value);
m_spinButton = new wxSpinCtrlButton(this, style);
m_spin_value = m_spinButton->GetValue();
// the string value overrides the numeric one (for backwards compatibility // the string value overrides the numeric one (for backwards compatibility
// reasons and also because it is simpler to satisfy the string value which // reasons and also because it is simpler to satisfy the string value which
// comes much sooner in the list of arguments and leave the initial // comes much sooner in the list of arguments and leave the initial
// parameter unspecified) // parameter unspecified)
if ( !value.empty() ) if ( !value.empty() )
{ {
long l; double d;
if ( value.ToLong(&l) ) if ( value.ToDouble(&d) )
initial = l; {
m_value = d;
m_textCtrl->SetValue(wxString::Format(m_format, m_value));
}
} }
m_text = new wxSpinCtrlText(this, value);
m_btn = new wxSpinCtrlButton(this, style);
m_btn->SetRange(min, max);
m_btn->SetValue(initial);
SetInitialSize(size); SetInitialSize(size);
Move(pos); Move(pos);
@@ -199,177 +231,324 @@ bool wxSpinCtrl::Create(wxWindow *parent,
return true; return true;
} }
wxSpinCtrl::~wxSpinCtrl() wxSpinCtrlGenericBase::~wxSpinCtrlGenericBase()
{ {
// delete the controls now, don't leave them alive even though they would // delete the controls now, don't leave them alive even though they would
// still be eventually deleted by our parent - but it will be too late, the // still be eventually deleted by our parent - but it will be too late, the
// user code expects them to be gone now // user code expects them to be gone now
delete m_text;
m_text = NULL ; if (m_textCtrl)
delete m_btn; {
m_btn = NULL ; // null this since MSW sends KILL_FOCUS on deletion, see ~wxSpinCtrlText
wxDynamicCast(m_textCtrl, wxSpinCtrlText)->m_spin = NULL;
wxSpinCtrlText *text = (wxSpinCtrlText*)m_textCtrl;
m_textCtrl = NULL;
delete text;
}
delete m_spinButton;
m_spinButton = NULL;
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// geometry // geometry
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
wxSize wxSpinCtrl::DoGetBestSize() const wxSize wxSpinCtrlGenericBase::DoGetBestSize() const
{ {
wxSize sizeBtn = m_btn->GetBestSize(), wxSize sizeBtn = m_spinButton->GetBestSize(),
sizeText = m_text->GetBestSize(); sizeText = m_textCtrl->GetBestSize();
return wxSize(sizeBtn.x + sizeText.x + MARGIN, sizeText.y); return wxSize(sizeBtn.x + sizeText.x + MARGIN, sizeText.y);
} }
void wxSpinCtrl::DoMoveWindow(int x, int y, int width, int height) void wxSpinCtrlGenericBase::DoMoveWindow(int x, int y, int width, int height)
{ {
wxControl::DoMoveWindow(x, y, width, height); wxControl::DoMoveWindow(x, y, width, height);
// position the subcontrols inside the client area // position the subcontrols inside the client area
wxSize sizeBtn = m_btn->GetSize(); wxSize sizeBtn = m_spinButton->GetSize();
wxCoord wText = width - sizeBtn.x; wxCoord wText = width - sizeBtn.x;
m_text->SetSize(x, y, wText, height); m_textCtrl->SetSize(x, y, wText, height);
m_btn->SetSize(x + wText + MARGIN, y, wxDefaultCoord, height); m_spinButton->SetSize(x + wText + MARGIN, y, wxDefaultCoord, height);
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// operations forwarded to the subcontrols // operations forwarded to the subcontrols
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
bool wxSpinCtrl::Enable(bool enable) bool wxSpinCtrlGenericBase::Enable(bool enable)
{ {
if ( !wxControl::Enable(enable) ) if ( !wxControl::Enable(enable) )
return false; return false;
m_btn->Enable(enable); m_spinButton->Enable(enable);
m_text->Enable(enable); m_textCtrl->Enable(enable);
return true; return true;
} }
bool wxSpinCtrl::Show(bool show) bool wxSpinCtrlGenericBase::Show(bool show)
{ {
if ( !wxControl::Show(show) ) if ( !wxControl::Show(show) )
return false; return false;
// under GTK Show() is called the first time before we are fully // under GTK Show() is called the first time before we are fully
// constructed // constructed
if ( m_btn ) if ( m_spinButton )
{ {
m_btn->Show(show); m_spinButton->Show(show);
m_text->Show(show); m_textCtrl->Show(show);
} }
return true; return true;
} }
bool wxSpinCtrl::Reparent(wxWindow *newParent) bool wxSpinCtrlGenericBase::Reparent(wxWindow *newParent)
{ {
if ( m_btn ) if ( m_spinButton )
{ {
m_btn->Reparent(newParent); m_spinButton->Reparent(newParent);
m_text->Reparent(newParent); m_textCtrl->Reparent(newParent);
} }
return true; return true;
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// value and range access // Handle sub controls events
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
bool wxSpinCtrl::GetTextValue(int *val) const void wxSpinCtrlGenericBase::OnSpinButton(wxSpinEvent& event)
{ {
long l; event.Skip();
if ( !m_text->GetValue().ToLong(&l) )
// Sync the textctrl since the user expects that the button will modify
// what they see in the textctrl.
if ( m_textCtrl && m_textCtrl->IsModified() )
SyncSpinToText();
int spin_value = event.GetPosition();
double step = (event.GetEventType() == wxEVT_SCROLL_LINEUP) ? 1 : -1;
// Use the spinbutton's acceleration, if any, but not if wrapping around
if (((spin_value >= 0) && (m_spin_value >= 0)) || ((spin_value <= 0) && (m_spin_value <= 0)))
step *= abs(spin_value - m_spin_value);
double value = m_value + step*m_increment;
// we can always reach the ends using the spinbutton
if (value < m_min) value = m_min;
if (value > m_max) value = m_max;
// Ignore the edges when it wraps since the up/down event may be opposite
// They are in GTK and Mac
if (abs(spin_value - m_spin_value) > SPINCTRLBUT_MAX)
{ {
// not a number at all m_spin_value = spin_value;
return false; return;
} }
if ( l < GetMin() || l > GetMax() ) m_spin_value = spin_value;
if (InRange(value) && DoSetValue(value))
DoSendEvent();
}
void wxSpinCtrlGenericBase::OnTextEnter(wxCommandEvent& event)
{
SyncSpinToText();
DoSendEvent();
event.Skip();
}
void wxSpinCtrlGenericBase::OnTextChar(wxKeyEvent& event)
{
double value = m_value;
switch ( event.GetKeyCode() )
{ {
// out of range case WXK_UP :
return false; value += m_increment;
break;
case WXK_DOWN :
value -= m_increment;
break;
case WXK_PAGEUP :
value += m_increment * 10.0;
break;
case WXK_PAGEDOWN :
value -= m_increment * 10.0;
break;
default:
event.Skip();
return;
} }
*val = l; if ( m_textCtrl && m_textCtrl->IsModified() )
SyncSpinToText();
return true; if ( DoSetValue(value) )
DoSendEvent();
} }
int wxSpinCtrl::GetValue() const // ----------------------------------------------------------------------------
{ // Textctrl functions
return m_btn ? m_btn->GetValue() : 0; // ----------------------------------------------------------------------------
}
int wxSpinCtrl::GetMin() const void wxSpinCtrlGenericBase::SyncSpinToText()
{ {
return m_btn ? m_btn->GetMin() : 0; if (!m_textCtrl)
} return;
int wxSpinCtrl::GetMax() const double textValue;
{ if ( m_textCtrl->GetValue().ToDouble(&textValue) )
return m_btn ? m_btn->GetMax() : 0; {
if (textValue > m_max)
textValue = m_max;
else if (textValue < m_min)
textValue = m_min;
if (m_value != textValue)
{
DoSetValue(textValue);
}
}
else
{
// textctrl is out of sync, discard and reset
DoSetValue(m_value);
}
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// changing value and range // changing value and range
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void wxSpinCtrl::SetTextValue(int val) void wxSpinCtrlGenericBase::SetValue(const wxString& text)
{ {
wxCHECK_RET( m_text, _T("invalid call to wxSpinCtrl::SetTextValue") ); wxCHECK_RET( m_textCtrl, _T("invalid call to wxSpinCtrl::SetValue") );
m_text->SetValue(wxString::Format(_T("%d"), val)); double val;
if ( text.ToDouble(&val) && InRange(val) )
// select all text
m_text->SetSelection(0, -1);
// and give focus to the control!
// m_text->SetFocus(); Why???? TODO.
}
void wxSpinCtrl::SetValue(int val)
{
wxCHECK_RET( m_btn, _T("invalid call to wxSpinCtrl::SetValue") );
SetTextValue(val);
m_btn->SetValue(val);
}
void wxSpinCtrl::SetValue(const wxString& text)
{
wxCHECK_RET( m_text, _T("invalid call to wxSpinCtrl::SetValue") );
long val;
if ( text.ToLong(&val) && ((val > INT_MIN) && (val < INT_MAX)) )
{ {
SetValue((int)val); DoSetValue(val);
} }
else // not a number at all or out of range else // not a number at all or out of range
{ {
m_text->SetValue(text); m_textCtrl->SetValue(text);
m_text->SetSelection(0, -1); m_textCtrl->SetSelection(0, -1);
} }
} }
void wxSpinCtrl::SetRange(int min, int max) bool wxSpinCtrlGenericBase::DoSetValue(double val)
{ {
wxCHECK_RET( m_btn, _T("invalid call to wxSpinCtrl::SetRange") ); wxCHECK_MSG( m_textCtrl, false, _T("invalid call to wxSpinCtrl::SetValue") );
m_btn->SetRange(min, max); if (!InRange(val))
return false;
if ( m_snap_to_ticks && (m_increment != 0) )
{
double snap_value = val / m_increment;
if (wxFinite(snap_value)) // FIXME what to do about a failure?
{
if ((snap_value - floor(snap_value)) < (ceil(snap_value) - snap_value))
val = floor(snap_value) * m_increment;
else
val = ceil(snap_value) * m_increment;
}
}
wxString str(wxString::Format(m_format.c_str(), val));
if ((val != m_value) || (str != m_textCtrl->GetValue()))
{
m_value = val;
str.ToDouble( &m_value ); // wysiwyg for textctrl
m_textCtrl->SetValue( str );
m_textCtrl->DiscardEdits();
return true;
}
return false;
} }
void wxSpinCtrl::SetSelection(long from, long to) void wxSpinCtrlGenericBase::DoSetRange(double min, double max)
{ {
wxCHECK_RET( m_text, _T("invalid call to wxSpinCtrl::SetSelection") ); m_min = min;
m_max = max;
m_text->SetSelection(from, to);
} }
void wxSpinCtrlGenericBase::DoSetIncrement(double inc)
{
m_increment = inc;
}
void wxSpinCtrlGenericBase::SetSnapToTicks(bool snap_to_ticks)
{
m_snap_to_ticks = snap_to_ticks;
DoSetValue(m_value);
}
void wxSpinCtrlGenericBase::SetSelection(long from, long to)
{
wxCHECK_RET( m_textCtrl, _T("invalid call to wxSpinCtrl::SetSelection") );
m_textCtrl->SetSelection(from, to);
}
#ifndef wxHAS_NATIVE_SPINCTRL
//-----------------------------------------------------------------------------
// wxSpinCtrl
//-----------------------------------------------------------------------------
IMPLEMENT_DYNAMIC_CLASS(wxSpinCtrl, wxSpinCtrlGenericBase)
void wxSpinCtrl::DoSendEvent()
{
wxSpinEvent event( wxEVT_COMMAND_SPINCTRL_UPDATED, GetId());
event.SetEventObject( this );
event.SetPosition((int)(m_value + 0.5)); // FIXME should be SetValue
event.SetString(m_textCtrl->GetValue());
GetEventHandler()->ProcessEvent( event );
}
#endif // !wxHAS_NATIVE_SPINCTRL
//-----------------------------------------------------------------------------
// wxSpinCtrlDouble
//-----------------------------------------------------------------------------
IMPLEMENT_DYNAMIC_CLASS(wxSpinCtrlDouble, wxSpinCtrlGenericBase)
void wxSpinCtrlDouble::DoSendEvent()
{
wxSpinDoubleEvent event( wxEVT_COMMAND_SPINCTRLDOUBLE_UPDATED, GetId());
event.SetEventObject( this );
event.SetValue(m_value);
event.SetString(m_textCtrl->GetValue());
GetEventHandler()->ProcessEvent( event );
}
void wxSpinCtrlDouble::SetDigits(unsigned digits)
{
wxCHECK_RET( digits <= 20, "too many digits for wxSpinCtrlDouble" );
m_format.Printf(wxT("%%0.%ulf"), digits);
DoSetValue(m_value);
}
#endif // wxUSE_SPINBTN
#endif // !wxPort-with-native-spinctrl
#endif // wxUSE_SPINCTRL #endif // wxUSE_SPINCTRL
#endif // !wxPort-with-native-spinctrl

View File

@@ -35,23 +35,35 @@ extern bool g_blockEventsOnDrag;
extern "C" { extern "C" {
static void static void
gtk_value_changed(GtkSpinButton* spinbutton, wxSpinCtrl* win) gtk_value_changed(GtkSpinButton* spinbutton, wxSpinCtrlGTKBase* win)
{ {
win->m_pos = int(gtk_spin_button_get_value(spinbutton)); win->m_value = gtk_spin_button_get_value(spinbutton);
if (!win->m_hasVMT || g_blockEventsOnDrag) if (!win->m_hasVMT || g_blockEventsOnDrag)
return; return;
wxCommandEvent event( wxEVT_COMMAND_SPINCTRL_UPDATED, win->GetId());
event.SetEventObject( win );
// note that we don't use wxSpinCtrl::GetValue() here because it would // note that we don't use wxSpinCtrl::GetValue() here because it would
// adjust the value to fit into the control range and this means that we // adjust the value to fit into the control range and this means that we
// would never be able to enter an "invalid" value in the control, even // would never be able to enter an "invalid" value in the control, even
// temporarily - and trying to enter 10 into the control which accepts the // temporarily - and trying to enter 10 into the control which accepts the
// values in range 5..50 is then, ummm, quite challenging (hint: you can't // values in range 5..50 is then, ummm, quite challenging (hint: you can't
// enter 1!) (VZ) // enter 1!) (VZ)
event.SetInt(win->m_pos);
if (wxIsKindOf(win, wxSpinCtrl))
{
wxSpinEvent event(wxEVT_COMMAND_SPINCTRL_UPDATED, win->GetId());
event.SetEventObject( win );
event.SetPosition((int)(win->m_value + 0.5)); // FIXME should be SetValue
event.SetString(GTK_ENTRY(spinbutton)->text);
win->HandleWindowEvent( event ); win->HandleWindowEvent( event );
}
else // wxIsKindOf(win, wxSpinCtrlDouble)
{
wxSpinDoubleEvent event( wxEVT_COMMAND_SPINCTRLDOUBLE_UPDATED, win->GetId());
event.SetEventObject( win );
event.SetValue(win->m_value);
event.SetString(GTK_ENTRY(spinbutton)->text);
win->HandleWindowEvent( event );
}
} }
} }
@@ -71,43 +83,39 @@ gtk_changed(GtkSpinButton* spinbutton, wxSpinCtrl* win)
event.SetString( GTK_ENTRY(spinbutton)->text ); event.SetString( GTK_ENTRY(spinbutton)->text );
// see above // see above
event.SetInt(win->m_pos); event.SetInt((int)win->m_value);
win->HandleWindowEvent( event ); win->HandleWindowEvent( event );
} }
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// wxSpinCtrl // wxSpinCtrlGTKBase
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
IMPLEMENT_DYNAMIC_CLASS(wxSpinCtrl,wxControl) IMPLEMENT_DYNAMIC_CLASS(wxSpinCtrlGTKBase, wxSpinCtrlBase)
BEGIN_EVENT_TABLE(wxSpinCtrl, wxControl) BEGIN_EVENT_TABLE(wxSpinCtrlGTKBase, wxSpinCtrlBase)
EVT_CHAR(wxSpinCtrl::OnChar) EVT_CHAR(wxSpinCtrlGTKBase::OnChar)
END_EVENT_TABLE() END_EVENT_TABLE()
wxSpinCtrl::wxSpinCtrl() bool wxSpinCtrlGTKBase::Create(wxWindow *parent, wxWindowID id,
{
m_pos = 0;
}
bool wxSpinCtrl::Create(wxWindow *parent, wxWindowID id,
const wxString& value, const wxString& value,
const wxPoint& pos, const wxSize& size, const wxPoint& pos, const wxSize& size,
long style, long style,
int min, int max, int initial, double min, double max, double initial, double inc,
const wxString& name) const wxString& name)
{ {
if (!PreCreation( parent, pos, size ) || if (!PreCreation( parent, pos, size ) ||
!CreateBase( parent, id, pos, size, style, wxDefaultValidator, name )) !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name ))
{ {
wxFAIL_MSG( wxT("wxSpinCtrl creation failed") ); wxFAIL_MSG( wxT("wxSpinCtrlGTKBase creation failed") );
return false; return false;
} }
m_widget = gtk_spin_button_new_with_range(min, max, 1); m_widget = gtk_spin_button_new_with_range(min, max, inc);
gtk_spin_button_set_value( GTK_SPIN_BUTTON(m_widget), initial); gtk_spin_button_set_value( GTK_SPIN_BUTTON(m_widget), initial);
m_pos = (int) gtk_spin_button_get_value( GTK_SPIN_BUTTON(m_widget)); m_value = gtk_spin_button_get_value( GTK_SPIN_BUTTON(m_widget));
gtk_spin_button_set_wrap( GTK_SPIN_BUTTON(m_widget), gtk_spin_button_set_wrap( GTK_SPIN_BUTTON(m_widget),
(int)(m_windowStyle & wxSP_WRAP) ); (int)(m_windowStyle & wxSP_WRAP) );
@@ -127,67 +135,92 @@ bool wxSpinCtrl::Create(wxWindow *parent, wxWindowID id,
return true; return true;
} }
int wxSpinCtrl::GetMin() const double wxSpinCtrlGTKBase::DoGetValue() const
{
wxCHECK_MSG( (m_widget != NULL), 0, wxT("invalid spin button") );
double min;
gtk_spin_button_get_range( GTK_SPIN_BUTTON(m_widget), &min, NULL);
return int(min);
}
int wxSpinCtrl::GetMax() const
{
wxCHECK_MSG( (m_widget != NULL), 0, wxT("invalid spin button") );
double max;
gtk_spin_button_get_range( GTK_SPIN_BUTTON(m_widget), NULL, &max);
return int(max);
}
int wxSpinCtrl::GetValue() const
{ {
wxCHECK_MSG( (m_widget != NULL), 0, wxT("invalid spin button") ); wxCHECK_MSG( (m_widget != NULL), 0, wxT("invalid spin button") );
GtkDisableEvents(); GtkDisableEvents();
gtk_spin_button_update( GTK_SPIN_BUTTON(m_widget) ); gtk_spin_button_update( GTK_SPIN_BUTTON(m_widget) );
wx_const_cast(wxSpinCtrl*, this)->m_pos = wx_const_cast(wxSpinCtrlGTKBase*, this)->m_value =
int(gtk_spin_button_get_value(GTK_SPIN_BUTTON(m_widget))); gtk_spin_button_get_value(GTK_SPIN_BUTTON(m_widget));
GtkEnableEvents(); GtkEnableEvents();
return m_pos; return m_value;
} }
void wxSpinCtrl::SetValue( const wxString& value ) double wxSpinCtrlGTKBase::DoGetMin() const
{
wxCHECK_MSG( (m_widget != NULL), 0, wxT("invalid spin button") );
double min = 0;
gtk_spin_button_get_range( GTK_SPIN_BUTTON(m_widget), &min, NULL);
return min;
}
double wxSpinCtrlGTKBase::DoGetMax() const
{
wxCHECK_MSG( (m_widget != NULL), 0, wxT("invalid spin button") );
double max = 0;
gtk_spin_button_get_range( GTK_SPIN_BUTTON(m_widget), NULL, &max);
return max;
}
double wxSpinCtrlGTKBase::DoGetIncrement() const
{
wxCHECK_MSG( (m_widget != NULL), 0, wxT("invalid spin button") );
double inc = 0;
gtk_spin_button_get_increments( GTK_SPIN_BUTTON(m_widget), NULL, &inc);
return inc;
}
bool wxSpinCtrlGTKBase::GetSnapToTicks() const
{
wxCHECK_MSG( m_widget, 0, "invalid spin button" );
return gtk_spin_button_get_snap_to_ticks( GTK_SPIN_BUTTON(m_widget) );
}
void wxSpinCtrlGTKBase::SetValue( const wxString& value )
{ {
wxCHECK_RET( (m_widget != NULL), wxT("invalid spin button") ); wxCHECK_RET( (m_widget != NULL), wxT("invalid spin button") );
int n; double n;
if ( (wxSscanf(value, wxT("%d"), &n) == 1) ) if ( wxSscanf(value, "%lg", &n) == 1 )
{ {
// a number - set it // a number - set it, let DoSetValue round for int value
SetValue(n); DoSetValue(n);
return;
} }
else
{
// invalid number - set text as is (wxMSW compatible) // invalid number - set text as is (wxMSW compatible)
GtkDisableEvents(); GtkDisableEvents();
gtk_entry_set_text( GTK_ENTRY(m_widget), wxGTK_CONV( value ) ); gtk_entry_set_text( GTK_ENTRY(m_widget), wxGTK_CONV( value ) );
GtkEnableEvents(); GtkEnableEvents();
}
} }
void wxSpinCtrl::SetValue( int value ) void wxSpinCtrlGTKBase::DoSetValue( double value )
{ {
wxCHECK_RET( (m_widget != NULL), wxT("invalid spin button") ); wxCHECK_RET( (m_widget != NULL), wxT("invalid spin button") );
if (wxIsKindOf(this, wxSpinCtrl))
value = int(value + 0.5);
GtkDisableEvents(); GtkDisableEvents();
gtk_spin_button_set_value( GTK_SPIN_BUTTON(m_widget), value); gtk_spin_button_set_value( GTK_SPIN_BUTTON(m_widget), value);
m_pos = (int) gtk_spin_button_get_value( GTK_SPIN_BUTTON(m_widget)); m_value = gtk_spin_button_get_value( GTK_SPIN_BUTTON(m_widget));
GtkEnableEvents(); GtkEnableEvents();
} }
void wxSpinCtrl::SetSelection(long from, long to) void wxSpinCtrlGTKBase::SetSnapToTicks(bool snap_to_ticks)
{
wxCHECK_RET( (m_widget != NULL), "invalid spin button" );
gtk_spin_button_set_snap_to_ticks( GTK_SPIN_BUTTON(m_widget), snap_to_ticks);
}
void wxSpinCtrlGTKBase::SetSelection(long from, long to)
{ {
// translate from wxWidgets conventions to GTK+ ones: (-1, -1) means the // translate from wxWidgets conventions to GTK+ ones: (-1, -1) means the
// entire range // entire range
@@ -200,18 +233,27 @@ void wxSpinCtrl::SetSelection(long from, long to)
gtk_editable_select_region( GTK_EDITABLE(m_widget), (gint)from, (gint)to ); gtk_editable_select_region( GTK_EDITABLE(m_widget), (gint)from, (gint)to );
} }
void wxSpinCtrl::SetRange(int minVal, int maxVal) void wxSpinCtrlGTKBase::DoSetRange(double minVal, double maxVal)
{ {
wxCHECK_RET( (m_widget != NULL), wxT("invalid spin button") ); wxCHECK_RET( (m_widget != NULL), wxT("invalid spin button") );
GtkDisableEvents(); GtkDisableEvents();
gtk_spin_button_set_range( GTK_SPIN_BUTTON(m_widget), minVal, maxVal); gtk_spin_button_set_range( GTK_SPIN_BUTTON(m_widget), minVal, maxVal);
m_pos = int(gtk_spin_button_get_value(GTK_SPIN_BUTTON(m_widget))); m_value = gtk_spin_button_get_value(GTK_SPIN_BUTTON(m_widget));
GtkEnableEvents(); GtkEnableEvents();
} }
void wxSpinCtrlGTKBase::DoSetIncrement(double inc)
{
wxCHECK_RET( m_widget, "invalid spin button" );
void wxSpinCtrl::GtkDisableEvents() const GtkDisableEvents();
gtk_spin_button_set_increments( GTK_SPIN_BUTTON(m_widget), inc, 10*inc);
m_value = gtk_spin_button_get_value(GTK_SPIN_BUTTON(m_widget));
GtkEnableEvents();
}
void wxSpinCtrlGTKBase::GtkDisableEvents() const
{ {
g_signal_handlers_block_by_func( m_widget, g_signal_handlers_block_by_func( m_widget,
(gpointer)gtk_value_changed, (void*) this); (gpointer)gtk_value_changed, (void*) this);
@@ -220,7 +262,7 @@ void wxSpinCtrl::GtkDisableEvents() const
(gpointer)gtk_changed, (void*) this); (gpointer)gtk_changed, (void*) this);
} }
void wxSpinCtrl::GtkEnableEvents() const void wxSpinCtrlGTKBase::GtkEnableEvents() const
{ {
g_signal_handlers_unblock_by_func(m_widget, g_signal_handlers_unblock_by_func(m_widget,
(gpointer)gtk_value_changed, (void*) this); (gpointer)gtk_value_changed, (void*) this);
@@ -229,7 +271,7 @@ void wxSpinCtrl::GtkEnableEvents() const
(gpointer)gtk_changed, (void*) this); (gpointer)gtk_changed, (void*) this);
} }
void wxSpinCtrl::OnChar( wxKeyEvent &event ) void wxSpinCtrlGTKBase::OnChar( wxKeyEvent &event )
{ {
wxCHECK_RET( m_widget != NULL, wxT("invalid spin ctrl") ); wxCHECK_RET( m_widget != NULL, wxT("invalid spin ctrl") );
@@ -266,7 +308,7 @@ void wxSpinCtrl::OnChar( wxKeyEvent &event )
event.Skip(); event.Skip();
} }
GdkWindow *wxSpinCtrl::GTKGetWindow(wxArrayGdkWindows& windows) const GdkWindow *wxSpinCtrlGTKBase::GTKGetWindow(wxArrayGdkWindows& windows) const
{ {
GtkSpinButton* spinbutton = GTK_SPIN_BUTTON(m_widget); GtkSpinButton* spinbutton = GTK_SPIN_BUTTON(m_widget);
@@ -276,7 +318,7 @@ GdkWindow *wxSpinCtrl::GTKGetWindow(wxArrayGdkWindows& windows) const
return NULL; return NULL;
} }
wxSize wxSpinCtrl::DoGetBestSize() const wxSize wxSpinCtrlGTKBase::DoGetBestSize() const
{ {
wxSize ret( wxControl::DoGetBestSize() ); wxSize ret( wxControl::DoGetBestSize() );
wxSize best(95, ret.y); // FIXME: 95? wxSize best(95, ret.y); // FIXME: 95?
@@ -286,12 +328,37 @@ wxSize wxSpinCtrl::DoGetBestSize() const
// static // static
wxVisualAttributes wxVisualAttributes
wxSpinCtrl::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant)) wxSpinCtrlGTKBase::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant))
{ {
// TODO: overload to accept functions like gtk_spin_button_new? // TODO: overload to accept functions like gtk_spin_button_new?
// Until then use a similar type // Until then use a similar type
return GetDefaultAttributesFromGTKWidget(gtk_entry_new, true); return GetDefaultAttributesFromGTKWidget(gtk_entry_new, true);
} }
#endif //-----------------------------------------------------------------------------
// wxUSE_SPINCTRL // wxSpinCtrl
//-----------------------------------------------------------------------------
IMPLEMENT_DYNAMIC_CLASS(wxSpinCtrl, wxSpinCtrlGTKBase)
//-----------------------------------------------------------------------------
// wxSpinCtrlDouble
//-----------------------------------------------------------------------------
IMPLEMENT_DYNAMIC_CLASS(wxSpinCtrlDouble, wxSpinCtrlGTKBase)
unsigned wxSpinCtrlDouble::GetDigits() const
{
wxCHECK_MSG( m_widget, 0, "invalid spin button" );
return gtk_spin_button_get_digits( GTK_SPIN_BUTTON(m_widget) );
}
void wxSpinCtrlDouble::SetDigits(unsigned digits)
{
wxCHECK_RET( m_widget, "invalid spin button" );
gtk_spin_button_set_digits( GTK_SPIN_BUTTON(m_widget), digits);
}
#endif // wxUSE_SPINCTRL