]> git.saurik.com Git - wxWidgets.git/blob - src/mac/spinctrl.cpp
Always use XPMs in this sample
[wxWidgets.git] / src / mac / spinctrl.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: 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 #ifdef __GNUG__
12 #pragma implementation "spinctlg.h"
13 #endif
14
15 #include "wx/defs.h"
16
17 #ifndef WX_PRECOMP
18 #include "wx/textctrl.h"
19 #endif //WX_PRECOMP
20
21 #if wxUSE_SPINCTRL
22
23 #include "wx/spinbutt.h"
24 #include "wx/spinctrl.h"
25
26
27 #include "wx/spinctrl.h"
28
29 // ----------------------------------------------------------------------------
30 // constants
31 // ----------------------------------------------------------------------------
32
33 // the margin between the text control and the spin
34 static const wxCoord MARGIN = 2;
35
36 // ----------------------------------------------------------------------------
37 // wxSpinCtrlText: text control used by spin control
38 // ----------------------------------------------------------------------------
39
40 class wxSpinCtrlText : public wxTextCtrl
41 {
42 public:
43 wxSpinCtrlText(wxSpinCtrl *spin, const wxString& value)
44 : wxTextCtrl(spin , -1, value)
45 {
46 m_spin = spin;
47 }
48
49 protected:
50 void OnTextChange(wxCommandEvent& event)
51 {
52 int val;
53 if ( m_spin->GetTextValue(&val) )
54 {
55 m_spin->GetSpinButton()->SetValue(val);
56 }
57
58 event.Skip();
59 }
60
61 bool ProcessEvent(wxEvent &event)
62 {
63 // Hand button down events to wxSpinCtrl. Doesn't work.
64 if (event.GetEventType() == wxEVT_LEFT_DOWN && m_spin->ProcessEvent( event ))
65 return TRUE;
66
67 return wxTextCtrl::ProcessEvent( event );
68 }
69
70 private:
71 wxSpinCtrl *m_spin;
72
73 DECLARE_EVENT_TABLE()
74 };
75
76 BEGIN_EVENT_TABLE(wxSpinCtrlText, wxTextCtrl)
77 EVT_TEXT(-1, wxSpinCtrlText::OnTextChange)
78 END_EVENT_TABLE()
79
80 // ----------------------------------------------------------------------------
81 // wxSpinCtrlButton: spin button used by spin control
82 // ----------------------------------------------------------------------------
83
84 class wxSpinCtrlButton : public wxSpinButton
85 {
86 public:
87 wxSpinCtrlButton(wxSpinCtrl *spin, int style)
88 : wxSpinButton(spin )
89 {
90 m_spin = spin;
91
92 SetWindowStyle(style | wxSP_VERTICAL);
93 }
94
95 protected:
96 void OnSpinButton(wxSpinEvent& eventSpin)
97 {
98 #if defined(__WXMAC__) || defined(__WXMOTIF__)
99 m_spin->SetTextValue(eventSpin.GetPosition());
100
101 wxCommandEvent event(wxEVT_COMMAND_SPINCTRL_UPDATED, m_spin->GetId());
102 event.SetEventObject(m_spin);
103 event.SetInt(eventSpin.GetPosition());
104
105 m_spin->GetEventHandler()->ProcessEvent(event);
106 #else
107 m_spin->SetTextValue(eventSpin.GetPosition());
108 eventSpin.Skip();
109 #endif
110 }
111
112 private:
113 wxSpinCtrl *m_spin;
114
115 DECLARE_EVENT_TABLE()
116 };
117
118 BEGIN_EVENT_TABLE(wxSpinCtrlButton, wxSpinButton)
119 EVT_SPIN(-1, wxSpinCtrlButton::OnSpinButton)
120 END_EVENT_TABLE()
121
122 IMPLEMENT_DYNAMIC_CLASS(wxSpinCtrl, wxControl)
123
124 // ============================================================================
125 // implementation
126 // ============================================================================
127
128 // ----------------------------------------------------------------------------
129 // wxSpinCtrl creation
130 // ----------------------------------------------------------------------------
131
132 void wxSpinCtrl::Init()
133 {
134 m_text = NULL;
135 m_btn = NULL;
136 }
137
138 bool wxSpinCtrl::Create(wxWindow *parent,
139 wxWindowID id,
140 const wxString& value,
141 const wxPoint& pos,
142 const wxSize& size,
143 long style,
144 int min,
145 int max,
146 int initial,
147 const wxString& name)
148 {
149 if ( !wxControl::Create(parent, id, wxDefaultPosition, wxDefaultSize, style,
150 wxDefaultValidator, name) )
151 {
152 return FALSE;
153 }
154
155 // the string value overrides the numeric one (for backwards compatibility
156 // reasons and also because it is simpler to satisfy the string value which
157 // comes much sooner in the list of arguments and leave the initial
158 // parameter unspecified)
159 if ( !value.empty() )
160 {
161 long l;
162 if ( value.ToLong(&l) )
163 initial = l;
164 }
165
166 wxSize csize = size ;
167 m_text = new wxSpinCtrlText(this, value);
168 m_btn = new wxSpinCtrlButton(this, style);
169
170 m_btn->SetRange(min, max);
171 m_btn->SetValue(initial);
172
173 if ( size.y == -1 ) {
174 csize.y = m_text->GetSize().y ;
175 }
176 DoSetSize(pos.x , pos.y , csize.x, csize.y);
177
178 return TRUE;
179 }
180
181 wxSpinCtrl::~wxSpinCtrl()
182 {
183 // delete the controls now, don't leave them alive even though they would
184 // still be eventually deleted by our parent - but it will be too late, the
185 // user code expects them to be gone now
186 delete m_text;
187 m_text = NULL ;
188 delete m_btn;
189 m_btn = NULL ;
190 }
191
192 // ----------------------------------------------------------------------------
193 // geometry
194 // ----------------------------------------------------------------------------
195
196 wxSize wxSpinCtrl::DoGetBestSize() const
197 {
198 wxSize sizeBtn = m_btn->GetBestSize(),
199 sizeText = m_text->GetBestSize();
200
201 return wxSize(sizeBtn.x + sizeText.x + MARGIN, sizeText.y);
202 }
203
204 void wxSpinCtrl::DoMoveWindow(int x, int y, int width, int height)
205 {
206 wxControl::DoMoveWindow(x, y, width, height);
207
208 // position the subcontrols inside the client area
209 wxSize sizeBtn = m_btn->GetSize();
210
211 wxCoord wText = width - sizeBtn.x;
212 m_text->SetSize(0, 0, wText, height);
213 m_btn->SetSize(0 + wText + MARGIN, 0, -1, -1);
214 }
215
216 // ----------------------------------------------------------------------------
217 // operations forwarded to the subcontrols
218 // ----------------------------------------------------------------------------
219
220 bool wxSpinCtrl::Enable(bool enable)
221 {
222 if ( !wxControl::Enable(enable) )
223 return FALSE;
224 return TRUE;
225 }
226
227 bool wxSpinCtrl::Show(bool show)
228 {
229 if ( !wxControl::Show(show) )
230 return FALSE;
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(); Why???? TODO.
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
322 void wxSpinCtrl::SetSelection(long from, long to)
323 {
324 // if from and to are both -1, it means (in wxWindows) that all text should
325 // be selected
326 if ( (from == -1) && (to == -1) )
327 {
328 from = 0;
329 }
330 m_text->SetSelection(from, to);
331 }
332
333 #endif // wxUSE_SPINCTRL