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