1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/univ/scrolbar.cpp
3 // Purpose: wxScrollBar implementation
4 // Author: Vadim Zeitlin
7 // Copyright: (c) 2000 SciTech Software, Inc. (www.scitechsoft.com)
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 // ============================================================================
13 // ============================================================================
15 // ----------------------------------------------------------------------------
17 // ----------------------------------------------------------------------------
19 #include "wx/wxprec.h"
27 #include "wx/scrolbar.h"
31 #include "wx/dcclient.h"
32 #include "wx/validate.h"
36 #include "wx/univ/scrtimer.h"
38 #include "wx/univ/renderer.h"
39 #include "wx/univ/inphand.h"
40 #include "wx/univ/theme.h"
42 #if wxDEBUG_LEVEL >= 2
43 #define WXDEBUG_SCROLLBAR
46 #if defined(WXDEBUG_SCROLLBAR) && defined(__WXMSW__) && !defined(__WXMICROWIN__)
47 #include "wx/msw/private.h"
50 // ----------------------------------------------------------------------------
51 // wxScrollBarTimer: this class is used to repeatedly scroll the scrollbar
52 // when the mouse is help pressed on the arrow or on the bar. It generates the
53 // given scroll action command periodically.
54 // ----------------------------------------------------------------------------
56 class wxScrollBarTimer
: public wxScrollTimer
59 wxScrollBarTimer(wxStdScrollBarInputHandler
*handler
,
60 const wxControlAction
& action
,
61 wxScrollBar
*control
);
64 virtual bool DoNotify();
67 wxStdScrollBarInputHandler
*m_handler
;
68 wxControlAction m_action
;
69 wxScrollBar
*m_control
;
72 // ============================================================================
74 // ============================================================================
76 BEGIN_EVENT_TABLE(wxScrollBar
, wxScrollBarBase
)
79 // ----------------------------------------------------------------------------
81 // ----------------------------------------------------------------------------
84 // warning C4355: 'this' : used in base member initializer list
85 #pragma warning(disable:4355) // so what? disable it...
88 wxScrollBar::wxScrollBar()
94 wxScrollBar::wxScrollBar(wxWindow
*parent
,
99 const wxValidator
& validator
,
100 const wxString
& name
)
105 (void)Create(parent
, id
, pos
, size
, style
, validator
, name
);
109 // warning C4355: 'this' : used in base member initializer list
110 #pragma warning(default:4355)
113 void wxScrollBar::Init()
122 for ( size_t n
= 0; n
< WXSIZEOF(m_elementsState
); n
++ )
124 m_elementsState
[n
] = 0;
130 bool wxScrollBar::Create(wxWindow
*parent
,
135 const wxValidator
& validator
,
136 const wxString
&name
)
138 // the scrollbars never have the border
139 style
&= ~wxBORDER_MASK
;
141 if ( !wxControl::Create(parent
, id
, pos
, size
, style
, validator
, name
) )
144 SetInitialSize(size
);
146 // override the cursor of the target window (if any)
147 SetCursor(wxCURSOR_ARROW
);
149 CreateInputHandler(wxINP_HANDLER_SCROLLBAR
);
154 wxScrollBar::~wxScrollBar()
158 // ----------------------------------------------------------------------------
160 // ----------------------------------------------------------------------------
162 bool wxScrollBar::IsStandalone() const
164 wxWindow
*parent
= GetParent();
170 return (parent
->GetScrollbar(wxHORIZONTAL
) != this) &&
171 (parent
->GetScrollbar(wxVERTICAL
) != this);
174 bool wxScrollBar::AcceptsFocus() const
176 // the window scrollbars never accept focus
177 return wxScrollBarBase::AcceptsFocus() && IsStandalone();
180 // ----------------------------------------------------------------------------
182 // ----------------------------------------------------------------------------
184 void wxScrollBar::DoSetThumb(int pos
)
186 // don't assert hecks here, we're a private function which is meant to be
187 // called with any args at all
192 else if ( pos
> m_range
- m_thumbSize
)
194 pos
= m_range
- m_thumbSize
;
197 if ( m_thumbPos
== pos
)
199 // nothing changed, avoid refreshes which would provoke flicker
203 if ( m_thumbPosOld
== -1 )
205 // remember the old thumb position
206 m_thumbPosOld
= m_thumbPos
;
211 // we have to refresh the part of the bar which was under the thumb and the
213 m_elementsState
[Element_Thumb
] |= wxCONTROL_DIRTY
;
214 m_elementsState
[m_thumbPos
> m_thumbPosOld
215 ? Element_Bar_1
: Element_Bar_2
] |= wxCONTROL_DIRTY
;
219 int wxScrollBar::GetThumbPosition() const
224 int wxScrollBar::GetThumbSize() const
229 int wxScrollBar::GetPageSize() const
234 int wxScrollBar::GetRange() const
239 void wxScrollBar::SetThumbPosition(int pos
)
241 wxCHECK_RET( pos
>= 0 && pos
<= m_range
, wxT("thumb position out of range") );
246 void wxScrollBar::SetScrollbar(int position
, int thumbSize
,
247 int range
, int pageSize
,
250 // we only refresh everything when the range changes, thumb position
251 // changes are handled in OnIdle
252 bool needsRefresh
= (range
!= m_range
) ||
253 (thumbSize
!= m_thumbSize
) ||
254 (pageSize
!= m_pageSize
);
256 // set all parameters
258 m_thumbSize
= thumbSize
;
259 SetThumbPosition(position
);
260 m_pageSize
= pageSize
;
262 // ignore refresh parameter unless we really need to refresh everything -
263 // there ir a lot of existing code which just calls SetScrollbar() without
264 // specifying the last parameter even though it doesn't need at all to
265 // refresh the window immediately
266 if ( refresh
&& needsRefresh
)
268 // and update the window
274 // ----------------------------------------------------------------------------
276 // ----------------------------------------------------------------------------
278 wxSize
wxScrollBar::DoGetBestClientSize() const
280 // this dimension is completely arbitrary
281 static const wxCoord SIZE
= 140;
283 wxSize size
= m_renderer
->GetScrollbarArrowSize();
296 wxScrollArrows::Arrow
wxScrollBar::HitTestArrow(const wxPoint
& pt
) const
298 switch ( HitTestBar(pt
) )
300 case wxHT_SCROLLBAR_ARROW_LINE_1
:
301 return wxScrollArrows::Arrow_First
;
303 case wxHT_SCROLLBAR_ARROW_LINE_2
:
304 return wxScrollArrows::Arrow_Second
;
307 return wxScrollArrows::Arrow_None
;
311 wxHitTest
wxScrollBar::HitTestBar(const wxPoint
& pt
) const
313 // we only need to work with either x or y coord depending on the
314 // orientation, choose one (but still check the other one to verify if the
315 // mouse is in the window at all)
316 const wxSize sizeArrowSB
= m_renderer
->GetScrollbarArrowSize();
318 wxCoord coord
, sizeArrow
, sizeTotal
;
319 wxSize size
= GetSize();
320 if ( GetWindowStyle() & wxVERTICAL
)
322 if ( pt
.x
< 0 || pt
.x
> size
.x
)
326 sizeArrow
= sizeArrowSB
.y
;
331 if ( pt
.y
< 0 || pt
.y
> size
.y
)
335 sizeArrow
= sizeArrowSB
.x
;
339 // test for the arrows first as it's faster
340 if ( coord
< 0 || coord
> sizeTotal
)
344 else if ( coord
< sizeArrow
)
346 return wxHT_SCROLLBAR_ARROW_LINE_1
;
348 else if ( coord
> sizeTotal
- sizeArrow
)
350 return wxHT_SCROLLBAR_ARROW_LINE_2
;
354 // calculate the thumb position in pixels
355 sizeTotal
-= 2*sizeArrow
;
356 wxCoord thumbStart
, thumbEnd
;
357 int range
= GetRange();
360 // clicking the scrollbar without range has no effect
365 GetScrollBarThumbSize(sizeTotal
,
373 // now compare with the thumb position
375 if ( coord
< thumbStart
)
376 return wxHT_SCROLLBAR_BAR_1
;
377 else if ( coord
> thumbEnd
)
378 return wxHT_SCROLLBAR_BAR_2
;
380 return wxHT_SCROLLBAR_THUMB
;
385 void wxScrollBar::GetScrollBarThumbSize(wxCoord length
,
392 // the thumb can't be made less than this number of pixels
393 static const wxCoord thumbMinWidth
= 8; // FIXME: should be configurable
395 *thumbStart
= (length
*thumbPos
) / range
;
396 *thumbEnd
= (length
*(thumbPos
+ thumbSize
)) / range
;
398 if ( *thumbEnd
- *thumbStart
< thumbMinWidth
)
400 // adjust the end if possible
401 if ( *thumbStart
<= length
- thumbMinWidth
)
403 // yes, just make it wider
404 *thumbEnd
= *thumbStart
+ thumbMinWidth
;
406 else // it is at the bottom of the scrollbar
408 // so move it a bit up
409 *thumbStart
= length
- thumbMinWidth
;
415 wxRect
wxScrollBar::GetScrollbarRect(wxScrollBar::Element elem
,
418 if ( thumbPos
== -1 )
420 thumbPos
= GetThumbPosition();
423 const wxSize sizeArrow
= m_renderer
->GetScrollbarArrowSize();
425 wxSize sizeTotal
= GetClientSize();
426 wxCoord
*start
, *width
;
427 wxCoord length
, arrow
;
432 rect
.width
= sizeTotal
.x
;
433 length
= sizeTotal
.y
;
435 width
= &rect
.height
;
441 rect
.height
= sizeTotal
.y
;
442 length
= sizeTotal
.x
;
450 case wxScrollBar::Element_Arrow_Line_1
:
455 case wxScrollBar::Element_Arrow_Line_2
:
456 *start
= length
- arrow
;
460 case wxScrollBar::Element_Arrow_Page_1
:
461 case wxScrollBar::Element_Arrow_Page_2
:
462 // we don't have them at all
465 case wxScrollBar::Element_Thumb
:
466 case wxScrollBar::Element_Bar_1
:
467 case wxScrollBar::Element_Bar_2
:
468 // we need to calculate the thumb position - do it
471 wxCoord thumbStart
, thumbEnd
;
472 int range
= GetRange();
480 GetScrollBarThumbSize(length
,
488 if ( elem
== wxScrollBar::Element_Thumb
)
491 *width
= thumbEnd
- thumbStart
;
493 else if ( elem
== wxScrollBar::Element_Bar_1
)
498 else // elem == wxScrollBar::Element_Bar_2
501 *width
= length
- thumbEnd
;
504 // everything is relative to the start of the shaft so far
509 case wxScrollBar::Element_Max
:
511 wxFAIL_MSG( wxT("unknown scrollbar element") );
517 wxCoord
wxScrollBar::GetScrollbarSize() const
519 const wxSize sizeArrowSB
= m_renderer
->GetScrollbarArrowSize();
521 wxCoord sizeArrow
, sizeTotal
;
522 if ( GetWindowStyle() & wxVERTICAL
)
524 sizeArrow
= sizeArrowSB
.y
;
525 sizeTotal
= GetSize().y
;
529 sizeArrow
= sizeArrowSB
.x
;
530 sizeTotal
= GetSize().x
;
533 return sizeTotal
- 2*sizeArrow
;
537 wxCoord
wxScrollBar::ScrollbarToPixel(int thumbPos
)
539 int range
= GetRange();
542 // the only valid position anyhow
546 if ( thumbPos
== -1 )
548 // by default use the current thumb position
549 thumbPos
= GetThumbPosition();
552 const wxSize sizeArrow
= m_renderer
->GetScrollbarArrowSize();
553 return (thumbPos
* GetScrollbarSize()) / range
554 + (IsVertical() ? sizeArrow
.y
: sizeArrow
.x
);
557 int wxScrollBar::PixelToScrollbar(wxCoord coord
)
559 const wxSize sizeArrow
= m_renderer
->GetScrollbarArrowSize();
560 return ((coord
- (IsVertical() ? sizeArrow
.y
: sizeArrow
.x
)) *
561 GetRange() ) / GetScrollbarSize();
564 // ----------------------------------------------------------------------------
566 // ----------------------------------------------------------------------------
568 void wxScrollBar::OnInternalIdle()
571 wxControl::OnInternalIdle();
574 void wxScrollBar::UpdateThumb()
578 for ( size_t n
= 0; n
< WXSIZEOF(m_elementsState
); n
++ )
580 if ( m_elementsState
[n
] & wxCONTROL_DIRTY
)
582 wxRect rect
= GetScrollbarRect((Element
)n
);
584 if ( rect
.width
&& rect
.height
)
586 // we try to avoid redrawing the entire shaft (which might
587 // be quite long) if possible by only redrawing the area
588 // wich really changed
589 if ( (n
== Element_Bar_1
|| n
== Element_Bar_2
) &&
590 (m_thumbPosOld
!= -1) )
592 // the less efficient but more reliable (i.e. this will
593 // probably work everywhere) version: refresh the
594 // distance covered by thumb since the last update
597 GetRenderer()->GetScrollbarRect(this,
602 if ( n
== Element_Bar_1
)
603 rect
.SetTop(rectOld
.GetBottom());
605 rect
.SetBottom(rectOld
.GetBottom());
609 if ( n
== Element_Bar_1
)
610 rect
.SetLeft(rectOld
.GetRight());
612 rect
.SetRight(rectOld
.GetRight());
614 #else // efficient version: only repaint the area occupied by
615 // the thumb previously - we can't do better than this
616 rect
= GetScrollbarRect(Element_Thumb
, m_thumbPosOld
);
620 #ifdef WXDEBUG_SCROLLBAR
621 static bool s_refreshDebug
= false;
622 if ( s_refreshDebug
)
625 dc
.SetBrush(*wxCYAN_BRUSH
);
626 dc
.SetPen(*wxTRANSPARENT_PEN
);
627 dc
.DrawRectangle(rect
);
629 // under Unix we use "--sync" X option for this
630 #if defined(__WXMSW__) && !defined(__WXMICROWIN__)
635 #endif // WXDEBUG_SCROLLBAR
637 Refresh(false, &rect
);
640 m_elementsState
[n
] &= ~wxCONTROL_DIRTY
;
648 void wxScrollBar::DoDraw(wxControlRenderer
*renderer
)
650 renderer
->DrawScrollbar(this, m_thumbPosOld
);
652 // clear all dirty flags
657 // ----------------------------------------------------------------------------
659 // ----------------------------------------------------------------------------
661 static inline wxScrollBar::Element
ElementForArrow(wxScrollArrows::Arrow arrow
)
663 return arrow
== wxScrollArrows::Arrow_First
664 ? wxScrollBar::Element_Arrow_Line_1
665 : wxScrollBar::Element_Arrow_Line_2
;
668 int wxScrollBar::GetArrowState(wxScrollArrows::Arrow arrow
) const
670 return GetState(ElementForArrow(arrow
));
673 void wxScrollBar::SetArrowFlag(wxScrollArrows::Arrow arrow
, int flag
, bool set
)
675 Element which
= ElementForArrow(arrow
);
676 int state
= GetState(which
);
682 SetState(which
, state
);
685 int wxScrollBar::GetState(Element which
) const
687 // if the entire scrollbar is disabled, all of its elements are too
688 int flags
= m_elementsState
[which
];
690 flags
|= wxCONTROL_DISABLED
;
695 void wxScrollBar::SetState(Element which
, int flags
)
697 if ( (int)(m_elementsState
[which
] & ~wxCONTROL_DIRTY
) != flags
)
699 m_elementsState
[which
] = flags
| wxCONTROL_DIRTY
;
705 // ----------------------------------------------------------------------------
707 // ----------------------------------------------------------------------------
709 bool wxScrollBar::OnArrow(wxScrollArrows::Arrow arrow
)
711 int oldThumbPos
= GetThumbPosition();
712 PerformAction(arrow
== wxScrollArrows::Arrow_First
713 ? wxACTION_SCROLL_LINE_UP
714 : wxACTION_SCROLL_LINE_DOWN
);
716 // did we scroll till the end?
717 return GetThumbPosition() != oldThumbPos
;
720 bool wxScrollBar::PerformAction(const wxControlAction
& action
,
722 const wxString
& strArg
)
724 int thumbOld
= m_thumbPos
;
726 bool notify
= false; // send an event about the change?
728 wxEventType scrollType
;
730 // test for thumb move first as these events happen in quick succession
731 if ( action
== wxACTION_SCROLL_THUMB_MOVE
)
735 // VS: we have to force redraw here, otherwise the thumb will lack
736 // behind mouse cursor
739 scrollType
= wxEVT_SCROLLWIN_THUMBTRACK
;
741 else if ( action
== wxACTION_SCROLL_LINE_UP
)
743 scrollType
= wxEVT_SCROLLWIN_LINEUP
;
746 else if ( action
== wxACTION_SCROLL_LINE_DOWN
)
748 scrollType
= wxEVT_SCROLLWIN_LINEDOWN
;
751 else if ( action
== wxACTION_SCROLL_PAGE_UP
)
753 scrollType
= wxEVT_SCROLLWIN_PAGEUP
;
756 else if ( action
== wxACTION_SCROLL_PAGE_DOWN
)
758 scrollType
= wxEVT_SCROLLWIN_PAGEDOWN
;
761 else if ( action
== wxACTION_SCROLL_START
)
763 scrollType
= wxEVT_SCROLLWIN_THUMBRELEASE
; // anything better?
766 else if ( action
== wxACTION_SCROLL_END
)
768 scrollType
= wxEVT_SCROLLWIN_THUMBRELEASE
; // anything better?
771 else if ( action
== wxACTION_SCROLL_THUMB_DRAG
)
773 // we won't use it but this line suppresses the compiler
774 // warning about "variable may be used without having been
776 scrollType
= wxEVT_NULL
;
778 else if ( action
== wxACTION_SCROLL_THUMB_RELEASE
)
780 // always notify about this
782 scrollType
= wxEVT_SCROLLWIN_THUMBRELEASE
;
785 return wxControl::PerformAction(action
, numArg
, strArg
);
787 // has scrollbar position changed?
788 bool changed
= m_thumbPos
!= thumbOld
;
789 if ( notify
|| changed
)
791 if ( IsStandalone() )
793 // we should generate EVT_SCROLL events for the standalone
794 // scrollbars and not the EVT_SCROLLWIN ones
796 // NB: we assume that scrollbar events are sequentially numbered
797 // but this should be ok as other code relies on this as well
798 scrollType
+= wxEVT_SCROLL_TOP
- wxEVT_SCROLLWIN_TOP
;
799 wxScrollEvent
event(scrollType
, this->GetId(), m_thumbPos
,
800 IsVertical() ? wxVERTICAL
: wxHORIZONTAL
);
801 event
.SetEventObject(this);
802 GetEventHandler()->ProcessEvent(event
);
804 else // part of the window
806 wxScrollWinEvent
event(scrollType
, m_thumbPos
,
807 IsVertical() ? wxVERTICAL
: wxHORIZONTAL
);
808 event
.SetEventObject(this);
809 GetParent()->GetEventHandler()->ProcessEvent(event
);
816 void wxScrollBar::ScrollToStart()
821 void wxScrollBar::ScrollToEnd()
823 DoSetThumb(m_range
- m_thumbSize
);
826 bool wxScrollBar::ScrollLines(int nLines
)
828 DoSetThumb(m_thumbPos
+ nLines
);
832 bool wxScrollBar::ScrollPages(int nPages
)
834 DoSetThumb(m_thumbPos
+ nPages
*m_pageSize
);
839 wxInputHandler
*wxScrollBar::GetStdInputHandler(wxInputHandler
*handlerDef
)
841 static wxStdScrollBarInputHandler
842 s_handler(wxTheme::Get()->GetRenderer(), handlerDef
);
847 // ============================================================================
848 // scroll bar input handler
849 // ============================================================================
851 // ----------------------------------------------------------------------------
853 // ----------------------------------------------------------------------------
855 wxScrollBarTimer::wxScrollBarTimer(wxStdScrollBarInputHandler
*handler
,
856 const wxControlAction
& action
,
857 wxScrollBar
*control
)
864 bool wxScrollBarTimer::DoNotify()
866 return m_handler
->OnScrollTimer(m_control
, m_action
);
869 // ----------------------------------------------------------------------------
870 // wxStdScrollBarInputHandler
871 // ----------------------------------------------------------------------------
873 wxStdScrollBarInputHandler::wxStdScrollBarInputHandler(wxRenderer
*renderer
,
874 wxInputHandler
*handler
)
875 : wxStdInputHandler(handler
)
877 m_renderer
= renderer
;
879 m_htLast
= wxHT_NOWHERE
;
880 m_timerScroll
= NULL
;
883 wxStdScrollBarInputHandler::~wxStdScrollBarInputHandler()
885 // normally, it's NULL by now but just in case the user somehow managed to
886 // keep the mouse captured until now...
887 delete m_timerScroll
;
890 void wxStdScrollBarInputHandler::SetElementState(wxScrollBar
*control
,
894 if ( m_htLast
> wxHT_SCROLLBAR_FIRST
&& m_htLast
< wxHT_SCROLLBAR_LAST
)
897 elem
= (wxScrollBar::Element
)(m_htLast
- wxHT_SCROLLBAR_FIRST
- 1);
899 int flags
= control
->GetState(elem
);
904 control
->SetState(elem
, flags
);
908 bool wxStdScrollBarInputHandler::OnScrollTimer(wxScrollBar
*scrollbar
,
909 const wxControlAction
& action
)
911 int oldThumbPos
= scrollbar
->GetThumbPosition();
912 scrollbar
->PerformAction(action
);
913 if ( scrollbar
->GetThumbPosition() != oldThumbPos
)
916 // we scrolled till the end
917 m_timerScroll
->Stop();
922 void wxStdScrollBarInputHandler::StopScrolling(wxScrollBar
*control
)
924 // return everything to the normal state
927 m_winCapture
->ReleaseMouse();
933 wxDELETE(m_timerScroll
);
935 // unpress the arrow and highlight the current element
936 Press(control
, false);
940 wxStdScrollBarInputHandler::GetMouseCoord(const wxScrollBar
*scrollbar
,
941 const wxMouseEvent
& event
) const
943 wxPoint pt
= event
.GetPosition();
944 return scrollbar
->GetWindowStyle() & wxVERTICAL
? pt
.y
: pt
.x
;
947 void wxStdScrollBarInputHandler::HandleThumbMove(wxScrollBar
*scrollbar
,
948 const wxMouseEvent
& event
)
950 int thumbPos
= GetMouseCoord(scrollbar
, event
) - m_ofsMouse
;
951 thumbPos
= scrollbar
->PixelToScrollbar(thumbPos
);
952 scrollbar
->PerformAction(wxACTION_SCROLL_THUMB_MOVE
, thumbPos
);
955 bool wxStdScrollBarInputHandler::HandleKey(wxInputConsumer
*consumer
,
956 const wxKeyEvent
& event
,
959 // we only react to the key presses here
962 wxControlAction action
;
963 switch ( event
.GetKeyCode() )
966 case WXK_RIGHT
: action
= wxACTION_SCROLL_LINE_DOWN
; break;
968 case WXK_LEFT
: action
= wxACTION_SCROLL_LINE_UP
; break;
969 case WXK_HOME
: action
= wxACTION_SCROLL_START
; break;
970 case WXK_END
: action
= wxACTION_SCROLL_END
; break;
971 case WXK_PAGEUP
: action
= wxACTION_SCROLL_PAGE_UP
; break;
972 case WXK_PAGEDOWN
: action
= wxACTION_SCROLL_PAGE_DOWN
; break;
975 if ( !action
.IsEmpty() )
977 consumer
->PerformAction(action
);
983 return wxStdInputHandler::HandleKey(consumer
, event
, pressed
);
986 bool wxStdScrollBarInputHandler::HandleMouse(wxInputConsumer
*consumer
,
987 const wxMouseEvent
& event
)
989 // is this a click event from an acceptable button?
990 int btn
= event
.GetButton();
991 if ( btn
== wxMOUSE_BTN_LEFT
)
993 // determine which part of the window mouse is in
994 wxScrollBar
*scrollbar
= wxStaticCast(consumer
->GetInputWindow(), wxScrollBar
);
995 wxHitTest ht
= scrollbar
->HitTestBar(event
.GetPosition());
997 // when the mouse is pressed on any scrollbar element, we capture it
998 // and hold capture until the same mouse button is released
999 if ( event
.ButtonDown() || event
.ButtonDClick() )
1001 if ( !m_winCapture
)
1004 m_winCapture
= consumer
->GetInputWindow();
1005 m_winCapture
->CaptureMouse();
1007 // generate the command
1008 bool hasAction
= true;
1009 wxControlAction action
;
1012 case wxHT_SCROLLBAR_ARROW_LINE_1
:
1013 action
= wxACTION_SCROLL_LINE_UP
;
1016 case wxHT_SCROLLBAR_ARROW_LINE_2
:
1017 action
= wxACTION_SCROLL_LINE_DOWN
;
1020 case wxHT_SCROLLBAR_BAR_1
:
1021 action
= wxACTION_SCROLL_PAGE_UP
;
1022 m_ptStartScrolling
= event
.GetPosition();
1025 case wxHT_SCROLLBAR_BAR_2
:
1026 action
= wxACTION_SCROLL_PAGE_DOWN
;
1027 m_ptStartScrolling
= event
.GetPosition();
1030 case wxHT_SCROLLBAR_THUMB
:
1031 consumer
->PerformAction(wxACTION_SCROLL_THUMB_DRAG
);
1032 m_ofsMouse
= GetMouseCoord(scrollbar
, event
) -
1033 scrollbar
->ScrollbarToPixel();
1035 // fall through: there is no immediate action
1041 // remove highlighting
1042 Highlight(scrollbar
, false);
1045 // and press the arrow or highlight thumb now instead
1046 if ( m_htLast
== wxHT_SCROLLBAR_THUMB
)
1047 Highlight(scrollbar
, true);
1049 Press(scrollbar
, true);
1054 m_timerScroll
= new wxScrollBarTimer(this, action
,
1056 m_timerScroll
->StartAutoScroll();
1058 //else: no (immediate) action
1061 //else: mouse already captured, nothing to do
1063 // release mouse if the *same* button went up
1064 else if ( btn
== m_btnCapture
)
1068 StopScrolling(scrollbar
);
1070 // if we were dragging the thumb, send the last event
1071 if ( m_htLast
== wxHT_SCROLLBAR_THUMB
)
1073 scrollbar
->PerformAction(wxACTION_SCROLL_THUMB_RELEASE
);
1077 Highlight(scrollbar
, true);
1081 // this is not supposed to happen as the button can't go up
1082 // without going down previously and then we'd have
1083 // m_winCapture by now
1084 wxFAIL_MSG( wxT("logic error in mouse capturing code") );
1089 return wxStdInputHandler::HandleMouse(consumer
, event
);
1092 bool wxStdScrollBarInputHandler::HandleMouseMove(wxInputConsumer
*consumer
,
1093 const wxMouseEvent
& event
)
1095 wxScrollBar
*scrollbar
= wxStaticCast(consumer
->GetInputWindow(), wxScrollBar
);
1099 if ( (m_htLast
== wxHT_SCROLLBAR_THUMB
) && event
.Dragging() )
1101 // make the thumb follow the mouse by keeping the same offset
1102 // between the mouse position and the top/left of the thumb
1103 HandleThumbMove(scrollbar
, event
);
1108 // no other changes are possible while the mouse is captured
1112 bool isArrow
= scrollbar
->GetArrows().HandleMouseMove(event
);
1114 if ( event
.Dragging() )
1116 wxHitTest ht
= scrollbar
->HitTestBar(event
.GetPosition());
1117 if ( ht
== m_htLast
)
1124 wxLogDebug("Scrollbar::OnMouseMove: ht = %d", ht
);
1125 #endif // DEBUG_MOUSE
1127 Highlight(scrollbar
, false);
1131 Highlight(scrollbar
, true);
1132 //else: already done by wxScrollArrows::HandleMouseMove
1134 else if ( event
.Leaving() )
1137 Highlight(scrollbar
, false);
1139 m_htLast
= wxHT_NOWHERE
;
1141 else // event.Entering()
1143 // we don't process this event
1151 #endif // wxUSE_SCROLLBAR
1155 // ----------------------------------------------------------------------------
1157 // ----------------------------------------------------------------------------
1159 wxScrollTimer::wxScrollTimer()
1164 void wxScrollTimer::StartAutoScroll()
1166 // start scrolling immediately
1169 // ... and end it too
1173 // there is an initial delay before the scrollbar starts scrolling -
1174 // implement it by ignoring the first timer expiration and only start
1175 // scrolling from the second one
1177 Start(200); // FIXME: hardcoded delay
1180 void wxScrollTimer::Notify()
1184 // scroll normally now - reduce the delay
1186 Start(50); // FIXME: hardcoded delay
1192 // if DoNotify() returns false, we're already deleted by the timer
1193 // event handler, so don't do anything else here
1198 #endif // wxUSE_TIMER