1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_vcl.hxx"
26
27 // #include <math.h>
28 #include <limits.h>
29 #include <tools/time.hxx>
30 #include <tools/debug.hxx>
31
32 #include <svids.hrc>
33 #include <svdata.hxx>
34 #include <scrwnd.hxx>
35
36 #include <vcl/timer.hxx>
37 #include <vcl/event.hxx>
38
39 #include <math.h>
40 #include <limits.h>
41
42 // -----------
43 // - Defines -
44 // -----------
45
46 #define WHEEL_WIDTH 25
47 #define WHEEL_RADIUS ((WHEEL_WIDTH) >> 1 )
48 #define MAX_TIME 300
49 #define MIN_TIME 20
50 #define DEF_TIMEOUT 50
51
52 // -------------------
53 // - ImplWheelWindow -
54 // -------------------
55
ImplWheelWindow(Window * pParent)56 ImplWheelWindow::ImplWheelWindow( Window* pParent ) :
57 FloatingWindow ( pParent, 0 ),
58 mnRepaintTime ( 1UL ),
59 mnTimeout ( DEF_TIMEOUT ),
60 mnWheelMode ( WHEELMODE_NONE ),
61 mnActDist ( 0UL ),
62 mnActDeltaX ( 0L ),
63 mnActDeltaY ( 0L )
64 {
65 // we need a parent
66 DBG_ASSERT( pParent, "ImplWheelWindow::ImplWheelWindow(): Parent not set!" );
67
68 const Size aSize( pParent->GetOutputSizePixel() );
69 const sal_uInt16 nFlags = ImplGetSVData()->maWinData.mnAutoScrollFlags;
70 const sal_Bool bHorz = ( nFlags & AUTOSCROLL_HORZ ) != 0;
71 const sal_Bool bVert = ( nFlags & AUTOSCROLL_VERT ) != 0;
72
73 // calculate maximum speed distance
74 mnMaxWidth = (sal_uLong) ( 0.4 * hypot( (double) aSize.Width(), aSize.Height() ) );
75
76 // create wheel window
77 SetTitleType( FLOATWIN_TITLE_NONE );
78 ImplCreateImageList();
79 ResMgr* pResMgr = ImplGetResMgr();
80 Bitmap aBmp;
81 if( pResMgr )
82 aBmp = Bitmap( ResId( SV_RESID_BITMAP_SCROLLMSK, *pResMgr ) );
83 ImplSetRegion( aBmp );
84
85 // set wheel mode
86 if( bHorz && bVert )
87 ImplSetWheelMode( WHEELMODE_VH );
88 else if( bHorz )
89 ImplSetWheelMode( WHEELMODE_H );
90 else
91 ImplSetWheelMode( WHEELMODE_V );
92
93 // init timer
94 mpTimer = new Timer;
95 mpTimer->SetTimeoutHdl( LINK( this, ImplWheelWindow, ImplScrollHdl ) );
96 mpTimer->SetTimeout( mnTimeout );
97 mpTimer->Start();
98
99 CaptureMouse();
100 }
101
102 // ------------------------------------------------------------------------
103
~ImplWheelWindow()104 ImplWheelWindow::~ImplWheelWindow()
105 {
106 ImplStop();
107 delete mpTimer;
108 }
109
110 // ------------------------------------------------------------------------
111
ImplStop()112 void ImplWheelWindow::ImplStop()
113 {
114 ReleaseMouse();
115 mpTimer->Stop();
116 Show(sal_False);
117 }
118
119 // ------------------------------------------------------------------------
120
ImplSetRegion(const Bitmap & rRegionBmp)121 void ImplWheelWindow::ImplSetRegion( const Bitmap& rRegionBmp )
122 {
123 Point aPos( GetPointerPosPixel() );
124 const Size aSize( rRegionBmp.GetSizePixel() );
125 Point aPoint;
126 const Rectangle aRect( aPoint, aSize );
127
128 maCenter = maLastMousePos = aPos;
129 aPos.X() -= aSize.Width() >> 1;
130 aPos.Y() -= aSize.Height() >> 1;
131
132 SetPosSizePixel( aPos, aSize );
133 SetWindowRegionPixel( rRegionBmp.CreateRegion( COL_BLACK, aRect ) );
134 }
135
136 // ------------------------------------------------------------------------
137
ImplCreateImageList()138 void ImplWheelWindow::ImplCreateImageList()
139 {
140 ResMgr* pResMgr = ImplGetResMgr();
141 if( pResMgr )
142 maImgList.InsertFromHorizontalBitmap
143 ( ResId( SV_RESID_BITMAP_SCROLLBMP, *pResMgr ), 6, NULL );
144 }
145
146 // ------------------------------------------------------------------------
147
ImplSetWheelMode(sal_uLong nWheelMode)148 void ImplWheelWindow::ImplSetWheelMode( sal_uLong nWheelMode )
149 {
150 if( nWheelMode != mnWheelMode )
151 {
152 mnWheelMode = nWheelMode;
153
154 if( WHEELMODE_NONE == mnWheelMode )
155 {
156 if( IsVisible() )
157 Hide();
158 }
159 else
160 {
161 if( !IsVisible() )
162 Show();
163
164 ImplDrawWheel();
165 }
166 }
167 }
168
169 // ------------------------------------------------------------------------
170
ImplDrawWheel()171 void ImplWheelWindow::ImplDrawWheel()
172 {
173 sal_uInt16 nId;
174
175 switch( mnWheelMode )
176 {
177 case( WHEELMODE_VH ): nId = 1; break;
178 case( WHEELMODE_V ): nId = 2; break;
179 case( WHEELMODE_H ): nId = 3; break;
180 case( WHEELMODE_SCROLL_VH ):nId = 4; break;
181 case( WHEELMODE_SCROLL_V ): nId = 5; break;
182 case( WHEELMODE_SCROLL_H ): nId = 6; break;
183 default: nId = 0; break;
184 }
185
186 if( nId )
187 DrawImage( Point(), maImgList.GetImage( nId ) );
188 }
189
190 // ------------------------------------------------------------------------
191
ImplRecalcScrollValues()192 void ImplWheelWindow::ImplRecalcScrollValues()
193 {
194 if( mnActDist < WHEEL_RADIUS )
195 {
196 mnActDeltaX = mnActDeltaY = 0L;
197 mnTimeout = DEF_TIMEOUT;
198 }
199 else
200 {
201 sal_uLong nCurTime;
202
203 // calc current time
204 if( mnMaxWidth )
205 {
206 const double fExp = ( (double) mnActDist / mnMaxWidth ) * log10( (double) MAX_TIME / MIN_TIME );
207 nCurTime = (sal_uLong) ( MAX_TIME / pow( 10., fExp ) );
208 }
209 else
210 nCurTime = MAX_TIME;
211
212 if( !nCurTime )
213 nCurTime = 1UL;
214
215 if( mnRepaintTime <= nCurTime )
216 mnTimeout = nCurTime - mnRepaintTime;
217 else
218 {
219 long nMult = mnRepaintTime / nCurTime;
220
221 if( !( mnRepaintTime % nCurTime ) )
222 mnTimeout = 0UL;
223 else
224 mnTimeout = ++nMult * nCurTime - mnRepaintTime;
225
226 double fValX = (double) mnActDeltaX * nMult;
227 double fValY = (double) mnActDeltaY * nMult;
228
229 if( fValX > LONG_MAX )
230 mnActDeltaX = LONG_MAX;
231 else if( fValX < LONG_MIN )
232 mnActDeltaX = LONG_MIN;
233 else
234 mnActDeltaX = (long) fValX;
235
236 if( fValY > LONG_MAX )
237 mnActDeltaY = LONG_MAX;
238 else if( fValY < LONG_MIN )
239 mnActDeltaY = LONG_MIN;
240 else
241 mnActDeltaY = (long) fValY;
242 }
243 }
244 }
245
246 // ------------------------------------------------------------------------
247
ImplGetMousePointer(long nDistX,long nDistY)248 PointerStyle ImplWheelWindow::ImplGetMousePointer( long nDistX, long nDistY )
249 {
250 PointerStyle eStyle;
251 const sal_uInt16 nFlags = ImplGetSVData()->maWinData.mnAutoScrollFlags;
252 const sal_Bool bHorz = ( nFlags & AUTOSCROLL_HORZ ) != 0;
253 const sal_Bool bVert = ( nFlags & AUTOSCROLL_VERT ) != 0;
254
255 if( bHorz || bVert )
256 {
257 if( mnActDist < WHEEL_RADIUS )
258 {
259 if( bHorz && bVert )
260 eStyle = POINTER_AUTOSCROLL_NSWE;
261 else if( bHorz )
262 eStyle = POINTER_AUTOSCROLL_WE;
263 else
264 eStyle = POINTER_AUTOSCROLL_NS;
265 }
266 else
267 {
268 double fAngle = atan2( (double) -nDistY, nDistX ) / F_PI180;
269
270 if( fAngle < 0.0 )
271 fAngle += 360.;
272
273 if( bHorz && bVert )
274 {
275 if( fAngle >= 22.5 && fAngle <= 67.5 )
276 eStyle = POINTER_AUTOSCROLL_NE;
277 else if( fAngle >= 67.5 && fAngle <= 112.5 )
278 eStyle = POINTER_AUTOSCROLL_N;
279 else if( fAngle >= 112.5 && fAngle <= 157.5 )
280 eStyle = POINTER_AUTOSCROLL_NW;
281 else if( fAngle >= 157.5 && fAngle <= 202.5 )
282 eStyle = POINTER_AUTOSCROLL_W;
283 else if( fAngle >= 202.5 && fAngle <= 247.5 )
284 eStyle = POINTER_AUTOSCROLL_SW;
285 else if( fAngle >= 247.5 && fAngle <= 292.5 )
286 eStyle = POINTER_AUTOSCROLL_S;
287 else if( fAngle >= 292.5 && fAngle <= 337.5 )
288 eStyle = POINTER_AUTOSCROLL_SE;
289 else
290 eStyle = POINTER_AUTOSCROLL_E;
291 }
292 else if( bHorz )
293 {
294 if( fAngle >= 270. || fAngle <= 90. )
295 eStyle = POINTER_AUTOSCROLL_E;
296 else
297 eStyle = POINTER_AUTOSCROLL_W;
298 }
299 else
300 {
301 if( fAngle >= 0. && fAngle <= 180. )
302 eStyle = POINTER_AUTOSCROLL_N;
303 else
304 eStyle = POINTER_AUTOSCROLL_S;
305 }
306 }
307 }
308 else
309 eStyle = POINTER_ARROW;
310
311 return eStyle;
312 }
313
314 // ------------------------------------------------------------------------
315
Paint(const Rectangle &)316 void ImplWheelWindow::Paint( const Rectangle& )
317 {
318 ImplDrawWheel();
319 }
320
321 // ------------------------------------------------------------------------
322
MouseMove(const MouseEvent & rMEvt)323 void ImplWheelWindow::MouseMove( const MouseEvent& rMEvt )
324 {
325 FloatingWindow::MouseMove( rMEvt );
326
327 const Point aMousePos( OutputToScreenPixel( rMEvt.GetPosPixel() ) );
328 const long nDistX = aMousePos.X() - maCenter.X();
329 const long nDistY = aMousePos.Y() - maCenter.Y();
330
331 mnActDist = (sal_uLong) hypot( (double) nDistX, nDistY );
332
333 const PointerStyle eActStyle = ImplGetMousePointer( nDistX, nDistY );
334 const sal_uInt16 nFlags = ImplGetSVData()->maWinData.mnAutoScrollFlags;
335 const sal_Bool bHorz = ( nFlags & AUTOSCROLL_HORZ ) != 0;
336 const sal_Bool bVert = ( nFlags & AUTOSCROLL_VERT ) != 0;
337 const sal_Bool bOuter = mnActDist > WHEEL_RADIUS;
338
339 if( bOuter && ( maLastMousePos != aMousePos ) )
340 {
341 switch( eActStyle )
342 {
343 case( POINTER_AUTOSCROLL_N ): mnActDeltaX = +0L, mnActDeltaY = +1L; break;
344 case( POINTER_AUTOSCROLL_S ): mnActDeltaX = +0L, mnActDeltaY = -1L; break;
345 case( POINTER_AUTOSCROLL_W ): mnActDeltaX = +1L, mnActDeltaY = +0L; break;
346 case( POINTER_AUTOSCROLL_E ): mnActDeltaX = -1L, mnActDeltaY = +0L; break;
347 case( POINTER_AUTOSCROLL_NW ): mnActDeltaX = +1L, mnActDeltaY = +1L; break;
348 case( POINTER_AUTOSCROLL_NE ): mnActDeltaX = -1L, mnActDeltaY = +1L; break;
349 case( POINTER_AUTOSCROLL_SW ): mnActDeltaX = +1L, mnActDeltaY = -1L; break;
350 case( POINTER_AUTOSCROLL_SE ): mnActDeltaX = -1L, mnActDeltaY = -1L; break;
351
352 default:
353 break;
354 }
355 }
356
357 ImplRecalcScrollValues();
358 maLastMousePos = aMousePos;
359 SetPointer( eActStyle );
360
361 if( bHorz && bVert )
362 ImplSetWheelMode( bOuter ? WHEELMODE_SCROLL_VH : WHEELMODE_VH );
363 else if( bHorz )
364 ImplSetWheelMode( bOuter ? WHEELMODE_SCROLL_H : WHEELMODE_H );
365 else
366 ImplSetWheelMode( bOuter ? WHEELMODE_SCROLL_V : WHEELMODE_V );
367 }
368
369 // ------------------------------------------------------------------------
370
MouseButtonUp(const MouseEvent & rMEvt)371 void ImplWheelWindow::MouseButtonUp( const MouseEvent& rMEvt )
372 {
373 if( mnActDist > WHEEL_RADIUS )
374 GetParent()->EndAutoScroll();
375 else
376 FloatingWindow::MouseButtonUp( rMEvt );
377 }
378
379 // ------------------------------------------------------------------------
380
IMPL_LINK(ImplWheelWindow,ImplScrollHdl,Timer *,EMPTYARG)381 IMPL_LINK( ImplWheelWindow, ImplScrollHdl, Timer*, EMPTYARG )
382 {
383 if ( mnActDeltaX || mnActDeltaY )
384 {
385 Window* pWindow = GetParent();
386 const Point aMousePos( pWindow->OutputToScreenPixel( pWindow->GetPointerPosPixel() ) );
387 Point aCmdMousePos( pWindow->ImplFrameToOutput( aMousePos ) );
388 CommandScrollData aScrollData( mnActDeltaX, mnActDeltaY );
389 CommandEvent aCEvt( aCmdMousePos, COMMAND_AUTOSCROLL, sal_True, &aScrollData );
390 NotifyEvent aNCmdEvt( EVENT_COMMAND, pWindow, &aCEvt );
391
392 if ( !ImplCallPreNotify( aNCmdEvt ) )
393 {
394 const sal_uLong nTime = Time::GetSystemTicks();
395 ImplDelData aDel( this );
396 pWindow->Command( aCEvt );
397 if( aDel.IsDead() )
398 return 0;
399 mnRepaintTime = Max( Time::GetSystemTicks() - nTime, 1UL );
400 ImplRecalcScrollValues();
401 }
402 }
403
404 if ( mnTimeout != mpTimer->GetTimeout() )
405 mpTimer->SetTimeout( mnTimeout );
406 mpTimer->Start();
407
408 return 0L;
409 }
410