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