]> git.saurik.com Git - wxWidgets.git/blame - src/univ/scrthumb.cpp
Extract wxFDIOEventLoopSourceHandler in its own header.
[wxWidgets.git] / src / univ / scrthumb.cpp
CommitLineData
1e6feb95 1/////////////////////////////////////////////////////////////////////////////
9a6384ca 2// Name: src/univ/scrthumb.cpp
1e6feb95
VZ
3// Purpose: wxScrollThumb and related classes
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 13.02.01
7// RCS-ID: $Id$
442b35b5 8// Copyright: (c) 2001 SciTech Software, Inc. (www.scitechsoft.com)
65571936 9// Licence: wxWindows licence
1e6feb95
VZ
10/////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
1e6feb95
VZ
20#include "wx/wxprec.h"
21
22#ifdef __BORLANDC__
23 #pragma hdrstop
24#endif
25
26#ifndef WX_PRECOMP
27 #include "wx/window.h"
28#endif // WX_PRECOMP
29
9a6384ca 30#include "wx/renderer.h"
1e6feb95
VZ
31#include "wx/univ/scrtimer.h"
32#include "wx/univ/scrthumb.h"
33
34// ----------------------------------------------------------------------------
35// wxScrollThumbCaptureData: the struct used while dragging the scroll thumb
36// ----------------------------------------------------------------------------
37
38struct WXDLLEXPORT wxScrollThumbCaptureData
39{
40 // start mouse capture after the user clicked the mouse button btn on this
41 // part of the control
42 wxScrollThumbCaptureData(wxScrollThumb::Shaft part,
43 int btn,
44 wxControlWithThumb *control)
45 {
46 m_shaftPart = part;
47 m_btnCapture = btn;
48 m_timerScroll = NULL;
49
50 m_window = control->GetWindow();
51 m_window->CaptureMouse();
52 }
53
54 // release mouse
55 ~wxScrollThumbCaptureData()
56 {
57 if ( m_window )
58 {
59 m_window->ReleaseMouse();
60 }
61
9a6384ca 62#if wxUSE_TIMER
1e6feb95 63 delete m_timerScroll;
9a6384ca 64#endif // wxUSE_TIMER
1e6feb95
VZ
65 }
66
67 // the thumb part being held pressed
68 wxScrollThumb::Shaft m_shaftPart;
69
70 // the mouse button which started the capture (-1 if none)
71 int m_btnCapture;
72
73 // the window which has captured the mouse
74 wxWindow *m_window;
75
76 // the offset between the mouse position and the start of the thumb which
77 // is kept constant while dragging the thumb
78 wxCoord m_ofsMouse;
79
80 // the timer for generating the scroll events when scrolling by page
81 wxScrollTimer *m_timerScroll;
82};
83
84// ----------------------------------------------------------------------------
85// wxScrollTimer: the timer used when the arrow is kept pressed
86// ----------------------------------------------------------------------------
87
9a6384ca
WS
88#if wxUSE_TIMER
89
1e6feb95
VZ
90class wxScrollThumbTimer : public wxScrollTimer
91{
92public:
93 wxScrollThumbTimer(wxControlWithThumb *control,
94 wxScrollThumb::Shaft shaftPart)
95 {
96 m_control = control;
97 switch ( shaftPart )
98 {
99 case wxScrollThumb::Shaft_Above:
100 m_inc = -1;
101 break;
102
103 default:
9a83f860 104 wxFAIL_MSG(wxT("unexpected shaft part in wxScrollThumbTimer"));
1e6feb95
VZ
105 // fall through
106
107 case wxScrollThumb::Shaft_Below:
108 m_inc = 1;
109 break;
110 }
111
112 m_control->OnPageScrollStart();
113
114 StartAutoScroll();
115 }
116
117protected:
118 virtual bool DoNotify()
119 {
120 return m_control->OnPageScroll(m_inc);
121 }
122
123 wxControlWithThumb *m_control;
124 int m_inc;
125};
126
9a6384ca
WS
127#endif // wxUSE_TIMER
128
1e6feb95
VZ
129// ============================================================================
130// implementation
131// ============================================================================
132
133// ----------------------------------------------------------------------------
134// wxScrollThumb constructor and dtor
135// ----------------------------------------------------------------------------
136
137wxScrollThumb::wxScrollThumb(wxControlWithThumb *control)
138{
139 m_shaftPart = Shaft_None;
140 m_control = control;
141 m_captureData = NULL;
142}
143
144wxScrollThumb::~wxScrollThumb()
145{
146 // it should have been destroyed
9a83f860 147 wxASSERT_MSG( !m_captureData, wxT("memory leak in wxScrollThumb") );
1e6feb95
VZ
148}
149
150// ----------------------------------------------------------------------------
151// wxScrollThumb mouse handling
152// ----------------------------------------------------------------------------
153
154bool wxScrollThumb::HandleMouse(const wxMouseEvent& event) const
155{
156 // is this a click event?
157 int btn = event.GetButton();
158 if ( btn == -1 )
159 {
160 // no...
a290fa5a 161 return false;
1e6feb95
VZ
162 }
163
164 // when the mouse is pressed on any scrollbar element, we capture it
165 // and hold capture until the same mouse button is released
166 if ( event.ButtonDown() || event.ButtonDClick() )
167 {
168 if ( HasCapture() )
169 {
170 // mouse already captured, nothing to do
a290fa5a 171 return false;
1e6feb95
VZ
172 }
173
174 // determine which part of the window the user clicked in
175 Shaft shaftPart = m_control->HitTest(event.GetPosition());
176
177 if ( shaftPart == Shaft_None )
178 {
179 // mouse pressed over something else
a290fa5a 180 return false;
1e6feb95
VZ
181 }
182
183 // capture the mouse
184 wxConstCast(this, wxScrollThumb)->m_captureData =
185 new wxScrollThumbCaptureData(shaftPart, btn, m_control);
186
187 // modify the visual appearance before sending the event which will
188 // cause a redraw
189 m_control->SetShaftPartState(shaftPart, wxCONTROL_PRESSED);
190
191 if ( shaftPart == Shaft_Thumb )
192 {
193 // save the mouse offset from the thumb position - we will keep it
194 // constant while dragging the thumb
195 m_captureData->m_ofsMouse =
196 GetMouseCoord(event) - m_control->ThumbPosToPixel();
197
198 // generate an additional event if we start dragging the thumb
199 m_control->OnThumbDragStart(GetThumbPos(event));
200 }
9a6384ca 201#if wxUSE_TIMER
1e6feb95
VZ
202 else // not the thumb
203 {
204 // start timer for auto scrolling when the user presses the mouse
205 // in the shaft above or below the thumb
206 m_captureData->m_timerScroll =
207 new wxScrollThumbTimer(m_control, shaftPart);
208 }
9a6384ca 209#endif // wxUSE_TIMER
1e6feb95
VZ
210 }
211 // release mouse if the *same* button went up
212 else if ( HasCapture() && (btn == m_captureData->m_btnCapture) )
213 {
214 Shaft shaftPart = m_captureData->m_shaftPart;
215
216 // if we were dragging the thumb, send the one last event
217 if ( shaftPart == Shaft_Thumb )
218 {
219 m_control->OnThumbDragEnd(GetThumbPos(event));
220 }
221
222 // release the mouse and free capture data
223 delete m_captureData;
224 wxConstCast(this, wxScrollThumb)->m_captureData = NULL;
225
a290fa5a 226 m_control->SetShaftPartState(shaftPart, wxCONTROL_PRESSED, false);
1e6feb95
VZ
227 }
228 else // another mouse button released
229 {
230 // we don't process this
a290fa5a 231 return false;
1e6feb95
VZ
232 }
233
a290fa5a 234 return true;
1e6feb95
VZ
235}
236
237bool wxScrollThumb::HandleMouseMove(const wxMouseEvent& event) const
238{
239 if ( HasCapture() )
240 {
241 if ( (m_captureData->m_shaftPart == Shaft_Thumb) && event.Moving() )
242 {
243 // make the thumb follow the mouse by keeping the same offset
244 // between the mouse position and the top/left of the thumb
245 m_control->OnThumbDrag(GetThumbPos(event));
246 }
247
248 // we process all mouse events while the mouse is captured by us
a290fa5a 249 return true;
1e6feb95
VZ
250 }
251 else // no capture
252 {
253 Shaft shaftPart;
254 if ( event.Leaving() )
255 {
256 // no part of the shaft has mouse if it left the window completely
257 shaftPart = Shaft_None;
258 }
259 else // Moving() or Entering(), treat them the same here
260 {
261 shaftPart = m_control->HitTest(event.GetPosition());
262 }
263
264 if ( shaftPart != m_shaftPart )
265 {
266 // update the highlighted state
a290fa5a 267 m_control->SetShaftPartState(m_shaftPart, wxCONTROL_CURRENT, false);
1e6feb95 268 wxConstCast(this, wxScrollThumb)->m_shaftPart = shaftPart;
a290fa5a 269 m_control->SetShaftPartState(m_shaftPart, wxCONTROL_CURRENT, true);
1e6feb95
VZ
270 }
271
272 // if the event happened on the shaft, it was for us and we processed
273 // it
274 return shaftPart != Shaft_None;
275 }
276}
277
278wxCoord wxScrollThumb::GetMouseCoord(const wxMouseEvent& event) const
279{
280 wxPoint pt = event.GetPosition();
281 return m_control->IsVertical() ? pt.y : pt.x;
282}
283
284int wxScrollThumb::GetThumbPos(const wxMouseEvent& event) const
285{
286 wxCHECK_MSG( m_captureData && m_captureData->m_shaftPart == Shaft_Thumb, 0,
9a83f860 287 wxT("can't be called when thumb is not dragged") );
1e6feb95
VZ
288
289 int x = GetMouseCoord(event) - m_captureData->m_ofsMouse;
290 return m_control->PixelToThumbPos(x);
291}