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