build fix: no comphelper/profilezone.hxx in this branch
[LibreOffice.git] / vcl / source / control / slider.cxx
blob5a4947caa3d785b43cd17874f87a5523c0a5a4f5
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/rc.h>
21 #include <vcl/event.hxx>
22 #include <vcl/decoview.hxx>
23 #include <vcl/slider.hxx>
24 #include <vcl/settings.hxx>
26 #include "thumbpos.hxx"
28 #define SLIDER_STATE_CHANNEL1_DOWN ((sal_uInt16)0x0001)
29 #define SLIDER_STATE_CHANNEL2_DOWN ((sal_uInt16)0x0002)
30 #define SLIDER_STATE_THUMB_DOWN ((sal_uInt16)0x0004)
32 #define SLIDER_THUMB_SIZE 9
33 #define SLIDER_THUMB_HALFSIZE 4
34 #define SLIDER_CHANNEL_OFFSET 0
35 #define SLIDER_CHANNEL_SIZE 4
36 #define SLIDER_CHANNEL_HALFSIZE 2
38 #define SLIDER_HEIGHT 16
40 #define SLIDER_VIEW_STYLE (WB_3DLOOK | WB_HORZ | WB_VERT)
42 void Slider::ImplInit( vcl::Window* pParent, WinBits nStyle )
44 mnThumbPixOffset = 0;
45 mnThumbPixRange = 0;
46 mnThumbPixPos = 0; // between mnThumbPixOffset and mnThumbPixOffset+mnThumbPixRange
47 mnChannelPixOffset = 0;
48 mnChannelPixRange = 0;
49 mnChannelPixTop = 0;
50 mnChannelPixBottom = 0;
52 mnMinRange = 0;
53 mnMaxRange = 100;
54 mnThumbPos = 0;
55 mnLineSize = 1;
56 mnPageSize = 1;
57 mnDelta = 0;
58 mnStateFlags = 0;
59 meScrollType = ScrollType::DontKnow;
60 mbCalcSize = true;
61 mbFullDrag = true;
63 mpLinkedField = nullptr;
65 Control::ImplInit( pParent, nStyle, nullptr );
67 ImplInitSettings();
68 SetSizePixel( CalcWindowSizePixel() );
71 Slider::Slider( vcl::Window* pParent, WinBits nStyle ) :
72 Control(WINDOW_SLIDER)
74 ImplInit( pParent, nStyle );
77 Slider::~Slider()
79 disposeOnce();
82 void Slider::dispose()
84 mpLinkedField.clear();
85 Control::dispose();
88 void Slider::ImplInitSettings()
90 vcl::Window* pParent = GetParent();
91 if ( pParent->IsChildTransparentModeEnabled() && !IsControlBackground() )
93 EnableChildTransparentMode();
94 SetParentClipMode( ParentClipMode::NoClip );
95 SetPaintTransparent( true );
96 SetBackground();
98 else
100 EnableChildTransparentMode( false );
101 SetParentClipMode();
102 SetPaintTransparent( false );
104 if ( IsControlBackground() )
105 SetBackground( GetControlBackground() );
106 else
107 SetBackground( pParent->GetBackground() );
111 void Slider::ImplUpdateRects( bool bUpdate )
113 Rectangle aOldThumbRect = maThumbRect;
114 bool bInvalidateAll = false;
116 if ( mnThumbPixRange )
118 if ( GetStyle() & WB_HORZ )
120 maThumbRect.Left() = mnThumbPixPos-SLIDER_THUMB_HALFSIZE;
121 maThumbRect.Right() = maThumbRect.Left()+SLIDER_THUMB_SIZE-1;
122 if ( mnChannelPixOffset < maThumbRect.Left() )
124 maChannel1Rect.Left() = mnChannelPixOffset;
125 maChannel1Rect.Right() = maThumbRect.Left()-1;
126 maChannel1Rect.Top() = mnChannelPixTop;
127 maChannel1Rect.Bottom() = mnChannelPixBottom;
129 else
130 maChannel1Rect.SetEmpty();
131 if ( mnChannelPixOffset+mnChannelPixRange-1 > maThumbRect.Right() )
133 maChannel2Rect.Left() = maThumbRect.Right()+1;
134 maChannel2Rect.Right() = mnChannelPixOffset+mnChannelPixRange-1;
135 maChannel2Rect.Top() = mnChannelPixTop;
136 maChannel2Rect.Bottom() = mnChannelPixBottom;
138 else
139 maChannel2Rect.SetEmpty();
141 const Rectangle aControlRegion( Rectangle( Point(0,0), Size( SLIDER_THUMB_SIZE, 10 ) ) );
142 Rectangle aThumbBounds, aThumbContent;
143 if ( GetNativeControlRegion( ControlType::Slider, ControlPart::ThumbHorz,
144 aControlRegion, ControlState::NONE, ImplControlValue(), OUString(),
145 aThumbBounds, aThumbContent ) )
147 maThumbRect.Left() = mnThumbPixPos - aThumbBounds.GetWidth()/2;
148 maThumbRect.Right() = maThumbRect.Left() + aThumbBounds.GetWidth() - 1;
149 bInvalidateAll = true;
152 else
154 maThumbRect.Top() = mnThumbPixPos-SLIDER_THUMB_HALFSIZE;
155 maThumbRect.Bottom() = maThumbRect.Top()+SLIDER_THUMB_SIZE-1;
156 if ( mnChannelPixOffset < maThumbRect.Top() )
158 maChannel1Rect.Top() = mnChannelPixOffset;
159 maChannel1Rect.Bottom() = maThumbRect.Top()-1;
160 maChannel1Rect.Left() = mnChannelPixTop;
161 maChannel1Rect.Right() = mnChannelPixBottom;
163 else
164 maChannel1Rect.SetEmpty();
165 if ( mnChannelPixOffset+mnChannelPixRange-1 > maThumbRect.Bottom() )
167 maChannel2Rect.Top() = maThumbRect.Bottom()+1;
168 maChannel2Rect.Bottom() = mnChannelPixOffset+mnChannelPixRange-1;
169 maChannel2Rect.Left() = mnChannelPixTop;
170 maChannel2Rect.Right() = mnChannelPixBottom;
172 else
173 maChannel2Rect.SetEmpty();
175 const Rectangle aControlRegion( Rectangle( Point(0,0), Size( 10, SLIDER_THUMB_SIZE ) ) );
176 Rectangle aThumbBounds, aThumbContent;
177 if ( GetNativeControlRegion( ControlType::Slider, ControlPart::ThumbVert,
178 aControlRegion, ControlState::NONE, ImplControlValue(), OUString(),
179 aThumbBounds, aThumbContent ) )
181 maThumbRect.Top() = mnThumbPixPos - aThumbBounds.GetHeight()/2;
182 maThumbRect.Bottom() = maThumbRect.Top() + aThumbBounds.GetHeight() - 1;
183 bInvalidateAll = true;
187 else
189 maChannel1Rect.SetEmpty();
190 maChannel2Rect.SetEmpty();
191 maThumbRect.SetEmpty();
194 if ( bUpdate )
196 if ( aOldThumbRect != maThumbRect )
198 if( bInvalidateAll )
199 Invalidate(InvalidateFlags::NoChildren | InvalidateFlags::NoErase);
200 else
202 vcl::Region aInvalidRegion( aOldThumbRect );
203 aInvalidRegion.Union( maThumbRect );
205 if( !IsBackground() && GetParent() )
207 const Point aPos( GetPosPixel() );
208 aInvalidRegion.Move( aPos.X(), aPos.Y() );
209 GetParent()->Invalidate( aInvalidRegion, InvalidateFlags::Transparent | InvalidateFlags::Update );
211 else
212 Invalidate( aInvalidRegion );
218 void Slider::ImplUpdateLinkedField()
220 if (mpLinkedField)
221 mpLinkedField->SetValue(mnThumbPos);
224 long Slider::ImplCalcThumbPos( long nPixPos )
226 // calculate position
227 long nCalcThumbPos;
228 nCalcThumbPos = ImplMulDiv( nPixPos-mnThumbPixOffset, mnMaxRange-mnMinRange, mnThumbPixRange-1 );
229 nCalcThumbPos += mnMinRange;
230 return nCalcThumbPos;
233 long Slider::ImplCalcThumbPosPix( long nPos )
235 // calculate position
236 long nCalcThumbPos;
237 nCalcThumbPos = ImplMulDiv( nPos-mnMinRange, mnThumbPixRange-1, mnMaxRange-mnMinRange );
238 // at the beginning and end we try to display Slider correctly
239 if ( !nCalcThumbPos && (mnThumbPos > mnMinRange) )
240 nCalcThumbPos = 1;
241 if ( nCalcThumbPos &&
242 (nCalcThumbPos == mnThumbPixRange-1) &&
243 (mnThumbPos < mnMaxRange) )
244 nCalcThumbPos--;
245 return nCalcThumbPos+mnThumbPixOffset;
248 void Slider::ImplCalc( bool bUpdate )
250 bool bInvalidateAll = false;
252 if ( mbCalcSize )
254 long nOldChannelPixOffset = mnChannelPixOffset;
255 long nOldChannelPixRange = mnChannelPixRange;
256 long nOldChannelPixTop = mnChannelPixTop;
257 long nOldChannelPixBottom = mnChannelPixBottom;
258 long nCalcWidth;
259 long nCalcHeight;
261 maChannel1Rect.SetEmpty();
262 maChannel2Rect.SetEmpty();
263 maThumbRect.SetEmpty();
265 Size aSize = GetOutputSizePixel();
266 if ( GetStyle() & WB_HORZ )
268 nCalcWidth = aSize.Width();
269 nCalcHeight = aSize.Height();
270 maThumbRect.Top() = 0;
271 maThumbRect.Bottom()= aSize.Height()-1;
273 else
275 nCalcWidth = aSize.Height();
276 nCalcHeight = aSize.Width();
277 maThumbRect.Left() = 0;
278 maThumbRect.Right() = aSize.Width()-1;
281 if ( nCalcWidth >= SLIDER_THUMB_SIZE )
283 mnThumbPixOffset = SLIDER_THUMB_HALFSIZE;
284 mnThumbPixRange = nCalcWidth-(SLIDER_THUMB_HALFSIZE*2);
285 mnThumbPixPos = 0;
286 mnChannelPixOffset = SLIDER_CHANNEL_OFFSET;
287 mnChannelPixRange = nCalcWidth-(SLIDER_CHANNEL_OFFSET*2);
288 mnChannelPixTop = (nCalcHeight/2)-SLIDER_CHANNEL_HALFSIZE;
289 mnChannelPixBottom = mnChannelPixTop+SLIDER_CHANNEL_SIZE-1;
291 else
293 mnThumbPixRange = 0;
294 mnChannelPixRange = 0;
297 if ( (nOldChannelPixOffset != mnChannelPixOffset) ||
298 (nOldChannelPixRange != mnChannelPixRange) ||
299 (nOldChannelPixTop != mnChannelPixTop) ||
300 (nOldChannelPixBottom != mnChannelPixBottom) )
301 bInvalidateAll = true;
303 mbCalcSize = false;
306 if ( mnThumbPixRange )
307 mnThumbPixPos = ImplCalcThumbPosPix( mnThumbPos );
309 if ( bUpdate && bInvalidateAll )
311 Invalidate();
312 bUpdate = false;
314 ImplUpdateRects( bUpdate );
317 void Slider::ImplDraw(vcl::RenderContext& rRenderContext)
319 DecorationView aDecoView(&rRenderContext);
320 DrawButtonFlags nStyle;
321 const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
322 bool bEnabled = IsEnabled();
324 // do missing calculations
325 if (mbCalcSize)
326 ImplCalc(false);
328 ControlPart nPart = (GetStyle() & WB_HORZ) ? ControlPart::TrackHorzArea : ControlPart::TrackVertArea;
329 ControlState nState = (IsEnabled() ? ControlState::ENABLED : ControlState::NONE);
330 nState |= (HasFocus() ? ControlState::FOCUSED : ControlState::NONE);
331 SliderValue sldValue;
333 sldValue.mnMin = mnMinRange;
334 sldValue.mnMax = mnMaxRange;
335 sldValue.mnCur = mnThumbPos;
336 sldValue.maThumbRect = maThumbRect;
338 if (IsMouseOver())
340 if (maThumbRect.IsInside(GetPointerPosPixel()))
341 sldValue.mnThumbState |= ControlState::ROLLOVER;
344 const Rectangle aCtrlRegion(Point(0,0), GetOutputSizePixel());
345 bool bNativeOK = rRenderContext.DrawNativeControl(ControlType::Slider, nPart, aCtrlRegion, nState, sldValue, OUString());
346 if (bNativeOK)
347 return;
349 if (!maChannel1Rect.IsEmpty())
351 long nRectSize;
352 Rectangle aRect = maChannel1Rect;
353 rRenderContext.SetLineColor(rStyleSettings.GetShadowColor());
354 if (GetStyle() & WB_HORZ)
356 rRenderContext.DrawLine(aRect.TopLeft(), Point(aRect.Left(), aRect.Bottom() - 1));
357 rRenderContext.DrawLine(aRect.TopLeft(), aRect.TopRight());
359 else
361 rRenderContext.DrawLine(aRect.TopLeft(), Point(aRect.Right() - 1, aRect.Top()));
362 rRenderContext.DrawLine(aRect.TopLeft(), aRect.BottomLeft());
364 rRenderContext.SetLineColor(rStyleSettings.GetLightColor());
365 if (GetStyle() & WB_HORZ)
367 rRenderContext.DrawLine(aRect.BottomLeft(), aRect.BottomRight());
368 nRectSize = aRect.GetWidth();
370 else
372 rRenderContext.DrawLine(aRect.TopRight(), aRect.BottomRight());
373 nRectSize = aRect.GetHeight();
376 if (nRectSize > 1)
378 aRect.Left()++;
379 aRect.Top()++;
380 if (GetStyle() & WB_HORZ)
381 aRect.Bottom()--;
382 else
383 aRect.Right()--;
384 rRenderContext.SetLineColor();
385 if (mnStateFlags & SLIDER_STATE_CHANNEL1_DOWN)
386 rRenderContext.SetFillColor(rStyleSettings.GetShadowColor());
387 else
388 rRenderContext.SetFillColor(rStyleSettings.GetCheckedColor());
389 rRenderContext.DrawRect(aRect);
393 if (!maChannel2Rect.IsEmpty())
395 long nRectSize;
396 Rectangle aRect = maChannel2Rect;
397 rRenderContext.SetLineColor(rStyleSettings.GetLightColor());
398 if (GetStyle() & WB_HORZ)
400 rRenderContext.DrawLine(aRect.TopRight(), aRect.BottomRight());
401 rRenderContext.DrawLine(aRect.BottomLeft(), aRect.BottomRight());
402 nRectSize = aRect.GetWidth();
404 else
406 rRenderContext.DrawLine(aRect.BottomLeft(), aRect.BottomRight());
407 rRenderContext.DrawLine(aRect.TopRight(), aRect.BottomRight());
408 nRectSize = aRect.GetHeight();
411 if (nRectSize > 1)
413 rRenderContext.SetLineColor(rStyleSettings.GetShadowColor());
414 if (GetStyle() & WB_HORZ)
415 rRenderContext.DrawLine(aRect.TopLeft(), Point(aRect.Right() - 1, aRect.Top()));
416 else
417 rRenderContext.DrawLine(aRect.TopLeft(), Point(aRect.Left(), aRect.Bottom() - 1));
419 aRect.Right()--;
420 aRect.Bottom()--;
421 if (GetStyle() & WB_HORZ)
422 aRect.Top()++;
423 else
424 aRect.Left()++;
425 rRenderContext.SetLineColor();
426 if (mnStateFlags & SLIDER_STATE_CHANNEL2_DOWN)
427 rRenderContext.SetFillColor(rStyleSettings.GetShadowColor());
428 else
429 rRenderContext.SetFillColor(rStyleSettings.GetCheckedColor());
430 rRenderContext.DrawRect(aRect);
434 if (!maThumbRect.IsEmpty())
436 if (bEnabled)
438 nStyle = DrawButtonFlags::NONE;
439 if (mnStateFlags & SLIDER_STATE_THUMB_DOWN)
440 nStyle |= DrawButtonFlags::Pressed;
441 aDecoView.DrawButton(maThumbRect, nStyle);
443 else
445 rRenderContext.SetLineColor(rStyleSettings.GetShadowColor());
446 rRenderContext.SetFillColor(rStyleSettings.GetCheckedColor());
447 rRenderContext.DrawRect(maThumbRect);
452 bool Slider::ImplIsPageUp( const Point& rPos )
454 Size aSize = GetOutputSizePixel();
455 Rectangle aRect = maChannel1Rect;
456 if ( GetStyle() & WB_HORZ )
458 aRect.Top() = 0;
459 aRect.Bottom() = aSize.Height()-1;
461 else
463 aRect.Left() = 0;
464 aRect.Right() = aSize.Width()-1;
466 return aRect.IsInside( rPos );
469 bool Slider::ImplIsPageDown( const Point& rPos )
471 Size aSize = GetOutputSizePixel();
472 Rectangle aRect = maChannel2Rect;
473 if ( GetStyle() & WB_HORZ )
475 aRect.Top() = 0;
476 aRect.Bottom() = aSize.Height()-1;
478 else
480 aRect.Left() = 0;
481 aRect.Right() = aSize.Width()-1;
483 return aRect.IsInside( rPos );
486 long Slider::ImplSlide( long nNewPos, bool bCallEndSlide )
488 long nOldPos = mnThumbPos;
489 SetThumbPos( nNewPos );
490 long nDelta = mnThumbPos-nOldPos;
491 if ( nDelta )
493 mnDelta = nDelta;
494 Slide();
495 if ( bCallEndSlide )
496 EndSlide();
497 mnDelta = 0;
499 return nDelta;
502 long Slider::ImplDoAction( bool bCallEndSlide )
504 long nDelta = 0;
506 switch ( meScrollType )
508 case ScrollType::LineUp:
509 nDelta = ImplSlide( mnThumbPos-mnLineSize, bCallEndSlide );
510 break;
512 case ScrollType::LineDown:
513 nDelta = ImplSlide( mnThumbPos+mnLineSize, bCallEndSlide );
514 break;
516 case ScrollType::PageUp:
517 nDelta = ImplSlide( mnThumbPos-mnPageSize, bCallEndSlide );
518 break;
520 case ScrollType::PageDown:
521 nDelta = ImplSlide( mnThumbPos+mnPageSize, bCallEndSlide );
522 break;
524 case ScrollType::Set:
525 nDelta = ImplSlide( ImplCalcThumbPos( GetPointerPosPixel().X() ), bCallEndSlide );
526 break;
527 default:
528 break;
531 return nDelta;
534 void Slider::ImplDoMouseAction( const Point& rMousePos, bool bCallAction )
536 sal_uInt16 nOldStateFlags = mnStateFlags;
537 bool bAction = false;
539 switch ( meScrollType )
541 case ScrollType::Set:
543 const bool bUp = ImplIsPageUp( rMousePos ), bDown = ImplIsPageDown( rMousePos );
545 if ( bUp || bDown )
547 bAction = bCallAction;
548 mnStateFlags |= ( bUp ? SLIDER_STATE_CHANNEL1_DOWN : SLIDER_STATE_CHANNEL2_DOWN );
550 else
551 mnStateFlags &= ~( SLIDER_STATE_CHANNEL1_DOWN | SLIDER_STATE_CHANNEL2_DOWN );
552 break;
555 case ScrollType::PageUp:
556 if ( ImplIsPageUp( rMousePos ) )
558 bAction = bCallAction;
559 mnStateFlags |= SLIDER_STATE_CHANNEL1_DOWN;
561 else
562 mnStateFlags &= ~SLIDER_STATE_CHANNEL1_DOWN;
563 break;
565 case ScrollType::PageDown:
566 if ( ImplIsPageDown( rMousePos ) )
568 bAction = bCallAction;
569 mnStateFlags |= SLIDER_STATE_CHANNEL2_DOWN;
571 else
572 mnStateFlags &= ~SLIDER_STATE_CHANNEL2_DOWN;
573 break;
574 default:
575 break;
578 if ( bAction )
580 if ( ImplDoAction( false ) )
582 Update();
583 Invalidate();
586 else if ( nOldStateFlags != mnStateFlags )
588 Invalidate();
592 void Slider::ImplDoSlide( long nNewPos )
594 if ( meScrollType != ScrollType::DontKnow )
595 return;
597 meScrollType = ScrollType::Drag;
598 ImplSlide( nNewPos, true );
599 meScrollType = ScrollType::DontKnow;
602 void Slider::ImplDoSlideAction( ScrollType eScrollType )
604 if ( (meScrollType != ScrollType::DontKnow) ||
605 (eScrollType == ScrollType::DontKnow) ||
606 (eScrollType == ScrollType::Drag) )
607 return;
609 meScrollType = eScrollType;
610 ImplDoAction( true );
611 meScrollType = ScrollType::DontKnow;
614 void Slider::MouseButtonDown( const MouseEvent& rMEvt )
616 if ( rMEvt.IsLeft() )
618 const Point& rMousePos = rMEvt.GetPosPixel();
619 StartTrackingFlags nTrackFlags = StartTrackingFlags::NONE;
621 if ( maThumbRect.IsInside( rMousePos ) )
623 meScrollType = ScrollType::Drag;
625 // calculate additional values
626 Point aCenterPos = maThumbRect.Center();
627 if ( GetStyle() & WB_HORZ )
628 mnMouseOff = rMousePos.X()-aCenterPos.X();
629 else
630 mnMouseOff = rMousePos.Y()-aCenterPos.Y();
632 else if ( ImplIsPageUp( rMousePos ) )
634 if( GetStyle() & WB_SLIDERSET )
635 meScrollType = ScrollType::Set;
636 else
638 nTrackFlags = StartTrackingFlags::ButtonRepeat;
639 meScrollType = ScrollType::PageUp;
642 else if ( ImplIsPageDown( rMousePos ) )
644 if( GetStyle() & WB_SLIDERSET )
645 meScrollType = ScrollType::Set;
646 else
648 nTrackFlags = StartTrackingFlags::ButtonRepeat;
649 meScrollType = ScrollType::PageDown;
653 // Shall we start Tracking?
654 if( meScrollType != ScrollType::DontKnow )
656 // store Start position for cancel and EndScroll delta
657 mnStartPos = mnThumbPos;
658 ImplDoMouseAction( rMousePos, meScrollType != ScrollType::Set );
659 Update();
661 if( meScrollType != ScrollType::Set )
662 StartTracking( nTrackFlags );
667 void Slider::MouseButtonUp( const MouseEvent& )
669 if( ScrollType::Set == meScrollType )
671 // reset Button and PageRect state
672 const sal_uInt16 nOldStateFlags = mnStateFlags;
674 mnStateFlags &= ~( SLIDER_STATE_CHANNEL1_DOWN | SLIDER_STATE_CHANNEL2_DOWN | SLIDER_STATE_THUMB_DOWN );
676 if ( nOldStateFlags != mnStateFlags )
678 Invalidate(InvalidateFlags::NoChildren | InvalidateFlags::NoErase);
680 ImplDoAction( true );
681 meScrollType = ScrollType::DontKnow;
685 void Slider::Tracking( const TrackingEvent& rTEvt )
687 if ( rTEvt.IsTrackingEnded() )
689 // reset Button and PageRect state
690 sal_uInt16 nOldStateFlags = mnStateFlags;
691 mnStateFlags &= ~(SLIDER_STATE_CHANNEL1_DOWN | SLIDER_STATE_CHANNEL2_DOWN |
692 SLIDER_STATE_THUMB_DOWN);
693 if ( nOldStateFlags != mnStateFlags )
695 Invalidate(InvalidateFlags::NoChildren | InvalidateFlags::NoErase);
698 // on cancel, reset the previous Thumb position
699 if ( rTEvt.IsTrackingCanceled() )
701 long nOldPos = mnThumbPos;
702 SetThumbPos( mnStartPos );
703 mnDelta = mnThumbPos-nOldPos;
704 Slide();
707 if ( meScrollType == ScrollType::Drag )
709 // after dragging, recalculate to a rounded Thumb position
710 ImplCalc();
711 Update();
713 if ( !mbFullDrag && (mnStartPos != mnThumbPos) )
715 mnDelta = mnThumbPos-mnStartPos;
716 Slide();
717 mnDelta = 0;
721 mnDelta = mnThumbPos-mnStartPos;
722 EndSlide();
723 mnDelta = 0;
724 meScrollType = ScrollType::DontKnow;
726 else
728 const Point rMousePos = rTEvt.GetMouseEvent().GetPosPixel();
730 // special handling for dragging
731 if ( meScrollType == ScrollType::Drag )
733 long nMovePix;
734 Point aCenterPos = maThumbRect.Center();
735 if ( GetStyle() & WB_HORZ )
736 nMovePix = rMousePos.X()-(aCenterPos.X()+mnMouseOff);
737 else
738 nMovePix = rMousePos.Y()-(aCenterPos.Y()+mnMouseOff);
739 // only if the mouse moves in Scroll direction we have to act
740 if ( nMovePix )
742 mnThumbPixPos += nMovePix;
743 if ( mnThumbPixPos < mnThumbPixOffset )
744 mnThumbPixPos = mnThumbPixOffset;
745 if ( mnThumbPixPos > (mnThumbPixOffset+mnThumbPixRange-1) )
746 mnThumbPixPos = mnThumbPixOffset+mnThumbPixRange-1;
747 long nOldPos = mnThumbPos;
748 mnThumbPos = ImplCalcThumbPos( mnThumbPixPos );
749 if ( nOldPos != mnThumbPos )
751 ImplUpdateRects();
752 Update();
753 ImplUpdateLinkedField();
754 if ( mbFullDrag && (nOldPos != mnThumbPos) )
756 mnDelta = mnThumbPos-nOldPos;
757 Slide();
758 mnDelta = 0;
763 else
764 ImplDoMouseAction( rMousePos, rTEvt.IsTrackingRepeat() );
766 // end tracking if ScrollBar values indicate we are done
767 if ( !IsVisible() )
768 EndTracking();
772 void Slider::KeyInput( const KeyEvent& rKEvt )
774 if ( !rKEvt.GetKeyCode().GetModifier() )
776 switch ( rKEvt.GetKeyCode().GetCode() )
778 case KEY_HOME:
779 ImplDoSlide( GetRangeMin() );
780 break;
781 case KEY_END:
782 ImplDoSlide( GetRangeMax() );
783 break;
785 case KEY_LEFT:
786 case KEY_UP:
787 ImplDoSlideAction( ScrollType::LineUp );
788 break;
790 case KEY_RIGHT:
791 case KEY_DOWN:
792 ImplDoSlideAction( ScrollType::LineDown );
793 break;
795 case KEY_PAGEUP:
796 ImplDoSlideAction( ScrollType::PageUp );
797 break;
799 case KEY_PAGEDOWN:
800 ImplDoSlideAction( ScrollType::PageDown );
801 break;
803 default:
804 Control::KeyInput( rKEvt );
805 break;
808 else
809 Control::KeyInput( rKEvt );
812 void Slider::Paint(vcl::RenderContext& rRenderContext, const Rectangle& /*rRect*/)
814 ImplDraw(rRenderContext);
817 void Slider::Resize()
819 Control::Resize();
820 mbCalcSize = true;
821 if ( IsReallyVisible() )
822 ImplCalc( false );
823 Invalidate(InvalidateFlags::NoChildren | InvalidateFlags::NoErase);
826 void Slider::SetLinkedField(VclPtr<NumericField> const & pField)
828 if (mpLinkedField)
830 mpLinkedField->SetModifyHdl(Link<Edit&,void>());
831 mpLinkedField->SetUpHdl(Link<SpinField&,void>());
832 mpLinkedField->SetDownHdl(Link<SpinField&,void>());
833 mpLinkedField->SetFirstHdl(Link<SpinField&,void>());
834 mpLinkedField->SetLastHdl(Link<SpinField&,void>());
835 mpLinkedField->SetLoseFocusHdl(Link<Control&,void>());
837 mpLinkedField = pField;
838 if (mpLinkedField)
840 mpLinkedField->SetModifyHdl(LINK(this, Slider, LinkedFieldModifyHdl));
841 mpLinkedField->SetUpHdl(LINK(this, Slider, LinkedFieldSpinnerHdl));
842 mpLinkedField->SetDownHdl(LINK(this, Slider, LinkedFieldSpinnerHdl));
843 mpLinkedField->SetFirstHdl(LINK(this, Slider, LinkedFieldSpinnerHdl));
844 mpLinkedField->SetLastHdl(LINK(this, Slider, LinkedFieldSpinnerHdl));
845 mpLinkedField->SetLoseFocusHdl(LINK(this, Slider, LinkedFieldLoseFocusHdl));
849 IMPL_LINK_NOARG(Slider, LinkedFieldSpinnerHdl, SpinField&, void)
851 if (mpLinkedField)
852 SetThumbPos(mpLinkedField->GetValue());
854 IMPL_LINK_NOARG(Slider, LinkedFieldLoseFocusHdl, Control&, void)
856 if (mpLinkedField)
857 SetThumbPos(mpLinkedField->GetValue());
859 IMPL_LINK_NOARG(Slider, LinkedFieldModifyHdl, Edit&, void)
861 if (mpLinkedField)
862 SetThumbPos(mpLinkedField->GetValue());
865 void Slider::StateChanged( StateChangedType nType )
867 Control::StateChanged( nType );
869 if ( nType == StateChangedType::InitShow )
870 ImplCalc( false );
871 else if ( nType == StateChangedType::Data )
873 if ( IsReallyVisible() && IsUpdateMode() )
874 ImplCalc();
876 else if ( nType == StateChangedType::UpdateMode )
878 if ( IsReallyVisible() && IsUpdateMode() )
880 ImplCalc( false );
881 Invalidate();
884 else if ( nType == StateChangedType::Enable )
886 if ( IsReallyVisible() && IsUpdateMode() )
888 Invalidate();
891 else if ( nType == StateChangedType::Style )
893 if ( IsReallyVisible() && IsUpdateMode() )
895 if ( (GetPrevStyle() & SLIDER_VIEW_STYLE) !=
896 (GetStyle() & SLIDER_VIEW_STYLE) )
898 mbCalcSize = true;
899 ImplCalc( false );
900 Invalidate();
904 else if ( nType == StateChangedType::ControlBackground )
906 ImplInitSettings();
907 Invalidate();
911 void Slider::DataChanged( const DataChangedEvent& rDCEvt )
913 Control::DataChanged( rDCEvt );
915 if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
916 (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) )
918 ImplInitSettings();
919 Invalidate();
923 void Slider::Slide()
925 maSlideHdl.Call( this );
928 void Slider::EndSlide()
930 maEndSlideHdl.Call( this );
933 void Slider::SetRangeMin(long nNewRange)
935 SetRange(Range(nNewRange, GetRangeMax()));
938 void Slider::SetRangeMax(long nNewRange)
940 SetRange(Range(GetRangeMin(), nNewRange));
943 void Slider::SetRange( const Range& rRange )
945 // adjust Range
946 Range aRange = rRange;
947 aRange.Justify();
948 long nNewMinRange = aRange.Min();
949 long nNewMaxRange = aRange.Max();
951 // reset Range if different
952 if ( (mnMinRange != nNewMinRange) ||
953 (mnMaxRange != nNewMaxRange) )
955 mnMinRange = nNewMinRange;
956 mnMaxRange = nNewMaxRange;
958 // adjust Thumb
959 if ( mnThumbPos > mnMaxRange )
960 mnThumbPos = mnMaxRange;
961 if ( mnThumbPos < mnMinRange )
962 mnThumbPos = mnMinRange;
963 ImplUpdateLinkedField();
964 CompatStateChanged( StateChangedType::Data );
968 void Slider::SetThumbPos( long nNewThumbPos )
970 if ( nNewThumbPos < mnMinRange )
971 nNewThumbPos = mnMinRange;
972 if ( nNewThumbPos > mnMaxRange )
973 nNewThumbPos = mnMaxRange;
975 if ( mnThumbPos != nNewThumbPos )
977 mnThumbPos = nNewThumbPos;
978 ImplUpdateLinkedField();
979 CompatStateChanged( StateChangedType::Data );
983 Size Slider::CalcWindowSizePixel()
985 long nWidth = mnMaxRange-mnMinRange+(SLIDER_THUMB_HALFSIZE*2)+1;
986 long nHeight = SLIDER_HEIGHT;
987 Size aSize;
988 if ( GetStyle() & WB_HORZ )
990 aSize.Width() = nWidth;
991 aSize.Height() = nHeight;
993 else
995 aSize.Height() = nWidth;
996 aSize.Width() = nHeight;
998 return aSize;
1001 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */