1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <tools/time.hxx>
22 #include <tools/debug.hxx>
28 #include <vcl/timer.hxx>
29 #include <vcl/event.hxx>
33 #define WHEEL_WIDTH 25
34 #define WHEEL_RADIUS ((WHEEL_WIDTH) >> 1 )
37 #define DEF_TIMEOUT 50
39 ImplWheelWindow::ImplWheelWindow( vcl::Window
* pParent
) :
40 FloatingWindow ( pParent
, 0 ),
41 mnRepaintTime ( 1UL ),
42 mnTimeout ( DEF_TIMEOUT
),
43 mnWheelMode ( WheelMode::NONE
),
49 SAL_WARN_IF( !pParent
, "vcl", "ImplWheelWindow::ImplWheelWindow(): Parent not set!" );
51 const Size
aSize( pParent
->GetOutputSizePixel() );
52 const StartAutoScrollFlags nFlags
= ImplGetSVData()->maWinData
.mnAutoScrollFlags
;
53 const bool bHorz( nFlags
& StartAutoScrollFlags::Horz
);
54 const bool bVert( nFlags
& StartAutoScrollFlags::Vert
);
56 // calculate maximum speed distance
57 mnMaxWidth
= (sal_uLong
) ( 0.4 * hypot( (double) aSize
.Width(), aSize
.Height() ) );
59 // create wheel window
60 SetTitleType( FloatWinTitleType::NONE
);
61 ImplCreateImageList();
62 ResMgr
* pResMgr
= ImplGetResMgr();
65 aBmp
= Bitmap( ResId( SV_RESID_BITMAP_SCROLLMSK
, *pResMgr
) );
66 ImplSetRegion( aBmp
);
70 ImplSetWheelMode( WheelMode::VH
);
72 ImplSetWheelMode( WheelMode::H
);
74 ImplSetWheelMode( WheelMode::V
);
77 mpTimer
= new Timer("WheelWindowTimer");
78 mpTimer
->SetTimeoutHdl( LINK( this, ImplWheelWindow
, ImplScrollHdl
) );
79 mpTimer
->SetTimeout( mnTimeout
);
80 mpTimer
->SetDebugName( "vcl::ImplWheelWindow mpTimer" );
86 ImplWheelWindow::~ImplWheelWindow()
91 void ImplWheelWindow::dispose()
97 FloatingWindow::dispose();
100 void ImplWheelWindow::ImplStop()
107 void ImplWheelWindow::ImplSetRegion( const Bitmap
& rRegionBmp
)
109 Point
aPos( GetPointerPosPixel() );
110 const Size
aSize( rRegionBmp
.GetSizePixel() );
112 const Rectangle
aRect( aPoint
, aSize
);
114 maCenter
= maLastMousePos
= aPos
;
115 aPos
.X() -= aSize
.Width() >> 1;
116 aPos
.Y() -= aSize
.Height() >> 1;
118 SetPosSizePixel( aPos
, aSize
);
119 SetWindowRegionPixel( rRegionBmp
.CreateRegion( COL_BLACK
, aRect
) );
122 void ImplWheelWindow::ImplCreateImageList()
124 ResMgr
* pResMgr
= ImplGetResMgr();
126 maImgList
.InsertFromHorizontalBitmap
127 ( ResId( SV_RESID_BITMAP_SCROLLBMP
, *pResMgr
), 6, nullptr );
130 void ImplWheelWindow::ImplSetWheelMode( WheelMode nWheelMode
)
132 if( nWheelMode
!= mnWheelMode
)
134 mnWheelMode
= nWheelMode
;
136 if( WheelMode::NONE
== mnWheelMode
)
151 void ImplWheelWindow::ImplDrawWheel(vcl::RenderContext
& rRenderContext
)
166 case WheelMode::ScrollVH
:
169 case WheelMode::ScrollV
:
172 case WheelMode::ScrollH
:
181 rRenderContext
.DrawImage(Point(), maImgList
.GetImage(nId
));
184 void ImplWheelWindow::ImplRecalcScrollValues()
186 if( mnActDist
< WHEEL_RADIUS
)
188 mnActDeltaX
= mnActDeltaY
= 0;
189 mnTimeout
= DEF_TIMEOUT
;
198 const double fExp
= ( (double) mnActDist
/ mnMaxWidth
) * log10( (double) MAX_TIME
/ MIN_TIME
);
199 nCurTime
= (sal_uInt64
) ( MAX_TIME
/ pow( 10., fExp
) );
207 if( mnRepaintTime
<= nCurTime
)
208 mnTimeout
= nCurTime
- mnRepaintTime
;
211 sal_uInt64 nMult
= mnRepaintTime
/ nCurTime
;
213 if( !( mnRepaintTime
% nCurTime
) )
216 mnTimeout
= ++nMult
* nCurTime
- mnRepaintTime
;
218 double fValX
= (double) mnActDeltaX
* nMult
;
219 double fValY
= (double) mnActDeltaY
* nMult
;
221 if( fValX
> LONG_MAX
)
222 mnActDeltaX
= LONG_MAX
;
223 else if( fValX
< LONG_MIN
)
224 mnActDeltaX
= LONG_MIN
;
226 mnActDeltaX
= (long) fValX
;
228 if( fValY
> LONG_MAX
)
229 mnActDeltaY
= LONG_MAX
;
230 else if( fValY
< LONG_MIN
)
231 mnActDeltaY
= LONG_MIN
;
233 mnActDeltaY
= (long) fValY
;
238 PointerStyle
ImplWheelWindow::ImplGetMousePointer( long nDistX
, long nDistY
)
241 const StartAutoScrollFlags nFlags
= ImplGetSVData()->maWinData
.mnAutoScrollFlags
;
242 const bool bHorz( nFlags
& StartAutoScrollFlags::Horz
);
243 const bool bVert( nFlags
& StartAutoScrollFlags::Vert
);
247 if( mnActDist
< WHEEL_RADIUS
)
250 eStyle
= PointerStyle::AutoScrollNSWE
;
252 eStyle
= PointerStyle::AutoScrollWE
;
254 eStyle
= PointerStyle::AutoScrollNS
;
258 double fAngle
= atan2( (double) -nDistY
, nDistX
) / F_PI180
;
265 if( fAngle
>= 22.5 && fAngle
<= 67.5 )
266 eStyle
= PointerStyle::AutoScrollNE
;
267 else if( fAngle
>= 67.5 && fAngle
<= 112.5 )
268 eStyle
= PointerStyle::AutoScrollN
;
269 else if( fAngle
>= 112.5 && fAngle
<= 157.5 )
270 eStyle
= PointerStyle::AutoScrollNW
;
271 else if( fAngle
>= 157.5 && fAngle
<= 202.5 )
272 eStyle
= PointerStyle::AutoScrollW
;
273 else if( fAngle
>= 202.5 && fAngle
<= 247.5 )
274 eStyle
= PointerStyle::AutoScrollSW
;
275 else if( fAngle
>= 247.5 && fAngle
<= 292.5 )
276 eStyle
= PointerStyle::AutoScrollS
;
277 else if( fAngle
>= 292.5 && fAngle
<= 337.5 )
278 eStyle
= PointerStyle::AutoScrollSE
;
280 eStyle
= PointerStyle::AutoScrollE
;
284 if( fAngle
>= 270. || fAngle
<= 90. )
285 eStyle
= PointerStyle::AutoScrollE
;
287 eStyle
= PointerStyle::AutoScrollW
;
291 if( fAngle
>= 0. && fAngle
<= 180. )
292 eStyle
= PointerStyle::AutoScrollN
;
294 eStyle
= PointerStyle::AutoScrollS
;
299 eStyle
= PointerStyle::Arrow
;
304 void ImplWheelWindow::Paint(vcl::RenderContext
& rRenderContext
, const Rectangle
&)
306 ImplDrawWheel(rRenderContext
);
309 void ImplWheelWindow::MouseMove( const MouseEvent
& rMEvt
)
311 FloatingWindow::MouseMove( rMEvt
);
313 const Point
aMousePos( OutputToScreenPixel( rMEvt
.GetPosPixel() ) );
314 const long nDistX
= aMousePos
.X() - maCenter
.X();
315 const long nDistY
= aMousePos
.Y() - maCenter
.Y();
317 mnActDist
= (sal_uLong
) hypot( (double) nDistX
, nDistY
);
319 const PointerStyle eActStyle
= ImplGetMousePointer( nDistX
, nDistY
);
320 const StartAutoScrollFlags nFlags
= ImplGetSVData()->maWinData
.mnAutoScrollFlags
;
321 const bool bHorz( nFlags
& StartAutoScrollFlags::Horz
);
322 const bool bVert( nFlags
& StartAutoScrollFlags::Vert
);
323 const bool bOuter
= mnActDist
> WHEEL_RADIUS
;
325 if( bOuter
&& ( maLastMousePos
!= aMousePos
) )
329 case( PointerStyle::AutoScrollN
): mnActDeltaX
= +0; mnActDeltaY
= +1; break;
330 case( PointerStyle::AutoScrollS
): mnActDeltaX
= +0; mnActDeltaY
= -1; break;
331 case( PointerStyle::AutoScrollW
): mnActDeltaX
= +1; mnActDeltaY
= +0; break;
332 case( PointerStyle::AutoScrollE
): mnActDeltaX
= -1; mnActDeltaY
= +0; break;
333 case( PointerStyle::AutoScrollNW
): mnActDeltaX
= +1; mnActDeltaY
= +1; break;
334 case( PointerStyle::AutoScrollNE
): mnActDeltaX
= -1; mnActDeltaY
= +1; break;
335 case( PointerStyle::AutoScrollSW
): mnActDeltaX
= +1; mnActDeltaY
= -1; break;
336 case( PointerStyle::AutoScrollSE
): mnActDeltaX
= -1; mnActDeltaY
= -1; break;
343 ImplRecalcScrollValues();
344 maLastMousePos
= aMousePos
;
345 SetPointer( eActStyle
);
348 ImplSetWheelMode( bOuter
? WheelMode::ScrollVH
: WheelMode::VH
);
350 ImplSetWheelMode( bOuter
? WheelMode::ScrollH
: WheelMode::H
);
352 ImplSetWheelMode( bOuter
? WheelMode::ScrollV
: WheelMode::V
);
355 void ImplWheelWindow::MouseButtonUp( const MouseEvent
& rMEvt
)
357 if( mnActDist
> WHEEL_RADIUS
)
358 GetParent()->EndAutoScroll();
360 FloatingWindow::MouseButtonUp( rMEvt
);
363 IMPL_LINK_NOARG(ImplWheelWindow
, ImplScrollHdl
, Timer
*, void)
365 if ( mnActDeltaX
|| mnActDeltaY
)
367 vcl::Window
* pWindow
= GetParent();
368 const Point
aMousePos( pWindow
->OutputToScreenPixel( pWindow
->GetPointerPosPixel() ) );
369 Point
aCmdMousePos( pWindow
->ImplFrameToOutput( aMousePos
) );
370 CommandScrollData
aScrollData( mnActDeltaX
, mnActDeltaY
);
371 CommandEvent
aCEvt( aCmdMousePos
, CommandEventId::AutoScroll
, true, &aScrollData
);
372 NotifyEvent
aNCmdEvt( MouseNotifyEvent::COMMAND
, pWindow
, &aCEvt
);
374 if ( !ImplCallPreNotify( aNCmdEvt
) )
376 const sal_uInt64 nTime
= tools::Time::GetSystemTicks();
377 VclPtr
<ImplWheelWindow
> xWin(this);
378 pWindow
->Command( aCEvt
);
379 if( xWin
->IsDisposed() )
381 mnRepaintTime
= std::max( tools::Time::GetSystemTicks() - nTime
, (sal_uInt64
)1 );
382 ImplRecalcScrollValues();
386 if ( mnTimeout
!= mpTimer
->GetTimeout() )
387 mpTimer
->SetTimeout( mnTimeout
);
391 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */