]> git.saurik.com Git - wxWidgets.git/blame - src/univ/scrthumb.cpp
Fix another crash when conversion fails in Unix PostScript code.
[wxWidgets.git] / src / univ / scrthumb.cpp
CommitLineData
1e6feb95 1/////////////////////////////////////////////////////////////////////////////
9a6384ca 2// Name: src/univ/scrthumb.cpp
1e6feb95
VZ
3// Purpose: wxScrollThumb and related classes
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 13.02.01
442b35b5 7// Copyright: (c) 2001 SciTech Software, Inc. (www.scitechsoft.com)
65571936 8// Licence: wxWindows licence
1e6feb95
VZ
9/////////////////////////////////////////////////////////////////////////////
10
11// ============================================================================
12// declarations
13// ============================================================================
14
15// ----------------------------------------------------------------------------
16// headers
17// ----------------------------------------------------------------------------
18
1e6feb95
VZ
19#include "wx/wxprec.h"
20
21#ifdef __BORLANDC__
22 #pragma hdrstop
23#endif
24
25#ifndef WX_PRECOMP
26 #include "wx/window.h"
27#endif // WX_PRECOMP
28
9a6384ca 29#include "wx/renderer.h"
1e6feb95
VZ
30#include "wx/univ/scrtimer.h"
31#include "wx/univ/scrthumb.h"
32
33// ----------------------------------------------------------------------------
34// wxScrollThumbCaptureData: the struct used while dragging the scroll thumb
35// ----------------------------------------------------------------------------
36
37struct WXDLLEXPORT wxScrollThumbCaptureData
38{
39 // start mouse capture after the user clicked the mouse button btn on this
40 // part of the control
41 wxScrollThumbCaptureData(wxScrollThumb::Shaft part,
42 int btn,
43 wxControlWithThumb *control)
44 {
45 m_shaftPart = part;
46 m_btnCapture = btn;
47 m_timerScroll = NULL;
48
49 m_window = control->GetWindow();
50 m_window->CaptureMouse();
51 }
52
53 // release mouse
54 ~wxScrollThumbCaptureData()
55 {
56 if ( m_window )
57 {
58 m_window->ReleaseMouse();
59 }
60
9a6384ca 61#if wxUSE_TIMER
1e6feb95 62 delete m_timerScroll;
9a6384ca 63#endif // wxUSE_TIMER
1e6feb95
VZ
64 }
65
66 // the thumb part being held pressed
67 wxScrollThumb::Shaft m_shaftPart;
68
69 // the mouse button which started the capture (-1 if none)
70 int m_btnCapture;
71
72 // the window which has captured the mouse
73 wxWindow *m_window;
74
75 // the offset between the mouse position and the start of the thumb which
76 // is kept constant while dragging the thumb
77 wxCoord m_ofsMouse;
78
79 // the timer for generating the scroll events when scrolling by page
80 wxScrollTimer *m_timerScroll;
81};
82
83// ----------------------------------------------------------------------------
84// wxScrollTimer: the timer used when the arrow is kept pressed
85// ----------------------------------------------------------------------------
86
9a6384ca
WS
87#if wxUSE_TIMER
88
1e6feb95
VZ
89class wxScrollThumbTimer : public wxScrollTimer
90{
91public:
92 wxScrollThumbTimer(wxControlWithThumb *control,
93 wxScrollThumb::Shaft shaftPart)
94 {
95 m_control = control;
96 switch ( shaftPart )
97 {
98 case wxScrollThumb::Shaft_Above:
99 m_inc = -1;
100 break;
101
102 default:
9a83f860 103 wxFAIL_MSG(wxT("unexpected shaft part in wxScrollThumbTimer"));
1e6feb95
VZ
104 // fall through
105
106 case wxScrollThumb::Shaft_Below:
107 m_inc = 1;
108 break;
109 }
110
111 m_control->OnPageScrollStart();
112
113 StartAutoScroll();
114 }
115
116protected:
117 virtual bool DoNotify()
118 {
119 return m_control->OnPageScroll(m_inc);
120 }
121
122 wxControlWithThumb *m_control;
123 int m_inc;
124};
125
9a6384ca
WS
126#endif // wxUSE_TIMER
127
1e6feb95
VZ
128// ============================================================================
129// implementation
130// ============================================================================
131
132// ----------------------------------------------------------------------------
133// wxScrollThumb constructor and dtor
134// ----------------------------------------------------------------------------
135
136wxScrollThumb::wxScrollThumb(wxControlWithThumb *control)
137{
138 m_shaftPart = Shaft_None;
139 m_control = control;
140 m_captureData = NULL;
141}
142
143wxScrollThumb::~wxScrollThumb()
144{
145 // it should have been destroyed
9a83f860 146 wxASSERT_MSG( !m_captureData, wxT("memory leak in wxScrollThumb") );
1e6feb95
VZ
147}
148
149// ----------------------------------------------------------------------------
150// wxScrollThumb mouse handling
151// ----------------------------------------------------------------------------
152
153bool wxScrollThumb::HandleMouse(const wxMouseEvent& event) const
154{
155 // is this a click event?
156 int btn = event.GetButton();
157 if ( btn == -1 )
158 {
159 // no...
a290fa5a 160 return false;
1e6feb95
VZ
161 }
162
163 // when the mouse is pressed on any scrollbar element, we capture it
164 // and hold capture until the same mouse button is released
165 if ( event.ButtonDown() || event.ButtonDClick() )
166 {
167 if ( HasCapture() )
168 {
169 // mouse already captured, nothing to do
a290fa5a 170 return false;
1e6feb95
VZ
171 }
172
173 // determine which part of the window the user clicked in
174 Shaft shaftPart = m_control->HitTest(event.GetPosition());
175
176 if ( shaftPart == Shaft_None )
177 {
178 // mouse pressed over something else
a290fa5a 179 return false;
1e6feb95
VZ
180 }
181
182 // capture the mouse
183 wxConstCast(this, wxScrollThumb)->m_captureData =
184 new wxScrollThumbCaptureData(shaftPart, btn, m_control);
185
186 // modify the visual appearance before sending the event which will
187 // cause a redraw
188 m_control->SetShaftPartState(shaftPart, wxCONTROL_PRESSED);
189
190 if ( shaftPart == Shaft_Thumb )
191 {
192 // save the mouse offset from the thumb position - we will keep it
193 // constant while dragging the thumb
194 m_captureData->m_ofsMouse =
195 GetMouseCoord(event) - m_control->ThumbPosToPixel();
196
197 // generate an additional event if we start dragging the thumb
198 m_control->OnThumbDragStart(GetThumbPos(event));
199 }
9a6384ca 200#if wxUSE_TIMER
1e6feb95
VZ
201 else // not the thumb
202 {
203 // start timer for auto scrolling when the user presses the mouse
204 // in the shaft above or below the thumb
205 m_captureData->m_timerScroll =
206 new wxScrollThumbTimer(m_control, shaftPart);
207 }
9a6384ca 208#endif // wxUSE_TIMER
1e6feb95
VZ
209 }
210 // release mouse if the *same* button went up
211 else if ( HasCapture() && (btn == m_captureData->m_btnCapture) )
212 {
213 Shaft shaftPart = m_captureData->m_shaftPart;
214
215 // if we were dragging the thumb, send the one last event
216 if ( shaftPart == Shaft_Thumb )
217 {
218 m_control->OnThumbDragEnd(GetThumbPos(event));
219 }
220
221 // release the mouse and free capture data
222 delete m_captureData;
223 wxConstCast(this, wxScrollThumb)->m_captureData = NULL;
224
a290fa5a 225 m_control->SetShaftPartState(shaftPart, wxCONTROL_PRESSED, false);
1e6feb95
VZ
226 }
227 else // another mouse button released
228 {
229 // we don't process this
a290fa5a 230 return false;
1e6feb95
VZ
231 }
232
a290fa5a 233 return true;
1e6feb95
VZ
234}
235
236bool wxScrollThumb::HandleMouseMove(const wxMouseEvent& event) const
237{
238 if ( HasCapture() )
239 {
240 if ( (m_captureData->m_shaftPart == Shaft_Thumb) && event.Moving() )
241 {
242 // make the thumb follow the mouse by keeping the same offset
243 // between the mouse position and the top/left of the thumb
244 m_control->OnThumbDrag(GetThumbPos(event));
245 }
246
247 // we process all mouse events while the mouse is captured by us
a290fa5a 248 return true;
1e6feb95
VZ
249 }
250 else // no capture
251 {
252 Shaft shaftPart;
253 if ( event.Leaving() )
254 {
255 // no part of the shaft has mouse if it left the window completely
256 shaftPart = Shaft_None;
257 }
258 else // Moving() or Entering(), treat them the same here
259 {
260 shaftPart = m_control->HitTest(event.GetPosition());
261 }
262
263 if ( shaftPart != m_shaftPart )
264 {
265 // update the highlighted state
a290fa5a 266 m_control->SetShaftPartState(m_shaftPart, wxCONTROL_CURRENT, false);
1e6feb95 267 wxConstCast(this, wxScrollThumb)->m_shaftPart = shaftPart;
a290fa5a 268 m_control->SetShaftPartState(m_shaftPart, wxCONTROL_CURRENT, true);
1e6feb95
VZ
269 }
270
271 // if the event happened on the shaft, it was for us and we processed
272 // it
273 return shaftPart != Shaft_None;
274 }
275}
276
277wxCoord wxScrollThumb::GetMouseCoord(const wxMouseEvent& event) const
278{
279 wxPoint pt = event.GetPosition();
280 return m_control->IsVertical() ? pt.y : pt.x;
281}
282
283int wxScrollThumb::GetThumbPos(const wxMouseEvent& event) const
284{
285 wxCHECK_MSG( m_captureData && m_captureData->m_shaftPart == Shaft_Thumb, 0,
9a83f860 286 wxT("can't be called when thumb is not dragged") );
1e6feb95
VZ
287
288 int x = GetMouseCoord(event) - m_captureData->m_ofsMouse;
289 return m_control->PixelToThumbPos(x);
290}