]> git.saurik.com Git - wxWidgets.git/blame - src/univ/scrarrow.cpp
Fix horizontal mouse wheel scrolling in wxGTK.
[wxWidgets.git] / src / univ / scrarrow.cpp
CommitLineData
1e6feb95
VZ
1///////////////////////////////////////////////////////////////////////////////
2// Name: src/univ/scrarrow.cpp
3// Purpose: wxScrollArrows class implementation
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 22.01.01
442b35b5 7// Copyright: (c) 2001 SciTech Software, Inc. (www.scitechsoft.com)
65571936 8// Licence: wxWindows licence
1e6feb95
VZ
9///////////////////////////////////////////////////////////////////////////////
10
11// ============================================================================
12// declarations
13// ============================================================================
14
15// ----------------------------------------------------------------------------
16// headers
17// ----------------------------------------------------------------------------
18
1e6feb95
VZ
19#include "wx/wxprec.h"
20
21#ifdef __BORLANDC__
22 #pragma hdrstop
23#endif
24
25#ifndef WX_PRECOMP
061fe33f 26 #include "wx/window.h"
1e6feb95
VZ
27#endif
28
29#include "wx/univ/scrtimer.h"
30#include "wx/univ/scrarrow.h"
31
32#include "wx/univ/renderer.h"
33#include "wx/univ/inphand.h"
34#include "wx/univ/theme.h"
35
36// ----------------------------------------------------------------------------
37// wxScrollArrowCaptureData: contains the data used while the arrow is being
38// pressed by the user
39// ----------------------------------------------------------------------------
40
41struct wxScrollArrowCaptureData
42{
43 wxScrollArrowCaptureData()
44 {
45 m_arrowPressed = wxScrollArrows::Arrow_None;
46 m_window = NULL;
47 m_btnCapture = -1;
9a6384ca 48#if wxUSE_TIMER
1e6feb95 49 m_timerScroll = NULL;
9a6384ca 50#endif // wxUSE_TIMER
1e6feb95
VZ
51 }
52
53 ~wxScrollArrowCaptureData()
54 {
55 if ( m_window )
56 m_window->ReleaseMouse();
57
9a6384ca 58#if wxUSE_TIMER
1e6feb95 59 delete m_timerScroll;
9a6384ca 60#endif // wxUSE_TIMER
1e6feb95
VZ
61 }
62
63 // the arrow being held pressed (may be Arrow_None)
64 wxScrollArrows::Arrow m_arrowPressed;
65
66 // the mouse button which started the capture (-1 if none)
67 int m_btnCapture;
68
69 // the window which has captured the mouse
70 wxWindow *m_window;
71
9a6384ca 72#if wxUSE_TIMER
1e6feb95
VZ
73 // the timer for generating the scroll events
74 wxScrollTimer *m_timerScroll;
9a6384ca 75#endif
1e6feb95
VZ
76};
77
78// ----------------------------------------------------------------------------
79// wxScrollArrowTimer: a wxScrollTimer which calls OnArrow()
80// ----------------------------------------------------------------------------
81
9a6384ca
WS
82#if wxUSE_TIMER
83
1e6feb95
VZ
84class wxScrollArrowTimer : public wxScrollTimer
85{
86public:
87 wxScrollArrowTimer(wxControlWithArrows *control,
88 wxScrollArrows::Arrow arrow)
89 {
90 m_control = control;
91 m_arrow = arrow;
92
93 StartAutoScroll();
94 }
95
96protected:
97 virtual bool DoNotify()
98 {
99 return m_control->OnArrow(m_arrow);
100 }
101
102 wxControlWithArrows *m_control;
103 wxScrollArrows::Arrow m_arrow;
104};
105
9a6384ca
WS
106#endif // wxUSE_TIMER
107
1e6feb95
VZ
108// ============================================================================
109// implementation of wxScrollArrows
110// ============================================================================
111
112// ----------------------------------------------------------------------------
113// con/destruction
114// ----------------------------------------------------------------------------
115
116wxScrollArrows::wxScrollArrows(wxControlWithArrows *control)
117{
118 m_control = control;
119 m_captureData = NULL;
120}
121
122wxScrollArrows::~wxScrollArrows()
123{
124 // it should have been destroyed
9a83f860 125 wxASSERT_MSG( !m_captureData, wxT("memory leak in wxScrollArrows") );
1e6feb95
VZ
126}
127
128// ----------------------------------------------------------------------------
129// drawing
130// ----------------------------------------------------------------------------
131
132void wxScrollArrows::DrawArrow(Arrow arrow,
133 wxDC& dc,
134 const wxRect& rect,
135 bool scrollbarLike) const
136{
137 static const wxDirection arrowDirs[2][Arrow_Max] =
138 {
139 { wxLEFT, wxRIGHT },
140 { wxUP, wxDOWN }
141 };
142
000307d7
VS
143 if ( scrollbarLike )
144 m_control->GetRenderer()->DrawScrollbarArrow(
145 dc,
146 arrowDirs[m_control->IsVertical()][arrow],
147 rect,
148 m_control->GetArrowState(arrow));
149 else
150 m_control->GetRenderer()->DrawArrow(
151 dc,
152 arrowDirs[m_control->IsVertical()][arrow],
153 rect,
154 m_control->GetArrowState(arrow));
1e6feb95
VZ
155}
156
157// ----------------------------------------------------------------------------
158// input handling
159// ----------------------------------------------------------------------------
160
161void wxScrollArrows::UpdateCurrentFlag(Arrow arrow, Arrow arrowCur) const
162{
163 m_control->SetArrowFlag(arrow, wxCONTROL_CURRENT, arrow == arrowCur);
164}
165
166bool wxScrollArrows::HandleMouseMove(const wxMouseEvent& event) const
167{
168 Arrow arrow;
169 if ( event.Leaving() )
170 {
171 // no arrow has mouse if it left the window completely
172 arrow = Arrow_None;
173 }
174 else // Moving() or Entering(), treat them the same here
175 {
6236b8b4 176 arrow = m_control->HitTestArrow(event.GetPosition());
1e6feb95
VZ
177 }
178
9a6384ca 179#if wxUSE_TIMER
f9bd9677 180 if ( m_captureData && m_captureData->m_timerScroll)
1e6feb95
VZ
181 {
182 // the mouse is captured, we may want to pause scrolling if it goes
183 // outside the arrow or to resume it if we had paused it before
184 wxTimer *timer = m_captureData->m_timerScroll;
185 if ( !timer->IsRunning() )
186 {
187 // timer is paused
188 if ( arrow == m_captureData->m_arrowPressed )
189 {
190 // resume now
a290fa5a 191 m_control->SetArrowFlag(arrow, wxCONTROL_PRESSED, true);
1e6feb95
VZ
192 timer->Start();
193
a290fa5a 194 return true;
1e6feb95
VZ
195 }
196 }
8a39593e 197 else // if ( 1 ) FIXME: m_control->ShouldPauseScrolling() )
1e6feb95
VZ
198 {
199 // we may want to stop it
200 if ( arrow != m_captureData->m_arrowPressed )
201 {
202 // stop as the mouse left the arrow
203 m_control->SetArrowFlag(m_captureData->m_arrowPressed,
a290fa5a 204 wxCONTROL_PRESSED, false);
1e6feb95
VZ
205 timer->Stop();
206
a290fa5a 207 return true;
1e6feb95
VZ
208 }
209 }
210
a290fa5a 211 return false;
1e6feb95 212 }
9a6384ca 213#endif // wxUSE_TIMER
1e6feb95
VZ
214
215 // reset the wxCONTROL_CURRENT flag for the arrows which don't have the
216 // mouse and set it for the one which has
217 UpdateCurrentFlag(Arrow_First, arrow);
218 UpdateCurrentFlag(Arrow_Second, arrow);
219
a290fa5a 220 // return true if it was really an event for an arrow
1e6feb95
VZ
221 return !event.Leaving() && arrow != Arrow_None;
222}
223
224bool wxScrollArrows::HandleMouse(const wxMouseEvent& event) const
225{
226 int btn = event.GetButton();
227 if ( btn == -1 )
228 {
229 // we only care about button press/release events
a290fa5a 230 return false;
1e6feb95
VZ
231 }
232
233 if ( event.ButtonDown() || event.ButtonDClick() )
234 {
235 if ( !m_captureData )
236 {
6236b8b4 237 Arrow arrow = m_control->HitTestArrow(event.GetPosition());
1e6feb95
VZ
238 if ( arrow == Arrow_None )
239 {
240 // mouse pressed over something else
a290fa5a 241 return false;
1e6feb95
VZ
242 }
243
244 if ( m_control->GetArrowState(arrow) & wxCONTROL_DISABLED )
245 {
246 // don't allow to press disabled arrows
a290fa5a 247 return true;
1e6feb95
VZ
248 }
249
250 wxConstCast(this, wxScrollArrows)->m_captureData =
251 new wxScrollArrowCaptureData;
252 m_captureData->m_arrowPressed = arrow;
253 m_captureData->m_btnCapture = btn;
254 m_captureData->m_window = m_control->GetWindow();
255 m_captureData->m_window->CaptureMouse();
256
9a6384ca
WS
257#if wxUSE_TIMER
258 // start scrolling
f9bd9677 259 wxScrollArrowTimer *tmpTimerScroll =
1e6feb95 260 new wxScrollArrowTimer(m_control, arrow);
9a6384ca 261#endif // wxUSE_TIMER
1e6feb95 262
9a6384ca
WS
263 // Because in some cases wxScrollArrowTimer can cause
264 // m_captureData to be destructed we need to test if it
f9bd9677
VZ
265 // is still valid before using.
266 if (m_captureData)
267 {
9a6384ca 268#if wxUSE_TIMER
f9bd9677 269 m_captureData->m_timerScroll = tmpTimerScroll;
9a6384ca 270#endif // wxUSE_TIMER
f9bd9677 271
a290fa5a 272 m_control->SetArrowFlag(arrow, wxCONTROL_PRESSED, true);
f9bd9677
VZ
273 }
274 else
275 {
9a6384ca 276#if wxUSE_TIMER
f9bd9677 277 delete tmpTimerScroll;
9a6384ca 278#endif // wxUSE_TIMER
f9bd9677 279 }
1e6feb95
VZ
280 }
281 //else: mouse already captured, nothing to do
282 }
283 // release mouse if the *same* button went up
284 else if ( m_captureData && (btn == m_captureData->m_btnCapture) )
285 {
286 Arrow arrow = m_captureData->m_arrowPressed;
287
288 delete m_captureData;
289 wxConstCast(this, wxScrollArrows)->m_captureData = NULL;
290
a290fa5a 291 m_control->SetArrowFlag(arrow, wxCONTROL_PRESSED, false);
1e6feb95
VZ
292 }
293 else
294 {
295 // we don't process this
a290fa5a 296 return false;
1e6feb95
VZ
297 }
298
a290fa5a 299 return true;
1e6feb95 300}