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 <vcl/event.hxx>
21 #include <vcl/toolkit/spin.hxx>
22 #include <vcl/settings.hxx>
23 #include <vcl/vclevent.hxx>
27 void SpinButton::ImplInit( vcl::Window
* pParent
, WinBits nStyle
)
32 mbInitialDown
= false;
39 maRepeatTimer
.SetTimeout(MouseSettings::GetButtonStartRepeat());
40 maRepeatTimer
.SetInvokeHandler(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(WindowType::SPINBUTTON
)
54 , mbUpperIsFocused(false)
56 ImplInit(pParent
, nStyle
);
59 IMPL_LINK(SpinButton
, ImplTimeout
, Timer
*, pTimer
, void)
61 if (pTimer
->GetTimeout() == MouseSettings::GetButtonStartRepeat())
63 pTimer
->SetTimeout( GetSettings().GetMouseSettings().GetButtonRepeat() );
77 if (ImplIsUpperEnabled())
79 mnValue
+= mnValueStep
;
80 CompatStateChanged(StateChangedType::Data
);
85 ImplCallEventListenersAndHandler(VclEventId::SpinbuttonUp
, nullptr );
88 void SpinButton::Down()
90 if (ImplIsLowerEnabled())
92 mnValue
-= mnValueStep
;
93 CompatStateChanged(StateChangedType::Data
);
98 ImplCallEventListenersAndHandler(VclEventId::SpinbuttonDown
, nullptr );
101 void SpinButton::Resize()
105 Size
aSize(GetOutputSizePixel());
106 tools::Rectangle
aRect(Point(), aSize
);
109 maLowerRect
= tools::Rectangle(0, 0, aSize
.Width() / 2, aSize
.Height() - 1);
110 maUpperRect
= tools::Rectangle(maLowerRect
.TopRight(), aRect
.BottomRight());
114 maUpperRect
= tools::Rectangle(0, 0, aSize
.Width() - 1, aSize
.Height() / 2);
115 maLowerRect
= tools::Rectangle(maUpperRect
.BottomLeft(), aRect
.BottomRight());
118 ImplCalcFocusRect(ImplIsUpperEnabled() || !ImplIsLowerEnabled());
123 void SpinButton::Draw(OutputDevice
* pDev
, const Point
& rPos
, DrawFlags nFlags
)
125 Point aPos
= pDev
->LogicToPixel(rPos
);
126 Size aSize
= GetSizePixel();
130 if ( !(nFlags
& DrawFlags::Mono
) )
132 // DecoView uses the FaceColor...
133 AllSettings aSettings
= pDev
->GetSettings();
134 StyleSettings aStyleSettings
= aSettings
.GetStyleSettings();
135 if ( IsControlBackground() )
136 aStyleSettings
.SetFaceColor( GetControlBackground() );
138 aStyleSettings
.SetFaceColor( GetSettings().GetStyleSettings().GetFaceColor() );
140 aSettings
.SetStyleSettings( aStyleSettings
);
141 pDev
->SetSettings( aSettings
);
144 tools::Rectangle
aRect( Point( 0, 0 ), aSize
);
145 tools::Rectangle aLowerRect
, aUpperRect
;
148 aLowerRect
= tools::Rectangle( 0, 0, aSize
.Width()/2, aSize
.Height()-1 );
149 aUpperRect
= tools::Rectangle( aLowerRect
.TopRight(), aRect
.BottomRight() );
153 aUpperRect
= tools::Rectangle( 0, 0, aSize
.Width()-1, aSize
.Height()/2 );
154 aLowerRect
= tools::Rectangle( aUpperRect
.BottomLeft(), aRect
.BottomRight() );
160 ImplDrawSpinButton(*pDev
, this, aUpperRect
, aLowerRect
, false, false,
161 IsEnabled() && ImplIsUpperEnabled(),
162 IsEnabled() && ImplIsLowerEnabled(), mbHorz
, true);
166 void SpinButton::Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
& /*rRect*/)
170 bool bEnable
= IsEnabled();
171 ImplDrawSpinButton(rRenderContext
, this, maUpperRect
, maLowerRect
, mbUpperIn
, mbLowerIn
,
172 bEnable
&& ImplIsUpperEnabled(),
173 bEnable
&& ImplIsLowerEnabled(), mbHorz
, true);
176 ShowFocus(maFocusRect
);
179 void SpinButton::MouseButtonDown( const MouseEvent
& rMEvt
)
181 if ( maUpperRect
.IsInside( rMEvt
.GetPosPixel() ) && ( ImplIsUpperEnabled() ) )
185 Invalidate( maUpperRect
);
187 else if ( maLowerRect
.IsInside( rMEvt
.GetPosPixel() ) && ( ImplIsLowerEnabled() ) )
190 mbInitialDown
= true;
191 Invalidate( maLowerRect
);
194 if ( mbUpperIn
|| mbLowerIn
)
198 maRepeatTimer
.Start();
202 void SpinButton::MouseButtonUp( const MouseEvent
& )
207 maRepeatTimer
.Stop();
208 maRepeatTimer
.SetTimeout(MouseSettings::GetButtonStartRepeat() );
214 Invalidate( maUpperRect
);
217 else if ( mbLowerIn
)
220 Invalidate( maLowerRect
);
224 mbInitialUp
= mbInitialDown
= false;
227 void SpinButton::MouseMove( const MouseEvent
& rMEvt
)
229 if ( !rMEvt
.IsLeft() || (!mbInitialUp
&& !mbInitialDown
) )
232 if ( !maUpperRect
.IsInside( rMEvt
.GetPosPixel() ) &&
233 mbUpperIn
&& mbInitialUp
)
236 maRepeatTimer
.Stop();
237 Invalidate( maUpperRect
);
239 else if ( !maLowerRect
.IsInside( rMEvt
.GetPosPixel() ) &&
240 mbLowerIn
&& mbInitialDown
)
243 maRepeatTimer
.Stop();
244 Invalidate( maLowerRect
);
246 else if ( maUpperRect
.IsInside( rMEvt
.GetPosPixel() ) &&
247 !mbUpperIn
&& mbInitialUp
)
251 maRepeatTimer
.Start();
252 Invalidate( maUpperRect
);
254 else if ( maLowerRect
.IsInside( rMEvt
.GetPosPixel() ) &&
255 !mbLowerIn
&& mbInitialDown
)
259 maRepeatTimer
.Start();
260 Invalidate( maLowerRect
);
264 void SpinButton::KeyInput( const KeyEvent
& rKEvt
)
266 if ( !rKEvt
.GetKeyCode().GetModifier() )
268 switch ( rKEvt
.GetKeyCode().GetCode() )
273 bool bUp
= KEY_RIGHT
== rKEvt
.GetKeyCode().GetCode();
274 if ( mbHorz
&& !ImplMoveFocus( bUp
) )
282 bool bUp
= KEY_UP
== rKEvt
.GetKeyCode().GetCode();
283 if ( !mbHorz
&& !ImplMoveFocus( KEY_UP
== rKEvt
.GetKeyCode().GetCode() ) )
289 mbUpperIsFocused
? Up() : Down();
293 Control::KeyInput( rKEvt
);
298 Control::KeyInput( rKEvt
);
301 void SpinButton::StateChanged( StateChangedType nType
)
305 case StateChangedType::Data
:
306 case StateChangedType::Enable
:
310 case StateChangedType::Style
:
312 bool bNewRepeat
= 0 != ( GetStyle() & WB_REPEAT
);
313 if ( bNewRepeat
!= mbRepeat
)
315 if ( maRepeatTimer
.IsActive() )
317 maRepeatTimer
.Stop();
318 maRepeatTimer
.SetTimeout( MouseSettings::GetButtonStartRepeat() );
320 mbRepeat
= bNewRepeat
;
323 bool bNewHorz
= 0 != ( GetStyle() & WB_HSCROLL
);
324 if ( bNewHorz
!= mbHorz
)
334 Control::StateChanged( nType
);
337 void SpinButton::SetRangeMin( tools::Long nNewRange
)
339 SetRange( Range( nNewRange
, GetRangeMax() ) );
342 void SpinButton::SetRangeMax( tools::Long nNewRange
)
344 SetRange( Range( GetRangeMin(), nNewRange
) );
347 void SpinButton::SetRange( const Range
& rRange
)
350 Range aRange
= rRange
;
352 tools::Long nNewMinRange
= aRange
.Min();
353 tools::Long nNewMaxRange
= aRange
.Max();
355 // do something only if old and new range differ
356 if ( (mnMinRange
== nNewMinRange
) && (mnMaxRange
== nNewMaxRange
))
359 mnMinRange
= nNewMinRange
;
360 mnMaxRange
= nNewMaxRange
;
362 // adjust value to new range, if necessary
363 if ( mnValue
> mnMaxRange
)
364 mnValue
= mnMaxRange
;
365 if ( mnValue
< mnMinRange
)
366 mnValue
= mnMinRange
;
368 CompatStateChanged( StateChangedType::Data
);
371 void SpinButton::SetValue( tools::Long nValue
)
373 // adjust, if necessary
374 if ( nValue
> mnMaxRange
)
376 if ( nValue
< mnMinRange
)
379 if ( mnValue
!= nValue
)
382 CompatStateChanged( StateChangedType::Data
);
386 void SpinButton::GetFocus()
388 ShowFocus( maFocusRect
);
392 void SpinButton::LoseFocus()
395 Control::LoseFocus();
398 bool SpinButton::ImplMoveFocus( bool _bUpper
)
400 if ( _bUpper
== mbUpperIsFocused
)
404 ImplCalcFocusRect( _bUpper
);
406 ShowFocus( maFocusRect
);
410 void SpinButton::ImplCalcFocusRect( bool _bUpper
)
412 maFocusRect
= _bUpper
? maUpperRect
: maLowerRect
;
413 // inflate by some pixels
414 maFocusRect
.AdjustLeft(2 );
415 maFocusRect
.AdjustTop(2 );
416 maFocusRect
.AdjustRight( -2 );
417 maFocusRect
.AdjustBottom( -2 );
418 mbUpperIsFocused
= _bUpper
;
421 tools::Rectangle
* SpinButton::ImplFindPartRect( const Point
& rPt
)
423 if( maUpperRect
.IsInside( rPt
) )
425 else if( maLowerRect
.IsInside( rPt
) )
431 bool SpinButton::PreNotify( NotifyEvent
& rNEvt
)
433 if (rNEvt
.GetType() == MouseNotifyEvent::MOUSEMOVE
)
435 const MouseEvent
* pMouseEvt
= rNEvt
.GetMouseEvent();
436 if (pMouseEvt
&& !pMouseEvt
->GetButtons() && !pMouseEvt
->IsSynthetic() && !pMouseEvt
->IsModifierChanged())
438 // trigger redraw if mouse over state has changed
439 if (IsNativeControlSupported(ControlType::Spinbox
, ControlPart::Entire
) ||
440 IsNativeControlSupported(ControlType::Spinbox
, ControlPart::AllButtons
) )
442 tools::Rectangle
* pRect
= ImplFindPartRect( GetPointerPosPixel() );
443 tools::Rectangle
* pLastRect
= ImplFindPartRect( GetLastPointerPosPixel() );
444 if (pRect
!= pLastRect
|| (pMouseEvt
->IsLeaveWindow() || pMouseEvt
->IsEnterWindow()))
446 vcl::Region
aRgn(GetActiveClipRegion());
449 SetClipRegion(vcl::Region(*pLastRect
));
450 Invalidate(*pLastRect
);
451 SetClipRegion( aRgn
);
455 SetClipRegion(vcl::Region(*pRect
));
464 return Control::PreNotify(rNEvt
);
467 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */