]> git.saurik.com Git - wxWidgets.git/blame - src/univ/scrthumb.cpp
fixed to work with themes that redefine icons (e.g. Fedora's Bluecurve)
[wxWidgets.git] / src / univ / scrthumb.cpp
CommitLineData
1e6feb95
VZ
1/////////////////////////////////////////////////////////////////////////////
2// Name: univ/scrthumb.cpp
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
14f355c2 20#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
a3870b2f 21 #pragma implementation "univscrthumb.h"
1e6feb95
VZ
22#endif
23
24#include "wx/wxprec.h"
25
26#ifdef __BORLANDC__
27 #pragma hdrstop
28#endif
29
30#ifndef WX_PRECOMP
31 #include "wx/window.h"
b5435dcc 32 #include "wx/renderer.h"
1e6feb95
VZ
33#endif // WX_PRECOMP
34
35#include "wx/univ/scrtimer.h"
36#include "wx/univ/scrthumb.h"
37
38// ----------------------------------------------------------------------------
39// wxScrollThumbCaptureData: the struct used while dragging the scroll thumb
40// ----------------------------------------------------------------------------
41
42struct WXDLLEXPORT wxScrollThumbCaptureData
43{
44 // start mouse capture after the user clicked the mouse button btn on this
45 // part of the control
46 wxScrollThumbCaptureData(wxScrollThumb::Shaft part,
47 int btn,
48 wxControlWithThumb *control)
49 {
50 m_shaftPart = part;
51 m_btnCapture = btn;
52 m_timerScroll = NULL;
53
54 m_window = control->GetWindow();
55 m_window->CaptureMouse();
56 }
57
58 // release mouse
59 ~wxScrollThumbCaptureData()
60 {
61 if ( m_window )
62 {
63 m_window->ReleaseMouse();
64 }
65
66 delete m_timerScroll;
67 }
68
69 // the thumb part being held pressed
70 wxScrollThumb::Shaft m_shaftPart;
71
72 // the mouse button which started the capture (-1 if none)
73 int m_btnCapture;
74
75 // the window which has captured the mouse
76 wxWindow *m_window;
77
78 // the offset between the mouse position and the start of the thumb which
79 // is kept constant while dragging the thumb
80 wxCoord m_ofsMouse;
81
82 // the timer for generating the scroll events when scrolling by page
83 wxScrollTimer *m_timerScroll;
84};
85
86// ----------------------------------------------------------------------------
87// wxScrollTimer: the timer used when the arrow is kept pressed
88// ----------------------------------------------------------------------------
89
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:
104 wxFAIL_MSG(_T("unexpected shaft part in wxScrollThumbTimer"));
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
127// ============================================================================
128// implementation
129// ============================================================================
130
131// ----------------------------------------------------------------------------
132// wxScrollThumb constructor and dtor
133// ----------------------------------------------------------------------------
134
135wxScrollThumb::wxScrollThumb(wxControlWithThumb *control)
136{
137 m_shaftPart = Shaft_None;
138 m_control = control;
139 m_captureData = NULL;
140}
141
142wxScrollThumb::~wxScrollThumb()
143{
144 // it should have been destroyed
145 wxASSERT_MSG( !m_captureData, _T("memory leak in wxScrollThumb") );
146}
147
148// ----------------------------------------------------------------------------
149// wxScrollThumb mouse handling
150// ----------------------------------------------------------------------------
151
152bool wxScrollThumb::HandleMouse(const wxMouseEvent& event) const
153{
154 // is this a click event?
155 int btn = event.GetButton();
156 if ( btn == -1 )
157 {
158 // no...
a290fa5a 159 return false;
1e6feb95
VZ
160 }
161
162 // when the mouse is pressed on any scrollbar element, we capture it
163 // and hold capture until the same mouse button is released
164 if ( event.ButtonDown() || event.ButtonDClick() )
165 {
166 if ( HasCapture() )
167 {
168 // mouse already captured, nothing to do
a290fa5a 169 return false;
1e6feb95
VZ
170 }
171
172 // determine which part of the window the user clicked in
173 Shaft shaftPart = m_control->HitTest(event.GetPosition());
174
175 if ( shaftPart == Shaft_None )
176 {
177 // mouse pressed over something else
a290fa5a 178 return false;
1e6feb95
VZ
179 }
180
181 // capture the mouse
182 wxConstCast(this, wxScrollThumb)->m_captureData =
183 new wxScrollThumbCaptureData(shaftPart, btn, m_control);
184
185 // modify the visual appearance before sending the event which will
186 // cause a redraw
187 m_control->SetShaftPartState(shaftPart, wxCONTROL_PRESSED);
188
189 if ( shaftPart == Shaft_Thumb )
190 {
191 // save the mouse offset from the thumb position - we will keep it
192 // constant while dragging the thumb
193 m_captureData->m_ofsMouse =
194 GetMouseCoord(event) - m_control->ThumbPosToPixel();
195
196 // generate an additional event if we start dragging the thumb
197 m_control->OnThumbDragStart(GetThumbPos(event));
198 }
199 else // not the thumb
200 {
201 // start timer for auto scrolling when the user presses the mouse
202 // in the shaft above or below the thumb
203 m_captureData->m_timerScroll =
204 new wxScrollThumbTimer(m_control, shaftPart);
205 }
206 }
207 // release mouse if the *same* button went up
208 else if ( HasCapture() && (btn == m_captureData->m_btnCapture) )
209 {
210 Shaft shaftPart = m_captureData->m_shaftPart;
211
212 // if we were dragging the thumb, send the one last event
213 if ( shaftPart == Shaft_Thumb )
214 {
215 m_control->OnThumbDragEnd(GetThumbPos(event));
216 }
217
218 // release the mouse and free capture data
219 delete m_captureData;
220 wxConstCast(this, wxScrollThumb)->m_captureData = NULL;
221
a290fa5a 222 m_control->SetShaftPartState(shaftPart, wxCONTROL_PRESSED, false);
1e6feb95
VZ
223 }
224 else // another mouse button released
225 {
226 // we don't process this
a290fa5a 227 return false;
1e6feb95
VZ
228 }
229
a290fa5a 230 return true;
1e6feb95
VZ
231}
232
233bool wxScrollThumb::HandleMouseMove(const wxMouseEvent& event) const
234{
235 if ( HasCapture() )
236 {
237 if ( (m_captureData->m_shaftPart == Shaft_Thumb) && event.Moving() )
238 {
239 // make the thumb follow the mouse by keeping the same offset
240 // between the mouse position and the top/left of the thumb
241 m_control->OnThumbDrag(GetThumbPos(event));
242 }
243
244 // we process all mouse events while the mouse is captured by us
a290fa5a 245 return true;
1e6feb95
VZ
246 }
247 else // no capture
248 {
249 Shaft shaftPart;
250 if ( event.Leaving() )
251 {
252 // no part of the shaft has mouse if it left the window completely
253 shaftPart = Shaft_None;
254 }
255 else // Moving() or Entering(), treat them the same here
256 {
257 shaftPart = m_control->HitTest(event.GetPosition());
258 }
259
260 if ( shaftPart != m_shaftPart )
261 {
262 // update the highlighted state
a290fa5a 263 m_control->SetShaftPartState(m_shaftPart, wxCONTROL_CURRENT, false);
1e6feb95 264 wxConstCast(this, wxScrollThumb)->m_shaftPart = shaftPart;
a290fa5a 265 m_control->SetShaftPartState(m_shaftPart, wxCONTROL_CURRENT, true);
1e6feb95
VZ
266 }
267
268 // if the event happened on the shaft, it was for us and we processed
269 // it
270 return shaftPart != Shaft_None;
271 }
272}
273
274wxCoord wxScrollThumb::GetMouseCoord(const wxMouseEvent& event) const
275{
276 wxPoint pt = event.GetPosition();
277 return m_control->IsVertical() ? pt.y : pt.x;
278}
279
280int wxScrollThumb::GetThumbPos(const wxMouseEvent& event) const
281{
282 wxCHECK_MSG( m_captureData && m_captureData->m_shaftPart == Shaft_Thumb, 0,
283 _T("can't be called when thumb is not dragged") );
284
285 int x = GetMouseCoord(event) - m_captureData->m_ofsMouse;
286 return m_control->PixelToThumbPos(x);
287}