diff options
Diffstat (limited to 'vcl/source/window/status.cxx')
-rw-r--r-- | vcl/source/window/status.cxx | 1794 |
1 files changed, 1794 insertions, 0 deletions
diff --git a/vcl/source/window/status.cxx b/vcl/source/window/status.cxx new file mode 100644 index 000000000000..385dd241c770 --- /dev/null +++ b/vcl/source/window/status.cxx @@ -0,0 +1,1794 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_vcl.hxx" +#include <tools/list.hxx> +#include <tools/debug.hxx> + +#ifndef _SV_RC_H +#include <tools/rc.h> +#endif +#include <vcl/svdata.hxx> +#include <vcl/event.hxx> +#include <vcl/decoview.hxx> +#include <vcl/svapp.hxx> +#include <vcl/help.hxx> +#include <vcl/status.hxx> +#include <vcl/virdev.hxx> +#include <vcl/window.h> + +// ======================================================================= + +#define STATUSBAR_OFFSET_X STATUSBAR_OFFSET +#define STATUSBAR_OFFSET_Y 2 +#define STATUSBAR_OFFSET_TEXTY 3 + +#define STATUSBAR_PRGS_OFFSET 3 +#define STATUSBAR_PRGS_COUNT 100 +#define STATUSBAR_PRGS_MIN 5 + +// ----------------------------------------------------------------------- + +class StatusBar::ImplData +{ +public: + ImplData(); + ~ImplData(); + + VirtualDevice* mpVirDev; + long mnItemBorderWidth; + bool mbTopBorder:1; + bool mbDrawItemFrames:1; +}; + +StatusBar::ImplData::ImplData() +{ + mpVirDev = NULL; + mbTopBorder = false; + mbDrawItemFrames = false; + mnItemBorderWidth = 0; +} + +StatusBar::ImplData::~ImplData() +{ +} + +struct ImplStatusItem +{ + USHORT mnId; + StatusBarItemBits mnBits; + long mnWidth; + long mnOffset; + long mnExtraWidth; + long mnX; + XubString maText; + XubString maHelpText; + XubString maQuickHelpText; + ULONG mnHelpId; + void* mpUserData; + BOOL mbVisible; + XubString maAccessibleName; + XubString maCommand; +}; + +DECLARE_LIST( ImplStatusItemList, ImplStatusItem* ) + +// ======================================================================= + +inline long ImplCalcProgessWidth( USHORT nMax, long nSize ) +{ + return ((nMax*(nSize+(nSize/2)))-(nSize/2)+(STATUSBAR_PRGS_OFFSET*2)); +} + +// ----------------------------------------------------------------------- + +static Point ImplGetItemTextPos( const Size& rRectSize, const Size& rTextSize, + USHORT nStyle ) +{ + long nX; + long nY; + long delta = (rTextSize.Height()/4) + 1; + if( delta + rTextSize.Width() > rRectSize.Width() ) + delta = 0; + + if ( nStyle & SIB_LEFT ) + nX = delta; + else if ( nStyle & SIB_RIGHT ) + nX = rRectSize.Width()-rTextSize.Width()-delta; + else // SIB_CENTER + nX = (rRectSize.Width()-rTextSize.Width())/2; + nY = (rRectSize.Height()-rTextSize.Height())/2 + 1; + return Point( nX, nY ); +} + +// ----------------------------------------------------------------------- + +BOOL StatusBar::ImplIsItemUpdate() +{ + if ( !mbProgressMode && mbVisibleItems && IsReallyVisible() && IsUpdateMode() ) + return TRUE; + else + return FALSE; +} + +// ----------------------------------------------------------------------- + +void StatusBar::ImplInit( Window* pParent, WinBits nStyle ) +{ + mpImplData = new ImplData; + + // Default ist RightAlign + if ( !(nStyle & (WB_LEFT | WB_RIGHT)) ) + nStyle |= WB_RIGHT; + + Window::ImplInit( pParent, nStyle & ~WB_BORDER, NULL ); + + // WinBits merken + mpItemList = new ImplStatusItemList; + mpImplData->mpVirDev = new VirtualDevice( *this ); + mnCurItemId = 0; + mbFormat = TRUE; + mbVisibleItems = TRUE; + mbProgressMode = FALSE; + mbInUserDraw = FALSE; + mbBottomBorder = FALSE; + mnItemsWidth = STATUSBAR_OFFSET_X; + mnDX = 0; + mnDY = 0; + mnCalcHeight = 0; + mnItemY = STATUSBAR_OFFSET_Y; + mnTextY = STATUSBAR_OFFSET_TEXTY; + + ImplInitSettings( TRUE, TRUE, TRUE ); + SetLineColor(); + + SetOutputSizePixel( CalcWindowSizePixel() ); +} + +// ----------------------------------------------------------------------- + +StatusBar::StatusBar( Window* pParent, WinBits nStyle ) : + Window( WINDOW_STATUSBAR ) +{ + ImplInit( pParent, nStyle ); +} + +// ----------------------------------------------------------------------- + +StatusBar::StatusBar( Window* pParent, const ResId& rResId ) : + Window( WINDOW_STATUSBAR ) +{ + rResId.SetRT( RSC_STATUSBAR ); + WinBits nStyle = ImplInitRes( rResId ); + ImplInit( pParent, nStyle ); + ImplLoadRes( rResId ); + + if ( !(nStyle & WB_HIDE) ) + Show(); +} + +// ----------------------------------------------------------------------- + +StatusBar::~StatusBar() +{ + // Alle Items loeschen + ImplStatusItem* pItem = mpItemList->First(); + while ( pItem ) + { + delete pItem; + pItem = mpItemList->Next(); + } + + delete mpItemList; + + // VirtualDevice loeschen + delete mpImplData->mpVirDev; + + delete mpImplData; +} + +// ----------------------------------------------------------------------- + +void StatusBar::ImplInitSettings( BOOL bFont, + BOOL bForeground, BOOL bBackground ) +{ + const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); + + if ( bFont ) + { + Font aFont = rStyleSettings.GetToolFont(); + if ( IsControlFont() ) + aFont.Merge( GetControlFont() ); + SetZoomedPointFont( aFont ); + } + + if ( bForeground || bFont ) + { + Color aColor; + if ( IsControlForeground() ) + aColor = GetControlForeground(); + else if ( GetStyle() & WB_3DLOOK ) + aColor = rStyleSettings.GetButtonTextColor(); + else + aColor = rStyleSettings.GetWindowTextColor(); + SetTextColor( aColor ); + SetTextFillColor(); + + mpImplData->mpVirDev->SetFont( GetFont() ); + mpImplData->mpVirDev->SetTextColor( GetTextColor() ); + mpImplData->mpVirDev->SetTextAlign( GetTextAlign() ); + mpImplData->mpVirDev->SetTextFillColor(); + } + + if ( bBackground ) + { + Color aColor; + if ( IsControlBackground() ) + aColor = GetControlBackground(); + else if ( GetStyle() & WB_3DLOOK ) + aColor = rStyleSettings.GetFaceColor(); + else + aColor = rStyleSettings.GetWindowColor(); + SetBackground( aColor ); + mpImplData->mpVirDev->SetBackground( GetBackground() ); + + // NWF background + if( ! IsControlBackground() && + IsNativeControlSupported( CTRL_WINDOW_BACKGROUND, PART_BACKGROUND_WINDOW ) ) + { + ImplGetWindowImpl()->mnNativeBackground = PART_BACKGROUND_WINDOW; + EnableChildTransparentMode( TRUE ); + } + } +} + +// ----------------------------------------------------------------------- + +void StatusBar::ImplFormat() +{ + ImplStatusItem* pItem; + long nExtraWidth; + long nExtraWidth2; + long nX; + USHORT nAutoSizeItems = 0; + + // Breiten zusammenrechnen + mnItemsWidth = STATUSBAR_OFFSET_X; + long nOffset = 0; + pItem = mpItemList->First(); + while ( pItem ) + { + if ( pItem->mbVisible ) + { + if ( pItem->mnBits & SIB_AUTOSIZE ) + nAutoSizeItems++; + + mnItemsWidth += pItem->mnWidth + nOffset; + nOffset = pItem->mnOffset; + } + + pItem = mpItemList->Next(); + } + + if ( GetStyle() & WB_RIGHT ) + { + // Bei rechtsbuendiger Ausrichtung wird kein AutoSize ausgewertet, + // da wir links den Text anzeigen, der mit SetText gesetzt wird + nX = mnDX - mnItemsWidth; + nExtraWidth = 0; + nExtraWidth2 = 0; + } + else + { + mnItemsWidth += STATUSBAR_OFFSET_X; + + // Bei linksbuendiger Ausrichtung muessen wir gegebenenfalls noch + // AutoSize auswerten + if ( nAutoSizeItems && (mnDX > (mnItemsWidth - STATUSBAR_OFFSET)) ) + { + nExtraWidth = (mnDX - mnItemsWidth - 1) / nAutoSizeItems; + nExtraWidth2 = (mnDX - mnItemsWidth - 1) % nAutoSizeItems; + } + else + { + nExtraWidth = 0; + nExtraWidth2 = 0; + } + nX = STATUSBAR_OFFSET_X; + } + + pItem = mpItemList->First(); + while ( pItem ) + { + if ( pItem->mbVisible ) + { + if ( pItem->mnBits & SIB_AUTOSIZE ) + { + pItem->mnExtraWidth = nExtraWidth; + if ( nExtraWidth2 ) + { + pItem->mnExtraWidth++; + nExtraWidth2--; + } + } + else + pItem->mnExtraWidth = 0; + + pItem->mnX = nX; + nX += pItem->mnWidth + pItem->mnExtraWidth + pItem->mnOffset; + } + + pItem = mpItemList->Next(); + } + + mbFormat = FALSE; +} + +// ----------------------------------------------------------------------- + +Rectangle StatusBar::ImplGetItemRectPos( USHORT nPos ) const +{ + Rectangle aRect; + ImplStatusItem* pItem; + pItem = mpItemList->GetObject( nPos ); + if ( pItem ) + { + if ( pItem->mbVisible ) + { + aRect.Left() = pItem->mnX; + aRect.Right() = aRect.Left() + pItem->mnWidth + pItem->mnExtraWidth; + aRect.Top() = mnItemY; + aRect.Bottom() = mnCalcHeight - STATUSBAR_OFFSET_Y; + if( IsTopBorder() ) + aRect.Bottom()+=2; + } + } + + return aRect; +} + +// ----------------------------------------------------------------------- + +USHORT StatusBar::ImplGetFirstVisiblePos() const +{ + ImplStatusItem* pItem; + + for( USHORT nPos = 0; nPos < mpItemList->Count(); nPos++ ) + { + pItem = mpItemList->GetObject( nPos ); + if ( pItem ) + { + if ( pItem->mbVisible ) + return nPos; + } + } + + return ~0; +} + +// ----------------------------------------------------------------------- + +void StatusBar::ImplDrawText( BOOL bOffScreen, long nOldTextWidth ) +{ + // Das ueberschreiben der Item-Box verhindern + Rectangle aTextRect; + aTextRect.Left() = STATUSBAR_OFFSET_X+1; + aTextRect.Top() = mnTextY; + if ( mbVisibleItems && (GetStyle() & WB_RIGHT) ) + aTextRect.Right() = mnDX - mnItemsWidth - 1; + else + aTextRect.Right() = mnDX - 1; + if ( aTextRect.Right() > aTextRect.Left() ) + { + // Position ermitteln + XubString aStr = GetText(); + USHORT nPos = aStr.Search( _LF ); + if ( nPos != STRING_NOTFOUND ) + aStr.Erase( nPos ); + + aTextRect.Bottom() = aTextRect.Top()+GetTextHeight()+1; + + if ( bOffScreen ) + { + long nMaxWidth = Max( nOldTextWidth, GetTextWidth( aStr ) ); + Size aVirDevSize( nMaxWidth, aTextRect.GetHeight() ); + mpImplData->mpVirDev->SetOutputSizePixel( aVirDevSize ); + Rectangle aTempRect = aTextRect; + aTempRect.SetPos( Point( 0, 0 ) ); + mpImplData->mpVirDev->DrawText( aTempRect, aStr, TEXT_DRAW_LEFT | TEXT_DRAW_TOP | TEXT_DRAW_CLIP | TEXT_DRAW_ENDELLIPSIS ); + DrawOutDev( aTextRect.TopLeft(), aVirDevSize, Point(), aVirDevSize, *mpImplData->mpVirDev ); + } + else + DrawText( aTextRect, aStr, TEXT_DRAW_LEFT | TEXT_DRAW_TOP | TEXT_DRAW_CLIP | TEXT_DRAW_ENDELLIPSIS ); + } +} + +// ----------------------------------------------------------------------- + +void StatusBar::ImplDrawItem( BOOL bOffScreen, USHORT nPos, BOOL bDrawText, BOOL bDrawFrame ) +{ + Rectangle aRect = ImplGetItemRectPos( nPos ); + + if ( aRect.IsEmpty() ) + return; + + // Ausgabebereich berechnen + ImplStatusItem* pItem = mpItemList->GetObject( nPos ); + long nW = mpImplData->mnItemBorderWidth + 1; + Rectangle aTextRect( aRect.Left()+nW, aRect.Top()+nW, + aRect.Right()-nW, aRect.Bottom()-nW ); + Size aTextRectSize( aTextRect.GetSize() ); + + if ( bOffScreen ) + mpImplData->mpVirDev->SetOutputSizePixel( aTextRectSize ); + else + { + Region aRegion( aTextRect ); + SetClipRegion( aRegion ); + } + + // Text ausgeben + if ( bDrawText ) + { + Size aTextSize( GetTextWidth( pItem->maText ), GetTextHeight() ); + Point aTextPos = ImplGetItemTextPos( aTextRectSize, aTextSize, pItem->mnBits ); + if ( bOffScreen ) + mpImplData->mpVirDev->DrawText( aTextPos, pItem->maText ); + else + { + aTextPos.X() += aTextRect.Left(); + aTextPos.Y() += aTextRect.Top(); + DrawText( aTextPos, pItem->maText ); + } + } + + // Gegebenenfalls auch DrawItem aufrufen + if ( pItem->mnBits & SIB_USERDRAW ) + { + if ( bOffScreen ) + { + mbInUserDraw = TRUE; + mpImplData->mpVirDev->EnableRTL( IsRTLEnabled() ); + UserDrawEvent aODEvt( mpImplData->mpVirDev, Rectangle( Point(), aTextRectSize ), pItem->mnId ); + UserDraw( aODEvt ); + mpImplData->mpVirDev->EnableRTL( FALSE ); + mbInUserDraw = FALSE; + } + else + { + UserDrawEvent aODEvt( this, aTextRect, pItem->mnId ); + UserDraw( aODEvt ); + } + } + + if ( bOffScreen ) + DrawOutDev( aTextRect.TopLeft(), aTextRectSize, Point(), aTextRectSize, *mpImplData->mpVirDev ); + else + SetClipRegion(); + + // Frame ausgeben + if ( bDrawFrame ) + { + if( mpImplData->mbDrawItemFrames ) + { + if( !(pItem->mnBits & SIB_FLAT) ) + { + USHORT nStyle; + + if ( pItem->mnBits & SIB_IN ) + nStyle = FRAME_DRAW_IN; + else + nStyle = FRAME_DRAW_OUT; + + DecorationView aDecoView( this ); + aDecoView.DrawFrame( aRect, nStyle ); + } + } + else if( nPos != ImplGetFirstVisiblePos() ) + { + // draw separator + Point aFrom( aRect.TopLeft() ); + aFrom.X()--; + aFrom.Y()++; + Point aTo( aRect.BottomLeft() ); + aTo.X()--; + aTo.Y()--; + + DecorationView aDecoView( this ); + aDecoView.DrawSeparator( aFrom, aTo ); + } + } + + if ( !ImplIsRecordLayout() ) + ImplCallEventListeners( VCLEVENT_STATUSBAR_DRAWITEM, (void*) sal_IntPtr(pItem->mnId) ); +} + +// ----------------------------------------------------------------------- + +void DrawProgress( Window* pWindow, const Point& rPos, + long nOffset, long nPrgsWidth, long nPrgsHeight, + USHORT nPercent1, USHORT nPercent2, USHORT nPercentCount, + const Rectangle& rFramePosSize + ) +{ + if( pWindow->IsNativeControlSupported( CTRL_PROGRESS, PART_ENTIRE_CONTROL ) ) + { + bool bNeedErase = ImplGetSVData()->maNWFData.mbProgressNeedsErase; + + long nFullWidth = (nPrgsWidth + nOffset) * (10000 / nPercentCount); + long nPerc = (nPercent2 > 10000) ? 10000 : nPercent2; + ImplControlValue aValue( nFullWidth * (long)nPerc / 10000 ); + Rectangle aDrawRect( rPos, Size( nFullWidth, nPrgsHeight ) ); + Rectangle aControlRegion( aDrawRect ); + if( bNeedErase ) + { + Window* pEraseWindow = pWindow; + while( pEraseWindow->IsPaintTransparent() && + ! pEraseWindow->ImplGetWindowImpl()->mbFrame ) + { + pEraseWindow = pEraseWindow->ImplGetWindowImpl()->mpParent; + } + if( pEraseWindow == pWindow ) + // restore background of pWindow + pEraseWindow->Erase( rFramePosSize ); + else + { + // restore transparent background + Point aTL( pWindow->OutputToAbsoluteScreenPixel( rFramePosSize.TopLeft() ) ); + aTL = pEraseWindow->AbsoluteScreenToOutputPixel( aTL ); + Rectangle aRect( aTL, rFramePosSize.GetSize() ); + pEraseWindow->Invalidate( aRect, INVALIDATE_NOCHILDREN | + INVALIDATE_NOCLIPCHILDREN | + INVALIDATE_TRANSPARENT ); + pEraseWindow->Update(); + } + pWindow->Push( PUSH_CLIPREGION ); + pWindow->IntersectClipRegion( rFramePosSize ); + } + BOOL bNativeOK = pWindow->DrawNativeControl( CTRL_PROGRESS, PART_ENTIRE_CONTROL, aControlRegion, + CTRL_STATE_ENABLED, aValue, rtl::OUString() ); + if( bNeedErase ) + pWindow->Pop(); + if( bNativeOK ) + { + pWindow->Flush(); + return; + } + } + + // Werte vorberechnen + USHORT nPerc1 = nPercent1 / nPercentCount; + USHORT nPerc2 = nPercent2 / nPercentCount; + + if ( nPerc1 > nPerc2 ) + { + // Support progress that can also decrease + + // Rechteck berechnen + long nDX = nPrgsWidth + nOffset; + long nLeft = rPos.X()+((nPerc1-1)*nDX); + Rectangle aRect( nLeft, rPos.Y(), nLeft+nPrgsWidth, rPos.Y()+nPrgsHeight ); + + do + { + pWindow->Erase( aRect ); + aRect.Left() -= nDX; + aRect.Right() -= nDX; + nPerc1--; + } + while ( nPerc1 > nPerc2 ); + + pWindow->Flush(); + } + else if ( nPerc1 < nPerc2 ) + { + // Percent-Rechtecke malen + // Wenn Percent2 ueber 100%, Werte anpassen + if ( nPercent2 > 10000 ) + { + nPerc2 = 10000 / nPercentCount; + if ( nPerc1 >= nPerc2 ) + nPerc1 = nPerc2-1; + } + + // Rechteck berechnen + long nDX = nPrgsWidth + nOffset; + long nLeft = rPos.X()+(nPerc1*nDX); + Rectangle aRect( nLeft, rPos.Y(), nLeft+nPrgsWidth, rPos.Y()+nPrgsHeight ); + + do + { + pWindow->DrawRect( aRect ); + aRect.Left() += nDX; + aRect.Right() += nDX; + nPerc1++; + } + while ( nPerc1 < nPerc2 ); + + // Bei mehr als 100%, lassen wir das Rechteck blinken + if ( nPercent2 > 10000 ) + { + // an/aus-Status festlegen + if ( ((nPercent2 / nPercentCount) & 0x01) == (nPercentCount & 0x01) ) + { + aRect.Left() -= nDX; + aRect.Right() -= nDX; + pWindow->Erase( aRect ); + } + } + + pWindow->Flush(); + } +} + +// ----------------------------------------------------------------------- + +void StatusBar::ImplDrawProgress( BOOL bPaint, + USHORT nPercent1, USHORT nPercent2 ) +{ + bool bNative = IsNativeControlSupported( CTRL_PROGRESS, PART_ENTIRE_CONTROL ); + // bPaint: draw text also, else only update progress + if ( bPaint ) + { + DrawText( maPrgsTxtPos, maPrgsTxt ); + if( ! bNative ) + { + DecorationView aDecoView( this ); + aDecoView.DrawFrame( maPrgsFrameRect, FRAME_DRAW_IN ); + } + } + + Point aPos( maPrgsFrameRect.Left()+STATUSBAR_PRGS_OFFSET, + maPrgsFrameRect.Top()+STATUSBAR_PRGS_OFFSET ); + long nPrgsHeight = mnPrgsSize; + if( bNative ) + { + aPos = maPrgsFrameRect.TopLeft(); + nPrgsHeight = maPrgsFrameRect.GetHeight(); + } + DrawProgress( this, aPos, mnPrgsSize/2, mnPrgsSize, nPrgsHeight, + nPercent1*100, nPercent2*100, mnPercentCount, maPrgsFrameRect ); +} + +// ----------------------------------------------------------------------- + +void StatusBar::ImplCalcProgressRect() +{ + // calculate text size + Size aPrgsTxtSize( GetTextWidth( maPrgsTxt ), GetTextHeight() ); + maPrgsTxtPos.X() = STATUSBAR_OFFSET_X+1; + + // calculate progress frame + maPrgsFrameRect.Left() = maPrgsTxtPos.X()+aPrgsTxtSize.Width()+STATUSBAR_OFFSET; + maPrgsFrameRect.Top() = mnItemY; + maPrgsFrameRect.Bottom() = mnCalcHeight - STATUSBAR_OFFSET_Y; + if( IsTopBorder() ) + maPrgsFrameRect.Bottom()+=2; + + // calculate size of progress rects + mnPrgsSize = maPrgsFrameRect.Bottom()-maPrgsFrameRect.Top()-(STATUSBAR_PRGS_OFFSET*2); + USHORT nMaxPercent = STATUSBAR_PRGS_COUNT; + + long nMaxWidth = mnDX-STATUSBAR_OFFSET-1; + + // make smaller if there are too many rects + while ( maPrgsFrameRect.Left()+ImplCalcProgessWidth( nMaxPercent, mnPrgsSize ) > nMaxWidth ) + { + nMaxPercent--; + if ( nMaxPercent <= STATUSBAR_PRGS_MIN ) + break; + } + maPrgsFrameRect.Right() = maPrgsFrameRect.Left() + ImplCalcProgessWidth( nMaxPercent, mnPrgsSize ); + + // save the divisor for later + mnPercentCount = 10000 / nMaxPercent; + BOOL bNativeOK = FALSE; + if( IsNativeControlSupported( CTRL_PROGRESS, PART_ENTIRE_CONTROL ) ) + { + ImplControlValue aValue; + Rectangle aControlRegion( Rectangle( (const Point&)Point(), maPrgsFrameRect.GetSize() ) ); + Rectangle aNativeControlRegion, aNativeContentRegion; + if( (bNativeOK = GetNativeControlRegion( CTRL_PROGRESS, PART_ENTIRE_CONTROL, aControlRegion, + CTRL_STATE_ENABLED, aValue, rtl::OUString(), + aNativeControlRegion, aNativeContentRegion ) ) != FALSE ) + { + long nProgressHeight = aNativeControlRegion.GetHeight(); + if( nProgressHeight > maPrgsFrameRect.GetHeight() ) + { + long nDelta = nProgressHeight - maPrgsFrameRect.GetHeight(); + maPrgsFrameRect.Top() -= (nDelta - nDelta/2); + maPrgsFrameRect.Bottom() += nDelta/2; + } + maPrgsTxtPos.Y() = maPrgsFrameRect.Top() + (nProgressHeight - GetTextHeight())/2; + } + } + if( ! bNativeOK ) + maPrgsTxtPos.Y() = mnTextY; +} + +// ----------------------------------------------------------------------- + +void StatusBar::MouseButtonDown( const MouseEvent& rMEvt ) +{ + // Nur bei linker Maustaste ToolBox ausloesen + if ( rMEvt.IsLeft() ) + { + if ( mbVisibleItems ) + { + Point aMousePos = rMEvt.GetPosPixel(); + USHORT i = 0; + + // Item suchen, das geklickt wurde + ImplStatusItem* pItem = mpItemList->First(); + while ( pItem ) + { + // Ist es dieses Item + if ( ImplGetItemRectPos( i ).IsInside( aMousePos ) ) + { + mnCurItemId = pItem->mnId; + if ( rMEvt.GetClicks() == 2 ) + DoubleClick(); + else + Click(); + mnCurItemId = 0; + + // Item wurde gefunden + return; + } + + i++; + pItem = mpItemList->Next(); + } + } + + // Kein Item, dann nur Click oder DoubleClick + if ( rMEvt.GetClicks() == 2 ) + DoubleClick(); + else + Click(); + } +} + +// ----------------------------------------------------------------------- + +void StatusBar::Paint( const Rectangle& ) +{ + if ( mbFormat ) + ImplFormat(); + + USHORT nItemCount = (USHORT)mpItemList->Count(); + + if ( mbProgressMode ) + ImplDrawProgress( TRUE, 0, mnPercent ); + else + { + // Text zeichen + if ( !mbVisibleItems || (GetStyle() & WB_RIGHT) ) + ImplDrawText( FALSE, 0 ); + + // Items zeichnen + if ( mbVisibleItems ) + { + // Items zeichnen + for ( USHORT i = 0; i < nItemCount; i++ ) + ImplDrawItem( FALSE, i, TRUE, TRUE ); + } + } + + // draw borders + if( IsTopBorder() ) + { + const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); + SetLineColor( rStyleSettings.GetShadowColor() ); + DrawLine( Point( 0, 0 ), Point( mnDX-1, 0 ) ); + SetLineColor( rStyleSettings.GetLightColor() ); + DrawLine( Point( 0, 1 ), Point( mnDX-1, 1 ) ); + } + + if ( IsBottomBorder() ) + { + const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); + SetLineColor( rStyleSettings.GetShadowColor() ); + DrawLine( Point( 0, mnDY-2 ), Point( mnDX-1, mnDY-2 ) ); + SetLineColor( rStyleSettings.GetLightColor() ); + DrawLine( Point( 0, mnDY-1 ), Point( mnDX-1, mnDY-1 ) ); + } +} + +// ----------------------------------------------------------------------- + +void StatusBar::Move() +{ + Window::Move(); +} + +// ----------------------------------------------------------------------- + +void StatusBar::Resize() +{ + // Breite und Hoehe abfragen und merken + Size aSize = GetOutputSizePixel(); + mnDX = aSize.Width(); + mnDY = aSize.Height(); + mnCalcHeight = mnDY; + // subtract border + if( IsTopBorder() ) + mnCalcHeight -= 2; + if ( IsBottomBorder() ) + mnCalcHeight -= 2; + + mnItemY = STATUSBAR_OFFSET_Y; + if( IsTopBorder() ) + mnItemY += 2; + mnTextY = (mnCalcHeight-GetTextHeight())/2; + if( IsTopBorder() ) + mnTextY += 2; + + // Formatierung neu ausloesen + mbFormat = TRUE; + + if ( mbProgressMode ) + ImplCalcProgressRect(); + + Invalidate(); +} + +// ----------------------------------------------------------------------- + +void StatusBar::RequestHelp( const HelpEvent& rHEvt ) +{ + // no keyboard help in status bar + if( rHEvt.KeyboardActivated() ) + return; + + USHORT nItemId = GetItemId( ScreenToOutputPixel( rHEvt.GetMousePosPixel() ) ); + + if ( nItemId ) + { + Rectangle aItemRect = GetItemRect( nItemId ); + Point aPt = OutputToScreenPixel( aItemRect.TopLeft() ); + aItemRect.Left() = aPt.X(); + aItemRect.Top() = aPt.Y(); + aPt = OutputToScreenPixel( aItemRect.BottomRight() ); + aItemRect.Right() = aPt.X(); + aItemRect.Bottom() = aPt.Y(); + + if ( rHEvt.GetMode() & HELPMODE_BALLOON ) + { + XubString aStr = GetHelpText( nItemId ); + Help::ShowBalloon( this, aItemRect.Center(), aItemRect, aStr ); + return; + } + else if ( rHEvt.GetMode() & HELPMODE_QUICK ) + { + XubString aStr = GetQuickHelpText( nItemId ); + // Show quickhelp if available + if( aStr.Len() ) + { + Help::ShowQuickHelp( this, aItemRect, aStr ); + return; + } + aStr = GetItemText( nItemId ); + // show a quick help if item text doesn't fit + if ( GetTextWidth( aStr ) > aItemRect.GetWidth() ) + { + Help::ShowQuickHelp( this, aItemRect, aStr ); + return; + } + } + else if ( rHEvt.GetMode() & HELPMODE_EXTENDED ) + { + String aCommand = GetItemCommand( nItemId ); + ULONG nHelpId = GetHelpId( nItemId ); + + if ( aCommand.Len() || nHelpId ) + { + // Wenn eine Hilfe existiert, dann ausloesen + Help* pHelp = Application::GetHelp(); + if ( pHelp ) + { + if ( aCommand.Len() ) + pHelp->Start( aCommand, this ); + else if ( nHelpId ) + pHelp->Start( nHelpId, this ); + } + return; + } + } + } + + Window::RequestHelp( rHEvt ); +} + +// ----------------------------------------------------------------------- + +void StatusBar::StateChanged( StateChangedType nType ) +{ + Window::StateChanged( nType ); + + if ( nType == STATE_CHANGE_INITSHOW ) + ImplFormat(); + else if ( nType == STATE_CHANGE_UPDATEMODE ) + Invalidate(); + else if ( (nType == STATE_CHANGE_ZOOM) || + (nType == STATE_CHANGE_CONTROLFONT) ) + { + mbFormat = TRUE; + ImplInitSettings( TRUE, FALSE, FALSE ); + Invalidate(); + } + else if ( nType == STATE_CHANGE_CONTROLFOREGROUND ) + { + ImplInitSettings( FALSE, TRUE, FALSE ); + Invalidate(); + } + else if ( nType == STATE_CHANGE_CONTROLBACKGROUND ) + { + ImplInitSettings( FALSE, FALSE, TRUE ); + Invalidate(); + } +} + +// ----------------------------------------------------------------------- + +void StatusBar::DataChanged( const DataChangedEvent& rDCEvt ) +{ + Window::DataChanged( rDCEvt ); + + if ( (rDCEvt.GetType() == DATACHANGED_DISPLAY) || + (rDCEvt.GetType() == DATACHANGED_FONTS) || + (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) || + ((rDCEvt.GetType() == DATACHANGED_SETTINGS) && + (rDCEvt.GetFlags() & SETTINGS_STYLE)) ) + { + mbFormat = TRUE; + ImplInitSettings( TRUE, TRUE, TRUE ); + ImplStatusItem* pItem = mpItemList->First(); + long nFudge = GetTextHeight() / 4; + while ( pItem ) + { + long nWidth = GetTextWidth( pItem->maText ) + nFudge; + if( nWidth > pItem->mnWidth + STATUSBAR_OFFSET ) + pItem->mnWidth = nWidth + STATUSBAR_OFFSET; + pItem = mpItemList->Next(); + } + Size aSize = GetSizePixel(); + // do not disturb current width, since + // CalcWindowSizePixel calculates a minimum width + aSize.Height() = CalcWindowSizePixel().Height(); + SetSizePixel( aSize ); + Invalidate(); + } +} + +// ----------------------------------------------------------------------- + +void StatusBar::Click() +{ + ImplCallEventListeners( VCLEVENT_STATUSBAR_CLICK ); + maClickHdl.Call( this ); +} + +// ----------------------------------------------------------------------- + +void StatusBar::DoubleClick() +{ + ImplCallEventListeners( VCLEVENT_STATUSBAR_DOUBLECLICK ); + maDoubleClickHdl.Call( this ); +} + +// ----------------------------------------------------------------------- + +void StatusBar::UserDraw( const UserDrawEvent& ) +{ +} + +// ----------------------------------------------------------------------- + +void StatusBar::InsertItem( USHORT nItemId, ULONG nWidth, + StatusBarItemBits nBits, + long nOffset, USHORT nPos ) +{ + DBG_ASSERT( nItemId, "StatusBar::InsertItem(): ItemId == 0" ); + DBG_ASSERT( GetItemPos( nItemId ) == STATUSBAR_ITEM_NOTFOUND, + "StatusBar::InsertItem(): ItemId already exists" ); + + // IN und CENTER sind Default + if ( !(nBits & (SIB_IN | SIB_OUT | SIB_FLAT)) ) + nBits |= SIB_IN; + if ( !(nBits & (SIB_LEFT | SIB_RIGHT | SIB_CENTER)) ) + nBits |= SIB_CENTER; + + // Item anlegen + long nFudge = GetTextHeight()/4; + ImplStatusItem* pItem = new ImplStatusItem; + pItem->mnId = nItemId; + pItem->mnBits = nBits; + pItem->mnWidth = (long)nWidth+nFudge+STATUSBAR_OFFSET; + pItem->mnOffset = nOffset; + pItem->mnHelpId = 0; + pItem->mpUserData = 0; + pItem->mbVisible = TRUE; + + // Item in die Liste einfuegen + mpItemList->Insert( pItem, nPos ); + + mbFormat = TRUE; + if ( ImplIsItemUpdate() ) + Invalidate(); + + ImplCallEventListeners( VCLEVENT_STATUSBAR_ITEMADDED, (void*) sal_IntPtr(nItemId) ); +} + +// ----------------------------------------------------------------------- + +void StatusBar::RemoveItem( USHORT nItemId ) +{ + USHORT nPos = GetItemPos( nItemId ); + if ( nPos != STATUSBAR_ITEM_NOTFOUND ) + { + ImplStatusItem* pItem = mpItemList->Remove( nPos ); + delete pItem; + + mbFormat = TRUE; + if ( ImplIsItemUpdate() ) + Invalidate(); + + ImplCallEventListeners( VCLEVENT_STATUSBAR_ITEMREMOVED, (void*) sal_IntPtr(nItemId) ); + } +} + +// ----------------------------------------------------------------------- + +void StatusBar::ShowItem( USHORT nItemId ) +{ + USHORT nPos = GetItemPos( nItemId ); + + if ( nPos != STATUSBAR_ITEM_NOTFOUND ) + { + ImplStatusItem* pItem = mpItemList->GetObject( nPos ); + if ( !pItem->mbVisible ) + { + pItem->mbVisible = TRUE; + + mbFormat = TRUE; + if ( ImplIsItemUpdate() ) + Invalidate(); + + ImplCallEventListeners( VCLEVENT_STATUSBAR_SHOWITEM, (void*) sal_IntPtr(nItemId) ); + } + } +} + +// ----------------------------------------------------------------------- + +void StatusBar::HideItem( USHORT nItemId ) +{ + USHORT nPos = GetItemPos( nItemId ); + + if ( nPos != STATUSBAR_ITEM_NOTFOUND ) + { + ImplStatusItem* pItem = mpItemList->GetObject( nPos ); + if ( pItem->mbVisible ) + { + pItem->mbVisible = FALSE; + + mbFormat = TRUE; + if ( ImplIsItemUpdate() ) + Invalidate(); + + ImplCallEventListeners( VCLEVENT_STATUSBAR_HIDEITEM, (void*) sal_IntPtr(nItemId) ); + } + } +} + +// ----------------------------------------------------------------------- + +BOOL StatusBar::IsItemVisible( USHORT nItemId ) const +{ + USHORT nPos = GetItemPos( nItemId ); + + if ( nPos != STATUSBAR_ITEM_NOTFOUND ) + return mpItemList->GetObject( nPos )->mbVisible; + else + return FALSE; +} + +// ----------------------------------------------------------------------- + +void StatusBar::ShowItems() +{ + if ( !mbVisibleItems ) + { + mbVisibleItems = TRUE; + if ( !mbProgressMode ) + Invalidate(); + + ImplCallEventListeners( VCLEVENT_STATUSBAR_SHOWALLITEMS ); + } +} + +// ----------------------------------------------------------------------- + +void StatusBar::HideItems() +{ + if ( mbVisibleItems ) + { + mbVisibleItems = FALSE; + if ( !mbProgressMode ) + Invalidate(); + + ImplCallEventListeners( VCLEVENT_STATUSBAR_HIDEALLITEMS ); + } +} + +// ----------------------------------------------------------------------- + +void StatusBar::CopyItems( const StatusBar& rStatusBar ) +{ + // Alle Items entfernen + ImplStatusItem* pItem = mpItemList->First(); + while ( pItem ) + { + delete pItem; + pItem = mpItemList->Next(); + } + + // Items aus der Liste loeschen + mpItemList->Clear(); + + // Items kopieren + ULONG i = 0; + pItem = rStatusBar.mpItemList->GetObject( i ); + while ( pItem ) + { + mpItemList->Insert( new ImplStatusItem( *pItem ), LIST_APPEND ); + i++; + pItem = rStatusBar.mpItemList->GetObject( i ); + } + + mbFormat = TRUE; + if ( ImplIsItemUpdate() ) + Invalidate(); +} + +// ----------------------------------------------------------------------- + +void StatusBar::Clear() +{ + // Alle Item loeschen + ImplStatusItem* pItem = mpItemList->First(); + while ( pItem ) + { + delete pItem; + pItem = mpItemList->Next(); + } + + // Items aus der Liste loeschen + mpItemList->Clear(); + + mbFormat = TRUE; + if ( ImplIsItemUpdate() ) + Invalidate(); + + ImplCallEventListeners( VCLEVENT_STATUSBAR_ALLITEMSREMOVED ); +} + +// ----------------------------------------------------------------------- + +USHORT StatusBar::GetItemCount() const +{ + return (USHORT)mpItemList->Count(); +} + +// ----------------------------------------------------------------------- + +USHORT StatusBar::GetItemId( USHORT nPos ) const +{ + ImplStatusItem* pItem = mpItemList->GetObject( nPos ); + if ( pItem ) + return pItem->mnId; + else + return 0; +} + +// ----------------------------------------------------------------------- + +USHORT StatusBar::GetItemPos( USHORT nItemId ) const +{ + ImplStatusItem* pItem = mpItemList->First(); + while ( pItem ) + { + if ( pItem->mnId == nItemId ) + return (USHORT)mpItemList->GetCurPos(); + + pItem = mpItemList->Next(); + } + + return STATUSBAR_ITEM_NOTFOUND; +} + +// ----------------------------------------------------------------------- + +USHORT StatusBar::GetItemId( const Point& rPos ) const +{ + if ( AreItemsVisible() && !mbFormat ) + { + USHORT nItemCount = GetItemCount(); + USHORT nPos; + for ( nPos = 0; nPos < nItemCount; nPos++ ) + { + // Rechteck holen + Rectangle aRect = ImplGetItemRectPos( nPos ); + if ( aRect.IsInside( rPos ) ) + return mpItemList->GetObject( nPos )->mnId; + } + } + + return 0; +} + +// ----------------------------------------------------------------------- + +Rectangle StatusBar::GetItemRect( USHORT nItemId ) const +{ + Rectangle aRect; + + if ( AreItemsVisible() && !mbFormat ) + { + USHORT nPos = GetItemPos( nItemId ); + if ( nPos != STATUSBAR_ITEM_NOTFOUND ) + { + // Rechteck holen und Rahmen abziehen + aRect = ImplGetItemRectPos( nPos ); + long nW = mpImplData->mnItemBorderWidth+1; + aRect.Top() += nW-1; + aRect.Bottom() -= nW-1; + aRect.Left() += nW; + aRect.Right() -= nW; + return aRect; + } + } + + return aRect; +} + +// ----------------------------------------------------------------------- + +Point StatusBar::GetItemTextPos( USHORT nItemId ) const +{ + if ( !mbFormat ) + { + USHORT nPos = GetItemPos( nItemId ); + if ( nPos != STATUSBAR_ITEM_NOTFOUND ) + { + // Rechteck holen + ImplStatusItem* pItem = mpItemList->GetObject( nPos ); + Rectangle aRect = ImplGetItemRectPos( nPos ); + long nW = mpImplData->mnItemBorderWidth + 1; + Rectangle aTextRect( aRect.Left()+nW, aRect.Top()+nW, + aRect.Right()-nW, aRect.Bottom()-nW ); + Point aPos = ImplGetItemTextPos( aTextRect.GetSize(), + Size( GetTextWidth( pItem->maText ), GetTextHeight() ), + pItem->mnBits ); + if ( !mbInUserDraw ) + { + aPos.X() += aTextRect.Left(); + aPos.Y() += aTextRect.Top(); + } + return aPos; + } + } + + return Point(); +} + +// ----------------------------------------------------------------------- + +ULONG StatusBar::GetItemWidth( USHORT nItemId ) const +{ + USHORT nPos = GetItemPos( nItemId ); + + if ( nPos != STATUSBAR_ITEM_NOTFOUND ) + return mpItemList->GetObject( nPos )->mnWidth; + else + return 0; +} + +// ----------------------------------------------------------------------- + +StatusBarItemBits StatusBar::GetItemBits( USHORT nItemId ) const +{ + USHORT nPos = GetItemPos( nItemId ); + + if ( nPos != STATUSBAR_ITEM_NOTFOUND ) + return mpItemList->GetObject( nPos )->mnBits; + else + return 0; +} + +// ----------------------------------------------------------------------- + +long StatusBar::GetItemOffset( USHORT nItemId ) const +{ + USHORT nPos = GetItemPos( nItemId ); + + if ( nPos != STATUSBAR_ITEM_NOTFOUND ) + return mpItemList->GetObject( nPos )->mnOffset; + else + return 0; +} + +// ----------------------------------------------------------------------- + +void StatusBar::SetItemText( USHORT nItemId, const XubString& rText ) +{ + USHORT nPos = GetItemPos( nItemId ); + + if ( nPos != STATUSBAR_ITEM_NOTFOUND ) + { + ImplStatusItem* pItem = mpItemList->GetObject( nPos ); + + if ( pItem->maText != rText ) + { + pItem->maText = rText; + + // adjust item width - see also DataChanged() + long nFudge = GetTextHeight()/4; + long nWidth = GetTextWidth( pItem->maText ) + nFudge; + if( (nWidth > pItem->mnWidth + STATUSBAR_OFFSET) || + ((nWidth < pItem->mnWidth) && (mnDX - STATUSBAR_OFFSET) < mnItemsWidth )) + { + pItem->mnWidth = nWidth + STATUSBAR_OFFSET; + ImplFormat(); + Invalidate(); + } + + // Item neu Zeichen, wenn StatusBar sichtbar und + // UpdateMode gesetzt ist + if ( pItem->mbVisible && !mbFormat && ImplIsItemUpdate() ) + { + Update(); + ImplDrawItem( TRUE, nPos, TRUE, FALSE ); + Flush(); + } + } + } +} + +// ----------------------------------------------------------------------- + +const XubString& StatusBar::GetItemText( USHORT nItemId ) const +{ + USHORT nPos = GetItemPos( nItemId ); + + if ( nPos != STATUSBAR_ITEM_NOTFOUND ) + return mpItemList->GetObject( nPos )->maText; + else + return ImplGetSVEmptyStr(); +} + +// ----------------------------------------------------------------------- + +void StatusBar::SetItemCommand( USHORT nItemId, const XubString& rCommand ) +{ + USHORT nPos = GetItemPos( nItemId ); + + if ( nPos != STATUSBAR_ITEM_NOTFOUND ) + { + ImplStatusItem* pItem = mpItemList->GetObject( nPos ); + + if ( pItem->maCommand != rCommand ) + pItem->maCommand = rCommand; + } +} + +// ----------------------------------------------------------------------- + +const XubString& StatusBar::GetItemCommand( USHORT nItemId ) +{ + USHORT nPos = GetItemPos( nItemId ); + + if ( nPos != STATUSBAR_ITEM_NOTFOUND ) + return mpItemList->GetObject( nPos )->maCommand; + else + return ImplGetSVEmptyStr(); +} + +// ----------------------------------------------------------------------- + +void StatusBar::SetItemData( USHORT nItemId, void* pNewData ) +{ + USHORT nPos = GetItemPos( nItemId ); + + if ( nPos != STATUSBAR_ITEM_NOTFOUND ) + { + ImplStatusItem* pItem = mpItemList->GetObject( nPos ); + pItem->mpUserData = pNewData; + + // Wenn es ein User-Item ist, DrawItem-Aufrufen + if ( (pItem->mnBits & SIB_USERDRAW) && pItem->mbVisible && + !mbFormat && ImplIsItemUpdate() ) + { + Update(); + ImplDrawItem( TRUE, nPos, FALSE, FALSE ); + Flush(); + } + } +} + +// ----------------------------------------------------------------------- + +void* StatusBar::GetItemData( USHORT nItemId ) const +{ + USHORT nPos = GetItemPos( nItemId ); + + if ( nPos != STATUSBAR_ITEM_NOTFOUND ) + return mpItemList->GetObject( nPos )->mpUserData; + else + return NULL; +} + +// ----------------------------------------------------------------------- + +void StatusBar::SetHelpText( USHORT nItemId, const XubString& rText ) +{ + USHORT nPos = GetItemPos( nItemId ); + + if ( nPos != STATUSBAR_ITEM_NOTFOUND ) + mpItemList->GetObject( nPos )->maHelpText = rText; +} + +// ----------------------------------------------------------------------- + +const XubString& StatusBar::GetHelpText( USHORT nItemId ) const +{ + USHORT nPos = GetItemPos( nItemId ); + + if ( nPos != STATUSBAR_ITEM_NOTFOUND ) + { + ImplStatusItem* pItem = mpItemList->GetObject( nPos ); + if ( !pItem->maHelpText.Len() && ( pItem->mnHelpId || pItem->maCommand.Len() )) + { + Help* pHelp = Application::GetHelp(); + if ( pHelp ) + { + if ( pItem->maCommand.Len() ) + pItem->maHelpText = pHelp->GetHelpText( pItem->maCommand, this ); + if ( !pItem->maHelpText.Len() && pItem->mnHelpId ) + pItem->maHelpText = pHelp->GetHelpText( pItem->mnHelpId, this ); + } + } + + return pItem->maHelpText; + } + else + return ImplGetSVEmptyStr(); +} + +// ----------------------------------------------------------------------- + +void StatusBar::SetQuickHelpText( USHORT nItemId, const XubString& rText ) +{ + USHORT nPos = GetItemPos( nItemId ); + + if ( nPos != STATUSBAR_ITEM_NOTFOUND ) + mpItemList->GetObject( nPos )->maQuickHelpText = rText; +} + +// ----------------------------------------------------------------------- + +const XubString& StatusBar::GetQuickHelpText( USHORT nItemId ) const +{ + USHORT nPos = GetItemPos( nItemId ); + + if ( nPos != STATUSBAR_ITEM_NOTFOUND ) + { + ImplStatusItem* pItem = mpItemList->GetObject( nPos ); + return pItem->maQuickHelpText; + } + else + return ImplGetSVEmptyStr(); +} + +// ----------------------------------------------------------------------- + +void StatusBar::SetHelpId( USHORT nItemId, ULONG nHelpId ) +{ + USHORT nPos = GetItemPos( nItemId ); + + if ( nPos != STATUSBAR_ITEM_NOTFOUND ) + mpItemList->GetObject( nPos )->mnHelpId = nHelpId; +} + +// ----------------------------------------------------------------------- + +ULONG StatusBar::GetHelpId( USHORT nItemId ) const +{ + USHORT nPos = GetItemPos( nItemId ); + + if ( nPos != STATUSBAR_ITEM_NOTFOUND ) + return mpItemList->GetObject( nPos )->mnHelpId; + else + return 0; +} + +// ----------------------------------------------------------------------- + +void StatusBar::ImplCalcBorder( ) +{ + mnCalcHeight = mnDY; + // subtract border + if( IsTopBorder() ) + { + mnCalcHeight -= 2; + mnTextY += 2; + mnItemY += 2; + } + if ( IsBottomBorder() ) + mnCalcHeight -= 2; + mbFormat = TRUE; + Invalidate(); +} + +void StatusBar::SetBottomBorder( BOOL bBottomBorder ) +{ + if ( mbBottomBorder != bBottomBorder ) + { + mbBottomBorder = bBottomBorder; + ImplCalcBorder(); + } +} + +void StatusBar::SetTopBorder( BOOL bTopBorder ) +{ + if ( mpImplData->mbTopBorder != static_cast<bool>(bTopBorder) ) + { + mpImplData->mbTopBorder = static_cast<bool>(bTopBorder); + ImplCalcBorder(); + } +} + +BOOL StatusBar::IsTopBorder() const +{ + return mpImplData->mbTopBorder; +} + +// ----------------------------------------------------------------------- + +void StatusBar::StartProgressMode( const XubString& rText ) +{ + DBG_ASSERT( !mbProgressMode, "StatusBar::StartProgressMode(): progress mode is active" ); + + mbProgressMode = TRUE; + mnPercent = 0; + maPrgsTxt = rText; + + // Groessen berechnen + ImplCalcProgressRect(); + + // Paint ausloesen (dort wird der Text und der Frame gemalt) + const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); + Color aPrgsColor = rStyleSettings.GetHighlightColor(); + if ( aPrgsColor == rStyleSettings.GetFaceColor() ) + aPrgsColor = rStyleSettings.GetDarkShadowColor(); + SetLineColor(); + SetFillColor( aPrgsColor ); + if ( IsReallyVisible() ) + { + Invalidate(); + Update(); + Flush(); + } +} + +// ----------------------------------------------------------------------- + +void StatusBar::SetProgressValue( USHORT nNewPercent ) +{ + DBG_ASSERT( mbProgressMode, "StatusBar::SetProgressValue(): no progrss mode" ); + DBG_ASSERTWARNING( nNewPercent <= 100, "StatusBar::SetProgressValue(): nPercent > 100" ); + + if ( mbProgressMode + && IsReallyVisible() + && (!mnPercent || (mnPercent != nNewPercent)) ) + { + Update(); + SetLineColor(); + ImplDrawProgress( FALSE, mnPercent, nNewPercent ); + Flush(); + } + mnPercent = nNewPercent; +} + +// ----------------------------------------------------------------------- + +void StatusBar::EndProgressMode() +{ + DBG_ASSERT( mbProgressMode, "StatusBar::EndProgressMode(): no progress mode" ); + + mbProgressMode = FALSE; + maPrgsTxt.Erase(); + + // Paint neu ausloesen um StatusBar wieder herzustellen + SetFillColor( GetSettings().GetStyleSettings().GetFaceColor() ); + if ( IsReallyVisible() ) + { + Invalidate(); + Update(); + Flush(); + } +} + +// ----------------------------------------------------------------------- + +void StatusBar::ResetProgressMode() +{ + if ( mbProgressMode ) + { + mnPercent = 0; + maPrgsTxt.Erase(); + if ( IsReallyVisible() ) + { + Invalidate(); + Update(); + Flush(); + } + } +} + +// ----------------------------------------------------------------------- + +void StatusBar::SetText( const XubString& rText ) +{ + if ( (!mbVisibleItems || (GetStyle() & WB_RIGHT)) && !mbProgressMode && + IsReallyVisible() && IsUpdateMode() ) + { + if ( mbFormat ) + { + Invalidate(); + Window::SetText( rText ); + } + else + { + Update(); + long nOldTextWidth = GetTextWidth( GetText() ); + Window::SetText( rText ); + ImplDrawText( TRUE, nOldTextWidth ); + Flush(); + } + } + else if ( mbProgressMode ) + { + maPrgsTxt = rText; + if ( IsReallyVisible() ) + { + Invalidate(); + Update(); + Flush(); + } + } + else + Window::SetText( rText ); +} + +// ----------------------------------------------------------------------- + +Size StatusBar::CalcWindowSizePixel() const +{ + ULONG i = 0; + ULONG nCount = mpItemList->Count(); + long nOffset = 0; + long nCalcWidth = (STATUSBAR_OFFSET_X*2); + long nCalcHeight; + + while ( i < nCount ) + { + ImplStatusItem* pItem = mpItemList->GetObject( i ); + nCalcWidth += pItem->mnWidth + nOffset; + nOffset = pItem->mnOffset; + i++; + } + + long nMinHeight = GetTextHeight(); + const long nBarTextOffset = STATUSBAR_OFFSET_TEXTY*2; + long nProgressHeight = nMinHeight + nBarTextOffset; + // FIXME: IsNativeControlSupported and GetNativeControlRegion should be const ? + StatusBar* pThis = const_cast<StatusBar*>( this ); + if( pThis->IsNativeControlSupported( CTRL_PROGRESS, PART_ENTIRE_CONTROL ) ) + { + ImplControlValue aValue; + Rectangle aControlRegion( (const Point&)Point(), Size( nCalcWidth, nMinHeight ) ); + Rectangle aNativeControlRegion, aNativeContentRegion; + if( pThis->GetNativeControlRegion( CTRL_PROGRESS, PART_ENTIRE_CONTROL, aControlRegion, + CTRL_STATE_ENABLED, aValue, rtl::OUString(), + aNativeControlRegion, aNativeContentRegion ) ) + { + nProgressHeight = aNativeControlRegion.GetHeight(); + } + } + + if( mpImplData->mbDrawItemFrames && + pThis->IsNativeControlSupported( CTRL_FRAME, PART_BORDER ) ) + { + ImplControlValue aControlValue( FRAME_DRAW_NODRAW ); + Rectangle aBound, aContent; + Rectangle aNatRgn( Point( 0, 0 ), Size( 150, 50 ) ); + if( pThis->GetNativeControlRegion(CTRL_FRAME, PART_BORDER, + aNatRgn, 0, aControlValue, rtl::OUString(), aBound, aContent) ) + { + mpImplData->mnItemBorderWidth = + ( aBound.GetHeight() - aContent.GetHeight() ) / 2; + } + } + + nCalcHeight = nMinHeight+nBarTextOffset + 2*mpImplData->mnItemBorderWidth; + if( nCalcHeight < nProgressHeight+2 ) + nCalcHeight = nProgressHeight+2; + + // add border + if( IsTopBorder() ) + nCalcHeight += 2; + if ( IsBottomBorder() ) + nCalcHeight += 2; + + return Size( nCalcWidth, nCalcHeight ); +} + + +// ----------------------------------------------------------------------- + +void StatusBar::SetAccessibleName( USHORT nItemId, const XubString& rName ) +{ + USHORT nPos = GetItemPos( nItemId ); + + if ( nPos != STATUSBAR_ITEM_NOTFOUND ) + { + ImplStatusItem* pItem = mpItemList->GetObject( nPos ); + + if ( pItem->maAccessibleName != rName ) + { + pItem->maAccessibleName = rName; + ImplCallEventListeners( VCLEVENT_STATUSBAR_NAMECHANGED, (void*) sal_IntPtr(pItem->mnId) ); + } + } +} + +// ----------------------------------------------------------------------- + +const XubString& StatusBar::GetAccessibleName( USHORT nItemId ) const +{ + USHORT nPos = GetItemPos( nItemId ); + + if ( nPos != STATUSBAR_ITEM_NOTFOUND ) + return mpItemList->GetObject( nPos )->maAccessibleName; + else + return ImplGetSVEmptyStr(); +} + +// ----------------------------------------------------------------------- |