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>
21 #include <vcl/event.hxx>
22 #include <vcl/spin.hxx>
23 #include <vcl/settings.hxx>
27 void SpinButton::ImplInit( vcl::Window
* pParent
, WinBits nStyle
)
32 mbInitialDown
= 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
, nullptr );
52 SpinButton::SpinButton( vcl::Window
* pParent
, WinBits nStyle
)
53 : Control(WINDOW_SPINBUTTON
)
54 , mbUpperIsFocused(false)
56 ImplInit(pParent
, nStyle
);
59 IMPL_LINK(SpinButton
, ImplTimeout
, Timer
*, pTimer
, void)
61 if (pTimer
->GetTimeout() == GetSettings().GetMouseSettings().GetButtonStartRepeat())
63 pTimer
->SetTimeout( GetSettings().GetMouseSettings().GetButtonRepeat() );
77 if (ImplIsUpperEnabled())
79 mnValue
+= mnValueStep
;
80 CompatStateChanged(StateChangedType::Data
);
85 ImplCallEventListenersAndHandler(VCLEVENT_SPINBUTTON_UP
, nullptr );
88 void SpinButton::Down()
90 if (ImplIsLowerEnabled())
92 mnValue
-= mnValueStep
;
93 CompatStateChanged(StateChangedType::Data
);
98 ImplCallEventListenersAndHandler(VCLEVENT_SPINBUTTON_DOWN
, nullptr );
101 void SpinButton::Resize()
105 Size
aSize(GetOutputSizePixel());
107 Rectangle
aRect(aTmpPoint
, aSize
);
110 maLowerRect
= Rectangle(0, 0, aSize
.Width() / 2, aSize
.Height() - 1);
111 maUpperRect
= Rectangle(maLowerRect
.TopRight(), aRect
.BottomRight());
115 maUpperRect
= Rectangle(0, 0, aSize
.Width() - 1, aSize
.Height() / 2);
116 maLowerRect
= Rectangle(maUpperRect
.BottomLeft(), aRect
.BottomRight());
119 ImplCalcFocusRect(ImplIsUpperEnabled() || !ImplIsLowerEnabled());
124 void SpinButton::Draw(OutputDevice
* pDev
, const Point
& rPos
, const Size
& rSize
, DrawFlags nFlags
)
126 Point aPos
= pDev
->LogicToPixel(rPos
);
127 Size aSize
= pDev
->LogicToPixel(rSize
);
131 if ( !(nFlags
& DrawFlags::Mono
) )
133 // DecoView uses the FaceColor...
134 AllSettings aSettings
= pDev
->GetSettings();
135 StyleSettings aStyleSettings
= aSettings
.GetStyleSettings();
136 if ( IsControlBackground() )
137 aStyleSettings
.SetFaceColor( GetControlBackground() );
139 aStyleSettings
.SetFaceColor( GetSettings().GetStyleSettings().GetFaceColor() );
141 aSettings
.SetStyleSettings( aStyleSettings
);
142 pDev
->SetSettings( aSettings
);
145 Rectangle
aRect( Point( 0, 0 ), aSize
);
146 Rectangle aLowerRect
, aUpperRect
;
149 aLowerRect
= Rectangle( 0, 0, aSize
.Width()/2, aSize
.Height()-1 );
150 aUpperRect
= Rectangle( aLowerRect
.TopRight(), aRect
.BottomRight() );
154 aUpperRect
= Rectangle( 0, 0, aSize
.Width()-1, aSize
.Height()/2 );
155 aLowerRect
= Rectangle( aUpperRect
.BottomLeft(), aRect
.BottomRight() );
161 ImplDrawSpinButton(*pDev
, this, aUpperRect
, aLowerRect
, false, false,
162 IsEnabled() && ImplIsUpperEnabled(),
163 IsEnabled() && ImplIsLowerEnabled(), mbHorz
, true);
167 void SpinButton::Paint(vcl::RenderContext
& rRenderContext
, const Rectangle
& /*rRect*/)
171 bool bEnable
= IsEnabled();
172 ImplDrawSpinButton(rRenderContext
, this, maUpperRect
, maLowerRect
, mbUpperIn
, mbLowerIn
,
173 bEnable
&& ImplIsUpperEnabled(),
174 bEnable
&& ImplIsLowerEnabled(), mbHorz
, true);
177 ShowFocus(maFocusRect
);
180 void SpinButton::MouseButtonDown( const MouseEvent
& rMEvt
)
182 if ( maUpperRect
.IsInside( rMEvt
.GetPosPixel() ) && ( ImplIsUpperEnabled() ) )
186 Invalidate( maUpperRect
);
188 else if ( maLowerRect
.IsInside( rMEvt
.GetPosPixel() ) && ( ImplIsLowerEnabled() ) )
191 mbInitialDown
= true;
192 Invalidate( maLowerRect
);
195 if ( mbUpperIn
|| mbLowerIn
)
200 maRepeatTimer
.Start();
204 void SpinButton::MouseButtonUp( const MouseEvent
& )
209 maRepeatTimer
.Stop();
210 maRepeatTimer
.SetTimeout(GetSettings().GetMouseSettings().GetButtonStartRepeat() );
216 Invalidate( maUpperRect
);
220 else if ( mbLowerIn
)
223 Invalidate( maLowerRect
);
228 mbInitialUp
= mbInitialDown
= false;
231 void SpinButton::MouseMove( const MouseEvent
& rMEvt
)
233 if ( !rMEvt
.IsLeft() || (!mbInitialUp
&& !mbInitialDown
) )
236 if ( !maUpperRect
.IsInside( rMEvt
.GetPosPixel() ) &&
237 mbUpperIn
&& mbInitialUp
)
240 maRepeatTimer
.Stop();
241 Invalidate( maUpperRect
);
244 else if ( !maLowerRect
.IsInside( rMEvt
.GetPosPixel() ) &&
245 mbLowerIn
&& mbInitialDown
)
248 maRepeatTimer
.Stop();
249 Invalidate( maLowerRect
);
252 else if ( maUpperRect
.IsInside( rMEvt
.GetPosPixel() ) &&
253 !mbUpperIn
&& mbInitialUp
)
257 maRepeatTimer
.Start();
258 Invalidate( maUpperRect
);
261 else if ( maLowerRect
.IsInside( rMEvt
.GetPosPixel() ) &&
262 !mbLowerIn
&& mbInitialDown
)
266 maRepeatTimer
.Start();
267 Invalidate( maLowerRect
);
272 void SpinButton::KeyInput( const KeyEvent
& rKEvt
)
274 if ( !rKEvt
.GetKeyCode().GetModifier() )
276 switch ( rKEvt
.GetKeyCode().GetCode() )
281 bool bUp
= KEY_RIGHT
== rKEvt
.GetKeyCode().GetCode();
282 if ( mbHorz
&& !ImplMoveFocus( bUp
) )
290 bool bUp
= KEY_UP
== rKEvt
.GetKeyCode().GetCode();
291 if ( !mbHorz
&& !ImplMoveFocus( KEY_UP
== rKEvt
.GetKeyCode().GetCode() ) )
297 mbUpperIsFocused
? Up() : Down();
301 Control::KeyInput( rKEvt
);
306 Control::KeyInput( rKEvt
);
309 void SpinButton::StateChanged( StateChangedType nType
)
313 case StateChangedType::Data
:
314 case StateChangedType::Enable
:
318 case StateChangedType::Style
:
320 bool bNewRepeat
= 0 != ( GetStyle() & WB_REPEAT
);
321 if ( bNewRepeat
!= mbRepeat
)
323 if ( maRepeatTimer
.IsActive() )
325 maRepeatTimer
.Stop();
326 maRepeatTimer
.SetTimeout( GetSettings().GetMouseSettings().GetButtonStartRepeat() );
328 mbRepeat
= bNewRepeat
;
331 bool bNewHorz
= 0 != ( GetStyle() & WB_HSCROLL
);
332 if ( bNewHorz
!= mbHorz
)
342 Control::StateChanged( nType
);
345 void SpinButton::SetRangeMin( long nNewRange
)
347 SetRange( Range( nNewRange
, GetRangeMax() ) );
350 void SpinButton::SetRangeMax( long nNewRange
)
352 SetRange( Range( GetRangeMin(), nNewRange
) );
355 void SpinButton::SetRange( const Range
& rRange
)
358 Range aRange
= rRange
;
360 long nNewMinRange
= aRange
.Min();
361 long nNewMaxRange
= aRange
.Max();
363 // do something only if old and new range differ
364 if ( (mnMinRange
!= nNewMinRange
) ||
365 (mnMaxRange
!= nNewMaxRange
) )
367 mnMinRange
= nNewMinRange
;
368 mnMaxRange
= nNewMaxRange
;
370 // adjust value to new range, if necessary
371 if ( mnValue
> mnMaxRange
)
372 mnValue
= mnMaxRange
;
373 if ( mnValue
< mnMinRange
)
374 mnValue
= mnMinRange
;
376 CompatStateChanged( StateChangedType::Data
);
380 void SpinButton::SetValue( long nValue
)
382 // adjust, if necessary
383 if ( nValue
> mnMaxRange
)
385 if ( nValue
< mnMinRange
)
388 if ( mnValue
!= nValue
)
391 CompatStateChanged( StateChangedType::Data
);
395 void SpinButton::GetFocus()
397 ShowFocus( maFocusRect
);
401 void SpinButton::LoseFocus()
404 Control::LoseFocus();
407 bool SpinButton::ImplMoveFocus( bool _bUpper
)
409 if ( _bUpper
== mbUpperIsFocused
)
413 ImplCalcFocusRect( _bUpper
);
415 ShowFocus( maFocusRect
);
419 void SpinButton::ImplCalcFocusRect( bool _bUpper
)
421 maFocusRect
= _bUpper
? maUpperRect
: maLowerRect
;
422 // inflate by some pixels
423 maFocusRect
.Left() += 2;
424 maFocusRect
.Top() += 2;
425 maFocusRect
.Right() -= 2;
426 maFocusRect
.Bottom() -= 2;
427 mbUpperIsFocused
= _bUpper
;
430 Rectangle
* SpinButton::ImplFindPartRect( const Point
& rPt
)
432 if( maUpperRect
.IsInside( rPt
) )
434 else if( maLowerRect
.IsInside( rPt
) )
440 bool SpinButton::PreNotify( NotifyEvent
& rNEvt
)
442 const MouseEvent
* pMouseEvt
= nullptr;
444 if ((rNEvt
.GetType() == MouseNotifyEvent::MOUSEMOVE
) && (pMouseEvt
= rNEvt
.GetMouseEvent()) != nullptr)
446 if (!pMouseEvt
->GetButtons() && !pMouseEvt
->IsSynthetic() && !pMouseEvt
->IsModifierChanged())
448 // trigger redraw if mouse over state has changed
449 if (IsNativeControlSupported(ControlType::Spinbox
, ControlPart::Entire
) ||
450 IsNativeControlSupported(ControlType::Spinbox
, ControlPart::AllButtons
) )
452 Rectangle
* pRect
= ImplFindPartRect( GetPointerPosPixel() );
453 Rectangle
* pLastRect
= ImplFindPartRect( GetLastPointerPosPixel() );
454 if (pRect
!= pLastRect
|| (pMouseEvt
->IsLeaveWindow() || pMouseEvt
->IsEnterWindow()))
456 vcl::Region
aRgn(GetActiveClipRegion());
459 SetClipRegion(vcl::Region(*pLastRect
));
460 Invalidate(*pLastRect
);
461 SetClipRegion( aRgn
);
465 SetClipRegion(vcl::Region(*pRect
));
474 return Control::PreNotify(rNEvt
);
477 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */