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