]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/generic/spinctlg.cpp
Captured mouse in grid column label so the drag isn't prematurely and messily
[wxWidgets.git] / src / generic / spinctlg.cpp
... / ...
CommitLineData
1///////////////////////////////////////////////////////////////////////////////
2// Name: src/generic/spinctlg.cpp
3// Purpose: implements wxSpinCtrl as a composite control
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 29.01.01
7// RCS-ID: $Id$
8// Copyright: (c) 2001 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9// License: wxWindows license
10///////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
20#ifdef __GNUG__
21 #pragma implementation "spinctlg.h"
22#endif
23
24// For compilers that support precompilation, includes "wx.h".
25#include "wx/wxprec.h"
26
27#ifdef __BORLANDC__
28 #pragma hdrstop
29#endif
30
31#if !(defined(__WXMSW__) || defined(__WXGTK__) || defined(__WXPM__)) || \
32 defined(__WXMAC__) || defined(__WXUNIVERSAL__)
33
34#ifndef WX_PRECOMP
35 #include "wx/textctrl.h"
36#endif //WX_PRECOMP
37
38#if wxUSE_SPINCTRL
39
40#include "wx/spinbutt.h"
41#include "wx/spinctrl.h"
42
43// ----------------------------------------------------------------------------
44// constants
45// ----------------------------------------------------------------------------
46
47// the margin between the text control and the spin
48static const wxCoord MARGIN = 2;
49
50// ----------------------------------------------------------------------------
51// wxSpinCtrlText: text control used by spin control
52// ----------------------------------------------------------------------------
53
54class wxSpinCtrlText : public wxTextCtrl
55{
56public:
57 wxSpinCtrlText(wxSpinCtrl *spin, const wxString& value)
58 : wxTextCtrl(spin->GetParent(), -1, value)
59 {
60 m_spin = spin;
61 }
62
63protected:
64 void OnTextChange(wxCommandEvent& event)
65 {
66 int val;
67 if ( m_spin->GetTextValue(&val) )
68 {
69 m_spin->GetSpinButton()->SetValue(val);
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->GetParent())
103 {
104 m_spin = spin;
105
106 SetWindowStyle(style | wxSP_VERTICAL);
107 }
108
109protected:
110 void OnSpinButton(wxSpinEvent& eventSpin)
111 {
112#ifdef __WXMAC__
113 m_spin->SetTextValue(eventSpin.GetPosition());
114
115 wxCommandEvent event(wxEVT_COMMAND_SPINCTRL_UPDATED, m_spin->GetId());
116 event.SetEventObject(m_spin);
117 event.SetInt(eventSpin.GetPosition());
118
119 m_spin->GetEventHandler()->ProcessEvent(event);
120#else
121 m_spin->SetTextValue(eventSpin.GetPosition());
122 eventSpin.Skip();
123#endif
124 }
125
126private:
127 wxSpinCtrl *m_spin;
128
129 DECLARE_EVENT_TABLE()
130};
131
132BEGIN_EVENT_TABLE(wxSpinCtrlButton, wxSpinButton)
133 EVT_SPIN(-1, wxSpinCtrlButton::OnSpinButton)
134END_EVENT_TABLE()
135
136IMPLEMENT_DYNAMIC_CLASS(wxSpinCtrl, wxControl)
137
138// ============================================================================
139// implementation
140// ============================================================================
141
142// ----------------------------------------------------------------------------
143// wxSpinCtrl creation
144// ----------------------------------------------------------------------------
145
146void wxSpinCtrl::Init()
147{
148 m_text = NULL;
149 m_btn = NULL;
150}
151
152bool wxSpinCtrl::Create(wxWindow *parent,
153 wxWindowID id,
154 const wxString& value,
155 const wxPoint& pos,
156 const wxSize& size,
157 long style,
158 int min,
159 int max,
160 int initial,
161 const wxString& name)
162{
163 if ( !wxControl::Create(parent, id, wxDefaultPosition, wxDefaultSize, style,
164 wxDefaultValidator, name) )
165 {
166 return FALSE;
167 }
168
169 // the string value overrides the numeric one (for backwards compatibility
170 // reasons and also because it is simpler to satisfy the string value which
171 // comes much sooner in the list of arguments and leave the initial
172 // parameter unspecified)
173 if ( !value.empty() )
174 {
175 long l;
176 if ( value.ToLong(&l) )
177 initial = l;
178 }
179
180 SetBackgroundColour(*wxRED);
181 m_text = new wxSpinCtrlText(this, value);
182 m_btn = new wxSpinCtrlButton(this, style);
183
184 m_btn->SetRange(min, max);
185 m_btn->SetValue(initial);
186#ifdef __WXMAC__
187 wxSize csize = size ;
188 if ( size.y == -1 ) {
189 csize.y = m_text->GetSize().y ;
190 }
191 DoSetSize(pos.x, pos.y, csize.x, csize.y);
192#else
193 DoSetSize(pos.x, pos.y, size.x, size.y);
194#endif
195 // have to disable this window to avoid interfering it with message
196 // processing to the text and the button... but pretend it is enabled to
197 // make IsEnabled() return TRUE
198 wxControl::Enable(FALSE); // don't use non virtual Disable() here!
199 m_isEnabled = TRUE;
200
201 // we don't even need to show this window itself - and not doing it avoids
202 // that it overwrites the text control
203 wxControl::Show(FALSE);
204#ifndef __WXMAC__
205 m_isShown = TRUE;
206#endif
207 return TRUE;
208}
209
210wxSpinCtrl::~wxSpinCtrl()
211{
212 // delete the controls now, don't leave them alive even though they woudl
213 // still be eventually deleted by our parent - but it will be too late, the
214 // user code expects them to be gone now
215 delete m_text;
216 delete m_btn;
217}
218
219// ----------------------------------------------------------------------------
220// geometry
221// ----------------------------------------------------------------------------
222
223wxSize wxSpinCtrl::DoGetBestClientSize() const
224{
225 wxSize sizeBtn = m_btn->GetBestSize(),
226 sizeText = m_text->GetBestSize();
227
228 return wxSize(sizeBtn.x + sizeText.x + MARGIN, sizeText.y);
229}
230
231void wxSpinCtrl::DoMoveWindow(int x, int y, int width, int height)
232{
233 wxControl::DoMoveWindow(x, y, width, height);
234
235 wxPoint p = GetParent() ?
236 GetParent()->GetClientAreaOrigin() : wxPoint(0,0);
237
238 // position the subcontrols inside the client area
239 wxSize sizeBtn = m_btn->GetSize();
240
241 wxCoord wText = width - sizeBtn.x;
242 m_text->SetSize(x-p.x, y-p.y, wText, height);
243#ifdef __WXMAC__
244 m_btn->SetSize(x-p.x + wText + MARGIN, y-p.y, -1, -1);
245#else
246 m_btn->SetSize(x-p.x + wText + MARGIN, y-p.y, -1, height);
247#endif
248}
249
250// ----------------------------------------------------------------------------
251// operations forwarded to the subcontrols
252// ----------------------------------------------------------------------------
253
254bool wxSpinCtrl::Enable(bool enable)
255{
256 if ( !wxControl::Enable(enable) )
257 return FALSE;
258
259 m_btn->Enable(enable);
260 m_text->Enable(enable);
261
262 return TRUE;
263}
264
265bool wxSpinCtrl::Show(bool show)
266{
267 if ( !wxControl::Show(show) )
268 return FALSE;
269
270 // under GTK Show() is called the first time before we are fully
271 // constructed
272 if ( m_btn )
273 {
274 m_btn->Show(show);
275 m_text->Show(show);
276 }
277
278 return TRUE;
279}
280
281// ----------------------------------------------------------------------------
282// value and range access
283// ----------------------------------------------------------------------------
284
285bool wxSpinCtrl::GetTextValue(int *val) const
286{
287 long l;
288 if ( !m_text->GetValue().ToLong(&l) )
289 {
290 // not a number at all
291 return FALSE;
292 }
293
294 if ( l < GetMin() || l > GetMax() )
295 {
296 // out of range
297 return FALSE;
298 }
299
300 *val = l;
301
302 return TRUE;
303}
304
305int wxSpinCtrl::GetValue() const
306{
307 return m_btn ? m_btn->GetValue() : 0;
308}
309
310int wxSpinCtrl::GetMin() const
311{
312 return m_btn ? m_btn->GetMin() : 0;
313}
314
315int wxSpinCtrl::GetMax() const
316{
317 return m_btn ? m_btn->GetMax() : 0;
318}
319
320// ----------------------------------------------------------------------------
321// changing value and range
322// ----------------------------------------------------------------------------
323
324void wxSpinCtrl::SetTextValue(int val)
325{
326 wxCHECK_RET( m_text, _T("invalid call to wxSpinCtrl::SetTextValue") );
327
328 m_text->SetValue(wxString::Format(_T("%d"), val));
329
330 // select all text
331 m_text->SetSelection(0, -1);
332
333 // and give focus to the control!
334 m_text->SetFocus();
335}
336
337void wxSpinCtrl::SetValue(int val)
338{
339 wxCHECK_RET( m_btn, _T("invalid call to wxSpinCtrl::SetValue") );
340
341 SetTextValue(val);
342
343 m_btn->SetValue(val);
344}
345
346void wxSpinCtrl::SetValue(const wxString& text)
347{
348 wxCHECK_RET( m_text, _T("invalid call to wxSpinCtrl::SetValue") );
349
350 long val;
351 if ( text.ToLong(&val) && ((val > INT_MIN) && (val < INT_MAX)) )
352 {
353 SetValue((int)val);
354 }
355 else // not a number at all or out of range
356 {
357 m_text->SetValue(text);
358 m_text->SetSelection(0, -1);
359 }
360}
361
362void wxSpinCtrl::SetRange(int min, int max)
363{
364 wxCHECK_RET( m_btn, _T("invalid call to wxSpinCtrl::SetRange") );
365
366 m_btn->SetRange(min, max);
367}
368
369#endif // wxUSE_SPINCTRL
370#endif // !wxPort-with-native-spinctrl