]> git.saurik.com Git - wxWidgets.git/blob - src/univ/scrarrow.cpp
copied wxMac and wxMotif faq from wxWebSite
[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 #ifdef __GNUG__
21 #pragma implementation "univscrarrow.h"
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
45 struct 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
80 class wxScrollArrowTimer : public wxScrollTimer
81 {
82 public:
83 wxScrollArrowTimer(wxControlWithArrows *control,
84 wxScrollArrows::Arrow arrow)
85 {
86 m_control = control;
87 m_arrow = arrow;
88
89 StartAutoScroll();
90 }
91
92 protected:
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
110 wxScrollArrows::wxScrollArrows(wxControlWithArrows *control)
111 {
112 m_control = control;
113 m_captureData = NULL;
114 }
115
116 wxScrollArrows::~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
126 void 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
137 void (wxRenderer::*pfn)(wxDC&, wxDirection, const wxRect&, int) =
138 scrollbarLike ? &wxRenderer::DrawScrollbarArrow
139 : &wxRenderer::DrawArrow;
140
141 (m_control->GetRenderer()->*pfn)
142 (
143 dc,
144 arrowDirs[m_control->IsVertical()][arrow],
145 rect,
146 m_control->GetArrowState(arrow)
147 );
148 }
149
150 // ----------------------------------------------------------------------------
151 // input handling
152 // ----------------------------------------------------------------------------
153
154 void wxScrollArrows::UpdateCurrentFlag(Arrow arrow, Arrow arrowCur) const
155 {
156 m_control->SetArrowFlag(arrow, wxCONTROL_CURRENT, arrow == arrowCur);
157 }
158
159 bool wxScrollArrows::HandleMouseMove(const wxMouseEvent& event) const
160 {
161 Arrow arrow;
162 if ( event.Leaving() )
163 {
164 // no arrow has mouse if it left the window completely
165 arrow = Arrow_None;
166 }
167 else // Moving() or Entering(), treat them the same here
168 {
169 arrow = m_control->HitTest(event.GetPosition());
170 }
171
172 if ( m_captureData )
173 {
174 // the mouse is captured, we may want to pause scrolling if it goes
175 // outside the arrow or to resume it if we had paused it before
176 wxTimer *timer = m_captureData->m_timerScroll;
177 if ( !timer->IsRunning() )
178 {
179 // timer is paused
180 if ( arrow == m_captureData->m_arrowPressed )
181 {
182 // resume now
183 m_control->SetArrowFlag(arrow, wxCONTROL_PRESSED, TRUE);
184 timer->Start();
185
186 return TRUE;
187 }
188 }
189 else if ( 1 ) //FIXME: m_control->ShouldPauseScrolling() )
190 {
191 // we may want to stop it
192 if ( arrow != m_captureData->m_arrowPressed )
193 {
194 // stop as the mouse left the arrow
195 m_control->SetArrowFlag(m_captureData->m_arrowPressed,
196 wxCONTROL_PRESSED, FALSE);
197 timer->Stop();
198
199 return TRUE;
200 }
201 }
202
203 return FALSE;
204 }
205
206 // reset the wxCONTROL_CURRENT flag for the arrows which don't have the
207 // mouse and set it for the one which has
208 UpdateCurrentFlag(Arrow_First, arrow);
209 UpdateCurrentFlag(Arrow_Second, arrow);
210
211 // return TRUE if it was really an event for an arrow
212 return !event.Leaving() && arrow != Arrow_None;
213 }
214
215 bool wxScrollArrows::HandleMouse(const wxMouseEvent& event) const
216 {
217 int btn = event.GetButton();
218 if ( btn == -1 )
219 {
220 // we only care about button press/release events
221 return FALSE;
222 }
223
224 if ( event.ButtonDown() || event.ButtonDClick() )
225 {
226 if ( !m_captureData )
227 {
228 Arrow arrow = m_control->HitTest(event.GetPosition());
229 if ( arrow == Arrow_None )
230 {
231 // mouse pressed over something else
232 return FALSE;
233 }
234
235 if ( m_control->GetArrowState(arrow) & wxCONTROL_DISABLED )
236 {
237 // don't allow to press disabled arrows
238 return TRUE;
239 }
240
241 wxConstCast(this, wxScrollArrows)->m_captureData =
242 new wxScrollArrowCaptureData;
243 m_captureData->m_arrowPressed = arrow;
244 m_captureData->m_btnCapture = btn;
245 m_captureData->m_window = m_control->GetWindow();
246 m_captureData->m_window->CaptureMouse();
247
248 // start scrolling
249 m_captureData->m_timerScroll =
250 new wxScrollArrowTimer(m_control, arrow);
251
252 m_control->SetArrowFlag(arrow, wxCONTROL_PRESSED, TRUE);
253 }
254 //else: mouse already captured, nothing to do
255 }
256 // release mouse if the *same* button went up
257 else if ( m_captureData && (btn == m_captureData->m_btnCapture) )
258 {
259 Arrow arrow = m_captureData->m_arrowPressed;
260
261 delete m_captureData;
262 wxConstCast(this, wxScrollArrows)->m_captureData = NULL;
263
264 m_control->SetArrowFlag(arrow, wxCONTROL_PRESSED, FALSE);
265 }
266 else
267 {
268 // we don't process this
269 return FALSE;
270 }
271
272 return TRUE;
273 }
274