]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/spinctrl.cpp
Correct slider width when labels are used.
[wxWidgets.git] / src / mac / carbon / 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 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
12 #pragma implementation "spinctrl.h"
13 #endif
14
15 #include "wx/defs.h"
16
17 #if wxUSE_SPINCTRL
18
19 #include "wx/spinbutt.h"
20 #include "wx/spinctrl.h"
21 #include "wx/textctrl.h"
22
23
24 // ----------------------------------------------------------------------------
25 // constants
26 // ----------------------------------------------------------------------------
27
28 // the margin between the text control and the spin
29 static const wxCoord MARGIN = 2;
30
31 // ----------------------------------------------------------------------------
32 // wxSpinCtrlText: text control used by spin control
33 // ----------------------------------------------------------------------------
34
35 class wxSpinCtrlText : public wxTextCtrl
36 {
37 public:
38 wxSpinCtrlText(wxSpinCtrl *spin, const wxString& value)
39 : wxTextCtrl(spin , -1, value)
40 {
41 m_spin = spin;
42
43 // remove the default minsize, the spinctrl will have one instead
44 SetSizeHints(-1,-1);
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 SetWindowStyle(style | wxSP_VERTICAL);
90
91 // TODO: The spin button gets truncated a little bit due to size
92 // differences so change it's default size a bit. SMALL still gets a
93 // bit truncated, but MINI seems to be too small... Readdress this
94 // when the textctrl issues are all sorted out.
95 SetWindowVariant(wxWINDOW_VARIANT_SMALL);
96
97 // remove the default minsize, the spinctrl will have one instead
98 SetSizeHints(-1,-1);
99 }
100
101 protected:
102 void OnSpinButton(wxSpinEvent& eventSpin)
103 {
104 m_spin->SetTextValue(eventSpin.GetPosition());
105
106 wxCommandEvent event(wxEVT_COMMAND_SPINCTRL_UPDATED, m_spin->GetId());
107 event.SetEventObject(m_spin);
108 event.SetInt(eventSpin.GetPosition());
109
110 m_spin->GetEventHandler()->ProcessEvent(event);
111 }
112
113 private:
114 wxSpinCtrl *m_spin;
115
116 DECLARE_EVENT_TABLE()
117 };
118
119 BEGIN_EVENT_TABLE(wxSpinCtrlButton, wxSpinButton)
120 EVT_SPIN(-1, wxSpinCtrlButton::OnSpinButton)
121 END_EVENT_TABLE()
122
123 IMPLEMENT_DYNAMIC_CLASS(wxSpinCtrl, wxControl)
124
125 // ============================================================================
126 // implementation
127 // ============================================================================
128
129 // ----------------------------------------------------------------------------
130 // wxSpinCtrl creation
131 // ----------------------------------------------------------------------------
132
133 void wxSpinCtrl::Init()
134 {
135 m_text = NULL;
136 m_btn = NULL;
137 }
138
139 bool wxSpinCtrl::Create(wxWindow *parent,
140 wxWindowID id,
141 const wxString& value,
142 const wxPoint& pos,
143 const wxSize& size,
144 long style,
145 int min,
146 int max,
147 int initial,
148 const wxString& name)
149 {
150 if ( !wxControl::Create(parent, id, wxDefaultPosition, wxDefaultSize, style,
151 wxDefaultValidator, name) )
152 {
153 return FALSE;
154 }
155
156 // the string value overrides the numeric one (for backwards compatibility
157 // reasons and also because it is simpler to satisfy the string value which
158 // comes much sooner in the list of arguments and leave the initial
159 // parameter unspecified)
160 if ( !value.empty() )
161 {
162 long l;
163 if ( value.ToLong(&l) )
164 initial = l;
165 }
166
167 wxSize csize = size ;
168 m_text = new wxSpinCtrlText(this, value);
169 m_btn = new wxSpinCtrlButton(this, style);
170
171 m_btn->SetRange(min, max);
172 m_btn->SetValue(initial);
173
174 if ( size.y == -1 ) {
175 csize.y = m_text->GetSize().y ;
176 }
177 SetBestSize(csize);
178
179 return TRUE;
180 }
181
182 wxSpinCtrl::~wxSpinCtrl()
183 {
184 // delete the controls now, don't leave them alive even though they would
185 // still be eventually deleted by our parent - but it will be too late, the
186 // user code expects them to be gone now
187 delete m_text;
188 m_text = NULL ;
189 delete m_btn;
190 m_btn = NULL ;
191 }
192
193 // ----------------------------------------------------------------------------
194 // geometry
195 // ----------------------------------------------------------------------------
196
197 wxSize wxSpinCtrl::DoGetBestSize() const
198 {
199 if (!m_btn || !m_text)
200 return GetSize();
201
202 wxSize sizeBtn = m_btn->GetBestSize(),
203 sizeText = m_text->GetBestSize();
204
205 return wxSize(sizeBtn.x + sizeText.x + MARGIN, sizeText.y);
206 }
207
208 void wxSpinCtrl::DoMoveWindow(int x, int y, int width, int height)
209 {
210 wxControl::DoMoveWindow(x, y, width, height);
211
212 // position the subcontrols inside the client area
213 wxSize sizeBtn = m_btn->GetSize();
214
215 wxCoord wText = width - sizeBtn.x;
216 m_text->SetSize(0, 0, wText, height);
217 m_btn->SetSize(0 + wText + MARGIN, 0, -1, height);
218 }
219
220 // ----------------------------------------------------------------------------
221 // operations forwarded to the subcontrols
222 // ----------------------------------------------------------------------------
223
224 bool wxSpinCtrl::Enable(bool enable)
225 {
226 if ( !wxControl::Enable(enable) )
227 return FALSE;
228 return TRUE;
229 }
230
231 bool wxSpinCtrl::Show(bool show)
232 {
233 if ( !wxControl::Show(show) )
234 return FALSE;
235 return TRUE;
236 }
237
238 // ----------------------------------------------------------------------------
239 // value and range access
240 // ----------------------------------------------------------------------------
241
242 bool wxSpinCtrl::GetTextValue(int *val) const
243 {
244 long l;
245 if ( !m_text->GetValue().ToLong(&l) )
246 {
247 // not a number at all
248 return FALSE;
249 }
250
251 if ( l < GetMin() || l > GetMax() )
252 {
253 // out of range
254 return FALSE;
255 }
256
257 *val = l;
258
259 return TRUE;
260 }
261
262 int wxSpinCtrl::GetValue() const
263 {
264 return m_btn ? m_btn->GetValue() : 0;
265 }
266
267 int wxSpinCtrl::GetMin() const
268 {
269 return m_btn ? m_btn->GetMin() : 0;
270 }
271
272 int wxSpinCtrl::GetMax() const
273 {
274 return m_btn ? m_btn->GetMax() : 0;
275 }
276
277 // ----------------------------------------------------------------------------
278 // changing value and range
279 // ----------------------------------------------------------------------------
280
281 void wxSpinCtrl::SetTextValue(int val)
282 {
283 wxCHECK_RET( m_text, _T("invalid call to wxSpinCtrl::SetTextValue") );
284
285 m_text->SetValue(wxString::Format(_T("%d"), val));
286
287 // select all text
288 m_text->SetSelection(0, -1);
289
290 // and give focus to the control!
291 // m_text->SetFocus(); Why???? TODO.
292 }
293
294 void wxSpinCtrl::SetValue(int val)
295 {
296 wxCHECK_RET( m_btn, _T("invalid call to wxSpinCtrl::SetValue") );
297
298 SetTextValue(val);
299
300 m_btn->SetValue(val);
301 }
302
303 void wxSpinCtrl::SetValue(const wxString& text)
304 {
305 wxCHECK_RET( m_text, _T("invalid call to wxSpinCtrl::SetValue") );
306
307 long val;
308 if ( text.ToLong(&val) && ((val > INT_MIN) && (val < INT_MAX)) )
309 {
310 SetValue((int)val);
311 }
312 else // not a number at all or out of range
313 {
314 m_text->SetValue(text);
315 m_text->SetSelection(0, -1);
316 }
317 }
318
319 void wxSpinCtrl::SetRange(int min, int max)
320 {
321 wxCHECK_RET( m_btn, _T("invalid call to wxSpinCtrl::SetRange") );
322
323 m_btn->SetRange(min, max);
324 }
325
326 void wxSpinCtrl::SetSelection(long from, long to)
327 {
328 // if from and to are both -1, it means (in wxWidgets) that all text should
329 // be selected
330 if ( (from == -1) && (to == -1) )
331 {
332 from = 0;
333 }
334 m_text->SetSelection(from, to);
335 }
336
337 #endif // wxUSE_SPINCTRL