]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/spinctrl.cpp
As reported by Chris Elliott some releases of Lesstif crash
[wxWidgets.git] / src / mac / carbon / spinctrl.cpp
CommitLineData
a5bc50ee
GD
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
65571936 8// Licence: wxWindows licence
a5bc50ee
GD
9/////////////////////////////////////////////////////////////////////////////
10
571d14b2
RD
11#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
12#pragma implementation "spinctrl.h"
a5bc50ee
GD
13#endif
14
3d1a4878 15#include "wx/wxprec.h"
a5bc50ee
GD
16
17#if wxUSE_SPINCTRL
18
327788ac 19#include "wx/spinbutt.h"
a842a96e 20#include "wx/spinctrl.h"
571d14b2 21#include "wx/textctrl.h"
a842a96e 22
a5bc50ee 23
327788ac
SC
24// ----------------------------------------------------------------------------
25// constants
26// ----------------------------------------------------------------------------
a842a96e 27
0fa8508d
SC
28// the focus rect around a text may have 4 pixels in each direction
29// we handle these problems right now in an extended vis region of a window
24567921 30static const wxCoord TEXTBORDER = 4 ;
327788ac 31// the margin between the text control and the spin
0fa8508d 32static const wxCoord MARGIN = 8 - TEXTBORDER;
a842a96e 33
327788ac
SC
34// ----------------------------------------------------------------------------
35// wxSpinCtrlText: text control used by spin control
36// ----------------------------------------------------------------------------
a842a96e 37
327788ac
SC
38class wxSpinCtrlText : public wxTextCtrl
39{
40public:
41 wxSpinCtrlText(wxSpinCtrl *spin, const wxString& value)
0fa8508d 42 : wxTextCtrl(spin , -1, value, wxDefaultPosition, wxSize(40, -1))
327788ac
SC
43 {
44 m_spin = spin;
571d14b2
RD
45
46 // remove the default minsize, the spinctrl will have one instead
47 SetSizeHints(-1,-1);
327788ac
SC
48 }
49
50protected:
51 void OnTextChange(wxCommandEvent& event)
52 {
53 int val;
54 if ( m_spin->GetTextValue(&val) )
55 {
56 m_spin->GetSpinButton()->SetValue(val);
5b884f4c
KH
57
58 // Send event that the text was manually changed
59 wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, m_spin->GetId());
60 event.SetEventObject(m_spin);
61 event.SetInt(val);
62
63 m_spin->GetEventHandler()->ProcessEvent(event);
327788ac
SC
64 }
65
66 event.Skip();
67 }
68
69 bool ProcessEvent(wxEvent &event)
70 {
71 // Hand button down events to wxSpinCtrl. Doesn't work.
72 if (event.GetEventType() == wxEVT_LEFT_DOWN && m_spin->ProcessEvent( event ))
73 return TRUE;
74
75 return wxTextCtrl::ProcessEvent( event );
76 }
77
78private:
79 wxSpinCtrl *m_spin;
80
81 DECLARE_EVENT_TABLE()
82};
83
84BEGIN_EVENT_TABLE(wxSpinCtrlText, wxTextCtrl)
85 EVT_TEXT(-1, wxSpinCtrlText::OnTextChange)
86END_EVENT_TABLE()
87
88// ----------------------------------------------------------------------------
89// wxSpinCtrlButton: spin button used by spin control
90// ----------------------------------------------------------------------------
91
92class wxSpinCtrlButton : public wxSpinButton
93{
94public:
95 wxSpinCtrlButton(wxSpinCtrl *spin, int style)
96 : wxSpinButton(spin )
97 {
98 m_spin = spin;
327788ac 99 SetWindowStyle(style | wxSP_VERTICAL);
571d14b2
RD
100
101 // TODO: The spin button gets truncated a little bit due to size
102 // differences so change it's default size a bit. SMALL still gets a
103 // bit truncated, but MINI seems to be too small... Readdress this
104 // when the textctrl issues are all sorted out.
3109d198 105 //SetWindowVariant(wxWINDOW_VARIANT_SMALL);
571d14b2
RD
106
107 // remove the default minsize, the spinctrl will have one instead
108 SetSizeHints(-1,-1);
327788ac 109 }
a5bc50ee 110
327788ac
SC
111protected:
112 void OnSpinButton(wxSpinEvent& eventSpin)
113 {
327788ac 114 m_spin->SetTextValue(eventSpin.GetPosition());
a5bc50ee 115
327788ac
SC
116 wxCommandEvent event(wxEVT_COMMAND_SPINCTRL_UPDATED, m_spin->GetId());
117 event.SetEventObject(m_spin);
118 event.SetInt(eventSpin.GetPosition());
119
120 m_spin->GetEventHandler()->ProcessEvent(event);
327788ac
SC
121 }
122
123private:
124 wxSpinCtrl *m_spin;
125
126 DECLARE_EVENT_TABLE()
127};
128
129BEGIN_EVENT_TABLE(wxSpinCtrlButton, wxSpinButton)
130 EVT_SPIN(-1, wxSpinCtrlButton::OnSpinButton)
131END_EVENT_TABLE()
132
133IMPLEMENT_DYNAMIC_CLASS(wxSpinCtrl, wxControl)
134
135// ============================================================================
136// implementation
137// ============================================================================
138
139// ----------------------------------------------------------------------------
140// wxSpinCtrl creation
141// ----------------------------------------------------------------------------
142
143void wxSpinCtrl::Init()
144{
145 m_text = NULL;
146 m_btn = NULL;
147}
148
149bool wxSpinCtrl::Create(wxWindow *parent,
150 wxWindowID id,
151 const wxString& value,
152 const wxPoint& pos,
153 const wxSize& size,
154 long style,
155 int min,
156 int max,
157 int initial,
158 const wxString& name)
159{
3109d198
KO
160 m_macIsUserPane = true;
161 if ( !wxControl::Create(parent, id, pos, size, style,
327788ac
SC
162 wxDefaultValidator, name) )
163 {
164 return FALSE;
165 }
166
167 // the string value overrides the numeric one (for backwards compatibility
168 // reasons and also because it is simpler to satisfy the string value which
169 // comes much sooner in the list of arguments and leave the initial
170 // parameter unspecified)
171 if ( !value.empty() )
172 {
173 long l;
174 if ( value.ToLong(&l) )
175 initial = l;
176 }
177
178 wxSize csize = size ;
179 m_text = new wxSpinCtrlText(this, value);
180 m_btn = new wxSpinCtrlButton(this, style);
3109d198 181
327788ac
SC
182 m_btn->SetRange(min, max);
183 m_btn->SetValue(initial);
184
3109d198
KO
185 if ( size.x == -1 ){
186 csize.x = m_text->GetSize().x + MARGIN + m_btn->GetSize().x ;
187 }
188
327788ac 189 if ( size.y == -1 ) {
0fa8508d
SC
190 csize.y = m_text->GetSize().y + 2 * TEXTBORDER ; //allow for text border highlights
191 if ( m_btn->GetSize().y > csize.y )
192 csize.y = m_btn->GetSize().y ;
327788ac 193 }
3109d198
KO
194
195 //SetSize(csize);
196
e07a2142 197 //MacPostControlCreate(pos, csize);
3109d198 198 SetInitialBestSize(csize);
327788ac
SC
199
200 return TRUE;
201}
202
203wxSpinCtrl::~wxSpinCtrl()
204{
205 // delete the controls now, don't leave them alive even though they would
206 // still be eventually deleted by our parent - but it will be too late, the
207 // user code expects them to be gone now
208 delete m_text;
209 m_text = NULL ;
210 delete m_btn;
211 m_btn = NULL ;
212}
213
214// ----------------------------------------------------------------------------
215// geometry
216// ----------------------------------------------------------------------------
217
218wxSize wxSpinCtrl::DoGetBestSize() const
219{
51e14ebe
JS
220 if (!m_btn || !m_text)
221 return GetSize();
222
327788ac
SC
223 wxSize sizeBtn = m_btn->GetBestSize(),
224 sizeText = m_text->GetBestSize();
225
0fa8508d
SC
226 sizeText.y += 2 * TEXTBORDER ;
227 sizeText.x += 2 * TEXTBORDER ;
228
3109d198
KO
229 int height;
230 if (sizeText.y > sizeBtn.y)
231 height = sizeText.y;
232 else
233 height = sizeBtn.y;
234
0fa8508d 235 return wxSize(sizeBtn.x + sizeText.x + MARGIN, height );
327788ac
SC
236}
237
238void wxSpinCtrl::DoMoveWindow(int x, int y, int width, int height)
239{
327788ac
SC
240 // position the subcontrols inside the client area
241 wxSize sizeBtn = m_btn->GetSize();
0fa8508d 242 wxSize sizeText = m_text->GetSize();
3109d198
KO
243
244 wxControl::DoMoveWindow(x, y, width, height);
327788ac 245
0fa8508d 246 wxCoord wText = width - sizeBtn.x - MARGIN - 2 * TEXTBORDER;
3109d198 247
0fa8508d
SC
248 m_text->SetSize(TEXTBORDER, (height - sizeText.y) / 2, wText, -1);
249 m_btn->SetSize(0 + wText + MARGIN + 2 * TEXTBORDER , (height - sizeBtn.y) / 2 , -1, -1 );
327788ac
SC
250}
251
252// ----------------------------------------------------------------------------
253// operations forwarded to the subcontrols
254// ----------------------------------------------------------------------------
255
256bool wxSpinCtrl::Enable(bool enable)
257{
258 if ( !wxControl::Enable(enable) )
259 return FALSE;
260 return TRUE;
261}
262
263bool wxSpinCtrl::Show(bool show)
264{
265 if ( !wxControl::Show(show) )
266 return FALSE;
267 return TRUE;
268}
269
c3aee5c1
SC
270void wxSpinCtrl::SetFocus()
271{
272 if ( m_text != NULL) {
273 m_text->SetFocus();
274 }
275}
276
327788ac
SC
277// ----------------------------------------------------------------------------
278// value and range access
279// ----------------------------------------------------------------------------
280
281bool wxSpinCtrl::GetTextValue(int *val) const
282{
283 long l;
284 if ( !m_text->GetValue().ToLong(&l) )
285 {
286 // not a number at all
287 return FALSE;
288 }
289
290 if ( l < GetMin() || l > GetMax() )
291 {
292 // out of range
293 return FALSE;
294 }
295
296 *val = l;
297
298 return TRUE;
299}
300
301int wxSpinCtrl::GetValue() const
302{
303 return m_btn ? m_btn->GetValue() : 0;
304}
305
306int wxSpinCtrl::GetMin() const
307{
308 return m_btn ? m_btn->GetMin() : 0;
309}
310
311int wxSpinCtrl::GetMax() const
312{
313 return m_btn ? m_btn->GetMax() : 0;
314}
315
316// ----------------------------------------------------------------------------
317// changing value and range
318// ----------------------------------------------------------------------------
319
320void wxSpinCtrl::SetTextValue(int val)
321{
322 wxCHECK_RET( m_text, _T("invalid call to wxSpinCtrl::SetTextValue") );
323
324 m_text->SetValue(wxString::Format(_T("%d"), val));
325
326 // select all text
327 m_text->SetSelection(0, -1);
328
329 // and give focus to the control!
330 // m_text->SetFocus(); Why???? TODO.
331}
332
333void wxSpinCtrl::SetValue(int val)
334{
335 wxCHECK_RET( m_btn, _T("invalid call to wxSpinCtrl::SetValue") );
336
337 SetTextValue(val);
338
339 m_btn->SetValue(val);
340}
341
342void wxSpinCtrl::SetValue(const wxString& text)
343{
344 wxCHECK_RET( m_text, _T("invalid call to wxSpinCtrl::SetValue") );
345
346 long val;
347 if ( text.ToLong(&val) && ((val > INT_MIN) && (val < INT_MAX)) )
348 {
349 SetValue((int)val);
350 }
351 else // not a number at all or out of range
352 {
353 m_text->SetValue(text);
354 m_text->SetSelection(0, -1);
355 }
356}
357
358void wxSpinCtrl::SetRange(int min, int max)
359{
360 wxCHECK_RET( m_btn, _T("invalid call to wxSpinCtrl::SetRange") );
9453cf2b 361
327788ac
SC
362 m_btn->SetRange(min, max);
363}
a5bc50ee 364
a811affe
GD
365void wxSpinCtrl::SetSelection(long from, long to)
366{
77ffb593 367 // if from and to are both -1, it means (in wxWidgets) that all text should
a811affe
GD
368 // be selected
369 if ( (from == -1) && (to == -1) )
370 {
371 from = 0;
372 }
373 m_text->SetSelection(from, to);
374}
375
327788ac 376#endif // wxUSE_SPINCTRL