xref: /aoo42x/main/vcl/source/window/status.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_vcl.hxx"
30 
31 #include <tools/list.hxx>
32 #include <tools/debug.hxx>
33 #include <tools/rc.h>
34 
35 #include <vcl/event.hxx>
36 #include <vcl/decoview.hxx>
37 #include <vcl/svapp.hxx>
38 #include <vcl/help.hxx>
39 #include <vcl/status.hxx>
40 #include <vcl/virdev.hxx>
41 
42 #include <svdata.hxx>
43 #include <window.h>
44 
45 // =======================================================================
46 
47 #define STATUSBAR_OFFSET_X		STATUSBAR_OFFSET
48 #define STATUSBAR_OFFSET_Y		2
49 #define STATUSBAR_OFFSET_TEXTY	3
50 
51 #define STATUSBAR_PRGS_OFFSET	3
52 #define STATUSBAR_PRGS_COUNT	100
53 #define STATUSBAR_PRGS_MIN		5
54 
55 // -----------------------------------------------------------------------
56 
57 class StatusBar::ImplData
58 {
59 public:
60     ImplData();
61     ~ImplData();
62 
63     VirtualDevice*		mpVirDev;
64     long                mnItemBorderWidth;
65     bool                mbTopBorder:1;
66     bool                mbDrawItemFrames:1;
67 };
68 
69 StatusBar::ImplData::ImplData()
70 {
71     mpVirDev = NULL;
72     mbTopBorder = false;
73     mbDrawItemFrames = false;
74     mnItemBorderWidth = 0;
75 }
76 
77 StatusBar::ImplData::~ImplData()
78 {
79 }
80 
81 struct ImplStatusItem
82 {
83 	sal_uInt16				mnId;
84 	StatusBarItemBits	mnBits;
85 	long				mnWidth;
86 	long				mnOffset;
87 	long				mnExtraWidth;
88 	long				mnX;
89 	XubString			maText;
90 	XubString			maHelpText;
91 	XubString			maQuickHelpText;
92 	rtl::OString		maHelpId;
93 	void*				mpUserData;
94 	sal_Bool				mbVisible;
95 	XubString			maAccessibleName;
96     XubString           maCommand;
97 };
98 
99 DECLARE_LIST( ImplStatusItemList, ImplStatusItem* )
100 
101 // =======================================================================
102 
103 inline long ImplCalcProgessWidth( sal_uInt16 nMax, long nSize )
104 {
105 	return ((nMax*(nSize+(nSize/2)))-(nSize/2)+(STATUSBAR_PRGS_OFFSET*2));
106 }
107 
108 // -----------------------------------------------------------------------
109 
110 static Point ImplGetItemTextPos( const Size& rRectSize, const Size& rTextSize,
111 								 sal_uInt16 nStyle )
112 {
113 	long nX;
114 	long nY;
115     long delta = (rTextSize.Height()/4) + 1;
116     if( delta + rTextSize.Width() > rRectSize.Width() )
117         delta = 0;
118 
119 	if ( nStyle & SIB_LEFT )
120 		nX = delta;
121 	else if ( nStyle & SIB_RIGHT )
122 		nX = rRectSize.Width()-rTextSize.Width()-delta;
123 	else // SIB_CENTER
124 		nX = (rRectSize.Width()-rTextSize.Width())/2;
125 	nY = (rRectSize.Height()-rTextSize.Height())/2 + 1;
126 	return Point( nX, nY );
127 }
128 
129 // -----------------------------------------------------------------------
130 
131 sal_Bool StatusBar::ImplIsItemUpdate()
132 {
133 	if ( !mbProgressMode && mbVisibleItems && IsReallyVisible() && IsUpdateMode() )
134 		return sal_True;
135 	else
136 		return sal_False;
137 }
138 
139 // -----------------------------------------------------------------------
140 
141 void StatusBar::ImplInit( Window* pParent, WinBits nStyle )
142 {
143     mpImplData = new ImplData;
144 
145 	// Default ist RightAlign
146 	if ( !(nStyle & (WB_LEFT | WB_RIGHT)) )
147 		nStyle |= WB_RIGHT;
148 
149 	Window::ImplInit( pParent, nStyle & ~WB_BORDER, NULL );
150 
151 	// WinBits merken
152 	mpItemList		= new ImplStatusItemList;
153 	mpImplData->mpVirDev		= new VirtualDevice( *this );
154 	mnCurItemId 	= 0;
155 	mbFormat		= sal_True;
156 	mbVisibleItems	= sal_True;
157 	mbProgressMode	= sal_False;
158 	mbInUserDraw	= sal_False;
159 	mbBottomBorder	= sal_False;
160     mnItemsWidth    = STATUSBAR_OFFSET_X;
161 	mnDX			= 0;
162 	mnDY			= 0;
163 	mnCalcHeight	= 0;
164 	mnItemY 		= STATUSBAR_OFFSET_Y;
165 	mnTextY 		= STATUSBAR_OFFSET_TEXTY;
166 
167 	ImplInitSettings( sal_True, sal_True, sal_True );
168 	SetLineColor();
169 
170     SetOutputSizePixel( CalcWindowSizePixel() );
171 }
172 
173 // -----------------------------------------------------------------------
174 
175 StatusBar::StatusBar( Window* pParent, WinBits nStyle ) :
176 	Window( WINDOW_STATUSBAR )
177 {
178 	ImplInit( pParent, nStyle );
179 }
180 
181 // -----------------------------------------------------------------------
182 
183 StatusBar::StatusBar( Window* pParent, const ResId& rResId ) :
184 	Window( WINDOW_STATUSBAR )
185 {
186 	rResId.SetRT( RSC_STATUSBAR );
187 	WinBits nStyle = ImplInitRes( rResId );
188 	ImplInit( pParent, nStyle );
189 	ImplLoadRes( rResId );
190 
191 	if ( !(nStyle & WB_HIDE) )
192 		Show();
193 }
194 
195 // -----------------------------------------------------------------------
196 
197 StatusBar::~StatusBar()
198 {
199 	// Alle Items loeschen
200 	ImplStatusItem* pItem = mpItemList->First();
201 	while ( pItem )
202 	{
203 		delete pItem;
204 		pItem = mpItemList->Next();
205 	}
206 
207 	delete mpItemList;
208 
209 	// VirtualDevice loeschen
210 	delete mpImplData->mpVirDev;
211 
212     delete mpImplData;
213 }
214 
215 // -----------------------------------------------------------------------
216 
217 void StatusBar::ImplInitSettings( sal_Bool bFont,
218 								  sal_Bool bForeground, sal_Bool bBackground )
219 {
220 	const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
221 
222 	if ( bFont )
223 	{
224 		Font aFont = rStyleSettings.GetToolFont();
225 		if ( IsControlFont() )
226 			aFont.Merge( GetControlFont() );
227 		SetZoomedPointFont( aFont );
228 	}
229 
230 	if ( bForeground || bFont )
231 	{
232 		Color aColor;
233 		if ( IsControlForeground() )
234 			aColor = GetControlForeground();
235 		else if ( GetStyle() & WB_3DLOOK )
236 			aColor = rStyleSettings.GetButtonTextColor();
237 		else
238 			aColor = rStyleSettings.GetWindowTextColor();
239 		SetTextColor( aColor );
240 		SetTextFillColor();
241 
242 		mpImplData->mpVirDev->SetFont( GetFont() );
243 		mpImplData->mpVirDev->SetTextColor( GetTextColor() );
244 		mpImplData->mpVirDev->SetTextAlign( GetTextAlign() );
245 		mpImplData->mpVirDev->SetTextFillColor();
246 	}
247 
248 	if ( bBackground )
249 	{
250 		Color aColor;
251 		if ( IsControlBackground() )
252 			aColor = GetControlBackground();
253 		else if ( GetStyle() & WB_3DLOOK )
254 			aColor = rStyleSettings.GetFaceColor();
255 		else
256 			aColor = rStyleSettings.GetWindowColor();
257         SetBackground( aColor );
258         mpImplData->mpVirDev->SetBackground( GetBackground() );
259 
260         // NWF background
261         if( ! IsControlBackground() &&
262               IsNativeControlSupported( CTRL_WINDOW_BACKGROUND, PART_BACKGROUND_WINDOW ) )
263         {
264             ImplGetWindowImpl()->mnNativeBackground = PART_BACKGROUND_WINDOW;
265             EnableChildTransparentMode( sal_True );
266         }
267 	}
268 }
269 
270 // -----------------------------------------------------------------------
271 
272 void StatusBar::ImplFormat()
273 {
274 	ImplStatusItem* pItem;
275 	long			nExtraWidth;
276 	long			nExtraWidth2;
277 	long			nX;
278 	sal_uInt16			nAutoSizeItems = 0;
279 
280 	// Breiten zusammenrechnen
281 	mnItemsWidth = STATUSBAR_OFFSET_X;
282 	long nOffset = 0;
283 	pItem = mpItemList->First();
284 	while ( pItem )
285 	{
286 		if ( pItem->mbVisible )
287 		{
288 			if ( pItem->mnBits & SIB_AUTOSIZE )
289 				nAutoSizeItems++;
290 
291 			mnItemsWidth += pItem->mnWidth + nOffset;
292 			nOffset = pItem->mnOffset;
293 		}
294 
295 		pItem = mpItemList->Next();
296 	}
297 
298 	if ( GetStyle() & WB_RIGHT )
299 	{
300 		// Bei rechtsbuendiger Ausrichtung wird kein AutoSize ausgewertet,
301 		// da wir links den Text anzeigen, der mit SetText gesetzt wird
302 		nX				= mnDX - mnItemsWidth;
303 		nExtraWidth 	= 0;
304 		nExtraWidth2	= 0;
305 	}
306 	else
307 	{
308 		mnItemsWidth += STATUSBAR_OFFSET_X;
309 
310 		// Bei linksbuendiger Ausrichtung muessen wir gegebenenfalls noch
311 		// AutoSize auswerten
312 		if ( nAutoSizeItems && (mnDX > (mnItemsWidth - STATUSBAR_OFFSET)) )
313 		{
314 			nExtraWidth  = (mnDX - mnItemsWidth - 1) / nAutoSizeItems;
315 			nExtraWidth2 = (mnDX - mnItemsWidth - 1) % nAutoSizeItems;
316 		}
317 		else
318 		{
319 			nExtraWidth  = 0;
320 			nExtraWidth2 = 0;
321 		}
322 		nX = STATUSBAR_OFFSET_X;
323 		if( ImplHasMirroredGraphics() && IsRTLEnabled() )
324 		    nX += ImplGetSVData()->maNWFData.mnStatusBarLowerRightOffset;
325 	}
326 
327 	pItem = mpItemList->First();
328 	while ( pItem )
329 	{
330 		if ( pItem->mbVisible )
331 		{
332 			if ( pItem->mnBits & SIB_AUTOSIZE )
333 			{
334 				pItem->mnExtraWidth = nExtraWidth;
335 				if ( nExtraWidth2 )
336 				{
337 					pItem->mnExtraWidth++;
338 					nExtraWidth2--;
339 				}
340 			}
341 			else
342 				pItem->mnExtraWidth = 0;
343 
344 			pItem->mnX = nX;
345 			nX += pItem->mnWidth + pItem->mnExtraWidth + pItem->mnOffset;
346 		}
347 
348 		pItem = mpItemList->Next();
349 	}
350 
351 	mbFormat = sal_False;
352 }
353 
354 // -----------------------------------------------------------------------
355 
356 Rectangle StatusBar::ImplGetItemRectPos( sal_uInt16 nPos ) const
357 {
358     Rectangle		aRect;
359     ImplStatusItem* pItem;
360     pItem = mpItemList->GetObject( nPos );
361     if ( pItem )
362     {
363         if ( pItem->mbVisible )
364         {
365             aRect.Left()   = pItem->mnX;
366             aRect.Right()  = aRect.Left() + pItem->mnWidth + pItem->mnExtraWidth;
367             aRect.Top()    = mnItemY;
368             aRect.Bottom() = mnCalcHeight - STATUSBAR_OFFSET_Y;
369             if( IsTopBorder() )
370                 aRect.Bottom()+=2;
371         }
372     }
373 
374     return aRect;
375 }
376 
377 // -----------------------------------------------------------------------
378 
379 sal_uInt16 StatusBar::ImplGetFirstVisiblePos() const
380 {
381     ImplStatusItem* pItem;
382 
383     for( sal_uInt16 nPos = 0; nPos < mpItemList->Count(); nPos++ )
384     {
385         pItem = mpItemList->GetObject( nPos );
386         if ( pItem )
387         {
388             if ( pItem->mbVisible )
389                 return nPos;
390         }
391     }
392 
393     return ~0;
394 }
395 
396 // -----------------------------------------------------------------------
397 
398 void StatusBar::ImplDrawText( sal_Bool bOffScreen, long nOldTextWidth )
399 {
400 	// Das ueberschreiben der Item-Box verhindern
401 	Rectangle aTextRect;
402 	aTextRect.Left() = STATUSBAR_OFFSET_X+1;
403 	aTextRect.Top()  = mnTextY;
404 	if ( mbVisibleItems && (GetStyle() & WB_RIGHT) )
405 		aTextRect.Right() = mnDX - mnItemsWidth - 1;
406 	else
407 		aTextRect.Right() = mnDX - 1;
408 	if ( aTextRect.Right() > aTextRect.Left() )
409 	{
410 		// Position ermitteln
411 		XubString aStr = GetText();
412 		sal_uInt16 nPos = aStr.Search( _LF );
413 		if ( nPos != STRING_NOTFOUND )
414 			aStr.Erase( nPos );
415 
416 		aTextRect.Bottom() = aTextRect.Top()+GetTextHeight()+1;
417 
418 		if ( bOffScreen )
419 		{
420 			long nMaxWidth = Max( nOldTextWidth, GetTextWidth( aStr ) );
421 			Size aVirDevSize( nMaxWidth, aTextRect.GetHeight() );
422 			mpImplData->mpVirDev->SetOutputSizePixel( aVirDevSize );
423 			Rectangle aTempRect = aTextRect;
424 			aTempRect.SetPos( Point( 0, 0 ) );
425 			mpImplData->mpVirDev->DrawText( aTempRect, aStr, TEXT_DRAW_LEFT | TEXT_DRAW_TOP | TEXT_DRAW_CLIP | TEXT_DRAW_ENDELLIPSIS );
426 			DrawOutDev( aTextRect.TopLeft(), aVirDevSize, Point(), aVirDevSize, *mpImplData->mpVirDev );
427 		}
428 		else
429 			DrawText( aTextRect, aStr, TEXT_DRAW_LEFT | TEXT_DRAW_TOP | TEXT_DRAW_CLIP | TEXT_DRAW_ENDELLIPSIS );
430 	}
431 }
432 
433 // -----------------------------------------------------------------------
434 
435 void StatusBar::ImplDrawItem( sal_Bool bOffScreen, sal_uInt16 nPos, sal_Bool bDrawText, sal_Bool bDrawFrame )
436 {
437 	Rectangle aRect = ImplGetItemRectPos( nPos );
438 
439 	if ( aRect.IsEmpty() )
440 		return;
441 
442 	// Ausgabebereich berechnen
443 	ImplStatusItem* 	pItem = mpItemList->GetObject( nPos );
444     long nW = mpImplData->mnItemBorderWidth + 1;
445 	Rectangle			aTextRect( aRect.Left()+nW, aRect.Top()+nW,
446 								   aRect.Right()-nW, aRect.Bottom()-nW );
447 	Size				aTextRectSize( aTextRect.GetSize() );
448 
449 	if ( bOffScreen )
450 		mpImplData->mpVirDev->SetOutputSizePixel( aTextRectSize );
451 	else
452 	{
453 		Region aRegion( aTextRect );
454 		SetClipRegion( aRegion );
455 	}
456 
457 	// Text ausgeben
458 	if ( bDrawText )
459 	{
460 		Size	aTextSize( GetTextWidth( pItem->maText ), GetTextHeight() );
461 		Point	aTextPos = ImplGetItemTextPos( aTextRectSize, aTextSize, pItem->mnBits );
462 		if ( bOffScreen )
463 			mpImplData->mpVirDev->DrawText( aTextPos, pItem->maText );
464 		else
465 		{
466 			aTextPos.X() += aTextRect.Left();
467 			aTextPos.Y() += aTextRect.Top();
468 			DrawText( aTextPos, pItem->maText );
469 		}
470 	}
471 
472 	// Gegebenenfalls auch DrawItem aufrufen
473 	if ( pItem->mnBits & SIB_USERDRAW )
474 	{
475 		if ( bOffScreen )
476 		{
477 			mbInUserDraw = sal_True;
478             mpImplData->mpVirDev->EnableRTL( IsRTLEnabled() );
479 			UserDrawEvent aODEvt( mpImplData->mpVirDev, Rectangle( Point(), aTextRectSize ), pItem->mnId );
480 			UserDraw( aODEvt );
481             mpImplData->mpVirDev->EnableRTL( sal_False );
482 			mbInUserDraw = sal_False;
483 		}
484 		else
485 		{
486 			UserDrawEvent aODEvt( this, aTextRect, pItem->mnId );
487 			UserDraw( aODEvt );
488 		}
489 	}
490 
491 	if ( bOffScreen )
492 		DrawOutDev( aTextRect.TopLeft(), aTextRectSize, Point(), aTextRectSize, *mpImplData->mpVirDev );
493 	else
494 		SetClipRegion();
495 
496 	// Frame ausgeben
497 	if ( bDrawFrame )
498     {
499         if( mpImplData->mbDrawItemFrames )
500         {
501             if( !(pItem->mnBits & SIB_FLAT) )
502             {
503                 sal_uInt16 nStyle;
504 
505                 if ( pItem->mnBits & SIB_IN )
506                     nStyle = FRAME_DRAW_IN;
507                 else
508                     nStyle = FRAME_DRAW_OUT;
509 
510                 DecorationView aDecoView( this );
511                 aDecoView.DrawFrame( aRect, nStyle );
512             }
513         }
514         else if( nPos != ImplGetFirstVisiblePos() )
515         {
516             // draw separator
517             Point aFrom( aRect.TopLeft() );
518             aFrom.X()--;
519             aFrom.Y()++;
520             Point aTo( aRect.BottomLeft() );
521             aTo.X()--;
522             aTo.Y()--;
523 
524             DecorationView aDecoView( this );
525             aDecoView.DrawSeparator( aFrom, aTo );
526         }
527     }
528 
529 	if ( !ImplIsRecordLayout() )
530 		ImplCallEventListeners( VCLEVENT_STATUSBAR_DRAWITEM, (void*) sal_IntPtr(pItem->mnId) );
531 }
532 
533 // -----------------------------------------------------------------------
534 
535 void DrawProgress( Window* pWindow, const Point& rPos,
536 				   long nOffset, long nPrgsWidth, long nPrgsHeight,
537 				   sal_uInt16 nPercent1, sal_uInt16 nPercent2, sal_uInt16 nPercentCount,
538                    const Rectangle& rFramePosSize
539                    )
540 {
541     if( pWindow->IsNativeControlSupported( CTRL_PROGRESS, PART_ENTIRE_CONTROL ) )
542     {
543         bool bNeedErase = ImplGetSVData()->maNWFData.mbProgressNeedsErase;
544 
545         long nFullWidth = (nPrgsWidth + nOffset) * (10000 / nPercentCount);
546         long nPerc = (nPercent2 > 10000) ? 10000 : nPercent2;
547         ImplControlValue aValue( nFullWidth * (long)nPerc / 10000 );
548         Rectangle aDrawRect( rPos, Size( nFullWidth, nPrgsHeight ) );
549         Rectangle aControlRegion( aDrawRect );
550         if( bNeedErase )
551         {
552             Window* pEraseWindow = pWindow;
553             while( pEraseWindow->IsPaintTransparent()                         &&
554                    ! pEraseWindow->ImplGetWindowImpl()->mbFrame )
555             {
556                 pEraseWindow = pEraseWindow->ImplGetWindowImpl()->mpParent;
557             }
558             if( pEraseWindow == pWindow )
559                 // restore background of pWindow
560                 pEraseWindow->Erase( rFramePosSize );
561             else
562             {
563                 // restore transparent background
564                 Point aTL( pWindow->OutputToAbsoluteScreenPixel( rFramePosSize.TopLeft() ) );
565                 aTL = pEraseWindow->AbsoluteScreenToOutputPixel( aTL );
566                 Rectangle aRect( aTL, rFramePosSize.GetSize() );
567                 pEraseWindow->Invalidate( aRect, INVALIDATE_NOCHILDREN     |
568                                                  INVALIDATE_NOCLIPCHILDREN |
569                                                  INVALIDATE_TRANSPARENT );
570                 pEraseWindow->Update();
571             }
572             pWindow->Push( PUSH_CLIPREGION );
573             pWindow->IntersectClipRegion( rFramePosSize );
574         }
575         sal_Bool bNativeOK = pWindow->DrawNativeControl( CTRL_PROGRESS, PART_ENTIRE_CONTROL, aControlRegion,
576                                                      CTRL_STATE_ENABLED, aValue, rtl::OUString() );
577         if( bNeedErase )
578             pWindow->Pop();
579         if( bNativeOK )
580         {
581             pWindow->Flush();
582             return;
583         }
584     }
585 
586 	// Werte vorberechnen
587 	sal_uInt16 nPerc1 = nPercent1 / nPercentCount;
588 	sal_uInt16 nPerc2 = nPercent2 / nPercentCount;
589 
590 	if ( nPerc1 > nPerc2 )
591 	{
592 		// Support progress that can also decrease
593 
594 		// Rechteck berechnen
595 		long		nDX = nPrgsWidth + nOffset;
596 		long		nLeft = rPos.X()+((nPerc1-1)*nDX);
597 		Rectangle	aRect( nLeft, rPos.Y(), nLeft+nPrgsWidth, rPos.Y()+nPrgsHeight );
598 
599 		do
600 		{
601 			pWindow->Erase( aRect );
602 			aRect.Left()  -= nDX;
603 			aRect.Right() -= nDX;
604 			nPerc1--;
605 		}
606 		while ( nPerc1 > nPerc2 );
607 
608 		pWindow->Flush();
609 	}
610 	else if ( nPerc1 < nPerc2 )
611 	{
612 		// Percent-Rechtecke malen
613 		// Wenn Percent2 ueber 100%, Werte anpassen
614 		if ( nPercent2 > 10000 )
615 		{
616 			nPerc2 = 10000 / nPercentCount;
617 			if ( nPerc1 >= nPerc2 )
618 				nPerc1 = nPerc2-1;
619 		}
620 
621 		// Rechteck berechnen
622 		long		nDX = nPrgsWidth + nOffset;
623 		long		nLeft = rPos.X()+(nPerc1*nDX);
624 		Rectangle	aRect( nLeft, rPos.Y(), nLeft+nPrgsWidth, rPos.Y()+nPrgsHeight );
625 
626 		do
627 		{
628 			pWindow->DrawRect( aRect );
629 			aRect.Left()  += nDX;
630 			aRect.Right() += nDX;
631 			nPerc1++;
632 		}
633 		while ( nPerc1 < nPerc2 );
634 
635 		// Bei mehr als 100%, lassen wir das Rechteck blinken
636 		if ( nPercent2 > 10000 )
637 		{
638 			// an/aus-Status festlegen
639 			if ( ((nPercent2 / nPercentCount) & 0x01) == (nPercentCount & 0x01) )
640 			{
641 				aRect.Left()  -= nDX;
642 				aRect.Right() -= nDX;
643 				pWindow->Erase( aRect );
644 			}
645 		}
646 
647 		pWindow->Flush();
648 	}
649 }
650 
651 // -----------------------------------------------------------------------
652 
653 void StatusBar::ImplDrawProgress( sal_Bool bPaint,
654 								  sal_uInt16 nPercent1, sal_uInt16 nPercent2 )
655 {
656     bool bNative = IsNativeControlSupported( CTRL_PROGRESS, PART_ENTIRE_CONTROL );
657 	// bPaint: draw text also, else only update progress
658 	if ( bPaint )
659 	{
660 		DrawText( maPrgsTxtPos, maPrgsTxt );
661         if( ! bNative )
662         {
663             DecorationView aDecoView( this );
664             aDecoView.DrawFrame( maPrgsFrameRect, FRAME_DRAW_IN );
665         }
666 	}
667 
668 	Point aPos( maPrgsFrameRect.Left()+STATUSBAR_PRGS_OFFSET,
669 				maPrgsFrameRect.Top()+STATUSBAR_PRGS_OFFSET );
670     long nPrgsHeight = mnPrgsSize;
671     if( bNative )
672     {
673         aPos = maPrgsFrameRect.TopLeft();
674         nPrgsHeight = maPrgsFrameRect.GetHeight();
675     }
676 	DrawProgress( this, aPos, mnPrgsSize/2, mnPrgsSize, nPrgsHeight,
677 				  nPercent1*100, nPercent2*100, mnPercentCount, maPrgsFrameRect );
678 }
679 
680 // -----------------------------------------------------------------------
681 
682 void StatusBar::ImplCalcProgressRect()
683 {
684 	// calculate text size
685 	Size aPrgsTxtSize( GetTextWidth( maPrgsTxt ), GetTextHeight() );
686 	maPrgsTxtPos.X()	= STATUSBAR_OFFSET_X+1;
687 
688 	// calculate progress frame
689 	maPrgsFrameRect.Left()		= maPrgsTxtPos.X()+aPrgsTxtSize.Width()+STATUSBAR_OFFSET;
690 	maPrgsFrameRect.Top()		= mnItemY;
691 	maPrgsFrameRect.Bottom()	= mnCalcHeight - STATUSBAR_OFFSET_Y;
692     if( IsTopBorder() )
693         maPrgsFrameRect.Bottom()+=2;
694 
695 	// calculate size of progress rects
696 	mnPrgsSize = maPrgsFrameRect.Bottom()-maPrgsFrameRect.Top()-(STATUSBAR_PRGS_OFFSET*2);
697 	sal_uInt16 nMaxPercent = STATUSBAR_PRGS_COUNT;
698 
699 	long nMaxWidth = mnDX-STATUSBAR_OFFSET-1;
700 
701 	// make smaller if there are too many rects
702 	while ( maPrgsFrameRect.Left()+ImplCalcProgessWidth( nMaxPercent, mnPrgsSize ) > nMaxWidth )
703 	{
704 		nMaxPercent--;
705 		if ( nMaxPercent <= STATUSBAR_PRGS_MIN )
706 			break;
707 	}
708 	maPrgsFrameRect.Right() = maPrgsFrameRect.Left() + ImplCalcProgessWidth( nMaxPercent, mnPrgsSize );
709 
710 	// save the divisor for later
711 	mnPercentCount = 10000 / nMaxPercent;
712     sal_Bool bNativeOK = sal_False;
713     if( IsNativeControlSupported( CTRL_PROGRESS, PART_ENTIRE_CONTROL ) )
714     {
715         ImplControlValue aValue;
716         Rectangle aControlRegion( Rectangle( (const Point&)Point(), maPrgsFrameRect.GetSize() ) );
717         Rectangle aNativeControlRegion, aNativeContentRegion;
718         if( (bNativeOK = GetNativeControlRegion( CTRL_PROGRESS, PART_ENTIRE_CONTROL, aControlRegion,
719                                                  CTRL_STATE_ENABLED, aValue, rtl::OUString(),
720                                                  aNativeControlRegion, aNativeContentRegion ) ) != sal_False )
721         {
722             long nProgressHeight = aNativeControlRegion.GetHeight();
723             if( nProgressHeight > maPrgsFrameRect.GetHeight() )
724             {
725                 long nDelta = nProgressHeight - maPrgsFrameRect.GetHeight();
726                 maPrgsFrameRect.Top() -= (nDelta - nDelta/2);
727                 maPrgsFrameRect.Bottom() += nDelta/2;
728             }
729             maPrgsTxtPos.Y() = maPrgsFrameRect.Top() + (nProgressHeight - GetTextHeight())/2;
730         }
731     }
732     if( ! bNativeOK )
733         maPrgsTxtPos.Y()	= mnTextY;
734 }
735 
736 // -----------------------------------------------------------------------
737 
738 void StatusBar::MouseButtonDown( const MouseEvent& rMEvt )
739 {
740 	// Nur bei linker Maustaste ToolBox ausloesen
741 	if ( rMEvt.IsLeft() )
742 	{
743 		if ( mbVisibleItems )
744 		{
745 			Point  aMousePos = rMEvt.GetPosPixel();
746 			sal_uInt16 i = 0;
747 
748 			// Item suchen, das geklickt wurde
749 			ImplStatusItem* pItem = mpItemList->First();
750 			while ( pItem )
751 			{
752 				// Ist es dieses Item
753 				if ( ImplGetItemRectPos( i ).IsInside( aMousePos ) )
754 				{
755 					mnCurItemId = pItem->mnId;
756 					if ( rMEvt.GetClicks() == 2 )
757 						DoubleClick();
758 					else
759 						Click();
760 					mnCurItemId = 0;
761 
762 					// Item wurde gefunden
763 					return;
764 				}
765 
766 				i++;
767 				pItem = mpItemList->Next();
768 			}
769 		}
770 
771 		// Kein Item, dann nur Click oder DoubleClick
772 		if ( rMEvt.GetClicks() == 2 )
773 			DoubleClick();
774 		else
775 			Click();
776 	}
777 }
778 
779 // -----------------------------------------------------------------------
780 
781 void StatusBar::Paint( const Rectangle& )
782 {
783 	if ( mbFormat )
784 		ImplFormat();
785 
786 	sal_uInt16 nItemCount = (sal_uInt16)mpItemList->Count();
787 
788 	if ( mbProgressMode )
789 		ImplDrawProgress( sal_True, 0, mnPercent );
790 	else
791 	{
792 		// Text zeichen
793 		if ( !mbVisibleItems || (GetStyle() & WB_RIGHT) )
794 			ImplDrawText( sal_False, 0 );
795 
796 		// Items zeichnen
797 		if ( mbVisibleItems )
798 		{
799 			// Items zeichnen
800 			for ( sal_uInt16 i = 0; i < nItemCount; i++ )
801 				ImplDrawItem( sal_False, i, sal_True, sal_True );
802 		}
803 	}
804 
805     // draw borders
806     if( IsTopBorder() )
807     {
808 	    const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
809 	    SetLineColor( rStyleSettings.GetShadowColor() );
810 	    DrawLine( Point( 0, 0 ), Point( mnDX-1, 0 ) );
811 	    SetLineColor( rStyleSettings.GetLightColor() );
812 	    DrawLine( Point( 0, 1 ), Point( mnDX-1, 1 ) );
813     }
814 
815 	if ( IsBottomBorder() )
816 	{
817 		const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
818 		SetLineColor( rStyleSettings.GetShadowColor() );
819 		DrawLine( Point( 0, mnDY-2 ), Point( mnDX-1, mnDY-2 ) );
820 		SetLineColor( rStyleSettings.GetLightColor() );
821 		DrawLine( Point( 0, mnDY-1 ), Point( mnDX-1, mnDY-1 ) );
822 	}
823 }
824 
825 // -----------------------------------------------------------------------
826 
827 void StatusBar::Move()
828 {
829 	Window::Move();
830 }
831 
832 // -----------------------------------------------------------------------
833 
834 void StatusBar::Resize()
835 {
836 	// Breite und Hoehe abfragen und merken
837 	Size aSize = GetOutputSizePixel();
838 	mnDX = aSize.Width() - ImplGetSVData()->maNWFData.mnStatusBarLowerRightOffset;
839 	mnDY = aSize.Height();
840 	mnCalcHeight = mnDY;
841     // subtract border
842     if( IsTopBorder() )
843         mnCalcHeight -= 2;
844 	if ( IsBottomBorder() )
845 		mnCalcHeight -= 2;
846 
847     mnItemY = STATUSBAR_OFFSET_Y;
848     if( IsTopBorder() )
849         mnItemY += 2;
850     mnTextY = (mnCalcHeight-GetTextHeight())/2;
851     if( IsTopBorder() )
852         mnTextY += 2;
853 
854 	// Formatierung neu ausloesen
855 	mbFormat = sal_True;
856 
857 	if ( mbProgressMode )
858 		ImplCalcProgressRect();
859 
860 	Invalidate();
861 }
862 
863 // -----------------------------------------------------------------------
864 
865 void StatusBar::RequestHelp( const HelpEvent& rHEvt )
866 {
867 	// no keyboard help in status bar
868 	if( rHEvt.KeyboardActivated() )
869 		return;
870 
871 	sal_uInt16 nItemId = GetItemId( ScreenToOutputPixel( rHEvt.GetMousePosPixel() ) );
872 
873 	if ( nItemId )
874 	{
875 		Rectangle aItemRect = GetItemRect( nItemId );
876 		Point aPt = OutputToScreenPixel( aItemRect.TopLeft() );
877 		aItemRect.Left()   = aPt.X();
878 		aItemRect.Top()    = aPt.Y();
879 		aPt = OutputToScreenPixel( aItemRect.BottomRight() );
880 		aItemRect.Right()  = aPt.X();
881 		aItemRect.Bottom() = aPt.Y();
882 
883 		if ( rHEvt.GetMode() & HELPMODE_BALLOON )
884 		{
885 			XubString aStr = GetHelpText( nItemId );
886 			Help::ShowBalloon( this, aItemRect.Center(), aItemRect, aStr );
887 			return;
888 		}
889 		else if ( rHEvt.GetMode() & HELPMODE_QUICK )
890 		{
891 			XubString	aStr = GetQuickHelpText( nItemId );
892             // Show quickhelp if available
893             if( aStr.Len() )
894             {
895 			    Help::ShowQuickHelp( this, aItemRect, aStr );
896                 return;
897             }
898 			aStr = GetItemText( nItemId );
899 			// show a quick help if item text doesn't fit
900 			if ( GetTextWidth( aStr ) > aItemRect.GetWidth() )
901 			{
902 				Help::ShowQuickHelp( this, aItemRect, aStr );
903 				return;
904 			}
905 		}
906 		else if ( rHEvt.GetMode() & HELPMODE_EXTENDED )
907 		{
908             String aCommand = GetItemCommand( nItemId );
909             rtl::OString aHelpId( GetHelpId( nItemId ) );
910 
911             if ( aCommand.Len() || aHelpId.getLength() )
912             {
913                 // Wenn eine Hilfe existiert, dann ausloesen
914                 Help* pHelp = Application::GetHelp();
915                 if ( pHelp )
916                 {
917                     if ( aCommand.Len() )
918                         pHelp->Start( aCommand, this );
919                     else if ( aHelpId.getLength() )
920                         pHelp->Start( rtl::OStringToOUString( aHelpId, RTL_TEXTENCODING_UTF8 ), this );
921                 }
922                 return;
923             }
924 		}
925 	}
926 
927 	Window::RequestHelp( rHEvt );
928 }
929 
930 // -----------------------------------------------------------------------
931 
932 void StatusBar::StateChanged( StateChangedType nType )
933 {
934 	Window::StateChanged( nType );
935 
936 	if ( nType == STATE_CHANGE_INITSHOW )
937 		ImplFormat();
938 	else if ( nType == STATE_CHANGE_UPDATEMODE )
939 		Invalidate();
940 	else if ( (nType == STATE_CHANGE_ZOOM) ||
941 			  (nType == STATE_CHANGE_CONTROLFONT) )
942 	{
943 		mbFormat = sal_True;
944 		ImplInitSettings( sal_True, sal_False, sal_False );
945 		Invalidate();
946 	}
947 	else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
948 	{
949 		ImplInitSettings( sal_False, sal_True, sal_False );
950 		Invalidate();
951 	}
952 	else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
953 	{
954 		ImplInitSettings( sal_False, sal_False, sal_True );
955 		Invalidate();
956 	}
957 }
958 
959 // -----------------------------------------------------------------------
960 
961 void StatusBar::DataChanged( const DataChangedEvent& rDCEvt )
962 {
963 	Window::DataChanged( rDCEvt );
964 
965 	if ( (rDCEvt.GetType() == DATACHANGED_DISPLAY) ||
966 		 (rDCEvt.GetType() == DATACHANGED_FONTS) ||
967 		 (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
968 		 ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
969 		  (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
970 	{
971 		mbFormat = sal_True;
972 		ImplInitSettings( sal_True, sal_True, sal_True );
973         ImplStatusItem* pItem = mpItemList->First();
974         long nFudge = GetTextHeight() / 4;
975         while ( pItem )
976         {
977             long nWidth = GetTextWidth( pItem->maText ) + nFudge;
978             if( nWidth > pItem->mnWidth + STATUSBAR_OFFSET )
979                 pItem->mnWidth = nWidth + STATUSBAR_OFFSET;
980             pItem = mpItemList->Next();
981         }
982         Size aSize = GetSizePixel();
983         // do not disturb current width, since
984         // CalcWindowSizePixel calculates a minimum width
985         aSize.Height() = CalcWindowSizePixel().Height();
986         SetSizePixel( aSize );
987 		Invalidate();
988 	}
989 }
990 
991 // -----------------------------------------------------------------------
992 
993 void StatusBar::Click()
994 {
995     ImplCallEventListeners( VCLEVENT_STATUSBAR_CLICK );
996 	maClickHdl.Call( this );
997 }
998 
999 // -----------------------------------------------------------------------
1000 
1001 void StatusBar::DoubleClick()
1002 {
1003     ImplCallEventListeners( VCLEVENT_STATUSBAR_DOUBLECLICK );
1004 	maDoubleClickHdl.Call( this );
1005 }
1006 
1007 // -----------------------------------------------------------------------
1008 
1009 void StatusBar::UserDraw( const UserDrawEvent& )
1010 {
1011 }
1012 
1013 // -----------------------------------------------------------------------
1014 
1015 void StatusBar::InsertItem( sal_uInt16 nItemId, sal_uLong nWidth,
1016 							StatusBarItemBits nBits,
1017 							long nOffset, sal_uInt16 nPos )
1018 {
1019 	DBG_ASSERT( nItemId, "StatusBar::InsertItem(): ItemId == 0" );
1020 	DBG_ASSERT( GetItemPos( nItemId ) == STATUSBAR_ITEM_NOTFOUND,
1021 				"StatusBar::InsertItem(): ItemId already exists" );
1022 
1023 	// IN und CENTER sind Default
1024 	if ( !(nBits & (SIB_IN | SIB_OUT | SIB_FLAT)) )
1025 		nBits |= SIB_IN;
1026 	if ( !(nBits & (SIB_LEFT | SIB_RIGHT | SIB_CENTER)) )
1027 		nBits |= SIB_CENTER;
1028 
1029 	// Item anlegen
1030     long nFudge = GetTextHeight()/4;
1031 	ImplStatusItem* pItem	= new ImplStatusItem;
1032 	pItem->mnId 			= nItemId;
1033 	pItem->mnBits			= nBits;
1034 	pItem->mnWidth			= (long)nWidth+nFudge+STATUSBAR_OFFSET;
1035 	pItem->mnOffset 		= nOffset;
1036 	pItem->mpUserData		= 0;
1037 	pItem->mbVisible		= sal_True;
1038 
1039 	// Item in die Liste einfuegen
1040 	mpItemList->Insert( pItem, nPos );
1041 
1042 	mbFormat = sal_True;
1043 	if ( ImplIsItemUpdate() )
1044 		Invalidate();
1045 
1046 	ImplCallEventListeners( VCLEVENT_STATUSBAR_ITEMADDED, (void*) sal_IntPtr(nItemId) );
1047 }
1048 
1049 // -----------------------------------------------------------------------
1050 
1051 void StatusBar::RemoveItem( sal_uInt16 nItemId )
1052 {
1053 	sal_uInt16 nPos = GetItemPos( nItemId );
1054 	if ( nPos != STATUSBAR_ITEM_NOTFOUND )
1055 	{
1056 		ImplStatusItem* pItem = mpItemList->Remove( nPos );
1057 		delete pItem;
1058 
1059 		mbFormat = sal_True;
1060 		if ( ImplIsItemUpdate() )
1061 			Invalidate();
1062 
1063 		ImplCallEventListeners( VCLEVENT_STATUSBAR_ITEMREMOVED, (void*) sal_IntPtr(nItemId) );
1064 	}
1065 }
1066 
1067 // -----------------------------------------------------------------------
1068 
1069 void StatusBar::ShowItem( sal_uInt16 nItemId )
1070 {
1071 	sal_uInt16 nPos = GetItemPos( nItemId );
1072 
1073 	if ( nPos != STATUSBAR_ITEM_NOTFOUND )
1074 	{
1075 		ImplStatusItem* pItem = mpItemList->GetObject( nPos );
1076 		if ( !pItem->mbVisible )
1077 		{
1078 			pItem->mbVisible = sal_True;
1079 
1080 			mbFormat = sal_True;
1081 			if ( ImplIsItemUpdate() )
1082 				Invalidate();
1083 
1084 			ImplCallEventListeners( VCLEVENT_STATUSBAR_SHOWITEM, (void*) sal_IntPtr(nItemId) );
1085 		}
1086 	}
1087 }
1088 
1089 // -----------------------------------------------------------------------
1090 
1091 void StatusBar::HideItem( sal_uInt16 nItemId )
1092 {
1093 	sal_uInt16 nPos = GetItemPos( nItemId );
1094 
1095 	if ( nPos != STATUSBAR_ITEM_NOTFOUND )
1096 	{
1097 		ImplStatusItem* pItem = mpItemList->GetObject( nPos );
1098 		if ( pItem->mbVisible )
1099 		{
1100 			pItem->mbVisible = sal_False;
1101 
1102 			mbFormat = sal_True;
1103 			if ( ImplIsItemUpdate() )
1104 				Invalidate();
1105 
1106 			ImplCallEventListeners( VCLEVENT_STATUSBAR_HIDEITEM, (void*) sal_IntPtr(nItemId) );
1107 		}
1108 	}
1109 }
1110 
1111 // -----------------------------------------------------------------------
1112 
1113 sal_Bool StatusBar::IsItemVisible( sal_uInt16 nItemId ) const
1114 {
1115 	sal_uInt16 nPos = GetItemPos( nItemId );
1116 
1117 	if ( nPos != STATUSBAR_ITEM_NOTFOUND )
1118 		return mpItemList->GetObject( nPos )->mbVisible;
1119 	else
1120 		return sal_False;
1121 }
1122 
1123 // -----------------------------------------------------------------------
1124 
1125 void StatusBar::ShowItems()
1126 {
1127 	if ( !mbVisibleItems )
1128 	{
1129 		mbVisibleItems = sal_True;
1130 		if ( !mbProgressMode )
1131 			Invalidate();
1132 
1133 		ImplCallEventListeners( VCLEVENT_STATUSBAR_SHOWALLITEMS );
1134 	}
1135 }
1136 
1137 // -----------------------------------------------------------------------
1138 
1139 void StatusBar::HideItems()
1140 {
1141 	if ( mbVisibleItems )
1142 	{
1143 		mbVisibleItems = sal_False;
1144 		if ( !mbProgressMode )
1145 			Invalidate();
1146 
1147 		ImplCallEventListeners( VCLEVENT_STATUSBAR_HIDEALLITEMS );
1148 	}
1149 }
1150 
1151 // -----------------------------------------------------------------------
1152 
1153 void StatusBar::CopyItems( const StatusBar& rStatusBar )
1154 {
1155 	// Alle Items entfernen
1156 	ImplStatusItem* pItem = mpItemList->First();
1157 	while ( pItem )
1158 	{
1159 		delete pItem;
1160 		pItem = mpItemList->Next();
1161 	}
1162 
1163 	// Items aus der Liste loeschen
1164 	mpItemList->Clear();
1165 
1166 	// Items kopieren
1167 	sal_uLong i = 0;
1168 	pItem = rStatusBar.mpItemList->GetObject( i );
1169 	while ( pItem )
1170 	{
1171 		mpItemList->Insert( new ImplStatusItem( *pItem ), LIST_APPEND );
1172 		i++;
1173 		pItem = rStatusBar.mpItemList->GetObject( i );
1174 	}
1175 
1176 	mbFormat = sal_True;
1177 	if ( ImplIsItemUpdate() )
1178 		Invalidate();
1179 }
1180 
1181 // -----------------------------------------------------------------------
1182 
1183 void StatusBar::Clear()
1184 {
1185 	// Alle Item loeschen
1186 	ImplStatusItem* pItem = mpItemList->First();
1187 	while ( pItem )
1188 	{
1189 		delete pItem;
1190 		pItem = mpItemList->Next();
1191 	}
1192 
1193 	// Items aus der Liste loeschen
1194 	mpItemList->Clear();
1195 
1196 	mbFormat = sal_True;
1197 	if ( ImplIsItemUpdate() )
1198 		Invalidate();
1199 
1200 	ImplCallEventListeners( VCLEVENT_STATUSBAR_ALLITEMSREMOVED );
1201 }
1202 
1203 // -----------------------------------------------------------------------
1204 
1205 sal_uInt16 StatusBar::GetItemCount() const
1206 {
1207 	return (sal_uInt16)mpItemList->Count();
1208 }
1209 
1210 // -----------------------------------------------------------------------
1211 
1212 sal_uInt16 StatusBar::GetItemId( sal_uInt16 nPos ) const
1213 {
1214 	ImplStatusItem* pItem = mpItemList->GetObject( nPos );
1215 	if ( pItem )
1216 		return pItem->mnId;
1217 	else
1218 		return 0;
1219 }
1220 
1221 // -----------------------------------------------------------------------
1222 
1223 sal_uInt16 StatusBar::GetItemPos( sal_uInt16 nItemId ) const
1224 {
1225 	ImplStatusItem* pItem = mpItemList->First();
1226 	while ( pItem )
1227 	{
1228 		if ( pItem->mnId == nItemId )
1229 			return (sal_uInt16)mpItemList->GetCurPos();
1230 
1231 		pItem = mpItemList->Next();
1232 	}
1233 
1234 	return STATUSBAR_ITEM_NOTFOUND;
1235 }
1236 
1237 // -----------------------------------------------------------------------
1238 
1239 sal_uInt16 StatusBar::GetItemId( const Point& rPos ) const
1240 {
1241 	if ( AreItemsVisible() && !mbFormat )
1242 	{
1243 		sal_uInt16 nItemCount = GetItemCount();
1244 		sal_uInt16 nPos;
1245 		for ( nPos = 0; nPos < nItemCount; nPos++ )
1246 		{
1247 			// Rechteck holen
1248 			Rectangle aRect = ImplGetItemRectPos( nPos );
1249 			if ( aRect.IsInside( rPos ) )
1250 				return mpItemList->GetObject( nPos )->mnId;
1251 		}
1252 	}
1253 
1254 	return 0;
1255 }
1256 
1257 // -----------------------------------------------------------------------
1258 
1259 Rectangle StatusBar::GetItemRect( sal_uInt16 nItemId ) const
1260 {
1261 	Rectangle aRect;
1262 
1263 	if ( AreItemsVisible() && !mbFormat )
1264 	{
1265 		sal_uInt16 nPos = GetItemPos( nItemId );
1266 		if ( nPos != STATUSBAR_ITEM_NOTFOUND )
1267 		{
1268 			// Rechteck holen und Rahmen abziehen
1269 			aRect = ImplGetItemRectPos( nPos );
1270             long nW = mpImplData->mnItemBorderWidth+1;
1271             aRect.Top() += nW-1;
1272             aRect.Bottom() -= nW-1;
1273 			aRect.Left() += nW;
1274 			aRect.Right() -= nW;
1275 			return aRect;
1276 		}
1277 	}
1278 
1279 	return aRect;
1280 }
1281 
1282 // -----------------------------------------------------------------------
1283 
1284 Point StatusBar::GetItemTextPos( sal_uInt16 nItemId ) const
1285 {
1286 	if ( !mbFormat )
1287 	{
1288 		sal_uInt16 nPos = GetItemPos( nItemId );
1289 		if ( nPos != STATUSBAR_ITEM_NOTFOUND )
1290 		{
1291 			// Rechteck holen
1292 			ImplStatusItem* pItem = mpItemList->GetObject( nPos );
1293 			Rectangle aRect = ImplGetItemRectPos( nPos );
1294             long nW = mpImplData->mnItemBorderWidth + 1;
1295             Rectangle			aTextRect( aRect.Left()+nW, aRect.Top()+nW,
1296                                            aRect.Right()-nW, aRect.Bottom()-nW );
1297 			Point aPos = ImplGetItemTextPos( aTextRect.GetSize(),
1298 											 Size( GetTextWidth( pItem->maText ), GetTextHeight() ),
1299 											 pItem->mnBits );
1300 			if ( !mbInUserDraw )
1301 			{
1302 				aPos.X() += aTextRect.Left();
1303 				aPos.Y() += aTextRect.Top();
1304 			}
1305 			return aPos;
1306 		}
1307 	}
1308 
1309 	return Point();
1310 }
1311 
1312 // -----------------------------------------------------------------------
1313 
1314 sal_uLong StatusBar::GetItemWidth( sal_uInt16 nItemId ) const
1315 {
1316 	sal_uInt16 nPos = GetItemPos( nItemId );
1317 
1318 	if ( nPos != STATUSBAR_ITEM_NOTFOUND )
1319 		return mpItemList->GetObject( nPos )->mnWidth;
1320 	else
1321 		return 0;
1322 }
1323 
1324 // -----------------------------------------------------------------------
1325 
1326 StatusBarItemBits StatusBar::GetItemBits( sal_uInt16 nItemId ) const
1327 {
1328 	sal_uInt16 nPos = GetItemPos( nItemId );
1329 
1330 	if ( nPos != STATUSBAR_ITEM_NOTFOUND )
1331 		return mpItemList->GetObject( nPos )->mnBits;
1332 	else
1333 		return 0;
1334 }
1335 
1336 // -----------------------------------------------------------------------
1337 
1338 long StatusBar::GetItemOffset( sal_uInt16 nItemId ) const
1339 {
1340 	sal_uInt16 nPos = GetItemPos( nItemId );
1341 
1342 	if ( nPos != STATUSBAR_ITEM_NOTFOUND )
1343 		return mpItemList->GetObject( nPos )->mnOffset;
1344 	else
1345 		return 0;
1346 }
1347 
1348 // -----------------------------------------------------------------------
1349 
1350 void StatusBar::SetItemText( sal_uInt16 nItemId, const XubString& rText )
1351 {
1352 	sal_uInt16 nPos = GetItemPos( nItemId );
1353 
1354 	if ( nPos != STATUSBAR_ITEM_NOTFOUND )
1355 	{
1356 		ImplStatusItem* pItem = mpItemList->GetObject( nPos );
1357 
1358 		if ( pItem->maText != rText )
1359 		{
1360 			pItem->maText = rText;
1361 
1362             // adjust item width - see also DataChanged()
1363             long nFudge = GetTextHeight()/4;
1364             long nWidth = GetTextWidth( pItem->maText ) + nFudge;
1365             if( (nWidth > pItem->mnWidth + STATUSBAR_OFFSET) ||
1366                 ((nWidth < pItem->mnWidth) && (mnDX - STATUSBAR_OFFSET) < mnItemsWidth  ))
1367             {
1368                 pItem->mnWidth = nWidth + STATUSBAR_OFFSET;
1369                 ImplFormat();
1370                 Invalidate();
1371             }
1372 
1373 			// Item neu Zeichen, wenn StatusBar sichtbar und
1374 			// UpdateMode gesetzt ist
1375 			if ( pItem->mbVisible && !mbFormat && ImplIsItemUpdate() )
1376 			{
1377 				Update();
1378 				ImplDrawItem( sal_True, nPos, sal_True, sal_False );
1379 				Flush();
1380 			}
1381 		}
1382 	}
1383 }
1384 
1385 // -----------------------------------------------------------------------
1386 
1387 const XubString& StatusBar::GetItemText( sal_uInt16 nItemId ) const
1388 {
1389 	sal_uInt16 nPos = GetItemPos( nItemId );
1390 
1391 	if ( nPos != STATUSBAR_ITEM_NOTFOUND )
1392 		return mpItemList->GetObject( nPos )->maText;
1393 	else
1394 		return ImplGetSVEmptyStr();
1395 }
1396 
1397 // -----------------------------------------------------------------------
1398 
1399 void StatusBar::SetItemCommand( sal_uInt16 nItemId, const XubString& rCommand )
1400 {
1401 	sal_uInt16 nPos = GetItemPos( nItemId );
1402 
1403 	if ( nPos != STATUSBAR_ITEM_NOTFOUND )
1404 	{
1405 		ImplStatusItem* pItem = mpItemList->GetObject( nPos );
1406 
1407 		if ( pItem->maCommand != rCommand )
1408 			pItem->maCommand = rCommand;
1409 	}
1410 }
1411 
1412 // -----------------------------------------------------------------------
1413 
1414 const XubString& StatusBar::GetItemCommand( sal_uInt16 nItemId )
1415 {
1416 	sal_uInt16 nPos = GetItemPos( nItemId );
1417 
1418 	if ( nPos != STATUSBAR_ITEM_NOTFOUND )
1419 		return mpItemList->GetObject( nPos )->maCommand;
1420 	else
1421 		return ImplGetSVEmptyStr();
1422 }
1423 
1424 // -----------------------------------------------------------------------
1425 
1426 void StatusBar::SetItemData( sal_uInt16 nItemId, void* pNewData )
1427 {
1428 	sal_uInt16 nPos = GetItemPos( nItemId );
1429 
1430 	if ( nPos != STATUSBAR_ITEM_NOTFOUND )
1431 	{
1432 		ImplStatusItem* pItem = mpItemList->GetObject( nPos );
1433 		pItem->mpUserData = pNewData;
1434 
1435 		// Wenn es ein User-Item ist, DrawItem-Aufrufen
1436 		if ( (pItem->mnBits & SIB_USERDRAW) && pItem->mbVisible &&
1437 			 !mbFormat && ImplIsItemUpdate() )
1438 		{
1439 			Update();
1440 			ImplDrawItem( sal_True, nPos, sal_False, sal_False );
1441 			Flush();
1442 		}
1443 	}
1444 }
1445 
1446 // -----------------------------------------------------------------------
1447 
1448 void* StatusBar::GetItemData( sal_uInt16 nItemId ) const
1449 {
1450 	sal_uInt16 nPos = GetItemPos( nItemId );
1451 
1452 	if ( nPos != STATUSBAR_ITEM_NOTFOUND )
1453 		return mpItemList->GetObject( nPos )->mpUserData;
1454 	else
1455 		return NULL;
1456 }
1457 
1458 // -----------------------------------------------------------------------
1459 
1460 void StatusBar::SetHelpText( sal_uInt16 nItemId, const XubString& rText )
1461 {
1462 	sal_uInt16 nPos = GetItemPos( nItemId );
1463 
1464 	if ( nPos != STATUSBAR_ITEM_NOTFOUND )
1465 		mpItemList->GetObject( nPos )->maHelpText = rText;
1466 }
1467 
1468 // -----------------------------------------------------------------------
1469 
1470 const XubString& StatusBar::GetHelpText( sal_uInt16 nItemId ) const
1471 {
1472 	sal_uInt16 nPos = GetItemPos( nItemId );
1473 
1474 	if ( nPos != STATUSBAR_ITEM_NOTFOUND )
1475 	{
1476 		ImplStatusItem* pItem = mpItemList->GetObject( nPos );
1477 		if ( !pItem->maHelpText.Len() && ( pItem->maHelpId.getLength() || pItem->maCommand.Len() ))
1478 		{
1479 			Help* pHelp = Application::GetHelp();
1480 			if ( pHelp )
1481             {
1482 				if ( pItem->maCommand.Len() )
1483                     pItem->maHelpText = pHelp->GetHelpText( pItem->maCommand, this );
1484                 if ( !pItem->maHelpText.Len() && pItem->maHelpId.getLength() )
1485                     pItem->maHelpText = pHelp->GetHelpText( rtl::OStringToOUString( pItem->maHelpId, RTL_TEXTENCODING_UTF8 ), this );
1486             }
1487 		}
1488 
1489 		return pItem->maHelpText;
1490 	}
1491 	else
1492 		return ImplGetSVEmptyStr();
1493 }
1494 
1495 // -----------------------------------------------------------------------
1496 
1497 void StatusBar::SetQuickHelpText( sal_uInt16 nItemId, const XubString& rText )
1498 {
1499 	sal_uInt16 nPos = GetItemPos( nItemId );
1500 
1501 	if ( nPos != STATUSBAR_ITEM_NOTFOUND )
1502 		mpItemList->GetObject( nPos )->maQuickHelpText = rText;
1503 }
1504 
1505 // -----------------------------------------------------------------------
1506 
1507 const XubString& StatusBar::GetQuickHelpText( sal_uInt16 nItemId ) const
1508 {
1509 	sal_uInt16 nPos = GetItemPos( nItemId );
1510 
1511 	if ( nPos != STATUSBAR_ITEM_NOTFOUND )
1512 	{
1513 		ImplStatusItem* pItem = mpItemList->GetObject( nPos );
1514 		return pItem->maQuickHelpText;
1515 	}
1516 	else
1517 		return ImplGetSVEmptyStr();
1518 }
1519 
1520 // -----------------------------------------------------------------------
1521 
1522 void StatusBar::SetHelpId( sal_uInt16 nItemId, const rtl::OString& rHelpId )
1523 {
1524 	sal_uInt16 nPos = GetItemPos( nItemId );
1525 
1526 	if ( nPos != STATUSBAR_ITEM_NOTFOUND )
1527 		mpItemList->GetObject( nPos )->maHelpId = rHelpId;
1528 }
1529 
1530 // -----------------------------------------------------------------------
1531 
1532 rtl::OString StatusBar::GetHelpId( sal_uInt16 nItemId ) const
1533 {
1534 	sal_uInt16 nPos = GetItemPos( nItemId );
1535 
1536 	rtl::OString aRet;
1537 	if ( nPos != STATUSBAR_ITEM_NOTFOUND )
1538     {
1539 		ImplStatusItem* pItem = mpItemList->GetObject( nPos );
1540         if ( pItem->maHelpId.getLength() )
1541             aRet = pItem->maHelpId;
1542         else
1543             aRet = ::rtl::OUStringToOString( pItem->maCommand, RTL_TEXTENCODING_UTF8 );
1544     }
1545 
1546 	return aRet;
1547 }
1548 
1549 // -----------------------------------------------------------------------
1550 
1551 void StatusBar::ImplCalcBorder( )
1552 {
1553 	mnCalcHeight = mnDY;
1554     // subtract border
1555     if( IsTopBorder() )
1556     {
1557         mnCalcHeight -= 2;
1558         mnTextY += 2;
1559         mnItemY += 2;
1560     }
1561 	if ( IsBottomBorder() )
1562 		mnCalcHeight -= 2;
1563 	mbFormat = sal_True;
1564 	Invalidate();
1565 }
1566 
1567 void StatusBar::SetBottomBorder( sal_Bool bBottomBorder )
1568 {
1569 	if ( mbBottomBorder != bBottomBorder )
1570 	{
1571 		mbBottomBorder = bBottomBorder;
1572         ImplCalcBorder();
1573 	}
1574 }
1575 
1576 void StatusBar::SetTopBorder( sal_Bool bTopBorder )
1577 {
1578     if ( mpImplData->mbTopBorder != static_cast<bool>(bTopBorder) )
1579     {
1580 	    mpImplData->mbTopBorder = static_cast<bool>(bTopBorder);
1581         ImplCalcBorder();
1582     }
1583 }
1584 
1585 sal_Bool StatusBar::IsTopBorder() const
1586 {
1587     return mpImplData->mbTopBorder;
1588 }
1589 
1590 // -----------------------------------------------------------------------
1591 
1592 void StatusBar::StartProgressMode( const XubString& rText )
1593 {
1594 	DBG_ASSERT( !mbProgressMode, "StatusBar::StartProgressMode(): progress mode is active" );
1595 
1596 	mbProgressMode	= sal_True;
1597 	mnPercent		= 0;
1598 	maPrgsTxt		= rText;
1599 
1600 	// Groessen berechnen
1601 	ImplCalcProgressRect();
1602 
1603 	// Paint ausloesen (dort wird der Text und der Frame gemalt)
1604 	const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
1605 	Color aPrgsColor = rStyleSettings.GetHighlightColor();
1606 	if ( aPrgsColor == rStyleSettings.GetFaceColor() )
1607 		aPrgsColor = rStyleSettings.GetDarkShadowColor();
1608 	SetLineColor();
1609 	SetFillColor( aPrgsColor );
1610 	if ( IsReallyVisible() )
1611 	{
1612 		Invalidate();
1613 		Update();
1614 		Flush();
1615 	}
1616 }
1617 
1618 // -----------------------------------------------------------------------
1619 
1620 void StatusBar::SetProgressValue( sal_uInt16 nNewPercent )
1621 {
1622 	DBG_ASSERT( mbProgressMode, "StatusBar::SetProgressValue(): no progrss mode" );
1623 	DBG_ASSERTWARNING( nNewPercent <= 100, "StatusBar::SetProgressValue(): nPercent > 100" );
1624 
1625 	if ( mbProgressMode
1626 	&&   IsReallyVisible()
1627 	&&   (!mnPercent || (mnPercent != nNewPercent)) )
1628 	{
1629 		Update();
1630 		SetLineColor();
1631 		ImplDrawProgress( sal_False, mnPercent, nNewPercent );
1632 		Flush();
1633 	}
1634 	mnPercent = nNewPercent;
1635 }
1636 
1637 // -----------------------------------------------------------------------
1638 
1639 void StatusBar::EndProgressMode()
1640 {
1641 	DBG_ASSERT( mbProgressMode, "StatusBar::EndProgressMode(): no progress mode" );
1642 
1643 	mbProgressMode = sal_False;
1644 	maPrgsTxt.Erase();
1645 
1646 	// Paint neu ausloesen um StatusBar wieder herzustellen
1647 	SetFillColor( GetSettings().GetStyleSettings().GetFaceColor() );
1648 	if ( IsReallyVisible() )
1649 	{
1650 		Invalidate();
1651 		Update();
1652 		Flush();
1653 	}
1654 }
1655 
1656 // -----------------------------------------------------------------------
1657 
1658 void StatusBar::ResetProgressMode()
1659 {
1660 	if ( mbProgressMode )
1661 	{
1662 		mnPercent = 0;
1663 		maPrgsTxt.Erase();
1664 		if ( IsReallyVisible() )
1665 		{
1666 			Invalidate();
1667 			Update();
1668 			Flush();
1669 		}
1670 	}
1671 }
1672 
1673 // -----------------------------------------------------------------------
1674 
1675 void StatusBar::SetText( const XubString& rText )
1676 {
1677 	if ( (!mbVisibleItems || (GetStyle() & WB_RIGHT)) && !mbProgressMode &&
1678 		 IsReallyVisible() && IsUpdateMode() )
1679 	{
1680 		if ( mbFormat  )
1681 		{
1682 			Invalidate();
1683 			Window::SetText( rText );
1684 		}
1685 		else
1686 		{
1687 			Update();
1688 			long nOldTextWidth = GetTextWidth( GetText() );
1689 			Window::SetText( rText );
1690 			ImplDrawText( sal_True, nOldTextWidth );
1691 			Flush();
1692 		}
1693 	}
1694 	else if ( mbProgressMode )
1695 	{
1696 		maPrgsTxt = rText;
1697 		if ( IsReallyVisible() )
1698 		{
1699 			Invalidate();
1700 			Update();
1701 			Flush();
1702 		}
1703 	}
1704 	else
1705 		Window::SetText( rText );
1706 }
1707 
1708 // -----------------------------------------------------------------------
1709 
1710 Size StatusBar::CalcWindowSizePixel() const
1711 {
1712 	sal_uLong	i = 0;
1713 	sal_uLong	nCount = mpItemList->Count();
1714 	long	nOffset = 0;
1715 	long	nCalcWidth = (STATUSBAR_OFFSET_X*2);
1716 	long	nCalcHeight;
1717 
1718 	while ( i < nCount )
1719 	{
1720 		ImplStatusItem* pItem = mpItemList->GetObject( i );
1721 		nCalcWidth += pItem->mnWidth + nOffset;
1722 		nOffset = pItem->mnOffset;
1723 		i++;
1724 	}
1725 
1726     long nMinHeight = GetTextHeight();
1727     const long nBarTextOffset = STATUSBAR_OFFSET_TEXTY*2;
1728     long nProgressHeight = nMinHeight + nBarTextOffset;
1729     // FIXME: IsNativeControlSupported and GetNativeControlRegion should be const ?
1730     StatusBar* pThis = const_cast<StatusBar*>( this );
1731     if( pThis->IsNativeControlSupported( CTRL_PROGRESS, PART_ENTIRE_CONTROL ) )
1732     {
1733         ImplControlValue aValue;
1734         Rectangle aControlRegion( (const Point&)Point(), Size( nCalcWidth, nMinHeight ) );
1735         Rectangle aNativeControlRegion, aNativeContentRegion;
1736         if( pThis->GetNativeControlRegion( CTRL_PROGRESS, PART_ENTIRE_CONTROL, aControlRegion,
1737                                            CTRL_STATE_ENABLED, aValue, rtl::OUString(),
1738                                            aNativeControlRegion, aNativeContentRegion ) )
1739         {
1740             nProgressHeight = aNativeControlRegion.GetHeight();
1741         }
1742     }
1743 
1744     if( mpImplData->mbDrawItemFrames &&
1745         pThis->IsNativeControlSupported( CTRL_FRAME, PART_BORDER ) )
1746     {
1747         ImplControlValue aControlValue( FRAME_DRAW_NODRAW );
1748         Rectangle aBound, aContent;
1749         Rectangle aNatRgn( Point( 0, 0 ), Size( 150, 50 ) );
1750         if(	pThis->GetNativeControlRegion(CTRL_FRAME, PART_BORDER,
1751             aNatRgn, 0, aControlValue, rtl::OUString(), aBound, aContent) )
1752         {
1753             mpImplData->mnItemBorderWidth =
1754                 ( aBound.GetHeight() - aContent.GetHeight() ) / 2;
1755         }
1756     }
1757 
1758 	nCalcHeight = nMinHeight+nBarTextOffset + 2*mpImplData->mnItemBorderWidth;
1759     if( nCalcHeight < nProgressHeight+2 )
1760         nCalcHeight = nProgressHeight+2;
1761 
1762     // add border
1763     if( IsTopBorder() )
1764         nCalcHeight += 2;
1765 	if ( IsBottomBorder() )
1766 		nCalcHeight += 2;
1767 
1768 	return Size( nCalcWidth, nCalcHeight );
1769 }
1770 
1771 
1772 // -----------------------------------------------------------------------
1773 
1774 void StatusBar::SetAccessibleName( sal_uInt16 nItemId, const XubString& rName )
1775 {
1776 	sal_uInt16 nPos = GetItemPos( nItemId );
1777 
1778 	if ( nPos != STATUSBAR_ITEM_NOTFOUND )
1779 	{
1780 		ImplStatusItem* pItem = mpItemList->GetObject( nPos );
1781 
1782 		if ( pItem->maAccessibleName != rName )
1783 		{
1784 			pItem->maAccessibleName = rName;
1785 			ImplCallEventListeners( VCLEVENT_STATUSBAR_NAMECHANGED, (void*) sal_IntPtr(pItem->mnId) );
1786 		}
1787 	}
1788 }
1789 
1790 // -----------------------------------------------------------------------
1791 
1792 const XubString& StatusBar::GetAccessibleName( sal_uInt16 nItemId ) const
1793 {
1794 	sal_uInt16 nPos = GetItemPos( nItemId );
1795 
1796 	if ( nPos != STATUSBAR_ITEM_NOTFOUND )
1797 		return mpItemList->GetObject( nPos )->maAccessibleName;
1798 	else
1799 		return ImplGetSVEmptyStr();
1800 }
1801 
1802 // -----------------------------------------------------------------------
1803