xref: /trunk/main/vcl/source/window/status.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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