]> git.saurik.com Git - wxWidgets.git/blob - src/mac/classic/spinctrl.cpp
don't reset the selection after event was vetoed if there is no old selection
[wxWidgets.git] / src / mac / classic / spinctrl.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/mac/classic/spinbutt.cpp
3 // Purpose: wxSpinCtrl
4 // Author: Robert
5 // Modified by: Mark Newsam (Based on GTK file)
6 // RCS-ID: $Id$
7 // Copyright: (c) Robert Roebling
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10
11 #include "wx/wxprec.h"
12
13 #ifdef __BORLANDC__
14 #pragma hdrstop
15 #endif
16
17 #if wxUSE_SPINCTRL
18
19 #include "wx/spinctrl.h"
20
21 #ifndef WX_PRECOMP
22 #include "wx/textctrl.h"
23 #endif //WX_PRECOMP
24
25 #include "wx/spinbutt.h"
26
27 // ----------------------------------------------------------------------------
28 // constants
29 // ----------------------------------------------------------------------------
30
31 // the margin between the text control and the spin
32 static const wxCoord MARGIN = 2;
33
34 // ----------------------------------------------------------------------------
35 // wxSpinCtrlText: text control used by spin control
36 // ----------------------------------------------------------------------------
37
38 class wxSpinCtrlText : public wxTextCtrl
39 {
40 public:
41 wxSpinCtrlText(wxSpinCtrl *spin, const wxString& value)
42 : wxTextCtrl(spin , -1, value)
43 {
44 m_spin = spin;
45 }
46
47 protected:
48 void OnTextChange(wxCommandEvent& event)
49 {
50 int val;
51 if ( m_spin->GetTextValue(&val) )
52 {
53 m_spin->GetSpinButton()->SetValue(val);
54 }
55
56 event.Skip();
57 }
58
59 bool ProcessEvent(wxEvent &event)
60 {
61 // Hand button down events to wxSpinCtrl. Doesn't work.
62 if (event.GetEventType() == wxEVT_LEFT_DOWN && m_spin->ProcessEvent( event ))
63 return true;
64
65 return wxTextCtrl::ProcessEvent( event );
66 }
67
68 private:
69 wxSpinCtrl *m_spin;
70
71 DECLARE_EVENT_TABLE()
72 };
73
74 BEGIN_EVENT_TABLE(wxSpinCtrlText, wxTextCtrl)
75 EVT_TEXT(-1, wxSpinCtrlText::OnTextChange)
76 END_EVENT_TABLE()
77
78 // ----------------------------------------------------------------------------
79 // wxSpinCtrlButton: spin button used by spin control
80 // ----------------------------------------------------------------------------
81
82 class wxSpinCtrlButton : public wxSpinButton
83 {
84 public:
85 wxSpinCtrlButton(wxSpinCtrl *spin, int style)
86 : wxSpinButton(spin )
87 {
88 m_spin = spin;
89
90 SetWindowStyle(style | wxSP_VERTICAL);
91 }
92
93 protected:
94 void OnSpinButton(wxSpinEvent& eventSpin)
95 {
96 #if defined(__WXMAC__) || defined(__WXMOTIF__)
97 m_spin->SetTextValue(eventSpin.GetPosition());
98
99 wxCommandEvent event(wxEVT_COMMAND_SPINCTRL_UPDATED, m_spin->GetId());
100 event.SetEventObject(m_spin);
101 event.SetInt(eventSpin.GetPosition());
102
103 m_spin->GetEventHandler()->ProcessEvent(event);
104 #else
105 m_spin->SetTextValue(eventSpin.GetPosition());
106 eventSpin.Skip();
107 #endif
108 }
109
110 private:
111 wxSpinCtrl *m_spin;
112
113 DECLARE_EVENT_TABLE()
114 };
115
116 BEGIN_EVENT_TABLE(wxSpinCtrlButton, wxSpinButton)
117 EVT_SPIN(-1, wxSpinCtrlButton::OnSpinButton)
118 END_EVENT_TABLE()
119
120 IMPLEMENT_DYNAMIC_CLASS(wxSpinCtrl, wxControl)
121
122 // ============================================================================
123 // implementation
124 // ============================================================================
125
126 // ----------------------------------------------------------------------------
127 // wxSpinCtrl creation
128 // ----------------------------------------------------------------------------
129
130 void wxSpinCtrl::Init()
131 {
132 m_text = NULL;
133 m_btn = NULL;
134 }
135
136 bool wxSpinCtrl::Create(wxWindow *parent,
137 wxWindowID id,
138 const wxString& value,
139 const wxPoint& pos,
140 const wxSize& size,
141 long style,
142 int min,
143 int max,
144 int initial,
145 const wxString& name)
146 {
147 if ( !wxControl::Create(parent, id, wxDefaultPosition, wxDefaultSize, style,
148 wxDefaultValidator, name) )
149 {
150 return false;
151 }
152
153 // the string value overrides the numeric one (for backwards compatibility
154 // reasons and also because it is simpler to satisfy the string value which
155 // comes much sooner in the list of arguments and leave the initial
156 // parameter unspecified)
157 if ( !value.empty() )
158 {
159 long l;
160 if ( value.ToLong(&l) )
161 initial = l;
162 }
163
164 wxSize csize = size ;
165 m_text = new wxSpinCtrlText(this, value);
166 m_btn = new wxSpinCtrlButton(this, style);
167
168 m_btn->SetRange(min, max);
169 m_btn->SetValue(initial);
170
171 if ( size.y == -1 ) {
172 csize.y = m_text->GetSize().y ;
173 }
174 DoSetSize(pos.x , pos.y , csize.x, csize.y);
175
176 return true;
177 }
178
179 wxSpinCtrl::~wxSpinCtrl()
180 {
181 // delete the controls now, don't leave them alive even though they would
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 m_text = NULL ;
186 delete m_btn;
187 m_btn = NULL ;
188 }
189
190 // ----------------------------------------------------------------------------
191 // geometry
192 // ----------------------------------------------------------------------------
193
194 wxSize wxSpinCtrl::DoGetBestSize() const
195 {
196 wxSize sizeBtn = m_btn->GetBestSize(),
197 sizeText = m_text->GetBestSize();
198
199 return wxSize(sizeBtn.x + sizeText.x + MARGIN, sizeText.y);
200 }
201
202 void wxSpinCtrl::DoMoveWindow(int x, int y, int width, int height)
203 {
204 wxControl::DoMoveWindow(x, y, width, height);
205
206 // position the subcontrols inside the client area
207 wxSize sizeBtn = m_btn->GetSize();
208
209 wxCoord wText = width - sizeBtn.x;
210 m_text->SetSize(0, 0, wText, height);
211 m_btn->SetSize(0 + wText + MARGIN, 0, -1, -1);
212 }
213
214 // ----------------------------------------------------------------------------
215 // operations forwarded to the subcontrols
216 // ----------------------------------------------------------------------------
217
218 bool wxSpinCtrl::Enable(bool enable)
219 {
220 if ( !wxControl::Enable(enable) )
221 return false;
222 return true;
223 }
224
225 bool wxSpinCtrl::Show(bool show)
226 {
227 if ( !wxControl::Show(show) )
228 return false;
229 return true;
230 }
231
232 // ----------------------------------------------------------------------------
233 // value and range access
234 // ----------------------------------------------------------------------------
235
236 bool wxSpinCtrl::GetTextValue(int *val) const
237 {
238 long l;
239 if ( !m_text->GetValue().ToLong(&l) )
240 {
241 // not a number at all
242 return false;
243 }
244
245 if ( l < GetMin() || l > GetMax() )
246 {
247 // out of range
248 return false;
249 }
250
251 *val = l;
252
253 return true;
254 }
255
256 int wxSpinCtrl::GetValue() const
257 {
258 return m_btn ? m_btn->GetValue() : 0;
259 }
260
261 int wxSpinCtrl::GetMin() const
262 {
263 return m_btn ? m_btn->GetMin() : 0;
264 }
265
266 int wxSpinCtrl::GetMax() const
267 {
268 return m_btn ? m_btn->GetMax() : 0;
269 }
270
271 // ----------------------------------------------------------------------------
272 // changing value and range
273 // ----------------------------------------------------------------------------
274
275 void wxSpinCtrl::SetTextValue(int val)
276 {
277 wxCHECK_RET( m_text, _T("invalid call to wxSpinCtrl::SetTextValue") );
278
279 m_text->SetValue(wxString::Format(_T("%d"), val));
280
281 // select all text
282 m_text->SetSelection(0, -1);
283
284 // and give focus to the control!
285 // m_text->SetFocus(); Why???? TODO.
286 }
287
288 void wxSpinCtrl::SetValue(int val)
289 {
290 wxCHECK_RET( m_btn, _T("invalid call to wxSpinCtrl::SetValue") );
291
292 SetTextValue(val);
293
294 m_btn->SetValue(val);
295 }
296
297 void wxSpinCtrl::SetValue(const wxString& text)
298 {
299 wxCHECK_RET( m_text, _T("invalid call to wxSpinCtrl::SetValue") );
300
301 long val;
302 if ( text.ToLong(&val) && ((val > INT_MIN) && (val < INT_MAX)) )
303 {
304 SetValue((int)val);
305 }
306 else // not a number at all or out of range
307 {
308 m_text->SetValue(text);
309 m_text->SetSelection(0, -1);
310 }
311 }
312
313 void wxSpinCtrl::SetRange(int min, int max)
314 {
315 wxCHECK_RET( m_btn, _T("invalid call to wxSpinCtrl::SetRange") );
316
317 m_btn->SetRange(min, max);
318 }
319
320 void wxSpinCtrl::SetSelection(long from, long to)
321 {
322 // if from and to are both -1, it means (in wxWidgets) that all text should
323 // be selected
324 if ( (from == -1) && (to == -1) )
325 {
326 from = 0;
327 }
328 m_text->SetSelection(from, to);
329 }
330
331 #endif // wxUSE_SPINCTRL