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 // There are port-specific versions for MSW, GTK, OS/2 and Mac, so exclude the 
  32 // contents of this file in those cases 
  33 #if !(defined(__WXMSW__) || defined(__WXGTK__) || defined(__WXPM__) || \ 
  34     defined(__WXMAC__)) || defined(__WXUNIVERSAL__) 
  37     #include "wx/textctrl.h" 
  42 #include "wx/spinbutt.h" 
  43 #include "wx/spinctrl.h" 
  45 // ---------------------------------------------------------------------------- 
  47 // ---------------------------------------------------------------------------- 
  49 // the margin between the text control and the spin 
  50 static const wxCoord MARGIN 
= 2; 
  52 // ---------------------------------------------------------------------------- 
  53 // wxSpinCtrlText: text control used by spin control 
  54 // ---------------------------------------------------------------------------- 
  56 class wxSpinCtrlText 
: public wxTextCtrl
 
  59     wxSpinCtrlText(wxSpinCtrl 
*spin
, const wxString
& value
) 
  60         : wxTextCtrl(spin
->GetParent(), wxID_ANY
, value
) 
  64         // remove the default minsize, the spinctrl will have one instead 
  65         SetSizeHints(wxDefaultCoord
,wxDefaultCoord
); 
  69     void OnTextChange(wxCommandEvent
& event
) 
  72         if ( m_spin
->GetTextValue(&val
) ) 
  74             m_spin
->GetSpinButton()->SetValue(val
); 
  80     bool ProcessEvent(wxEvent 
&event
) 
  82         // Hand button down events to wxSpinCtrl. Doesn't work. 
  83         if (event
.GetEventType() == wxEVT_LEFT_DOWN 
&& m_spin
->ProcessEvent( event 
)) 
  86         return wxTextCtrl::ProcessEvent( event 
); 
  95 BEGIN_EVENT_TABLE(wxSpinCtrlText
, wxTextCtrl
) 
  96     EVT_TEXT(wxID_ANY
, wxSpinCtrlText::OnTextChange
) 
  99 // ---------------------------------------------------------------------------- 
 100 // wxSpinCtrlButton: spin button used by spin control 
 101 // ---------------------------------------------------------------------------- 
 103 class wxSpinCtrlButton 
: public wxSpinButton
 
 106     wxSpinCtrlButton(wxSpinCtrl 
*spin
, int style
) 
 107         : wxSpinButton(spin
->GetParent()) 
 111         SetWindowStyle(style 
| wxSP_VERTICAL
); 
 113         // remove the default minsize, the spinctrl will have one instead 
 114         SetSizeHints(wxDefaultCoord
,wxDefaultCoord
); 
 118     void OnSpinButton(wxSpinEvent
& eventSpin
) 
 120         m_spin
->SetTextValue(eventSpin
.GetPosition()); 
 122         wxCommandEvent 
event(wxEVT_COMMAND_SPINCTRL_UPDATED
, m_spin
->GetId()); 
 123         event
.SetEventObject(m_spin
); 
 124         event
.SetInt(eventSpin
.GetPosition()); 
 126         m_spin
->GetEventHandler()->ProcessEvent(event
); 
 134     DECLARE_EVENT_TABLE() 
 137 BEGIN_EVENT_TABLE(wxSpinCtrlButton
, wxSpinButton
) 
 138     EVT_SPIN(wxID_ANY
, wxSpinCtrlButton::OnSpinButton
) 
 141 IMPLEMENT_DYNAMIC_CLASS(wxSpinCtrl
, wxControl
) 
 143 // ============================================================================ 
 145 // ============================================================================ 
 147 // ---------------------------------------------------------------------------- 
 148 // wxSpinCtrl creation 
 149 // ---------------------------------------------------------------------------- 
 151 void wxSpinCtrl::Init() 
 157 bool wxSpinCtrl::Create(wxWindow 
*parent
, 
 159                         const wxString
& value
, 
 160                         const wxPoint
& WXUNUSED(pos
), 
 166                         const wxString
& name
) 
 168     if ( !wxControl::Create(parent
, id
, wxDefaultPosition
, wxDefaultSize
, style
, 
 169                             wxDefaultValidator
, name
) ) 
 174     // the string value overrides the numeric one (for backwards compatibility 
 175     // reasons and also because it is simpler to satisfy the string value which 
 176     // comes much sooner in the list of arguments and leave the initial 
 177     // parameter unspecified) 
 178     if ( !value
.empty() ) 
 181         if ( value
.ToLong(&l
) ) 
 185     m_text 
= new wxSpinCtrlText(this, value
); 
 186     m_btn 
= new wxSpinCtrlButton(this, style
); 
 188     m_btn
->SetRange(min
, max
); 
 189     m_btn
->SetValue(initial
); 
 192     // have to disable this window to avoid interfering it with message 
 193     // processing to the text and the button... but pretend it is enabled to 
 194     // make IsEnabled() return true 
 195     wxControl::Enable(false); // don't use non virtual Disable() here! 
 198     // we don't even need to show this window itself - and not doing it avoids 
 199     // that it overwrites the text control 
 200     wxControl::Show(false); 
 205 wxSpinCtrl::~wxSpinCtrl() 
 207     // delete the controls now, don't leave them alive even though they would 
 208     // still be eventually deleted by our parent - but it will be too late, the 
 209     // user code expects them to be gone now 
 216 // ---------------------------------------------------------------------------- 
 218 // ---------------------------------------------------------------------------- 
 220 wxSize 
wxSpinCtrl::DoGetBestSize() const 
 222     wxSize sizeBtn 
= m_btn
->GetBestSize(), 
 223            sizeText 
= m_text
->GetBestSize(); 
 225     return wxSize(sizeBtn
.x 
+ sizeText
.x 
+ MARGIN
, sizeText
.y
); 
 228 void wxSpinCtrl::DoMoveWindow(int x
, int y
, int width
, int height
) 
 230     wxControl::DoMoveWindow(x
, y
, width
, height
); 
 232     // position the subcontrols inside the client area 
 233     wxSize sizeBtn 
= m_btn
->GetSize(); 
 235     wxCoord wText 
= width 
- sizeBtn
.x
; 
 236     m_text
->SetSize(x
, y
, wText
, height
); 
 237     m_btn
->SetSize(x 
+ wText 
+ MARGIN
, y
, wxDefaultCoord
, height
); 
 240 // ---------------------------------------------------------------------------- 
 241 // operations forwarded to the subcontrols 
 242 // ---------------------------------------------------------------------------- 
 244 bool wxSpinCtrl::Enable(bool enable
) 
 246     if ( !wxControl::Enable(enable
) ) 
 249     m_btn
->Enable(enable
); 
 250     m_text
->Enable(enable
); 
 255 bool wxSpinCtrl::Show(bool show
) 
 257     if ( !wxControl::Show(show
) ) 
 260     // under GTK Show() is called the first time before we are fully 
 271 // ---------------------------------------------------------------------------- 
 272 // value and range access 
 273 // ---------------------------------------------------------------------------- 
 275 bool wxSpinCtrl::GetTextValue(int *val
) const 
 278     if ( !m_text
->GetValue().ToLong(&l
) ) 
 280         // not a number at all 
 284     if ( l 
< GetMin() || l 
> GetMax() ) 
 295 int wxSpinCtrl::GetValue() const 
 297     return m_btn 
? m_btn
->GetValue() : 0; 
 300 int wxSpinCtrl::GetMin() const 
 302     return m_btn 
? m_btn
->GetMin() : 0; 
 305 int wxSpinCtrl::GetMax() const 
 307     return m_btn 
? m_btn
->GetMax() : 0; 
 310 // ---------------------------------------------------------------------------- 
 311 // changing value and range 
 312 // ---------------------------------------------------------------------------- 
 314 void wxSpinCtrl::SetTextValue(int val
) 
 316     wxCHECK_RET( m_text
, _T("invalid call to wxSpinCtrl::SetTextValue") ); 
 318     m_text
->SetValue(wxString::Format(_T("%d"), val
)); 
 321     m_text
->SetSelection(0, -1); 
 323     // and give focus to the control! 
 324     // m_text->SetFocus();    Why???? TODO. 
 327 void wxSpinCtrl::SetValue(int val
) 
 329     wxCHECK_RET( m_btn
, _T("invalid call to wxSpinCtrl::SetValue") ); 
 333     m_btn
->SetValue(val
); 
 336 void wxSpinCtrl::SetValue(const wxString
& text
) 
 338     wxCHECK_RET( m_text
, _T("invalid call to wxSpinCtrl::SetValue") ); 
 341     if ( text
.ToLong(&val
) && ((val 
> INT_MIN
) && (val 
< INT_MAX
)) ) 
 345     else // not a number at all or out of range 
 347         m_text
->SetValue(text
); 
 348         m_text
->SetSelection(0, -1); 
 352 void wxSpinCtrl::SetRange(int min
, int max
) 
 354     wxCHECK_RET( m_btn
, _T("invalid call to wxSpinCtrl::SetRange") ); 
 356     m_btn
->SetRange(min
, max
); 
 359 void wxSpinCtrl::SetSelection(long from
, long to
) 
 361     wxCHECK_RET( m_text
, _T("invalid call to wxSpinCtrl::SetSelection") ); 
 363     m_text
->SetSelection(from
, to
); 
 366 #endif // wxUSE_SPINCTRL 
 367 #endif // !wxPort-with-native-spinctrl