1 /////////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/generic/spinctlg.cpp 
   3 // Purpose:     implements wxSpinCtrl as a composite control 
   4 // Author:      Vadim Zeitlin 
   8 // Copyright:   (c) 2001 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr> 
   9 // License:     wxWindows licence 
  10 /////////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  20 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) 
  21     #pragma implementation "spinctlg.h" 
  24 // For compilers that support precompilation, includes "wx.h". 
  25 #include "wx/wxprec.h" 
  31 #if !(defined(__WXMSW__) || defined(__WXGTK__) || defined(__WXPM__)) || \ 
  32     defined(__WXMAC__) || defined(__WXUNIVERSAL__) 
  35     #include "wx/textctrl.h" 
  40 #include "wx/spinbutt.h" 
  41 #include "wx/spinctrl.h" 
  43 // ---------------------------------------------------------------------------- 
  45 // ---------------------------------------------------------------------------- 
  47 // the margin between the text control and the spin 
  49 static const wxCoord MARGIN 
= 4; 
  51 static const wxCoord MARGIN 
= 2; 
  54 // ---------------------------------------------------------------------------- 
  55 // wxSpinCtrlText: text control used by spin control 
  56 // ---------------------------------------------------------------------------- 
  58 class wxSpinCtrlText 
: public wxTextCtrl
 
  61     wxSpinCtrlText(wxSpinCtrl 
*spin
, const wxString
& value
) 
  62         : wxTextCtrl(spin
->GetParent(), -1, value
) 
  66         // remove the default minsize, the spinctrl will have one instead 
  71     void OnTextChange(wxCommandEvent
& event
) 
  74         if ( m_spin
->GetTextValue(&val
) ) 
  76             m_spin
->GetSpinButton()->SetValue(val
); 
  82     bool ProcessEvent(wxEvent 
&event
) 
  84         // Hand button down events to wxSpinCtrl. Doesn't work. 
  85         if (event
.GetEventType() == wxEVT_LEFT_DOWN 
&& m_spin
->ProcessEvent( event 
)) 
  88         return wxTextCtrl::ProcessEvent( event 
); 
  97 BEGIN_EVENT_TABLE(wxSpinCtrlText
, wxTextCtrl
) 
  98     EVT_TEXT(-1, wxSpinCtrlText::OnTextChange
) 
 101 // ---------------------------------------------------------------------------- 
 102 // wxSpinCtrlButton: spin button used by spin control 
 103 // ---------------------------------------------------------------------------- 
 105 class wxSpinCtrlButton 
: public wxSpinButton
 
 108     wxSpinCtrlButton(wxSpinCtrl 
*spin
, int style
) 
 109         : wxSpinButton(spin
->GetParent()) 
 113         SetWindowStyle(style 
| wxSP_VERTICAL
); 
 115         // remove the default minsize, the spinctrl will have one instead 
 120     void OnSpinButton(wxSpinEvent
& eventSpin
) 
 122         m_spin
->SetTextValue(eventSpin
.GetPosition()); 
 124         wxCommandEvent 
event(wxEVT_COMMAND_SPINCTRL_UPDATED
, m_spin
->GetId()); 
 125         event
.SetEventObject(m_spin
); 
 126         event
.SetInt(eventSpin
.GetPosition()); 
 128         m_spin
->GetEventHandler()->ProcessEvent(event
); 
 136     DECLARE_EVENT_TABLE() 
 139 BEGIN_EVENT_TABLE(wxSpinCtrlButton
, wxSpinButton
) 
 140     EVT_SPIN(-1, wxSpinCtrlButton::OnSpinButton
) 
 143 IMPLEMENT_DYNAMIC_CLASS(wxSpinCtrl
, wxControl
) 
 145 // ============================================================================ 
 147 // ============================================================================ 
 149 // ---------------------------------------------------------------------------- 
 150 // wxSpinCtrl creation 
 151 // ---------------------------------------------------------------------------- 
 153 void wxSpinCtrl::Init() 
 159 bool wxSpinCtrl::Create(wxWindow 
*parent
, 
 161                         const wxString
& value
, 
 168                         const wxString
& name
) 
 170     if ( !wxControl::Create(parent
, id
, wxDefaultPosition
, wxDefaultSize
, style
, 
 171                             wxDefaultValidator
, name
) ) 
 176     // the string value overrides the numeric one (for backwards compatibility 
 177     // reasons and also because it is simpler to satisfy the string value which 
 178     // comes much sooner in the list of arguments and leave the initial 
 179     // parameter unspecified) 
 180     if ( !value
.empty() ) 
 183         if ( value
.ToLong(&l
) ) 
 187     m_text 
= new wxSpinCtrlText(this, value
); 
 188     m_btn 
= new wxSpinCtrlButton(this, style
); 
 190     m_btn
->SetRange(min
, max
); 
 191     m_btn
->SetValue(initial
); 
 193     wxSize csize 
= size 
; 
 194     if ( size
.y 
== -1 ) { 
 195       csize
.y 
= m_text
->GetSize().y
; 
 202     // have to disable this window to avoid interfering it with message 
 203     // processing to the text and the button... but pretend it is enabled to 
 204     // make IsEnabled() return TRUE 
 205     wxControl::Enable(FALSE
); // don't use non virtual Disable() here! 
 208     // we don't even need to show this window itself - and not doing it avoids 
 209     // that it overwrites the text control 
 210     wxControl::Show(FALSE
); 
 217 wxSpinCtrl::~wxSpinCtrl() 
 219     // delete the controls now, don't leave them alive even though they would 
 220     // still be eventually deleted by our parent - but it will be too late, the 
 221     // user code expects them to be gone now 
 228 // ---------------------------------------------------------------------------- 
 230 // ---------------------------------------------------------------------------- 
 232 wxSize 
wxSpinCtrl::DoGetBestSize() const 
 234     wxSize sizeBtn 
= m_btn
->GetBestSize(), 
 235            sizeText 
= m_text
->GetBestSize(); 
 237     return wxSize(sizeBtn
.x 
+ sizeText
.x 
+ MARGIN
, sizeText
.y
); 
 240 void wxSpinCtrl::DoMoveWindow(int x
, int y
, int width
, int height
) 
 242     wxControl::DoMoveWindow(x
, y
, width
, height
); 
 244     // position the subcontrols inside the client area 
 245     wxSize sizeBtn 
= m_btn
->GetSize(); 
 247     wxCoord wText 
= width 
- sizeBtn
.x
; 
 248     m_text
->SetSize(x
, y
, wText
, height
); 
 249     m_btn
->SetSize(x 
+ wText 
+ MARGIN
, y
, -1, height
); 
 252 // ---------------------------------------------------------------------------- 
 253 // operations forwarded to the subcontrols 
 254 // ---------------------------------------------------------------------------- 
 256 bool wxSpinCtrl::Enable(bool enable
) 
 258     if ( !wxControl::Enable(enable
) ) 
 261     m_btn
->Enable(enable
); 
 262     m_text
->Enable(enable
); 
 267 bool wxSpinCtrl::Show(bool show
) 
 269     if ( !wxControl::Show(show
) ) 
 272     // under GTK Show() is called the first time before we are fully 
 283 // ---------------------------------------------------------------------------- 
 284 // value and range access 
 285 // ---------------------------------------------------------------------------- 
 287 bool wxSpinCtrl::GetTextValue(int *val
) const 
 290     if ( !m_text
->GetValue().ToLong(&l
) ) 
 292         // not a number at all 
 296     if ( l 
< GetMin() || l 
> GetMax() ) 
 307 int wxSpinCtrl::GetValue() const 
 309     return m_btn 
? m_btn
->GetValue() : 0; 
 312 int wxSpinCtrl::GetMin() const 
 314     return m_btn 
? m_btn
->GetMin() : 0; 
 317 int wxSpinCtrl::GetMax() const 
 319     return m_btn 
? m_btn
->GetMax() : 0; 
 322 // ---------------------------------------------------------------------------- 
 323 // changing value and range 
 324 // ---------------------------------------------------------------------------- 
 326 void wxSpinCtrl::SetTextValue(int val
) 
 328     wxCHECK_RET( m_text
, _T("invalid call to wxSpinCtrl::SetTextValue") ); 
 330     m_text
->SetValue(wxString::Format(_T("%d"), val
)); 
 333     m_text
->SetSelection(0, -1); 
 335     // and give focus to the control! 
 336     // m_text->SetFocus();    Why???? TODO. 
 339 void wxSpinCtrl::SetValue(int val
) 
 341     wxCHECK_RET( m_btn
, _T("invalid call to wxSpinCtrl::SetValue") ); 
 345     m_btn
->SetValue(val
); 
 348 void wxSpinCtrl::SetValue(const wxString
& text
) 
 350     wxCHECK_RET( m_text
, _T("invalid call to wxSpinCtrl::SetValue") ); 
 353     if ( text
.ToLong(&val
) && ((val 
> INT_MIN
) && (val 
< INT_MAX
)) ) 
 357     else // not a number at all or out of range 
 359         m_text
->SetValue(text
); 
 360         m_text
->SetSelection(0, -1); 
 364 void wxSpinCtrl::SetRange(int min
, int max
) 
 366     wxCHECK_RET( m_btn
, _T("invalid call to wxSpinCtrl::SetRange") ); 
 368     m_btn
->SetRange(min
, max
); 
 371 void wxSpinCtrl::SetSelection(long from
, long to
) 
 373     wxCHECK_RET( m_text
, _T("invalid call to wxSpinCtrl::SetSelection") ); 
 375     m_text
->SetSelection(from
, to
); 
 378 #endif // wxUSE_SPINCTRL 
 379 #endif // !wxPort-with-native-spinctrl