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