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