fixed wxUniv's wxDialog::ShowModal() to use GetParentForModalDialog()
[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 #include "wx/window.h"
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
42 struct wxScrollArrowCaptureData
43 {
44 wxScrollArrowCaptureData()
45 {
46 m_arrowPressed = wxScrollArrows::Arrow_None;
47 m_window = NULL;
48 m_btnCapture = -1;
49 #if wxUSE_TIMER
50 m_timerScroll = NULL;
51 #endif // wxUSE_TIMER
52 }
53
54 ~wxScrollArrowCaptureData()
55 {
56 if ( m_window )
57 m_window->ReleaseMouse();
58
59 #if wxUSE_TIMER
60 delete m_timerScroll;
61 #endif // wxUSE_TIMER
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
73 #if wxUSE_TIMER
74 // the timer for generating the scroll events
75 wxScrollTimer *m_timerScroll;
76 #endif
77 };
78
79 // ----------------------------------------------------------------------------
80 // wxScrollArrowTimer: a wxScrollTimer which calls OnArrow()
81 // ----------------------------------------------------------------------------
82
83 #if wxUSE_TIMER
84
85 class wxScrollArrowTimer : public wxScrollTimer
86 {
87 public:
88 wxScrollArrowTimer(wxControlWithArrows *control,
89 wxScrollArrows::Arrow arrow)
90 {
91 m_control = control;
92 m_arrow = arrow;
93
94 StartAutoScroll();
95 }
96
97 protected:
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
107 #endif // wxUSE_TIMER
108
109 // ============================================================================
110 // implementation of wxScrollArrows
111 // ============================================================================
112
113 // ----------------------------------------------------------------------------
114 // con/destruction
115 // ----------------------------------------------------------------------------
116
117 wxScrollArrows::wxScrollArrows(wxControlWithArrows *control)
118 {
119 m_control = control;
120 m_captureData = NULL;
121 }
122
123 wxScrollArrows::~wxScrollArrows()
124 {
125 // it should have been destroyed
126 wxASSERT_MSG( !m_captureData, _T("memory leak in wxScrollArrows") );
127 }
128
129 // ----------------------------------------------------------------------------
130 // drawing
131 // ----------------------------------------------------------------------------
132
133 void 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
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));
156 }
157
158 // ----------------------------------------------------------------------------
159 // input handling
160 // ----------------------------------------------------------------------------
161
162 void wxScrollArrows::UpdateCurrentFlag(Arrow arrow, Arrow arrowCur) const
163 {
164 m_control->SetArrowFlag(arrow, wxCONTROL_CURRENT, arrow == arrowCur);
165 }
166
167 bool 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 {
177 arrow = m_control->HitTestArrow(event.GetPosition());
178 }
179
180 #if wxUSE_TIMER
181 if ( m_captureData && m_captureData->m_timerScroll)
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
192 m_control->SetArrowFlag(arrow, wxCONTROL_PRESSED, true);
193 timer->Start();
194
195 return true;
196 }
197 }
198 else // if ( 1 ) FIXME: m_control->ShouldPauseScrolling() )
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,
205 wxCONTROL_PRESSED, false);
206 timer->Stop();
207
208 return true;
209 }
210 }
211
212 return false;
213 }
214 #endif // wxUSE_TIMER
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
221 // return true if it was really an event for an arrow
222 return !event.Leaving() && arrow != Arrow_None;
223 }
224
225 bool 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
231 return false;
232 }
233
234 if ( event.ButtonDown() || event.ButtonDClick() )
235 {
236 if ( !m_captureData )
237 {
238 Arrow arrow = m_control->HitTestArrow(event.GetPosition());
239 if ( arrow == Arrow_None )
240 {
241 // mouse pressed over something else
242 return false;
243 }
244
245 if ( m_control->GetArrowState(arrow) & wxCONTROL_DISABLED )
246 {
247 // don't allow to press disabled arrows
248 return true;
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
258 #if wxUSE_TIMER
259 // start scrolling
260 wxScrollArrowTimer *tmpTimerScroll =
261 new wxScrollArrowTimer(m_control, arrow);
262 #endif // wxUSE_TIMER
263
264 // Because in some cases wxScrollArrowTimer can cause
265 // m_captureData to be destructed we need to test if it
266 // is still valid before using.
267 if (m_captureData)
268 {
269 #if wxUSE_TIMER
270 m_captureData->m_timerScroll = tmpTimerScroll;
271 #endif // wxUSE_TIMER
272
273 m_control->SetArrowFlag(arrow, wxCONTROL_PRESSED, true);
274 }
275 else
276 {
277 #if wxUSE_TIMER
278 delete tmpTimerScroll;
279 #endif // wxUSE_TIMER
280 }
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
292 m_control->SetArrowFlag(arrow, wxCONTROL_PRESSED, false);
293 }
294 else
295 {
296 // we don't process this
297 return false;
298 }
299
300 return true;
301 }