1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/univ/scrolbar.cpp
3 // Purpose: wxScrollBar implementation
4 // Author: Vadim Zeitlin
8 // Copyright: (c) 2000 SciTech Software, Inc. (www.scitechsoft.com)
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 #include "wx/wxprec.h"
28 #include "wx/scrolbar.h"
32 #include "wx/dcclient.h"
33 #include "wx/validate.h"
37 #include "wx/univ/scrtimer.h"
39 #include "wx/univ/renderer.h"
40 #include "wx/univ/inphand.h"
41 #include "wx/univ/theme.h"
43 #if wxDEBUG_LEVEL >= 2
44 #define WXDEBUG_SCROLLBAR
47 #if defined(WXDEBUG_SCROLLBAR) && defined(__WXMSW__) && !defined(__WXMICROWIN__)
48 #include "wx/msw/private.h"
51 // ----------------------------------------------------------------------------
52 // wxScrollBarTimer: this class is used to repeatedly scroll the scrollbar
53 // when the mouse is help pressed on the arrow or on the bar. It generates the
54 // given scroll action command periodically.
55 // ----------------------------------------------------------------------------
57 class wxScrollBarTimer
: public wxScrollTimer
60 wxScrollBarTimer(wxStdScrollBarInputHandler
*handler
,
61 const wxControlAction
& action
,
62 wxScrollBar
*control
);
65 virtual bool DoNotify();
68 wxStdScrollBarInputHandler
*m_handler
;
69 wxControlAction m_action
;
70 wxScrollBar
*m_control
;
73 // ============================================================================
75 // ============================================================================
77 IMPLEMENT_DYNAMIC_CLASS(wxScrollBar
, wxControl
)
79 BEGIN_EVENT_TABLE(wxScrollBar
, wxScrollBarBase
)
82 // ----------------------------------------------------------------------------
84 // ----------------------------------------------------------------------------
87 // warning C4355: 'this' : used in base member initializer list
88 #pragma warning(disable:4355) // so what? disable it...
91 wxScrollBar::wxScrollBar()
97 wxScrollBar::wxScrollBar(wxWindow
*parent
,
102 const wxValidator
& validator
,
103 const wxString
& name
)
108 (void)Create(parent
, id
, pos
, size
, style
, validator
, name
);
112 // warning C4355: 'this' : used in base member initializer list
113 #pragma warning(default:4355)
116 void wxScrollBar::Init()
125 for ( size_t n
= 0; n
< WXSIZEOF(m_elementsState
); n
++ )
127 m_elementsState
[n
] = 0;
133 bool wxScrollBar::Create(wxWindow
*parent
,
138 const wxValidator
& validator
,
139 const wxString
&name
)
141 // the scrollbars never have the border
142 style
&= ~wxBORDER_MASK
;
144 if ( !wxControl::Create(parent
, id
, pos
, size
, style
, validator
, name
) )
147 SetInitialSize(size
);
149 // override the cursor of the target window (if any)
150 SetCursor(wxCURSOR_ARROW
);
152 CreateInputHandler(wxINP_HANDLER_SCROLLBAR
);
157 wxScrollBar::~wxScrollBar()
161 // ----------------------------------------------------------------------------
163 // ----------------------------------------------------------------------------
165 bool wxScrollBar::IsStandalone() const
167 wxWindow
*parent
= GetParent();
173 return (parent
->GetScrollbar(wxHORIZONTAL
) != this) &&
174 (parent
->GetScrollbar(wxVERTICAL
) != this);
177 bool wxScrollBar::AcceptsFocus() const
179 // the window scrollbars never accept focus
180 return wxScrollBarBase::AcceptsFocus() && IsStandalone();
183 // ----------------------------------------------------------------------------
185 // ----------------------------------------------------------------------------
187 void wxScrollBar::DoSetThumb(int pos
)
189 // don't assert hecks here, we're a private function which is meant to be
190 // called with any args at all
195 else if ( pos
> m_range
- m_thumbSize
)
197 pos
= m_range
- m_thumbSize
;
200 if ( m_thumbPos
== pos
)
202 // nothing changed, avoid refreshes which would provoke flicker
206 if ( m_thumbPosOld
== -1 )
208 // remember the old thumb position
209 m_thumbPosOld
= m_thumbPos
;
214 // we have to refresh the part of the bar which was under the thumb and the
216 m_elementsState
[Element_Thumb
] |= wxCONTROL_DIRTY
;
217 m_elementsState
[m_thumbPos
> m_thumbPosOld
218 ? Element_Bar_1
: Element_Bar_2
] |= wxCONTROL_DIRTY
;
222 int wxScrollBar::GetThumbPosition() const
227 int wxScrollBar::GetThumbSize() const
232 int wxScrollBar::GetPageSize() const
237 int wxScrollBar::GetRange() const
242 void wxScrollBar::SetThumbPosition(int pos
)
244 wxCHECK_RET( pos
>= 0 && pos
<= m_range
, _T("thumb position out of range") );
249 void wxScrollBar::SetScrollbar(int position
, int thumbSize
,
250 int range
, int pageSize
,
253 // we only refresh everything when the range changes, thumb position
254 // changes are handled in OnIdle
255 bool needsRefresh
= (range
!= m_range
) ||
256 (thumbSize
!= m_thumbSize
) ||
257 (pageSize
!= m_pageSize
);
259 // set all parameters
261 m_thumbSize
= thumbSize
;
262 SetThumbPosition(position
);
263 m_pageSize
= pageSize
;
265 // ignore refresh parameter unless we really need to refresh everything -
266 // there ir a lot of existing code which just calls SetScrollbar() without
267 // specifying the last parameter even though it doesn't need at all to
268 // refresh the window immediately
269 if ( refresh
&& needsRefresh
)
271 // and update the window
277 // ----------------------------------------------------------------------------
279 // ----------------------------------------------------------------------------
281 wxSize
wxScrollBar::DoGetBestClientSize() const
283 // this dimension is completely arbitrary
284 static const wxCoord SIZE
= 140;
286 wxSize size
= m_renderer
->GetScrollbarArrowSize();
299 wxScrollArrows::Arrow
wxScrollBar::HitTestArrow(const wxPoint
& pt
) const
301 switch ( HitTestBar(pt
) )
303 case wxHT_SCROLLBAR_ARROW_LINE_1
:
304 return wxScrollArrows::Arrow_First
;
306 case wxHT_SCROLLBAR_ARROW_LINE_2
:
307 return wxScrollArrows::Arrow_Second
;
310 return wxScrollArrows::Arrow_None
;
314 wxHitTest
wxScrollBar::HitTestBar(const wxPoint
& pt
) const
316 // we only need to work with either x or y coord depending on the
317 // orientation, choose one (but still check the other one to verify if the
318 // mouse is in the window at all)
319 const wxSize sizeArrowSB
= m_renderer
->GetScrollbarArrowSize();
321 wxCoord coord
, sizeArrow
, sizeTotal
;
322 wxSize size
= GetSize();
323 if ( GetWindowStyle() & wxVERTICAL
)
325 if ( pt
.x
< 0 || pt
.x
> size
.x
)
329 sizeArrow
= sizeArrowSB
.y
;
334 if ( pt
.y
< 0 || pt
.y
> size
.y
)
338 sizeArrow
= sizeArrowSB
.x
;
342 // test for the arrows first as it's faster
343 if ( coord
< 0 || coord
> sizeTotal
)
347 else if ( coord
< sizeArrow
)
349 return wxHT_SCROLLBAR_ARROW_LINE_1
;
351 else if ( coord
> sizeTotal
- sizeArrow
)
353 return wxHT_SCROLLBAR_ARROW_LINE_2
;
357 // calculate the thumb position in pixels
358 sizeTotal
-= 2*sizeArrow
;
359 wxCoord thumbStart
, thumbEnd
;
360 int range
= GetRange();
363 // clicking the scrollbar without range has no effect
368 GetScrollBarThumbSize(sizeTotal
,
376 // now compare with the thumb position
378 if ( coord
< thumbStart
)
379 return wxHT_SCROLLBAR_BAR_1
;
380 else if ( coord
> thumbEnd
)
381 return wxHT_SCROLLBAR_BAR_2
;
383 return wxHT_SCROLLBAR_THUMB
;
388 void wxScrollBar::GetScrollBarThumbSize(wxCoord length
,
395 // the thumb can't be made less than this number of pixels
396 static const wxCoord thumbMinWidth
= 8; // FIXME: should be configurable
398 *thumbStart
= (length
*thumbPos
) / range
;
399 *thumbEnd
= (length
*(thumbPos
+ thumbSize
)) / range
;
401 if ( *thumbEnd
- *thumbStart
< thumbMinWidth
)
403 // adjust the end if possible
404 if ( *thumbStart
<= length
- thumbMinWidth
)
406 // yes, just make it wider
407 *thumbEnd
= *thumbStart
+ thumbMinWidth
;
409 else // it is at the bottom of the scrollbar
411 // so move it a bit up
412 *thumbStart
= length
- thumbMinWidth
;
418 wxRect
wxScrollBar::GetScrollbarRect(wxScrollBar::Element elem
,
421 if ( thumbPos
== -1 )
423 thumbPos
= GetThumbPosition();
426 const wxSize sizeArrow
= m_renderer
->GetScrollbarArrowSize();
428 wxSize sizeTotal
= GetClientSize();
429 wxCoord
*start
, *width
;
430 wxCoord length
, arrow
;
435 rect
.width
= sizeTotal
.x
;
436 length
= sizeTotal
.y
;
438 width
= &rect
.height
;
444 rect
.height
= sizeTotal
.y
;
445 length
= sizeTotal
.x
;
453 case wxScrollBar::Element_Arrow_Line_1
:
458 case wxScrollBar::Element_Arrow_Line_2
:
459 *start
= length
- arrow
;
463 case wxScrollBar::Element_Arrow_Page_1
:
464 case wxScrollBar::Element_Arrow_Page_2
:
465 // we don't have them at all
468 case wxScrollBar::Element_Thumb
:
469 case wxScrollBar::Element_Bar_1
:
470 case wxScrollBar::Element_Bar_2
:
471 // we need to calculate the thumb position - do it
474 wxCoord thumbStart
, thumbEnd
;
475 int range
= GetRange();
483 GetScrollBarThumbSize(length
,
491 if ( elem
== wxScrollBar::Element_Thumb
)
494 *width
= thumbEnd
- thumbStart
;
496 else if ( elem
== wxScrollBar::Element_Bar_1
)
501 else // elem == wxScrollBar::Element_Bar_2
504 *width
= length
- thumbEnd
;
507 // everything is relative to the start of the shaft so far
512 case wxScrollBar::Element_Max
:
514 wxFAIL_MSG( _T("unknown scrollbar element") );
520 wxCoord
wxScrollBar::GetScrollbarSize() const
522 const wxSize sizeArrowSB
= m_renderer
->GetScrollbarArrowSize();
524 wxCoord sizeArrow
, sizeTotal
;
525 if ( GetWindowStyle() & wxVERTICAL
)
527 sizeArrow
= sizeArrowSB
.y
;
528 sizeTotal
= GetSize().y
;
532 sizeArrow
= sizeArrowSB
.x
;
533 sizeTotal
= GetSize().x
;
536 return sizeTotal
- 2*sizeArrow
;
540 wxCoord
wxScrollBar::ScrollbarToPixel(int thumbPos
)
542 int range
= GetRange();
545 // the only valid position anyhow
549 if ( thumbPos
== -1 )
551 // by default use the current thumb position
552 thumbPos
= GetThumbPosition();
555 const wxSize sizeArrow
= m_renderer
->GetScrollbarArrowSize();
556 return (thumbPos
* GetScrollbarSize()) / range
557 + (IsVertical() ? sizeArrow
.y
: sizeArrow
.x
);
560 int wxScrollBar::PixelToScrollbar(wxCoord coord
)
562 const wxSize sizeArrow
= m_renderer
->GetScrollbarArrowSize();
563 return ((coord
- (IsVertical() ? sizeArrow
.y
: sizeArrow
.x
)) *
564 GetRange() ) / GetScrollbarSize();
567 // ----------------------------------------------------------------------------
569 // ----------------------------------------------------------------------------
571 void wxScrollBar::OnInternalIdle()
574 wxControl::OnInternalIdle();
577 void wxScrollBar::UpdateThumb()
581 for ( size_t n
= 0; n
< WXSIZEOF(m_elementsState
); n
++ )
583 if ( m_elementsState
[n
] & wxCONTROL_DIRTY
)
585 wxRect rect
= GetScrollbarRect((Element
)n
);
587 if ( rect
.width
&& rect
.height
)
589 // we try to avoid redrawing the entire shaft (which might
590 // be quite long) if possible by only redrawing the area
591 // wich really changed
592 if ( (n
== Element_Bar_1
|| n
== Element_Bar_2
) &&
593 (m_thumbPosOld
!= -1) )
595 // the less efficient but more reliable (i.e. this will
596 // probably work everywhere) version: refresh the
597 // distance covered by thumb since the last update
600 GetRenderer()->GetScrollbarRect(this,
605 if ( n
== Element_Bar_1
)
606 rect
.SetTop(rectOld
.GetBottom());
608 rect
.SetBottom(rectOld
.GetBottom());
612 if ( n
== Element_Bar_1
)
613 rect
.SetLeft(rectOld
.GetRight());
615 rect
.SetRight(rectOld
.GetRight());
617 #else // efficient version: only repaint the area occupied by
618 // the thumb previously - we can't do better than this
619 rect
= GetScrollbarRect(Element_Thumb
, m_thumbPosOld
);
623 #ifdef WXDEBUG_SCROLLBAR
624 static bool s_refreshDebug
= false;
625 if ( s_refreshDebug
)
628 dc
.SetBrush(*wxCYAN_BRUSH
);
629 dc
.SetPen(*wxTRANSPARENT_PEN
);
630 dc
.DrawRectangle(rect
);
632 // under Unix we use "--sync" X option for this
633 #if defined(__WXMSW__) && !defined(__WXMICROWIN__)
638 #endif // WXDEBUG_SCROLLBAR
640 Refresh(false, &rect
);
643 m_elementsState
[n
] &= ~wxCONTROL_DIRTY
;
651 void wxScrollBar::DoDraw(wxControlRenderer
*renderer
)
653 renderer
->DrawScrollbar(this, m_thumbPosOld
);
655 // clear all dirty flags
660 // ----------------------------------------------------------------------------
662 // ----------------------------------------------------------------------------
664 static inline wxScrollBar::Element
ElementForArrow(wxScrollArrows::Arrow arrow
)
666 return arrow
== wxScrollArrows::Arrow_First
667 ? wxScrollBar::Element_Arrow_Line_1
668 : wxScrollBar::Element_Arrow_Line_2
;
671 int wxScrollBar::GetArrowState(wxScrollArrows::Arrow arrow
) const
673 return GetState(ElementForArrow(arrow
));
676 void wxScrollBar::SetArrowFlag(wxScrollArrows::Arrow arrow
, int flag
, bool set
)
678 Element which
= ElementForArrow(arrow
);
679 int state
= GetState(which
);
685 SetState(which
, state
);
688 int wxScrollBar::GetState(Element which
) const
690 // if the entire scrollbar is disabled, all of its elements are too
691 int flags
= m_elementsState
[which
];
693 flags
|= wxCONTROL_DISABLED
;
698 void wxScrollBar::SetState(Element which
, int flags
)
700 if ( (int)(m_elementsState
[which
] & ~wxCONTROL_DIRTY
) != flags
)
702 m_elementsState
[which
] = flags
| wxCONTROL_DIRTY
;
708 // ----------------------------------------------------------------------------
710 // ----------------------------------------------------------------------------
712 bool wxScrollBar::OnArrow(wxScrollArrows::Arrow arrow
)
714 int oldThumbPos
= GetThumbPosition();
715 PerformAction(arrow
== wxScrollArrows::Arrow_First
716 ? wxACTION_SCROLL_LINE_UP
717 : wxACTION_SCROLL_LINE_DOWN
);
719 // did we scroll till the end?
720 return GetThumbPosition() != oldThumbPos
;
723 bool wxScrollBar::PerformAction(const wxControlAction
& action
,
725 const wxString
& strArg
)
727 int thumbOld
= m_thumbPos
;
729 bool notify
= false; // send an event about the change?
731 wxEventType scrollType
;
733 // test for thumb move first as these events happen in quick succession
734 if ( action
== wxACTION_SCROLL_THUMB_MOVE
)
738 // VS: we have to force redraw here, otherwise the thumb will lack
739 // behind mouse cursor
742 scrollType
= wxEVT_SCROLLWIN_THUMBTRACK
;
744 else if ( action
== wxACTION_SCROLL_LINE_UP
)
746 scrollType
= wxEVT_SCROLLWIN_LINEUP
;
749 else if ( action
== wxACTION_SCROLL_LINE_DOWN
)
751 scrollType
= wxEVT_SCROLLWIN_LINEDOWN
;
754 else if ( action
== wxACTION_SCROLL_PAGE_UP
)
756 scrollType
= wxEVT_SCROLLWIN_PAGEUP
;
759 else if ( action
== wxACTION_SCROLL_PAGE_DOWN
)
761 scrollType
= wxEVT_SCROLLWIN_PAGEDOWN
;
764 else if ( action
== wxACTION_SCROLL_START
)
766 scrollType
= wxEVT_SCROLLWIN_THUMBRELEASE
; // anything better?
769 else if ( action
== wxACTION_SCROLL_END
)
771 scrollType
= wxEVT_SCROLLWIN_THUMBRELEASE
; // anything better?
774 else if ( action
== wxACTION_SCROLL_THUMB_DRAG
)
776 // we won't use it but this line suppresses the compiler
777 // warning about "variable may be used without having been
779 scrollType
= wxEVT_NULL
;
781 else if ( action
== wxACTION_SCROLL_THUMB_RELEASE
)
783 // always notify about this
785 scrollType
= wxEVT_SCROLLWIN_THUMBRELEASE
;
788 return wxControl::PerformAction(action
, numArg
, strArg
);
790 // has scrollbar position changed?
791 bool changed
= m_thumbPos
!= thumbOld
;
792 if ( notify
|| changed
)
794 if ( IsStandalone() )
796 // we should generate EVT_SCROLL events for the standalone
797 // scrollbars and not the EVT_SCROLLWIN ones
799 // NB: we assume that scrollbar events are sequentially numbered
800 // but this should be ok as other code relies on this as well
801 scrollType
+= wxEVT_SCROLL_TOP
- wxEVT_SCROLLWIN_TOP
;
802 wxScrollEvent
event(scrollType
, this->GetId(), m_thumbPos
,
803 IsVertical() ? wxVERTICAL
: wxHORIZONTAL
);
804 event
.SetEventObject(this);
805 GetEventHandler()->ProcessEvent(event
);
807 else // part of the window
809 wxScrollWinEvent
event(scrollType
, m_thumbPos
,
810 IsVertical() ? wxVERTICAL
: wxHORIZONTAL
);
811 event
.SetEventObject(this);
812 GetParent()->GetEventHandler()->ProcessEvent(event
);
819 void wxScrollBar::ScrollToStart()
824 void wxScrollBar::ScrollToEnd()
826 DoSetThumb(m_range
- m_thumbSize
);
829 bool wxScrollBar::ScrollLines(int nLines
)
831 DoSetThumb(m_thumbPos
+ nLines
);
835 bool wxScrollBar::ScrollPages(int nPages
)
837 DoSetThumb(m_thumbPos
+ nPages
*m_pageSize
);
842 wxInputHandler
*wxScrollBar::GetStdInputHandler(wxInputHandler
*handlerDef
)
844 static wxStdScrollBarInputHandler
845 s_handler(wxTheme::Get()->GetRenderer(), handlerDef
);
850 // ============================================================================
851 // scroll bar input handler
852 // ============================================================================
854 // ----------------------------------------------------------------------------
856 // ----------------------------------------------------------------------------
858 wxScrollBarTimer::wxScrollBarTimer(wxStdScrollBarInputHandler
*handler
,
859 const wxControlAction
& action
,
860 wxScrollBar
*control
)
867 bool wxScrollBarTimer::DoNotify()
869 return m_handler
->OnScrollTimer(m_control
, m_action
);
872 // ----------------------------------------------------------------------------
873 // wxStdScrollBarInputHandler
874 // ----------------------------------------------------------------------------
876 wxStdScrollBarInputHandler::wxStdScrollBarInputHandler(wxRenderer
*renderer
,
877 wxInputHandler
*handler
)
878 : wxStdInputHandler(handler
)
880 m_renderer
= renderer
;
882 m_htLast
= wxHT_NOWHERE
;
883 m_timerScroll
= NULL
;
886 wxStdScrollBarInputHandler::~wxStdScrollBarInputHandler()
888 // normally, it's NULL by now but just in case the user somehow managed to
889 // keep the mouse captured until now...
890 delete m_timerScroll
;
893 void wxStdScrollBarInputHandler::SetElementState(wxScrollBar
*control
,
897 if ( m_htLast
> wxHT_SCROLLBAR_FIRST
&& m_htLast
< wxHT_SCROLLBAR_LAST
)
900 elem
= (wxScrollBar::Element
)(m_htLast
- wxHT_SCROLLBAR_FIRST
- 1);
902 int flags
= control
->GetState(elem
);
907 control
->SetState(elem
, flags
);
911 bool wxStdScrollBarInputHandler::OnScrollTimer(wxScrollBar
*scrollbar
,
912 const wxControlAction
& action
)
914 int oldThumbPos
= scrollbar
->GetThumbPosition();
915 scrollbar
->PerformAction(action
);
916 if ( scrollbar
->GetThumbPosition() != oldThumbPos
)
919 // we scrolled till the end
920 m_timerScroll
->Stop();
925 void wxStdScrollBarInputHandler::StopScrolling(wxScrollBar
*control
)
927 // return everything to the normal state
930 m_winCapture
->ReleaseMouse();
938 delete m_timerScroll
;
939 m_timerScroll
= NULL
;
942 // unpress the arrow and highlight the current element
943 Press(control
, false);
947 wxStdScrollBarInputHandler::GetMouseCoord(const wxScrollBar
*scrollbar
,
948 const wxMouseEvent
& event
) const
950 wxPoint pt
= event
.GetPosition();
951 return scrollbar
->GetWindowStyle() & wxVERTICAL
? pt
.y
: pt
.x
;
954 void wxStdScrollBarInputHandler::HandleThumbMove(wxScrollBar
*scrollbar
,
955 const wxMouseEvent
& event
)
957 int thumbPos
= GetMouseCoord(scrollbar
, event
) - m_ofsMouse
;
958 thumbPos
= scrollbar
->PixelToScrollbar(thumbPos
);
959 scrollbar
->PerformAction(wxACTION_SCROLL_THUMB_MOVE
, thumbPos
);
962 bool wxStdScrollBarInputHandler::HandleKey(wxInputConsumer
*consumer
,
963 const wxKeyEvent
& event
,
966 // we only react to the key presses here
969 wxControlAction action
;
970 switch ( event
.GetKeyCode() )
973 case WXK_RIGHT
: action
= wxACTION_SCROLL_LINE_DOWN
; break;
975 case WXK_LEFT
: action
= wxACTION_SCROLL_LINE_UP
; break;
976 case WXK_HOME
: action
= wxACTION_SCROLL_START
; break;
977 case WXK_END
: action
= wxACTION_SCROLL_END
; break;
978 case WXK_PAGEUP
: action
= wxACTION_SCROLL_PAGE_UP
; break;
979 case WXK_PAGEDOWN
: action
= wxACTION_SCROLL_PAGE_DOWN
; break;
982 if ( !action
.IsEmpty() )
984 consumer
->PerformAction(action
);
990 return wxStdInputHandler::HandleKey(consumer
, event
, pressed
);
993 bool wxStdScrollBarInputHandler::HandleMouse(wxInputConsumer
*consumer
,
994 const wxMouseEvent
& event
)
996 // is this a click event from an acceptable button?
997 int btn
= event
.GetButton();
998 if ( btn
== wxMOUSE_BTN_LEFT
)
1000 // determine which part of the window mouse is in
1001 wxScrollBar
*scrollbar
= wxStaticCast(consumer
->GetInputWindow(), wxScrollBar
);
1002 wxHitTest ht
= scrollbar
->HitTestBar(event
.GetPosition());
1004 // when the mouse is pressed on any scrollbar element, we capture it
1005 // and hold capture until the same mouse button is released
1006 if ( event
.ButtonDown() || event
.ButtonDClick() )
1008 if ( !m_winCapture
)
1011 m_winCapture
= consumer
->GetInputWindow();
1012 m_winCapture
->CaptureMouse();
1014 // generate the command
1015 bool hasAction
= true;
1016 wxControlAction action
;
1019 case wxHT_SCROLLBAR_ARROW_LINE_1
:
1020 action
= wxACTION_SCROLL_LINE_UP
;
1023 case wxHT_SCROLLBAR_ARROW_LINE_2
:
1024 action
= wxACTION_SCROLL_LINE_DOWN
;
1027 case wxHT_SCROLLBAR_BAR_1
:
1028 action
= wxACTION_SCROLL_PAGE_UP
;
1029 m_ptStartScrolling
= event
.GetPosition();
1032 case wxHT_SCROLLBAR_BAR_2
:
1033 action
= wxACTION_SCROLL_PAGE_DOWN
;
1034 m_ptStartScrolling
= event
.GetPosition();
1037 case wxHT_SCROLLBAR_THUMB
:
1038 consumer
->PerformAction(wxACTION_SCROLL_THUMB_DRAG
);
1039 m_ofsMouse
= GetMouseCoord(scrollbar
, event
) -
1040 scrollbar
->ScrollbarToPixel();
1042 // fall through: there is no immediate action
1048 // remove highlighting
1049 Highlight(scrollbar
, false);
1052 // and press the arrow or highlight thumb now instead
1053 if ( m_htLast
== wxHT_SCROLLBAR_THUMB
)
1054 Highlight(scrollbar
, true);
1056 Press(scrollbar
, true);
1061 m_timerScroll
= new wxScrollBarTimer(this, action
,
1063 m_timerScroll
->StartAutoScroll();
1065 //else: no (immediate) action
1068 //else: mouse already captured, nothing to do
1070 // release mouse if the *same* button went up
1071 else if ( btn
== m_btnCapture
)
1075 StopScrolling(scrollbar
);
1077 // if we were dragging the thumb, send the last event
1078 if ( m_htLast
== wxHT_SCROLLBAR_THUMB
)
1080 scrollbar
->PerformAction(wxACTION_SCROLL_THUMB_RELEASE
);
1084 Highlight(scrollbar
, true);
1088 // this is not supposed to happen as the button can't go up
1089 // without going down previously and then we'd have
1090 // m_winCapture by now
1091 wxFAIL_MSG( _T("logic error in mouse capturing code") );
1096 return wxStdInputHandler::HandleMouse(consumer
, event
);
1099 bool wxStdScrollBarInputHandler::HandleMouseMove(wxInputConsumer
*consumer
,
1100 const wxMouseEvent
& event
)
1102 wxScrollBar
*scrollbar
= wxStaticCast(consumer
->GetInputWindow(), wxScrollBar
);
1106 if ( (m_htLast
== wxHT_SCROLLBAR_THUMB
) && event
.Dragging() )
1108 // make the thumb follow the mouse by keeping the same offset
1109 // between the mouse position and the top/left of the thumb
1110 HandleThumbMove(scrollbar
, event
);
1115 // no other changes are possible while the mouse is captured
1119 bool isArrow
= scrollbar
->GetArrows().HandleMouseMove(event
);
1121 if ( event
.Dragging() )
1123 wxHitTest ht
= scrollbar
->HitTestBar(event
.GetPosition());
1124 if ( ht
== m_htLast
)
1131 wxLogDebug("Scrollbar::OnMouseMove: ht = %d", ht
);
1132 #endif // DEBUG_MOUSE
1134 Highlight(scrollbar
, false);
1138 Highlight(scrollbar
, true);
1139 //else: already done by wxScrollArrows::HandleMouseMove
1141 else if ( event
.Leaving() )
1144 Highlight(scrollbar
, false);
1146 m_htLast
= wxHT_NOWHERE
;
1148 else // event.Entering()
1150 // we don't process this event
1158 #endif // wxUSE_SCROLLBAR
1162 // ----------------------------------------------------------------------------
1164 // ----------------------------------------------------------------------------
1166 wxScrollTimer::wxScrollTimer()
1171 void wxScrollTimer::StartAutoScroll()
1173 // start scrolling immediately
1176 // ... and end it too
1180 // there is an initial delay before the scrollbar starts scrolling -
1181 // implement it by ignoring the first timer expiration and only start
1182 // scrolling from the second one
1184 Start(200); // FIXME: hardcoded delay
1187 void wxScrollTimer::Notify()
1191 // scroll normally now - reduce the delay
1193 Start(50); // FIXME: hardcoded delay
1199 // if DoNotify() returns false, we're already deleted by the timer
1200 // event handler, so don't do anything else here
1205 #endif // wxUSE_TIMER