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