]> git.saurik.com Git - wxWidgets.git/blame - src/generic/spinctlg.cpp
don't pass NULL pointer to printf(), this crashes Solaris printf
[wxWidgets.git] / src / generic / spinctlg.cpp
CommitLineData
21709999
JS
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>
65571936 9// License: wxWindows licence
21709999
JS
10///////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
14f355c2 20#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
21709999
JS
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
571d14b2
RD
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__)
21709999
JS
35
36#ifndef WX_PRECOMP
37 #include "wx/textctrl.h"
38#endif //WX_PRECOMP
39
c67d6888
JS
40#if wxUSE_SPINCTRL
41
21709999
JS
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
50static const wxCoord MARGIN = 2;
51
52// ----------------------------------------------------------------------------
53// wxSpinCtrlText: text control used by spin control
54// ----------------------------------------------------------------------------
55
56class wxSpinCtrlText : public wxTextCtrl
57{
58public:
59 wxSpinCtrlText(wxSpinCtrl *spin, const wxString& value)
3fb79396 60 : wxTextCtrl(spin->GetParent(), wxID_ANY, value)
21709999
JS
61 {
62 m_spin = spin;
ca65c044 63
e459a794 64 // remove the default minsize, the spinctrl will have one instead
422d0ff0 65 SetSizeHints(wxDefaultCoord,wxDefaultCoord);
21709999
JS
66 }
67
68protected:
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 }
71e03035 79
23d416bf
RR
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 ))
3fb79396 84 return true;
71e03035 85
23d416bf
RR
86 return wxTextCtrl::ProcessEvent( event );
87 }
21709999
JS
88
89private:
90 wxSpinCtrl *m_spin;
91
92 DECLARE_EVENT_TABLE()
93};
94
95BEGIN_EVENT_TABLE(wxSpinCtrlText, wxTextCtrl)
3fb79396 96 EVT_TEXT(wxID_ANY, wxSpinCtrlText::OnTextChange)
21709999
JS
97END_EVENT_TABLE()
98
99// ----------------------------------------------------------------------------
100// wxSpinCtrlButton: spin button used by spin control
101// ----------------------------------------------------------------------------
102
103class wxSpinCtrlButton : public wxSpinButton
104{
105public:
106 wxSpinCtrlButton(wxSpinCtrl *spin, int style)
107 : wxSpinButton(spin->GetParent())
108 {
109 m_spin = spin;
110
71e03035 111 SetWindowStyle(style | wxSP_VERTICAL);
e459a794
RD
112
113 // remove the default minsize, the spinctrl will have one instead
422d0ff0 114 SetSizeHints(wxDefaultCoord,wxDefaultCoord);
21709999
JS
115 }
116
117protected:
63efc55f 118 void OnSpinButton(wxSpinEvent& eventSpin)
21709999 119 {
c1eb1102 120 m_spin->SetTextValue(eventSpin.GetPosition());
63efc55f 121
c1eb1102
VZ
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);
21709999 127
5d0000b5 128 eventSpin.Skip();
21709999
JS
129 }
130
131private:
132 wxSpinCtrl *m_spin;
133
134 DECLARE_EVENT_TABLE()
135};
136
137BEGIN_EVENT_TABLE(wxSpinCtrlButton, wxSpinButton)
3fb79396 138 EVT_SPIN(wxID_ANY, wxSpinCtrlButton::OnSpinButton)
21709999
JS
139END_EVENT_TABLE()
140
141IMPLEMENT_DYNAMIC_CLASS(wxSpinCtrl, wxControl)
739555e3 142
21709999
JS
143// ============================================================================
144// implementation
145// ============================================================================
146
147// ----------------------------------------------------------------------------
148// wxSpinCtrl creation
149// ----------------------------------------------------------------------------
150
151void wxSpinCtrl::Init()
152{
153 m_text = NULL;
154 m_btn = NULL;
155}
156
157bool wxSpinCtrl::Create(wxWindow *parent,
158 wxWindowID id,
159 const wxString& value,
9cb6c9a0 160 const wxPoint& pos,
21709999
JS
161 const wxSize& size,
162 long style,
163 int min,
164 int max,
165 int initial,
166 const wxString& name)
167{
094ca819 168 if ( !wxControl::Create(parent, id, wxDefaultPosition, wxDefaultSize, style,
21709999
JS
169 wxDefaultValidator, name) )
170 {
3fb79396 171 return false;
21709999
JS
172 }
173
71e03035
VZ
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
21709999
JS
185 m_text = new wxSpinCtrlText(this, value);
186 m_btn = new wxSpinCtrlButton(this, style);
ca65c044 187
21709999
JS
188 m_btn->SetRange(min, max);
189 m_btn->SetValue(initial);
e459a794 190 SetBestSize(size);
9cb6c9a0 191 Move(pos);
ca65c044 192
21709999
JS
193 // have to disable this window to avoid interfering it with message
194 // processing to the text and the button... but pretend it is enabled to
3fb79396
WS
195 // make IsEnabled() return true
196 wxControl::Enable(false); // don't use non virtual Disable() here!
197 m_isEnabled = true;
21709999
JS
198
199 // we don't even need to show this window itself - and not doing it avoids
200 // that it overwrites the text control
3fb79396
WS
201 wxControl::Show(false);
202 m_isShown = true;
203 return true;
21709999
JS
204}
205
206wxSpinCtrl::~wxSpinCtrl()
207{
e459a794 208 // delete the controls now, don't leave them alive even though they would
21709999
JS
209 // still be eventually deleted by our parent - but it will be too late, the
210 // user code expects them to be gone now
211 delete m_text;
e459a794 212 m_text = NULL ;
21709999 213 delete m_btn;
e459a794 214 m_btn = NULL ;
21709999
JS
215}
216
217// ----------------------------------------------------------------------------
218// geometry
219// ----------------------------------------------------------------------------
220
dba00620 221wxSize wxSpinCtrl::DoGetBestSize() const
21709999
JS
222{
223 wxSize sizeBtn = m_btn->GetBestSize(),
224 sizeText = m_text->GetBestSize();
225
226 return wxSize(sizeBtn.x + sizeText.x + MARGIN, sizeText.y);
227}
228
229void wxSpinCtrl::DoMoveWindow(int x, int y, int width, int height)
230{
231 wxControl::DoMoveWindow(x, y, width, height);
232
233 // position the subcontrols inside the client area
3379ed37 234 wxSize sizeBtn = m_btn->GetSize();
21709999
JS
235
236 wxCoord wText = width - sizeBtn.x;
e466fe5f 237 m_text->SetSize(x, y, wText, height);
422d0ff0 238 m_btn->SetSize(x + wText + MARGIN, y, wxDefaultCoord, height);
21709999
JS
239}
240
241// ----------------------------------------------------------------------------
242// operations forwarded to the subcontrols
243// ----------------------------------------------------------------------------
244
245bool wxSpinCtrl::Enable(bool enable)
246{
247 if ( !wxControl::Enable(enable) )
3fb79396 248 return false;
21709999
JS
249
250 m_btn->Enable(enable);
251 m_text->Enable(enable);
252
3fb79396 253 return true;
21709999
JS
254}
255
256bool wxSpinCtrl::Show(bool show)
257{
258 if ( !wxControl::Show(show) )
3fb79396 259 return false;
21709999 260
3379ed37
VZ
261 // under GTK Show() is called the first time before we are fully
262 // constructed
263 if ( m_btn )
264 {
265 m_btn->Show(show);
266 m_text->Show(show);
267 }
21709999 268
3fb79396 269 return true;
21709999
JS
270}
271
272// ----------------------------------------------------------------------------
273// value and range access
274// ----------------------------------------------------------------------------
275
276bool wxSpinCtrl::GetTextValue(int *val) const
277{
278 long l;
279 if ( !m_text->GetValue().ToLong(&l) )
280 {
281 // not a number at all
3fb79396 282 return false;
21709999
JS
283 }
284
285 if ( l < GetMin() || l > GetMax() )
286 {
287 // out of range
3fb79396 288 return false;
21709999
JS
289 }
290
291 *val = l;
292
3fb79396 293 return true;
21709999
JS
294}
295
296int wxSpinCtrl::GetValue() const
297{
298 return m_btn ? m_btn->GetValue() : 0;
299}
300
301int wxSpinCtrl::GetMin() const
302{
303 return m_btn ? m_btn->GetMin() : 0;
304}
305
306int wxSpinCtrl::GetMax() const
307{
308 return m_btn ? m_btn->GetMax() : 0;
309}
310
311// ----------------------------------------------------------------------------
312// changing value and range
313// ----------------------------------------------------------------------------
314
315void wxSpinCtrl::SetTextValue(int val)
316{
317 wxCHECK_RET( m_text, _T("invalid call to wxSpinCtrl::SetTextValue") );
318
319 m_text->SetValue(wxString::Format(_T("%d"), val));
320
321 // select all text
322 m_text->SetSelection(0, -1);
323
324 // and give focus to the control!
d45906e0 325 // m_text->SetFocus(); Why???? TODO.
21709999
JS
326}
327
328void wxSpinCtrl::SetValue(int val)
329{
330 wxCHECK_RET( m_btn, _T("invalid call to wxSpinCtrl::SetValue") );
331
332 SetTextValue(val);
333
334 m_btn->SetValue(val);
335}
336
337void wxSpinCtrl::SetValue(const wxString& text)
338{
339 wxCHECK_RET( m_text, _T("invalid call to wxSpinCtrl::SetValue") );
340
341 long val;
342 if ( text.ToLong(&val) && ((val > INT_MIN) && (val < INT_MAX)) )
343 {
344 SetValue((int)val);
345 }
346 else // not a number at all or out of range
347 {
348 m_text->SetValue(text);
349 m_text->SetSelection(0, -1);
350 }
351}
352
353void wxSpinCtrl::SetRange(int min, int max)
354{
355 wxCHECK_RET( m_btn, _T("invalid call to wxSpinCtrl::SetRange") );
356
357 m_btn->SetRange(min, max);
358}
359
739555e3
VZ
360void wxSpinCtrl::SetSelection(long from, long to)
361{
362 wxCHECK_RET( m_text, _T("invalid call to wxSpinCtrl::SetSelection") );
363
364 m_text->SetSelection(from, to);
365}
366
c67d6888 367#endif // wxUSE_SPINCTRL
3379ed37 368#endif // !wxPort-with-native-spinctrl