]> git.saurik.com Git - wxWidgets.git/blame - src/generic/spinctlg.cpp
scroll of subwindow confined to rect param
[wxWidgets.git] / src / generic / spinctlg.cpp
CommitLineData
21709999
JS
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>
6aa89a22 9// License: wxWindows licence
21709999
JS
10///////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
14f355c2 20#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
21709999
JS
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
9f081f02
GD
31#if !(defined(__WXMSW__) || defined(__WXGTK__) || defined(__WXPM__)) || \
32 defined(__WXMAC__) || defined(__WXUNIVERSAL__)
21709999
JS
33
34#ifndef WX_PRECOMP
35 #include "wx/textctrl.h"
36#endif //WX_PRECOMP
37
c67d6888
JS
38#if wxUSE_SPINCTRL
39
21709999
JS
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 }
71e03035 74
23d416bf
RR
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;
71e03035 80
23d416bf
RR
81 return wxTextCtrl::ProcessEvent( event );
82 }
21709999
JS
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
71e03035 106 SetWindowStyle(style | wxSP_VERTICAL);
21709999
JS
107 }
108
109protected:
63efc55f 110 void OnSpinButton(wxSpinEvent& eventSpin)
21709999 111 {
c1eb1102 112 m_spin->SetTextValue(eventSpin.GetPosition());
63efc55f 113
c1eb1102
VZ
114 wxCommandEvent event(wxEVT_COMMAND_SPINCTRL_UPDATED, m_spin->GetId());
115 event.SetEventObject(m_spin);
116 event.SetInt(eventSpin.GetPosition());
117
118 m_spin->GetEventHandler()->ProcessEvent(event);
21709999 119
5d0000b5 120 eventSpin.Skip();
21709999
JS
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)
739555e3 134
21709999
JS
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{
094ca819 160 if ( !wxControl::Create(parent, id, wxDefaultPosition, wxDefaultSize, style,
21709999
JS
161 wxDefaultValidator, name) )
162 {
163 return FALSE;
164 }
165
71e03035
VZ
166 // the string value overrides the numeric one (for backwards compatibility
167 // reasons and also because it is simpler to satisfy the string value which
168 // comes much sooner in the list of arguments and leave the initial
169 // parameter unspecified)
170 if ( !value.empty() )
171 {
172 long l;
173 if ( value.ToLong(&l) )
174 initial = l;
175 }
176
21709999 177 SetBackgroundColour(*wxRED);
21709999
JS
178 m_text = new wxSpinCtrlText(this, value);
179 m_btn = new wxSpinCtrlButton(this, style);
180
181 m_btn->SetRange(min, max);
182 m_btn->SetValue(initial);
9453cf2b 183#ifdef __WXMAC__
954fc50b
SC
184 wxSize csize = size ;
185 if ( size.y == -1 ) {
186 csize.y = m_text->GetSize().y ;
187 }
188 DoSetSize(pos.x, pos.y, csize.x, csize.y);
189#else
dba00620
MB
190 wxSize best = GetBestSize();
191 if ( size.x != -1 ) best.x = size.x;
192 if ( size.y != -1 ) best.y = size.y;
193 DoSetSize(pos.x, pos.y, best.x, best.y);
9453cf2b 194#endif
21709999
JS
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);
954fc50b 204#ifndef __WXMAC__
21709999 205 m_isShown = TRUE;
954fc50b 206#endif
21709999
JS
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
dba00620 223wxSize wxSpinCtrl::DoGetBestSize() const
21709999
JS
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 // position the subcontrols inside the client area
3379ed37 236 wxSize sizeBtn = m_btn->GetSize();
21709999
JS
237
238 wxCoord wText = width - sizeBtn.x;
e466fe5f 239 m_text->SetSize(x, y, wText, height);
3363eadf 240#ifdef __WXMAC__
e466fe5f 241 m_btn->SetSize(x + wText + MARGIN, y, -1, -1);
3363eadf 242#else
e466fe5f 243 m_btn->SetSize(x + wText + MARGIN, y, -1, height);
3363eadf 244#endif
21709999
JS
245}
246
247// ----------------------------------------------------------------------------
248// operations forwarded to the subcontrols
249// ----------------------------------------------------------------------------
250
251bool wxSpinCtrl::Enable(bool enable)
252{
253 if ( !wxControl::Enable(enable) )
254 return FALSE;
255
256 m_btn->Enable(enable);
257 m_text->Enable(enable);
258
259 return TRUE;
260}
261
262bool wxSpinCtrl::Show(bool show)
263{
264 if ( !wxControl::Show(show) )
265 return FALSE;
266
3379ed37
VZ
267 // under GTK Show() is called the first time before we are fully
268 // constructed
269 if ( m_btn )
270 {
271 m_btn->Show(show);
272 m_text->Show(show);
273 }
21709999
JS
274
275 return TRUE;
276}
277
278// ----------------------------------------------------------------------------
279// value and range access
280// ----------------------------------------------------------------------------
281
282bool wxSpinCtrl::GetTextValue(int *val) const
283{
284 long l;
285 if ( !m_text->GetValue().ToLong(&l) )
286 {
287 // not a number at all
288 return FALSE;
289 }
290
291 if ( l < GetMin() || l > GetMax() )
292 {
293 // out of range
294 return FALSE;
295 }
296
297 *val = l;
298
299 return TRUE;
300}
301
302int wxSpinCtrl::GetValue() const
303{
304 return m_btn ? m_btn->GetValue() : 0;
305}
306
307int wxSpinCtrl::GetMin() const
308{
309 return m_btn ? m_btn->GetMin() : 0;
310}
311
312int wxSpinCtrl::GetMax() const
313{
314 return m_btn ? m_btn->GetMax() : 0;
315}
316
317// ----------------------------------------------------------------------------
318// changing value and range
319// ----------------------------------------------------------------------------
320
321void wxSpinCtrl::SetTextValue(int val)
322{
323 wxCHECK_RET( m_text, _T("invalid call to wxSpinCtrl::SetTextValue") );
324
325 m_text->SetValue(wxString::Format(_T("%d"), val));
326
327 // select all text
328 m_text->SetSelection(0, -1);
329
330 // and give focus to the control!
d45906e0 331 // m_text->SetFocus(); Why???? TODO.
21709999
JS
332}
333
334void wxSpinCtrl::SetValue(int val)
335{
336 wxCHECK_RET( m_btn, _T("invalid call to wxSpinCtrl::SetValue") );
337
338 SetTextValue(val);
339
340 m_btn->SetValue(val);
341}
342
343void wxSpinCtrl::SetValue(const wxString& text)
344{
345 wxCHECK_RET( m_text, _T("invalid call to wxSpinCtrl::SetValue") );
346
347 long val;
348 if ( text.ToLong(&val) && ((val > INT_MIN) && (val < INT_MAX)) )
349 {
350 SetValue((int)val);
351 }
352 else // not a number at all or out of range
353 {
354 m_text->SetValue(text);
355 m_text->SetSelection(0, -1);
356 }
357}
358
359void wxSpinCtrl::SetRange(int min, int max)
360{
361 wxCHECK_RET( m_btn, _T("invalid call to wxSpinCtrl::SetRange") );
362
363 m_btn->SetRange(min, max);
364}
365
739555e3
VZ
366void wxSpinCtrl::SetSelection(long from, long to)
367{
368 wxCHECK_RET( m_text, _T("invalid call to wxSpinCtrl::SetSelection") );
369
370 m_text->SetSelection(from, to);
371}
372
c67d6888 373#endif // wxUSE_SPINCTRL
3379ed37 374#endif // !wxPort-with-native-spinctrl