sdext: adapt xpdfwrapper to poppler 24.12
[LibreOffice.git] / vcl / source / control / scrbar.cxx
blobfc56cc4be24aabe68e83a984d10a50adcf668cfe
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 <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>
29 /* #i77549#
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" };
68 bool mbHide;
71 void ScrollBar::ImplInit( vcl::Window* pParent, WinBits nStyle )
73 mpData = nullptr;
74 mnThumbPixRange = 0;
75 mnThumbPixPos = 0;
76 mnThumbPixSize = 0;
77 mnMinRange = 0;
78 mnMaxRange = 100;
79 mnThumbPos = 0;
80 mnVisibleSize = 0;
81 mnLineSize = 1;
82 mnPageSize = 1;
83 mnDelta = 0;
84 mnStateFlags = 0;
85 meScrollType = ScrollType::DontKnow;
86 mbCalcSize = true;
87 mbFullDrag = false;
88 mbSwapArrows = false;
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 )
100 mbFullDrag = true;
101 else
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()
113 disposeOnce();
116 void ScrollBar::dispose()
118 mpData.reset();
119 Control::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();
135 else
136 maPage1Rect.SetRight( maThumbRect.Left()-1 );
137 if ( mnThumbPixPos >= (mnThumbPixRange-mnThumbPixSize) )
138 maPage2Rect.SetWidthEmpty();
139 else
141 maPage2Rect.SetLeft( maThumbRect.Right()+1 );
142 maPage2Rect.SetRight( maTrackRect.Right() );
145 else
147 maThumbRect.SetTop( maTrackRect.Top()+mnThumbPixPos );
148 maThumbRect.SetBottom( maThumbRect.Top()+mnThumbPixSize-1 );
149 if ( !mnThumbPixPos )
150 maPage1Rect.SetHeightEmpty();
151 else
152 maPage1Rect.SetBottom( maThumbRect.Top()-1 );
153 if ( mnThumbPixPos >= (mnThumbPixRange-mnThumbPixSize) )
154 maPage2Rect.SetHeightEmpty();
155 else
157 maPage2Rect.SetTop( maThumbRect.Bottom()+1 );
158 maPage2Rect.SetBottom( maTrackRect.Bottom() );
162 else
164 if ( GetStyle() & WB_HORZ )
166 const tools::Long nSpace = maTrackRect.Right() - maTrackRect.Left();
167 if ( nSpace > 0 )
169 maPage1Rect.SetLeft( maTrackRect.Left() );
170 maPage1Rect.SetRight( maTrackRect.Left() + (nSpace/2) );
171 maPage2Rect.SetLeft( maPage1Rect.Right() + 1 );
172 maPage2Rect.SetRight( maTrackRect.Right() );
175 else
177 const tools::Long nSpace = maTrackRect.Bottom() - maTrackRect.Top();
178 if ( nSpace > 0 )
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;
198 if ( bUpdate )
200 Invalidate();
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) )
224 nCalcThumbPos = 1;
225 if ( nCalcThumbPos &&
226 ((nCalcThumbPos+mnThumbPixSize) >= mnThumbPixRange) &&
227 (mnThumbPos < (mnMaxRange-mnVisibleSize)) )
228 nCalcThumbPos--;
230 return nCalcThumbPos;
233 void ScrollBar::ImplCalc( bool bUpdate )
235 const Size aSize = GetOutputSizePixel();
236 const tools::Long nMinThumbSize = GetSettings().GetStyleSettings().GetMinThumbSize();
238 if ( mbCalcSize )
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;
261 else
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;
273 else
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() );
285 else
286 mnThumbPixRange = 0;
288 else // WB_VERT
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;
298 else
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;
310 else
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() );
322 else
323 mnThumbPixRange = 0;
326 mbCalcSize = false;
328 Size aNewSize = getCurrentCalcSize();
329 if (aOldSize != aNewSize)
331 queue_resize();
335 if ( mnThumbPixRange )
337 // Calculate values
338 if ( (mnVisibleSize >= (mnMaxRange-mnMinRange)) ||
339 ((mnMaxRange-mnMinRange) <= 0) )
341 mnThumbPos = mnMinRange;
342 mnThumbPixPos = 0;
343 mnThumbPixSize = mnThumbPixRange;
345 else
347 if ( mnVisibleSize )
348 mnThumbPixSize = ImplMulDiv( mnThumbPixRange, mnVisibleSize, mnMaxRange-mnMinRange );
349 else
351 if ( GetStyle() & WB_HORZ )
352 mnThumbPixSize = maThumbRect.GetWidth();
353 else
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() )
369 Invalidate();
370 bUpdate = false;
372 ImplUpdateRects( bUpdate );
375 void ScrollBar::Draw( OutputDevice* pDev, const Point& rPos, SystemTextColorFlags nFlags )
377 Point aPos = pDev->LogicToPixel( rPos );
379 pDev->Push();
380 pDev->SetMapMode();
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() );
388 else
389 aStyleSettings.SetFaceColor( GetSettings().GetStyleSettings().GetFaceColor() );
391 aSettings.SetStyleSettings( aStyleSettings );
392 pDev->SetSettings( aSettings );
395 // For printing:
396 // - calculate the size of the rects
397 // - because this is zero-based add the correct offset
398 // - print
399 // - force recalculate
401 if ( mbCalcSize )
402 ImplCalc( false );
404 maBtn1Rect+=aPos;
405 maBtn2Rect+=aPos;
406 maThumbRect+=aPos;
407 maTrackRect+=aPos;
408 maPage1Rect+=aPos;
409 maPage2Rect+=aPos;
411 ImplDraw(*pDev);
412 pDev->Pop();
414 mbCalcSize = true;
417 bool ScrollBar::ImplDrawNative(vcl::RenderContext& rRenderContext, sal_uInt16 nSystemTextColorFlags)
419 ScrollbarValue scrValue;
421 bool bNativeOK = rRenderContext.IsNativeControlSupported(ControlType::Scrollbar, ControlPart::Entire);
422 if (!bNativeOK)
423 return false;
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);
446 if (IsMouseOver())
448 tools::Rectangle* pRect = ImplFindPartRect(GetPointerPosPixel());
449 if (pRect)
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());
483 else
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);
498 if (IsMouseOver())
500 tools::Rectangle* pRect = ImplFindPartRect(GetPointerPosPixel());
501 if (pRect)
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);
527 else
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;
538 if (IsMouseOver())
540 tools::Rectangle* pRect = ImplFindPartRect(GetPointerPosPixel());
541 if (pRect)
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;
564 if (HasFocus())
565 nState |= ControlState::FOCUSED;
567 if (IsMouseOver())
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());
578 return bNativeOK;
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)
591 if (mbCalcSize)
592 ImplCalc(false);
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);
602 return;
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;
617 else
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;
634 else
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())
645 if (bEnabled)
647 nStyle = DrawButtonFlags::NoLightBorder;
648 aTempRect = aDecoView.DrawButton(PixelToLogic(maThumbRect), nStyle);
650 else
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());
662 else
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());
670 else
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;
681 if ( nDelta )
683 mnDelta = nDelta;
684 Scroll();
685 if ( bCallEndScroll )
686 EndScroll();
687 mnDelta = 0;
689 return nDelta;
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 );
700 break;
702 case ScrollType::LineDown:
703 nDelta = ImplScroll( mnThumbPos+mnLineSize, bCallEndScroll );
704 break;
706 case ScrollType::PageUp:
707 nDelta = ImplScroll( mnThumbPos-mnPageSize, bCallEndScroll );
708 break;
710 case ScrollType::PageDown:
711 nDelta = ImplScroll( mnThumbPos+mnPageSize, bCallEndScroll );
712 break;
713 default:
717 return nDelta;
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 )?
735 bIsInside:
736 maBtn1Rect.Contains( rMousePos ) )
738 bAction = bCallAction;
739 mnStateFlags |= SCRBAR_STATE_BTN1_DOWN;
741 else
742 mnStateFlags &= ~SCRBAR_STATE_BTN1_DOWN;
743 break;
745 case ScrollType::LineDown:
746 if ( GetOutDev()->HitTestNativeScrollbar( bHorizontal? (IsRTLEnabled()? ControlPart::ButtonLeft: ControlPart::ButtonRight): ControlPart::ButtonDown,
747 aControlRegion, rMousePos, bIsInside )?
748 bIsInside:
749 maBtn2Rect.Contains( rMousePos ) )
751 bAction = bCallAction;
752 mnStateFlags |= SCRBAR_STATE_BTN2_DOWN;
754 else
755 mnStateFlags &= ~SCRBAR_STATE_BTN2_DOWN;
756 break;
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 )?
762 bIsInside:
763 maPage1Rect.Contains( rMousePos ) )
765 bAction = bCallAction;
766 mnStateFlags |= SCRBAR_STATE_PAGE1_DOWN;
768 else
769 mnStateFlags &= ~SCRBAR_STATE_PAGE1_DOWN;
770 break;
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 )?
776 bIsInside:
777 maPage2Rect.Contains( rMousePos ) )
779 bAction = bCallAction;
780 mnStateFlags |= SCRBAR_STATE_PAGE2_DOWN;
782 else
783 mnStateFlags &= ~SCRBAR_STATE_PAGE2_DOWN;
784 break;
785 default:
789 if ( nOldStateFlags != mnStateFlags )
790 Invalidate();
791 if ( bAction )
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);
800 else
801 nMovePix = rMousePos.Y()-(maThumbRect.Top()+mnMouseOff);
803 // Move thumb if necessary
804 if ( !nMovePix )
805 return;
807 mnThumbPixPos += nMovePix;
808 if ( mnThumbPixPos < 0 )
809 mnThumbPixPos = 0;
810 if ( mnThumbPixPos > (mnThumbPixRange-mnThumbPixSize) )
811 mnThumbPixPos = mnThumbPixRange-mnThumbPixSize;
812 tools::Long nOldPos = mnThumbPos;
813 mnThumbPos = ImplCalcThumbPos( mnThumbPixPos );
814 ImplUpdateRects();
815 if ( !(mbFullDrag && (nOldPos != mnThumbPos)) )
816 return;
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())
823 Invalidate();
824 PaintImmediately();
826 else
827 ImplDraw(*GetOutDev());
829 mnDelta = mnThumbPos-nOldPos;
830 Scroll();
831 mnDelta = 0;
834 void ScrollBar::MouseButtonDown( const MouseEvent& rMEvt )
836 bool bPrimaryWarps = GetSettings().GetStyleSettings().GetPrimaryButtonWarpsSlider();
837 #ifdef MACOSX
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;
843 #endif
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())
849 return;
851 Point aPosPixel;
852 if (!IsMapModeEnabled() && GetMapMode().GetMapUnit() == MapUnit::MapTwip)
854 // rMEvt coordinates are in twips.
855 GetOutDev()->Push(vcl::PushFlags::MAPMODE);
856 EnableMapMode();
857 MapMode aMapMode = GetMapMode();
858 aMapMode.SetOrigin(Point(0, 0));
859 SetMapMode(aMapMode);
860 aPosPixel = LogicToPixel(rMEvt.GetPosPixel());
861 GetOutDev()->Pop();
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 )?
874 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 )?
885 bIsInside:
886 maBtn2Rect.Contains( rMousePos ) )
888 if (rMEvt.IsLeft() && !(mnStateFlags & SCRBAR_STATE_BTN2_DISABLE) )
890 nTrackFlags = StartTrackingFlags::ButtonRepeat;
891 meScrollType = ScrollType::LineDown;
894 else
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);
903 if( bDragHandling )
905 if( mpData )
907 mpData->mbHide = true; // disable focus blinking
908 if (HasFocus())
910 mnStateFlags |= SCRBAR_DRAW_THUMB; // paint without focus
911 Invalidate();
915 if ( mnVisibleSize < mnMaxRange-mnMinRange )
917 nTrackFlags = StartTrackingFlags::NONE;
918 meScrollType = ScrollType::Drag;
920 // calculate mouse offset
921 if (bWarp && (!bThumbHit || !bPrimaryWarping))
923 bDragToMouse = true;
924 if ( GetStyle() & WB_HORZ )
925 mnMouseOff = maThumbRect.GetWidth()/2;
926 else
927 mnMouseOff = maThumbRect.GetHeight()/2;
929 else
931 if ( GetStyle() & WB_HORZ )
932 mnMouseOff = rMousePos.X()-maThumbRect.Left();
933 else
934 mnMouseOff = rMousePos.Y()-maThumbRect.Top();
937 mnStateFlags |= SCRBAR_STATE_THUMB_DOWN;
938 Invalidate();
941 else if(bPage && (!GetOutDev()->HitTestNativeScrollbar( bHorizontal? ControlPart::TrackHorzArea : ControlPart::TrackVertArea,
942 aControlRegion, rMousePos, bIsInside ) ||
943 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 )?
950 bIsInside:
951 maPage1Rect.Contains( rMousePos ) )
953 meScrollType = ScrollType::PageUp;
955 else
957 meScrollType = ScrollType::PageDown;
962 // Should we start Tracking?
963 if ( meScrollType == ScrollType::DontKnow )
964 return;
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 );
974 if( bDragToMouse )
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 )
989 Invalidate();
991 // Restore the old ThumbPosition when canceled
992 if ( rTEvt.IsTrackingCanceled() )
994 tools::Long nOldPos = mnThumbPos;
995 SetThumbPos( mnStartPos );
996 mnDelta = mnThumbPos-nOldPos;
997 Scroll();
1000 if ( meScrollType == ScrollType::Drag )
1002 // On a SCROLLDRAG we recalculate the Thumb, so that it's back to a
1003 // rounded ThumbPosition
1004 ImplCalc();
1006 if ( !mbFullDrag && (mnStartPos != mnThumbPos) )
1008 mnDelta = mnThumbPos-mnStartPos;
1009 Scroll();
1010 mnDelta = 0;
1014 mnDelta = mnThumbPos-mnStartPos;
1015 EndScroll();
1016 mnDelta = 0;
1017 meScrollType = ScrollType::DontKnow;
1019 if( mpData )
1020 mpData->mbHide = false; // re-enable focus blinking
1022 else
1024 Point aPosPixel;
1025 if (!IsMapModeEnabled() && GetMapMode().GetMapUnit() == MapUnit::MapTwip)
1027 // rTEvt coordinates are in twips.
1028 GetOutDev()->Push(vcl::PushFlags::MAPMODE);
1029 EnableMapMode();
1030 MapMode aMapMode = GetMapMode();
1031 aMapMode.SetOrigin(Point(0, 0));
1032 SetMapMode(aMapMode);
1033 aPosPixel = LogicToPixel(rTEvt.GetMouseEvent().GetPosPixel());
1034 GetOutDev()->Pop();
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 );
1041 else
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)) )
1047 EndTracking();
1051 void ScrollBar::KeyInput( const KeyEvent& rKEvt )
1053 if ( !rKEvt.GetKeyCode().GetModifier() )
1055 switch ( rKEvt.GetKeyCode().GetCode() )
1057 case KEY_HOME:
1058 DoScroll( 0 );
1059 break;
1061 case KEY_END:
1062 DoScroll( GetRangeMax() );
1063 break;
1065 case KEY_LEFT:
1066 case KEY_UP:
1067 DoScrollAction( ScrollType::LineUp );
1068 break;
1070 case KEY_RIGHT:
1071 case KEY_DOWN:
1072 DoScrollAction( ScrollType::LineDown );
1073 break;
1075 case KEY_PAGEUP:
1076 DoScrollAction( ScrollType::PageUp );
1077 break;
1079 case KEY_PAGEDOWN:
1080 DoScrollAction( ScrollType::PageDown );
1081 break;
1083 default:
1084 Control::KeyInput( rKEvt );
1085 break;
1088 else
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()
1104 Control::Move();
1105 mbCalcSize = true;
1106 if (IsReallyVisible())
1107 ImplCalc(false);
1108 Invalidate();
1111 void ScrollBar::Resize()
1113 Control::Resize();
1114 mbCalcSize = true;
1115 if ( IsReallyVisible() )
1116 ImplCalc( false );
1117 Invalidate();
1120 IMPL_LINK_NOARG(ScrollBar, ImplAutoTimerHdl, Timer *, void)
1122 if( mpData && mpData->mbHide )
1123 return;
1124 ImplInvert();
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()
1146 if( !mpData )
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()
1161 if( mpData )
1162 mpData->maTimer.Stop();
1163 Invalidate();
1165 Control::LoseFocus();
1168 void ScrollBar::StateChanged( StateChangedType nType )
1170 Control::StateChanged( nType );
1172 if ( nType == StateChangedType::InitShow )
1173 ImplCalc( false );
1174 else if ( nType == StateChangedType::Data )
1176 if ( IsReallyVisible() && IsUpdateMode() )
1177 ImplCalc();
1179 else if ( nType == StateChangedType::UpdateMode )
1181 if ( IsReallyVisible() && IsUpdateMode() )
1183 ImplCalc( false );
1184 Invalidate();
1187 else if ( nType == StateChangedType::Enable )
1189 if ( IsReallyVisible() && IsUpdateMode() )
1190 Invalidate();
1192 else if ( nType == StateChangedType::Style )
1194 ImplInitStyle( GetStyle() );
1195 if ( IsReallyVisible() && IsUpdateMode() )
1197 if ( (GetPrevStyle() & SCRBAR_VIEW_STYLE) !=
1198 (GetStyle() & SCRBAR_VIEW_STYLE) )
1200 mbCalcSize = true;
1201 ImplCalc( false );
1202 Invalidate();
1208 void ScrollBar::DataChanged( const DataChangedEvent& rDCEvt )
1210 Control::DataChanged( rDCEvt );
1212 if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
1213 (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) )
1215 mbCalcSize = true;
1216 ImplCalc( false );
1217 Invalidate();
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 )?
1231 bIsInside:
1232 maBtn1Rect.Contains( rPt ) )
1233 return &maBtn1Rect;
1234 else if( GetOutDev()->HitTestNativeScrollbar( bHorizontal? (IsRTLEnabled()? ControlPart::ButtonLeft: ControlPart::ButtonRight): ControlPart::ButtonDown,
1235 aControlRegion, rPt, bIsInside )?
1236 bIsInside:
1237 maBtn2Rect.Contains( rPt ) )
1238 return &maBtn2Rect;
1239 // HitTestNativeScrollbar, see remark at top of file
1240 else if( GetOutDev()->HitTestNativeScrollbar( bHorizontal ? ControlPart::TrackHorzLeft : ControlPart::TrackVertUpper,
1241 maPage1Rect, rPt, bIsInside)?
1242 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)?
1248 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)?
1254 bIsInside:
1255 maThumbRect.Contains( rPt ) )
1256 return &maThumbRect;
1257 else
1258 return nullptr;
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;
1278 if ( pRect )
1279 aClipRegion.Union( *pRect );
1280 if ( pLastRect )
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 )
1315 return 0;
1317 SAL_INFO("vcl.scrollbar", "DoScroll(" << nNewPos << ")");
1318 meScrollType = ScrollType::Drag;
1319 tools::Long nDelta = ImplScroll( nNewPos, true );
1320 meScrollType = ScrollType::DontKnow;
1321 return nDelta;
1324 tools::Long ScrollBar::DoScrollAction( ScrollType eScrollType )
1326 if ( (meScrollType != ScrollType::DontKnow) ||
1327 (eScrollType == ScrollType::DontKnow) ||
1328 (eScrollType == ScrollType::Drag) )
1329 return 0;
1331 meScrollType = eScrollType;
1332 tools::Long nDelta = ImplDoAction( true );
1333 meScrollType = ScrollType::DontKnow;
1334 return nDelta;
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 )
1349 // Adapt Range
1350 Range aRange = rRange;
1351 aRange.Normalize();
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))
1357 return;
1359 mnMinRange = nNewMinRange;
1360 mnMaxRange = nNewMaxRange;
1362 // Adapt Thumb
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;
1391 // Adapt Thumb
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
1402 if (mbCalcSize)
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() );
1413 else
1415 aRet.setHeight( maBtn1Rect.GetHeight() + nMinThumbSize + maBtn2Rect.GetHeight() );
1418 return aRet;
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)
1467 Invalidate();
1471 void ScrollBarBox::DataChanged( const DataChangedEvent& rDCEvt )
1473 Window::DataChanged( rDCEvt );
1475 if ((rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
1476 (rDCEvt.GetFlags() & AllSettingsFlags::STYLE))
1478 Invalidate();
1482 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */