]>
git.saurik.com Git - wxWidgets.git/blob - src/univ/spinbutt.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: univ/spinbutt.cpp
3 // Purpose: implementation of the universal version of wxSpinButton
4 // Author: Vadim Zeitlin
8 // Copyright: (c) 2001 SciTech Software, Inc. (www.scitechsoft.com)
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
21 #pragma implementation "spinbutt.h"
22 #pragma implementation "univspinbutt.h"
25 #include "wx/wxprec.h"
34 #include "wx/spinbutt.h"
38 #include "wx/univ/renderer.h"
39 #include "wx/univ/inphand.h"
40 #include "wx/univ/theme.h"
42 // ============================================================================
43 // implementation of wxSpinButton
44 // ============================================================================
46 IMPLEMENT_DYNAMIC_CLASS(wxSpinEvent
, wxNotifyEvent
)
47 IMPLEMENT_DYNAMIC_CLASS(wxSpinButton
, wxControl
)
49 // ----------------------------------------------------------------------------
51 // ----------------------------------------------------------------------------
54 // warning C4355: 'this' : used in base member initializer list
55 #pragma warning(disable:4355) // so what? disable it...
58 wxSpinButton::wxSpinButton()
64 wxSpinButton::wxSpinButton(wxWindow
*parent
,
74 (void)Create(parent
, id
, pos
, size
, style
, name
);
78 // warning C4355: 'this' : used in base member initializer list
79 #pragma warning(default:4355)
82 void wxSpinButton::Init()
84 for ( size_t n
= 0; n
< WXSIZEOF(m_arrowsState
); n
++ )
92 bool wxSpinButton::Create(wxWindow
*parent
,
99 // the spin buttons never have the border
100 style
&= ~wxBORDER_MASK
;
102 if ( !wxSpinButtonBase::Create(parent
, id
, pos
, size
, style
,
103 wxDefaultValidator
, name
) )
108 CreateInputHandler(wxINP_HANDLER_SPINBTN
);
113 // ----------------------------------------------------------------------------
115 // ----------------------------------------------------------------------------
117 void wxSpinButton::SetRange(int minVal
, int maxVal
)
119 wxSpinButtonBase::SetRange(minVal
, maxVal
);
121 // because the arrows disabled state might have changed - we don't check if
122 // it really changed or not because SetRange() is called rarely enough and
123 // son an extre refresh here doesn't really hurt
127 int wxSpinButton::GetValue() const
132 void wxSpinButton::SetValue(int val
)
134 if ( val
!= m_value
)
142 int wxSpinButton::NormalizeValue(int value
) const
146 if ( GetWindowStyleFlag() & wxSP_WRAP
)
147 value
= m_min
+ (value
- m_max
- 1) % (m_max
- m_min
+ 1);
151 else if ( value
< m_min
)
153 if ( GetWindowStyleFlag() & wxSP_WRAP
)
154 value
= m_max
- (m_min
- value
- 1) % (m_max
- m_min
+ 1);
162 bool wxSpinButton::ChangeValue(int inc
)
164 int valueNew
= NormalizeValue(m_value
+ inc
);
166 if ( valueNew
== m_value
)
168 // nothing changed - most likely because we are already at min/max
173 wxSpinEvent
event(inc
> 0 ? wxEVT_SCROLL_LINEUP
: wxEVT_SCROLL_LINEDOWN
,
175 event
.SetPosition(valueNew
);
176 event
.SetEventObject(this);
178 if ( GetEventHandler()->ProcessEvent(event
) && !event
.IsAllowed() )
180 // programm has vetoed the event
186 // send wxEVT_SCROLL_THUMBTRACK as well
187 event
.SetEventType(wxEVT_SCROLL_THUMBTRACK
);
188 (void)GetEventHandler()->ProcessEvent(event
);
193 // ----------------------------------------------------------------------------
195 // ----------------------------------------------------------------------------
197 wxSize
wxSpinButton::DoGetBestClientSize() const
199 // a spin button has by default the same size as two scrollbar arrows put
201 wxSize size
= m_renderer
->GetScrollbarArrowSize();
214 // ----------------------------------------------------------------------------
215 // wxControlWithArrows methods
216 // ----------------------------------------------------------------------------
218 int wxSpinButton::GetArrowState(wxScrollArrows::Arrow arrow
) const
220 int state
= m_arrowsState
[arrow
];
222 // the arrow may also be disabled: either because the control is completely
224 bool disabled
= !IsEnabled();
226 if ( !disabled
&& !(GetWindowStyleFlag() & wxSP_WRAP
) )
228 // ... or because we can't go any further - note that this never
229 // happens if we just wrap
232 if ( arrow
== wxScrollArrows::Arrow_First
)
233 disabled
= m_value
== m_max
;
235 disabled
= m_value
== m_min
;
239 if ( arrow
== wxScrollArrows::Arrow_First
)
240 disabled
= m_value
== m_min
;
242 disabled
= m_value
== m_max
;
248 state
|= wxCONTROL_DISABLED
;
254 void wxSpinButton::SetArrowFlag(wxScrollArrows::Arrow arrow
, int flag
, bool set
)
256 int state
= m_arrowsState
[arrow
];
262 if ( state
!= m_arrowsState
[arrow
] )
264 m_arrowsState
[arrow
] = state
;
269 bool wxSpinButton::OnArrow(wxScrollArrows::Arrow arrow
)
271 int valueOld
= GetValue();
273 wxControlAction action
;
274 if ( arrow
== wxScrollArrows::Arrow_First
)
275 action
= IsVertical() ? wxACTION_SPIN_INC
: wxACTION_SPIN_DEC
;
277 action
= IsVertical() ? wxACTION_SPIN_DEC
: wxACTION_SPIN_INC
;
279 PerformAction(action
);
281 // did we scroll to the end?
282 return GetValue() != valueOld
;
285 // ----------------------------------------------------------------------------
287 // ----------------------------------------------------------------------------
289 void wxSpinButton::DoDraw(wxControlRenderer
*renderer
)
291 wxRect rectArrow1
, rectArrow2
;
292 CalcArrowRects(&rectArrow1
, &rectArrow2
);
294 wxDC
& dc
= renderer
->GetDC();
295 m_arrows
.DrawArrow(wxScrollArrows::Arrow_First
, dc
, rectArrow1
);
296 m_arrows
.DrawArrow(wxScrollArrows::Arrow_Second
, dc
, rectArrow2
);
299 // ----------------------------------------------------------------------------
301 // ----------------------------------------------------------------------------
303 void wxSpinButton::CalcArrowRects(wxRect
*rect1
, wxRect
*rect2
) const
305 // calculate the rectangles for both arrows: note that normally the 2
306 // arrows are adjacent to each other but if the total control width/height
307 // is odd, we can have 1 pixel between them
308 wxRect rectTotal
= GetClientRect();
317 rect2
->y
+= rect1
->height
;
318 if ( rectTotal
.height
% 2 )
326 rect2
->x
+= rect1
->width
;
327 if ( rectTotal
.width
% 2 )
332 wxScrollArrows::Arrow
wxSpinButton::HitTest(const wxPoint
& pt
) const
334 wxRect rectArrow1
, rectArrow2
;
335 CalcArrowRects(&rectArrow1
, &rectArrow2
);
337 if ( rectArrow1
.Inside(pt
) )
338 return wxScrollArrows::Arrow_First
;
339 else if ( rectArrow2
.Inside(pt
) )
340 return wxScrollArrows::Arrow_Second
;
342 return wxScrollArrows::Arrow_None
;
345 // ----------------------------------------------------------------------------
347 // ----------------------------------------------------------------------------
349 bool wxSpinButton::PerformAction(const wxControlAction
& action
,
351 const wxString
& strArg
)
353 if ( action
== wxACTION_SPIN_INC
)
355 else if ( action
== wxACTION_SPIN_DEC
)
358 return wxControl::PerformAction(action
, numArg
, strArg
);
363 // ----------------------------------------------------------------------------
364 // wxStdSpinButtonInputHandler
365 // ----------------------------------------------------------------------------
367 wxStdSpinButtonInputHandler::
368 wxStdSpinButtonInputHandler(wxInputHandler
*inphand
)
369 : wxStdInputHandler(inphand
)
373 bool wxStdSpinButtonInputHandler::HandleKey(wxInputConsumer
*consumer
,
374 const wxKeyEvent
& event
,
379 wxControlAction action
;
380 switch ( event
.GetKeyCode() )
384 action
= wxACTION_SPIN_DEC
;
389 action
= wxACTION_SPIN_INC
;
395 consumer
->PerformAction(action
);
401 return wxStdInputHandler::HandleKey(consumer
, event
, pressed
);
404 bool wxStdSpinButtonInputHandler::HandleMouse(wxInputConsumer
*consumer
,
405 const wxMouseEvent
& event
)
407 wxSpinButton
*spinbtn
= wxStaticCast(consumer
->GetInputWindow(), wxSpinButton
);
409 if ( spinbtn
->GetArrows().HandleMouse(event
) )
411 // don't refresh, everything is already done
415 return wxStdInputHandler::HandleMouse(consumer
, event
);
418 bool wxStdSpinButtonInputHandler::HandleMouseMove(wxInputConsumer
*consumer
,
419 const wxMouseEvent
& event
)
421 wxSpinButton
*spinbtn
= wxStaticCast(consumer
->GetInputWindow(), wxSpinButton
);
423 if ( spinbtn
->GetArrows().HandleMouseMove(event
) )
425 // processed by the arrows
429 return wxStdInputHandler::HandleMouseMove(consumer
, event
);
433 #endif // wxUSE_SPINBTN