| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the 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 "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 ((sal_uInt16)0x0001) |
| #define SCRBAR_DRAW_BTN2 ((sal_uInt16)0x0002) |
| #define SCRBAR_DRAW_PAGE1 ((sal_uInt16)0x0004) |
| #define SCRBAR_DRAW_PAGE2 ((sal_uInt16)0x0008) |
| #define SCRBAR_DRAW_THUMB ((sal_uInt16)0x0010) |
| #define SCRBAR_DRAW_BACKGROUND ((sal_uInt16)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 ((sal_uInt16)0x0001) |
| #define SCRBAR_STATE_BTN1_DISABLE ((sal_uInt16)0x0002) |
| #define SCRBAR_STATE_BTN2_DOWN ((sal_uInt16)0x0004) |
| #define SCRBAR_STATE_BTN2_DISABLE ((sal_uInt16)0x0008) |
| #define SCRBAR_STATE_PAGE1_DOWN ((sal_uInt16)0x0010) |
| #define SCRBAR_STATE_PAGE2_DOWN ((sal_uInt16)0x0020) |
| #define SCRBAR_STATE_THUMB_DOWN ((sal_uInt16)0x0040) |
| |
| #define SCRBAR_VIEW_STYLE (WB_3DLOOK | WB_HORZ | WB_VERT) |
| |
| struct ImplScrollBarData |
| { |
| AutoTimer maTimer; // Timer |
| sal_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 = sal_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 = sal_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 = sal_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 ); |
| |
| sal_Int16 nMin = ReadShortRes(); |
| sal_Int16 nMax = ReadShortRes(); |
| sal_Int16 nThumbPos = ReadShortRes(); |
| sal_Int16 nPage = ReadShortRes(); |
| sal_Int16 nStep = ReadShortRes(); |
| sal_Int16 nVisibleSize = ReadShortRes(); |
| |
| SetRange( Range( nMin, nMax ) ); |
| SetLineSize( nStep ); |
| SetPageSize( nPage ); |
| SetVisibleSize( nVisibleSize ); |
| SetThumbPos( nThumbPos ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ScrollBar::ImplUpdateRects( sal_Bool bUpdate ) |
| { |
| sal_uInt16 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 ) |
| { |
| sal_uInt16 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( sal_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 |
| { |
| if (aBtn1Region.IsEmpty() && aBtn2Region.IsEmpty()) |
| { |
| Size aBtnSize( aSize.Height(), aSize.Height() ); |
| maBtn2Rect.Top() = maBtn1Rect.Top(); |
| maBtn2Rect.Left() = aSize.Width()-aSize.Height(); |
| maBtn1Rect.SetSize( aBtnSize ); |
| maBtn2Rect.SetSize( aBtnSize ); |
| } |
| else |
| { |
| maBtn1Rect.SetEmpty(); |
| maBtn2Rect.SetEmpty(); |
| } |
| } |
| |
| if ( GetNativeControlRegion( CTRL_SCROLLBAR, PART_TRACK_HORZ_AREA, |
| aControlRegion, 0, ImplControlValue(), rtl::OUString(), aBoundingRegion, aTrackRegion ) ) |
| { |
| maTrackRect = aTrackRegion; |
| } |
| else |
| { |
| if ( ! maBtn1Rect.IsEmpty()) |
| maTrackRect = Rectangle( maBtn1Rect.TopRight(), maBtn2Rect.BottomLeft() ); |
| else |
| maTrackRect = aControlRegion; |
| } |
| |
| // 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 |
| { |
| if (aBtn1Region.IsEmpty() && aBtn2Region.IsEmpty()) |
| { |
| const Size aBtnSize( aSize.Width(), aSize.Width() ); |
| maBtn2Rect.Left() = maBtn1Rect.Left(); |
| maBtn2Rect.Top() = aSize.Height()-aSize.Width(); |
| maBtn1Rect.SetSize( aBtnSize ); |
| maBtn2Rect.SetSize( aBtnSize ); |
| } |
| else |
| { |
| maBtn1Rect.SetEmpty(); |
| maBtn2Rect.SetEmpty(); |
| } |
| } |
| |
| if ( GetNativeControlRegion( CTRL_SCROLLBAR, PART_TRACK_VERT_AREA, |
| aControlRegion, 0, ImplControlValue(), rtl::OUString(), aBoundingRegion, aTrackRegion ) ) |
| maTrackRect = aTrackRegion; |
| else |
| { |
| if ( ! maBtn1Rect.IsEmpty()) |
| maTrackRect = Rectangle( maBtn1Rect.BottomLeft()+Point(0,1), maBtn2Rect.TopRight() ); |
| else |
| maTrackRect = aControlRegion; |
| } |
| |
| // 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 = sal_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 = sal_False; |
| } |
| ImplUpdateRects( bUpdate ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ScrollBar::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize, sal_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( sal_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 = sal_True; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_Bool ScrollBar::ImplDrawNative( sal_uInt16 nDrawFlags ) |
| { |
| ScrollbarValue scrValue; |
| |
| sal_Bool bNativeOK = IsNativeControlSupported(CTRL_SCROLLBAR, PART_ENTIRE_CONTROL); |
| if( bNativeOK ) |
| { |
| sal_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( sal_uInt16 nDrawFlags, OutputDevice* pOutDev ) |
| { |
| DecorationView aDecoView( pOutDev ); |
| Rectangle aTempRect; |
| sal_uInt16 nStyle; |
| const StyleSettings& rStyleSettings = pOutDev->GetSettings().GetStyleSettings(); |
| SymbolType eSymbolType; |
| sal_Bool bEnabled = IsEnabled(); |
| |
| // Evt. noch offene Berechnungen nachholen |
| if ( mbCalcSize ) |
| ImplCalc( sal_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; |
| aTempRect = aDecoView.DrawButton( maThumbRect, nStyle ); |
| } |
| 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, sal_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( sal_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, sal_Bool bCallAction ) |
| { |
| sal_uInt16 nOldStateFlags = mnStateFlags; |
| sal_Bool bAction = sal_False; |
| sal_Bool bHorizontal = ( GetStyle() & WB_HORZ )? sal_True: sal_False; |
| sal_Bool bIsInside = sal_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( sal_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(); |
| sal_uInt16 nTrackFlags = 0; |
| sal_Bool bHorizontal = ( GetStyle() & WB_HORZ )? sal_True: sal_False; |
| sal_Bool bIsInside = sal_False; |
| sal_Bool bDragToMouse = sal_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 = sal_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 = sal_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 : sal_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 |
| sal_uInt16 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 = sal_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 = sal_True; |
| if ( IsReallyVisible() ) |
| ImplCalc( sal_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 = sal_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( sal_False ); |
| else if ( nType == STATE_CHANGE_DATA ) |
| { |
| if ( IsReallyVisible() && IsUpdateMode() ) |
| ImplCalc( sal_True ); |
| } |
| else if ( nType == STATE_CHANGE_UPDATEMODE ) |
| { |
| if ( IsReallyVisible() && IsUpdateMode() ) |
| { |
| ImplCalc( sal_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 = sal_True; |
| ImplCalc( sal_False ); |
| Invalidate(); |
| } |
| } |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ScrollBar::DataChanged( const DataChangedEvent& rDCEvt ) |
| { |
| Control::DataChanged( rDCEvt ); |
| |
| if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && |
| (rDCEvt.GetFlags() & SETTINGS_STYLE) ) |
| { |
| mbCalcSize = sal_True; |
| ImplCalc( sal_False ); |
| Invalidate(); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| Rectangle* ScrollBar::ImplFindPartRect( const Point& rPt ) |
| { |
| sal_Bool bHorizontal = ( GetStyle() & WB_HORZ )? sal_True: sal_False; |
| sal_Bool bIsInside = sal_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 |
| sal_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, sal_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( sal_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(); |
| } |
| } |