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