]> git.saurik.com Git - wxWidgets.git/blob - src/generic/spinctlg.cpp
fixed wxString char<->wchar_t conversion constructors to not truncate strings and...
[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 licence
10 ///////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
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 // 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__)
35
36 #ifndef WX_PRECOMP
37 #include "wx/textctrl.h"
38 #endif //WX_PRECOMP
39
40 #if wxUSE_SPINCTRL
41
42 #include "wx/spinbutt.h"
43 #include "wx/spinctrl.h"
44
45 // ----------------------------------------------------------------------------
46 // constants
47 // ----------------------------------------------------------------------------
48
49 // the margin between the text control and the spin
50 static const wxCoord MARGIN = 2;
51
52 // ----------------------------------------------------------------------------
53 // wxSpinCtrlText: text control used by spin control
54 // ----------------------------------------------------------------------------
55
56 class wxSpinCtrlText : public wxTextCtrl
57 {
58 public:
59 wxSpinCtrlText(wxSpinCtrl *spin, const wxString& value)
60 : wxTextCtrl(spin->GetParent(), wxID_ANY, value)
61 {
62 m_spin = spin;
63
64 // remove the default minsize, the spinctrl will have one instead
65 SetSizeHints(wxDefaultSize.x,wxDefaultSize.y);
66 }
67
68 protected:
69 void OnTextChange(wxCommandEvent& event)
70 {
71 int val;
72 if ( m_spin->GetTextValue(&val) )
73 {
74 m_spin->GetSpinButton()->SetValue(val);
75 }
76
77 event.Skip();
78 }
79
80 bool ProcessEvent(wxEvent &event)
81 {
82 // Hand button down events to wxSpinCtrl. Doesn't work.
83 if (event.GetEventType() == wxEVT_LEFT_DOWN && m_spin->ProcessEvent( event ))
84 return true;
85
86 return wxTextCtrl::ProcessEvent( event );
87 }
88
89 private:
90 wxSpinCtrl *m_spin;
91
92 DECLARE_EVENT_TABLE()
93 };
94
95 BEGIN_EVENT_TABLE(wxSpinCtrlText, wxTextCtrl)
96 EVT_TEXT(wxID_ANY, wxSpinCtrlText::OnTextChange)
97 END_EVENT_TABLE()
98
99 // ----------------------------------------------------------------------------
100 // wxSpinCtrlButton: spin button used by spin control
101 // ----------------------------------------------------------------------------
102
103 class wxSpinCtrlButton : public wxSpinButton
104 {
105 public:
106 wxSpinCtrlButton(wxSpinCtrl *spin, int style)
107 : wxSpinButton(spin->GetParent())
108 {
109 m_spin = spin;
110
111 SetWindowStyle(style | wxSP_VERTICAL);
112
113 // remove the default minsize, the spinctrl will have one instead
114 SetSizeHints(wxDefaultSize.x,wxDefaultSize.y);
115 }
116
117 protected:
118 void OnSpinButton(wxSpinEvent& eventSpin)
119 {
120 m_spin->SetTextValue(eventSpin.GetPosition());
121
122 wxCommandEvent event(wxEVT_COMMAND_SPINCTRL_UPDATED, m_spin->GetId());
123 event.SetEventObject(m_spin);
124 event.SetInt(eventSpin.GetPosition());
125
126 m_spin->GetEventHandler()->ProcessEvent(event);
127
128 eventSpin.Skip();
129 }
130
131 private:
132 wxSpinCtrl *m_spin;
133
134 DECLARE_EVENT_TABLE()
135 };
136
137 BEGIN_EVENT_TABLE(wxSpinCtrlButton, wxSpinButton)
138 EVT_SPIN(wxID_ANY, wxSpinCtrlButton::OnSpinButton)
139 END_EVENT_TABLE()
140
141 IMPLEMENT_DYNAMIC_CLASS(wxSpinCtrl, wxControl)
142
143 // ============================================================================
144 // implementation
145 // ============================================================================
146
147 // ----------------------------------------------------------------------------
148 // wxSpinCtrl creation
149 // ----------------------------------------------------------------------------
150
151 void wxSpinCtrl::Init()
152 {
153 m_text = NULL;
154 m_btn = NULL;
155 }
156
157 bool wxSpinCtrl::Create(wxWindow *parent,
158 wxWindowID id,
159 const wxString& value,
160 const wxPoint& WXUNUSED(pos),
161 const wxSize& size,
162 long style,
163 int min,
164 int max,
165 int initial,
166 const wxString& name)
167 {
168 if ( !wxControl::Create(parent, id, wxDefaultPosition, wxDefaultSize, style,
169 wxDefaultValidator, name) )
170 {
171 return false;
172 }
173
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() )
179 {
180 long l;
181 if ( value.ToLong(&l) )
182 initial = l;
183 }
184
185 m_text = new wxSpinCtrlText(this, value);
186 m_btn = new wxSpinCtrlButton(this, style);
187
188 m_btn->SetRange(min, max);
189 m_btn->SetValue(initial);
190 SetBestSize(size);
191
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!
196 m_isEnabled = true;
197
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);
201 m_isShown = true;
202 return true;
203 }
204
205 wxSpinCtrl::~wxSpinCtrl()
206 {
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
210 delete m_text;
211 m_text = NULL ;
212 delete m_btn;
213 m_btn = NULL ;
214 }
215
216 // ----------------------------------------------------------------------------
217 // geometry
218 // ----------------------------------------------------------------------------
219
220 wxSize wxSpinCtrl::DoGetBestSize() const
221 {
222 wxSize sizeBtn = m_btn->GetBestSize(),
223 sizeText = m_text->GetBestSize();
224
225 return wxSize(sizeBtn.x + sizeText.x + MARGIN, sizeText.y);
226 }
227
228 void wxSpinCtrl::DoMoveWindow(int x, int y, int width, int height)
229 {
230 wxControl::DoMoveWindow(x, y, width, height);
231
232 // position the subcontrols inside the client area
233 wxSize sizeBtn = m_btn->GetSize();
234
235 wxCoord wText = width - sizeBtn.x;
236 m_text->SetSize(x, y, wText, height);
237 m_btn->SetSize(x + wText + MARGIN, y, wxDefaultSize.x, height);
238 }
239
240 // ----------------------------------------------------------------------------
241 // operations forwarded to the subcontrols
242 // ----------------------------------------------------------------------------
243
244 bool wxSpinCtrl::Enable(bool enable)
245 {
246 if ( !wxControl::Enable(enable) )
247 return false;
248
249 m_btn->Enable(enable);
250 m_text->Enable(enable);
251
252 return true;
253 }
254
255 bool wxSpinCtrl::Show(bool show)
256 {
257 if ( !wxControl::Show(show) )
258 return false;
259
260 // under GTK Show() is called the first time before we are fully
261 // constructed
262 if ( m_btn )
263 {
264 m_btn->Show(show);
265 m_text->Show(show);
266 }
267
268 return true;
269 }
270
271 // ----------------------------------------------------------------------------
272 // value and range access
273 // ----------------------------------------------------------------------------
274
275 bool wxSpinCtrl::GetTextValue(int *val) const
276 {
277 long l;
278 if ( !m_text->GetValue().ToLong(&l) )
279 {
280 // not a number at all
281 return false;
282 }
283
284 if ( l < GetMin() || l > GetMax() )
285 {
286 // out of range
287 return false;
288 }
289
290 *val = l;
291
292 return true;
293 }
294
295 int wxSpinCtrl::GetValue() const
296 {
297 return m_btn ? m_btn->GetValue() : 0;
298 }
299
300 int wxSpinCtrl::GetMin() const
301 {
302 return m_btn ? m_btn->GetMin() : 0;
303 }
304
305 int wxSpinCtrl::GetMax() const
306 {
307 return m_btn ? m_btn->GetMax() : 0;
308 }
309
310 // ----------------------------------------------------------------------------
311 // changing value and range
312 // ----------------------------------------------------------------------------
313
314 void wxSpinCtrl::SetTextValue(int val)
315 {
316 wxCHECK_RET( m_text, _T("invalid call to wxSpinCtrl::SetTextValue") );
317
318 m_text->SetValue(wxString::Format(_T("%d"), val));
319
320 // select all text
321 m_text->SetSelection(0, -1);
322
323 // and give focus to the control!
324 // m_text->SetFocus(); Why???? TODO.
325 }
326
327 void wxSpinCtrl::SetValue(int val)
328 {
329 wxCHECK_RET( m_btn, _T("invalid call to wxSpinCtrl::SetValue") );
330
331 SetTextValue(val);
332
333 m_btn->SetValue(val);
334 }
335
336 void wxSpinCtrl::SetValue(const wxString& text)
337 {
338 wxCHECK_RET( m_text, _T("invalid call to wxSpinCtrl::SetValue") );
339
340 long val;
341 if ( text.ToLong(&val) && ((val > INT_MIN) && (val < INT_MAX)) )
342 {
343 SetValue((int)val);
344 }
345 else // not a number at all or out of range
346 {
347 m_text->SetValue(text);
348 m_text->SetSelection(0, -1);
349 }
350 }
351
352 void wxSpinCtrl::SetRange(int min, int max)
353 {
354 wxCHECK_RET( m_btn, _T("invalid call to wxSpinCtrl::SetRange") );
355
356 m_btn->SetRange(min, max);
357 }
358
359 void wxSpinCtrl::SetSelection(long from, long to)
360 {
361 wxCHECK_RET( m_text, _T("invalid call to wxSpinCtrl::SetSelection") );
362
363 m_text->SetSelection(from, to);
364 }
365
366 #endif // wxUSE_SPINCTRL
367 #endif // !wxPort-with-native-spinctrl