xref: /AOO41X/main/vcl/source/window/status.cxx (revision 47148b3bc50811ceb41802e4cc50a5db21535900)
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 
ImplData()65 StatusBar::ImplData::ImplData()
66 {
67     mpVirDev = NULL;
68     mbTopBorder = false;
69     mbDrawItemFrames = false;
70     mnItemBorderWidth = 0;
71 }
72 
~ImplData()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 
DECLARE_LIST(ImplStatusItemList,ImplStatusItem *)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 
ImplGetItemTextPos(const Size & rRectSize,const Size & rTextSize,sal_uInt16 nStyle)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 
ImplIsItemUpdate()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 
ImplInit(Window * pParent,WinBits nStyle)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 
StatusBar(Window * pParent,WinBits nStyle)171 StatusBar::StatusBar( Window* pParent, WinBits nStyle ) :
172     Window( WINDOW_STATUSBAR )
173 {
174     ImplInit( pParent, nStyle );
175 }
176 
177 // -----------------------------------------------------------------------
178 
StatusBar(Window * pParent,const ResId & rResId)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 
~StatusBar()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 
ImplInitSettings(sal_Bool bFont,sal_Bool bForeground,sal_Bool bBackground)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 
ImplFormat()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 
ImplGetItemRectPos(sal_uInt16 nPos) const352 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 
ImplGetFirstVisiblePos() const375 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 
ImplDrawText(sal_Bool bOffScreen,long nOldTextWidth)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 
ImplDrawItem(sal_Bool bOffScreen,sal_uInt16 nPos,sal_Bool bDrawText,sal_Bool bDrawFrame)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 
DrawProgress(Window * pWindow,const Point & rPos,long nOffset,long nPrgsWidth,long nPrgsHeight,sal_uInt16 nPercent1,sal_uInt16 nPercent2,sal_uInt16 nPercentCount,const Rectangle & rFramePosSize)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 
ImplDrawProgress(sal_Bool bPaint,sal_uInt16 nPercent1,sal_uInt16 nPercent2)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 
ImplCalcProgressRect()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 
MouseButtonDown(const MouseEvent & rMEvt)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 
Paint(const Rectangle &)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 
Move()823 void StatusBar::Move()
824 {
825     Window::Move();
826 }
827 
828 // -----------------------------------------------------------------------
829 
Resize()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 
RequestHelp(const HelpEvent & rHEvt)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 
StateChanged(StateChangedType nType)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 
DataChanged(const DataChangedEvent & rDCEvt)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 
Click()989 void StatusBar::Click()
990 {
991     ImplCallEventListeners( VCLEVENT_STATUSBAR_CLICK );
992     maClickHdl.Call( this );
993 }
994 
995 // -----------------------------------------------------------------------
996 
DoubleClick()997 void StatusBar::DoubleClick()
998 {
999     ImplCallEventListeners( VCLEVENT_STATUSBAR_DOUBLECLICK );
1000     maDoubleClickHdl.Call( this );
1001 }
1002 
1003 // -----------------------------------------------------------------------
1004 
UserDraw(const UserDrawEvent &)1005 void StatusBar::UserDraw( const UserDrawEvent& )
1006 {
1007 }
1008 
1009 // -----------------------------------------------------------------------
1010 
InsertItem(sal_uInt16 nItemId,sal_uLong nWidth,StatusBarItemBits nBits,long nOffset,sal_uInt16 nPos)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 
RemoveItem(sal_uInt16 nItemId)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 
ShowItem(sal_uInt16 nItemId)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 
HideItem(sal_uInt16 nItemId)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 
IsItemVisible(sal_uInt16 nItemId) const1109 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 
ShowItems()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 
HideItems()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 
CopyItems(const StatusBar & rStatusBar)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 
Clear()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 
GetItemCount() const1201 sal_uInt16 StatusBar::GetItemCount() const
1202 {
1203     return (sal_uInt16)mpItemList->Count();
1204 }
1205 
1206 // -----------------------------------------------------------------------
1207 
GetItemId(sal_uInt16 nPos) const1208 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 
GetItemPos(sal_uInt16 nItemId) const1219 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 
GetItemId(const Point & rPos) const1235 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 
GetItemRect(sal_uInt16 nItemId) const1255 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 
GetItemTextPos(sal_uInt16 nItemId) const1280 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 
GetItemWidth(sal_uInt16 nItemId) const1310 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 
GetItemBits(sal_uInt16 nItemId) const1322 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 
GetItemOffset(sal_uInt16 nItemId) const1334 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 
SetItemText(sal_uInt16 nItemId,const XubString & rText)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 
GetItemText(sal_uInt16 nItemId) const1383 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 
SetItemCommand(sal_uInt16 nItemId,const XubString & rCommand)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 
GetItemCommand(sal_uInt16 nItemId)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 
SetItemData(sal_uInt16 nItemId,void * pNewData)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 
RedrawItem(sal_uInt16 nItemId)1442 void StatusBar::RedrawItem( sal_uInt16 nItemId )
1443 {
1444     if ( mbFormat )
1445         return;
1446 
1447     sal_uInt16 nPos = GetItemPos( nItemId );
1448     if ( nPos == STATUSBAR_ITEM_NOTFOUND )
1449         return;
1450 
1451     ImplStatusItem* pItem = mpItemList->GetObject( nPos );
1452     if ( pItem && (pItem->mnBits & SIB_USERDRAW) &&
1453          pItem->mbVisible && ImplIsItemUpdate() )
1454     {
1455         Update();
1456         ImplDrawItem( sal_True, nPos, sal_False, sal_False );
1457         Flush();
1458     }
1459 }
1460 
1461 // -----------------------------------------------------------------------
1462 
GetItemData(sal_uInt16 nItemId) const1463 void* StatusBar::GetItemData( sal_uInt16 nItemId ) const
1464 {
1465     sal_uInt16 nPos = GetItemPos( nItemId );
1466 
1467     if ( nPos != STATUSBAR_ITEM_NOTFOUND )
1468         return mpItemList->GetObject( nPos )->mpUserData;
1469     else
1470         return NULL;
1471 }
1472 
1473 // -----------------------------------------------------------------------
1474 
SetHelpText(sal_uInt16 nItemId,const XubString & rText)1475 void StatusBar::SetHelpText( sal_uInt16 nItemId, const XubString& rText )
1476 {
1477     sal_uInt16 nPos = GetItemPos( nItemId );
1478 
1479     if ( nPos != STATUSBAR_ITEM_NOTFOUND )
1480         mpItemList->GetObject( nPos )->maHelpText = rText;
1481 }
1482 
1483 // -----------------------------------------------------------------------
1484 
GetHelpText(sal_uInt16 nItemId) const1485 const XubString& StatusBar::GetHelpText( sal_uInt16 nItemId ) const
1486 {
1487     sal_uInt16 nPos = GetItemPos( nItemId );
1488 
1489     if ( nPos != STATUSBAR_ITEM_NOTFOUND )
1490     {
1491         ImplStatusItem* pItem = mpItemList->GetObject( nPos );
1492         if ( !pItem->maHelpText.Len() && ( pItem->maHelpId.getLength() || pItem->maCommand.Len() ))
1493         {
1494             Help* pHelp = Application::GetHelp();
1495             if ( pHelp )
1496             {
1497                 if ( pItem->maCommand.Len() )
1498                     pItem->maHelpText = pHelp->GetHelpText( pItem->maCommand, this );
1499                 if ( !pItem->maHelpText.Len() && pItem->maHelpId.getLength() )
1500                     pItem->maHelpText = pHelp->GetHelpText( rtl::OStringToOUString( pItem->maHelpId, RTL_TEXTENCODING_UTF8 ), this );
1501             }
1502         }
1503 
1504         return pItem->maHelpText;
1505     }
1506     else
1507         return ImplGetSVEmptyStr();
1508 }
1509 
1510 // -----------------------------------------------------------------------
1511 
SetQuickHelpText(sal_uInt16 nItemId,const XubString & rText)1512 void StatusBar::SetQuickHelpText( sal_uInt16 nItemId, const XubString& rText )
1513 {
1514     sal_uInt16 nPos = GetItemPos( nItemId );
1515 
1516     if ( nPos != STATUSBAR_ITEM_NOTFOUND )
1517         mpItemList->GetObject( nPos )->maQuickHelpText = rText;
1518 }
1519 
1520 // -----------------------------------------------------------------------
1521 
GetQuickHelpText(sal_uInt16 nItemId) const1522 const XubString& StatusBar::GetQuickHelpText( sal_uInt16 nItemId ) const
1523 {
1524     sal_uInt16 nPos = GetItemPos( nItemId );
1525 
1526     if ( nPos != STATUSBAR_ITEM_NOTFOUND )
1527     {
1528         ImplStatusItem* pItem = mpItemList->GetObject( nPos );
1529         return pItem->maQuickHelpText;
1530     }
1531     else
1532         return ImplGetSVEmptyStr();
1533 }
1534 
1535 // -----------------------------------------------------------------------
1536 
SetHelpId(sal_uInt16 nItemId,const rtl::OString & rHelpId)1537 void StatusBar::SetHelpId( sal_uInt16 nItemId, const rtl::OString& rHelpId )
1538 {
1539     sal_uInt16 nPos = GetItemPos( nItemId );
1540 
1541     if ( nPos != STATUSBAR_ITEM_NOTFOUND )
1542         mpItemList->GetObject( nPos )->maHelpId = rHelpId;
1543 }
1544 
1545 // -----------------------------------------------------------------------
1546 
GetHelpId(sal_uInt16 nItemId) const1547 rtl::OString StatusBar::GetHelpId( sal_uInt16 nItemId ) const
1548 {
1549     sal_uInt16 nPos = GetItemPos( nItemId );
1550 
1551     rtl::OString aRet;
1552     if ( nPos != STATUSBAR_ITEM_NOTFOUND )
1553     {
1554         ImplStatusItem* pItem = mpItemList->GetObject( nPos );
1555         if ( pItem->maHelpId.getLength() )
1556             aRet = pItem->maHelpId;
1557         else
1558             aRet = ::rtl::OUStringToOString( pItem->maCommand, RTL_TEXTENCODING_UTF8 );
1559     }
1560 
1561     return aRet;
1562 }
1563 
1564 // -----------------------------------------------------------------------
1565 
ImplCalcBorder()1566 void StatusBar::ImplCalcBorder( )
1567 {
1568     mnCalcHeight = mnDY;
1569     // subtract border
1570     if( IsTopBorder() )
1571     {
1572         mnCalcHeight -= 2;
1573         mnTextY += 2;
1574         mnItemY += 2;
1575     }
1576     if ( IsBottomBorder() )
1577         mnCalcHeight -= 2;
1578     mbFormat = sal_True;
1579     Invalidate();
1580 }
1581 
SetBottomBorder(sal_Bool bBottomBorder)1582 void StatusBar::SetBottomBorder( sal_Bool bBottomBorder )
1583 {
1584     if ( mbBottomBorder != bBottomBorder )
1585     {
1586         mbBottomBorder = bBottomBorder;
1587         ImplCalcBorder();
1588     }
1589 }
1590 
SetTopBorder(sal_Bool bTopBorder)1591 void StatusBar::SetTopBorder( sal_Bool bTopBorder )
1592 {
1593     if ( mpImplData->mbTopBorder != static_cast<bool>(bTopBorder) )
1594     {
1595         mpImplData->mbTopBorder = static_cast<bool>(bTopBorder);
1596         ImplCalcBorder();
1597     }
1598 }
1599 
IsTopBorder() const1600 sal_Bool StatusBar::IsTopBorder() const
1601 {
1602     return mpImplData->mbTopBorder;
1603 }
1604 
1605 // -----------------------------------------------------------------------
1606 
StartProgressMode(const XubString & rText)1607 void StatusBar::StartProgressMode( const XubString& rText )
1608 {
1609     DBG_ASSERT( !mbProgressMode, "StatusBar::StartProgressMode(): progress mode is active" );
1610 
1611     mbProgressMode  = sal_True;
1612     mnPercent       = 0;
1613     maPrgsTxt       = rText;
1614 
1615     // Groessen berechnen
1616     ImplCalcProgressRect();
1617 
1618     // Paint ausloesen (dort wird der Text und der Frame gemalt)
1619     const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
1620     Color aPrgsColor = rStyleSettings.GetHighlightColor();
1621     if ( aPrgsColor == rStyleSettings.GetFaceColor() )
1622         aPrgsColor = rStyleSettings.GetDarkShadowColor();
1623     SetLineColor();
1624     SetFillColor( aPrgsColor );
1625     if ( IsReallyVisible() )
1626     {
1627         Invalidate();
1628         Update();
1629         Flush();
1630     }
1631 }
1632 
1633 // -----------------------------------------------------------------------
1634 
SetProgressValue(sal_uInt16 nNewPercent)1635 void StatusBar::SetProgressValue( sal_uInt16 nNewPercent )
1636 {
1637     DBG_ASSERT( mbProgressMode, "StatusBar::SetProgressValue(): no progrss mode" );
1638     DBG_ASSERTWARNING( nNewPercent <= 100, "StatusBar::SetProgressValue(): nPercent > 100" );
1639 
1640     if ( mbProgressMode
1641     &&   IsReallyVisible()
1642     &&   (!mnPercent || (mnPercent != nNewPercent)) )
1643     {
1644         Update();
1645         SetLineColor();
1646         ImplDrawProgress( sal_False, mnPercent, nNewPercent );
1647         Flush();
1648     }
1649     mnPercent = nNewPercent;
1650 }
1651 
1652 // -----------------------------------------------------------------------
1653 
EndProgressMode()1654 void StatusBar::EndProgressMode()
1655 {
1656     DBG_ASSERT( mbProgressMode, "StatusBar::EndProgressMode(): no progress mode" );
1657 
1658     mbProgressMode = sal_False;
1659     maPrgsTxt.Erase();
1660 
1661     // Paint neu ausloesen um StatusBar wieder herzustellen
1662     SetFillColor( GetSettings().GetStyleSettings().GetFaceColor() );
1663     if ( IsReallyVisible() )
1664     {
1665         Invalidate();
1666         Update();
1667         Flush();
1668     }
1669 }
1670 
1671 // -----------------------------------------------------------------------
1672 
ResetProgressMode()1673 void StatusBar::ResetProgressMode()
1674 {
1675     if ( mbProgressMode )
1676     {
1677         mnPercent = 0;
1678         maPrgsTxt.Erase();
1679         if ( IsReallyVisible() )
1680         {
1681             Invalidate();
1682             Update();
1683             Flush();
1684         }
1685     }
1686 }
1687 
1688 // -----------------------------------------------------------------------
1689 
SetText(const XubString & rText)1690 void StatusBar::SetText( const XubString& rText )
1691 {
1692     if ( (!mbVisibleItems || (GetStyle() & WB_RIGHT)) && !mbProgressMode &&
1693          IsReallyVisible() && IsUpdateMode() )
1694     {
1695         if ( mbFormat  )
1696         {
1697             Invalidate();
1698             Window::SetText( rText );
1699         }
1700         else
1701         {
1702             Update();
1703             long nOldTextWidth = GetTextWidth( GetText() );
1704             Window::SetText( rText );
1705             ImplDrawText( sal_True, nOldTextWidth );
1706             Flush();
1707         }
1708     }
1709     else if ( mbProgressMode )
1710     {
1711         maPrgsTxt = rText;
1712         if ( IsReallyVisible() )
1713         {
1714             Invalidate();
1715             Update();
1716             Flush();
1717         }
1718     }
1719     else
1720         Window::SetText( rText );
1721 }
1722 
1723 // -----------------------------------------------------------------------
1724 
CalcWindowSizePixel() const1725 Size StatusBar::CalcWindowSizePixel() const
1726 {
1727     sal_uLong   i = 0;
1728     sal_uLong   nCount = mpItemList->Count();
1729     long    nOffset = 0;
1730     long    nCalcWidth = (STATUSBAR_OFFSET_X*2);
1731     long    nCalcHeight;
1732 
1733     while ( i < nCount )
1734     {
1735         ImplStatusItem* pItem = mpItemList->GetObject( i );
1736         nCalcWidth += pItem->mnWidth + nOffset;
1737         nOffset = pItem->mnOffset;
1738         i++;
1739     }
1740 
1741     long nMinHeight = GetTextHeight();
1742     const long nBarTextOffset = STATUSBAR_OFFSET_TEXTY*2;
1743     long nProgressHeight = nMinHeight + nBarTextOffset;
1744     // FIXME: IsNativeControlSupported and GetNativeControlRegion should be const ?
1745     StatusBar* pThis = const_cast<StatusBar*>( this );
1746     if( pThis->IsNativeControlSupported( CTRL_PROGRESS, PART_ENTIRE_CONTROL ) )
1747     {
1748         ImplControlValue aValue;
1749         Rectangle aControlRegion( (const Point&)Point(), Size( nCalcWidth, nMinHeight ) );
1750         Rectangle aNativeControlRegion, aNativeContentRegion;
1751         if( pThis->GetNativeControlRegion( CTRL_PROGRESS, PART_ENTIRE_CONTROL, aControlRegion,
1752                                            CTRL_STATE_ENABLED, aValue, rtl::OUString(),
1753                                            aNativeControlRegion, aNativeContentRegion ) )
1754         {
1755             nProgressHeight = aNativeControlRegion.GetHeight();
1756         }
1757     }
1758 
1759     if( mpImplData->mbDrawItemFrames &&
1760         pThis->IsNativeControlSupported( CTRL_FRAME, PART_BORDER ) )
1761     {
1762         ImplControlValue aControlValue( FRAME_DRAW_NODRAW );
1763         Rectangle aBound, aContent;
1764         Rectangle aNatRgn( Point( 0, 0 ), Size( 150, 50 ) );
1765         if( pThis->GetNativeControlRegion(CTRL_FRAME, PART_BORDER,
1766             aNatRgn, 0, aControlValue, rtl::OUString(), aBound, aContent) )
1767         {
1768             mpImplData->mnItemBorderWidth =
1769                 ( aBound.GetHeight() - aContent.GetHeight() ) / 2;
1770         }
1771     }
1772 
1773     nCalcHeight = nMinHeight+nBarTextOffset + 2*mpImplData->mnItemBorderWidth;
1774     if( nCalcHeight < nProgressHeight+2 )
1775         nCalcHeight = nProgressHeight+2;
1776 
1777     // add border
1778     if( IsTopBorder() )
1779         nCalcHeight += 2;
1780     if ( IsBottomBorder() )
1781         nCalcHeight += 2;
1782 
1783     return Size( nCalcWidth, nCalcHeight );
1784 }
1785 
1786 
1787 // -----------------------------------------------------------------------
1788 
SetAccessibleName(sal_uInt16 nItemId,const XubString & rName)1789 void StatusBar::SetAccessibleName( sal_uInt16 nItemId, const XubString& rName )
1790 {
1791     sal_uInt16 nPos = GetItemPos( nItemId );
1792 
1793     if ( nPos != STATUSBAR_ITEM_NOTFOUND )
1794     {
1795         ImplStatusItem* pItem = mpItemList->GetObject( nPos );
1796 
1797         if ( pItem->maAccessibleName != rName )
1798         {
1799             pItem->maAccessibleName = rName;
1800             ImplCallEventListeners( VCLEVENT_STATUSBAR_NAMECHANGED, (void*) sal_IntPtr(pItem->mnId) );
1801         }
1802     }
1803 }
1804 
1805 // -----------------------------------------------------------------------
1806 
GetAccessibleName(sal_uInt16 nItemId) const1807 const XubString& StatusBar::GetAccessibleName( sal_uInt16 nItemId ) const
1808 {
1809     sal_uInt16 nPos = GetItemPos( nItemId );
1810 
1811     if ( nPos != STATUSBAR_ITEM_NOTFOUND )
1812         return mpItemList->GetObject( nPos )->maAccessibleName;
1813     else
1814         return ImplGetSVEmptyStr();
1815 }
1816 
1817 // -----------------------------------------------------------------------
1818