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