]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/spinctrl.cpp
sometimes mutexes are used before our module is initialized
[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 wxSize sizeBtn = m_btn->GetBestSize(),
200 sizeText = m_text->GetBestSize();
201
202 return wxSize(sizeBtn.x + sizeText.x + MARGIN, sizeText.y);
203 }
204
205 void wxSpinCtrl::DoMoveWindow(int x, int y, int width, int height)
206 {
207 wxControl::DoMoveWindow(x, y, width, height);
208
209 // position the subcontrols inside the client area
210 wxSize sizeBtn = m_btn->GetSize();
211
212 wxCoord wText = width - sizeBtn.x;
213 m_text->SetSize(0, 0, wText, height);
214 m_btn->SetSize(0 + wText + MARGIN, 0, -1, height);
215 }
216
217 // ----------------------------------------------------------------------------
218 // operations forwarded to the subcontrols
219 // ----------------------------------------------------------------------------
220
221 bool wxSpinCtrl::Enable(bool enable)
222 {
223 if ( !wxControl::Enable(enable) )
224 return FALSE;
225 return TRUE;
226 }
227
228 bool wxSpinCtrl::Show(bool show)
229 {
230 if ( !wxControl::Show(show) )
231 return FALSE;
232 return TRUE;
233 }
234
235 // ----------------------------------------------------------------------------
236 // value and range access
237 // ----------------------------------------------------------------------------
238
239 bool wxSpinCtrl::GetTextValue(int *val) const
240 {
241 long l;
242 if ( !m_text->GetValue().ToLong(&l) )
243 {
244 // not a number at all
245 return FALSE;
246 }
247
248 if ( l < GetMin() || l > GetMax() )
249 {
250 // out of range
251 return FALSE;
252 }
253
254 *val = l;
255
256 return TRUE;
257 }
258
259 int wxSpinCtrl::GetValue() const
260 {
261 return m_btn ? m_btn->GetValue() : 0;
262 }
263
264 int wxSpinCtrl::GetMin() const
265 {
266 return m_btn ? m_btn->GetMin() : 0;
267 }
268
269 int wxSpinCtrl::GetMax() const
270 {
271 return m_btn ? m_btn->GetMax() : 0;
272 }
273
274 // ----------------------------------------------------------------------------
275 // changing value and range
276 // ----------------------------------------------------------------------------
277
278 void wxSpinCtrl::SetTextValue(int val)
279 {
280 wxCHECK_RET( m_text, _T("invalid call to wxSpinCtrl::SetTextValue") );
281
282 m_text->SetValue(wxString::Format(_T("%d"), val));
283
284 // select all text
285 m_text->SetSelection(0, -1);
286
287 // and give focus to the control!
288 // m_text->SetFocus(); Why???? TODO.
289 }
290
291 void wxSpinCtrl::SetValue(int val)
292 {
293 wxCHECK_RET( m_btn, _T("invalid call to wxSpinCtrl::SetValue") );
294
295 SetTextValue(val);
296
297 m_btn->SetValue(val);
298 }
299
300 void wxSpinCtrl::SetValue(const wxString& text)
301 {
302 wxCHECK_RET( m_text, _T("invalid call to wxSpinCtrl::SetValue") );
303
304 long val;
305 if ( text.ToLong(&val) && ((val > INT_MIN) && (val < INT_MAX)) )
306 {
307 SetValue((int)val);
308 }
309 else // not a number at all or out of range
310 {
311 m_text->SetValue(text);
312 m_text->SetSelection(0, -1);
313 }
314 }
315
316 void wxSpinCtrl::SetRange(int min, int max)
317 {
318 wxCHECK_RET( m_btn, _T("invalid call to wxSpinCtrl::SetRange") );
319
320 m_btn->SetRange(min, max);
321 }
322
323 void wxSpinCtrl::SetSelection(long from, long to)
324 {
325 // if from and to are both -1, it means (in wxWindows) that all text should
326 // be selected
327 if ( (from == -1) && (to == -1) )
328 {
329 from = 0;
330 }
331 m_text->SetSelection(from, to);
332 }
333
334 #endif // wxUSE_SPINCTRL