Files
libreoffice/vcl/source/control/scrbar.cxx

1659 lines
57 KiB
C++
Raw Normal View History

2000-09-18 16:07:07 +00:00
/*************************************************************************
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
2000-09-18 16:07:07 +00:00
*
* Copyright 2008 by Sun Microsystems, Inc.
2000-09-18 16:07:07 +00:00
*
* OpenOffice.org - a multi-platform office productivity suite
2000-09-18 16:07:07 +00:00
*
* $RCSfile: scrbar.cxx,v $
* $Revision: 1.25 $
2000-09-18 16:07:07 +00:00
*
* This file is part of OpenOffice.org.
2000-09-18 16:07:07 +00:00
*
* 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.
2000-09-18 16:07:07 +00:00
*
* 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).
2000-09-18 16:07:07 +00:00
*
* 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.
2000-09-18 16:07:07 +00:00
*
************************************************************************/
// 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"
2000-09-18 16:07:07 +00:00
#include "rtl/string.hxx"
#include "tools/rc.h"
2000-09-18 16:07:07 +00:00
2000-09-18 16:07:07 +00:00
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.
*/
2000-09-18 16:07:07 +00:00
// =======================================================================
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)
2000-09-18 16:07:07 +00:00
#define SCRBAR_DRAW_ALL (SCRBAR_DRAW_BTN1 | SCRBAR_DRAW_BTN2 | \
SCRBAR_DRAW_PAGE1 | SCRBAR_DRAW_PAGE2 |\
SCRBAR_DRAW_THUMB | SCRBAR_DRAW_BACKGROUND )
2000-09-18 16:07:07 +00:00
#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
};
2000-09-18 16:07:07 +00:00
// =======================================================================
void ScrollBar::ImplInit( Window* pParent, WinBits nStyle )
{
mpData = NULL;
2000-09-18 16:07:07 +00:00
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;
}
2000-09-18 16:07:07 +00:00
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;
2000-09-18 16:07:07 +00:00
}
// -----------------------------------------------------------------------
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
2000-09-18 16:07:07 +00:00
if ( mnThumbPixRange )
{
if ( GetStyle() & WB_HORZ )
{
maThumbRect.Left() = maTrackRect.Left()+mnThumbPixPos;
2000-09-18 16:07:07 +00:00
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();
2000-09-18 16:07:07 +00:00
}
}
else
{
maThumbRect.Top() = maTrackRect.Top()+mnThumbPixPos;
2000-09-18 16:07:07 +00:00
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();
2000-09-18 16:07:07 +00:00
}
}
}
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();
}
}
}
2000-09-18 16:07:07 +00:00
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;
}
2000-09-18 16:07:07 +00:00
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 );
2000-09-18 16:07:07 +00:00
}
}
// -----------------------------------------------------------------------
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
2000-09-18 16:07:07 +00:00
if ( mbCalcSize )
{
const Region aControlRegion( Rectangle( (const Point&)Point(0,0), aSize ) );
Region aBtn1Region, aBtn2Region, aTrackRegion, aBoundingRegion;
2000-09-18 16:07:07 +00:00
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 ) )
2000-09-18 16:07:07 +00:00
{
maBtn1Rect = aBtn1Region.GetBoundRect();
maBtn2Rect = aBtn2Region.GetBoundRect();
2000-09-18 16:07:07 +00:00
}
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.GetBoundRect();
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();
2000-09-18 16:07:07 +00:00
}
else
{
mnThumbPixRange = 0;
maPage1Rect.SetEmpty();
maPage2Rect.SetEmpty();
}
2000-09-18 16:07:07 +00:00
}
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 ) )
2000-09-18 16:07:07 +00:00
{
maBtn1Rect = aBtn1Region.GetBoundRect();
maBtn2Rect = aBtn2Region.GetBoundRect();
2000-09-18 16:07:07 +00:00
}
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.GetBoundRect();
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();
2000-09-18 16:07:07 +00:00
}
else
{
mnThumbPixRange = 0;
maPage1Rect.SetEmpty();
maPage2Rect.SetEmpty();
}
2000-09-18 16:07:07 +00:00
}
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();
2000-09-18 16:07:07 +00:00
}
if ( mnThumbPixSize < nMinThumbSize )
mnThumbPixSize = nMinThumbSize;
2000-09-18 16:07:07 +00:00
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 )
{
ImplControlValue aControlValue( BUTTONVALUE_DONTKNOW, rtl::OUString(), 0 );
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 );
ScrollbarValue scrValue;
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;
}
}
aControlValue.setOptionalVal( (void *)(&scrValue) );
#if 1
Region aCtrlRegion;
aCtrlRegion.Union( maBtn1Rect );
aCtrlRegion.Union( maBtn2Rect );
aCtrlRegion.Union( maPage1Rect );
aCtrlRegion.Union( maPage2Rect );
aCtrlRegion.Union( maThumbRect );
#else
const Region aCtrlRegion( Rectangle( Point(0,0), GetOutputSizePixel() ) );
#endif
bNativeOK = DrawNativeControl( CTRL_SCROLLBAR, (bHorz ? PART_DRAW_BACKGROUND_HORZ : PART_DRAW_BACKGROUND_VERT),
aCtrlRegion, nState, aControlValue, 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;
Region aCtrlRegion1( maPage1Rect );
Region 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,
aControlValue, rtl::OUString() );
if ( nDrawFlags & SCRBAR_DRAW_PAGE2 )
bNativeOK = DrawNativeControl( CTRL_SCROLLBAR, part2, aCtrlRegion2, nState2,
aControlValue, 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;
Region aCtrlRegion1( maBtn1Rect );
Region 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,
aControlValue, rtl::OUString() );
if ( nDrawFlags & SCRBAR_DRAW_BTN2 )
bNativeOK = DrawNativeControl( CTRL_SCROLLBAR, part2, aCtrlRegion2, nState2,
aControlValue, rtl::OUString() );
}
if ( (nDrawFlags & SCRBAR_DRAW_THUMB) && !maThumbRect.IsEmpty() )
{
ControlState nState = IsEnabled() ? CTRL_STATE_ENABLED : 0;
Region 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, aControlValue, rtl::OUString() );
}
}
}
return bNativeOK;
}
void ScrollBar::ImplDraw( USHORT nDrawFlags, OutputDevice* pOutDev )
2000-09-18 16:07:07 +00:00
{
DecorationView aDecoView( pOutDev );
2000-09-18 16:07:07 +00:00
Rectangle aTempRect;
USHORT nStyle;
const StyleSettings& rStyleSettings = pOutDev->GetSettings().GetStyleSettings();
2000-09-18 16:07:07 +00:00
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 ) ) )
2000-09-18 16:07:07 +00:00
{
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 ) ) )
2000-09-18 16:07:07 +00:00
{
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();
2000-09-18 16:07:07 +00:00
if ( (nDrawFlags & SCRBAR_DRAW_THUMB) && (!pWin || !ImplDrawNative( SCRBAR_DRAW_THUMB ) ) )
2000-09-18 16:07:07 +00:00
{
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;
2000-09-18 16:07:07 +00:00
aTempRect = aDecoView.DrawButton( maThumbRect, nStyle );
// OS2 style requires pattern on the thumb
2000-09-18 16:07:07 +00:00
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 ),
2000-09-18 16:07:07 +00:00
Point( nX, aTempRect.Bottom()-1 ) );
nX++;
pOutDev->SetLineColor( rStyleSettings.GetLightColor() );
pOutDev->DrawLine( Point( nX, aTempRect.Top()+1 ),
2000-09-18 16:07:07 +00:00
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 ),
2000-09-18 16:07:07 +00:00
Point( aTempRect.Right()-1, nY ) );
nY++;
pOutDev->SetLineColor( rStyleSettings.GetLightColor() );
pOutDev->DrawLine( Point( aTempRect.Left()+1, nY ),
2000-09-18 16:07:07 +00:00
Point( aTempRect.Right()-1, nY ) );
nY++;
}
}
}
pOutDev->SetLineColor();
2000-09-18 16:07:07 +00:00
}
}
else
{
pOutDev->SetFillColor( rStyleSettings.GetCheckedColor() );
pOutDev->DrawRect( maThumbRect );
2000-09-18 16:07:07 +00:00
}
}
}
if ( (nDrawFlags & SCRBAR_DRAW_PAGE1) && (!pWin || !ImplDrawNative( SCRBAR_DRAW_PAGE1 ) ) )
2000-09-18 16:07:07 +00:00
{
if ( mnStateFlags & SCRBAR_STATE_PAGE1_DOWN )
pOutDev->SetFillColor( rStyleSettings.GetShadowColor() );
2000-09-18 16:07:07 +00:00
else
pOutDev->SetFillColor( rStyleSettings.GetCheckedColor() );
pOutDev->DrawRect( maPage1Rect );
2000-09-18 16:07:07 +00:00
}
if ( (nDrawFlags & SCRBAR_DRAW_PAGE2) && (!pWin || !ImplDrawNative( SCRBAR_DRAW_PAGE2 ) ) )
2000-09-18 16:07:07 +00:00
{
if ( mnStateFlags & SCRBAR_STATE_PAGE2_DOWN )
pOutDev->SetFillColor( rStyleSettings.GetShadowColor() );
2000-09-18 16:07:07 +00:00
else
pOutDev->SetFillColor( rStyleSettings.GetCheckedColor() );
pOutDev->DrawRect( maPage2Rect );
2000-09-18 16:07:07 +00:00
}
}
// -----------------------------------------------------------------------
long ScrollBar::ImplScroll( long nNewPos, BOOL bCallEndScroll )
{
long nOldPos = mnThumbPos;
2000-09-18 16:07:07 +00:00
SetThumbPos( nNewPos );
long nDelta = mnThumbPos-nOldPos;
2000-09-18 16:07:07 +00:00
if ( nDelta )
{
mnDelta = nDelta;
Scroll();
2000-09-18 16:07:07 +00:00
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:
;
2000-09-18 16:07:07 +00:00
}
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 );
Region aControlRegion( Rectangle( aPoint, GetOutputSizePixel() ) );
2000-09-18 16:07:07 +00:00
switch ( meScrollType )
{
case SCROLL_LINEUP:
if ( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? PART_BUTTON_LEFT: PART_BUTTON_UP,
aControlRegion, rMousePos, bIsInside )?
bIsInside:
maBtn1Rect.IsInside( rMousePos ) )
2000-09-18 16:07:07 +00:00
{
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 ) )
2000-09-18 16:07:07 +00:00
{
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,
Region( maPage1Rect ), rMousePos, bIsInside )?
bIsInside:
maPage1Rect.IsInside( rMousePos ) )
2000-09-18 16:07:07 +00:00
{
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,
Region( maPage2Rect ), rMousePos, bIsInside )?
bIsInside:
maPage2Rect.IsInside( rMousePos ) )
2000-09-18 16:07:07 +00:00
{
bAction = bCallAction;
mnStateFlags |= SCRBAR_STATE_PAGE2_DOWN;
}
else
mnStateFlags &= ~SCRBAR_STATE_PAGE2_DOWN;
break;
default:
;
2000-09-18 16:07:07 +00:00
}
if ( nOldStateFlags != mnStateFlags )
ImplDraw( mnDragDraw, this );
2000-09-18 16:07:07 +00:00
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;
}
}
}
// -----------------------------------------------------------------------
2000-09-18 16:07:07 +00:00
void ScrollBar::MouseButtonDown( const MouseEvent& rMEvt )
{
if ( rMEvt.IsLeft() || rMEvt.IsMiddle() )
2000-09-18 16:07:07 +00:00
{
const Point& rMousePos = rMEvt.GetPosPixel();
USHORT nTrackFlags = 0;
BOOL bHorizontal = ( GetStyle() & WB_HORZ )? TRUE: FALSE;
BOOL bIsInside = FALSE;
BOOL bDragToMouse = FALSE;
2000-09-18 16:07:07 +00:00
Point aPoint( 0, 0 );
Region aControlRegion( Rectangle( aPoint, GetOutputSizePixel() ) );
if ( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? PART_BUTTON_LEFT: PART_BUTTON_UP,
aControlRegion, rMousePos, bIsInside )?
bIsInside:
maBtn1Rect.IsInside( rMousePos ) )
2000-09-18 16:07:07 +00:00
{
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 ) )
2000-09-18 16:07:07 +00:00
{
if ( !(mnStateFlags & SCRBAR_STATE_BTN2_DISABLE) )
{
nTrackFlags = STARTTRACK_BUTTONREPEAT;
meScrollType = SCROLL_LINEDOWN;
mnDragDraw = SCRBAR_DRAW_BTN2;
}
else
Sound::Beep( SOUND_DISABLE, this );
}
else
2000-09-18 16:07:07 +00:00
{
bool bThumbHit = HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? PART_THUMB_HORZ : PART_THUMB_VERT,
Region( 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 )
2000-09-18 16:07:07 +00:00
{
nTrackFlags = STARTTRACK_BUTTONREPEAT;
2000-09-18 16:07:07 +00:00
// HitTestNativeControl, see remark at top of file
if ( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? PART_TRACK_HORZ_LEFT : PART_TRACK_VERT_UPPER,
Region( maPage1Rect ), rMousePos, bIsInside )?
bIsInside:
maPage1Rect.IsInside( rMousePos ) )
{
meScrollType = SCROLL_PAGEUP;
mnDragDraw = SCRBAR_DRAW_PAGE1;
}
2000-09-18 16:07:07 +00:00
else
{
meScrollType = SCROLL_PAGEDOWN;
mnDragDraw = SCRBAR_DRAW_PAGE2;
}
2000-09-18 16:07:07 +00:00
}
}
// Soll Tracking gestartet werden
if ( meScrollType != SCROLL_DONTKNOW )
{
// remember original position in case of abort or EndScroll-Delta
2000-09-18 16:07:07 +00:00
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
2000-09-18 16:07:07 +00:00
StartTracking( nTrackFlags );
ImplDoMouseAction( rMousePos );
if( bDragToMouse )
ImplDragThumb( rMousePos );
2000-09-18 16:07:07 +00:00
}
}
}
// -----------------------------------------------------------------------
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 );
2000-09-18 16:07:07 +00:00
mnDragDraw = 0;
// Bei Abbruch, die alte ThumbPosition wieder herstellen
if ( rTEvt.IsTrackingCanceled() )
{
long nOldPos = mnThumbPos;
2000-09-18 16:07:07 +00:00
SetThumbPos( mnStartPos );
mnDelta = mnThumbPos-nOldPos;
Scroll();
2000-09-18 16:07:07 +00:00
}
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
2000-09-18 16:07:07 +00:00
}
else
{
const Point rMousePos = rTEvt.GetMouseEvent().GetPosPixel();
// Dragging wird speziell behandelt
if ( meScrollType == SCROLL_DRAG )
ImplDragThumb( rMousePos );
2000-09-18 16:07:07 +00:00
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& )
2000-09-18 16:07:07 +00:00
{
ImplDraw( SCRBAR_DRAW_ALL, this );
2000-09-18 16:07:07 +00:00
}
// -----------------------------------------------------------------------
void ScrollBar::Resize()
{
Control::Resize();
2000-09-18 16:07:07 +00:00
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();
}
// -----------------------------------------------------------------------
2000-09-18 16:07:07 +00:00
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 );
2000-09-18 16:07:07 +00:00
Invalidate();
}
2000-09-18 16:07:07 +00:00
}
// -----------------------------------------------------------------------
Rectangle* ScrollBar::ImplFindPartRect( const Point& rPt )
{
BOOL bHorizontal = ( GetStyle() & WB_HORZ )? TRUE: FALSE;
BOOL bIsInside = FALSE;
Point aPoint( 0, 0 );
Region aControlRegion( Rectangle( 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,
Region( 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,
Region( 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,
Region( 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);
}
// -----------------------------------------------------------------------
2000-09-18 16:07:07 +00:00
void ScrollBar::Scroll()
{
ImplCallEventListenersAndHandler( VCLEVENT_SCROLLBAR_SCROLL, maScrollHdl, this );
2000-09-18 16:07:07 +00:00
}
// -----------------------------------------------------------------------
void ScrollBar::EndScroll()
{
ImplCallEventListenersAndHandler( VCLEVENT_SCROLLBAR_ENDSCROLL, maEndScrollHdl, this );
2000-09-18 16:07:07 +00:00
}
// -----------------------------------------------------------------------
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();
}
}