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 .
20 #include <tools/rcid.h>
22 #include <vcl/event.hxx>
23 #include <vcl/spin.hxx>
25 // =======================================================================
27 void SpinButton::ImplInit( Window
* pParent
, WinBits nStyle
)
29 mbUpperIn
= sal_False
;
30 mbLowerIn
= sal_False
;
31 mbInitialUp
= sal_False
;
32 mbInitialDown
= sal_False
;
39 maRepeatTimer
.SetTimeout( GetSettings().GetMouseSettings().GetButtonStartRepeat() );
40 maRepeatTimer
.SetTimeoutHdl( LINK( this, SpinButton
, ImplTimeout
) );
42 mbRepeat
= 0 != ( nStyle
& WB_REPEAT
);
44 if ( nStyle
& WB_HSCROLL
)
49 Control::ImplInit( pParent
, nStyle
, NULL
);
52 // -----------------------------------------------------------------------
54 SpinButton::SpinButton( Window
* pParent
, WinBits nStyle
)
55 :Control( WINDOW_SPINBUTTON
)
56 ,mbUpperIsFocused( sal_False
)
58 ImplInit( pParent
, nStyle
);
61 // -----------------------------------------------------------------------
63 SpinButton::~SpinButton()
67 // -----------------------------------------------------------------------
69 IMPL_LINK( SpinButton
, ImplTimeout
, Timer
*, pTimer
)
71 if ( pTimer
->GetTimeout() == GetSettings().GetMouseSettings().GetButtonStartRepeat() )
73 pTimer
->SetTimeout( GetSettings().GetMouseSettings().GetButtonRepeat() );
87 // -----------------------------------------------------------------------
91 if ( ImplIsUpperEnabled() )
93 mnValue
+= mnValueStep
;
94 StateChanged( STATE_CHANGE_DATA
);
96 ImplMoveFocus( sal_True
);
99 ImplCallEventListenersAndHandler( VCLEVENT_SPINBUTTON_UP
, maUpHdlLink
, this );
102 // -----------------------------------------------------------------------
104 void SpinButton::Down()
106 if ( ImplIsLowerEnabled() )
108 mnValue
-= mnValueStep
;
109 StateChanged( STATE_CHANGE_DATA
);
111 ImplMoveFocus( sal_False
);
114 ImplCallEventListenersAndHandler( VCLEVENT_SPINBUTTON_DOWN
, maDownHdlLink
, this );
117 // -----------------------------------------------------------------------
119 void SpinButton::Resize()
123 Size
aSize( GetOutputSizePixel() );
125 Rectangle
aRect( aTmpPoint
, aSize
);
128 maLowerRect
= Rectangle( 0, 0, aSize
.Width()/2, aSize
.Height()-1 );
129 maUpperRect
= Rectangle( maLowerRect
.TopRight(), aRect
.BottomRight() );
133 maUpperRect
= Rectangle( 0, 0, aSize
.Width()-1, aSize
.Height()/2 );
134 maLowerRect
= Rectangle( maUpperRect
.BottomLeft(), aRect
.BottomRight() );
137 ImplCalcFocusRect( ImplIsUpperEnabled() || !ImplIsLowerEnabled() );
142 // -----------------------------------------------------------------------
144 void SpinButton::Draw( OutputDevice
* pDev
, const Point
& rPos
, const Size
& rSize
, sal_uLong nFlags
)
146 Point aPos
= pDev
->LogicToPixel( rPos
);
147 Size aSize
= pDev
->LogicToPixel( rSize
);
151 if ( !(nFlags
& WINDOW_DRAW_MONO
) )
153 // DecoView uses the FaceColor...
154 AllSettings aSettings
= pDev
->GetSettings();
155 StyleSettings aStyleSettings
= aSettings
.GetStyleSettings();
156 if ( IsControlBackground() )
157 aStyleSettings
.SetFaceColor( GetControlBackground() );
159 aStyleSettings
.SetFaceColor( GetSettings().GetStyleSettings().GetFaceColor() );
161 aSettings
.SetStyleSettings( aStyleSettings
);
162 pDev
->SetSettings( aSettings
);
165 Rectangle
aRect( Point( 0, 0 ), aSize
);
166 Rectangle aLowerRect
, aUpperRect
;
169 aLowerRect
= Rectangle( 0, 0, aSize
.Width()/2, aSize
.Height()-1 );
170 aUpperRect
= Rectangle( aLowerRect
.TopRight(), aRect
.BottomRight() );
174 aUpperRect
= Rectangle( 0, 0, aSize
.Width()-1, aSize
.Height()/2 );
175 aLowerRect
= Rectangle( aUpperRect
.BottomLeft(), aRect
.BottomRight() );
181 ImplDrawSpinButton( pDev
, aUpperRect
, aLowerRect
, sal_False
, sal_False
,
182 IsEnabled() && ImplIsUpperEnabled(),
183 IsEnabled() && ImplIsLowerEnabled(), mbHorz
, sal_True
);
188 void SpinButton::Paint( const Rectangle
& )
192 sal_Bool bEnable
= IsEnabled();
193 ImplDrawSpinButton( this, maUpperRect
, maLowerRect
, mbUpperIn
, mbLowerIn
,
194 bEnable
&& ImplIsUpperEnabled(),
195 bEnable
&& ImplIsLowerEnabled(), mbHorz
, sal_True
);
198 ShowFocus( maFocusRect
);
201 // -----------------------------------------------------------------------
203 void SpinButton::MouseButtonDown( const MouseEvent
& rMEvt
)
205 if ( maUpperRect
.IsInside( rMEvt
.GetPosPixel() ) && ( ImplIsUpperEnabled() ) )
207 mbUpperIn
= sal_True
;
208 mbInitialUp
= sal_True
;
209 Invalidate( maUpperRect
);
211 else if ( maLowerRect
.IsInside( rMEvt
.GetPosPixel() ) && ( ImplIsLowerEnabled() ) )
213 mbLowerIn
= sal_True
;
214 mbInitialDown
= sal_True
;
215 Invalidate( maLowerRect
);
218 if ( mbUpperIn
|| mbLowerIn
)
223 maRepeatTimer
.Start();
227 // -----------------------------------------------------------------------
229 void SpinButton::MouseButtonUp( const MouseEvent
& )
234 maRepeatTimer
.Stop();
235 maRepeatTimer
.SetTimeout(GetSettings().GetMouseSettings().GetButtonStartRepeat() );
240 mbUpperIn
= sal_False
;
241 Invalidate( maUpperRect
);
245 else if ( mbLowerIn
)
247 mbLowerIn
= sal_False
;
248 Invalidate( maLowerRect
);
253 mbInitialUp
= mbInitialDown
= sal_False
;
256 // -----------------------------------------------------------------------
258 void SpinButton::MouseMove( const MouseEvent
& rMEvt
)
260 if ( !rMEvt
.IsLeft() || (!mbInitialUp
&& !mbInitialDown
) )
263 if ( !maUpperRect
.IsInside( rMEvt
.GetPosPixel() ) &&
264 mbUpperIn
&& mbInitialUp
)
266 mbUpperIn
= sal_False
;
267 maRepeatTimer
.Stop();
268 Invalidate( maUpperRect
);
271 else if ( !maLowerRect
.IsInside( rMEvt
.GetPosPixel() ) &&
272 mbLowerIn
& mbInitialDown
)
274 mbLowerIn
= sal_False
;
275 maRepeatTimer
.Stop();
276 Invalidate( maLowerRect
);
279 else if ( maUpperRect
.IsInside( rMEvt
.GetPosPixel() ) &&
280 !mbUpperIn
&& mbInitialUp
)
282 mbUpperIn
= sal_True
;
284 maRepeatTimer
.Start();
285 Invalidate( maUpperRect
);
288 else if ( maLowerRect
.IsInside( rMEvt
.GetPosPixel() ) &&
289 !mbLowerIn
&& mbInitialDown
)
291 mbLowerIn
= sal_True
;
293 maRepeatTimer
.Start();
294 Invalidate( maLowerRect
);
299 // -----------------------------------------------------------------------
301 void SpinButton::KeyInput( const KeyEvent
& rKEvt
)
303 if ( !rKEvt
.GetKeyCode().GetModifier() )
305 switch ( rKEvt
.GetKeyCode().GetCode() )
310 bool bUp
= KEY_RIGHT
== rKEvt
.GetKeyCode().GetCode();
311 if ( mbHorz
&& !ImplMoveFocus( bUp
) )
319 bool bUp
= KEY_UP
== rKEvt
.GetKeyCode().GetCode();
320 if ( !mbHorz
&& !ImplMoveFocus( KEY_UP
== rKEvt
.GetKeyCode().GetCode() ) )
326 mbUpperIsFocused
? Up() : Down();
330 Control::KeyInput( rKEvt
);
335 Control::KeyInput( rKEvt
);
338 // -----------------------------------------------------------------------
340 void SpinButton::StateChanged( StateChangedType nType
)
344 case STATE_CHANGE_DATA
:
345 case STATE_CHANGE_ENABLE
:
349 case STATE_CHANGE_STYLE
:
351 sal_Bool bNewRepeat
= 0 != ( GetStyle() & WB_REPEAT
);
352 if ( bNewRepeat
!= mbRepeat
)
354 if ( maRepeatTimer
.IsActive() )
356 maRepeatTimer
.Stop();
357 maRepeatTimer
.SetTimeout( GetSettings().GetMouseSettings().GetButtonStartRepeat() );
359 mbRepeat
= bNewRepeat
;
362 sal_Bool bNewHorz
= 0 != ( GetStyle() & WB_HSCROLL
);
363 if ( bNewHorz
!= mbHorz
)
372 Control::StateChanged( nType
);
375 // -----------------------------------------------------------------------
377 void SpinButton::SetRangeMin( long nNewRange
)
379 SetRange( Range( nNewRange
, GetRangeMax() ) );
382 // -----------------------------------------------------------------------
384 void SpinButton::SetRangeMax( long nNewRange
)
386 SetRange( Range( GetRangeMin(), nNewRange
) );
389 // -----------------------------------------------------------------------
391 void SpinButton::SetRange( const Range
& rRange
)
394 Range aRange
= rRange
;
396 long nNewMinRange
= aRange
.Min();
397 long nNewMaxRange
= aRange
.Max();
399 // do something only if old and new range differ
400 if ( (mnMinRange
!= nNewMinRange
) ||
401 (mnMaxRange
!= nNewMaxRange
) )
403 mnMinRange
= nNewMinRange
;
404 mnMaxRange
= nNewMaxRange
;
406 // adjust value to new range, if necessary
407 if ( mnValue
> mnMaxRange
)
408 mnValue
= mnMaxRange
;
409 if ( mnValue
< mnMinRange
)
410 mnValue
= mnMinRange
;
412 StateChanged( STATE_CHANGE_DATA
);
416 // -----------------------------------------------------------------------
418 void SpinButton::SetValue( long nValue
)
420 // adjust, if necessary
421 if ( nValue
> mnMaxRange
)
423 if ( nValue
< mnMinRange
)
426 if ( mnValue
!= nValue
)
429 StateChanged( STATE_CHANGE_DATA
);
433 // -----------------------------------------------------------------------
435 void SpinButton::GetFocus()
437 ShowFocus( maFocusRect
);
441 // -----------------------------------------------------------------------
443 void SpinButton::LoseFocus()
446 Control::LoseFocus();
449 // -----------------------------------------------------------------------
451 sal_Bool
SpinButton::ImplMoveFocus( sal_Bool _bUpper
)
453 if ( _bUpper
== mbUpperIsFocused
)
457 ImplCalcFocusRect( _bUpper
);
459 ShowFocus( maFocusRect
);
463 // -----------------------------------------------------------------------
465 void SpinButton::ImplCalcFocusRect( sal_Bool _bUpper
)
467 maFocusRect
= _bUpper
? maUpperRect
: maLowerRect
;
468 // inflate by some pixels
469 maFocusRect
.Left() += 2;
470 maFocusRect
.Top() += 2;
471 maFocusRect
.Right() -= 2;
472 maFocusRect
.Bottom() -= 2;
473 mbUpperIsFocused
= _bUpper
;
476 // -----------------------------------------------------------------------
478 Rectangle
* SpinButton::ImplFindPartRect( const Point
& rPt
)
480 if( maUpperRect
.IsInside( rPt
) )
482 else if( maLowerRect
.IsInside( rPt
) )
488 long SpinButton::PreNotify( NotifyEvent
& rNEvt
)
491 const MouseEvent
* pMouseEvt
= NULL
;
493 if( (rNEvt
.GetType() == EVENT_MOUSEMOVE
) && (pMouseEvt
= rNEvt
.GetMouseEvent()) != NULL
)
495 if( !pMouseEvt
->GetButtons() && !pMouseEvt
->IsSynthetic() && !pMouseEvt
->IsModifierChanged() )
497 // trigger redraw if mouse over state has changed
498 if( IsNativeControlSupported(CTRL_SPINBOX
, PART_ENTIRE_CONTROL
) ||
499 IsNativeControlSupported(CTRL_SPINBOX
, PART_ALL_BUTTONS
) )
501 Rectangle
* pRect
= ImplFindPartRect( GetPointerPosPixel() );
502 Rectangle
* pLastRect
= ImplFindPartRect( GetLastPointerPosPixel() );
503 if( pRect
!= pLastRect
|| (pMouseEvt
->IsLeaveWindow() || pMouseEvt
->IsEnterWindow()) )
505 Region
aRgn( GetActiveClipRegion() );
508 SetClipRegion(Region(*pLastRect
));
510 SetClipRegion( aRgn
);
514 SetClipRegion(Region(*pRect
));
516 SetClipRegion( aRgn
);
523 return nDone
? nDone
: Control::PreNotify(rNEvt
);
526 // -----------------------------------------------------------------------
528 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */