]>
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 // ---------------------------------------------------------------------------- 
  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
) % (m_max 
- m_min
); 
 151     else if ( value 
< m_min 
) 
 153         if ( GetWindowStyleFlag() & wxSP_WRAP 
) 
 154             value 
= m_max 
- (m_min 
- value
) % (m_max 
- m_min
); 
 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