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

1592 lines
54 KiB
C++
Raw Normal View History

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
re-base on ALv2 code. Includes (at least) relevant parts of: linecap: Reintegrating finished LineCap feature Patch contributed by Regina Henschel http://svn.apache.org/viewvc?view=revision&revision=1232507 Patches contributed by Sven Jacobi impress212: #i81610# fixed animation export http://svn.apache.org/viewvc?view=revision&revision=1167620 impress212: drawinglayer gbuild environment changes http://svn.apache.org/viewvc?view=revision&revision=1167627 http://svn.apache.org/viewvc?view=revision&revision=1167628 impress212: DffPropSet -> minor code improvements, removing table http://svn.apache.org/viewvc?view=revision&revision=1167634 impress212: #158494# fixed excel import (text rotation) http://svn.apache.org/viewvc?view=revision&revision=1167638 Patches contributed by Armin Le Grand Svg: Reintegrated Svg replacement from /branches/alg/svgreplavement http://svn.apache.org/viewvc?view=revision&revision=1220836 #118728# changed indentifying definitions for Svg file detection http://svn.apache.org/viewvc?view=revision&revision=1229961 #118838# LineGeometry creation for complicated cases optimized to create single Polygons http://svn.apache.org/viewvc?view=revision&revision=1236232 #119176# corrected file type detection for SVG for svg files without xml header http://svn.apache.org/viewvc?view=revision&revision=1309445 #118728# Extended Svg file detection http://svn.apache.org/viewvc?view=revision&revision=1230531 #118529# solve break converters and convert commands for OLEs and images http://svn.apache.org/viewvc?view=revision&revision=1186168 svg: added WaE changes from branch svgreplacement to trunc http://svn.apache.org/viewvc?view=revision&revision=1222974 svg: corrected missing member initialization http://svn.apache.org/viewvc?view=revision&revision=1226134 fix for #118525#: Using primitives for chart sub-geometry visualisation http://svn.apache.org/viewvc?view=revision&revision=1226879 #118898# Adapted ImpGraphic::ImplGetBitmap to correctly convert metafiles to bitmapEx ... http://svn.apache.org/viewvc?view=revision&revision=1293316 fix for #118525#: removed no longer used variable maOriginalMapMode, one more exception eliminated http://svn.apache.org/viewvc?view=revision&revision=1227097 #16758# Added buffering to the VDev usages of the VclProcessor2D derivates... http://svn.apache.org/viewvc?view=revision&revision=1229521 #116758# Secured VDev buffer device to Vcl deinit http://svn.apache.org/viewvc?view=revision&revision=1230574 #116758# added remembering allocated VDevs for VDevBuffer to be able to also delete these when vcl goes down; it should never happen, but You never know http://svn.apache.org/viewvc?view=revision&revision=1230927 #118730# Changed SvgClipPathNode to use MaskPrimitive2D for primitive representation instead of TransparencePrimitive2D http://svn.apache.org/viewvc?view=revision&revision=1231198 #118822# secured 3D geometry creation (slices) by subdividing the 2D source polyPolygon early http://svn.apache.org/viewvc?view=revision&revision=1234749 #118829# enhanced Svg gradient quality, obstacles avoided http://svn.apache.org/viewvc?view=revision&revision=1235361 #118834# Unified usage of TextBreakupHelper as single tooling class for i18n text primitive breakup http://svn.apache.org/viewvc?view=revision&revision=1236110 #118853# added square pixel size limit to conversion of TransparencePrimitive2D to Metafile action http://svn.apache.org/viewvc?view=revision&revision=1237656 #118824# coreccted mirroring and boundrect when the graphicmanager is used for bitmap output http://svn.apache.org/viewvc?view=revision&revision=1240097 #115092# Corrected VclProcessor2D::RenderPolygonStrokePrimitive2D for various optimization scenarios http://svn.apache.org/viewvc?view=revision&revision=1241434 #118783# Corrected errors in ID strings, corrected Svg line/fill export, corrected polygon close state http://svn.apache.org/viewvc?view=revision&revision=1232006 #118796# corrected null-pointer usage in SVG text exporter http://svn.apache.org/viewvc?view=revision&revision=1240262 #118729# Use GraphicStreamUrl and GraphicUrl to allow multi image import with linked graphics, too http://svn.apache.org/viewvc?view=revision&revision=1229962 #118898# corrected error in GDIMetaFile::GetBoundRect in handling MetaFloatTransparentAction http://svn.apache.org/viewvc?view=revision&revision=1293349 #118855# Corrected handling of possibly created empty clipRegions after PolyPolygon clipping http://svn.apache.org/viewvc?view=revision&revision=1237725 #115962# Better (but not yet optimal, see comments in task) handling of MetaFloatTransparentAction in PDF export http://svn.apache.org/viewvc?view=revision&revision=1241078 IP clearance: #118466# This patch removes librsvg, libcroco, libgsf, ... http://svn.apache.org/viewvc?view=revision&revision=1200879 118779# Added svg content streaming in/out to ImpGraphic stream operators http://svn.apache.org/viewvc?view=revision&revision=1231908 linecap: correctons for WaE and mac drawing http://svn.apache.org/viewvc?view=revision&revision=1232793 svg: uses current system Dpi for Svg replacement image creation http://svn.apache.org/viewvc?view=revision&revision=1233948 Patches contributed by Mathias Bauer (and others) gnumake4 work variously http://svn.apache.org/viewvc?view=revision&revision=1394326 http://svn.apache.org/viewvc?view=revision&revision=1396797 http://svn.apache.org/viewvc?view=revision&revision=1397315 http://svn.apache.org/viewvc?view=revision&revision=1394326 Remove duplicate header includes. cws mba34issues01: #i117720#: convert assertion into warning http://svn.apache.org/viewvc?view=revision&revision=1172352 118485 - Styles for OLEs are not saved. Submitted by Armin Le Grand. http://svn.apache.org/viewvc?view=revision&revision=1182166 cws mba34issues01: #i117714#: remove assertion http://svn.apache.org/viewvc?view=revision&revision=1172357 Patch contributed by Jurgen Schmidt add some additional checks to ensure proper reading operations http://svn.apache.org/viewvc?view=revision&revision=1209022 mostly prefer our stream / bounds checking work. Patches contributed by Herbert Duerr #i118816# add clarifying comment regarding Font::*Color*() methods http://svn.apache.org/viewvc?view=revision&revision=1233833 extend macro->string handling for empty strings http://svn.apache.org/viewvc?view=revision&revision=1175801 avoid magic constants for SALCOLOR_NONE http://svn.apache.org/viewvc?view=revision&revision=1177543 initialize slant properly in ImplFontMetricData constructor (author=iorsh) http://svn.apache.org/viewvc?view=revision&revision=1177551 #i118675# make check for extension updates more stable http://svn.apache.org/viewvc?view=revision&revision=1214797 #a118617# remove VBasicEventListener.dll binary There are no known users depending on its CLSID http://svn.apache.org/viewvc?view=revision&revision=1203697 Patches contributed by Ariel Constenla-Haile Fix build breaker on Linux/gcc http://svn.apache.org/viewvc?view=revision&revision=1221104 Fix crash when trying to instantiate css.graphic.GraphicRasterizer_RSVG http://svn.apache.org/viewvc?view=revision&revision=1215559 Patches contributed by Oliver-Rainer Wittmann sw34bf06: #i117962# - method <SwFlyFrm::IsPaint(..)> - consider instances of <SwFlyDrawObj> http://svn.apache.org/viewvc?view=revision&revision=1172120 sw34bf06: #i117783# - Writer's implementation of XPagePrintable - apply print settings to new printing routines http://svn.apache.org/viewvc?view=revision&revision=1172115 gnumake4 work variously from Hans-Joachim Lankenau http://svn.apache.org/viewvc?view=revision&revision=1397315 http://svn.apache.org/viewvc?view=revision&revision=1396797 http://svn.apache.org/viewvc?view=revision&revision=1396782 http://svn.apache.org/viewvc?view=revision&revision=1394707 plus some amount of re-splitting of legacy headers. Patch contributed by Pavel Janik WaE: Remove unused variables. http://svn.apache.org/viewvc?view=revision&revision=1230697 Patches contributed by Takashi Ono mingwport35: i#117795: MinGW port fix for vcl2gnumake http://svn.apache.org/viewvc?view=revision&revision=1172091 mingwport35: i#117795: MinGW port fix for vcl2gnumake http://svn.apache.org/viewvc?view=revision&revision=1172091 Patch contributed by Christian Lippka impress212: #i98044# re enable Text menu for outline and title shapes http://svn.apache.org/viewvc?view=revision&revision=1167639 Patch contributed by Andre Fischer 118674: Made category B code optional and disabled by default. http://svn.apache.org/viewvc?view=revision&revision=1215131 118881: Ignore empty paragraphs after bullets. http://svn.apache.org/viewvc?view=revision&revision=1296205 Patches contributed by Philipp Lohmann ooo340fixes: #i117780# use rtl allocator http://svn.apache.org/viewvc?view=revision&revision=1172087 ooo34gsl02: #i117807# fix an off by one error (index actually inside the pfb section header) http://svn.apache.org/viewvc?view=revision&revision=1167576 various cleanups, related compilation fixes, warning cleanups, re-working of obsolete stl template pieces to use boost instead, changed string classes, re-adapt KDE about data, about dialog, fixing warnings, and other fixes & improvements. Disable svg import / render for about/ branding code-paths for now. Restore full icon theme set. Remove OS/2 conditionals and sources. Remove conflicting gtk/full-screen monitors support. Retain existing svg rasterizer files - temporarily disabled. Standardize stringificaiton and fixup dllpostfix issues. Rename SvgGradientHelper::== to equalTo to avoid overloading issues. Use the flat GdiPlus API for LineCaps calls.
2012-10-09 12:22:23 +01:00
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* 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 .
*/
2000-09-18 16:07:07 +00:00
#include "vcl/event.hxx"
#include "vcl/decoview.hxx"
#include "vcl/scrbar.hxx"
#include "vcl/timer.hxx"
#include "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
2011-03-01 22:45:35 +01:00
using ::rtl::OUString;
2000-09-18 16:07:07 +00:00
/* #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.
*/
#include "thumbpos.hxx"
2000-09-18 16:07:07 +00:00
// =======================================================================
#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)
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 ((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)
2000-09-18 16:07:07 +00:00
#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
};
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 = sal_True;
2000-09-18 16:07:07 +00:00
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;
}
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 = sal_True;
2000-09-18 16:07:07 +00:00
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 );
sal_Int16 nMin = ReadShortRes();
sal_Int16 nMax = ReadShortRes();
sal_Int16 nThumbPos = ReadShortRes();
sal_Int16 nPage = ReadShortRes();
sal_Int16 nStep = ReadShortRes();
sal_Int16 nVisibleSize = ReadShortRes();
2000-09-18 16:07:07 +00:00
SetRange( Range( nMin, nMax ) );
SetLineSize( nStep );
SetPageSize( nPage );
SetVisibleSize( nVisibleSize );
SetThumbPos( nThumbPos );
}
// -----------------------------------------------------------------------
void ScrollBar::ImplUpdateRects( sal_Bool bUpdate )
2000-09-18 16:07:07 +00:00
{
sal_uInt16 nOldStateFlags = mnStateFlags;
2000-09-18 16:07:07 +00:00
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
{
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 )
{
sal_uInt16 nDraw = 0;
2000-09-18 16:07:07 +00:00
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( sal_Bool bUpdate )
2000-09-18 16:07:07 +00:00
{
const Size aSize = GetOutputSizePixel();
2011-12-14 14:43:58 -05:00
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 )
{
Size aOldSize = getCurrentCalcSize();
const Rectangle aControlRegion( Point(0,0), aSize );
Rectangle 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;
maBtn2Rect = aBtn2Region;
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;
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;
maBtn2Rect = aBtn2Region;
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;
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 = sal_False;
Size aNewSize = getCurrentCalcSize();
if (aOldSize != aNewSize)
{
queue_resize();
}
2000-09-18 16:07:07 +00:00
}
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 = sal_False;
2000-09-18 16:07:07 +00:00
}
ImplUpdateRects( bUpdate );
}
// -----------------------------------------------------------------------
void ScrollBar::Draw( OutputDevice* pDev, const Point& rPos, const Size& /* rSize */, sal_uLong nFlags )
{
Point aPos = pDev->LogicToPixel( rPos );
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 )
2000-09-18 16:07:07 +00:00
{
DecorationView aDecoView( pOutDev );
2000-09-18 16:07:07 +00:00
Rectangle aTempRect;
sal_uInt16 nStyle;
const StyleSettings& rStyleSettings = pOutDev->GetSettings().GetStyleSettings();
2000-09-18 16:07:07 +00:00
SymbolType eSymbolType;
sal_Bool bEnabled = IsEnabled();
2000-09-18 16:07:07 +00:00
// Evt. noch offene Berechnungen nachholen
if ( mbCalcSize )
ImplCalc( sal_False );
2000-09-18 16:07:07 +00:00
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;
aTempRect = aDecoView.DrawButton( maThumbRect, nStyle );
}
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, sal_Bool bCallEndScroll )
2000-09-18 16:07:07 +00:00
{
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( sal_Bool bCallEndScroll )
2000-09-18 16:07:07 +00:00
{
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, sal_Bool bCallAction )
2000-09-18 16:07:07 +00:00
{
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() );
2000-09-18 16:07:07 +00:00
switch ( meScrollType )
{
case SCROLL_LINEUP:
if ( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? (IsRTLEnabled()? PART_BUTTON_RIGHT: 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? (IsRTLEnabled()? PART_BUTTON_LEFT: 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,
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,
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( sal_False );
2000-09-18 16:07:07 +00:00
}
// -----------------------------------------------------------------------
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 )
{
bool bPrimaryWarps = GetSettings().GetStyleSettings().GetPrimaryButtonWarpsSlider();
bool bWarp = bPrimaryWarps ? rMEvt.IsLeft() : rMEvt.IsMiddle();
bool bPrimaryWarping = bWarp && rMEvt.IsLeft();
bool bPage = bPrimaryWarps ? rMEvt.IsRight() : rMEvt.IsLeft();
if (rMEvt.IsLeft() || rMEvt.IsMiddle() || rMEvt.IsRight())
2000-09-18 16:07:07 +00:00
{
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;
2000-09-18 16:07:07 +00:00
Point aPoint( 0, 0 );
Rectangle aControlRegion( aPoint, GetOutputSizePixel() );
if ( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? (IsRTLEnabled()? PART_BUTTON_RIGHT: PART_BUTTON_LEFT): PART_BUTTON_UP,
aControlRegion, rMousePos, bIsInside )?
bIsInside:
maBtn1Rect.IsInside( rMousePos ) )
2000-09-18 16:07:07 +00:00
{
if (rMEvt.IsLeft() && !(mnStateFlags & SCRBAR_STATE_BTN1_DISABLE) )
2000-09-18 16:07:07 +00:00
{
nTrackFlags = STARTTRACK_BUTTONREPEAT;
meScrollType = SCROLL_LINEUP;
mnDragDraw = SCRBAR_DRAW_BTN1;
}
}
else if ( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? (IsRTLEnabled()? PART_BUTTON_LEFT: PART_BUTTON_RIGHT): PART_BUTTON_DOWN,
aControlRegion, rMousePos, bIsInside )?
bIsInside:
maBtn2Rect.IsInside( rMousePos ) )
2000-09-18 16:07:07 +00:00
{
if (rMEvt.IsLeft() && !(mnStateFlags & SCRBAR_STATE_BTN2_DISABLE) )
2000-09-18 16:07:07 +00:00
{
nTrackFlags = STARTTRACK_BUTTONREPEAT;
meScrollType = SCROLL_LINEDOWN;
mnDragDraw = SCRBAR_DRAW_BTN2;
}
}
else
2000-09-18 16:07:07 +00:00
{
bool bThumbHit = HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? PART_THUMB_HORZ : PART_THUMB_VERT,
maThumbRect, rMousePos, bIsInside )
? bIsInside : maThumbRect.IsInside( rMousePos );
bool bThumbAction = bWarp || bPage;
bool bDragHandling = bWarp || (bThumbHit && bThumbAction);
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 (bWarp && (!bThumbHit || !bPrimaryWarping))
{
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 if(bPage && (HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? PART_TRACK_HORZ_AREA : PART_TRACK_VERT_AREA,
aControlRegion, rMousePos, bIsInside ) ?
bIsInside : sal_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,
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
sal_uInt16 nOldStateFlags = mnStateFlags;
2000-09-18 16:07:07 +00:00
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 = sal_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();
mbCalcSize = sal_True;
2000-09-18 16:07:07 +00:00
if ( IsReallyVisible() )
ImplCalc( sal_False );
2000-09-18 16:07:07 +00:00
Invalidate();
}
// -----------------------------------------------------------------------
IMPL_LINK_NOARG(ScrollBar, ImplAutoTimerHdl)
{
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();
}
// -----------------------------------------------------------------------
2000-09-18 16:07:07 +00:00
void ScrollBar::StateChanged( StateChangedType nType )
{
Control::StateChanged( nType );
if ( nType == STATE_CHANGE_INITSHOW )
ImplCalc( sal_False );
2000-09-18 16:07:07 +00:00
else if ( nType == STATE_CHANGE_DATA )
{
if ( IsReallyVisible() && IsUpdateMode() )
ImplCalc( sal_True );
2000-09-18 16:07:07 +00:00
}
else if ( nType == STATE_CHANGE_UPDATEMODE )
{
if ( IsReallyVisible() && IsUpdateMode() )
{
ImplCalc( sal_False );
2000-09-18 16:07:07 +00:00
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 );
2000-09-18 16:07:07 +00:00
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 );
2000-09-18 16:07:07 +00:00
Invalidate();
}
2000-09-18 16:07:07 +00:00
}
// -----------------------------------------------------------------------
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? (IsRTLEnabled()? PART_BUTTON_RIGHT: PART_BUTTON_LEFT): PART_BUTTON_UP,
aControlRegion, rPt, bIsInside )?
bIsInside:
maBtn1Rect.IsInside( rPt ) )
return &maBtn1Rect;
else if( HitTestNativeControl( CTRL_SCROLLBAR, bHorizontal? (IsRTLEnabled()? PART_BUTTON_LEFT: 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);
}
// -----------------------------------------------------------------------
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;
SAL_INFO("vcl.scrollbar", "DoScroll(" << nNewPos << ")");
2000-09-18 16:07:07 +00:00
meScrollType = SCROLL_DRAG;
long nDelta = ImplScroll( nNewPos, sal_True );
2000-09-18 16:07:07 +00:00
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 );
2000-09-18 16:07:07 +00:00
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 );
}
}
Size ScrollBar::GetOptimalSize() const
{
if (mbCalcSize)
const_cast<ScrollBar*>(this)->ImplCalc(sal_False);
return getCurrentCalcSize();
}
Size ScrollBar::getCurrentCalcSize() const
{
Rectangle aCtrlRegion;
aCtrlRegion.Union(maBtn1Rect);
aCtrlRegion.Union(maBtn2Rect);
aCtrlRegion.Union(maPage1Rect);
aCtrlRegion.Union(maPage2Rect);
aCtrlRegion.Union(maThumbRect);
return aCtrlRegion.GetSize();
}
2000-09-18 16:07:07 +00:00
// =======================================================================
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 );
}
// -----------------------------------------------------------------------
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();
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */