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/decoview.hxx>
22 #include <vcl/timer.hxx>
23 #include <vcl/settings.hxx>
24 #include <vcl/toolkit/scrbar.hxx>
25 #include <vcl/vclevent.hxx>
27 #include <sal/log.hxx>
30 HACK: for scrollbars in case of thumb rect, page up and page down rect we
31 abuse the HitTestNativeScrollbar interface. All theming engines but macOS
32 are actually able to draw the thumb according to our internal representation.
33 However macOS draws a little outside. The canonical way would be to enhance the
34 HitTestNativeScrollbar passing a ScrollbarValue additionally so all necessary
35 information is available in the call.
37 However since there is only this one small exception we will deviate a little and
38 instead pass the respective rect as control region to allow for a small correction.
40 So all places using HitTestNativeScrollbar on ControlPart::ThumbHorz, ControlPart::ThumbVert,
41 ControlPart::TrackHorzLeft, ControlPart::TrackHorzRight, ControlPart::TrackVertUpper, ControlPart::TrackVertLower
42 do not use the control rectangle as region but the actual part rectangle, making
43 only small deviations feasible.
46 #include "thumbpos.hxx"
48 #define SCRBAR_DRAW_BTN1 (sal_uInt16(0x0001))
49 #define SCRBAR_DRAW_BTN2 (sal_uInt16(0x0002))
50 #define SCRBAR_DRAW_PAGE1 (sal_uInt16(0x0004))
51 #define SCRBAR_DRAW_PAGE2 (sal_uInt16(0x0008))
52 #define SCRBAR_DRAW_THUMB (sal_uInt16(0x0010))
53 #define SCRBAR_DRAW_BACKGROUND (sal_uInt16(0x0020))
55 #define SCRBAR_STATE_BTN1_DOWN (sal_uInt16(0x0001))
56 #define SCRBAR_STATE_BTN1_DISABLE (sal_uInt16(0x0002))
57 #define SCRBAR_STATE_BTN2_DOWN (sal_uInt16(0x0004))
58 #define SCRBAR_STATE_BTN2_DISABLE (sal_uInt16(0x0008))
59 #define SCRBAR_STATE_PAGE1_DOWN (sal_uInt16(0x0010))
60 #define SCRBAR_STATE_PAGE2_DOWN (sal_uInt16(0x0020))
61 #define SCRBAR_STATE_THUMB_DOWN (sal_uInt16(0x0040))
63 #define SCRBAR_VIEW_STYLE (WB_3DLOOK | WB_HORZ | WB_VERT)
65 struct ImplScrollBarData
67 AutoTimer maTimer
{ "vcl::ScrollBar mpData->maTimer" };
71 void ScrollBar::ImplInit( vcl::Window
* pParent
, WinBits nStyle
)
85 meScrollType
= ScrollType::DontKnow
;
90 ImplInitStyle( nStyle
);
91 Control::ImplInit( pParent
, nStyle
, nullptr );
93 tools::Long nScrollSize
= GetSettings().GetStyleSettings().GetScrollBarSize();
94 SetSizePixel( Size( nScrollSize
, nScrollSize
) );
97 void ScrollBar::ImplInitStyle( WinBits nStyle
)
99 if ( nStyle
& WB_DRAG
)
102 mbFullDrag
= bool(GetSettings().GetStyleSettings().GetDragFullOptions() & DragFullOptions::Scroll
);
105 ScrollBar::ScrollBar( vcl::Window
* pParent
, WinBits nStyle
) :
106 Control( WindowType::SCROLLBAR
)
108 ImplInit( pParent
, nStyle
);
111 ScrollBar::~ScrollBar()
116 void ScrollBar::dispose()
122 void ScrollBar::ImplUpdateRects( bool bUpdate
)
124 mnStateFlags
&= ~SCRBAR_STATE_BTN1_DISABLE
;
125 mnStateFlags
&= ~SCRBAR_STATE_BTN2_DISABLE
;
127 if ( mnThumbPixRange
)
129 if ( GetStyle() & WB_HORZ
)
131 maThumbRect
.SetLeft( maTrackRect
.Left()+mnThumbPixPos
);
132 maThumbRect
.SetRight( maThumbRect
.Left()+mnThumbPixSize
-1 );
133 if ( !mnThumbPixPos
)
134 maPage1Rect
.SetWidthEmpty();
136 maPage1Rect
.SetRight( maThumbRect
.Left()-1 );
137 if ( mnThumbPixPos
>= (mnThumbPixRange
-mnThumbPixSize
) )
138 maPage2Rect
.SetWidthEmpty();
141 maPage2Rect
.SetLeft( maThumbRect
.Right()+1 );
142 maPage2Rect
.SetRight( maTrackRect
.Right() );
147 maThumbRect
.SetTop( maTrackRect
.Top()+mnThumbPixPos
);
148 maThumbRect
.SetBottom( maThumbRect
.Top()+mnThumbPixSize
-1 );
149 if ( !mnThumbPixPos
)
150 maPage1Rect
.SetHeightEmpty();
152 maPage1Rect
.SetBottom( maThumbRect
.Top()-1 );
153 if ( mnThumbPixPos
>= (mnThumbPixRange
-mnThumbPixSize
) )
154 maPage2Rect
.SetHeightEmpty();
157 maPage2Rect
.SetTop( maThumbRect
.Bottom()+1 );
158 maPage2Rect
.SetBottom( maTrackRect
.Bottom() );
164 if ( GetStyle() & WB_HORZ
)
166 const tools::Long nSpace
= maTrackRect
.Right() - maTrackRect
.Left();
169 maPage1Rect
.SetLeft( maTrackRect
.Left() );
170 maPage1Rect
.SetRight( maTrackRect
.Left() + (nSpace
/2) );
171 maPage2Rect
.SetLeft( maPage1Rect
.Right() + 1 );
172 maPage2Rect
.SetRight( maTrackRect
.Right() );
177 const tools::Long nSpace
= maTrackRect
.Bottom() - maTrackRect
.Top();
180 maPage1Rect
.SetTop( maTrackRect
.Top() );
181 maPage1Rect
.SetBottom( maTrackRect
.Top() + (nSpace
/2) );
182 maPage2Rect
.SetTop( maPage1Rect
.Bottom() + 1 );
183 maPage2Rect
.SetBottom( maTrackRect
.Bottom() );
188 if( !IsNativeControlSupported(ControlType::Scrollbar
, ControlPart::Entire
) )
190 // disable scrollbar buttons only in VCL's own 'theme'
191 // as it is uncommon on other platforms
192 if ( mnThumbPos
== mnMinRange
)
193 mnStateFlags
|= SCRBAR_STATE_BTN1_DISABLE
;
194 if ( mnThumbPos
>= (mnMaxRange
-mnVisibleSize
) )
195 mnStateFlags
|= SCRBAR_STATE_BTN2_DISABLE
;
204 tools::Long
ScrollBar::ImplCalcThumbPos( tools::Long nPixPos
) const
206 // Calculate position
207 tools::Long nCalcThumbPos
;
208 nCalcThumbPos
= ImplMulDiv( nPixPos
, mnMaxRange
-mnVisibleSize
-mnMinRange
,
209 mnThumbPixRange
-mnThumbPixSize
);
210 nCalcThumbPos
+= mnMinRange
;
211 return nCalcThumbPos
;
214 tools::Long
ScrollBar::ImplCalcThumbPosPix( tools::Long nPos
) const
216 tools::Long nCalcThumbPos
;
218 // Calculate position
219 nCalcThumbPos
= ImplMulDiv( nPos
-mnMinRange
, mnThumbPixRange
-mnThumbPixSize
,
220 mnMaxRange
-mnVisibleSize
-mnMinRange
);
222 // At the start and end of the ScrollBar, we try to show the display correctly
223 if ( !nCalcThumbPos
&& (mnThumbPos
> mnMinRange
) )
225 if ( nCalcThumbPos
&&
226 ((nCalcThumbPos
+mnThumbPixSize
) >= mnThumbPixRange
) &&
227 (mnThumbPos
< (mnMaxRange
-mnVisibleSize
)) )
230 return nCalcThumbPos
;
233 void ScrollBar::ImplCalc( bool bUpdate
)
235 const Size aSize
= GetOutputSizePixel();
236 const tools::Long nMinThumbSize
= GetSettings().GetStyleSettings().GetMinThumbSize();
240 Size aOldSize
= getCurrentCalcSize();
242 const tools::Rectangle
aControlRegion( Point(0,0), aSize
);
243 tools::Rectangle aBtn1Region
, aBtn2Region
, aTrackRegion
, aBoundingRegion
;
244 const bool bSwapArrows
= mbSwapArrows
|| IsRTLEnabled();
246 // reset rectangles to empty *and* (0,0) position
247 maThumbRect
= tools::Rectangle();
248 maPage1Rect
= tools::Rectangle();
249 maPage2Rect
= tools::Rectangle();
251 if ( GetStyle() & WB_HORZ
)
253 if ( GetNativeControlRegion( ControlType::Scrollbar
, bSwapArrows
? ControlPart::ButtonRight
: ControlPart::ButtonLeft
,
254 aControlRegion
, ControlState::NONE
, ImplControlValue(), aBoundingRegion
, aBtn1Region
) &&
255 GetNativeControlRegion( ControlType::Scrollbar
, bSwapArrows
? ControlPart::ButtonLeft
: ControlPart::ButtonRight
,
256 aControlRegion
, ControlState::NONE
, ImplControlValue(), aBoundingRegion
, aBtn2Region
) )
258 maBtn1Rect
= aBtn1Region
;
259 maBtn2Rect
= aBtn2Region
;
263 Size
aBtnSize( aSize
.Height(), aSize
.Height() );
264 maBtn2Rect
.SetTop( maBtn1Rect
.Top() );
265 maBtn2Rect
.SetLeft( aSize
.Width()-aSize
.Height() );
266 maBtn1Rect
.SetSize( aBtnSize
);
267 maBtn2Rect
.SetSize( aBtnSize
);
270 if ( GetNativeControlRegion( ControlType::Scrollbar
, ControlPart::TrackHorzArea
,
271 aControlRegion
, ControlState::NONE
, ImplControlValue(), aBoundingRegion
, aTrackRegion
) )
272 maTrackRect
= aTrackRegion
;
274 maTrackRect
= tools::Rectangle::Normalize( maBtn1Rect
.TopRight(), maBtn2Rect
.BottomLeft() );
276 // Check if available space is big enough for thumb ( min thumb size = ScrBar width/height )
277 mnThumbPixRange
= maTrackRect
.Right() - maTrackRect
.Left();
278 if( mnThumbPixRange
> 0 )
280 maPage1Rect
.SetLeft( maTrackRect
.Left() );
281 maPage1Rect
.SetBottom( maTrackRect
.Bottom() );
282 maPage2Rect
.SetBottom (maTrackRect
.Bottom() );
283 maThumbRect
.SetBottom( maTrackRect
.Bottom() );
290 if ( GetNativeControlRegion( ControlType::Scrollbar
, ControlPart::ButtonUp
,
291 aControlRegion
, ControlState::NONE
, ImplControlValue(), aBoundingRegion
, aBtn1Region
) &&
292 GetNativeControlRegion( ControlType::Scrollbar
, ControlPart::ButtonDown
,
293 aControlRegion
, ControlState::NONE
, ImplControlValue(), aBoundingRegion
, aBtn2Region
) )
295 maBtn1Rect
= aBtn1Region
;
296 maBtn2Rect
= aBtn2Region
;
300 const Size
aBtnSize( aSize
.Width(), aSize
.Width() );
301 maBtn2Rect
.SetLeft( maBtn1Rect
.Left() );
302 maBtn2Rect
.SetTop( aSize
.Height()-aSize
.Width() );
303 maBtn1Rect
.SetSize( aBtnSize
);
304 maBtn2Rect
.SetSize( aBtnSize
);
307 if ( GetNativeControlRegion( ControlType::Scrollbar
, ControlPart::TrackVertArea
,
308 aControlRegion
, ControlState::NONE
, ImplControlValue(), aBoundingRegion
, aTrackRegion
) )
309 maTrackRect
= aTrackRegion
;
311 maTrackRect
= tools::Rectangle::Normalize( maBtn1Rect
.BottomLeft()+Point(0,1), maBtn2Rect
.TopRight() );
313 // Check if available space is big enough for thumb
314 mnThumbPixRange
= maTrackRect
.Bottom() - maTrackRect
.Top();
315 if( mnThumbPixRange
> 0 )
317 maPage1Rect
.SetTop( maTrackRect
.Top() );
318 maPage1Rect
.SetRight( maTrackRect
.Right() );
319 maPage2Rect
.SetRight( maTrackRect
.Right() );
320 maThumbRect
.SetRight( maTrackRect
.Right() );
328 Size aNewSize
= getCurrentCalcSize();
329 if (aOldSize
!= aNewSize
)
335 if ( mnThumbPixRange
)
338 if ( (mnVisibleSize
>= (mnMaxRange
-mnMinRange
)) ||
339 ((mnMaxRange
-mnMinRange
) <= 0) )
341 mnThumbPos
= mnMinRange
;
343 mnThumbPixSize
= mnThumbPixRange
;
348 mnThumbPixSize
= ImplMulDiv( mnThumbPixRange
, mnVisibleSize
, mnMaxRange
-mnMinRange
);
351 if ( GetStyle() & WB_HORZ
)
352 mnThumbPixSize
= maThumbRect
.GetWidth();
354 mnThumbPixSize
= maThumbRect
.GetHeight();
356 if ( mnThumbPixSize
< nMinThumbSize
)
357 mnThumbPixSize
= nMinThumbSize
;
358 if ( mnThumbPixSize
> mnThumbPixRange
)
359 mnThumbPixSize
= mnThumbPixRange
;
360 mnThumbPixPos
= ImplCalcThumbPosPix( mnThumbPos
);
364 // If we're ought to output again and we have been triggered
365 // a Paint event via an Action, we don't output directly,
366 // but invalidate everything
367 if ( bUpdate
&& HasPaintEvent() )
372 ImplUpdateRects( bUpdate
);
375 void ScrollBar::Draw( OutputDevice
* pDev
, const Point
& rPos
, SystemTextColorFlags nFlags
)
377 Point aPos
= pDev
->LogicToPixel( rPos
);
381 if ( !(nFlags
& SystemTextColorFlags::Mono
) )
383 // DecoView uses the FaceColor...
384 AllSettings aSettings
= pDev
->GetSettings();
385 StyleSettings aStyleSettings
= aSettings
.GetStyleSettings();
386 if ( IsControlBackground() )
387 aStyleSettings
.SetFaceColor( GetControlBackground() );
389 aStyleSettings
.SetFaceColor( GetSettings().GetStyleSettings().GetFaceColor() );
391 aSettings
.SetStyleSettings( aStyleSettings
);
392 pDev
->SetSettings( aSettings
);
396 // - calculate the size of the rects
397 // - because this is zero-based add the correct offset
399 // - force recalculate
417 bool ScrollBar::ImplDrawNative(vcl::RenderContext
& rRenderContext
, sal_uInt16 nSystemTextColorFlags
)
419 ScrollbarValue scrValue
;
421 bool bNativeOK
= rRenderContext
.IsNativeControlSupported(ControlType::Scrollbar
, ControlPart::Entire
);
425 bool bHorz
= (GetStyle() & WB_HORZ
) != 0;
427 // Draw the entire background if the control supports it
428 if (rRenderContext
.IsNativeControlSupported(ControlType::Scrollbar
, bHorz
? ControlPart::DrawBackgroundHorz
: ControlPart::DrawBackgroundVert
))
430 ControlState nState
= (IsEnabled() ? ControlState::ENABLED
: ControlState::NONE
)
431 | (HasFocus() ? ControlState::FOCUSED
: ControlState::NONE
);
433 scrValue
.mnMin
= mnMinRange
;
434 scrValue
.mnMax
= mnMaxRange
;
435 scrValue
.mnCur
= mnThumbPos
;
436 scrValue
.mnVisibleSize
= mnVisibleSize
;
437 scrValue
.maThumbRect
= maThumbRect
;
438 scrValue
.maButton1Rect
= maBtn1Rect
;
439 scrValue
.maButton2Rect
= maBtn2Rect
;
440 scrValue
.mnButton1State
= ((mnStateFlags
& SCRBAR_STATE_BTN1_DOWN
) ? ControlState::PRESSED
: ControlState::NONE
) |
441 ((!(mnStateFlags
& SCRBAR_STATE_BTN1_DISABLE
)) ? ControlState::ENABLED
: ControlState::NONE
);
442 scrValue
.mnButton2State
= ((mnStateFlags
& SCRBAR_STATE_BTN2_DOWN
) ? ControlState::PRESSED
: ControlState::NONE
) |
443 ((!(mnStateFlags
& SCRBAR_STATE_BTN2_DISABLE
)) ? ControlState::ENABLED
: ControlState::NONE
);
444 scrValue
.mnThumbState
= nState
| ((mnStateFlags
& SCRBAR_STATE_THUMB_DOWN
) ? ControlState::PRESSED
: ControlState::NONE
);
448 tools::Rectangle
* pRect
= ImplFindPartRect(GetPointerPosPixel());
451 if (pRect
== &maThumbRect
)
452 scrValue
.mnThumbState
|= ControlState::ROLLOVER
;
453 else if (pRect
== &maBtn1Rect
)
454 scrValue
.mnButton1State
|= ControlState::ROLLOVER
;
455 else if (pRect
== &maBtn2Rect
)
456 scrValue
.mnButton2State
|= ControlState::ROLLOVER
;
460 tools::Rectangle aCtrlRegion
;
461 aCtrlRegion
.Union(maBtn1Rect
);
462 aCtrlRegion
.Union(maBtn2Rect
);
463 aCtrlRegion
.Union(maPage1Rect
);
464 aCtrlRegion
.Union(maPage2Rect
);
465 aCtrlRegion
.Union(maThumbRect
);
467 tools::Rectangle
aRequestedRegion(Point(0,0), GetOutputSizePixel());
468 // if the actual native control region is smaller then the region that
469 // we requested the control to draw in, then draw a background rectangle
470 // to avoid drawing artifacts in the uncovered region
471 if (aCtrlRegion
.GetWidth() < aRequestedRegion
.GetWidth() ||
472 aCtrlRegion
.GetHeight() < aRequestedRegion
.GetHeight())
474 Color aFaceColor
= rRenderContext
.GetSettings().GetStyleSettings().GetFaceColor();
475 rRenderContext
.SetFillColor(aFaceColor
);
476 rRenderContext
.SetLineColor(aFaceColor
);
477 rRenderContext
.DrawRect(aRequestedRegion
);
480 bNativeOK
= rRenderContext
.DrawNativeControl(ControlType::Scrollbar
, (bHorz
? ControlPart::DrawBackgroundHorz
: ControlPart::DrawBackgroundVert
),
481 aCtrlRegion
, nState
, scrValue
, OUString());
485 if ((nSystemTextColorFlags
& SCRBAR_DRAW_PAGE1
) || (nSystemTextColorFlags
& SCRBAR_DRAW_PAGE2
))
487 ControlPart part1
= bHorz
? ControlPart::TrackHorzLeft
: ControlPart::TrackVertUpper
;
488 ControlPart part2
= bHorz
? ControlPart::TrackHorzRight
: ControlPart::TrackVertLower
;
489 tools::Rectangle
aCtrlRegion1(maPage1Rect
);
490 tools::Rectangle
aCtrlRegion2(maPage2Rect
);
491 ControlState nState1
= (IsEnabled() ? ControlState::ENABLED
: ControlState::NONE
)
492 | (HasFocus() ? ControlState::FOCUSED
: ControlState::NONE
);
493 ControlState nState2
= nState1
;
495 nState1
|= ((mnStateFlags
& SCRBAR_STATE_PAGE1_DOWN
) ? ControlState::PRESSED
: ControlState::NONE
);
496 nState2
|= ((mnStateFlags
& SCRBAR_STATE_PAGE2_DOWN
) ? ControlState::PRESSED
: ControlState::NONE
);
500 tools::Rectangle
* pRect
= ImplFindPartRect(GetPointerPosPixel());
503 if (pRect
== &maPage1Rect
)
504 nState1
|= ControlState::ROLLOVER
;
505 else if (pRect
== &maPage2Rect
)
506 nState2
|= ControlState::ROLLOVER
;
510 if (nSystemTextColorFlags
& SCRBAR_DRAW_PAGE1
)
511 bNativeOK
= rRenderContext
.DrawNativeControl(ControlType::Scrollbar
, part1
, aCtrlRegion1
, nState1
, scrValue
, OUString());
513 if (nSystemTextColorFlags
& SCRBAR_DRAW_PAGE2
)
514 bNativeOK
= rRenderContext
.DrawNativeControl(ControlType::Scrollbar
, part2
, aCtrlRegion2
, nState2
, scrValue
, OUString());
516 if ((nSystemTextColorFlags
& SCRBAR_DRAW_BTN1
) || (nSystemTextColorFlags
& SCRBAR_DRAW_BTN2
))
518 ControlPart part1
= bHorz
? ControlPart::ButtonLeft
: ControlPart::ButtonUp
;
519 ControlPart part2
= bHorz
? ControlPart::ButtonRight
: ControlPart::ButtonDown
;
520 tools::Rectangle
aCtrlRegion1(maBtn1Rect
);
521 tools::Rectangle
aCtrlRegion2(maBtn2Rect
);
522 ControlState nState1
= HasFocus() ? ControlState::FOCUSED
: ControlState::NONE
;
523 ControlState nState2
= nState1
;
525 if (!Window::IsEnabled() || !IsEnabled())
526 nState1
= (nState2
&= ~ControlState::ENABLED
);
528 nState1
= (nState2
|= ControlState::ENABLED
);
530 nState1
|= ((mnStateFlags
& SCRBAR_STATE_BTN1_DOWN
) ? ControlState::PRESSED
: ControlState::NONE
);
531 nState2
|= ((mnStateFlags
& SCRBAR_STATE_BTN2_DOWN
) ? ControlState::PRESSED
: ControlState::NONE
);
533 if (mnStateFlags
& SCRBAR_STATE_BTN1_DISABLE
)
534 nState1
&= ~ControlState::ENABLED
;
535 if (mnStateFlags
& SCRBAR_STATE_BTN2_DISABLE
)
536 nState2
&= ~ControlState::ENABLED
;
540 tools::Rectangle
* pRect
= ImplFindPartRect(GetPointerPosPixel());
543 if (pRect
== &maBtn1Rect
)
544 nState1
|= ControlState::ROLLOVER
;
545 else if (pRect
== &maBtn2Rect
)
546 nState2
|= ControlState::ROLLOVER
;
550 if (nSystemTextColorFlags
& SCRBAR_DRAW_BTN1
)
551 bNativeOK
= rRenderContext
.DrawNativeControl(ControlType::Scrollbar
, part1
, aCtrlRegion1
, nState1
, scrValue
, OUString());
553 if (nSystemTextColorFlags
& SCRBAR_DRAW_BTN2
)
554 bNativeOK
= rRenderContext
.DrawNativeControl(ControlType::Scrollbar
, part2
, aCtrlRegion2
, nState2
, scrValue
, OUString());
556 if ((nSystemTextColorFlags
& SCRBAR_DRAW_THUMB
) && !maThumbRect
.IsEmpty())
558 ControlState nState
= IsEnabled() ? ControlState::ENABLED
: ControlState::NONE
;
559 tools::Rectangle
aCtrlRegion(maThumbRect
);
561 if (mnStateFlags
& SCRBAR_STATE_THUMB_DOWN
)
562 nState
|= ControlState::PRESSED
;
565 nState
|= ControlState::FOCUSED
;
569 tools::Rectangle
* pRect
= ImplFindPartRect(GetPointerPosPixel());
570 if (pRect
&& pRect
== &maThumbRect
)
571 nState
|= ControlState::ROLLOVER
;
574 bNativeOK
= rRenderContext
.DrawNativeControl(ControlType::Scrollbar
, (bHorz
? ControlPart::ThumbHorz
: ControlPart::ThumbVert
),
575 aCtrlRegion
, nState
, scrValue
, OUString());
581 void ScrollBar::ImplDraw(vcl::RenderContext
& rRenderContext
)
583 DecorationView
aDecoView(&rRenderContext
);
584 tools::Rectangle aTempRect
;
585 DrawButtonFlags nStyle
;
586 const StyleSettings
& rStyleSettings
= rRenderContext
.GetSettings().GetStyleSettings();
587 SymbolType eSymbolType
;
588 bool bEnabled
= IsEnabled();
590 // Finish some open calculations (if any)
594 //vcl::Window *pWin = NULL;
595 //if (rRenderContext.GetOutDevType() == OUTDEV_WINDOW)
596 // pWin = static_cast<vcl::Window*>(&rRenderContext);
598 // Draw the entire control if the native theme engine needs it
599 if (rRenderContext
.IsNativeControlSupported(ControlType::Scrollbar
, ControlPart::DrawBackgroundHorz
))
601 ImplDrawNative(rRenderContext
, SCRBAR_DRAW_BACKGROUND
);
605 if (!ImplDrawNative(rRenderContext
, SCRBAR_DRAW_BTN1
))
607 nStyle
= DrawButtonFlags::NoLightBorder
;
608 if (mnStateFlags
& SCRBAR_STATE_BTN1_DOWN
)
609 nStyle
|= DrawButtonFlags::Pressed
;
610 aTempRect
= aDecoView
.DrawButton( PixelToLogic(maBtn1Rect
), nStyle
);
611 ImplCalcSymbolRect( aTempRect
);
612 DrawSymbolFlags nSymbolStyle
= DrawSymbolFlags::NONE
;
613 if ((mnStateFlags
& SCRBAR_STATE_BTN1_DISABLE
) || !bEnabled
)
614 nSymbolStyle
|= DrawSymbolFlags::Disable
;
615 if (GetStyle() & WB_HORZ
)
616 eSymbolType
= SymbolType::SPIN_LEFT
;
618 eSymbolType
= SymbolType::SPIN_UP
;
619 aDecoView
.DrawSymbol(aTempRect
, eSymbolType
, rStyleSettings
.GetButtonTextColor(), nSymbolStyle
);
622 if (!ImplDrawNative(rRenderContext
, SCRBAR_DRAW_BTN2
))
624 nStyle
= DrawButtonFlags::NoLightBorder
;
625 if (mnStateFlags
& SCRBAR_STATE_BTN2_DOWN
)
626 nStyle
|= DrawButtonFlags::Pressed
;
627 aTempRect
= aDecoView
.DrawButton(PixelToLogic(maBtn2Rect
), nStyle
);
628 ImplCalcSymbolRect(aTempRect
);
629 DrawSymbolFlags nSymbolStyle
= DrawSymbolFlags::NONE
;
630 if ((mnStateFlags
& SCRBAR_STATE_BTN2_DISABLE
) || !bEnabled
)
631 nSymbolStyle
|= DrawSymbolFlags::Disable
;
632 if (GetStyle() & WB_HORZ
)
633 eSymbolType
= SymbolType::SPIN_RIGHT
;
635 eSymbolType
= SymbolType::SPIN_DOWN
;
636 aDecoView
.DrawSymbol(aTempRect
, eSymbolType
, rStyleSettings
.GetButtonTextColor(), nSymbolStyle
);
639 rRenderContext
.SetLineColor();
641 if (!ImplDrawNative(rRenderContext
, SCRBAR_DRAW_THUMB
))
643 if (!maThumbRect
.IsEmpty())
647 nStyle
= DrawButtonFlags::NoLightBorder
;
648 aTempRect
= aDecoView
.DrawButton(PixelToLogic(maThumbRect
), nStyle
);
652 rRenderContext
.SetFillColor(rStyleSettings
.GetCheckedColor());
653 rRenderContext
.DrawRect(PixelToLogic(maThumbRect
));
658 if (!ImplDrawNative(rRenderContext
, SCRBAR_DRAW_PAGE1
))
660 if (mnStateFlags
& SCRBAR_STATE_PAGE1_DOWN
)
661 rRenderContext
.SetFillColor(rStyleSettings
.GetShadowColor());
663 rRenderContext
.SetFillColor(rStyleSettings
.GetCheckedColor());
664 rRenderContext
.DrawRect(PixelToLogic(maPage1Rect
));
666 if (!ImplDrawNative(rRenderContext
, SCRBAR_DRAW_PAGE2
))
668 if (mnStateFlags
& SCRBAR_STATE_PAGE2_DOWN
)
669 rRenderContext
.SetFillColor(rStyleSettings
.GetShadowColor());
671 rRenderContext
.SetFillColor(rStyleSettings
.GetCheckedColor());
672 rRenderContext
.DrawRect(PixelToLogic(maPage2Rect
));
676 tools::Long
ScrollBar::ImplScroll( tools::Long nNewPos
, bool bCallEndScroll
)
678 tools::Long nOldPos
= mnThumbPos
;
679 SetThumbPos( nNewPos
);
680 tools::Long nDelta
= mnThumbPos
-nOldPos
;
685 if ( bCallEndScroll
)
692 tools::Long
ScrollBar::ImplDoAction( bool bCallEndScroll
)
694 tools::Long nDelta
= 0;
696 switch ( meScrollType
)
698 case ScrollType::LineUp
:
699 nDelta
= ImplScroll( mnThumbPos
-mnLineSize
, bCallEndScroll
);
702 case ScrollType::LineDown
:
703 nDelta
= ImplScroll( mnThumbPos
+mnLineSize
, bCallEndScroll
);
706 case ScrollType::PageUp
:
707 nDelta
= ImplScroll( mnThumbPos
-mnPageSize
, bCallEndScroll
);
710 case ScrollType::PageDown
:
711 nDelta
= ImplScroll( mnThumbPos
+mnPageSize
, bCallEndScroll
);
720 void ScrollBar::ImplDoMouseAction( const Point
& rMousePos
, bool bCallAction
)
722 sal_uInt16 nOldStateFlags
= mnStateFlags
;
723 bool bAction
= false;
724 bool bHorizontal
= ( GetStyle() & WB_HORZ
) != 0;
725 bool bIsInside
= false;
727 Point
aPoint( 0, 0 );
728 tools::Rectangle
aControlRegion( aPoint
, GetOutputSizePixel() );
730 switch ( meScrollType
)
732 case ScrollType::LineUp
:
733 if ( GetOutDev()->HitTestNativeScrollbar( bHorizontal
? (IsRTLEnabled()? ControlPart::ButtonRight
: ControlPart::ButtonLeft
): ControlPart::ButtonUp
,
734 aControlRegion
, rMousePos
, bIsInside
)?
736 maBtn1Rect
.Contains( rMousePos
) )
738 bAction
= bCallAction
;
739 mnStateFlags
|= SCRBAR_STATE_BTN1_DOWN
;
742 mnStateFlags
&= ~SCRBAR_STATE_BTN1_DOWN
;
745 case ScrollType::LineDown
:
746 if ( GetOutDev()->HitTestNativeScrollbar( bHorizontal
? (IsRTLEnabled()? ControlPart::ButtonLeft
: ControlPart::ButtonRight
): ControlPart::ButtonDown
,
747 aControlRegion
, rMousePos
, bIsInside
)?
749 maBtn2Rect
.Contains( rMousePos
) )
751 bAction
= bCallAction
;
752 mnStateFlags
|= SCRBAR_STATE_BTN2_DOWN
;
755 mnStateFlags
&= ~SCRBAR_STATE_BTN2_DOWN
;
758 case ScrollType::PageUp
:
759 // HitTestNativeScrollbar, see remark at top of file
760 if ( GetOutDev()->HitTestNativeScrollbar( bHorizontal
? ControlPart::TrackHorzLeft
: ControlPart::TrackVertUpper
,
761 maPage1Rect
, rMousePos
, bIsInside
)?
763 maPage1Rect
.Contains( rMousePos
) )
765 bAction
= bCallAction
;
766 mnStateFlags
|= SCRBAR_STATE_PAGE1_DOWN
;
769 mnStateFlags
&= ~SCRBAR_STATE_PAGE1_DOWN
;
772 case ScrollType::PageDown
:
773 // HitTestNativeScrollbar, see remark at top of file
774 if ( GetOutDev()->HitTestNativeScrollbar( bHorizontal
? ControlPart::TrackHorzRight
: ControlPart::TrackVertLower
,
775 maPage2Rect
, rMousePos
, bIsInside
)?
777 maPage2Rect
.Contains( rMousePos
) )
779 bAction
= bCallAction
;
780 mnStateFlags
|= SCRBAR_STATE_PAGE2_DOWN
;
783 mnStateFlags
&= ~SCRBAR_STATE_PAGE2_DOWN
;
789 if ( nOldStateFlags
!= mnStateFlags
)
792 ImplDoAction( false );
795 void ScrollBar::ImplDragThumb( const Point
& rMousePos
)
797 tools::Long nMovePix
;
798 if ( GetStyle() & WB_HORZ
)
799 nMovePix
= rMousePos
.X()-(maThumbRect
.Left()+mnMouseOff
);
801 nMovePix
= rMousePos
.Y()-(maThumbRect
.Top()+mnMouseOff
);
803 // Move thumb if necessary
807 mnThumbPixPos
+= nMovePix
;
808 if ( mnThumbPixPos
< 0 )
810 if ( mnThumbPixPos
> (mnThumbPixRange
-mnThumbPixSize
) )
811 mnThumbPixPos
= mnThumbPixRange
-mnThumbPixSize
;
812 tools::Long nOldPos
= mnThumbPos
;
813 mnThumbPos
= ImplCalcThumbPos( mnThumbPixPos
);
815 if ( !(mbFullDrag
&& (nOldPos
!= mnThumbPos
)) )
818 // When dragging in windows the repaint request gets starved so dragging
819 // the scrollbar feels slower than it actually is. Let's force an immediate
820 // repaint of the scrollbar.
821 if (SupportsDoubleBuffering())
827 ImplDraw(*GetOutDev());
829 mnDelta
= mnThumbPos
-nOldPos
;
834 void ScrollBar::MouseButtonDown( const MouseEvent
& rMEvt
)
836 bool bPrimaryWarps
= GetSettings().GetStyleSettings().GetPrimaryButtonWarpsSlider();
838 // tdf#147067 Jump to clicked spot if left mouse click with Option key
839 // Most macOS applications such as TextEdit and Safari jump to the
840 // clicked spot if the Option key is pressed during a left mouse click.
841 if (!bPrimaryWarps
&& rMEvt
.IsLeft() && rMEvt
.GetModifier() == KEY_MOD2
)
842 bPrimaryWarps
= true;
844 bool bWarp
= bPrimaryWarps
? rMEvt
.IsLeft() : rMEvt
.IsMiddle();
845 bool bPrimaryWarping
= bWarp
&& rMEvt
.IsLeft();
846 bool bPage
= bPrimaryWarps
? rMEvt
.IsRight() : rMEvt
.IsLeft();
848 if (!rMEvt
.IsLeft() && !rMEvt
.IsMiddle() && !rMEvt
.IsRight())
852 if (!IsMapModeEnabled() && GetMapMode().GetMapUnit() == MapUnit::MapTwip
)
854 // rMEvt coordinates are in twips.
855 GetOutDev()->Push(vcl::PushFlags::MAPMODE
);
857 MapMode aMapMode
= GetMapMode();
858 aMapMode
.SetOrigin(Point(0, 0));
859 SetMapMode(aMapMode
);
860 aPosPixel
= LogicToPixel(rMEvt
.GetPosPixel());
863 const Point
& rMousePos
= (GetMapMode().GetMapUnit() != MapUnit::MapTwip
? rMEvt
.GetPosPixel() : aPosPixel
);
864 StartTrackingFlags nTrackFlags
= StartTrackingFlags::NONE
;
865 bool bHorizontal
= ( GetStyle() & WB_HORZ
) != 0;
866 bool bIsInside
= false;
867 bool bDragToMouse
= false;
869 Point
aPoint( 0, 0 );
870 tools::Rectangle
aControlRegion( aPoint
, GetOutputSizePixel() );
872 if ( GetOutDev()->HitTestNativeScrollbar( bHorizontal
? (IsRTLEnabled()? ControlPart::ButtonRight
: ControlPart::ButtonLeft
): ControlPart::ButtonUp
,
873 aControlRegion
, rMousePos
, bIsInside
)?
875 maBtn1Rect
.Contains( rMousePos
) )
877 if (rMEvt
.IsLeft() && !(mnStateFlags
& SCRBAR_STATE_BTN1_DISABLE
) )
879 nTrackFlags
= StartTrackingFlags::ButtonRepeat
;
880 meScrollType
= ScrollType::LineUp
;
883 else if ( GetOutDev()->HitTestNativeScrollbar( bHorizontal
? (IsRTLEnabled()? ControlPart::ButtonLeft
: ControlPart::ButtonRight
): ControlPart::ButtonDown
,
884 aControlRegion
, rMousePos
, bIsInside
)?
886 maBtn2Rect
.Contains( rMousePos
) )
888 if (rMEvt
.IsLeft() && !(mnStateFlags
& SCRBAR_STATE_BTN2_DISABLE
) )
890 nTrackFlags
= StartTrackingFlags::ButtonRepeat
;
891 meScrollType
= ScrollType::LineDown
;
896 bool bThumbHit
= GetOutDev()->HitTestNativeScrollbar( bHorizontal
? ControlPart::ThumbHorz
: ControlPart::ThumbVert
,
897 maThumbRect
, rMousePos
, bIsInside
)
898 ? bIsInside
: maThumbRect
.Contains( rMousePos
);
900 bool bThumbAction
= bWarp
|| bPage
;
902 bool bDragHandling
= bWarp
|| (bThumbHit
&& bThumbAction
);
907 mpData
->mbHide
= true; // disable focus blinking
910 mnStateFlags
|= SCRBAR_DRAW_THUMB
; // paint without focus
915 if ( mnVisibleSize
< mnMaxRange
-mnMinRange
)
917 nTrackFlags
= StartTrackingFlags::NONE
;
918 meScrollType
= ScrollType::Drag
;
920 // calculate mouse offset
921 if (bWarp
&& (!bThumbHit
|| !bPrimaryWarping
))
924 if ( GetStyle() & WB_HORZ
)
925 mnMouseOff
= maThumbRect
.GetWidth()/2;
927 mnMouseOff
= maThumbRect
.GetHeight()/2;
931 if ( GetStyle() & WB_HORZ
)
932 mnMouseOff
= rMousePos
.X()-maThumbRect
.Left();
934 mnMouseOff
= rMousePos
.Y()-maThumbRect
.Top();
937 mnStateFlags
|= SCRBAR_STATE_THUMB_DOWN
;
941 else if(bPage
&& (!GetOutDev()->HitTestNativeScrollbar( bHorizontal
? ControlPart::TrackHorzArea
: ControlPart::TrackVertArea
,
942 aControlRegion
, rMousePos
, bIsInside
) ||
945 nTrackFlags
= StartTrackingFlags::ButtonRepeat
;
947 // HitTestNativeScrollbar, see remark at top of file
948 if ( GetOutDev()->HitTestNativeScrollbar( bHorizontal
? ControlPart::TrackHorzLeft
: ControlPart::TrackVertUpper
,
949 maPage1Rect
, rMousePos
, bIsInside
)?
951 maPage1Rect
.Contains( rMousePos
) )
953 meScrollType
= ScrollType::PageUp
;
957 meScrollType
= ScrollType::PageDown
;
962 // Should we start Tracking?
963 if ( meScrollType
== ScrollType::DontKnow
)
966 // store original position for cancel and EndScroll delta
967 mnStartPos
= mnThumbPos
;
968 // #92906# Call StartTracking() before ImplDoMouseAction(), otherwise
969 // MouseButtonUp() / EndTracking() may be called if somebody is spending
970 // a lot of time in the scroll handler
971 StartTracking( nTrackFlags
);
972 ImplDoMouseAction( rMousePos
);
975 ImplDragThumb( rMousePos
);
979 void ScrollBar::Tracking( const TrackingEvent
& rTEvt
)
981 if ( rTEvt
.IsTrackingEnded() )
983 // Restore Button and PageRect status
984 sal_uInt16 nOldStateFlags
= mnStateFlags
;
985 mnStateFlags
&= ~(SCRBAR_STATE_BTN1_DOWN
| SCRBAR_STATE_BTN2_DOWN
|
986 SCRBAR_STATE_PAGE1_DOWN
| SCRBAR_STATE_PAGE2_DOWN
|
987 SCRBAR_STATE_THUMB_DOWN
);
988 if ( nOldStateFlags
!= mnStateFlags
)
991 // Restore the old ThumbPosition when canceled
992 if ( rTEvt
.IsTrackingCanceled() )
994 tools::Long nOldPos
= mnThumbPos
;
995 SetThumbPos( mnStartPos
);
996 mnDelta
= mnThumbPos
-nOldPos
;
1000 if ( meScrollType
== ScrollType::Drag
)
1002 // On a SCROLLDRAG we recalculate the Thumb, so that it's back to a
1003 // rounded ThumbPosition
1006 if ( !mbFullDrag
&& (mnStartPos
!= mnThumbPos
) )
1008 mnDelta
= mnThumbPos
-mnStartPos
;
1014 mnDelta
= mnThumbPos
-mnStartPos
;
1017 meScrollType
= ScrollType::DontKnow
;
1020 mpData
->mbHide
= false; // re-enable focus blinking
1025 if (!IsMapModeEnabled() && GetMapMode().GetMapUnit() == MapUnit::MapTwip
)
1027 // rTEvt coordinates are in twips.
1028 GetOutDev()->Push(vcl::PushFlags::MAPMODE
);
1030 MapMode aMapMode
= GetMapMode();
1031 aMapMode
.SetOrigin(Point(0, 0));
1032 SetMapMode(aMapMode
);
1033 aPosPixel
= LogicToPixel(rTEvt
.GetMouseEvent().GetPosPixel());
1036 const Point rMousePos
= (GetMapMode().GetMapUnit() != MapUnit::MapTwip
? rTEvt
.GetMouseEvent().GetPosPixel() : aPosPixel
);
1038 // Dragging is treated in a special way
1039 if ( meScrollType
== ScrollType::Drag
)
1040 ImplDragThumb( rMousePos
);
1042 ImplDoMouseAction( rMousePos
, rTEvt
.IsTrackingRepeat() );
1044 // If ScrollBar values are translated in a way that there's
1045 // nothing left to track, we cancel here
1046 if ( !IsVisible() || (mnVisibleSize
>= (mnMaxRange
-mnMinRange
)) )
1051 void ScrollBar::KeyInput( const KeyEvent
& rKEvt
)
1053 if ( !rKEvt
.GetKeyCode().GetModifier() )
1055 switch ( rKEvt
.GetKeyCode().GetCode() )
1062 DoScroll( GetRangeMax() );
1067 DoScrollAction( ScrollType::LineUp
);
1072 DoScrollAction( ScrollType::LineDown
);
1076 DoScrollAction( ScrollType::PageUp
);
1080 DoScrollAction( ScrollType::PageDown
);
1084 Control::KeyInput( rKEvt
);
1089 Control::KeyInput( rKEvt
);
1092 void ScrollBar::ApplySettings(vcl::RenderContext
& rRenderContext
)
1094 rRenderContext
.SetBackground();
1097 void ScrollBar::Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
&)
1099 ImplDraw(rRenderContext
);
1102 void ScrollBar::Move()
1106 if (IsReallyVisible())
1111 void ScrollBar::Resize()
1115 if ( IsReallyVisible() )
1120 IMPL_LINK_NOARG(ScrollBar
, ImplAutoTimerHdl
, Timer
*, void)
1122 if( mpData
&& mpData
->mbHide
)
1127 void ScrollBar::ImplInvert()
1129 tools::Rectangle
aRect( maThumbRect
);
1130 if( aRect
.GetWidth() > 5 )
1132 aRect
.AdjustLeft(2 );
1133 aRect
.AdjustRight( -2 );
1135 if( aRect
.GetHeight() > 5 )
1137 aRect
.AdjustTop(2 );
1138 aRect
.AdjustBottom( -2 );
1141 GetOutDev()->Invert( aRect
);
1144 void ScrollBar::GetFocus()
1148 mpData
.reset(new ImplScrollBarData
);
1149 mpData
->maTimer
.SetInvokeHandler( LINK( this, ScrollBar
, ImplAutoTimerHdl
) );
1150 mpData
->mbHide
= false;
1152 ImplInvert(); // react immediately
1153 mpData
->maTimer
.SetTimeout( GetSettings().GetStyleSettings().GetCursorBlinkTime() );
1154 if (mpData
->maTimer
.GetTimeout() != STYLE_CURSOR_NOBLINKTIME
)
1155 mpData
->maTimer
.Start();
1156 Control::GetFocus();
1159 void ScrollBar::LoseFocus()
1162 mpData
->maTimer
.Stop();
1165 Control::LoseFocus();
1168 void ScrollBar::StateChanged( StateChangedType nType
)
1170 Control::StateChanged( nType
);
1172 if ( nType
== StateChangedType::InitShow
)
1174 else if ( nType
== StateChangedType::Data
)
1176 if ( IsReallyVisible() && IsUpdateMode() )
1179 else if ( nType
== StateChangedType::UpdateMode
)
1181 if ( IsReallyVisible() && IsUpdateMode() )
1187 else if ( nType
== StateChangedType::Enable
)
1189 if ( IsReallyVisible() && IsUpdateMode() )
1192 else if ( nType
== StateChangedType::Style
)
1194 ImplInitStyle( GetStyle() );
1195 if ( IsReallyVisible() && IsUpdateMode() )
1197 if ( (GetPrevStyle() & SCRBAR_VIEW_STYLE
) !=
1198 (GetStyle() & SCRBAR_VIEW_STYLE
) )
1208 void ScrollBar::DataChanged( const DataChangedEvent
& rDCEvt
)
1210 Control::DataChanged( rDCEvt
);
1212 if ( (rDCEvt
.GetType() == DataChangedEventType::SETTINGS
) &&
1213 (rDCEvt
.GetFlags() & AllSettingsFlags::STYLE
) )
1221 tools::Rectangle
* ScrollBar::ImplFindPartRect( const Point
& rPt
)
1223 bool bHorizontal
= ( GetStyle() & WB_HORZ
) != 0;
1224 bool bIsInside
= false;
1226 Point
aPoint( 0, 0 );
1227 tools::Rectangle
aControlRegion( aPoint
, GetOutputSizePixel() );
1229 if( GetOutDev()->HitTestNativeScrollbar( bHorizontal
? (IsRTLEnabled()? ControlPart::ButtonRight
: ControlPart::ButtonLeft
): ControlPart::ButtonUp
,
1230 aControlRegion
, rPt
, bIsInside
)?
1232 maBtn1Rect
.Contains( rPt
) )
1234 else if( GetOutDev()->HitTestNativeScrollbar( bHorizontal
? (IsRTLEnabled()? ControlPart::ButtonLeft
: ControlPart::ButtonRight
): ControlPart::ButtonDown
,
1235 aControlRegion
, rPt
, bIsInside
)?
1237 maBtn2Rect
.Contains( rPt
) )
1239 // HitTestNativeScrollbar, see remark at top of file
1240 else if( GetOutDev()->HitTestNativeScrollbar( bHorizontal
? ControlPart::TrackHorzLeft
: ControlPart::TrackVertUpper
,
1241 maPage1Rect
, rPt
, bIsInside
)?
1243 maPage1Rect
.Contains( rPt
) )
1244 return &maPage1Rect
;
1245 // HitTestNativeScrollbar, see remark at top of file
1246 else if( GetOutDev()->HitTestNativeScrollbar( bHorizontal
? ControlPart::TrackHorzRight
: ControlPart::TrackVertLower
,
1247 maPage2Rect
, rPt
, bIsInside
)?
1249 maPage2Rect
.Contains( rPt
) )
1250 return &maPage2Rect
;
1251 // HitTestNativeScrollbar, see remark at top of file
1252 else if( GetOutDev()->HitTestNativeScrollbar( bHorizontal
? ControlPart::ThumbHorz
: ControlPart::ThumbVert
,
1253 maThumbRect
, rPt
, bIsInside
)?
1255 maThumbRect
.Contains( rPt
) )
1256 return &maThumbRect
;
1261 bool ScrollBar::PreNotify( NotifyEvent
& rNEvt
)
1263 if( rNEvt
.GetType() == NotifyEventType::MOUSEMOVE
)
1265 const MouseEvent
* pMouseEvt
= rNEvt
.GetMouseEvent();
1266 if( pMouseEvt
&& !pMouseEvt
->GetButtons() && !pMouseEvt
->IsSynthetic() && !pMouseEvt
->IsModifierChanged() )
1268 // Trigger a redraw if mouse over state has changed
1269 if( IsNativeControlSupported(ControlType::Scrollbar
, ControlPart::Entire
) )
1271 tools::Rectangle
* pRect
= ImplFindPartRect( GetPointerPosPixel() );
1272 tools::Rectangle
* pLastRect
= ImplFindPartRect( GetLastPointerPosPixel() );
1273 if( pRect
!= pLastRect
|| pMouseEvt
->IsLeaveWindow() || pMouseEvt
->IsEnterWindow() )
1275 vcl::Region
aRgn( GetOutDev()->GetActiveClipRegion() );
1276 vcl::Region aClipRegion
;
1279 aClipRegion
.Union( *pRect
);
1281 aClipRegion
.Union( *pLastRect
);
1283 // Support for 3-button scroll bars
1284 bool bHas3Buttons
= IsNativeControlSupported( ControlType::Scrollbar
, ControlPart::HasThreeButtons
);
1285 if ( bHas3Buttons
&& ( pRect
== &maBtn1Rect
|| pLastRect
== &maBtn1Rect
) )
1287 aClipRegion
.Union( maBtn2Rect
);
1290 GetOutDev()->SetClipRegion( aClipRegion
);
1291 Invalidate(aClipRegion
.GetBoundRect());
1293 GetOutDev()->SetClipRegion( aRgn
);
1299 return Control::PreNotify(rNEvt
);
1302 void ScrollBar::Scroll()
1304 ImplCallEventListenersAndHandler( VclEventId::ScrollbarScroll
, [this] () { maScrollHdl
.Call(this); } );
1307 void ScrollBar::EndScroll()
1309 ImplCallEventListenersAndHandler( VclEventId::ScrollbarEndScroll
, [this] () { maEndScrollHdl
.Call(this); } );
1312 tools::Long
ScrollBar::DoScroll( tools::Long nNewPos
)
1314 if ( meScrollType
!= ScrollType::DontKnow
)
1317 SAL_INFO("vcl.scrollbar", "DoScroll(" << nNewPos
<< ")");
1318 meScrollType
= ScrollType::Drag
;
1319 tools::Long nDelta
= ImplScroll( nNewPos
, true );
1320 meScrollType
= ScrollType::DontKnow
;
1324 tools::Long
ScrollBar::DoScrollAction( ScrollType eScrollType
)
1326 if ( (meScrollType
!= ScrollType::DontKnow
) ||
1327 (eScrollType
== ScrollType::DontKnow
) ||
1328 (eScrollType
== ScrollType::Drag
) )
1331 meScrollType
= eScrollType
;
1332 tools::Long nDelta
= ImplDoAction( true );
1333 meScrollType
= ScrollType::DontKnow
;
1337 void ScrollBar::SetRangeMin( tools::Long nNewRange
)
1339 SetRange( Range( nNewRange
, GetRangeMax() ) );
1342 void ScrollBar::SetRangeMax( tools::Long nNewRange
)
1344 SetRange( Range( GetRangeMin(), nNewRange
) );
1347 void ScrollBar::SetRange( const Range
& rRange
)
1350 Range aRange
= rRange
;
1352 tools::Long nNewMinRange
= aRange
.Min();
1353 tools::Long nNewMaxRange
= aRange
.Max();
1355 // If Range differs, set a new one
1356 if ( (mnMinRange
== nNewMinRange
) && (mnMaxRange
== nNewMaxRange
))
1359 mnMinRange
= nNewMinRange
;
1360 mnMaxRange
= nNewMaxRange
;
1363 if ( mnThumbPos
> mnMaxRange
-mnVisibleSize
)
1364 mnThumbPos
= mnMaxRange
-mnVisibleSize
;
1365 if ( mnThumbPos
< mnMinRange
)
1366 mnThumbPos
= mnMinRange
;
1368 CompatStateChanged( StateChangedType::Data
);
1371 void ScrollBar::SetThumbPos( tools::Long nNewThumbPos
)
1373 if ( nNewThumbPos
> mnMaxRange
-mnVisibleSize
)
1374 nNewThumbPos
= mnMaxRange
-mnVisibleSize
;
1375 if ( nNewThumbPos
< mnMinRange
)
1376 nNewThumbPos
= mnMinRange
;
1378 if ( mnThumbPos
!= nNewThumbPos
)
1380 mnThumbPos
= nNewThumbPos
;
1381 CompatStateChanged( StateChangedType::Data
);
1385 void ScrollBar::SetVisibleSize( tools::Long nNewSize
)
1387 if ( mnVisibleSize
!= nNewSize
)
1389 mnVisibleSize
= nNewSize
;
1392 if ( mnThumbPos
> mnMaxRange
-mnVisibleSize
)
1393 mnThumbPos
= mnMaxRange
-mnVisibleSize
;
1394 if ( mnThumbPos
< mnMinRange
)
1395 mnThumbPos
= mnMinRange
;
1396 CompatStateChanged( StateChangedType::Data
);
1400 Size
ScrollBar::GetOptimalSize() const
1403 const_cast<ScrollBar
*>(this)->ImplCalc(false);
1405 Size aRet
= getCurrentCalcSize();
1407 const tools::Long nMinThumbSize
= GetSettings().GetStyleSettings().GetMinThumbSize();
1409 if (GetStyle() & WB_HORZ
)
1411 aRet
.setWidth( maBtn1Rect
.GetWidth() + nMinThumbSize
+ maBtn2Rect
.GetWidth() );
1415 aRet
.setHeight( maBtn1Rect
.GetHeight() + nMinThumbSize
+ maBtn2Rect
.GetHeight() );
1421 Size
ScrollBar::getCurrentCalcSize() const
1423 tools::Rectangle aCtrlRegion
;
1424 aCtrlRegion
.Union(maBtn1Rect
);
1425 aCtrlRegion
.Union(maBtn2Rect
);
1426 aCtrlRegion
.Union(maPage1Rect
);
1427 aCtrlRegion
.Union(maPage2Rect
);
1428 aCtrlRegion
.Union(maThumbRect
);
1429 return aCtrlRegion
.GetSize();
1432 bool ScrollBar::Inactive() const
1434 return !IsEnabled() || !IsInputEnabled() || IsInModalMode();
1437 void ScrollBarBox::ImplInit(vcl::Window
* pParent
, WinBits nStyle
)
1439 Window::ImplInit( pParent
, nStyle
, nullptr );
1441 const StyleSettings
& rStyleSettings
= GetSettings().GetStyleSettings();
1442 tools::Long nScrollSize
= rStyleSettings
.GetScrollBarSize();
1443 SetSizePixel(Size(nScrollSize
, nScrollSize
));
1446 ScrollBarBox::ScrollBarBox( vcl::Window
* pParent
, WinBits nStyle
) :
1447 Window( WindowType::SCROLLBARBOX
)
1449 ImplInit( pParent
, nStyle
);
1452 void ScrollBarBox::ApplySettings(vcl::RenderContext
& rRenderContext
)
1454 if (rRenderContext
.IsBackground())
1456 Color aColor
= rRenderContext
.GetSettings().GetStyleSettings().GetFaceColor();
1457 ApplyControlBackground(rRenderContext
, aColor
);
1461 void ScrollBarBox::StateChanged( StateChangedType nType
)
1463 Window::StateChanged( nType
);
1465 if (nType
== StateChangedType::ControlBackground
)
1471 void ScrollBarBox::DataChanged( const DataChangedEvent
& rDCEvt
)
1473 Window::DataChanged( rDCEvt
);
1475 if ((rDCEvt
.GetType() == DataChangedEventType::SETTINGS
) &&
1476 (rDCEvt
.GetFlags() & AllSettingsFlags::STYLE
))
1482 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */