summaryrefslogtreecommitdiff
path: root/vcl/source/control/scrbar.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'vcl/source/control/scrbar.cxx')
-rw-r--r--vcl/source/control/scrbar.cxx1648
1 files changed, 1648 insertions, 0 deletions
diff --git a/vcl/source/control/scrbar.cxx b/vcl/source/control/scrbar.cxx
new file mode 100644
index 000000000000..9c82bb096dec
--- /dev/null
+++ b/vcl/source/control/scrbar.cxx
@@ -0,0 +1,1648 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_vcl.hxx"
+
+#include "vcl/event.hxx"
+#include "vcl/sound.hxx"
+#include "vcl/decoview.hxx"
+#include "vcl/scrbar.hxx"
+#include "vcl/timer.hxx"
+#include "vcl/svdata.hxx"
+
+#include "rtl/string.hxx"
+#include "tools/rc.h"
+
+
+
+using namespace rtl;
+
+/* #i77549#
+ HACK: for scrollbars in case of thumb rect, page up and page down rect we
+ abuse the HitTestNativeControl interface. All theming engines but aqua
+ are actually able to draw the thumb according to our internal representation.
+ However aqua draws a little outside. The canonical way would be to enhance the
+ HitTestNativeControl passing a ScrollbarValue additionally so all necessary
+ information is available in the call.
+ .
+ However since there is only this one small exception we will deviate a little and
+ instead pass the respective rect as control region to allow for a small correction.
+
+ So all places using HitTestNativeControl on PART_THUMB_HORZ, PART_THUMB_VERT,
+ PART_TRACK_HORZ_LEFT, PART_TRACK_HORZ_RIGHT, PART_TRACK_VERT_UPPER, PART_TRACK_VERT_LOWER
+ do not use the control rectangle as region but the actuall part rectangle, making
+ only small deviations feasible.
+*/
+
+
+// =======================================================================
+
+static long ImplMulDiv( long nNumber, long nNumerator, long nDenominator )
+{
+ double n = ((double)nNumber * (double)nNumerator) / (double)nDenominator;
+ return (long)n;
+}
+
+// =======================================================================
+
+#define SCRBAR_DRAW_BTN1 ((USHORT)0x0001)
+#define SCRBAR_DRAW_BTN2 ((USHORT)0x0002)
+#define SCRBAR_DRAW_PAGE1 ((USHORT)0x0004)
+#define SCRBAR_DRAW_PAGE2 ((USHORT)0x0008)
+#define SCRBAR_DRAW_THUMB ((USHORT)0x0010)
+#define SCRBAR_DRAW_BACKGROUND ((USHORT)0x0020)
+#define SCRBAR_DRAW_ALL (SCRBAR_DRAW_BTN1 | SCRBAR_DRAW_BTN2 | \
+ SCRBAR_DRAW_PAGE1 | SCRBAR_DRAW_PAGE2 |\
+ SCRBAR_DRAW_THUMB | SCRBAR_DRAW_BACKGROUND )
+
+#define SCRBAR_STATE_BTN1_DOWN ((USHORT)0x0001)
+#define SCRBAR_STATE_BTN1_DISABLE ((USHORT)0x0002)
+#define SCRBAR_STATE_BTN2_DOWN ((USHORT)0x0004)
+#define SCRBAR_STATE_BTN2_DISABLE ((USHORT)0x0008)
+#define SCRBAR_STATE_PAGE1_DOWN ((USHORT)0x0010)
+#define SCRBAR_STATE_PAGE2_DOWN ((USHORT)0x0020)
+#define SCRBAR_STATE_THUMB_DOWN ((USHORT)0x0040)
+
+#define SCRBAR_VIEW_STYLE (WB_3DLOOK | WB_HORZ | WB_VERT)
+
+struct ImplScrollBarData
+{
+ AutoTimer maTimer; // Timer
+ BOOL mbHide;
+ Rectangle maTrackRect; // TODO: move to ScrollBar class when binary incompatibility of ScrollBar class is no longer problematic
+};
+
+// =======================================================================
+
+void ScrollBar::ImplInit( Window* pParent, WinBits nStyle )
+{
+ mpData = NULL;
+ mnThumbPixRange = 0;
+ mnThumbPixPos = 0;
+ mnThumbPixSize = 0;
+ mnMinRange = 0;
+ mnMaxRange = 100;
+ mnThumbPos = 0;
+ mnVisibleSize = 0;
+ mnLineSize = 1;
+ mnPageSize = 1;
+ mnDelta = 0;
+ mnDragDraw = 0;
+ mnStateFlags = 0;
+ meScrollType = SCROLL_DONTKNOW;
+ meDDScrollType = SCROLL_DONTKNOW;
+ mbCalcSize = TRUE;
+ mbFullDrag = 0;
+
+ if( !mpData ) // TODO: remove when maTrackRect is no longer in mpData
+ {
+ mpData = new ImplScrollBarData;
+ mpData->maTimer.SetTimeoutHdl( LINK( this, ScrollBar, ImplAutoTimerHdl ) );
+ mpData->mbHide = FALSE;
+ }
+
+ ImplInitStyle( nStyle );
+ Control::ImplInit( pParent, nStyle, NULL );
+
+ long nScrollSize = GetSettings().GetStyleSettings().GetScrollBarSize();
+ SetSizePixel( Size( nScrollSize, nScrollSize ) );
+ SetBackground();
+}
+
+// -----------------------------------------------------------------------
+
+void ScrollBar::ImplInitStyle( WinBits nStyle )
+{
+ if ( nStyle & WB_DRAG )
+ mbFullDrag = TRUE;
+ else
+ mbFullDrag = (GetSettings().GetStyleSettings().GetDragFullOptions() & DRAGFULL_OPTION_SCROLL) != 0;
+}
+
+// -----------------------------------------------------------------------
+
+ScrollBar::ScrollBar( Window* pParent, WinBits nStyle ) :
+ Control( WINDOW_SCROLLBAR )
+{
+ ImplInit( pParent, nStyle );
+}
+
+// -----------------------------------------------------------------------
+
+ScrollBar::ScrollBar( Window* pParent, const ResId& rResId ) :
+ Control( WINDOW_SCROLLBAR )
+{
+ rResId.SetRT( RSC_SCROLLBAR );
+ WinBits nStyle = ImplInitRes( rResId );
+ ImplInit( pParent, nStyle );
+ ImplLoadRes( rResId );
+
+ if ( !(nStyle & WB_HIDE) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+ScrollBar::~ScrollBar()
+{
+ if( mpData )
+ delete mpData;
+}
+
+// -----------------------------------------------------------------------
+
+void ScrollBar::ImplLoadRes( const ResId& rResId )
+{
+ Control::ImplLoadRes( rResId );
+
+ INT16 nMin = ReadShortRes();
+ INT16 nMax = ReadShortRes();
+ INT16 nThumbPos = ReadShortRes();
+ INT16 nPage = ReadShortRes();
+ INT16 nStep = ReadShortRes();
+ INT16 nVisibleSize = ReadShortRes();
+
+ SetRange( Range( nMin, nMax ) );
+ SetLineSize( nStep );
+ SetPageSize( nPage );
+ SetVisibleSize( nVisibleSize );
+ SetThumbPos( nThumbPos );
+}
+
+// -----------------------------------------------------------------------
+
+void ScrollBar::ImplUpdateRects( BOOL bUpdate )
+{
+ USHORT nOldStateFlags = mnStateFlags;
+ Rectangle aOldPage1Rect = maPage1Rect;
+ Rectangle aOldPage2Rect = maPage2Rect;
+ Rectangle aOldThumbRect = maThumbRect;
+
+ mnStateFlags &= ~SCRBAR_STATE_BTN1_DISABLE;
+ mnStateFlags &= ~SCRBAR_STATE_BTN2_DISABLE;
+
+ Rectangle& maTrackRect = mpData->maTrackRect; // TODO: remove when maTrackRect is no longer in mpData
+ if ( mnThumbPixRange )
+ {
+ if ( GetStyle() & WB_HORZ )
+ {
+ maThumbRect.Left() = maTrackRect.Left()+mnThumbPixPos;
+ maThumbRect.Right() = maThumbRect.Left()+mnThumbPixSize-1;
+ if ( !mnThumbPixPos )
+ maPage1Rect.Right() = RECT_EMPTY;
+ else
+ maPage1Rect.Right() = maThumbRect.Left()-1;
+ if ( mnThumbPixPos >= (mnThumbPixRange-mnThumbPixSize) )
+ maPage2Rect.Right() = RECT_EMPTY;
+ else
+ {
+ maPage2Rect.Left() = maThumbRect.Right()+1;
+ maPage2Rect.Right() = maTrackRect.Right();
+ }
+ }
+ else
+ {
+ maThumbRect.Top() = maTrackRect.Top()+mnThumbPixPos;
+ maThumbRect.Bottom() = maThumbRect.Top()+mnThumbPixSize-1;
+ if ( !mnThumbPixPos )
+ maPage1Rect.Bottom() = RECT_EMPTY;
+ else
+ maPage1Rect.Bottom() = maThumbRect.Top()-1;
+ if ( mnThumbPixPos >= (mnThumbPixRange-mnThumbPixSize) )
+ maPage2Rect.Bottom() = RECT_EMPTY;
+ else
+ {
+ maPage2Rect.Top() = maThumbRect.Bottom()+1;
+ maPage2Rect.Bottom() = maTrackRect.Bottom();
+ }
+ }
+ }
+ else
+ {
+ Size aScrBarSize = GetOutputSizePixel();
+ if ( GetStyle() & WB_HORZ )
+ {
+ const long nSpace = maTrackRect.Right() - maTrackRect.Left();
+ if ( nSpace > 0 )
+ {
+ maPage1Rect.Left() = maTrackRect.Left();
+ maPage1Rect.Right() = maTrackRect.Left() + (nSpace/2);
+ maPage2Rect.Left() = maPage1Rect.Right() + 1;
+ maPage2Rect.Right() = maTrackRect.Right();
+ }
+ }
+ else
+ {
+ const long nSpace = maTrackRect.Bottom() - maTrackRect.Top();
+ if ( nSpace > 0 )
+ {
+ maPage1Rect.Top() = maTrackRect.Top();
+ maPage1Rect.Bottom() = maTrackRect.Top() + (nSpace/2);
+ maPage2Rect.Top() = maPage1Rect.Bottom() + 1;
+ maPage2Rect.Bottom() = maTrackRect.Bottom();
+ }
+ }
+ }
+
+ if( !IsNativeControlSupported(CTRL_SCROLLBAR, PART_ENTIRE_CONTROL) )
+ {
+ // disable scrollbar buttons only in VCL's own 'theme'
+ // as it is uncommon on other platforms
+ if ( mnThumbPos == mnMinRange )
+ mnStateFlags |= SCRBAR_STATE_BTN1_DISABLE;
+ if ( mnThumbPos >= (mnMaxRange-mnVisibleSize) )
+ mnStateFlags |= SCRBAR_STATE_BTN2_DISABLE;
+ }
+
+ if ( bUpdate )
+ {
+ USHORT nDraw = 0;
+ if ( (nOldStateFlags & SCRBAR_STATE_BTN1_DISABLE) !=
+ (mnStateFlags & SCRBAR_STATE_BTN1_DISABLE) )
+ nDraw |= SCRBAR_DRAW_BTN1;
+ if ( (nOldStateFlags & SCRBAR_STATE_BTN2_DISABLE) !=
+ (mnStateFlags & SCRBAR_STATE_BTN2_DISABLE) )
+ nDraw |= SCRBAR_DRAW_BTN2;
+ if ( aOldPage1Rect != maPage1Rect )
+ nDraw |= SCRBAR_DRAW_PAGE1;
+ if ( aOldPage2Rect != maPage2Rect )
+ nDraw |= SCRBAR_DRAW_PAGE2;
+ if ( aOldThumbRect != maThumbRect )
+ nDraw |= SCRBAR_DRAW_THUMB;
+ ImplDraw( nDraw, this );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+long ScrollBar::ImplCalcThumbPos( long nPixPos )
+{
+ // Position berechnen
+ long nCalcThumbPos;
+ nCalcThumbPos = ImplMulDiv( nPixPos, mnMaxRange-mnVisibleSize-mnMinRange,
+ mnThumbPixRange-mnThumbPixSize );
+ nCalcThumbPos += mnMinRange;
+ return nCalcThumbPos;
+}
+
+// -----------------------------------------------------------------------
+
+long ScrollBar::ImplCalcThumbPosPix( long nPos )
+{
+ long nCalcThumbPos;
+
+ // Position berechnen
+ nCalcThumbPos = ImplMulDiv( nPos-mnMinRange, mnThumbPixRange-mnThumbPixSize,
+ mnMaxRange-mnVisibleSize-mnMinRange );
+
+ // Am Anfang und Ende des ScrollBars versuchen wir die Anzeige korrekt
+ // anzuzeigen
+ if ( !nCalcThumbPos && (mnThumbPos > mnMinRange) )
+ nCalcThumbPos = 1;
+ if ( nCalcThumbPos &&
+ ((nCalcThumbPos+mnThumbPixSize) >= mnThumbPixRange) &&
+ (mnThumbPos < (mnMaxRange-mnVisibleSize)) )
+ nCalcThumbPos--;
+
+ return nCalcThumbPos;
+}
+
+// -----------------------------------------------------------------------
+
+void ScrollBar::ImplCalc( BOOL bUpdate )
+{
+ const Size aSize = GetOutputSizePixel();
+ const long nMinThumbSize = GetSettings().GetStyleSettings().GetMinThumbSize();;
+
+ Rectangle& maTrackRect = mpData->maTrackRect; // TODO: remove when maTrackRect is no longer in mpData
+ if ( mbCalcSize )
+ {
+ const Rectangle aControlRegion( Point(0,0), aSize );
+ Rectangle aBtn1Region, aBtn2Region, aTrackRegion, aBoundingRegion;
+
+ if ( GetStyle() & WB_HORZ )
+ {
+ if ( GetNativeControlRegion( CTRL_SCROLLBAR, PART_BUTTON_LEFT,
+ aControlRegion, 0, ImplControlValue(), rtl::OUString(), aBoundingRegion, aBtn1Region ) &&
+ GetNativeControlRegion( CTRL_SCROLLBAR, PART_BUTTON_RIGHT,
+ aControlRegion, 0, ImplControlValue(), rtl::OUString(), aBoundingRegion, aBtn2Region ) )
+ {
+ maBtn1Rect = aBtn1Region;
+ maBtn2Rect = aBtn2Region;
+ }
+ else
+ {
+ Size aBtnSize( aSize.Height(), aSize.Height() );
+ maBtn2Rect.Top() = maBtn1Rect.Top();
+ maBtn2Rect.Left() = aSize.Width()-aSize.Height();
+ maBtn1Rect.SetSize( aBtnSize );
+ maBtn2Rect.SetSize( aBtnSize );
+ }
+
+ if ( GetNativeControlRegion( CTRL_SCROLLBAR, PART_TRACK_HORZ_AREA,
+ aControlRegion, 0, ImplControlValue(), rtl::OUString(), aBoundingRegion, aTrackRegion ) )
+ maTrackRect = aTrackRegion;
+ else
+ maTrackRect = Rectangle( maBtn1Rect.TopRight(), maBtn2Rect.BottomLeft() );
+
+ // Check if available space is big enough for thumb ( min thumb size = ScrBar width/height )
+ mnThumbPixRange = maTrackRect.Right() - maTrackRect.Left();
+ if( mnThumbPixRange > 0 )
+ {
+ maPage1Rect.Left() = maTrackRect.Left();
+ maPage1Rect.Bottom() =
+ maPage2Rect.Bottom() =
+ maThumbRect.Bottom() = maTrackRect.Bottom();
+ }
+ else
+ {
+ mnThumbPixRange = 0;
+ maPage1Rect.SetEmpty();
+ maPage2Rect.SetEmpty();
+ }
+ }
+ else
+ {
+ if ( GetNativeControlRegion( CTRL_SCROLLBAR, PART_BUTTON_UP,
+ aControlRegion, 0, ImplControlValue(), rtl::OUString(), aBoundingRegion, aBtn1Region ) &&
+ GetNativeControlRegion( CTRL_SCROLLBAR, PART_BUTTON_DOWN,
+ aControlRegion, 0, ImplControlValue(), rtl::OUString(), aBoundingRegion, aBtn2Region ) )
+ {
+ maBtn1Rect = aBtn1Region;
+ maBtn2Rect = aBtn2Region;
+ }
+ else
+ {
+ const Size aBtnSize( aSize.Width(), aSize.Width() );
+ maBtn2Rect.Left() = maBtn1Rect.Left();
+ maBtn2Rect.Top() = aSize.Height()-aSize.Width();
+ maBtn1Rect.SetSize( aBtnSize );
+ maBtn2Rect.SetSize( aBtnSize );
+ }
+
+ if ( GetNativeControlRegion( CTRL_SCROLLBAR, PART_TRACK_VERT_AREA,
+ aControlRegion, 0, ImplControlValue(), rtl::OUString(), aBoundingRegion, aTrackRegion ) )
+ maTrackRect = aTrackRegion;
+ else
+ maTrackRect = Rectangle( maBtn1Rect.BottomLeft()+Point(0,1), maBtn2Rect.TopRight() );
+
+ // Check if available space is big enough for thumb
+ mnThumbPixRange = maTrackRect.Bottom() - maTrackRect.Top();
+ if( mnThumbPixRange > 0 )
+ {
+ maPage1Rect.Top() = maTrackRect.Top();
+ maPage1Rect.Right() =
+ maPage2Rect.Right() =
+ maThumbRect.Right() = maTrackRect.Right();
+ }
+ else
+ {
+ mnThumbPixRange = 0;
+ maPage1Rect.SetEmpty();
+ maPage2Rect.SetEmpty();
+ }
+ }
+
+ if ( !mnThumbPixRange )
+ maThumbRect.SetEmpty();
+
+ mbCalcSize = FALSE;
+ }
+
+ if ( mnThumbPixRange )
+ {
+ // Werte berechnen
+ if ( (mnVisibleSize >= (mnMaxRange-mnMinRange)) ||
+ ((mnMaxRange-mnMinRange) <= 0) )
+ {
+ mnThumbPos = mnMinRange;
+ mnThumbPixPos = 0;
+ mnThumbPixSize = mnThumbPixRange;
+ }
+ else
+ {
+ if ( mnVisibleSize )
+ mnThumbPixSize = ImplMulDiv( mnThumbPixRange, mnVisibleSize, mnMaxRange-mnMinRange );
+ else
+ {
+ if ( GetStyle() & WB_HORZ )
+ mnThumbPixSize = maThumbRect.GetWidth();
+ else
+ mnThumbPixSize = maThumbRect.GetHeight();
+ }
+ if ( mnThumbPixSize < nMinThumbSize )
+ mnThumbPixSize = nMinThumbSize;
+ if ( mnThumbPixSize > mnThumbPixRange )
+ mnThumbPixSize = mnThumbPixRange;
+ mnThumbPixPos = ImplCalcThumbPosPix( mnThumbPos );
+ }
+ }
+
+ // Wenn neu ausgegeben werden soll und wir schon ueber eine
+ // Aktion einen Paint-Event ausgeloest bekommen haben, dann
+ // geben wir nicht direkt aus, sondern invalidieren nur alles
+ if ( bUpdate && HasPaintEvent() )
+ {
+ Invalidate();
+ bUpdate = FALSE;
+ }
+ ImplUpdateRects( bUpdate );
+}
+
+// -----------------------------------------------------------------------
+
+void ScrollBar::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize, ULONG nFlags )
+{
+ Point aPos = pDev->LogicToPixel( rPos );
+ Size aSize = pDev->LogicToPixel( rSize );
+ Rectangle aRect( aPos, aSize );
+
+ pDev->Push();
+ pDev->SetMapMode();
+ if ( !(nFlags & WINDOW_DRAW_MONO) )
+ {
+ // DecoView uses the FaceColor...
+ AllSettings aSettings = pDev->GetSettings();
+ StyleSettings aStyleSettings = aSettings.GetStyleSettings();
+ if ( IsControlBackground() )
+ aStyleSettings.SetFaceColor( GetControlBackground() );
+ else
+ aStyleSettings.SetFaceColor( GetSettings().GetStyleSettings().GetFaceColor() );
+
+ aSettings.SetStyleSettings( aStyleSettings );
+ pDev->SetSettings( aSettings );
+ }
+
+ // for printing:
+ // -calculate the size of the rects
+ // -because this is zero-based add the correct offset
+ // -print
+ // -force recalculate
+
+ if ( mbCalcSize )
+ ImplCalc( FALSE );
+
+ maBtn1Rect+=aPos;
+ maBtn2Rect+=aPos;
+ maThumbRect+=aPos;
+ mpData->maTrackRect+=aPos; // TODO: update when maTrackRect is no longer in mpData
+ maPage1Rect+=aPos;
+ maPage2Rect+=aPos;
+
+ ImplDraw( SCRBAR_DRAW_ALL, pDev );
+ pDev->Pop();
+
+ mbCalcSize = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ScrollBar::ImplDrawNative( USHORT nDrawFlags )
+{
+ ScrollbarValue scrValue;
+
+ BOOL bNativeOK = IsNativeControlSupported(CTRL_SCROLLBAR, PART_ENTIRE_CONTROL);
+ if( bNativeOK )
+ {
+ BOOL bHorz = (GetStyle() & WB_HORZ ? true : false);
+
+ // Draw the entire background if the control supports it
+ if( IsNativeControlSupported(CTRL_SCROLLBAR, bHorz ? PART_DRAW_BACKGROUND_HORZ : PART_DRAW_BACKGROUND_VERT) )
+ {
+ ControlState nState = ( IsEnabled() ? CTRL_STATE_ENABLED : 0 ) | ( HasFocus() ? CTRL_STATE_FOCUSED : 0 );
+
+ scrValue.mnMin = mnMinRange;
+ scrValue.mnMax = mnMaxRange;
+ scrValue.mnCur = mnThumbPos;
+ scrValue.mnVisibleSize = mnVisibleSize;
+ scrValue.maThumbRect = maThumbRect;
+ scrValue.maButton1Rect = maBtn1Rect;
+ scrValue.maButton2Rect = maBtn2Rect;
+ scrValue.mnButton1State = ((mnStateFlags & SCRBAR_STATE_BTN1_DOWN) ? CTRL_STATE_PRESSED : 0) |
+ ((!(mnStateFlags & SCRBAR_STATE_BTN1_DISABLE)) ? CTRL_STATE_ENABLED : 0);
+ scrValue.mnButton2State = ((mnStateFlags & SCRBAR_STATE_BTN2_DOWN) ? CTRL_STATE_PRESSED : 0) |
+ ((!(mnStateFlags & SCRBAR_STATE_BTN2_DISABLE)) ? CTRL_STATE_ENABLED : 0);
+ scrValue.mnThumbState = nState | ((mnStateFlags & SCRBAR_STATE_THUMB_DOWN) ? CTRL_STATE_PRESSED : 0);
+ scrValue.mnPage1State = nState | ((mnStateFlags & SCRBAR_STATE_PAGE1_DOWN) ? CTRL_STATE_PRESSED : 0);
+ scrValue.mnPage2State = nState | ((mnStateFlags & SCRBAR_STATE_PAGE2_DOWN) ? CTRL_STATE_PRESSED : 0);
+
+ if( IsMouseOver() )
+ {
+ Rectangle* pRect = ImplFindPartRect( GetPointerPosPixel() );
+ if( pRect )
+ {
+ if( pRect == &maThumbRect )
+ scrValue.mnThumbState |= CTRL_STATE_ROLLOVER;
+ else if( pRect == &maBtn1Rect )
+ scrValue.mnButton1State |= CTRL_STATE_ROLLOVER;
+ else if( pRect == &maBtn2Rect )
+ scrValue.mnButton2State |= CTRL_STATE_ROLLOVER;
+ else if( pRect == &maPage1Rect )
+ scrValue.mnPage1State |= CTRL_STATE_ROLLOVER;
+ else if( pRect == &maPage2Rect )
+ scrValue.mnPage2State |= CTRL_STATE_ROLLOVER;
+ }
+ }
+
+ Rectangle aCtrlRegion;
+ aCtrlRegion.Union( maBtn1Rect );
+ aCtrlRegion.Union( maBtn2Rect );
+ aCtrlRegion.Union( maPage1Rect );
+ aCtrlRegion.Union( maPage2Rect );
+ aCtrlRegion.Union( maThumbRect );
+ bNativeOK = DrawNativeControl( CTRL_SCROLLBAR, (bHorz ? PART_DRAW_BACKGROUND_HORZ : PART_DRAW_BACKGROUND_VERT),
+ aCtrlRegion, nState, scrValue, rtl::OUString() );
+ }
+ else
+ {
+ if ( (nDrawFlags & SCRBAR_DRAW_PAGE1) || (nDrawFlags & SCRBAR_DRAW_PAGE2) )
+ {
+ sal_uInt32 part1 = bHorz ? PART_TRACK_HORZ_LEFT : PART_TRACK_VERT_UPPER;
+ sal_uInt32 part2 = bHorz ? PART_TRACK_HORZ_RIGHT : PART_TRACK_VERT_LOWER;
+ Rectangle aCtrlRegion1( maPage1Rect );
+ Rectangle aCtrlRegion2( maPage2Rect );
+ ControlState nState1 = (IsEnabled() ? CTRL_STATE_ENABLED : 0) | (HasFocus() ? CTRL_STATE_FOCUSED : 0);
+ ControlState nState2 = nState1;
+
+ nState1 |= ((mnStateFlags & SCRBAR_STATE_PAGE1_DOWN) ? CTRL_STATE_PRESSED : 0);
+ nState2 |= ((mnStateFlags & SCRBAR_STATE_PAGE2_DOWN) ? CTRL_STATE_PRESSED : 0);
+
+ if( IsMouseOver() )
+ {
+ Rectangle* pRect = ImplFindPartRect( GetPointerPosPixel() );
+ if( pRect )
+ {
+ if( pRect == &maPage1Rect )
+ nState1 |= CTRL_STATE_ROLLOVER;
+ else if( pRect == &maPage2Rect )
+ nState2 |= CTRL_STATE_ROLLOVER;
+ }
+ }
+
+ if ( nDrawFlags & SCRBAR_DRAW_PAGE1 )
+ bNativeOK = DrawNativeControl( CTRL_SCROLLBAR, part1, aCtrlRegion1, nState1,
+ scrValue, rtl::OUString() );
+
+ if ( nDrawFlags & SCRBAR_DRAW_PAGE2 )
+ bNativeOK = DrawNativeControl( CTRL_SCROLLBAR, part2, aCtrlRegion2, nState2,
+ scrValue, rtl::OUString() );
+ }
+ if ( (nDrawFlags & SCRBAR_DRAW_BTN1) || (nDrawFlags & SCRBAR_DRAW_BTN2) )
+ {
+ sal_uInt32 part1 = bHorz ? PART_BUTTON_LEFT : PART_BUTTON_UP;
+ sal_uInt32 part2 = bHorz ? PART_BUTTON_RIGHT : PART_BUTTON_DOWN;
+ Rectangle aCtrlRegion1( maBtn1Rect );
+ Rectangle aCtrlRegion2( maBtn2Rect );
+ ControlState nState1 = HasFocus() ? CTRL_STATE_FOCUSED : 0;
+ ControlState nState2 = nState1;
+
+ if ( !Window::IsEnabled() || !IsEnabled() )
+ nState1 = (nState2 &= ~CTRL_STATE_ENABLED);
+ else
+ nState1 = (nState2 |= CTRL_STATE_ENABLED);
+
+ nState1 |= ((mnStateFlags & SCRBAR_STATE_BTN1_DOWN) ? CTRL_STATE_PRESSED : 0);
+ nState2 |= ((mnStateFlags & SCRBAR_STATE_BTN2_DOWN) ? CTRL_STATE_PRESSED : 0);
+
+ if(mnStateFlags & SCRBAR_STATE_BTN1_DISABLE)
+ nState1 &= ~CTRL_STATE_ENABLED;
+ if(mnStateFlags & SCRBAR_STATE_BTN2_DISABLE)
+ nState2 &= ~CTRL_STATE_ENABLED;
+
+ if( IsMouseOver() )
+ {
+ Rectangle* pRect = ImplFindPartRect( GetPointerPosPixel() );
+ if( pRect )
+ {
+ if( pRect == &maBtn1Rect )
+ nState1 |= CTRL_STATE_ROLLOVER;
+ else if( pRect == &maBtn2Rect )
+ nState2 |= CTRL_STATE_ROLLOVER;
+ }
+ }
+
+ if ( nDrawFlags & SCRBAR_DRAW_BTN1 )
+ bNativeOK = DrawNativeControl( CTRL_SCROLLBAR, part1, aCtrlRegion1, nState1,
+ scrValue, rtl::OUString() );
+
+ if ( nDrawFlags & SCRBAR_DRAW_BTN2 )
+ bNativeOK = DrawNativeControl( CTRL_SCROLLBAR, part2, aCtrlRegion2, nState2,
+ scrValue, rtl::OUString() );
+ }
+ if ( (nDrawFlags & SCRBAR_DRAW_THUMB) && !maThumbRect.IsEmpty() )
+ {
+ ControlState nState = IsEnabled() ? CTRL_STATE_ENABLED : 0;
+ Rectangle aCtrlRegion( maThumbRect );
+
+ if ( mnStateFlags & SCRBAR_STATE_THUMB_DOWN )
+ nState |= CTRL_STATE_PRESSED;
+
+ if ( HasFocus() )
+ nState |= CTRL_STATE_FOCUSED;
+
+ if( IsMouseOver() )
+ {
+ Rectangle* pRect = ImplFindPartRect( GetPointerPosPixel() );
+ if( pRect )
+ {
+ if( pRect == &maThumbRect )
+ nState |= CTRL_STATE_ROLLOVER;
+ }
+ }
+
+ bNativeOK = DrawNativeControl( CTRL_SCROLLBAR, (bHorz ? PART_THUMB_HORZ : PART_THUMB_VERT),
+ aCtrlRegion, nState, scrValue, rtl::OUString() );
+ }
+ }
+ }
+ return bNativeOK;
+}
+
+void ScrollBar::ImplDraw( USHORT nDrawFlags, OutputDevice* pOutDev )
+{
+ DecorationView aDecoView( pOutDev );
+ Rectangle aTempRect;
+ USHORT nStyle;
+ const StyleSettings& rStyleSettings = pOutDev->GetSettings().GetStyleSettings();
+ SymbolType eSymbolType;
+ BOOL bEnabled = IsEnabled();
+
+ // Evt. noch offene Berechnungen nachholen
+ if ( mbCalcSize )
+ ImplCalc( FALSE );
+
+ Window *pWin = NULL;
+ if( pOutDev->GetOutDevType() == OUTDEV_WINDOW )
+ pWin = (Window*) pOutDev;
+
+ // Draw the entire control if the native theme engine needs it
+ if ( nDrawFlags && pWin && pWin->IsNativeControlSupported(CTRL_SCROLLBAR, PART_DRAW_BACKGROUND_HORZ) )
+ {
+ ImplDrawNative( SCRBAR_DRAW_BACKGROUND );
+ return;
+ }
+
+ if( (nDrawFlags & SCRBAR_DRAW_BTN1) && (!pWin || !ImplDrawNative( SCRBAR_DRAW_BTN1 ) ) )
+ {
+ nStyle = BUTTON_DRAW_NOLIGHTBORDER;
+ if ( mnStateFlags & SCRBAR_STATE_BTN1_DOWN )
+ nStyle |= BUTTON_DRAW_PRESSED;
+ aTempRect = aDecoView.DrawButton( maBtn1Rect, nStyle );
+ ImplCalcSymbolRect( aTempRect );
+ nStyle = 0;
+ if ( (mnStateFlags & SCRBAR_STATE_BTN1_DISABLE) || !bEnabled )
+ nStyle |= SYMBOL_DRAW_DISABLE;
+ if ( rStyleSettings.GetOptions() & STYLE_OPTION_SCROLLARROW )
+ {
+ if ( GetStyle() & WB_HORZ )
+ eSymbolType = SYMBOL_ARROW_LEFT;
+ else
+ eSymbolType = SYMBOL_ARROW_UP;
+ }
+ else
+ {
+ if ( GetStyle() & WB_HORZ )
+ eSymbolType = SYMBOL_SPIN_LEFT;
+ else
+ eSymbolType = SYMBOL_SPIN_UP;
+ }
+ aDecoView.DrawSymbol( aTempRect, eSymbolType, rStyleSettings.GetButtonTextColor(), nStyle );
+ }
+
+ if ( (nDrawFlags & SCRBAR_DRAW_BTN2) && (!pWin || !ImplDrawNative( SCRBAR_DRAW_BTN2 ) ) )
+ {
+ nStyle = BUTTON_DRAW_NOLIGHTBORDER;
+ if ( mnStateFlags & SCRBAR_STATE_BTN2_DOWN )
+ nStyle |= BUTTON_DRAW_PRESSED;
+ aTempRect = aDecoView.DrawButton( maBtn2Rect, nStyle );
+ ImplCalcSymbolRect( aTempRect );
+ nStyle = 0;
+ if ( (mnStateFlags & SCRBAR_STATE_BTN2_DISABLE) || !bEnabled )
+ nStyle |= SYMBOL_DRAW_DISABLE;
+ if ( rStyleSettings.GetOptions() & STYLE_OPTION_SCROLLARROW )
+ {
+ if ( GetStyle() & WB_HORZ )
+ eSymbolType = SYMBOL_ARROW_RIGHT;
+ else
+ eSymbolType = SYMBOL_ARROW_DOWN;
+ }
+ else
+ {
+ if ( GetStyle() & WB_HORZ )
+ eSymbolType = SYMBOL_SPIN_RIGHT;
+ else
+ eSymbolType = SYMBOL_SPIN_DOWN;
+ }
+ aDecoView.DrawSymbol( aTempRect, eSymbolType, rStyleSettings.GetButtonTextColor(), nStyle );
+ }
+
+ pOutDev->SetLineColor();
+
+ if ( (nDrawFlags & SCRBAR_DRAW_THUMB) && (!pWin || !ImplDrawNative( SCRBAR_DRAW_THUMB ) ) )
+ {
+ if ( !maThumbRect.IsEmpty() )
+ {
+ if ( bEnabled )
+ {
+ nStyle = BUTTON_DRAW_NOLIGHTBORDER;
+ // pressed thumbs only in OS2 style
+ if ( rStyleSettings.GetOptions() & STYLE_OPTION_OS2STYLE )
+ if ( mnStateFlags & SCRBAR_STATE_THUMB_DOWN )
+ nStyle |= BUTTON_DRAW_PRESSED;
+ aTempRect = aDecoView.DrawButton( maThumbRect, nStyle );
+ // OS2 style requires pattern on the thumb
+ if ( rStyleSettings.GetOptions() & STYLE_OPTION_OS2STYLE )
+ {
+ if ( GetStyle() & WB_HORZ )
+ {
+ if ( aTempRect.GetWidth() > 6 )
+ {
+ long nX = aTempRect.Center().X();
+ nX -= 6;
+ if ( nX < aTempRect.Left() )
+ nX = aTempRect.Left();
+ for ( int i = 0; i < 6; i++ )
+ {
+ if ( nX > aTempRect.Right()-1 )
+ break;
+
+ pOutDev->SetLineColor( rStyleSettings.GetButtonTextColor() );
+ pOutDev->DrawLine( Point( nX, aTempRect.Top()+1 ),
+ Point( nX, aTempRect.Bottom()-1 ) );
+ nX++;
+ pOutDev->SetLineColor( rStyleSettings.GetLightColor() );
+ pOutDev->DrawLine( Point( nX, aTempRect.Top()+1 ),
+ Point( nX, aTempRect.Bottom()-1 ) );
+ nX++;
+ }
+ }
+ }
+ else
+ {
+ if ( aTempRect.GetHeight() > 6 )
+ {
+ long nY = aTempRect.Center().Y();
+ nY -= 6;
+ if ( nY < aTempRect.Top() )
+ nY = aTempRect.Top();
+ for ( int i = 0; i < 6; i++ )
+ {
+ if ( nY > aTempRect.Bottom()-1 )
+ break;
+
+ pOutDev->SetLineColor( rStyleSettings.GetButtonTextColor() );
+ pOutDev->DrawLine( Point( aTempRect.Left()+1, nY ),
+ Point( aTempRect.Right()-1, nY ) );
+ nY++;
+ pOutDev->SetLineColor( rStyleSettings.GetLightColor() );
+ pOutDev->DrawLine( Point( aTempRect.Left()+1, nY ),
+ Point( aTempRect.Right()-1, nY ) );
+ nY++;
+ }
+ }
+ }
+ pOutDev->SetLineColor();
+ }
+ }
+ else
+ {
+ pOutDev->SetFillColor( rStyleSettings.GetCheckedColor() );
+ pOutDev->DrawRect( maThumbRect );
+ }
+ }
+ }
+
+ if ( (nDrawFlags & SCRBAR_DRAW_PAGE1) && (!pWin || !ImplDrawNative( SCRBAR_DRAW_PAGE1 ) ) )
+ {
+ if ( mnStateFlags & SCRBAR_STATE_PAGE1_DOWN )
+ pOutDev->SetFillColor( rStyleSettings.GetShadowColor() );
+ else
+ pOutDev->SetFillColor( rStyleSettings.GetCheckedColor() );
+ pOutDev->DrawRect( maPage1Rect );
+ }
+ if ( (nDrawFlags & SCRBAR_DRAW_PAGE2) && (!pWin || !ImplDrawNative( SCRBAR_DRAW_PAGE2 ) ) )
+ {
+ if ( mnStateFlags & SCRBAR_STATE_PAGE2_DOWN )
+ pOutDev->SetFillColor( rStyleSettings.GetShadowColor() );
+ else
+ pOutDev->SetFillColor( rStyleSettings.GetCheckedColor() );
+ pOutDev->DrawRect( maPage2Rect );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+long ScrollBar::ImplScroll( long nNewPos, BOOL bCallEndScroll )
+{
+ long nOldPos = mnThumbPos;
+ SetThumbPos( nNewPos );
+ long nDelta = mnThumbPos-nOldPos;
+ if ( nDelta )
+ {
+ mnDelta = nDelta;
+ Scroll();
+ if ( bCallEndScroll )
+ EndScroll();
+ mnDelta = 0;
+ }
+ return nDelta;
+}
+
+// -----------------------------------------------------------------------
+
+long ScrollBar::ImplDoAction( BOOL bCallEndScroll )
+{
+ long nDelta = 0;
+
+ switch ( meScrollType )
+ {
+ case SCROLL_LINEUP:
+ nDelta = ImplScroll( mnThumbPos-mnLineSize, bCallEndScroll );
+ break;
+
+ case SCROLL_LINEDOWN:
+ nDelta = ImplScroll( mnThumbPos+mnLineSize, bCallEndScroll );
+ break;
+
+ case SCROLL_PAGEUP:
+ nDelta = ImplScroll( mnThumbPos-mnPageSize, bCallEndScroll );
+ break;
+
+ case SCROLL_PAGEDOWN:
+ nDelta = ImplScroll( mnThumbPos+mnPageSize, bCallEndScroll );
+ break;
+ default:
+ ;
+ }
+
+ return nDelta;
+}
+
+// -----------------------------------------------------------------------
+
+void ScrollBar::ImplDoMouseAction( const Point& rMousePos, BOOL bCallAction )
+{
+ USHORT nOldStateFlags = mnStateFlags;
+ BOOL bAction = FALSE;
+ BOOL bHorizontal = ( GetStyle() & WB_HORZ )? TRUE: FALSE;
+ BOOL bIsInside = FALSE;
+
+ Point aPoint( 0, 0 );
+ Rectangle aControlRegion( aPoint, GetOutputSizePixel() );
+
+ switch ( meScrollType )
+ {
+ case SCROLL_LINEUP:
+ if ( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? PART_BUTTON_LEFT: PART_BUTTON_UP,
+ aControlRegion, rMousePos, bIsInside )?
+ bIsInside:
+ maBtn1Rect.IsInside( rMousePos ) )
+ {
+ bAction = bCallAction;
+ mnStateFlags |= SCRBAR_STATE_BTN1_DOWN;
+ }
+ else
+ mnStateFlags &= ~SCRBAR_STATE_BTN1_DOWN;
+ break;
+
+ case SCROLL_LINEDOWN:
+ if ( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? PART_BUTTON_RIGHT: PART_BUTTON_DOWN,
+ aControlRegion, rMousePos, bIsInside )?
+ bIsInside:
+ maBtn2Rect.IsInside( rMousePos ) )
+ {
+ bAction = bCallAction;
+ mnStateFlags |= SCRBAR_STATE_BTN2_DOWN;
+ }
+ else
+ mnStateFlags &= ~SCRBAR_STATE_BTN2_DOWN;
+ break;
+
+ case SCROLL_PAGEUP:
+ // HitTestNativeControl, see remark at top of file
+ if ( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? PART_TRACK_HORZ_LEFT: PART_TRACK_VERT_UPPER,
+ maPage1Rect, rMousePos, bIsInside )?
+ bIsInside:
+ maPage1Rect.IsInside( rMousePos ) )
+ {
+ bAction = bCallAction;
+ mnStateFlags |= SCRBAR_STATE_PAGE1_DOWN;
+ }
+ else
+ mnStateFlags &= ~SCRBAR_STATE_PAGE1_DOWN;
+ break;
+
+ case SCROLL_PAGEDOWN:
+ // HitTestNativeControl, see remark at top of file
+ if ( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? PART_TRACK_HORZ_RIGHT: PART_TRACK_VERT_LOWER,
+ maPage2Rect, rMousePos, bIsInside )?
+ bIsInside:
+ maPage2Rect.IsInside( rMousePos ) )
+ {
+ bAction = bCallAction;
+ mnStateFlags |= SCRBAR_STATE_PAGE2_DOWN;
+ }
+ else
+ mnStateFlags &= ~SCRBAR_STATE_PAGE2_DOWN;
+ break;
+ default:
+ ;
+ }
+
+ if ( nOldStateFlags != mnStateFlags )
+ ImplDraw( mnDragDraw, this );
+ if ( bAction )
+ ImplDoAction( FALSE );
+}
+
+// -----------------------------------------------------------------------
+
+void ScrollBar::ImplDragThumb( const Point& rMousePos )
+{
+ long nMovePix;
+ if ( GetStyle() & WB_HORZ )
+ nMovePix = rMousePos.X()-(maThumbRect.Left()+mnMouseOff);
+ else
+ nMovePix = rMousePos.Y()-(maThumbRect.Top()+mnMouseOff);
+
+ // move thumb if necessary
+ if ( nMovePix )
+ {
+ mnThumbPixPos += nMovePix;
+ if ( mnThumbPixPos < 0 )
+ mnThumbPixPos = 0;
+ if ( mnThumbPixPos > (mnThumbPixRange-mnThumbPixSize) )
+ mnThumbPixPos = mnThumbPixRange-mnThumbPixSize;
+ long nOldPos = mnThumbPos;
+ mnThumbPos = ImplCalcThumbPos( mnThumbPixPos );
+ ImplUpdateRects();
+ if ( mbFullDrag && (nOldPos != mnThumbPos) )
+ {
+ mnDelta = mnThumbPos-nOldPos;
+ Scroll();
+ mnDelta = 0;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ScrollBar::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ if ( rMEvt.IsLeft() || rMEvt.IsMiddle() )
+ {
+ const Point& rMousePos = rMEvt.GetPosPixel();
+ USHORT nTrackFlags = 0;
+ BOOL bHorizontal = ( GetStyle() & WB_HORZ )? TRUE: FALSE;
+ BOOL bIsInside = FALSE;
+ BOOL bDragToMouse = FALSE;
+
+ Point aPoint( 0, 0 );
+ Rectangle aControlRegion( aPoint, GetOutputSizePixel() );
+
+ if ( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? PART_BUTTON_LEFT: PART_BUTTON_UP,
+ aControlRegion, rMousePos, bIsInside )?
+ bIsInside:
+ maBtn1Rect.IsInside( rMousePos ) )
+ {
+ if ( !(mnStateFlags & SCRBAR_STATE_BTN1_DISABLE) )
+ {
+ nTrackFlags = STARTTRACK_BUTTONREPEAT;
+ meScrollType = SCROLL_LINEUP;
+ mnDragDraw = SCRBAR_DRAW_BTN1;
+ }
+ else
+ Sound::Beep( SOUND_DISABLE, this );
+ }
+ else if ( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? PART_BUTTON_RIGHT: PART_BUTTON_DOWN,
+ aControlRegion, rMousePos, bIsInside )?
+ bIsInside:
+ maBtn2Rect.IsInside( rMousePos ) )
+ {
+ if ( !(mnStateFlags & SCRBAR_STATE_BTN2_DISABLE) )
+ {
+ nTrackFlags = STARTTRACK_BUTTONREPEAT;
+ meScrollType = SCROLL_LINEDOWN;
+ mnDragDraw = SCRBAR_DRAW_BTN2;
+ }
+ else
+ Sound::Beep( SOUND_DISABLE, this );
+ }
+ else
+ {
+ bool bThumbHit = HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? PART_THUMB_HORZ : PART_THUMB_VERT,
+ maThumbRect, rMousePos, bIsInside )
+ ? bIsInside : maThumbRect.IsInside( rMousePos );
+ bool bDragHandling = rMEvt.IsMiddle() || bThumbHit || ImplGetSVData()->maNWFData.mbScrollbarJumpPage;
+ if( bDragHandling )
+ {
+ if( mpData )
+ {
+ mpData->mbHide = TRUE; // disable focus blinking
+ if( HasFocus() )
+ ImplDraw( SCRBAR_DRAW_THUMB, this ); // paint without focus
+ }
+
+ if ( mnVisibleSize < mnMaxRange-mnMinRange )
+ {
+ nTrackFlags = 0;
+ meScrollType = SCROLL_DRAG;
+ mnDragDraw = SCRBAR_DRAW_THUMB;
+
+ // calculate mouse offset
+ if( rMEvt.IsMiddle() || (ImplGetSVData()->maNWFData.mbScrollbarJumpPage && !bThumbHit) )
+ {
+ bDragToMouse = TRUE;
+ if ( GetStyle() & WB_HORZ )
+ mnMouseOff = maThumbRect.GetWidth()/2;
+ else
+ mnMouseOff = maThumbRect.GetHeight()/2;
+ }
+ else
+ {
+ if ( GetStyle() & WB_HORZ )
+ mnMouseOff = rMousePos.X()-maThumbRect.Left();
+ else
+ mnMouseOff = rMousePos.Y()-maThumbRect.Top();
+ }
+
+ mnStateFlags |= SCRBAR_STATE_THUMB_DOWN;
+ ImplDraw( mnDragDraw, this );
+ }
+ else
+ Sound::Beep( SOUND_DISABLE, this );
+ }
+ else if( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? PART_TRACK_HORZ_AREA : PART_TRACK_VERT_AREA,
+ aControlRegion, rMousePos, bIsInside )?
+ bIsInside : TRUE )
+ {
+ nTrackFlags = STARTTRACK_BUTTONREPEAT;
+
+ // HitTestNativeControl, see remark at top of file
+ if ( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? PART_TRACK_HORZ_LEFT : PART_TRACK_VERT_UPPER,
+ maPage1Rect, rMousePos, bIsInside )?
+ bIsInside:
+ maPage1Rect.IsInside( rMousePos ) )
+ {
+ meScrollType = SCROLL_PAGEUP;
+ mnDragDraw = SCRBAR_DRAW_PAGE1;
+ }
+ else
+ {
+ meScrollType = SCROLL_PAGEDOWN;
+ mnDragDraw = SCRBAR_DRAW_PAGE2;
+ }
+ }
+ }
+
+ // Soll Tracking gestartet werden
+ if ( meScrollType != SCROLL_DONTKNOW )
+ {
+ // remember original position in case of abort or EndScroll-Delta
+ mnStartPos = mnThumbPos;
+ // #92906# Call StartTracking() before ImplDoMouseAction(), otherwise
+ // MouseButtonUp() / EndTracking() may be called if somebody is spending
+ // a lot of time in the scroll handler
+ StartTracking( nTrackFlags );
+ ImplDoMouseAction( rMousePos );
+
+ if( bDragToMouse )
+ ImplDragThumb( rMousePos );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ScrollBar::Tracking( const TrackingEvent& rTEvt )
+{
+ if ( rTEvt.IsTrackingEnded() )
+ {
+ // Button und PageRect-Status wieder herstellen
+ USHORT nOldStateFlags = mnStateFlags;
+ mnStateFlags &= ~(SCRBAR_STATE_BTN1_DOWN | SCRBAR_STATE_BTN2_DOWN |
+ SCRBAR_STATE_PAGE1_DOWN | SCRBAR_STATE_PAGE2_DOWN |
+ SCRBAR_STATE_THUMB_DOWN);
+ if ( nOldStateFlags != mnStateFlags )
+ ImplDraw( mnDragDraw, this );
+ mnDragDraw = 0;
+
+ // Bei Abbruch, die alte ThumbPosition wieder herstellen
+ if ( rTEvt.IsTrackingCanceled() )
+ {
+ long nOldPos = mnThumbPos;
+ SetThumbPos( mnStartPos );
+ mnDelta = mnThumbPos-nOldPos;
+ Scroll();
+ }
+
+ if ( meScrollType == SCROLL_DRAG )
+ {
+ // Wenn gedragt wurde, berechnen wir den Thumb neu, damit
+ // er wieder auf einer gerundeten ThumbPosition steht
+ ImplCalc();
+
+ if ( !mbFullDrag && (mnStartPos != mnThumbPos) )
+ {
+ mnDelta = mnThumbPos-mnStartPos;
+ Scroll();
+ mnDelta = 0;
+ }
+ }
+
+ mnDelta = mnThumbPos-mnStartPos;
+ EndScroll();
+ mnDelta = 0;
+ meScrollType = SCROLL_DONTKNOW;
+
+ if( mpData )
+ mpData->mbHide = FALSE; // re-enable focus blinking
+ }
+ else
+ {
+ const Point rMousePos = rTEvt.GetMouseEvent().GetPosPixel();
+
+ // Dragging wird speziell behandelt
+ if ( meScrollType == SCROLL_DRAG )
+ ImplDragThumb( rMousePos );
+ else
+ ImplDoMouseAction( rMousePos, rTEvt.IsTrackingRepeat() );
+
+ // Wenn ScrollBar-Werte so umgesetzt wurden, das es nichts
+ // mehr zum Tracking gibt, dann berechen wir hier ab
+ if ( !IsVisible() || (mnVisibleSize >= (mnMaxRange-mnMinRange)) )
+ EndTracking();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ScrollBar::KeyInput( const KeyEvent& rKEvt )
+{
+ if ( !rKEvt.GetKeyCode().GetModifier() )
+ {
+ switch ( rKEvt.GetKeyCode().GetCode() )
+ {
+ case KEY_HOME:
+ DoScroll( 0 );
+ break;
+
+ case KEY_END:
+ DoScroll( GetRangeMax() );
+ break;
+
+ case KEY_LEFT:
+ case KEY_UP:
+ DoScrollAction( SCROLL_LINEUP );
+ break;
+
+ case KEY_RIGHT:
+ case KEY_DOWN:
+ DoScrollAction( SCROLL_LINEDOWN );
+ break;
+
+ case KEY_PAGEUP:
+ DoScrollAction( SCROLL_PAGEUP );
+ break;
+
+ case KEY_PAGEDOWN:
+ DoScrollAction( SCROLL_PAGEDOWN );
+ break;
+
+ default:
+ Control::KeyInput( rKEvt );
+ break;
+ }
+ }
+ else
+ Control::KeyInput( rKEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void ScrollBar::Paint( const Rectangle& )
+{
+ ImplDraw( SCRBAR_DRAW_ALL, this );
+}
+
+// -----------------------------------------------------------------------
+
+void ScrollBar::Resize()
+{
+ Control::Resize();
+ mbCalcSize = TRUE;
+ if ( IsReallyVisible() )
+ ImplCalc( FALSE );
+ Invalidate();
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( ScrollBar, ImplAutoTimerHdl, AutoTimer*, EMPTYARG )
+{
+ if( mpData && mpData->mbHide )
+ return 0;
+ ImplInvert();
+ return 0;
+}
+
+void ScrollBar::ImplInvert()
+{
+ Rectangle aRect( maThumbRect );
+ if( aRect.getWidth() > 4 )
+ {
+ aRect.Left() += 2;
+ aRect.Right() -= 2;
+ }
+ if( aRect.getHeight() > 4 )
+ {
+ aRect.Top() += 2;
+ aRect.Bottom() -= 2;
+ }
+
+ Invert( aRect, 0 );
+}
+
+// -----------------------------------------------------------------------
+
+void ScrollBar::GetFocus()
+{
+ if( !mpData )
+ {
+ mpData = new ImplScrollBarData;
+ mpData->maTimer.SetTimeoutHdl( LINK( this, ScrollBar, ImplAutoTimerHdl ) );
+ mpData->mbHide = FALSE;
+ }
+ ImplInvert(); // react immediately
+ mpData->maTimer.SetTimeout( GetSettings().GetStyleSettings().GetCursorBlinkTime() );
+ mpData->maTimer.Start();
+ Control::GetFocus();
+}
+
+// -----------------------------------------------------------------------
+
+void ScrollBar::LoseFocus()
+{
+ if( mpData )
+ mpData->maTimer.Stop();
+ ImplDraw( SCRBAR_DRAW_THUMB, this );
+
+ Control::LoseFocus();
+}
+
+// -----------------------------------------------------------------------
+
+void ScrollBar::StateChanged( StateChangedType nType )
+{
+ Control::StateChanged( nType );
+
+ if ( nType == STATE_CHANGE_INITSHOW )
+ ImplCalc( FALSE );
+ else if ( nType == STATE_CHANGE_DATA )
+ {
+ if ( IsReallyVisible() && IsUpdateMode() )
+ ImplCalc( TRUE );
+ }
+ else if ( nType == STATE_CHANGE_UPDATEMODE )
+ {
+ if ( IsReallyVisible() && IsUpdateMode() )
+ {
+ ImplCalc( FALSE );
+ Invalidate();
+ }
+ }
+ else if ( nType == STATE_CHANGE_ENABLE )
+ {
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_STYLE )
+ {
+ ImplInitStyle( GetStyle() );
+ if ( IsReallyVisible() && IsUpdateMode() )
+ {
+ if ( (GetPrevStyle() & SCRBAR_VIEW_STYLE) !=
+ (GetStyle() & SCRBAR_VIEW_STYLE) )
+ {
+ mbCalcSize = TRUE;
+ ImplCalc( FALSE );
+ Invalidate();
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ScrollBar::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ Control::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_STYLE) )
+ {
+ mbCalcSize = TRUE;
+ ImplCalc( FALSE );
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle* ScrollBar::ImplFindPartRect( const Point& rPt )
+{
+ BOOL bHorizontal = ( GetStyle() & WB_HORZ )? TRUE: FALSE;
+ BOOL bIsInside = FALSE;
+
+ Point aPoint( 0, 0 );
+ Rectangle aControlRegion( aPoint, GetOutputSizePixel() );
+
+ if( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? PART_BUTTON_LEFT: PART_BUTTON_UP,
+ aControlRegion, rPt, bIsInside )?
+ bIsInside:
+ maBtn1Rect.IsInside( rPt ) )
+ return &maBtn1Rect;
+ else if( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? PART_BUTTON_RIGHT: PART_BUTTON_DOWN,
+ aControlRegion, rPt, bIsInside )?
+ bIsInside:
+ maBtn2Rect.IsInside( rPt ) )
+ return &maBtn2Rect;
+ // HitTestNativeControl, see remark at top of file
+ else if( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal ? PART_TRACK_HORZ_LEFT : PART_TRACK_VERT_UPPER,
+ maPage1Rect, rPt, bIsInside)?
+ bIsInside:
+ maPage1Rect.IsInside( rPt ) )
+ return &maPage1Rect;
+ // HitTestNativeControl, see remark at top of file
+ else if( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal ? PART_TRACK_HORZ_RIGHT : PART_TRACK_VERT_LOWER,
+ maPage2Rect, rPt, bIsInside)?
+ bIsInside:
+ maPage2Rect.IsInside( rPt ) )
+ return &maPage2Rect;
+ // HitTestNativeControl, see remark at top of file
+ else if( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal ? PART_THUMB_HORZ : PART_THUMB_VERT,
+ maThumbRect, rPt, bIsInside)?
+ bIsInside:
+ maThumbRect.IsInside( rPt ) )
+ return &maThumbRect;
+ else
+ return NULL;
+}
+
+long ScrollBar::PreNotify( NotifyEvent& rNEvt )
+{
+ long nDone = 0;
+ const MouseEvent* pMouseEvt = NULL;
+
+ if( (rNEvt.GetType() == EVENT_MOUSEMOVE) && (pMouseEvt = rNEvt.GetMouseEvent()) != NULL )
+ {
+ if( !pMouseEvt->GetButtons() && !pMouseEvt->IsSynthetic() && !pMouseEvt->IsModifierChanged() )
+ {
+ // trigger redraw if mouse over state has changed
+ if( IsNativeControlSupported(CTRL_SCROLLBAR, PART_ENTIRE_CONTROL) )
+ {
+ Rectangle* pRect = ImplFindPartRect( GetPointerPosPixel() );
+ Rectangle* pLastRect = ImplFindPartRect( GetLastPointerPosPixel() );
+ if( pRect != pLastRect || pMouseEvt->IsLeaveWindow() || pMouseEvt->IsEnterWindow() )
+ {
+ Region aRgn( GetActiveClipRegion() );
+ Region aClipRegion;
+
+ if ( pRect )
+ aClipRegion.Union( *pRect );
+ if ( pLastRect )
+ aClipRegion.Union( *pLastRect );
+
+ // Support for 3-button scroll bars
+ BOOL bHas3Buttons = IsNativeControlSupported( CTRL_SCROLLBAR, HAS_THREE_BUTTONS );
+ if ( bHas3Buttons && ( pRect == &maBtn1Rect || pLastRect == &maBtn1Rect ) )
+ {
+ aClipRegion.Union( maBtn2Rect );
+ }
+
+ SetClipRegion( aClipRegion );
+ Paint( aClipRegion.GetBoundRect() );
+
+ SetClipRegion( aRgn );
+ }
+ }
+ }
+ }
+
+ return nDone ? nDone : Control::PreNotify(rNEvt);
+}
+
+// -----------------------------------------------------------------------
+
+void ScrollBar::Scroll()
+{
+ ImplCallEventListenersAndHandler( VCLEVENT_SCROLLBAR_SCROLL, maScrollHdl, this );
+}
+
+// -----------------------------------------------------------------------
+
+void ScrollBar::EndScroll()
+{
+ ImplCallEventListenersAndHandler( VCLEVENT_SCROLLBAR_ENDSCROLL, maEndScrollHdl, this );
+}
+
+// -----------------------------------------------------------------------
+
+long ScrollBar::DoScroll( long nNewPos )
+{
+ if ( meScrollType != SCROLL_DONTKNOW )
+ return 0;
+
+ meScrollType = SCROLL_DRAG;
+ long nDelta = ImplScroll( nNewPos, TRUE );
+ meScrollType = SCROLL_DONTKNOW;
+ return nDelta;
+}
+
+// -----------------------------------------------------------------------
+
+long ScrollBar::DoScrollAction( ScrollType eScrollType )
+{
+ if ( (meScrollType != SCROLL_DONTKNOW) ||
+ (eScrollType == SCROLL_DONTKNOW) ||
+ (eScrollType == SCROLL_DRAG) )
+ return 0;
+
+ meScrollType = eScrollType;
+ long nDelta = ImplDoAction( TRUE );
+ meScrollType = SCROLL_DONTKNOW;
+ return nDelta;
+}
+
+// -----------------------------------------------------------------------
+
+void ScrollBar::SetRangeMin( long nNewRange )
+{
+ SetRange( Range( nNewRange, GetRangeMax() ) );
+}
+
+// -----------------------------------------------------------------------
+
+void ScrollBar::SetRangeMax( long nNewRange )
+{
+ SetRange( Range( GetRangeMin(), nNewRange ) );
+}
+
+// -----------------------------------------------------------------------
+
+void ScrollBar::SetRange( const Range& rRange )
+{
+ // Range einpassen
+ Range aRange = rRange;
+ aRange.Justify();
+ long nNewMinRange = aRange.Min();
+ long nNewMaxRange = aRange.Max();
+
+ // Wenn Range sich unterscheidet, dann neuen setzen
+ if ( (mnMinRange != nNewMinRange) ||
+ (mnMaxRange != nNewMaxRange) )
+ {
+ mnMinRange = nNewMinRange;
+ mnMaxRange = nNewMaxRange;
+
+ // Thumb einpassen
+ if ( mnThumbPos > mnMaxRange-mnVisibleSize )
+ mnThumbPos = mnMaxRange-mnVisibleSize;
+ if ( mnThumbPos < mnMinRange )
+ mnThumbPos = mnMinRange;
+
+ StateChanged( STATE_CHANGE_DATA );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ScrollBar::SetThumbPos( long nNewThumbPos )
+{
+ if ( nNewThumbPos > mnMaxRange-mnVisibleSize )
+ nNewThumbPos = mnMaxRange-mnVisibleSize;
+ if ( nNewThumbPos < mnMinRange )
+ nNewThumbPos = mnMinRange;
+
+ if ( mnThumbPos != nNewThumbPos )
+ {
+ mnThumbPos = nNewThumbPos;
+ StateChanged( STATE_CHANGE_DATA );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ScrollBar::SetVisibleSize( long nNewSize )
+{
+ if ( mnVisibleSize != nNewSize )
+ {
+ mnVisibleSize = nNewSize;
+
+ // Thumb einpassen
+ if ( mnThumbPos > mnMaxRange-mnVisibleSize )
+ mnThumbPos = mnMaxRange-mnVisibleSize;
+ if ( mnThumbPos < mnMinRange )
+ mnThumbPos = mnMinRange;
+ StateChanged( STATE_CHANGE_DATA );
+ }
+}
+
+// =======================================================================
+
+void ScrollBarBox::ImplInit( Window* pParent, WinBits nStyle )
+{
+ Window::ImplInit( pParent, nStyle, NULL );
+
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ long nScrollSize = rStyleSettings.GetScrollBarSize();
+ SetSizePixel( Size( nScrollSize, nScrollSize ) );
+ ImplInitSettings();
+}
+
+// -----------------------------------------------------------------------
+
+ScrollBarBox::ScrollBarBox( Window* pParent, WinBits nStyle ) :
+ Window( WINDOW_SCROLLBARBOX )
+{
+ ImplInit( pParent, nStyle );
+}
+
+// -----------------------------------------------------------------------
+
+ScrollBarBox::ScrollBarBox( Window* pParent, const ResId& rResId ) :
+ Window( WINDOW_SCROLLBARBOX )
+{
+ rResId.SetRT( RSC_SCROLLBAR );
+ ImplInit( pParent, ImplInitRes( rResId ) );
+ ImplLoadRes( rResId );
+}
+
+// -----------------------------------------------------------------------
+
+void ScrollBarBox::ImplInitSettings()
+{
+ // Hack, damit man auch DockingWindows ohne Hintergrund bauen kann
+ // und noch nicht alles umgestellt ist
+ if ( IsBackground() )
+ {
+ Color aColor;
+ if ( IsControlBackground() )
+ aColor = GetControlBackground();
+ else
+ aColor = GetSettings().GetStyleSettings().GetFaceColor();
+ SetBackground( aColor );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ScrollBarBox::StateChanged( StateChangedType nType )
+{
+ Window::StateChanged( nType );
+
+ if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
+ {
+ ImplInitSettings();
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ScrollBarBox::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ Window::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_STYLE) )
+ {
+ ImplInitSettings();
+ Invalidate();
+ }
+}