build fix: no comphelper/profilezone.hxx in this branch
[LibreOffice.git] / vcl / source / control / spinbtn.cxx
blob4c1a7085eb2bef51e3c15d82f7f0645152dfc109
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
25 #include "spin.hxx"
27 void SpinButton::ImplInit( vcl::Window* pParent, WinBits nStyle )
29 mbUpperIn = false;
30 mbLowerIn = false;
31 mbInitialUp = false;
32 mbInitialDown = false;
34 mnMinRange = 0;
35 mnMaxRange = 100;
36 mnValue = 0;
37 mnValueStep = 1;
39 maRepeatTimer.SetTimeout(GetSettings().GetMouseSettings().GetButtonStartRepeat());
40 maRepeatTimer.SetTimeoutHdl(LINK(this, SpinButton, ImplTimeout));
42 mbRepeat = 0 != (nStyle & WB_REPEAT);
44 if (nStyle & WB_HSCROLL)
45 mbHorz = true;
46 else
47 mbHorz = false;
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() );
64 pTimer->Start();
66 else
68 if (mbInitialUp)
69 Up();
70 else
71 Down();
75 void SpinButton::Up()
77 if (ImplIsUpperEnabled())
79 mnValue += mnValueStep;
80 CompatStateChanged(StateChangedType::Data);
82 ImplMoveFocus(true);
85 ImplCallEventListenersAndHandler(VCLEVENT_SPINBUTTON_UP, nullptr );
88 void SpinButton::Down()
90 if (ImplIsLowerEnabled())
92 mnValue -= mnValueStep;
93 CompatStateChanged(StateChangedType::Data);
95 ImplMoveFocus(false);
98 ImplCallEventListenersAndHandler(VCLEVENT_SPINBUTTON_DOWN, nullptr );
101 void SpinButton::Resize()
103 Control::Resize();
105 Size aSize(GetOutputSizePixel());
106 Point aTmpPoint;
107 Rectangle aRect(aTmpPoint, aSize);
108 if (mbHorz)
110 maLowerRect = Rectangle(0, 0, aSize.Width() / 2, aSize.Height() - 1);
111 maUpperRect = Rectangle(maLowerRect.TopRight(), aRect.BottomRight());
113 else
115 maUpperRect = Rectangle(0, 0, aSize.Width() - 1, aSize.Height() / 2);
116 maLowerRect = Rectangle(maUpperRect.BottomLeft(), aRect.BottomRight());
119 ImplCalcFocusRect(ImplIsUpperEnabled() || !ImplIsLowerEnabled());
121 Invalidate();
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);
129 pDev->Push();
130 pDev->SetMapMode();
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() );
138 else
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;
147 if ( mbHorz )
149 aLowerRect = Rectangle( 0, 0, aSize.Width()/2, aSize.Height()-1 );
150 aUpperRect = Rectangle( aLowerRect.TopRight(), aRect.BottomRight() );
152 else
154 aUpperRect = Rectangle( 0, 0, aSize.Width()-1, aSize.Height()/2 );
155 aLowerRect = Rectangle( aUpperRect.BottomLeft(), aRect.BottomRight() );
158 aUpperRect += aPos;
159 aLowerRect += aPos;
161 ImplDrawSpinButton(*pDev, this, aUpperRect, aLowerRect, false, false,
162 IsEnabled() && ImplIsUpperEnabled(),
163 IsEnabled() && ImplIsLowerEnabled(), mbHorz, true);
164 pDev->Pop();
167 void SpinButton::Paint(vcl::RenderContext& rRenderContext, const Rectangle& /*rRect*/)
169 HideFocus();
171 bool bEnable = IsEnabled();
172 ImplDrawSpinButton(rRenderContext, this, maUpperRect, maLowerRect, mbUpperIn, mbLowerIn,
173 bEnable && ImplIsUpperEnabled(),
174 bEnable && ImplIsLowerEnabled(), mbHorz, true);
176 if (HasFocus())
177 ShowFocus(maFocusRect);
180 void SpinButton::MouseButtonDown( const MouseEvent& rMEvt )
182 if ( maUpperRect.IsInside( rMEvt.GetPosPixel() ) && ( ImplIsUpperEnabled() ) )
184 mbUpperIn = true;
185 mbInitialUp = true;
186 Invalidate( maUpperRect );
188 else if ( maLowerRect.IsInside( rMEvt.GetPosPixel() ) && ( ImplIsLowerEnabled() ) )
190 mbLowerIn = true;
191 mbInitialDown = true;
192 Invalidate( maLowerRect );
195 if ( mbUpperIn || mbLowerIn )
197 Update();
198 CaptureMouse();
199 if ( mbRepeat )
200 maRepeatTimer.Start();
204 void SpinButton::MouseButtonUp( const MouseEvent& )
206 ReleaseMouse();
207 if ( mbRepeat )
209 maRepeatTimer.Stop();
210 maRepeatTimer.SetTimeout(GetSettings().GetMouseSettings().GetButtonStartRepeat() );
213 if ( mbUpperIn )
215 mbUpperIn = false;
216 Invalidate( maUpperRect );
217 Update();
218 Up();
220 else if ( mbLowerIn )
222 mbLowerIn = false;
223 Invalidate( maLowerRect );
224 Update();
225 Down();
228 mbInitialUp = mbInitialDown = false;
231 void SpinButton::MouseMove( const MouseEvent& rMEvt )
233 if ( !rMEvt.IsLeft() || (!mbInitialUp && !mbInitialDown) )
234 return;
236 if ( !maUpperRect.IsInside( rMEvt.GetPosPixel() ) &&
237 mbUpperIn && mbInitialUp )
239 mbUpperIn = false;
240 maRepeatTimer.Stop();
241 Invalidate( maUpperRect );
242 Update();
244 else if ( !maLowerRect.IsInside( rMEvt.GetPosPixel() ) &&
245 mbLowerIn && mbInitialDown )
247 mbLowerIn = false;
248 maRepeatTimer.Stop();
249 Invalidate( maLowerRect );
250 Update();
252 else if ( maUpperRect.IsInside( rMEvt.GetPosPixel() ) &&
253 !mbUpperIn && mbInitialUp )
255 mbUpperIn = true;
256 if ( mbRepeat )
257 maRepeatTimer.Start();
258 Invalidate( maUpperRect );
259 Update();
261 else if ( maLowerRect.IsInside( rMEvt.GetPosPixel() ) &&
262 !mbLowerIn && mbInitialDown )
264 mbLowerIn = true;
265 if ( mbRepeat )
266 maRepeatTimer.Start();
267 Invalidate( maLowerRect );
268 Update();
272 void SpinButton::KeyInput( const KeyEvent& rKEvt )
274 if ( !rKEvt.GetKeyCode().GetModifier() )
276 switch ( rKEvt.GetKeyCode().GetCode() )
278 case KEY_LEFT:
279 case KEY_RIGHT:
281 bool bUp = KEY_RIGHT == rKEvt.GetKeyCode().GetCode();
282 if ( mbHorz && !ImplMoveFocus( bUp ) )
283 bUp ? Up() : Down();
285 break;
287 case KEY_UP:
288 case KEY_DOWN:
290 bool bUp = KEY_UP == rKEvt.GetKeyCode().GetCode();
291 if ( !mbHorz && !ImplMoveFocus( KEY_UP == rKEvt.GetKeyCode().GetCode() ) )
292 bUp ? Up() : Down();
294 break;
296 case KEY_SPACE:
297 mbUpperIsFocused ? Up() : Down();
298 break;
300 default:
301 Control::KeyInput( rKEvt );
302 break;
305 else
306 Control::KeyInput( rKEvt );
309 void SpinButton::StateChanged( StateChangedType nType )
311 switch ( nType )
313 case StateChangedType::Data:
314 case StateChangedType::Enable:
315 Invalidate();
316 break;
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 )
334 mbHorz = bNewHorz;
335 Resize();
338 break;
339 default:;
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 )
357 // adjust rage
358 Range aRange = rRange;
359 aRange.Justify();
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 )
384 nValue = mnMaxRange;
385 if ( nValue < mnMinRange )
386 nValue = mnMinRange;
388 if ( mnValue != nValue )
390 mnValue = nValue;
391 CompatStateChanged( StateChangedType::Data );
395 void SpinButton::GetFocus()
397 ShowFocus( maFocusRect );
398 Control::GetFocus();
401 void SpinButton::LoseFocus()
403 HideFocus();
404 Control::LoseFocus();
407 bool SpinButton::ImplMoveFocus( bool _bUpper )
409 if ( _bUpper == mbUpperIsFocused )
410 return false;
412 HideFocus();
413 ImplCalcFocusRect( _bUpper );
414 if ( HasFocus() )
415 ShowFocus( maFocusRect );
416 return true;
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 ) )
433 return &maUpperRect;
434 else if( maLowerRect.IsInside( rPt ) )
435 return &maLowerRect;
436 else
437 return nullptr;
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());
457 if (pLastRect)
459 SetClipRegion(vcl::Region(*pLastRect));
460 Invalidate(*pLastRect);
461 SetClipRegion( aRgn );
463 if (pRect)
465 SetClipRegion(vcl::Region(*pRect));
466 Invalidate(*pRect);
467 SetClipRegion(aRgn);
474 return Control::PreNotify(rNEvt);
477 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */