1 /////////////////////////////////////////////////////////////////////////////
5 // Modified by: Mark Newsam (Based on GTK file)
7 // Copyright: (c) Robert Roebling
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 #include "wx/wxprec.h"
15 #include "wx/spinbutt.h"
16 #include "wx/spinctrl.h"
17 #include "wx/textctrl.h"
20 // ----------------------------------------------------------------------------
22 // ----------------------------------------------------------------------------
24 // the focus rect around a text may have 4 pixels in each direction
25 // we handle these problems right now in an extended vis region of a window
26 static const wxCoord TEXTBORDER
= 4 ;
27 // the margin between the text control and the spin
28 static const wxCoord MARGIN
= 8 - TEXTBORDER
;
30 // ----------------------------------------------------------------------------
31 // wxSpinCtrlText: text control used by spin control
32 // ----------------------------------------------------------------------------
34 class wxSpinCtrlText
: public wxTextCtrl
37 wxSpinCtrlText(wxSpinCtrl
*spin
, const wxString
& value
)
38 : wxTextCtrl(spin
, -1, value
, wxDefaultPosition
, wxSize(40, -1))
42 // remove the default minsize, the spinctrl will have one instead
47 void OnTextChange(wxCommandEvent
& event
)
50 if ( m_spin
->GetTextValue(&val
) )
52 m_spin
->GetSpinButton()->SetValue(val
);
54 // If we're already processing a text update from m_spin,
55 // don't send it again, since we could end up recursing
57 if (event
.GetId() == m_spin
->GetId())
63 // Send event that the text was manually changed
64 wxCommandEvent
event(wxEVT_COMMAND_TEXT_UPDATED
, m_spin
->GetId());
65 event
.SetEventObject(m_spin
);
68 m_spin
->GetEventHandler()->ProcessEvent(event
);
74 bool ProcessEvent(wxEvent
&event
)
76 // Hand button down events to wxSpinCtrl. Doesn't work.
77 if (event
.GetEventType() == wxEVT_LEFT_DOWN
&& m_spin
->ProcessEvent( event
))
80 return wxTextCtrl::ProcessEvent( event
);
89 BEGIN_EVENT_TABLE(wxSpinCtrlText
, wxTextCtrl
)
90 EVT_TEXT(-1, wxSpinCtrlText::OnTextChange
)
93 // ----------------------------------------------------------------------------
94 // wxSpinCtrlButton: spin button used by spin control
95 // ----------------------------------------------------------------------------
97 class wxSpinCtrlButton
: public wxSpinButton
100 wxSpinCtrlButton(wxSpinCtrl
*spin
, int style
)
101 : wxSpinButton(spin
)
104 SetWindowStyle(style
| wxSP_VERTICAL
);
106 // TODO: The spin button gets truncated a little bit due to size
107 // differences so change it's default size a bit. SMALL still gets a
108 // bit truncated, but MINI seems to be too small... Readdress this
109 // when the textctrl issues are all sorted out.
110 //SetWindowVariant(wxWINDOW_VARIANT_SMALL);
112 // remove the default minsize, the spinctrl will have one instead
117 void OnSpinButton(wxSpinEvent
& eventSpin
)
119 m_spin
->SetTextValue(eventSpin
.GetPosition());
121 wxCommandEvent
event(wxEVT_COMMAND_SPINCTRL_UPDATED
, m_spin
->GetId());
122 event
.SetEventObject(m_spin
);
123 event
.SetInt(eventSpin
.GetPosition());
125 m_spin
->GetEventHandler()->ProcessEvent(event
);
131 DECLARE_EVENT_TABLE()
134 BEGIN_EVENT_TABLE(wxSpinCtrlButton
, wxSpinButton
)
135 EVT_SPIN(-1, wxSpinCtrlButton::OnSpinButton
)
138 IMPLEMENT_DYNAMIC_CLASS(wxSpinCtrl
, wxControl
)
140 // ============================================================================
142 // ============================================================================
144 // ----------------------------------------------------------------------------
145 // wxSpinCtrl creation
146 // ----------------------------------------------------------------------------
148 void wxSpinCtrl::Init()
154 bool wxSpinCtrl::Create(wxWindow
*parent
,
156 const wxString
& value
,
163 const wxString
& name
)
165 m_macIsUserPane
= true;
166 if ( !wxControl::Create(parent
, id
, pos
, size
, style
,
167 wxDefaultValidator
, name
) )
172 // the string value overrides the numeric one (for backwards compatibility
173 // reasons and also because it is simpler to satisfy the string value which
174 // comes much sooner in the list of arguments and leave the initial
175 // parameter unspecified)
176 if ( !value
.empty() )
179 if ( value
.ToLong(&l
) )
183 wxSize csize
= size
;
184 m_text
= new wxSpinCtrlText(this, value
);
185 m_btn
= new wxSpinCtrlButton(this, style
);
187 m_btn
->SetRange(min
, max
);
188 m_btn
->SetValue(initial
);
191 csize
.x
= m_text
->GetSize().x
+ MARGIN
+ m_btn
->GetSize().x
;
194 if ( size
.y
== -1 ) {
195 csize
.y
= m_text
->GetSize().y
+ 2 * TEXTBORDER
; //allow for text border highlights
196 if ( m_btn
->GetSize().y
> csize
.y
)
197 csize
.y
= m_btn
->GetSize().y
;
202 //MacPostControlCreate(pos, csize);
203 SetInitialBestSize(csize
);
208 wxSpinCtrl::~wxSpinCtrl()
210 // delete the controls now, don't leave them alive even though they would
211 // still be eventually deleted by our parent - but it will be too late, the
212 // user code expects them to be gone now
219 // ----------------------------------------------------------------------------
221 // ----------------------------------------------------------------------------
223 wxSize
wxSpinCtrl::DoGetBestSize() const
225 if (!m_btn
|| !m_text
)
228 wxSize sizeBtn
= m_btn
->GetBestSize(),
229 sizeText
= m_text
->GetBestSize();
231 sizeText
.y
+= 2 * TEXTBORDER
;
232 sizeText
.x
+= 2 * TEXTBORDER
;
235 if (sizeText
.y
> sizeBtn
.y
)
240 return wxSize(sizeBtn
.x
+ sizeText
.x
+ MARGIN
, height
);
243 void wxSpinCtrl::DoMoveWindow(int x
, int y
, int width
, int height
)
245 // position the subcontrols inside the client area
246 wxSize sizeBtn
= m_btn
->GetSize();
247 wxSize sizeText
= m_text
->GetSize();
249 wxControl::DoMoveWindow(x
, y
, width
, height
);
251 wxCoord wText
= width
- sizeBtn
.x
- MARGIN
- 2 * TEXTBORDER
;
253 m_text
->SetSize(TEXTBORDER
, (height
- sizeText
.y
) / 2, wText
, -1);
254 m_btn
->SetSize(0 + wText
+ MARGIN
+ 2 * TEXTBORDER
, (height
- sizeBtn
.y
) / 2 , -1, -1 );
257 // ----------------------------------------------------------------------------
258 // operations forwarded to the subcontrols
259 // ----------------------------------------------------------------------------
261 bool wxSpinCtrl::Enable(bool enable
)
263 if ( !wxControl::Enable(enable
) )
268 bool wxSpinCtrl::Show(bool show
)
270 if ( !wxControl::Show(show
) )
275 void wxSpinCtrl::SetFocus()
277 if ( m_text
!= NULL
) {
282 // ----------------------------------------------------------------------------
283 // value and range access
284 // ----------------------------------------------------------------------------
286 bool wxSpinCtrl::GetTextValue(int *val
) const
289 if ( !m_text
->GetValue().ToLong(&l
) )
291 // not a number at all
295 if ( l
< GetMin() || l
> GetMax() )
306 int wxSpinCtrl::GetValue() const
308 return m_btn
? m_btn
->GetValue() : 0;
311 int wxSpinCtrl::GetMin() const
313 return m_btn
? m_btn
->GetMin() : 0;
316 int wxSpinCtrl::GetMax() const
318 return m_btn
? m_btn
->GetMax() : 0;
321 // ----------------------------------------------------------------------------
322 // changing value and range
323 // ----------------------------------------------------------------------------
325 void wxSpinCtrl::SetTextValue(int val
)
327 wxCHECK_RET( m_text
, _T("invalid call to wxSpinCtrl::SetTextValue") );
329 m_text
->SetValue(wxString::Format(_T("%d"), val
));
332 m_text
->SetSelection(0, -1);
334 // and give focus to the control!
335 // m_text->SetFocus(); Why???? TODO.
338 void wxSpinCtrl::SetValue(int val
)
340 wxCHECK_RET( m_btn
, _T("invalid call to wxSpinCtrl::SetValue") );
344 m_btn
->SetValue(val
);
347 void wxSpinCtrl::SetValue(const wxString
& text
)
349 wxCHECK_RET( m_text
, _T("invalid call to wxSpinCtrl::SetValue") );
352 if ( text
.ToLong(&val
) && ((val
> INT_MIN
) && (val
< INT_MAX
)) )
356 else // not a number at all or out of range
358 m_text
->SetValue(text
);
359 m_text
->SetSelection(0, -1);
363 void wxSpinCtrl::SetRange(int min
, int max
)
365 wxCHECK_RET( m_btn
, _T("invalid call to wxSpinCtrl::SetRange") );
367 m_btn
->SetRange(min
, max
);
370 void wxSpinCtrl::SetSelection(long from
, long to
)
372 // if from and to are both -1, it means (in wxWidgets) that all text should
374 if ( (from
== -1) && (to
== -1) )
378 m_text
->SetSelection(from
, to
);
381 #endif // wxUSE_SPINCTRL