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 BEGIN_EVENT_TABLE(wxScrollBar
, wxScrollBarBase
)
80 // ----------------------------------------------------------------------------
82 // ----------------------------------------------------------------------------
85 // warning C4355: 'this' : used in base member initializer list
86 #pragma warning(disable:4355) // so what? disable it...
89 wxScrollBar::wxScrollBar()
95 wxScrollBar::wxScrollBar(wxWindow
*parent
,
100 const wxValidator
& validator
,
101 const wxString
& name
)
106 (void)Create(parent
, id
, pos
, size
, style
, validator
, name
);
110 // warning C4355: 'this' : used in base member initializer list
111 #pragma warning(default:4355)
114 void wxScrollBar::Init()
123 for ( size_t n
= 0; n
< WXSIZEOF(m_elementsState
); n
++ )
125 m_elementsState
[n
] = 0;
131 bool wxScrollBar::Create(wxWindow
*parent
,
136 const wxValidator
& validator
,
137 const wxString
&name
)
139 // the scrollbars never have the border
140 style
&= ~wxBORDER_MASK
;
142 if ( !wxControl::Create(parent
, id
, pos
, size
, style
, validator
, name
) )
145 SetInitialSize(size
);
147 // override the cursor of the target window (if any)
148 SetCursor(wxCURSOR_ARROW
);
150 CreateInputHandler(wxINP_HANDLER_SCROLLBAR
);
155 wxScrollBar::~wxScrollBar()
159 // ----------------------------------------------------------------------------
161 // ----------------------------------------------------------------------------
163 bool wxScrollBar::IsStandalone() const
165 wxWindow
*parent
= GetParent();
171 return (parent
->GetScrollbar(wxHORIZONTAL
) != this) &&
172 (parent
->GetScrollbar(wxVERTICAL
) != this);
175 bool wxScrollBar::AcceptsFocus() const
177 // the window scrollbars never accept focus
178 return wxScrollBarBase::AcceptsFocus() && IsStandalone();
181 // ----------------------------------------------------------------------------
183 // ----------------------------------------------------------------------------
185 void wxScrollBar::DoSetThumb(int pos
)
187 // don't assert hecks here, we're a private function which is meant to be
188 // called with any args at all
193 else if ( pos
> m_range
- m_thumbSize
)
195 pos
= m_range
- m_thumbSize
;
198 if ( m_thumbPos
== pos
)
200 // nothing changed, avoid refreshes which would provoke flicker
204 if ( m_thumbPosOld
== -1 )
206 // remember the old thumb position
207 m_thumbPosOld
= m_thumbPos
;
212 // we have to refresh the part of the bar which was under the thumb and the
214 m_elementsState
[Element_Thumb
] |= wxCONTROL_DIRTY
;
215 m_elementsState
[m_thumbPos
> m_thumbPosOld
216 ? Element_Bar_1
: Element_Bar_2
] |= wxCONTROL_DIRTY
;
220 int wxScrollBar::GetThumbPosition() const
225 int wxScrollBar::GetThumbSize() const
230 int wxScrollBar::GetPageSize() const
235 int wxScrollBar::GetRange() const
240 void wxScrollBar::SetThumbPosition(int pos
)
242 wxCHECK_RET( pos
>= 0 && pos
<= m_range
, wxT("thumb position out of range") );
247 void wxScrollBar::SetScrollbar(int position
, int thumbSize
,
248 int range
, int pageSize
,
251 // we only refresh everything when the range changes, thumb position
252 // changes are handled in OnIdle
253 bool needsRefresh
= (range
!= m_range
) ||
254 (thumbSize
!= m_thumbSize
) ||
255 (pageSize
!= m_pageSize
);
257 // set all parameters
259 m_thumbSize
= thumbSize
;
260 SetThumbPosition(position
);
261 m_pageSize
= pageSize
;
263 // ignore refresh parameter unless we really need to refresh everything -
264 // there ir a lot of existing code which just calls SetScrollbar() without
265 // specifying the last parameter even though it doesn't need at all to
266 // refresh the window immediately
267 if ( refresh
&& needsRefresh
)
269 // and update the window
275 // ----------------------------------------------------------------------------
277 // ----------------------------------------------------------------------------
279 wxSize
wxScrollBar::DoGetBestClientSize() const
281 // this dimension is completely arbitrary
282 static const wxCoord SIZE
= 140;
284 wxSize size
= m_renderer
->GetScrollbarArrowSize();
297 wxScrollArrows::Arrow
wxScrollBar::HitTestArrow(const wxPoint
& pt
) const
299 switch ( HitTestBar(pt
) )
301 case wxHT_SCROLLBAR_ARROW_LINE_1
:
302 return wxScrollArrows::Arrow_First
;
304 case wxHT_SCROLLBAR_ARROW_LINE_2
:
305 return wxScrollArrows::Arrow_Second
;
308 return wxScrollArrows::Arrow_None
;
312 wxHitTest
wxScrollBar::HitTestBar(const wxPoint
& pt
) const
314 // we only need to work with either x or y coord depending on the
315 // orientation, choose one (but still check the other one to verify if the
316 // mouse is in the window at all)
317 const wxSize sizeArrowSB
= m_renderer
->GetScrollbarArrowSize();
319 wxCoord coord
, sizeArrow
, sizeTotal
;
320 wxSize size
= GetSize();
321 if ( GetWindowStyle() & wxVERTICAL
)
323 if ( pt
.x
< 0 || pt
.x
> size
.x
)
327 sizeArrow
= sizeArrowSB
.y
;
332 if ( pt
.y
< 0 || pt
.y
> size
.y
)
336 sizeArrow
= sizeArrowSB
.x
;
340 // test for the arrows first as it's faster
341 if ( coord
< 0 || coord
> sizeTotal
)
345 else if ( coord
< sizeArrow
)
347 return wxHT_SCROLLBAR_ARROW_LINE_1
;
349 else if ( coord
> sizeTotal
- sizeArrow
)
351 return wxHT_SCROLLBAR_ARROW_LINE_2
;
355 // calculate the thumb position in pixels
356 sizeTotal
-= 2*sizeArrow
;
357 wxCoord thumbStart
, thumbEnd
;
358 int range
= GetRange();
361 // clicking the scrollbar without range has no effect
366 GetScrollBarThumbSize(sizeTotal
,
374 // now compare with the thumb position
376 if ( coord
< thumbStart
)
377 return wxHT_SCROLLBAR_BAR_1
;
378 else if ( coord
> thumbEnd
)
379 return wxHT_SCROLLBAR_BAR_2
;
381 return wxHT_SCROLLBAR_THUMB
;
386 void wxScrollBar::GetScrollBarThumbSize(wxCoord length
,
393 // the thumb can't be made less than this number of pixels
394 static const wxCoord thumbMinWidth
= 8; // FIXME: should be configurable
396 *thumbStart
= (length
*thumbPos
) / range
;
397 *thumbEnd
= (length
*(thumbPos
+ thumbSize
)) / range
;
399 if ( *thumbEnd
- *thumbStart
< thumbMinWidth
)
401 // adjust the end if possible
402 if ( *thumbStart
<= length
- thumbMinWidth
)
404 // yes, just make it wider
405 *thumbEnd
= *thumbStart
+ thumbMinWidth
;
407 else // it is at the bottom of the scrollbar
409 // so move it a bit up
410 *thumbStart
= length
- thumbMinWidth
;
416 wxRect
wxScrollBar::GetScrollbarRect(wxScrollBar::Element elem
,
419 if ( thumbPos
== -1 )
421 thumbPos
= GetThumbPosition();
424 const wxSize sizeArrow
= m_renderer
->GetScrollbarArrowSize();
426 wxSize sizeTotal
= GetClientSize();
427 wxCoord
*start
, *width
;
428 wxCoord length
, arrow
;
433 rect
.width
= sizeTotal
.x
;
434 length
= sizeTotal
.y
;
436 width
= &rect
.height
;
442 rect
.height
= sizeTotal
.y
;
443 length
= sizeTotal
.x
;
451 case wxScrollBar::Element_Arrow_Line_1
:
456 case wxScrollBar::Element_Arrow_Line_2
:
457 *start
= length
- arrow
;
461 case wxScrollBar::Element_Arrow_Page_1
:
462 case wxScrollBar::Element_Arrow_Page_2
:
463 // we don't have them at all
466 case wxScrollBar::Element_Thumb
:
467 case wxScrollBar::Element_Bar_1
:
468 case wxScrollBar::Element_Bar_2
:
469 // we need to calculate the thumb position - do it
472 wxCoord thumbStart
, thumbEnd
;
473 int range
= GetRange();
481 GetScrollBarThumbSize(length
,
489 if ( elem
== wxScrollBar::Element_Thumb
)
492 *width
= thumbEnd
- thumbStart
;
494 else if ( elem
== wxScrollBar::Element_Bar_1
)
499 else // elem == wxScrollBar::Element_Bar_2
502 *width
= length
- thumbEnd
;
505 // everything is relative to the start of the shaft so far
510 case wxScrollBar::Element_Max
:
512 wxFAIL_MSG( wxT("unknown scrollbar element") );
518 wxCoord
wxScrollBar::GetScrollbarSize() const
520 const wxSize sizeArrowSB
= m_renderer
->GetScrollbarArrowSize();
522 wxCoord sizeArrow
, sizeTotal
;
523 if ( GetWindowStyle() & wxVERTICAL
)
525 sizeArrow
= sizeArrowSB
.y
;
526 sizeTotal
= GetSize().y
;
530 sizeArrow
= sizeArrowSB
.x
;
531 sizeTotal
= GetSize().x
;
534 return sizeTotal
- 2*sizeArrow
;
538 wxCoord
wxScrollBar::ScrollbarToPixel(int thumbPos
)
540 int range
= GetRange();
543 // the only valid position anyhow
547 if ( thumbPos
== -1 )
549 // by default use the current thumb position
550 thumbPos
= GetThumbPosition();
553 const wxSize sizeArrow
= m_renderer
->GetScrollbarArrowSize();
554 return (thumbPos
* GetScrollbarSize()) / range
555 + (IsVertical() ? sizeArrow
.y
: sizeArrow
.x
);
558 int wxScrollBar::PixelToScrollbar(wxCoord coord
)
560 const wxSize sizeArrow
= m_renderer
->GetScrollbarArrowSize();
561 return ((coord
- (IsVertical() ? sizeArrow
.y
: sizeArrow
.x
)) *
562 GetRange() ) / GetScrollbarSize();
565 // ----------------------------------------------------------------------------
567 // ----------------------------------------------------------------------------
569 void wxScrollBar::OnInternalIdle()
572 wxControl::OnInternalIdle();
575 void wxScrollBar::UpdateThumb()
579 for ( size_t n
= 0; n
< WXSIZEOF(m_elementsState
); n
++ )
581 if ( m_elementsState
[n
] & wxCONTROL_DIRTY
)
583 wxRect rect
= GetScrollbarRect((Element
)n
);
585 if ( rect
.width
&& rect
.height
)
587 // we try to avoid redrawing the entire shaft (which might
588 // be quite long) if possible by only redrawing the area
589 // wich really changed
590 if ( (n
== Element_Bar_1
|| n
== Element_Bar_2
) &&
591 (m_thumbPosOld
!= -1) )
593 // the less efficient but more reliable (i.e. this will
594 // probably work everywhere) version: refresh the
595 // distance covered by thumb since the last update
598 GetRenderer()->GetScrollbarRect(this,
603 if ( n
== Element_Bar_1
)
604 rect
.SetTop(rectOld
.GetBottom());
606 rect
.SetBottom(rectOld
.GetBottom());
610 if ( n
== Element_Bar_1
)
611 rect
.SetLeft(rectOld
.GetRight());
613 rect
.SetRight(rectOld
.GetRight());
615 #else // efficient version: only repaint the area occupied by
616 // the thumb previously - we can't do better than this
617 rect
= GetScrollbarRect(Element_Thumb
, m_thumbPosOld
);
621 #ifdef WXDEBUG_SCROLLBAR
622 static bool s_refreshDebug
= false;
623 if ( s_refreshDebug
)
626 dc
.SetBrush(*wxCYAN_BRUSH
);
627 dc
.SetPen(*wxTRANSPARENT_PEN
);
628 dc
.DrawRectangle(rect
);
630 // under Unix we use "--sync" X option for this
631 #if defined(__WXMSW__) && !defined(__WXMICROWIN__)
636 #endif // WXDEBUG_SCROLLBAR
638 Refresh(false, &rect
);
641 m_elementsState
[n
] &= ~wxCONTROL_DIRTY
;
649 void wxScrollBar::DoDraw(wxControlRenderer
*renderer
)
651 renderer
->DrawScrollbar(this, m_thumbPosOld
);
653 // clear all dirty flags
658 // ----------------------------------------------------------------------------
660 // ----------------------------------------------------------------------------
662 static inline wxScrollBar::Element
ElementForArrow(wxScrollArrows::Arrow arrow
)
664 return arrow
== wxScrollArrows::Arrow_First
665 ? wxScrollBar::Element_Arrow_Line_1
666 : wxScrollBar::Element_Arrow_Line_2
;
669 int wxScrollBar::GetArrowState(wxScrollArrows::Arrow arrow
) const
671 return GetState(ElementForArrow(arrow
));
674 void wxScrollBar::SetArrowFlag(wxScrollArrows::Arrow arrow
, int flag
, bool set
)
676 Element which
= ElementForArrow(arrow
);
677 int state
= GetState(which
);
683 SetState(which
, state
);
686 int wxScrollBar::GetState(Element which
) const
688 // if the entire scrollbar is disabled, all of its elements are too
689 int flags
= m_elementsState
[which
];
691 flags
|= wxCONTROL_DISABLED
;
696 void wxScrollBar::SetState(Element which
, int flags
)
698 if ( (int)(m_elementsState
[which
] & ~wxCONTROL_DIRTY
) != flags
)
700 m_elementsState
[which
] = flags
| wxCONTROL_DIRTY
;
706 // ----------------------------------------------------------------------------
708 // ----------------------------------------------------------------------------
710 bool wxScrollBar::OnArrow(wxScrollArrows::Arrow arrow
)
712 int oldThumbPos
= GetThumbPosition();
713 PerformAction(arrow
== wxScrollArrows::Arrow_First
714 ? wxACTION_SCROLL_LINE_UP
715 : wxACTION_SCROLL_LINE_DOWN
);
717 // did we scroll till the end?
718 return GetThumbPosition() != oldThumbPos
;
721 bool wxScrollBar::PerformAction(const wxControlAction
& action
,
723 const wxString
& strArg
)
725 int thumbOld
= m_thumbPos
;
727 bool notify
= false; // send an event about the change?
729 wxEventType scrollType
;
731 // test for thumb move first as these events happen in quick succession
732 if ( action
== wxACTION_SCROLL_THUMB_MOVE
)
736 // VS: we have to force redraw here, otherwise the thumb will lack
737 // behind mouse cursor
740 scrollType
= wxEVT_SCROLLWIN_THUMBTRACK
;
742 else if ( action
== wxACTION_SCROLL_LINE_UP
)
744 scrollType
= wxEVT_SCROLLWIN_LINEUP
;
747 else if ( action
== wxACTION_SCROLL_LINE_DOWN
)
749 scrollType
= wxEVT_SCROLLWIN_LINEDOWN
;
752 else if ( action
== wxACTION_SCROLL_PAGE_UP
)
754 scrollType
= wxEVT_SCROLLWIN_PAGEUP
;
757 else if ( action
== wxACTION_SCROLL_PAGE_DOWN
)
759 scrollType
= wxEVT_SCROLLWIN_PAGEDOWN
;
762 else if ( action
== wxACTION_SCROLL_START
)
764 scrollType
= wxEVT_SCROLLWIN_THUMBRELEASE
; // anything better?
767 else if ( action
== wxACTION_SCROLL_END
)
769 scrollType
= wxEVT_SCROLLWIN_THUMBRELEASE
; // anything better?
772 else if ( action
== wxACTION_SCROLL_THUMB_DRAG
)
774 // we won't use it but this line suppresses the compiler
775 // warning about "variable may be used without having been
777 scrollType
= wxEVT_NULL
;
779 else if ( action
== wxACTION_SCROLL_THUMB_RELEASE
)
781 // always notify about this
783 scrollType
= wxEVT_SCROLLWIN_THUMBRELEASE
;
786 return wxControl::PerformAction(action
, numArg
, strArg
);
788 // has scrollbar position changed?
789 bool changed
= m_thumbPos
!= thumbOld
;
790 if ( notify
|| changed
)
792 if ( IsStandalone() )
794 // we should generate EVT_SCROLL events for the standalone
795 // scrollbars and not the EVT_SCROLLWIN ones
797 // NB: we assume that scrollbar events are sequentially numbered
798 // but this should be ok as other code relies on this as well
799 scrollType
+= wxEVT_SCROLL_TOP
- wxEVT_SCROLLWIN_TOP
;
800 wxScrollEvent
event(scrollType
, this->GetId(), m_thumbPos
,
801 IsVertical() ? wxVERTICAL
: wxHORIZONTAL
);
802 event
.SetEventObject(this);
803 GetEventHandler()->ProcessEvent(event
);
805 else // part of the window
807 wxScrollWinEvent
event(scrollType
, m_thumbPos
,
808 IsVertical() ? wxVERTICAL
: wxHORIZONTAL
);
809 event
.SetEventObject(this);
810 GetParent()->GetEventHandler()->ProcessEvent(event
);
817 void wxScrollBar::ScrollToStart()
822 void wxScrollBar::ScrollToEnd()
824 DoSetThumb(m_range
- m_thumbSize
);
827 bool wxScrollBar::ScrollLines(int nLines
)
829 DoSetThumb(m_thumbPos
+ nLines
);
833 bool wxScrollBar::ScrollPages(int nPages
)
835 DoSetThumb(m_thumbPos
+ nPages
*m_pageSize
);
840 wxInputHandler
*wxScrollBar::GetStdInputHandler(wxInputHandler
*handlerDef
)
842 static wxStdScrollBarInputHandler
843 s_handler(wxTheme::Get()->GetRenderer(), handlerDef
);
848 // ============================================================================
849 // scroll bar input handler
850 // ============================================================================
852 // ----------------------------------------------------------------------------
854 // ----------------------------------------------------------------------------
856 wxScrollBarTimer::wxScrollBarTimer(wxStdScrollBarInputHandler
*handler
,
857 const wxControlAction
& action
,
858 wxScrollBar
*control
)
865 bool wxScrollBarTimer::DoNotify()
867 return m_handler
->OnScrollTimer(m_control
, m_action
);
870 // ----------------------------------------------------------------------------
871 // wxStdScrollBarInputHandler
872 // ----------------------------------------------------------------------------
874 wxStdScrollBarInputHandler::wxStdScrollBarInputHandler(wxRenderer
*renderer
,
875 wxInputHandler
*handler
)
876 : wxStdInputHandler(handler
)
878 m_renderer
= renderer
;
880 m_htLast
= wxHT_NOWHERE
;
881 m_timerScroll
= NULL
;
884 wxStdScrollBarInputHandler::~wxStdScrollBarInputHandler()
886 // normally, it's NULL by now but just in case the user somehow managed to
887 // keep the mouse captured until now...
888 delete m_timerScroll
;
891 void wxStdScrollBarInputHandler::SetElementState(wxScrollBar
*control
,
895 if ( m_htLast
> wxHT_SCROLLBAR_FIRST
&& m_htLast
< wxHT_SCROLLBAR_LAST
)
898 elem
= (wxScrollBar::Element
)(m_htLast
- wxHT_SCROLLBAR_FIRST
- 1);
900 int flags
= control
->GetState(elem
);
905 control
->SetState(elem
, flags
);
909 bool wxStdScrollBarInputHandler::OnScrollTimer(wxScrollBar
*scrollbar
,
910 const wxControlAction
& action
)
912 int oldThumbPos
= scrollbar
->GetThumbPosition();
913 scrollbar
->PerformAction(action
);
914 if ( scrollbar
->GetThumbPosition() != oldThumbPos
)
917 // we scrolled till the end
918 m_timerScroll
->Stop();
923 void wxStdScrollBarInputHandler::StopScrolling(wxScrollBar
*control
)
925 // return everything to the normal state
928 m_winCapture
->ReleaseMouse();
934 wxDELETE(m_timerScroll
);
936 // unpress the arrow and highlight the current element
937 Press(control
, false);
941 wxStdScrollBarInputHandler::GetMouseCoord(const wxScrollBar
*scrollbar
,
942 const wxMouseEvent
& event
) const
944 wxPoint pt
= event
.GetPosition();
945 return scrollbar
->GetWindowStyle() & wxVERTICAL
? pt
.y
: pt
.x
;
948 void wxStdScrollBarInputHandler::HandleThumbMove(wxScrollBar
*scrollbar
,
949 const wxMouseEvent
& event
)
951 int thumbPos
= GetMouseCoord(scrollbar
, event
) - m_ofsMouse
;
952 thumbPos
= scrollbar
->PixelToScrollbar(thumbPos
);
953 scrollbar
->PerformAction(wxACTION_SCROLL_THUMB_MOVE
, thumbPos
);
956 bool wxStdScrollBarInputHandler::HandleKey(wxInputConsumer
*consumer
,
957 const wxKeyEvent
& event
,
960 // we only react to the key presses here
963 wxControlAction action
;
964 switch ( event
.GetKeyCode() )
967 case WXK_RIGHT
: action
= wxACTION_SCROLL_LINE_DOWN
; break;
969 case WXK_LEFT
: action
= wxACTION_SCROLL_LINE_UP
; break;
970 case WXK_HOME
: action
= wxACTION_SCROLL_START
; break;
971 case WXK_END
: action
= wxACTION_SCROLL_END
; break;
972 case WXK_PAGEUP
: action
= wxACTION_SCROLL_PAGE_UP
; break;
973 case WXK_PAGEDOWN
: action
= wxACTION_SCROLL_PAGE_DOWN
; break;
976 if ( !action
.IsEmpty() )
978 consumer
->PerformAction(action
);
984 return wxStdInputHandler::HandleKey(consumer
, event
, pressed
);
987 bool wxStdScrollBarInputHandler::HandleMouse(wxInputConsumer
*consumer
,
988 const wxMouseEvent
& event
)
990 // is this a click event from an acceptable button?
991 int btn
= event
.GetButton();
992 if ( btn
== wxMOUSE_BTN_LEFT
)
994 // determine which part of the window mouse is in
995 wxScrollBar
*scrollbar
= wxStaticCast(consumer
->GetInputWindow(), wxScrollBar
);
996 wxHitTest ht
= scrollbar
->HitTestBar(event
.GetPosition());
998 // when the mouse is pressed on any scrollbar element, we capture it
999 // and hold capture until the same mouse button is released
1000 if ( event
.ButtonDown() || event
.ButtonDClick() )
1002 if ( !m_winCapture
)
1005 m_winCapture
= consumer
->GetInputWindow();
1006 m_winCapture
->CaptureMouse();
1008 // generate the command
1009 bool hasAction
= true;
1010 wxControlAction action
;
1013 case wxHT_SCROLLBAR_ARROW_LINE_1
:
1014 action
= wxACTION_SCROLL_LINE_UP
;
1017 case wxHT_SCROLLBAR_ARROW_LINE_2
:
1018 action
= wxACTION_SCROLL_LINE_DOWN
;
1021 case wxHT_SCROLLBAR_BAR_1
:
1022 action
= wxACTION_SCROLL_PAGE_UP
;
1023 m_ptStartScrolling
= event
.GetPosition();
1026 case wxHT_SCROLLBAR_BAR_2
:
1027 action
= wxACTION_SCROLL_PAGE_DOWN
;
1028 m_ptStartScrolling
= event
.GetPosition();
1031 case wxHT_SCROLLBAR_THUMB
:
1032 consumer
->PerformAction(wxACTION_SCROLL_THUMB_DRAG
);
1033 m_ofsMouse
= GetMouseCoord(scrollbar
, event
) -
1034 scrollbar
->ScrollbarToPixel();
1036 // fall through: there is no immediate action
1042 // remove highlighting
1043 Highlight(scrollbar
, false);
1046 // and press the arrow or highlight thumb now instead
1047 if ( m_htLast
== wxHT_SCROLLBAR_THUMB
)
1048 Highlight(scrollbar
, true);
1050 Press(scrollbar
, true);
1055 m_timerScroll
= new wxScrollBarTimer(this, action
,
1057 m_timerScroll
->StartAutoScroll();
1059 //else: no (immediate) action
1062 //else: mouse already captured, nothing to do
1064 // release mouse if the *same* button went up
1065 else if ( btn
== m_btnCapture
)
1069 StopScrolling(scrollbar
);
1071 // if we were dragging the thumb, send the last event
1072 if ( m_htLast
== wxHT_SCROLLBAR_THUMB
)
1074 scrollbar
->PerformAction(wxACTION_SCROLL_THUMB_RELEASE
);
1078 Highlight(scrollbar
, true);
1082 // this is not supposed to happen as the button can't go up
1083 // without going down previously and then we'd have
1084 // m_winCapture by now
1085 wxFAIL_MSG( wxT("logic error in mouse capturing code") );
1090 return wxStdInputHandler::HandleMouse(consumer
, event
);
1093 bool wxStdScrollBarInputHandler::HandleMouseMove(wxInputConsumer
*consumer
,
1094 const wxMouseEvent
& event
)
1096 wxScrollBar
*scrollbar
= wxStaticCast(consumer
->GetInputWindow(), wxScrollBar
);
1100 if ( (m_htLast
== wxHT_SCROLLBAR_THUMB
) && event
.Dragging() )
1102 // make the thumb follow the mouse by keeping the same offset
1103 // between the mouse position and the top/left of the thumb
1104 HandleThumbMove(scrollbar
, event
);
1109 // no other changes are possible while the mouse is captured
1113 bool isArrow
= scrollbar
->GetArrows().HandleMouseMove(event
);
1115 if ( event
.Dragging() )
1117 wxHitTest ht
= scrollbar
->HitTestBar(event
.GetPosition());
1118 if ( ht
== m_htLast
)
1125 wxLogDebug("Scrollbar::OnMouseMove: ht = %d", ht
);
1126 #endif // DEBUG_MOUSE
1128 Highlight(scrollbar
, false);
1132 Highlight(scrollbar
, true);
1133 //else: already done by wxScrollArrows::HandleMouseMove
1135 else if ( event
.Leaving() )
1138 Highlight(scrollbar
, false);
1140 m_htLast
= wxHT_NOWHERE
;
1142 else // event.Entering()
1144 // we don't process this event
1152 #endif // wxUSE_SCROLLBAR
1156 // ----------------------------------------------------------------------------
1158 // ----------------------------------------------------------------------------
1160 wxScrollTimer::wxScrollTimer()
1165 void wxScrollTimer::StartAutoScroll()
1167 // start scrolling immediately
1170 // ... and end it too
1174 // there is an initial delay before the scrollbar starts scrolling -
1175 // implement it by ignoring the first timer expiration and only start
1176 // scrolling from the second one
1178 Start(200); // FIXME: hardcoded delay
1181 void wxScrollTimer::Notify()
1185 // scroll normally now - reduce the delay
1187 Start(50); // FIXME: hardcoded delay
1193 // if DoNotify() returns false, we're already deleted by the timer
1194 // event handler, so don't do anything else here
1199 #endif // wxUSE_TIMER