1 ///////////////////////////////////////////////////////////////////////////// 
   5 // Modified by: Mark Newsam (Based on GTK file) 
   7 // Copyright:   (c) Robert Roebling 
   8 // Licence:     wxWindows licence 
   9 ///////////////////////////////////////////////////////////////////////////// 
  12 #pragma implementation "spinctlg.h" 
  18     #include "wx/textctrl.h" 
  23 #include "wx/spinbutt.h" 
  24 #include "wx/spinctrl.h" 
  27 #include "wx/spinctrl.h" 
  29 // ---------------------------------------------------------------------------- 
  31 // ---------------------------------------------------------------------------- 
  33 // the margin between the text control and the spin 
  34 static const wxCoord MARGIN 
= 2; 
  36 // ---------------------------------------------------------------------------- 
  37 // wxSpinCtrlText: text control used by spin control 
  38 // ---------------------------------------------------------------------------- 
  40 class wxSpinCtrlText 
: public wxTextCtrl
 
  43     wxSpinCtrlText(wxSpinCtrl 
*spin
, const wxString
& value
) 
  44         : wxTextCtrl(spin 
, -1, value
) 
  50     void OnTextChange(wxCommandEvent
& event
) 
  53         if ( m_spin
->GetTextValue(&val
) ) 
  55             m_spin
->GetSpinButton()->SetValue(val
); 
  61     bool ProcessEvent(wxEvent 
&event
) 
  63         // Hand button down events to wxSpinCtrl. Doesn't work. 
  64         if (event
.GetEventType() == wxEVT_LEFT_DOWN 
&& m_spin
->ProcessEvent( event 
)) 
  67         return wxTextCtrl::ProcessEvent( event 
); 
  76 BEGIN_EVENT_TABLE(wxSpinCtrlText
, wxTextCtrl
) 
  77     EVT_TEXT(-1, wxSpinCtrlText::OnTextChange
) 
  80 // ---------------------------------------------------------------------------- 
  81 // wxSpinCtrlButton: spin button used by spin control 
  82 // ---------------------------------------------------------------------------- 
  84 class wxSpinCtrlButton 
: public wxSpinButton
 
  87     wxSpinCtrlButton(wxSpinCtrl 
*spin
, int style
) 
  92         SetWindowStyle(style 
| wxSP_VERTICAL
); 
  96     void OnSpinButton(wxSpinEvent
& eventSpin
) 
  98 #if defined(__WXMAC__) || defined(__WXMOTIF__) 
  99       m_spin
->SetTextValue(eventSpin
.GetPosition()); 
 101       wxCommandEvent 
event(wxEVT_COMMAND_SPINCTRL_UPDATED
, m_spin
->GetId()); 
 102       event
.SetEventObject(m_spin
); 
 103       event
.SetInt(eventSpin
.GetPosition()); 
 105       m_spin
->GetEventHandler()->ProcessEvent(event
); 
 107         m_spin
->SetTextValue(eventSpin
.GetPosition()); 
 115     DECLARE_EVENT_TABLE() 
 118 BEGIN_EVENT_TABLE(wxSpinCtrlButton
, wxSpinButton
) 
 119     EVT_SPIN(-1, wxSpinCtrlButton::OnSpinButton
) 
 122 IMPLEMENT_DYNAMIC_CLASS(wxSpinCtrl
, wxControl
) 
 124 // ============================================================================ 
 126 // ============================================================================ 
 128 // ---------------------------------------------------------------------------- 
 129 // wxSpinCtrl creation 
 130 // ---------------------------------------------------------------------------- 
 132 void wxSpinCtrl::Init() 
 138 bool wxSpinCtrl::Create(wxWindow 
*parent
, 
 140                         const wxString
& value
, 
 147                         const wxString
& name
) 
 149     if ( !wxControl::Create(parent
, id
, wxDefaultPosition
, wxDefaultSize
, style
, 
 150                             wxDefaultValidator
, name
) ) 
 155     // the string value overrides the numeric one (for backwards compatibility 
 156     // reasons and also because it is simpler to satisfy the string value which 
 157     // comes much sooner in the list of arguments and leave the initial 
 158     // parameter unspecified) 
 159     if ( !value
.empty() ) 
 162         if ( value
.ToLong(&l
) ) 
 166     wxSize csize 
= size 
; 
 167     m_text 
= new wxSpinCtrlText(this, value
); 
 168     m_btn 
= new wxSpinCtrlButton(this, style
); 
 170     m_btn
->SetRange(min
, max
); 
 171     m_btn
->SetValue(initial
); 
 173     if ( size
.y 
== -1 ) { 
 174       csize
.y 
= m_text
->GetSize().y 
; 
 176     DoSetSize(pos
.x 
, pos
.y 
, csize
.x
, csize
.y
); 
 181 wxSpinCtrl::~wxSpinCtrl() 
 183     // delete the controls now, don't leave them alive even though they would 
 184     // still be eventually deleted by our parent - but it will be too late, the 
 185     // user code expects them to be gone now 
 192 // ---------------------------------------------------------------------------- 
 194 // ---------------------------------------------------------------------------- 
 196 wxSize 
wxSpinCtrl::DoGetBestSize() const 
 198     wxSize sizeBtn 
= m_btn
->GetBestSize(), 
 199            sizeText 
= m_text
->GetBestSize(); 
 201     return wxSize(sizeBtn
.x 
+ sizeText
.x 
+ MARGIN
, sizeText
.y
); 
 204 void wxSpinCtrl::DoMoveWindow(int x
, int y
, int width
, int height
) 
 206     wxControl::DoMoveWindow(x
, y
, width
, height
); 
 208     // position the subcontrols inside the client area 
 209     wxSize sizeBtn 
= m_btn
->GetSize(); 
 211     wxCoord wText 
= width 
- sizeBtn
.x
; 
 212     m_text
->SetSize(0, 0, wText
, height
); 
 213     m_btn
->SetSize(0 + wText 
+ MARGIN
, 0, -1, -1); 
 216 // ---------------------------------------------------------------------------- 
 217 // operations forwarded to the subcontrols 
 218 // ---------------------------------------------------------------------------- 
 220 bool wxSpinCtrl::Enable(bool enable
) 
 222     if ( !wxControl::Enable(enable
) ) 
 227 bool wxSpinCtrl::Show(bool show
) 
 229     if ( !wxControl::Show(show
) ) 
 234 // ---------------------------------------------------------------------------- 
 235 // value and range access 
 236 // ---------------------------------------------------------------------------- 
 238 bool wxSpinCtrl::GetTextValue(int *val
) const 
 241     if ( !m_text
->GetValue().ToLong(&l
) ) 
 243         // not a number at all 
 247     if ( l 
< GetMin() || l 
> GetMax() ) 
 258 int wxSpinCtrl::GetValue() const 
 260     return m_btn 
? m_btn
->GetValue() : 0; 
 263 int wxSpinCtrl::GetMin() const 
 265     return m_btn 
? m_btn
->GetMin() : 0; 
 268 int wxSpinCtrl::GetMax() const 
 270     return m_btn 
? m_btn
->GetMax() : 0; 
 273 // ---------------------------------------------------------------------------- 
 274 // changing value and range 
 275 // ---------------------------------------------------------------------------- 
 277 void wxSpinCtrl::SetTextValue(int val
) 
 279     wxCHECK_RET( m_text
, _T("invalid call to wxSpinCtrl::SetTextValue") ); 
 281     m_text
->SetValue(wxString::Format(_T("%d"), val
)); 
 284     m_text
->SetSelection(0, -1); 
 286     // and give focus to the control! 
 287     // m_text->SetFocus();    Why???? TODO. 
 290 void wxSpinCtrl::SetValue(int val
) 
 292     wxCHECK_RET( m_btn
, _T("invalid call to wxSpinCtrl::SetValue") ); 
 296     m_btn
->SetValue(val
); 
 299 void wxSpinCtrl::SetValue(const wxString
& text
) 
 301     wxCHECK_RET( m_text
, _T("invalid call to wxSpinCtrl::SetValue") ); 
 304     if ( text
.ToLong(&val
) && ((val 
> INT_MIN
) && (val 
< INT_MAX
)) ) 
 308     else // not a number at all or out of range 
 310         m_text
->SetValue(text
); 
 311         m_text
->SetSelection(0, -1); 
 315 void wxSpinCtrl::SetRange(int min
, int max
) 
 317     wxCHECK_RET( m_btn
, _T("invalid call to wxSpinCtrl::SetRange") ); 
 319     m_btn
->SetRange(min
, max
); 
 322 void wxSpinCtrl::SetSelection(long from
, long to
) 
 324     // if from and to are both -1, it means (in wxWidgets) that all text should 
 326     if ( (from 
== -1) && (to 
== -1) ) 
 330     m_text
->SetSelection(from
, to
); 
 333 #endif // wxUSE_SPINCTRL