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
, const Size
& rSize
, DrawFlags nFlags
)
125 Point aPos
= pDev
->LogicToPixel(rPos
);
126 Size aSize
= pDev
->LogicToPixel(rSize
);
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
)
199 maRepeatTimer
.Start();
203 void SpinButton::MouseButtonUp( const MouseEvent
& )
208 maRepeatTimer
.Stop();
209 maRepeatTimer
.SetTimeout(MouseSettings::GetButtonStartRepeat() );
215 Invalidate( maUpperRect
);
219 else if ( mbLowerIn
)
222 Invalidate( maLowerRect
);
227 mbInitialUp
= mbInitialDown
= false;
230 void SpinButton::MouseMove( const MouseEvent
& rMEvt
)
232 if ( !rMEvt
.IsLeft() || (!mbInitialUp
&& !mbInitialDown
) )
235 if ( !maUpperRect
.IsInside( rMEvt
.GetPosPixel() ) &&
236 mbUpperIn
&& mbInitialUp
)
239 maRepeatTimer
.Stop();
240 Invalidate( maUpperRect
);
243 else if ( !maLowerRect
.IsInside( rMEvt
.GetPosPixel() ) &&
244 mbLowerIn
&& mbInitialDown
)
247 maRepeatTimer
.Stop();
248 Invalidate( maLowerRect
);
251 else if ( maUpperRect
.IsInside( rMEvt
.GetPosPixel() ) &&
252 !mbUpperIn
&& mbInitialUp
)
256 maRepeatTimer
.Start();
257 Invalidate( maUpperRect
);
260 else if ( maLowerRect
.IsInside( rMEvt
.GetPosPixel() ) &&
261 !mbLowerIn
&& mbInitialDown
)
265 maRepeatTimer
.Start();
266 Invalidate( maLowerRect
);
271 void SpinButton::KeyInput( const KeyEvent
& rKEvt
)
273 if ( !rKEvt
.GetKeyCode().GetModifier() )
275 switch ( rKEvt
.GetKeyCode().GetCode() )
280 bool bUp
= KEY_RIGHT
== rKEvt
.GetKeyCode().GetCode();
281 if ( mbHorz
&& !ImplMoveFocus( bUp
) )
289 bool bUp
= KEY_UP
== rKEvt
.GetKeyCode().GetCode();
290 if ( !mbHorz
&& !ImplMoveFocus( KEY_UP
== rKEvt
.GetKeyCode().GetCode() ) )
296 mbUpperIsFocused
? Up() : Down();
300 Control::KeyInput( rKEvt
);
305 Control::KeyInput( rKEvt
);
308 void SpinButton::StateChanged( StateChangedType nType
)
312 case StateChangedType::Data
:
313 case StateChangedType::Enable
:
317 case StateChangedType::Style
:
319 bool bNewRepeat
= 0 != ( GetStyle() & WB_REPEAT
);
320 if ( bNewRepeat
!= mbRepeat
)
322 if ( maRepeatTimer
.IsActive() )
324 maRepeatTimer
.Stop();
325 maRepeatTimer
.SetTimeout( MouseSettings::GetButtonStartRepeat() );
327 mbRepeat
= bNewRepeat
;
330 bool bNewHorz
= 0 != ( GetStyle() & WB_HSCROLL
);
331 if ( bNewHorz
!= mbHorz
)
341 Control::StateChanged( nType
);
344 void SpinButton::SetRangeMin( long nNewRange
)
346 SetRange( Range( nNewRange
, GetRangeMax() ) );
349 void SpinButton::SetRangeMax( long nNewRange
)
351 SetRange( Range( GetRangeMin(), nNewRange
) );
354 void SpinButton::SetRange( const Range
& rRange
)
357 Range aRange
= rRange
;
359 long nNewMinRange
= aRange
.Min();
360 long nNewMaxRange
= aRange
.Max();
362 // do something only if old and new range differ
363 if ( (mnMinRange
!= nNewMinRange
) ||
364 (mnMaxRange
!= nNewMaxRange
) )
366 mnMinRange
= nNewMinRange
;
367 mnMaxRange
= nNewMaxRange
;
369 // adjust value to new range, if necessary
370 if ( mnValue
> mnMaxRange
)
371 mnValue
= mnMaxRange
;
372 if ( mnValue
< mnMinRange
)
373 mnValue
= mnMinRange
;
375 CompatStateChanged( StateChangedType::Data
);
379 void SpinButton::SetValue( long nValue
)
381 // adjust, if necessary
382 if ( nValue
> mnMaxRange
)
384 if ( nValue
< mnMinRange
)
387 if ( mnValue
!= nValue
)
390 CompatStateChanged( StateChangedType::Data
);
394 void SpinButton::GetFocus()
396 ShowFocus( maFocusRect
);
400 void SpinButton::LoseFocus()
403 Control::LoseFocus();
406 bool SpinButton::ImplMoveFocus( bool _bUpper
)
408 if ( _bUpper
== mbUpperIsFocused
)
412 ImplCalcFocusRect( _bUpper
);
414 ShowFocus( maFocusRect
);
418 void SpinButton::ImplCalcFocusRect( bool _bUpper
)
420 maFocusRect
= _bUpper
? maUpperRect
: maLowerRect
;
421 // inflate by some pixels
422 maFocusRect
.AdjustLeft(2 );
423 maFocusRect
.AdjustTop(2 );
424 maFocusRect
.AdjustRight( -2 );
425 maFocusRect
.AdjustBottom( -2 );
426 mbUpperIsFocused
= _bUpper
;
429 tools::Rectangle
* SpinButton::ImplFindPartRect( const Point
& rPt
)
431 if( maUpperRect
.IsInside( rPt
) )
433 else if( maLowerRect
.IsInside( rPt
) )
439 bool SpinButton::PreNotify( NotifyEvent
& rNEvt
)
441 const MouseEvent
* pMouseEvt
= nullptr;
443 if ((rNEvt
.GetType() == MouseNotifyEvent::MOUSEMOVE
) && (pMouseEvt
= rNEvt
.GetMouseEvent()) != nullptr)
445 if (!pMouseEvt
->GetButtons() && !pMouseEvt
->IsSynthetic() && !pMouseEvt
->IsModifierChanged())
447 // trigger redraw if mouse over state has changed
448 if (IsNativeControlSupported(ControlType::Spinbox
, ControlPart::Entire
) ||
449 IsNativeControlSupported(ControlType::Spinbox
, ControlPart::AllButtons
) )
451 tools::Rectangle
* pRect
= ImplFindPartRect( GetPointerPosPixel() );
452 tools::Rectangle
* pLastRect
= ImplFindPartRect( GetLastPointerPosPixel() );
453 if (pRect
!= pLastRect
|| (pMouseEvt
->IsLeaveWindow() || pMouseEvt
->IsEnterWindow()))
455 vcl::Region
aRgn(GetActiveClipRegion());
458 SetClipRegion(vcl::Region(*pLastRect
));
459 Invalidate(*pLastRect
);
460 SetClipRegion( aRgn
);
464 SetClipRegion(vcl::Region(*pRect
));
473 return Control::PreNotify(rNEvt
);
476 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */