/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_vcl.hxx"

#include <tools/list.hxx>
#include <tools/debug.hxx>
#include <tools/rc.h>

#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 <svdata.hxx>
#include <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
{
	sal_uInt16				mnId;
	StatusBarItemBits	mnBits;
	long				mnWidth;
	long				mnOffset;
	long				mnExtraWidth;
	long				mnX;
	XubString			maText;
	XubString			maHelpText;
	XubString			maQuickHelpText;
	rtl::OString		maHelpId;
	void*				mpUserData;
	sal_Bool				mbVisible;
	XubString			maAccessibleName;
    XubString           maCommand;
};

DECLARE_LIST( ImplStatusItemList, ImplStatusItem* )

// =======================================================================

inline long ImplCalcProgessWidth( sal_uInt16 nMax, long nSize )
{
	return ((nMax*(nSize+(nSize/2)))-(nSize/2)+(STATUSBAR_PRGS_OFFSET*2));
}

// -----------------------------------------------------------------------

static Point ImplGetItemTextPos( const Size& rRectSize, const Size& rTextSize,
								 sal_uInt16 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 );
}

// -----------------------------------------------------------------------

sal_Bool StatusBar::ImplIsItemUpdate()
{
	if ( !mbProgressMode && mbVisibleItems && IsReallyVisible() && IsUpdateMode() )
		return sal_True;
	else
		return sal_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		= sal_True;
	mbVisibleItems	= sal_True;
	mbProgressMode	= sal_False;
	mbInUserDraw	= sal_False;
	mbBottomBorder	= sal_False;
    mnItemsWidth    = STATUSBAR_OFFSET_X;
	mnDX			= 0;
	mnDY			= 0;
	mnCalcHeight	= 0;
	mnItemY 		= STATUSBAR_OFFSET_Y;
	mnTextY 		= STATUSBAR_OFFSET_TEXTY;

	ImplInitSettings( sal_True, sal_True, sal_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( sal_Bool bFont,
								  sal_Bool bForeground, sal_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( sal_True );
        }
	}
}

// -----------------------------------------------------------------------

void StatusBar::ImplFormat()
{
	ImplStatusItem* pItem;
	long			nExtraWidth;
	long			nExtraWidth2;
	long			nX;
	sal_uInt16			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;
		if( ImplHasMirroredGraphics() && IsRTLEnabled() )
		    nX += ImplGetSVData()->maNWFData.mnStatusBarLowerRightOffset;
	}

	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 = sal_False;
}

// -----------------------------------------------------------------------

Rectangle StatusBar::ImplGetItemRectPos( sal_uInt16 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;
}

// -----------------------------------------------------------------------

sal_uInt16 StatusBar::ImplGetFirstVisiblePos() const
{
    ImplStatusItem* pItem;
    
    for( sal_uInt16 nPos = 0; nPos < mpItemList->Count(); nPos++ )
    {
        pItem = mpItemList->GetObject( nPos );
        if ( pItem )
        {
            if ( pItem->mbVisible )
                return nPos;
        }
    }
    
    return ~0;
}

// -----------------------------------------------------------------------

void StatusBar::ImplDrawText( sal_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();
		sal_uInt16 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( sal_Bool bOffScreen, sal_uInt16 nPos, sal_Bool bDrawText, sal_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 = sal_True;
            mpImplData->mpVirDev->EnableRTL( IsRTLEnabled() );
			UserDrawEvent aODEvt( mpImplData->mpVirDev, Rectangle( Point(), aTextRectSize ), pItem->mnId );
			UserDraw( aODEvt );
            mpImplData->mpVirDev->EnableRTL( sal_False );
			mbInUserDraw = sal_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) )
            {
                sal_uInt16 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,
				   sal_uInt16 nPercent1, sal_uInt16 nPercent2, sal_uInt16 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 );
        }
        sal_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
	sal_uInt16 nPerc1 = nPercent1 / nPercentCount;
	sal_uInt16 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( sal_Bool bPaint,
								  sal_uInt16 nPercent1, sal_uInt16 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);
	sal_uInt16 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;
    sal_Bool bNativeOK = sal_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 ) ) != sal_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();
			sal_uInt16 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();

	sal_uInt16 nItemCount = (sal_uInt16)mpItemList->Count();

	if ( mbProgressMode )
		ImplDrawProgress( sal_True, 0, mnPercent );
	else
	{
		// Text zeichen
		if ( !mbVisibleItems || (GetStyle() & WB_RIGHT) )
			ImplDrawText( sal_False, 0 );

		// Items zeichnen
		if ( mbVisibleItems )
		{
			// Items zeichnen
			for ( sal_uInt16 i = 0; i < nItemCount; i++ )
				ImplDrawItem( sal_False, i, sal_True, sal_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() - ImplGetSVData()->maNWFData.mnStatusBarLowerRightOffset;
	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 = sal_True;

	if ( mbProgressMode )
		ImplCalcProgressRect();

	Invalidate();
}

// -----------------------------------------------------------------------

void StatusBar::RequestHelp( const HelpEvent& rHEvt )
{
	// no keyboard help in status bar
	if( rHEvt.KeyboardActivated() )
		return;

	sal_uInt16 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 );
            rtl::OString aHelpId( GetHelpId( nItemId ) );

            if ( aCommand.Len() || aHelpId.getLength() )
            {
                // Wenn eine Hilfe existiert, dann ausloesen
                Help* pHelp = Application::GetHelp();
                if ( pHelp )
                {
                    if ( aCommand.Len() )
                        pHelp->Start( aCommand, this );
                    else if ( aHelpId.getLength() )
                        pHelp->Start( rtl::OStringToOUString( aHelpId, RTL_TEXTENCODING_UTF8 ), 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 = sal_True;
		ImplInitSettings( sal_True, sal_False, sal_False );
		Invalidate();
	}
	else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
	{
		ImplInitSettings( sal_False, sal_True, sal_False );
		Invalidate();
	}
	else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
	{
		ImplInitSettings( sal_False, sal_False, sal_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 = sal_True;
		ImplInitSettings( sal_True, sal_True, sal_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( sal_uInt16 nItemId, sal_uLong nWidth,
							StatusBarItemBits nBits,
							long nOffset, sal_uInt16 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->mpUserData		= 0;
	pItem->mbVisible		= sal_True;

	// Item in die Liste einfuegen
	mpItemList->Insert( pItem, nPos );

	mbFormat = sal_True;
	if ( ImplIsItemUpdate() )
		Invalidate();

	ImplCallEventListeners( VCLEVENT_STATUSBAR_ITEMADDED, (void*) sal_IntPtr(nItemId) );
}

// -----------------------------------------------------------------------

void StatusBar::RemoveItem( sal_uInt16 nItemId )
{
	sal_uInt16 nPos = GetItemPos( nItemId );
	if ( nPos != STATUSBAR_ITEM_NOTFOUND )
	{
		ImplStatusItem* pItem = mpItemList->Remove( nPos );
		delete pItem;

		mbFormat = sal_True;
		if ( ImplIsItemUpdate() )
			Invalidate();

		ImplCallEventListeners( VCLEVENT_STATUSBAR_ITEMREMOVED, (void*) sal_IntPtr(nItemId) );
	}
}

// -----------------------------------------------------------------------

void StatusBar::ShowItem( sal_uInt16 nItemId )
{
	sal_uInt16 nPos = GetItemPos( nItemId );

	if ( nPos != STATUSBAR_ITEM_NOTFOUND )
	{
		ImplStatusItem* pItem = mpItemList->GetObject( nPos );
		if ( !pItem->mbVisible )
		{
			pItem->mbVisible = sal_True;

			mbFormat = sal_True;
			if ( ImplIsItemUpdate() )
				Invalidate();

			ImplCallEventListeners( VCLEVENT_STATUSBAR_SHOWITEM, (void*) sal_IntPtr(nItemId) );
		}
	}
}

// -----------------------------------------------------------------------

void StatusBar::HideItem( sal_uInt16 nItemId )
{
	sal_uInt16 nPos = GetItemPos( nItemId );

	if ( nPos != STATUSBAR_ITEM_NOTFOUND )
	{
		ImplStatusItem* pItem = mpItemList->GetObject( nPos );
		if ( pItem->mbVisible )
		{
			pItem->mbVisible = sal_False;

			mbFormat = sal_True;
			if ( ImplIsItemUpdate() )
				Invalidate();

			ImplCallEventListeners( VCLEVENT_STATUSBAR_HIDEITEM, (void*) sal_IntPtr(nItemId) );
		}
	}
}

// -----------------------------------------------------------------------

sal_Bool StatusBar::IsItemVisible( sal_uInt16 nItemId ) const
{
	sal_uInt16 nPos = GetItemPos( nItemId );

	if ( nPos != STATUSBAR_ITEM_NOTFOUND )
		return mpItemList->GetObject( nPos )->mbVisible;
	else
		return sal_False;
}

// -----------------------------------------------------------------------

void StatusBar::ShowItems()
{
	if ( !mbVisibleItems )
	{
		mbVisibleItems = sal_True;
		if ( !mbProgressMode )
			Invalidate();

		ImplCallEventListeners( VCLEVENT_STATUSBAR_SHOWALLITEMS );
	}
}

// -----------------------------------------------------------------------

void StatusBar::HideItems()
{
	if ( mbVisibleItems )
	{
		mbVisibleItems = sal_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
	sal_uLong i = 0;
	pItem = rStatusBar.mpItemList->GetObject( i );
	while ( pItem )
	{
		mpItemList->Insert( new ImplStatusItem( *pItem ), LIST_APPEND );
		i++;
		pItem = rStatusBar.mpItemList->GetObject( i );
	}

	mbFormat = sal_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 = sal_True;
	if ( ImplIsItemUpdate() )
		Invalidate();

	ImplCallEventListeners( VCLEVENT_STATUSBAR_ALLITEMSREMOVED );
}

// -----------------------------------------------------------------------

sal_uInt16 StatusBar::GetItemCount() const
{
	return (sal_uInt16)mpItemList->Count();
}

// -----------------------------------------------------------------------

sal_uInt16 StatusBar::GetItemId( sal_uInt16 nPos ) const
{
	ImplStatusItem* pItem = mpItemList->GetObject( nPos );
	if ( pItem )
		return pItem->mnId;
	else
		return 0;
}

// -----------------------------------------------------------------------

sal_uInt16 StatusBar::GetItemPos( sal_uInt16 nItemId ) const
{
	ImplStatusItem* pItem = mpItemList->First();
	while ( pItem )
	{
		if ( pItem->mnId == nItemId )
			return (sal_uInt16)mpItemList->GetCurPos();

		pItem = mpItemList->Next();
	}

	return STATUSBAR_ITEM_NOTFOUND;
}

// -----------------------------------------------------------------------

sal_uInt16 StatusBar::GetItemId( const Point& rPos ) const
{
	if ( AreItemsVisible() && !mbFormat )
	{
		sal_uInt16 nItemCount = GetItemCount();
		sal_uInt16 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( sal_uInt16 nItemId ) const
{
	Rectangle aRect;

	if ( AreItemsVisible() && !mbFormat )
	{
		sal_uInt16 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( sal_uInt16 nItemId ) const
{
	if ( !mbFormat )
	{
		sal_uInt16 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();
}

// -----------------------------------------------------------------------

sal_uLong StatusBar::GetItemWidth( sal_uInt16 nItemId ) const
{
	sal_uInt16 nPos = GetItemPos( nItemId );

	if ( nPos != STATUSBAR_ITEM_NOTFOUND )
		return mpItemList->GetObject( nPos )->mnWidth;
	else
		return 0;
}

// -----------------------------------------------------------------------

StatusBarItemBits StatusBar::GetItemBits( sal_uInt16 nItemId ) const
{
	sal_uInt16 nPos = GetItemPos( nItemId );

	if ( nPos != STATUSBAR_ITEM_NOTFOUND )
		return mpItemList->GetObject( nPos )->mnBits;
	else
		return 0;
}

// -----------------------------------------------------------------------

long StatusBar::GetItemOffset( sal_uInt16 nItemId ) const
{
	sal_uInt16 nPos = GetItemPos( nItemId );

	if ( nPos != STATUSBAR_ITEM_NOTFOUND )
		return mpItemList->GetObject( nPos )->mnOffset;
	else
		return 0;
}

// -----------------------------------------------------------------------

void StatusBar::SetItemText( sal_uInt16 nItemId, const XubString& rText )
{
	sal_uInt16 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( sal_True, nPos, sal_True, sal_False );
				Flush();
			}
		}
	}
}

// -----------------------------------------------------------------------

const XubString& StatusBar::GetItemText( sal_uInt16 nItemId ) const
{
	sal_uInt16 nPos = GetItemPos( nItemId );

	if ( nPos != STATUSBAR_ITEM_NOTFOUND )
		return mpItemList->GetObject( nPos )->maText;
	else
		return ImplGetSVEmptyStr();
}

// -----------------------------------------------------------------------

void StatusBar::SetItemCommand( sal_uInt16 nItemId, const XubString& rCommand )
{
	sal_uInt16 nPos = GetItemPos( nItemId );

	if ( nPos != STATUSBAR_ITEM_NOTFOUND )
	{
		ImplStatusItem* pItem = mpItemList->GetObject( nPos );

		if ( pItem->maCommand != rCommand )
			pItem->maCommand = rCommand;
	}
}

// -----------------------------------------------------------------------

const XubString& StatusBar::GetItemCommand( sal_uInt16 nItemId )
{
	sal_uInt16 nPos = GetItemPos( nItemId );

	if ( nPos != STATUSBAR_ITEM_NOTFOUND )
		return mpItemList->GetObject( nPos )->maCommand;
	else
		return ImplGetSVEmptyStr();
}

// -----------------------------------------------------------------------

void StatusBar::SetItemData( sal_uInt16 nItemId, void* pNewData )
{
	sal_uInt16 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( sal_True, nPos, sal_False, sal_False );
			Flush();
		}
	}
}

void StatusBar::RedrawItem( sal_uInt16 nItemId )
{
    if ( mbFormat )
        return;

    sal_uInt16 nPos = GetItemPos( nItemId );
    if ( nPos == STATUSBAR_ITEM_NOTFOUND )
        return;

    ImplStatusItem* pItem = mpItemList->GetObject( nPos );
    if ( pItem && (pItem->mnBits & SIB_USERDRAW) &&
         pItem->mbVisible && ImplIsItemUpdate() )
    {
        Update();
        ImplDrawItem( sal_True, nPos, sal_False, sal_False );
        Flush();
    }
}

// -----------------------------------------------------------------------

void* StatusBar::GetItemData( sal_uInt16 nItemId ) const
{
	sal_uInt16 nPos = GetItemPos( nItemId );

	if ( nPos != STATUSBAR_ITEM_NOTFOUND )
		return mpItemList->GetObject( nPos )->mpUserData;
	else
		return NULL;
}

// -----------------------------------------------------------------------

void StatusBar::SetHelpText( sal_uInt16 nItemId, const XubString& rText )
{
	sal_uInt16 nPos = GetItemPos( nItemId );

	if ( nPos != STATUSBAR_ITEM_NOTFOUND )
		mpItemList->GetObject( nPos )->maHelpText = rText;
}

// -----------------------------------------------------------------------

const XubString& StatusBar::GetHelpText( sal_uInt16 nItemId ) const
{
	sal_uInt16 nPos = GetItemPos( nItemId );

	if ( nPos != STATUSBAR_ITEM_NOTFOUND )
	{
		ImplStatusItem* pItem = mpItemList->GetObject( nPos );
		if ( !pItem->maHelpText.Len() && ( pItem->maHelpId.getLength() || 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->maHelpId.getLength() )
                    pItem->maHelpText = pHelp->GetHelpText( rtl::OStringToOUString( pItem->maHelpId, RTL_TEXTENCODING_UTF8 ), this );
            }
		}

		return pItem->maHelpText;
	}
	else
		return ImplGetSVEmptyStr();
}

// -----------------------------------------------------------------------

void StatusBar::SetQuickHelpText( sal_uInt16 nItemId, const XubString& rText )
{
	sal_uInt16 nPos = GetItemPos( nItemId );

	if ( nPos != STATUSBAR_ITEM_NOTFOUND )
		mpItemList->GetObject( nPos )->maQuickHelpText = rText;
}

// -----------------------------------------------------------------------

const XubString& StatusBar::GetQuickHelpText( sal_uInt16 nItemId ) const
{
	sal_uInt16 nPos = GetItemPos( nItemId );

	if ( nPos != STATUSBAR_ITEM_NOTFOUND )
	{
		ImplStatusItem* pItem = mpItemList->GetObject( nPos );
		return pItem->maQuickHelpText;
	}
	else
		return ImplGetSVEmptyStr();
}

// -----------------------------------------------------------------------

void StatusBar::SetHelpId( sal_uInt16 nItemId, const rtl::OString& rHelpId )
{
	sal_uInt16 nPos = GetItemPos( nItemId );

	if ( nPos != STATUSBAR_ITEM_NOTFOUND )
		mpItemList->GetObject( nPos )->maHelpId = rHelpId;
}

// -----------------------------------------------------------------------

rtl::OString StatusBar::GetHelpId( sal_uInt16 nItemId ) const
{
	sal_uInt16 nPos = GetItemPos( nItemId );

	rtl::OString aRet;
	if ( nPos != STATUSBAR_ITEM_NOTFOUND )
    {
		ImplStatusItem* pItem = mpItemList->GetObject( nPos );
        if ( pItem->maHelpId.getLength() )
            aRet = pItem->maHelpId;
        else
            aRet = ::rtl::OUStringToOString( pItem->maCommand, RTL_TEXTENCODING_UTF8 );        
    }

	return aRet;
}

// -----------------------------------------------------------------------

void StatusBar::ImplCalcBorder( )
{
	mnCalcHeight = mnDY;
    // subtract border
    if( IsTopBorder() )
    {
        mnCalcHeight -= 2;
        mnTextY += 2;
        mnItemY += 2;
    }
	if ( IsBottomBorder() )
		mnCalcHeight -= 2;
	mbFormat = sal_True;
	Invalidate();
}

void StatusBar::SetBottomBorder( sal_Bool bBottomBorder )
{
	if ( mbBottomBorder != bBottomBorder )
	{
		mbBottomBorder = bBottomBorder;
        ImplCalcBorder();
	}
}

void StatusBar::SetTopBorder( sal_Bool bTopBorder )
{
    if ( mpImplData->mbTopBorder != static_cast<bool>(bTopBorder) )
    {
	    mpImplData->mbTopBorder = static_cast<bool>(bTopBorder);
        ImplCalcBorder();
    }
}

sal_Bool StatusBar::IsTopBorder() const
{
    return mpImplData->mbTopBorder;
}

// -----------------------------------------------------------------------

void StatusBar::StartProgressMode( const XubString& rText )
{
	DBG_ASSERT( !mbProgressMode, "StatusBar::StartProgressMode(): progress mode is active" );

	mbProgressMode	= sal_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( sal_uInt16 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( sal_False, mnPercent, nNewPercent );
		Flush();
	}
	mnPercent = nNewPercent;
}

// -----------------------------------------------------------------------

void StatusBar::EndProgressMode()
{
	DBG_ASSERT( mbProgressMode, "StatusBar::EndProgressMode(): no progress mode" );

	mbProgressMode = sal_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( sal_True, nOldTextWidth );
			Flush();
		}
	}
	else if ( mbProgressMode )
	{
		maPrgsTxt = rText;
		if ( IsReallyVisible() )
		{
			Invalidate();
			Update();
			Flush();
		}
	}
	else
		Window::SetText( rText );
}

// -----------------------------------------------------------------------

Size StatusBar::CalcWindowSizePixel() const
{
	sal_uLong	i = 0;
	sal_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( sal_uInt16 nItemId, const XubString& rName )
{
	sal_uInt16 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( sal_uInt16 nItemId ) const
{
	sal_uInt16 nPos = GetItemPos( nItemId );

	if ( nPos != STATUSBAR_ITEM_NOTFOUND )
		return mpItemList->GetObject( nPos )->maAccessibleName;
	else
		return ImplGetSVEmptyStr();
}

// -----------------------------------------------------------------------