Further wxUniv fixes
[wxWidgets.git] / src / generic / spinctlg.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/generic/spinctlg.cpp
3 // Purpose: implements wxSpinCtrl as a composite control
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 29.01.01
7 // RCS-ID: $Id$
8 // Copyright: (c) 2001 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // License: wxWindows license
10 ///////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 #ifdef __GNUG__
21 #pragma implementation "spinctlg.h"
22 #endif
23
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
26
27 #ifdef __BORLANDC__
28 #pragma hdrstop
29 #endif
30
31 #if !wxUSE_SPINBTN
32 #error "This file can only be compiled if wxSpinButton is available"
33 #endif // !wxUSE_SPINBTN
34
35 #ifndef WX_PRECOMP
36 #include "wx/textctrl.h"
37 #endif //WX_PRECOMP
38
39 #include "wx/spinbutt.h"
40 #include "wx/spinctrl.h"
41
42 // ----------------------------------------------------------------------------
43 // constants
44 // ----------------------------------------------------------------------------
45
46 // the margin between the text control and the spin
47 static const wxCoord MARGIN = 2;
48
49 // ----------------------------------------------------------------------------
50 // wxSpinCtrlText: text control used by spin control
51 // ----------------------------------------------------------------------------
52
53 class wxSpinCtrlText : public wxTextCtrl
54 {
55 public:
56 wxSpinCtrlText(wxSpinCtrl *spin, const wxString& value)
57 : wxTextCtrl(spin->GetParent(), -1, value)
58 {
59 m_spin = spin;
60 }
61
62 protected:
63 void OnTextChange(wxCommandEvent& event)
64 {
65 int val;
66 if ( m_spin->GetTextValue(&val) )
67 {
68 m_spin->GetSpinButton()->SetValue(val);
69 }
70
71 event.Skip();
72 }
73
74 private:
75 wxSpinCtrl *m_spin;
76
77 DECLARE_EVENT_TABLE()
78 };
79
80 BEGIN_EVENT_TABLE(wxSpinCtrlText, wxTextCtrl)
81 EVT_TEXT(-1, wxSpinCtrlText::OnTextChange)
82 END_EVENT_TABLE()
83
84 // ----------------------------------------------------------------------------
85 // wxSpinCtrlButton: spin button used by spin control
86 // ----------------------------------------------------------------------------
87
88 class wxSpinCtrlButton : public wxSpinButton
89 {
90 public:
91 wxSpinCtrlButton(wxSpinCtrl *spin, int style)
92 : wxSpinButton(spin->GetParent())
93 {
94 m_spin = spin;
95
96 SetWindowStyle(style);
97 }
98
99 protected:
100 void OnSpinButton(wxSpinEvent& event)
101 {
102 m_spin->SetTextValue(event.GetPosition());
103
104 event.Skip();
105 }
106
107 private:
108 wxSpinCtrl *m_spin;
109
110 DECLARE_EVENT_TABLE()
111 };
112
113 BEGIN_EVENT_TABLE(wxSpinCtrlButton, wxSpinButton)
114 EVT_SPIN(-1, wxSpinCtrlButton::OnSpinButton)
115 END_EVENT_TABLE()
116
117 IMPLEMENT_DYNAMIC_CLASS(wxSpinCtrl, wxControl)
118
119 // ============================================================================
120 // implementation
121 // ============================================================================
122
123 // ----------------------------------------------------------------------------
124 // wxSpinCtrl creation
125 // ----------------------------------------------------------------------------
126
127 void wxSpinCtrl::Init()
128 {
129 m_text = NULL;
130 m_btn = NULL;
131 }
132
133 bool wxSpinCtrl::Create(wxWindow *parent,
134 wxWindowID id,
135 const wxString& value,
136 const wxPoint& pos,
137 const wxSize& size,
138 long style,
139 int min,
140 int max,
141 int initial,
142 const wxString& name)
143 {
144 if ( !wxControl::Create(parent, id, pos, size, style,
145 wxDefaultValidator, name) )
146 {
147 return FALSE;
148 }
149
150 SetBackgroundColour(*wxRED);
151
152 m_text = new wxSpinCtrlText(this, value);
153 m_btn = new wxSpinCtrlButton(this, style);
154
155 m_btn->SetRange(min, max);
156 m_btn->SetValue(initial);
157
158 DoSetSize(pos.x, pos.y, size.x, size.y);
159
160 // have to disable this window to avoid interfering it with message
161 // processing to the text and the button... but pretend it is enabled to
162 // make IsEnabled() return TRUE
163 wxControl::Enable(FALSE); // don't use non virtual Disable() here!
164 m_isEnabled = TRUE;
165
166 // we don't even need to show this window itself - and not doing it avoids
167 // that it overwrites the text control
168 wxControl::Show(FALSE);
169 m_isShown = TRUE;
170
171 return TRUE;
172 }
173
174 wxSpinCtrl::~wxSpinCtrl()
175 {
176 // delete the controls now, don't leave them alive even though they woudl
177 // still be eventually deleted by our parent - but it will be too late, the
178 // user code expects them to be gone now
179 delete m_text;
180 delete m_btn;
181 }
182
183 // ----------------------------------------------------------------------------
184 // geometry
185 // ----------------------------------------------------------------------------
186
187 wxSize wxSpinCtrl::DoGetBestClientSize() const
188 {
189 wxSize sizeBtn = m_btn->GetBestSize(),
190 sizeText = m_text->GetBestSize();
191
192 return wxSize(sizeBtn.x + sizeText.x + MARGIN, sizeText.y);
193 }
194
195 void wxSpinCtrl::DoMoveWindow(int x, int y, int width, int height)
196 {
197 wxControl::DoMoveWindow(x, y, width, height);
198
199 // position the subcontrols inside the client area
200 wxSize sizeBtn = m_btn->GetSize(),
201 sizeText = m_text->GetSize();
202
203 wxCoord wText = width - sizeBtn.x;
204 m_text->SetSize(x, y, wText, height);
205 m_btn->SetSize(x + wText + MARGIN, y, -1, height);
206 }
207
208 // ----------------------------------------------------------------------------
209 // operations forwarded to the subcontrols
210 // ----------------------------------------------------------------------------
211
212 bool wxSpinCtrl::Enable(bool enable)
213 {
214 if ( !wxControl::Enable(enable) )
215 return FALSE;
216
217 m_btn->Enable(enable);
218 m_text->Enable(enable);
219
220 return TRUE;
221 }
222
223 bool wxSpinCtrl::Show(bool show)
224 {
225 if ( !wxControl::Show(show) )
226 return FALSE;
227
228 m_btn->Show(show);
229 m_text->Show(show);
230
231 return TRUE;
232 }
233
234 // ----------------------------------------------------------------------------
235 // value and range access
236 // ----------------------------------------------------------------------------
237
238 bool wxSpinCtrl::GetTextValue(int *val) const
239 {
240 long l;
241 if ( !m_text->GetValue().ToLong(&l) )
242 {
243 // not a number at all
244 return FALSE;
245 }
246
247 if ( l < GetMin() || l > GetMax() )
248 {
249 // out of range
250 return FALSE;
251 }
252
253 *val = l;
254
255 return TRUE;
256 }
257
258 int wxSpinCtrl::GetValue() const
259 {
260 return m_btn ? m_btn->GetValue() : 0;
261 }
262
263 int wxSpinCtrl::GetMin() const
264 {
265 return m_btn ? m_btn->GetMin() : 0;
266 }
267
268 int wxSpinCtrl::GetMax() const
269 {
270 return m_btn ? m_btn->GetMax() : 0;
271 }
272
273 // ----------------------------------------------------------------------------
274 // changing value and range
275 // ----------------------------------------------------------------------------
276
277 void wxSpinCtrl::SetTextValue(int val)
278 {
279 wxCHECK_RET( m_text, _T("invalid call to wxSpinCtrl::SetTextValue") );
280
281 m_text->SetValue(wxString::Format(_T("%d"), val));
282
283 // select all text
284 m_text->SetSelection(0, -1);
285
286 // and give focus to the control!
287 m_text->SetFocus();
288 }
289
290 void wxSpinCtrl::SetValue(int val)
291 {
292 wxCHECK_RET( m_btn, _T("invalid call to wxSpinCtrl::SetValue") );
293
294 SetTextValue(val);
295
296 m_btn->SetValue(val);
297 }
298
299 void wxSpinCtrl::SetValue(const wxString& text)
300 {
301 wxCHECK_RET( m_text, _T("invalid call to wxSpinCtrl::SetValue") );
302
303 long val;
304 if ( text.ToLong(&val) && ((val > INT_MIN) && (val < INT_MAX)) )
305 {
306 SetValue((int)val);
307 }
308 else // not a number at all or out of range
309 {
310 m_text->SetValue(text);
311 m_text->SetSelection(0, -1);
312 }
313 }
314
315 void wxSpinCtrl::SetRange(int min, int max)
316 {
317 wxCHECK_RET( m_btn, _T("invalid call to wxSpinCtrl::SetRange") );
318
319 m_btn->SetRange(min, max);
320 }
321