1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/univ/spinbutt.cpp
3 // Purpose: implementation of the universal version of wxSpinButton
4 // Author: Vadim Zeitlin
7 // Copyright: (c) 2001 SciTech Software, Inc. (www.scitechsoft.com)
8 // Licence: wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
11 // ============================================================================
13 // ============================================================================
15 // ----------------------------------------------------------------------------
17 // ----------------------------------------------------------------------------
19 #include "wx/wxprec.h"
28 #include "wx/spinbutt.h"
32 #include "wx/univ/renderer.h"
33 #include "wx/univ/inphand.h"
34 #include "wx/univ/theme.h"
36 // ============================================================================
37 // implementation of wxSpinButton
38 // ============================================================================
40 // ----------------------------------------------------------------------------
42 // ----------------------------------------------------------------------------
45 // warning C4355: 'this' : used in base member initializer list
46 #pragma warning(disable:4355) // so what? disable it...
49 wxSpinButton::wxSpinButton()
55 wxSpinButton::wxSpinButton(wxWindow
*parent
,
65 (void)Create(parent
, id
, pos
, size
, style
, name
);
69 // warning C4355: 'this' : used in base member initializer list
70 #pragma warning(default:4355)
73 void wxSpinButton::Init()
75 for ( size_t n
= 0; n
< WXSIZEOF(m_arrowsState
); n
++ )
83 bool wxSpinButton::Create(wxWindow
*parent
,
90 // the spin buttons never have the border
91 style
&= ~wxBORDER_MASK
;
93 if ( !wxSpinButtonBase::Create(parent
, id
, pos
, size
, style
,
94 wxDefaultValidator
, name
) )
99 CreateInputHandler(wxINP_HANDLER_SPINBTN
);
104 // ----------------------------------------------------------------------------
106 // ----------------------------------------------------------------------------
108 void wxSpinButton::SetRange(int minVal
, int maxVal
)
110 wxSpinButtonBase::SetRange(minVal
, maxVal
);
112 // because the arrows disabled state might have changed - we don't check if
113 // it really changed or not because SetRange() is called rarely enough and
114 // son an extre refresh here doesn't really hurt
118 int wxSpinButton::GetValue() const
123 void wxSpinButton::SetValue(int val
)
125 if ( val
!= m_value
)
133 int wxSpinButton::NormalizeValue(int value
) const
137 if ( GetWindowStyleFlag() & wxSP_WRAP
)
138 value
= m_min
+ (value
- m_max
- 1) % (m_max
- m_min
+ 1);
142 else if ( value
< m_min
)
144 if ( GetWindowStyleFlag() & wxSP_WRAP
)
145 value
= m_max
- (m_min
- value
- 1) % (m_max
- m_min
+ 1);
153 bool wxSpinButton::ChangeValue(int inc
)
155 int valueNew
= NormalizeValue(m_value
+ inc
);
157 if ( valueNew
== m_value
)
159 // nothing changed - most likely because we are already at min/max
164 wxSpinEvent
event(inc
> 0 ? wxEVT_SCROLL_LINEUP
: wxEVT_SCROLL_LINEDOWN
,
166 event
.SetPosition(valueNew
);
167 event
.SetEventObject(this);
169 if ( GetEventHandler()->ProcessEvent(event
) && !event
.IsAllowed() )
171 // programm has vetoed the event
177 // send wxEVT_SCROLL_THUMBTRACK as well
178 event
.SetEventType(wxEVT_SCROLL_THUMBTRACK
);
179 (void)GetEventHandler()->ProcessEvent(event
);
184 // ----------------------------------------------------------------------------
186 // ----------------------------------------------------------------------------
188 wxSize
wxSpinButton::DoGetBestClientSize() const
190 // a spin button has by default the same size as two scrollbar arrows put
192 wxSize size
= m_renderer
->GetScrollbarArrowSize();
205 // ----------------------------------------------------------------------------
206 // wxControlWithArrows methods
207 // ----------------------------------------------------------------------------
209 int wxSpinButton::GetArrowState(wxScrollArrows::Arrow arrow
) const
211 int state
= m_arrowsState
[arrow
];
213 // the arrow may also be disabled: either because the control is completely
215 bool disabled
= !IsEnabled();
217 if ( !disabled
&& !(GetWindowStyleFlag() & wxSP_WRAP
) )
219 // ... or because we can't go any further - note that this never
220 // happens if we just wrap
223 if ( arrow
== wxScrollArrows::Arrow_First
)
224 disabled
= m_value
== m_max
;
226 disabled
= m_value
== m_min
;
230 if ( arrow
== wxScrollArrows::Arrow_First
)
231 disabled
= m_value
== m_min
;
233 disabled
= m_value
== m_max
;
239 state
|= wxCONTROL_DISABLED
;
245 void wxSpinButton::SetArrowFlag(wxScrollArrows::Arrow arrow
, int flag
, bool set
)
247 int state
= m_arrowsState
[arrow
];
253 if ( state
!= m_arrowsState
[arrow
] )
255 m_arrowsState
[arrow
] = state
;
260 bool wxSpinButton::OnArrow(wxScrollArrows::Arrow arrow
)
262 int valueOld
= GetValue();
264 wxControlAction action
;
265 if ( arrow
== wxScrollArrows::Arrow_First
)
266 action
= IsVertical() ? wxACTION_SPIN_INC
: wxACTION_SPIN_DEC
;
268 action
= IsVertical() ? wxACTION_SPIN_DEC
: wxACTION_SPIN_INC
;
270 PerformAction(action
);
272 // did we scroll to the end?
273 return GetValue() != valueOld
;
276 // ----------------------------------------------------------------------------
278 // ----------------------------------------------------------------------------
280 void wxSpinButton::DoDraw(wxControlRenderer
*renderer
)
282 wxRect rectArrow1
, rectArrow2
;
283 CalcArrowRects(&rectArrow1
, &rectArrow2
);
285 wxDC
& dc
= renderer
->GetDC();
286 m_arrows
.DrawArrow(wxScrollArrows::Arrow_First
, dc
, rectArrow1
);
287 m_arrows
.DrawArrow(wxScrollArrows::Arrow_Second
, dc
, rectArrow2
);
290 // ----------------------------------------------------------------------------
292 // ----------------------------------------------------------------------------
294 void wxSpinButton::CalcArrowRects(wxRect
*rect1
, wxRect
*rect2
) const
296 // calculate the rectangles for both arrows: note that normally the 2
297 // arrows are adjacent to each other but if the total control width/height
298 // is odd, we can have 1 pixel between them
299 wxRect rectTotal
= GetClientRect();
308 rect2
->y
+= rect1
->height
;
309 if ( rectTotal
.height
% 2 )
317 rect2
->x
+= rect1
->width
;
318 if ( rectTotal
.width
% 2 )
323 wxScrollArrows::Arrow
wxSpinButton::HitTestArrow(const wxPoint
& pt
) const
325 wxRect rectArrow1
, rectArrow2
;
326 CalcArrowRects(&rectArrow1
, &rectArrow2
);
328 if ( rectArrow1
.Contains(pt
) )
329 return wxScrollArrows::Arrow_First
;
330 else if ( rectArrow2
.Contains(pt
) )
331 return wxScrollArrows::Arrow_Second
;
333 return wxScrollArrows::Arrow_None
;
336 // ----------------------------------------------------------------------------
338 // ----------------------------------------------------------------------------
340 bool wxSpinButton::PerformAction(const wxControlAction
& action
,
342 const wxString
& strArg
)
344 if ( action
== wxACTION_SPIN_INC
)
346 else if ( action
== wxACTION_SPIN_DEC
)
349 return wxControl::PerformAction(action
, numArg
, strArg
);
355 wxInputHandler
*wxSpinButton::GetStdInputHandler(wxInputHandler
*handlerDef
)
357 static wxStdSpinButtonInputHandler
s_handler(handlerDef
);
362 // ----------------------------------------------------------------------------
363 // wxStdSpinButtonInputHandler
364 // ----------------------------------------------------------------------------
366 wxStdSpinButtonInputHandler::
367 wxStdSpinButtonInputHandler(wxInputHandler
*inphand
)
368 : wxStdInputHandler(inphand
)
372 bool wxStdSpinButtonInputHandler::HandleKey(wxInputConsumer
*consumer
,
373 const wxKeyEvent
& event
,
378 wxControlAction action
;
379 switch ( event
.GetKeyCode() )
383 action
= wxACTION_SPIN_DEC
;
388 action
= wxACTION_SPIN_INC
;
392 if ( !action
.IsEmpty() )
394 consumer
->PerformAction(action
);
400 return wxStdInputHandler::HandleKey(consumer
, event
, pressed
);
403 bool wxStdSpinButtonInputHandler::HandleMouse(wxInputConsumer
*consumer
,
404 const wxMouseEvent
& event
)
406 wxSpinButton
*spinbtn
= wxStaticCast(consumer
->GetInputWindow(), wxSpinButton
);
408 if ( spinbtn
->GetArrows().HandleMouse(event
) )
410 // don't refresh, everything is already done
414 return wxStdInputHandler::HandleMouse(consumer
, event
);
417 bool wxStdSpinButtonInputHandler::HandleMouseMove(wxInputConsumer
*consumer
,
418 const wxMouseEvent
& event
)
420 wxSpinButton
*spinbtn
= wxStaticCast(consumer
->GetInputWindow(), wxSpinButton
);
422 if ( spinbtn
->GetArrows().HandleMouseMove(event
) )
424 // processed by the arrows
428 return wxStdInputHandler::HandleMouseMove(consumer
, event
);
432 #endif // wxUSE_SPINBTN