LibreOffice Module vcl (master)  1
status.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 
21 #include <sal/log.hxx>
22 #include <comphelper/string.hxx>
23 #include <vcl/event.hxx>
24 #include <vcl/decoview.hxx>
25 #include <vcl/svapp.hxx>
26 #include <vcl/help.hxx>
27 #include <vcl/vcllayout.hxx>
28 #include <vcl/status.hxx>
29 #include <vcl/virdev.hxx>
30 #include <vcl/settings.hxx>
31 #include <config_features.h>
32 #include <svdata.hxx>
33 #include <window.h>
34 
35 #define STATUSBAR_OFFSET_X STATUSBAR_OFFSET
36 #define STATUSBAR_OFFSET_Y 2
37 #define STATUSBAR_OFFSET_TEXTY 3
38 
39 #define STATUSBAR_PRGS_OFFSET 3
40 #define STATUSBAR_PRGS_COUNT 100
41 #define STATUSBAR_PRGS_MIN 5
42 
44 {
45 public:
46  ImplData();
47 
49 };
50 
52 {
53  mpVirDev = nullptr;
54 }
55 
57 {
58  sal_uInt16 mnId;
64  OUString maText;
65  OUString maHelpText;
66  OUString maQuickHelpText;
67  OString maHelpId;
68  void* mpUserData;
69  bool mbVisible;
70  OUString maAccessibleName;
71  OUString maCommand;
72  std::unique_ptr<SalLayout> mxLayoutCache;
73 };
74 
75 static tools::Long ImplCalcProgressWidth( sal_uInt16 nMax, tools::Long nSize )
76 {
77  return ((nMax*(nSize+(nSize/2)))-(nSize/2)+(STATUSBAR_PRGS_OFFSET*2));
78 }
79 
80 static Point ImplGetItemTextPos( const Size& rRectSize, const Size& rTextSize,
81  StatusBarItemBits nStyle )
82 {
83  tools::Long nX;
84  tools::Long nY;
85  tools::Long delta = (rTextSize.Height()/4) + 1;
86  if( delta + rTextSize.Width() > rRectSize.Width() )
87  delta = 0;
88 
89  if ( nStyle & StatusBarItemBits::Left )
90  nX = delta;
91  else if ( nStyle & StatusBarItemBits::Right )
92  nX = rRectSize.Width()-rTextSize.Width()-delta;
93  else // StatusBarItemBits::Center
94  nX = (rRectSize.Width()-rTextSize.Width())/2;
95  nY = (rRectSize.Height()-rTextSize.Height())/2 + 1;
96  return Point( nX, nY );
97 }
98 
100 {
101  return !mbProgressMode && IsReallyVisible() && IsUpdateMode();
102 }
103 
104 void StatusBar::ImplInit( vcl::Window* pParent, WinBits nStyle )
105 {
106  mpImplData.reset(new ImplData);
107 
108  // default: RightAlign
109  if ( !(nStyle & (WB_LEFT | WB_RIGHT)) )
110  nStyle |= WB_RIGHT;
111 
112  Window::ImplInit( pParent, nStyle & ~WB_BORDER, nullptr );
113 
114  // remember WinBits
115  mpImplData->mpVirDev = VclPtr<VirtualDevice>::Create( *this );
116  mnCurItemId = 0;
117  mbFormat = true;
118  mbProgressMode = false;
119  mbInUserDraw = false;
120  mbAdjustHiDPI = false;
122  mnDX = 0;
123  mnDY = 0;
124  mnCalcHeight = 0;
126 
128 
130 }
131 
134  mnLastProgressPaint_ms(osl_getGlobalTimer())
135 {
136  ImplInit( pParent, nStyle );
137 }
138 
140 {
141  disposeOnce();
142 }
143 
145 {
146  // delete all items
147  mvItemList.clear();
148 
149  // delete VirtualDevice
150  mpImplData->mpVirDev.disposeAndClear();
151  mpImplData.reset();
152  Window::dispose();
153 }
154 
156 {
157  mbAdjustHiDPI = true;
158 }
159 
161 {
162  rRenderContext.SetLineColor();
163 
164  const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
165  ApplyControlFont(rRenderContext, rStyleSettings.GetToolFont());
166 
167  Color aColor;
168  if (IsControlForeground())
169  aColor = GetControlForeground();
170  else if (GetStyle() & WB_3DLOOK)
171  aColor = rStyleSettings.GetButtonTextColor();
172  else
173  aColor = rStyleSettings.GetWindowTextColor();
174  rRenderContext.SetTextColor(aColor);
175 
176  rRenderContext.SetTextFillColor();
177 
178  if (IsControlBackground())
179  aColor = GetControlBackground();
180  else if (GetStyle() & WB_3DLOOK)
181  aColor = rStyleSettings.GetFaceColor();
182  else
183  aColor = rStyleSettings.GetWindowColor();
184  rRenderContext.SetBackground(aColor);
185 
186  // NWF background
187  if (!IsControlBackground() &&
189  {
192  }
193 }
194 
196 {
197  ApplySettings(*this);
198 
199  mpImplData->mpVirDev->SetFont(GetFont());
200  mpImplData->mpVirDev->SetTextColor(GetTextColor());
201  mpImplData->mpVirDev->SetTextAlign(GetTextAlign());
202  mpImplData->mpVirDev->SetTextFillColor();
203  mpImplData->mpVirDev->SetBackground(GetBackground());
204 }
205 
207 {
208  tools::Long nExtraWidth;
209  tools::Long nExtraWidth2;
210  tools::Long nX;
211  sal_uInt16 nAutoSizeItems;
212  bool bChanged;
213 
214  do {
215  // sum up widths
216  nAutoSizeItems = 0;
218  bChanged = false;
219  tools::Long nOffset = 0;
220  for ( const auto & pItem : mvItemList ) {
221  if ( pItem->mbVisible )
222  {
223  if ( pItem->mnBits & StatusBarItemBits::AutoSize ) {
224  nAutoSizeItems++;
225  }
226 
227  mnItemsWidth += pItem->mnWidth + nOffset;
228  nOffset = pItem->mnOffset;
229  }
230  }
231 
232  if ( mnDX > 0 && mnDX < mnItemsWidth )
233  {
234  // Total width of items is more than available width
235  // Try to hide secondary elements, if any
236  for ( auto & pItem : mvItemList )
237  {
238  if ( pItem->mbVisible && !(pItem->mnBits & StatusBarItemBits::Mandatory) )
239  {
240  pItem->mbVisible = false;
241  bChanged = true;
242  break;
243  }
244  }
245  }
246  else if ( mnDX > mnItemsWidth )
247  {
248  // Width of statusbar is sufficient.
249  // Try to restore hidden items, if any
250  for ( auto & pItem : mvItemList )
251  {
252  if ( !pItem->mbVisible &&
253  !(pItem->mnBits & StatusBarItemBits::Mandatory) &&
254  pItem->mnWidth + nOffset + mnItemsWidth < mnDX )
255  {
256  pItem->mbVisible = true;
257  bChanged = true;
258  break;
259  }
260  }
261  }
262  } while ( bChanged );
263 
264  if ( GetStyle() & WB_RIGHT )
265  {
266  // AutoSize isn't computed for right-alignment,
267  // because we show the text that is declared by SetText on the left side
268  nX = mnDX - mnItemsWidth;
269  nExtraWidth = 0;
270  nExtraWidth2 = 0;
271  }
272  else
273  {
275 
276  // calling AutoSize is potentially necessary for left-aligned text,
277  if ( nAutoSizeItems && (mnDX > (mnItemsWidth - STATUSBAR_OFFSET)) )
278  {
279  nExtraWidth = (mnDX - mnItemsWidth - 1) / nAutoSizeItems;
280  nExtraWidth2 = (mnDX - mnItemsWidth - 1) % nAutoSizeItems;
281  }
282  else
283  {
284  nExtraWidth = 0;
285  nExtraWidth2 = 0;
286  }
287  nX = STATUSBAR_OFFSET_X;
288 
289  if( HasMirroredGraphics() && IsRTLEnabled() )
291  }
292 
293  for (auto & pItem : mvItemList) {
294  if ( pItem->mbVisible ) {
295  if ( pItem->mnBits & StatusBarItemBits::AutoSize ) {
296  pItem->mnExtraWidth = nExtraWidth;
297  if ( nExtraWidth2 ) {
298  pItem->mnExtraWidth++;
299  nExtraWidth2--;
300  }
301  } else {
302  pItem->mnExtraWidth = 0;
303  }
304 
305  pItem->mnX = nX;
306  nX += pItem->mnWidth + pItem->mnExtraWidth + pItem->mnOffset;
307  }
308  }
309 
310  mbFormat = false;
311 }
312 
314 {
315  tools::Rectangle aRect;
316  ImplStatusItem* pItem = ( nPos < mvItemList.size() ) ? mvItemList[ nPos ].get() : nullptr;
317  if ( pItem && pItem->mbVisible )
318  {
319  aRect.SetLeft( pItem->mnX );
320  aRect.SetRight( aRect.Left() + pItem->mnWidth + pItem->mnExtraWidth );
321  aRect.SetTop( STATUSBAR_OFFSET_Y );
323  }
324 
325  return aRect;
326 }
327 
329 {
330  for( size_t nPos = 0; nPos < mvItemList.size(); nPos++ )
331  {
332  ImplStatusItem* pItem = mvItemList[ nPos ].get();
333  if ( pItem->mbVisible )
334  return sal_uInt16(nPos);
335  }
336 
337  return SAL_MAX_UINT16;
338 }
339 
341 {
342  // prevent item box from being overwritten
343  tools::Rectangle aTextRect;
344  aTextRect.SetLeft( STATUSBAR_OFFSET_X + 1 );
345  aTextRect.SetTop( mnTextY );
346  if (GetStyle() & WB_RIGHT)
347  aTextRect.SetRight( mnDX - mnItemsWidth - 1 );
348  else
349  aTextRect.SetRight( mnDX - 1 );
350  if (aTextRect.Right() > aTextRect.Left())
351  {
352  // compute position
353  OUString aStr = GetText();
354  sal_Int32 nPos = aStr.indexOf('\n');
355  if (nPos != -1)
356  aStr = aStr.copy(0, nPos);
357 
358  aTextRect.SetBottom( aTextRect.Top()+GetTextHeight()+1 );
359 
361  }
362 }
363 
364 void StatusBar::ImplDrawItem(vcl::RenderContext& rRenderContext, bool bOffScreen, sal_uInt16 nPos)
365 {
366  tools::Rectangle aRect = ImplGetItemRectPos(nPos);
367 
368  if (aRect.IsEmpty())
369  return;
370 
371  // compute output region
372  ImplStatusItem* pItem = mvItemList[nPos].get();
373  tools::Long nW = 1;
374  tools::Rectangle aTextRect(aRect.Left() + nW, aRect.Top() + nW,
375  aRect.Right() - nW, aRect.Bottom() - nW);
376 
377  Size aTextRectSize(aTextRect.GetSize());
378 
379  if (bOffScreen)
380  {
381  mpImplData->mpVirDev->SetOutputSizePixel(aTextRectSize);
382  }
383  else
384  {
385  vcl::Region aRegion(aTextRect);
386  rRenderContext.SetClipRegion(aRegion);
387  }
388 
389  // if the framework code is drawing status, let it do all the work
390  if (!(pItem->mnBits & StatusBarItemBits::UserDraw))
391  {
392  SalLayout* pLayoutCache = pItem->mxLayoutCache.get();
393 
394  if(!pLayoutCache)
395  {
396  // update cache
397  pItem->mxLayoutCache = rRenderContext.ImplLayout(pItem->maText, 0, -1);
398  pLayoutCache = pItem->mxLayoutCache.get();
399  }
400 
401  const SalLayoutGlyphs* pGlyphs = pLayoutCache ? pLayoutCache->GetGlyphs() : nullptr;
402  Size aTextSize(rRenderContext.GetTextWidth(pItem->maText,0,-1,nullptr,pGlyphs), rRenderContext.GetTextHeight());
403  Point aTextPos = ImplGetItemTextPos(aTextRectSize, aTextSize, pItem->mnBits);
404 
405  if (bOffScreen)
406  {
407  mpImplData->mpVirDev->DrawText(
408  aTextPos,
409  pItem->maText,
410  0, -1, nullptr, nullptr,
411  pGlyphs );
412  }
413  else
414  {
415  aTextPos.AdjustX(aTextRect.Left() );
416  aTextPos.AdjustY(aTextRect.Top() );
417  rRenderContext.DrawText(
418  aTextPos,
419  pItem->maText,
420  0, -1, nullptr, nullptr,
421  pGlyphs );
422  }
423  }
424 
425  // call DrawItem if necessary
426  if (pItem->mnBits & StatusBarItemBits::UserDraw)
427  {
428  if (bOffScreen)
429  {
430  mbInUserDraw = true;
431  mpImplData->mpVirDev->EnableRTL( IsRTLEnabled() );
432  UserDrawEvent aODEvt(this, mpImplData->mpVirDev, tools::Rectangle(Point(), aTextRectSize), pItem->mnId);
433  UserDraw(aODEvt);
434  mpImplData->mpVirDev->EnableRTL(false);
435  mbInUserDraw = false;
436  }
437  else
438  {
439  UserDrawEvent aODEvt(this, &rRenderContext, aTextRect, pItem->mnId);
440  UserDraw(aODEvt);
441  }
442  }
443 
444  if (bOffScreen)
445  rRenderContext.DrawOutDev(aTextRect.TopLeft(), aTextRectSize, Point(), aTextRectSize, *mpImplData->mpVirDev);
446  else
447  rRenderContext.SetClipRegion();
448 
449  if (nPos != ImplGetFirstVisiblePos())
450  {
451  // draw separator
452  Point aFrom(aRect.TopLeft());
453  aFrom.AdjustX( -4 );
454  aFrom.AdjustY( 1 );
455  Point aTo(aRect.BottomLeft());
456  aTo.AdjustX( -4 );
457  aTo.AdjustY( -1 );
458 
459  DecorationView aDecoView(&rRenderContext);
460  aDecoView.DrawSeparator(aFrom, aTo);
461  }
462 
463  if (!rRenderContext.ImplIsRecordLayout())
464  CallEventListeners(VclEventId::StatusbarDrawItem, reinterpret_cast<void*>(pItem->mnId));
465 }
466 
467 void DrawProgress(vcl::Window* pWindow, vcl::RenderContext& rRenderContext, const Point& rPos,
468  tools::Long nOffset, tools::Long nPrgsWidth, tools::Long nPrgsHeight,
469  sal_uInt16 nPercent1, sal_uInt16 nPercent2, sal_uInt16 nPercentCount,
470  const tools::Rectangle& rFramePosSize)
471 {
473  {
474  bool bNeedErase = ImplGetSVData()->maNWFData.mbProgressNeedsErase;
475 
476  tools::Long nFullWidth = (nPrgsWidth + nOffset) * (10000 / nPercentCount);
477  tools::Long nPerc = std::min<sal_uInt16>(nPercent2, 10000);
478  ImplControlValue aValue(nFullWidth * nPerc / 10000);
479  tools::Rectangle aDrawRect(rPos, Size(nFullWidth, nPrgsHeight));
480  tools::Rectangle aControlRegion(aDrawRect);
481 
482  if(bNeedErase)
483  {
484  vcl::Window* pEraseWindow = pWindow;
485  while (pEraseWindow->IsPaintTransparent() && !pEraseWindow->ImplGetWindowImpl()->mbFrame)
486  {
487  pEraseWindow = pEraseWindow->ImplGetWindowImpl()->mpParent;
488  }
489 
490  if (pEraseWindow == pWindow)
491  {
492  // restore background of pWindow
493  rRenderContext.Erase(rFramePosSize);
494  }
495  else
496  {
497  // restore transparent background
498  Point aTL(pWindow->OutputToAbsoluteScreenPixel(rFramePosSize.TopLeft()));
499  aTL = pEraseWindow->AbsoluteScreenToOutputPixel(aTL);
500  tools::Rectangle aRect(aTL, rFramePosSize.GetSize());
501  pEraseWindow->Invalidate(aRect, InvalidateFlags::NoChildren |
504  pEraseWindow->PaintImmediately();
505  }
506  rRenderContext.Push(PushFlags::CLIPREGION);
507  rRenderContext.IntersectClipRegion(rFramePosSize);
508  }
509 
510  bool bNativeOK = rRenderContext.DrawNativeControl(ControlType::Progress, ControlPart::Entire, aControlRegion,
511  ControlState::ENABLED, aValue, OUString());
512  if (bNeedErase)
513  rRenderContext.Pop();
514  if (bNativeOK)
515  return;
516  }
517 
518  // precompute values
519  sal_uInt16 nPerc1 = nPercent1 / nPercentCount;
520  sal_uInt16 nPerc2 = nPercent2 / nPercentCount;
521 
522  if (nPerc1 > nPerc2)
523  {
524  // support progress that can also decrease
525 
526  // compute rectangle
527  tools::Long nDX = nPrgsWidth + nOffset;
528  tools::Long nLeft = rPos.X() + ((nPerc1 - 1) * nDX);
529  tools::Rectangle aRect(nLeft, rPos.Y(), nLeft + nPrgsWidth, rPos.Y() + nPrgsHeight);
530 
531  do
532  {
533  rRenderContext.Erase(aRect);
534  aRect.AdjustLeft( -nDX );
535  aRect.AdjustRight( -nDX );
536  nPerc1--;
537  }
538  while (nPerc1 > nPerc2);
539  }
540  else if (nPerc1 < nPerc2)
541  {
542  // draw Percent rectangle
543  // if Percent2 greater than 100%, adapt values
544  if (nPercent2 > 10000)
545  {
546  nPerc2 = 10000 / nPercentCount;
547  if (nPerc1 >= nPerc2)
548  nPerc1 = nPerc2 - 1;
549  }
550 
551  // compute rectangle
552  tools::Long nDX = nPrgsWidth + nOffset;
553  tools::Long nLeft = rPos.X() + (nPerc1 * nDX);
554  tools::Rectangle aRect(nLeft, rPos.Y(), nLeft + nPrgsWidth, rPos.Y() + nPrgsHeight);
555 
556  do
557  {
558  rRenderContext.DrawRect(aRect);
559  aRect.AdjustLeft(nDX );
560  aRect.AdjustRight(nDX );
561  nPerc1++;
562  }
563  while (nPerc1 < nPerc2);
564 
565  // if greater than 100%, set rectangle to blink
566  if (nPercent2 > 10000)
567  {
568  // define on/off status
569  if (((nPercent2 / nPercentCount) & 0x01) == (nPercentCount & 0x01))
570  {
571  aRect.AdjustLeft( -nDX );
572  aRect.AdjustRight( -nDX );
573  rRenderContext.Erase(aRect);
574  }
575  }
576  }
577 }
578 
579 void StatusBar::ImplDrawProgress(vcl::RenderContext& rRenderContext, sal_uInt16 nPercent2)
580 {
582  // bPaint: draw text also, else only update progress
583  rRenderContext.DrawText(maPrgsTxtPos, maPrgsTxt);
584  if (!bNative)
585  {
586  DecorationView aDecoView(&rRenderContext);
588  }
589 
592  tools::Long nPrgsHeight = mnPrgsSize;
593  if (bNative)
594  {
595  aPos = maPrgsFrameRect.TopLeft();
596  nPrgsHeight = maPrgsFrameRect.GetHeight();
597  }
598  DrawProgress(this, rRenderContext, aPos, mnPrgsSize / 2, mnPrgsSize, nPrgsHeight,
599  0, nPercent2 * 100, mnPercentCount, maPrgsFrameRect);
600 }
601 
603 {
604  // calculate text size
605  Size aPrgsTxtSize( GetTextWidth( maPrgsTxt ), GetTextHeight() );
607 
608  // calculate progress frame
612 
613  // calculate size of progress rects
615  sal_uInt16 nMaxPercent = STATUSBAR_PRGS_COUNT;
616 
617  tools::Long nMaxWidth = mnDX-STATUSBAR_OFFSET-1;
618 
619  // make smaller if there are too many rects
620  while ( maPrgsFrameRect.Left()+ImplCalcProgressWidth( nMaxPercent, mnPrgsSize ) > nMaxWidth )
621  {
622  nMaxPercent--;
623  if ( nMaxPercent <= STATUSBAR_PRGS_MIN )
624  break;
625  }
627 
628  // save the divisor for later
629  mnPercentCount = 10000 / nMaxPercent;
630  bool bNativeOK = false;
632  {
633  ImplControlValue aValue;
635  tools::Rectangle aNativeControlRegion, aNativeContentRegion;
636  if( (bNativeOK = GetNativeControlRegion( ControlType::Progress, ControlPart::Entire, aControlRegion,
637  ControlState::ENABLED, aValue,
638  aNativeControlRegion, aNativeContentRegion ) ) )
639  {
640  tools::Long nProgressHeight = aNativeControlRegion.GetHeight();
641  if( nProgressHeight > maPrgsFrameRect.GetHeight() )
642  {
643  tools::Long nDelta = nProgressHeight - maPrgsFrameRect.GetHeight();
644  maPrgsFrameRect.AdjustTop( -(nDelta - nDelta/2) );
645  maPrgsFrameRect.AdjustBottom(nDelta/2 );
646  }
647  maPrgsTxtPos.setY( maPrgsFrameRect.Top() + (nProgressHeight - GetTextHeight())/2 );
648  }
649  }
650  if( ! bNativeOK )
651  maPrgsTxtPos.setY( mnTextY );
652 }
653 
655 {
656  // trigger toolbox only for left mouse button
657  if ( !rMEvt.IsLeft() )
658  return;
659 
660  Point aMousePos = rMEvt.GetPosPixel();
661 
662  // search for clicked item
663  for ( size_t i = 0; i < mvItemList.size(); ++i )
664  {
665  ImplStatusItem* pItem = mvItemList[ i ].get();
666  // check item for being clicked
667  if ( ImplGetItemRectPos( sal_uInt16(i) ).IsInside( aMousePos ) )
668  {
669  mnCurItemId = pItem->mnId;
670  if ( rMEvt.GetClicks() == 2 )
671  DoubleClick();
672  else
673  Click();
674  mnCurItemId = 0;
675 
676  // Item found
677  return;
678  }
679  }
680 
681  // if there's no item, trigger Click or DoubleClick
682  if ( rMEvt.GetClicks() == 2 )
683  DoubleClick();
684  else
685  Click();
686 }
687 
688 void StatusBar::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
689 {
690  if (mbFormat)
691  ImplFormat();
692 
693  sal_uInt16 nItemCount = sal_uInt16( mvItemList.size() );
694 
695  if (mbProgressMode)
696  {
698 
699  const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
700  Color aProgressColor = rStyleSettings.GetHighlightColor();
701  if (aProgressColor == rStyleSettings.GetFaceColor())
702  aProgressColor = rStyleSettings.GetDarkShadowColor();
703  rRenderContext.SetLineColor();
704  rRenderContext.SetFillColor(aProgressColor);
705 
706  ImplDrawProgress(rRenderContext, mnPercent);
707 
708  rRenderContext.Pop();
709  }
710  else
711  {
712  // draw text
713  if (GetStyle() & WB_RIGHT)
714  ImplDrawText(rRenderContext);
715 
716  // draw items
717 
718  // Do offscreen only when we are not recording layout...
719  bool bOffscreen = !rRenderContext.ImplIsRecordLayout();
720 
721  if (!bOffscreen)
722  rRenderContext.Erase(rRect);
723 
724  for (sal_uInt16 i = 0; i < nItemCount; i++)
725  ImplDrawItem(rRenderContext, bOffscreen, i);
726  }
727 
728  // draw line at the top of the status bar (to visually distinguish it from
729  // shell / docking area)
730  const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
731  rRenderContext.SetLineColor(rStyleSettings.GetShadowColor());
732  rRenderContext.DrawLine(Point(0, 0), Point(mnDX-1, 0));
733 }
734 
736 {
737  // save width and height
738  Size aSize = GetOutputSizePixel();
740  mnDY = aSize.Height();
741  mnCalcHeight = mnDY;
742 
744 
745  // provoke re-formatting
746  mbFormat = true;
747 
748  if ( mbProgressMode )
750 
751  Invalidate();
752 }
753 
754 void StatusBar::RequestHelp( const HelpEvent& rHEvt )
755 {
756  // no keyboard help in status bar
757  if( rHEvt.KeyboardActivated() )
758  return;
759 
760  sal_uInt16 nItemId = GetItemId( ScreenToOutputPixel( rHEvt.GetMousePosPixel() ) );
761 
762  if ( nItemId )
763  {
764  tools::Rectangle aItemRect = GetItemRect( nItemId );
765  Point aPt = OutputToScreenPixel( aItemRect.TopLeft() );
766  aItemRect.SetLeft( aPt.X() );
767  aItemRect.SetTop( aPt.Y() );
768  aPt = OutputToScreenPixel( aItemRect.BottomRight() );
769  aItemRect.SetRight( aPt.X() );
770  aItemRect.SetBottom( aPt.Y() );
771 
772  if ( rHEvt.GetMode() & HelpEventMode::BALLOON )
773  {
774  OUString aStr = GetHelpText( nItemId );
775  Help::ShowBalloon( this, aItemRect.Center(), aItemRect, aStr );
776  return;
777  }
778  else if ( rHEvt.GetMode() & HelpEventMode::QUICK )
779  {
780  OUString aStr(GetQuickHelpText(nItemId));
781  // show quickhelp if available
782  if (!aStr.isEmpty())
783  {
784  Help::ShowQuickHelp( this, aItemRect, aStr );
785  return;
786  }
787  aStr = GetItemText( nItemId );
788  // show a quick help if item text doesn't fit
789  if ( GetTextWidth( aStr ) > aItemRect.GetWidth() )
790  {
791  Help::ShowQuickHelp( this, aItemRect, aStr );
792  return;
793  }
794  }
795  }
796 
797  Window::RequestHelp( rHEvt );
798 }
799 
801 {
802  Window::StateChanged( nType );
803 
804  if ( nType == StateChangedType::InitShow )
805  ImplFormat();
806  else if ( nType == StateChangedType::UpdateMode )
807  Invalidate();
808  else if ( (nType == StateChangedType::Zoom) ||
809  (nType == StateChangedType::ControlFont) )
810  {
811  mbFormat = true;
813  Invalidate();
814  }
815  else if ( nType == StateChangedType::ControlForeground )
816  {
818  Invalidate();
819  }
820  else if ( nType == StateChangedType::ControlBackground )
821  {
823  Invalidate();
824  }
825 
826  //invalidate layout cache
827  for (auto & pItem : mvItemList)
828  {
829  pItem->mxLayoutCache.reset();
830  }
831 
832 }
833 
835 {
836  Window::DataChanged( rDCEvt );
837 
838  if ( !((rDCEvt.GetType() == DataChangedEventType::DISPLAY )
839  || (rDCEvt.GetType() == DataChangedEventType::FONTS )
841  || ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS)
842  && (rDCEvt.GetFlags() & AllSettingsFlags::STYLE )
843  ))
844  )
845  return;
846 
847  mbFormat = true;
849  tools::Long nFudge = GetTextHeight() / 4;
850  for (auto & pItem : mvItemList)
851  {
852  tools::Long nWidth = GetTextWidth( pItem->maText ) + nFudge;
853  if( nWidth > pItem->mnWidth + STATUSBAR_OFFSET )
854  pItem->mnWidth = nWidth + STATUSBAR_OFFSET;
855 
856  pItem->mxLayoutCache.reset();
857  }
858  Size aSize = GetSizePixel();
859  // do not disturb current width, since
860  // CalcWindowSizePixel calculates a minimum width
861  aSize.setHeight( CalcWindowSizePixel().Height() );
862  SetSizePixel( aSize );
863  Invalidate();
864 }
865 
867 {
868  maClickHdl.Call( this );
869 }
870 
872 {
873  maDoubleClickHdl.Call( this );
874 }
875 
877 {
878 }
879 
880 void StatusBar::InsertItem( sal_uInt16 nItemId, sal_uLong nWidth,
881  StatusBarItemBits nBits,
882  tools::Long nOffset, sal_uInt16 nPos )
883 {
884  SAL_WARN_IF( !nItemId, "vcl", "StatusBar::InsertItem(): ItemId == 0" );
885  SAL_WARN_IF( GetItemPos( nItemId ) != STATUSBAR_ITEM_NOTFOUND, "vcl",
886  "StatusBar::InsertItem(): ItemId already exists" );
887 
888  // default: IN and CENTER
890  nBits |= StatusBarItemBits::In;
892  nBits |= StatusBarItemBits::Center;
893 
894  // create item
895  if (mbAdjustHiDPI)
896  {
897  nWidth *= GetDPIScaleFactor();
898  }
899  tools::Long nFudge = GetTextHeight()/4;
900  std::unique_ptr<ImplStatusItem> pItem(new ImplStatusItem);
901  pItem->mnId = nItemId;
902  pItem->mnBits = nBits;
903  pItem->mnWidth = static_cast<tools::Long>(nWidth)+nFudge+STATUSBAR_OFFSET;
904  pItem->mnOffset = nOffset;
905  pItem->mpUserData = nullptr;
906  pItem->mbVisible = true;
907 
908  // add item to list
909  if ( nPos < mvItemList.size() ) {
910  mvItemList.insert( mvItemList.begin() + nPos, std::move(pItem) );
911  } else {
912  mvItemList.push_back( std::move(pItem) );
913  }
914 
915  mbFormat = true;
916  if ( ImplIsItemUpdate() )
917  Invalidate();
918 
919  CallEventListeners( VclEventId::StatusbarItemAdded, reinterpret_cast<void*>(nItemId) );
920 }
921 
922 void StatusBar::RemoveItem( sal_uInt16 nItemId )
923 {
924  sal_uInt16 nPos = GetItemPos( nItemId );
925  if ( nPos != STATUSBAR_ITEM_NOTFOUND )
926  {
927  mvItemList.erase( mvItemList.begin() + nPos );
928 
929  mbFormat = true;
930  if ( ImplIsItemUpdate() )
931  Invalidate();
932 
933  CallEventListeners( VclEventId::StatusbarItemRemoved, reinterpret_cast<void*>(nItemId) );
934  }
935 }
936 
937 void StatusBar::ShowItem( sal_uInt16 nItemId )
938 {
939  sal_uInt16 nPos = GetItemPos( nItemId );
940 
941  if ( nPos == STATUSBAR_ITEM_NOTFOUND )
942  return;
943 
944  ImplStatusItem* pItem = mvItemList[ nPos ].get();
945  if ( !pItem->mbVisible )
946  {
947  pItem->mbVisible = true;
948 
949  mbFormat = true;
950  if ( ImplIsItemUpdate() )
951  Invalidate();
952 
953  CallEventListeners( VclEventId::StatusbarShowItem, reinterpret_cast<void*>(nItemId) );
954  }
955 }
956 
957 void StatusBar::HideItem( sal_uInt16 nItemId )
958 {
959  sal_uInt16 nPos = GetItemPos( nItemId );
960 
961  if ( nPos == STATUSBAR_ITEM_NOTFOUND )
962  return;
963 
964  ImplStatusItem* pItem = mvItemList[ nPos ].get();
965  if ( pItem->mbVisible )
966  {
967  pItem->mbVisible = false;
968 
969  mbFormat = true;
970  if ( ImplIsItemUpdate() )
971  Invalidate();
972 
973  CallEventListeners( VclEventId::StatusbarHideItem, reinterpret_cast<void*>(nItemId) );
974  }
975 }
976 
977 bool StatusBar::IsItemVisible( sal_uInt16 nItemId ) const
978 {
979  sal_uInt16 nPos = GetItemPos( nItemId );
980 
981  if ( nPos != STATUSBAR_ITEM_NOTFOUND )
982  return mvItemList[ nPos ]->mbVisible;
983  else
984  return false;
985 }
986 
988 {
989  // delete all items
990  mvItemList.clear();
991 
992  mbFormat = true;
993  if ( ImplIsItemUpdate() )
994  Invalidate();
995 
997 }
998 
999 sal_uInt16 StatusBar::GetItemCount() const
1000 {
1001  return static_cast<sal_uInt16>(mvItemList.size());
1002 }
1003 
1004 sal_uInt16 StatusBar::GetItemId( sal_uInt16 nPos ) const
1005 {
1006  if ( nPos < mvItemList.size() )
1007  return mvItemList[ nPos ]->mnId;
1008  return 0;
1009 }
1010 
1011 sal_uInt16 StatusBar::GetItemPos( sal_uInt16 nItemId ) const
1012 {
1013  for ( size_t i = 0, n = mvItemList.size(); i < n; ++i ) {
1014  if ( mvItemList[ i ]->mnId == nItemId ) {
1015  return sal_uInt16( i );
1016  }
1017  }
1018 
1019  return STATUSBAR_ITEM_NOTFOUND;
1020 }
1021 
1022 sal_uInt16 StatusBar::GetItemId( const Point& rPos ) const
1023 {
1024  if ( !mbFormat )
1025  {
1026  sal_uInt16 nItemCount = GetItemCount();
1027  sal_uInt16 nPos;
1028  for ( nPos = 0; nPos < nItemCount; nPos++ )
1029  {
1030  // get rectangle
1031  tools::Rectangle aRect = ImplGetItemRectPos( nPos );
1032  if ( aRect.IsInside( rPos ) )
1033  return mvItemList[ nPos ]->mnId;
1034  }
1035  }
1036 
1037  return 0;
1038 }
1039 
1040 tools::Rectangle StatusBar::GetItemRect( sal_uInt16 nItemId ) const
1041 {
1042  tools::Rectangle aRect;
1043 
1044  if ( !mbFormat )
1045  {
1046  sal_uInt16 nPos = GetItemPos( nItemId );
1047  if ( nPos != STATUSBAR_ITEM_NOTFOUND )
1048  {
1049  // get rectangle and subtract frame
1050  aRect = ImplGetItemRectPos( nPos );
1051  tools::Long nW = 1;
1052  aRect.AdjustTop(nW-1 );
1053  aRect.AdjustBottom( -(nW-1) );
1054  aRect.AdjustLeft(nW );
1055  aRect.AdjustRight( -nW );
1056  return aRect;
1057  }
1058  }
1059 
1060  return aRect;
1061 }
1062 
1063 Point StatusBar::GetItemTextPos( sal_uInt16 nItemId ) const
1064 {
1065  if ( !mbFormat )
1066  {
1067  sal_uInt16 nPos = GetItemPos( nItemId );
1068  if ( nPos != STATUSBAR_ITEM_NOTFOUND )
1069  {
1070  // get rectangle
1071  ImplStatusItem* pItem = mvItemList[ nPos ].get();
1072  tools::Rectangle aRect = ImplGetItemRectPos( nPos );
1073  tools::Long nW = 1;
1074  tools::Rectangle aTextRect( aRect.Left()+nW, aRect.Top()+nW,
1075  aRect.Right()-nW, aRect.Bottom()-nW );
1076  Point aPos = ImplGetItemTextPos( aTextRect.GetSize(),
1077  Size( GetTextWidth( pItem->maText ), GetTextHeight() ),
1078  pItem->mnBits );
1079  if ( !mbInUserDraw )
1080  {
1081  aPos.AdjustX(aTextRect.Left() );
1082  aPos.AdjustY(aTextRect.Top() );
1083  }
1084  return aPos;
1085  }
1086  }
1087 
1088  return Point();
1089 }
1090 
1091 sal_uLong StatusBar::GetItemWidth( sal_uInt16 nItemId ) const
1092 {
1093  sal_uInt16 nPos = GetItemPos( nItemId );
1094 
1095  if ( nPos != STATUSBAR_ITEM_NOTFOUND )
1096  return mvItemList[ nPos ]->mnWidth;
1097 
1098  return 0;
1099 }
1100 
1101 StatusBarItemBits StatusBar::GetItemBits( sal_uInt16 nItemId ) const
1102 {
1103  sal_uInt16 nPos = GetItemPos( nItemId );
1104 
1105  if ( nPos != STATUSBAR_ITEM_NOTFOUND )
1106  return mvItemList[ nPos ]->mnBits;
1107 
1108  return StatusBarItemBits::NONE;
1109 }
1110 
1111 tools::Long StatusBar::GetItemOffset( sal_uInt16 nItemId ) const
1112 {
1113  sal_uInt16 nPos = GetItemPos( nItemId );
1114 
1115  if ( nPos != STATUSBAR_ITEM_NOTFOUND )
1116  return mvItemList[ nPos ]->mnOffset;
1117 
1118  return 0;
1119 }
1120 
1121 void StatusBar::SetItemText( sal_uInt16 nItemId, const OUString& rText, int nCharsWidth )
1122 {
1123  sal_uInt16 nPos = GetItemPos( nItemId );
1124 
1125  if ( nPos == STATUSBAR_ITEM_NOTFOUND )
1126  return;
1127 
1128  ImplStatusItem* pItem = mvItemList[ nPos ].get();
1129 
1130  if ( pItem->maText == rText )
1131  return;
1132 
1133  pItem->maText = rText;
1134 
1135  // adjust item width - see also DataChanged()
1136  tools::Long nFudge = GetTextHeight()/4;
1137 
1138  tools::Long nWidth;
1139  if (nCharsWidth != -1)
1140  {
1141  std::unique_ptr<SalLayout> pSalLayout = ImplLayout("0",0,-1);
1142  const SalLayoutGlyphs* pGlyphs = pSalLayout ? pSalLayout->GetGlyphs() : nullptr;
1143  nWidth = GetTextWidth("0",0,-1,nullptr,pGlyphs );
1144  nWidth = nWidth * nCharsWidth + nFudge;
1145  }
1146  else
1147  {
1148  std::unique_ptr<SalLayout> pSalLayout = ImplLayout(pItem->maText,0,-1);
1149  const SalLayoutGlyphs* pGlyphs = pSalLayout ? pSalLayout->GetGlyphs() : nullptr;
1150  nWidth = GetTextWidth( pItem->maText,0,-1,nullptr,pGlyphs ) + nFudge;
1151  // Store the calculated layout.
1152  pItem->mxLayoutCache = std::move(pSalLayout);
1153  }
1154 
1155  if( (nWidth > pItem->mnWidth + STATUSBAR_OFFSET) ||
1156  ((nWidth < pItem->mnWidth) && (mnDX - STATUSBAR_OFFSET) < mnItemsWidth ))
1157  {
1158  pItem->mnWidth = nWidth + STATUSBAR_OFFSET;
1159  ImplFormat();
1160  Invalidate();
1161  }
1162 
1163  // re-draw item if StatusBar is visible and UpdateMode active
1164  if ( pItem->mbVisible && !mbFormat && ImplIsItemUpdate() )
1165  {
1166  tools::Rectangle aRect = ImplGetItemRectPos(nPos);
1167  Invalidate(aRect);
1168  PaintImmediately();
1169  }
1170 }
1171 
1172 const OUString& StatusBar::GetItemText( sal_uInt16 nItemId ) const
1173 {
1174  sal_uInt16 nPos = GetItemPos( nItemId );
1175 
1176  assert( nPos != STATUSBAR_ITEM_NOTFOUND );
1177 
1178  return mvItemList[ nPos ]->maText;
1179 }
1180 
1181 void StatusBar::SetItemCommand( sal_uInt16 nItemId, const OUString& rCommand )
1182 {
1183  sal_uInt16 nPos = GetItemPos( nItemId );
1184 
1185  if ( nPos != STATUSBAR_ITEM_NOTFOUND )
1186  {
1187  ImplStatusItem* pItem = mvItemList[ nPos ].get();
1188 
1189  if ( pItem->maCommand != rCommand )
1190  pItem->maCommand = rCommand;
1191  }
1192 }
1193 
1194 OUString StatusBar::GetItemCommand( sal_uInt16 nItemId )
1195 {
1196  sal_uInt16 nPos = GetItemPos( nItemId );
1197 
1198  if ( nPos != STATUSBAR_ITEM_NOTFOUND )
1199  return mvItemList[ nPos ]->maCommand;
1200 
1201  return OUString();
1202 }
1203 
1204 void StatusBar::SetItemData( sal_uInt16 nItemId, void* pNewData )
1205 {
1206  sal_uInt16 nPos = GetItemPos( nItemId );
1207 
1208  if ( nPos == STATUSBAR_ITEM_NOTFOUND )
1209  return;
1210 
1211  ImplStatusItem* pItem = mvItemList[ nPos ].get();
1212  // invalidate cache
1213  pItem->mxLayoutCache.reset();
1214  pItem->mpUserData = pNewData;
1215 
1216  // call Draw-Item if it's a User-Item
1217  if ( (pItem->mnBits & StatusBarItemBits::UserDraw) && pItem->mbVisible &&
1218  !mbFormat && ImplIsItemUpdate() )
1219  {
1220  tools::Rectangle aRect = ImplGetItemRectPos(nPos);
1222  PaintImmediately();
1223  }
1224 }
1225 
1226 void* StatusBar::GetItemData( sal_uInt16 nItemId ) const
1227 {
1228  sal_uInt16 nPos = GetItemPos( nItemId );
1229 
1230  if ( nPos != STATUSBAR_ITEM_NOTFOUND )
1231  return mvItemList[ nPos ]->mpUserData;
1232 
1233  return nullptr;
1234 }
1235 
1236 void StatusBar::RedrawItem(sal_uInt16 nItemId)
1237 {
1238  if ( mbFormat )
1239  return;
1240 
1241  sal_uInt16 nPos = GetItemPos(nItemId);
1242  if ( nPos == STATUSBAR_ITEM_NOTFOUND )
1243  return;
1244 
1245  ImplStatusItem* pItem = mvItemList[ nPos ].get();
1246  if ((pItem->mnBits & StatusBarItemBits::UserDraw) &&
1247  pItem->mbVisible && ImplIsItemUpdate())
1248  {
1249  tools::Rectangle aRect = ImplGetItemRectPos(nPos);
1250  Invalidate(aRect);
1251  PaintImmediately();
1252  }
1253 }
1254 
1255 void StatusBar::SetHelpText( sal_uInt16 nItemId, const OUString& rText )
1256 {
1257  sal_uInt16 nPos = GetItemPos( nItemId );
1258 
1259  if ( nPos != STATUSBAR_ITEM_NOTFOUND )
1260  mvItemList[ nPos ]->maHelpText = rText;
1261 }
1262 
1263 const OUString& StatusBar::GetHelpText( sal_uInt16 nItemId ) const
1264 {
1265  sal_uInt16 nPos = GetItemPos( nItemId );
1266 
1267  assert ( nPos != STATUSBAR_ITEM_NOTFOUND );
1268 
1269  ImplStatusItem* pItem = mvItemList[ nPos ].get();
1270  if ( pItem->maHelpText.isEmpty() && ( !pItem->maHelpId.isEmpty() || !pItem->maCommand.isEmpty() ))
1271  {
1272  Help* pHelp = Application::GetHelp();
1273  if ( pHelp )
1274  {
1275  if ( !pItem->maCommand.isEmpty() )
1276  pItem->maHelpText = pHelp->GetHelpText( pItem->maCommand, this );
1277  if ( pItem->maHelpText.isEmpty() && !pItem->maHelpId.isEmpty() )
1278  pItem->maHelpText = pHelp->GetHelpText( OStringToOUString( pItem->maHelpId, RTL_TEXTENCODING_UTF8 ), this );
1279  }
1280  }
1281 
1282  return pItem->maHelpText;
1283 }
1284 
1285 void StatusBar::SetQuickHelpText( sal_uInt16 nItemId, const OUString& rText )
1286 {
1287  sal_uInt16 nPos = GetItemPos( nItemId );
1288 
1289  if ( nPos != STATUSBAR_ITEM_NOTFOUND )
1290  mvItemList[ nPos ]->maQuickHelpText = rText;
1291 }
1292 
1293 const OUString& StatusBar::GetQuickHelpText( sal_uInt16 nItemId ) const
1294 {
1295  sal_uInt16 nPos = GetItemPos( nItemId );
1296 
1297  assert ( nPos != STATUSBAR_ITEM_NOTFOUND );
1298 
1299  ImplStatusItem* pItem = mvItemList[ nPos ].get();
1300  return pItem->maQuickHelpText;
1301 }
1302 
1303 void StatusBar::SetHelpId( sal_uInt16 nItemId, const OString& rHelpId )
1304 {
1305  sal_uInt16 nPos = GetItemPos( nItemId );
1306 
1307  if ( nPos != STATUSBAR_ITEM_NOTFOUND )
1308  mvItemList[ nPos ]->maHelpId = rHelpId;
1309 }
1310 
1311 void StatusBar::StartProgressMode( const OUString& rText )
1312 {
1313  SAL_WARN_IF( mbProgressMode, "vcl", "StatusBar::StartProgressMode(): progress mode is active" );
1314 
1315  mbProgressMode = true;
1316  mnPercent = 0;
1317  maPrgsTxt = rText;
1318 
1319  // compute size
1321 
1322  // trigger Paint, which draws text and frame
1323  if ( IsReallyVisible() )
1324  {
1325  Invalidate();
1326  PaintImmediately();
1327  }
1328 }
1329 
1330 void StatusBar::SetProgressValue( sal_uInt16 nNewPercent )
1331 {
1332  SAL_WARN_IF( !mbProgressMode, "vcl", "StatusBar::SetProgressValue(): no progress mode" );
1333  SAL_WARN_IF( nNewPercent > 100, "vcl", "StatusBar::SetProgressValue(): nPercent > 100" );
1334 
1335  bool bInvalidate = mbProgressMode && IsReallyVisible() && (!mnPercent || (mnPercent != nNewPercent));
1336 
1337  mnPercent = nNewPercent;
1338 
1339  if (bInvalidate)
1340  {
1341  // Rate limit how often we paint, otherwise in some loading scenarios we can spend significant
1342  // time just painting progress bars.
1343  sal_uInt32 nTime_ms = osl_getGlobalTimer();
1344  if ((nTime_ms - mnLastProgressPaint_ms) > 100)
1345  {
1347  PaintImmediately();
1348  mnLastProgressPaint_ms = nTime_ms;
1349  }
1350  }
1351 }
1352 
1354 {
1355  SAL_WARN_IF( !mbProgressMode, "vcl", "StatusBar::EndProgressMode(): no progress mode" );
1356 
1357  mbProgressMode = false;
1358  maPrgsTxt.clear();
1359 
1360  if ( IsReallyVisible() )
1361  {
1362  Invalidate();
1363  PaintImmediately();
1364  }
1365 }
1366 
1367 void StatusBar::SetText(const OUString& rText)
1368 {
1370  {
1371  if (mbFormat)
1372  {
1373  Invalidate();
1374  Window::SetText(rText);
1375  }
1376  else
1377  {
1378  Invalidate();
1379  Window::SetText(rText);
1380  PaintImmediately();
1381  }
1382  }
1383  else if (mbProgressMode)
1384  {
1385  maPrgsTxt = rText;
1386  if (IsReallyVisible())
1387  {
1388  Invalidate();
1389  PaintImmediately();
1390  }
1391  }
1392  else
1393  {
1394  Window::SetText(rText);
1395  }
1396 }
1397 
1399 {
1400  size_t i = 0;
1401  size_t nCount = mvItemList.size();
1402  tools::Long nOffset = 0;
1403  tools::Long nCalcWidth = STATUSBAR_OFFSET_X*2;
1404  tools::Long nCalcHeight;
1405 
1406  while ( i < nCount )
1407  {
1408  ImplStatusItem* pItem = mvItemList[ i ].get();
1409  nCalcWidth += pItem->mnWidth + nOffset;
1410  nOffset = pItem->mnOffset;
1411  i++;
1412  }
1413 
1414  tools::Long nMinHeight = GetTextHeight();
1415  const tools::Long nBarTextOffset = STATUSBAR_OFFSET_TEXTY*2;
1416  tools::Long nProgressHeight = nMinHeight + nBarTextOffset;
1417 
1419  {
1420  ImplControlValue aValue;
1421  tools::Rectangle aControlRegion( Point(), Size( nCalcWidth, nMinHeight ) );
1422  tools::Rectangle aNativeControlRegion, aNativeContentRegion;
1424  aControlRegion, ControlState::ENABLED, aValue,
1425  aNativeControlRegion, aNativeContentRegion ) )
1426  {
1427  nProgressHeight = aNativeControlRegion.GetHeight();
1428  }
1429  }
1430 
1431  nCalcHeight = nMinHeight+nBarTextOffset;
1432  if( nCalcHeight < nProgressHeight+2 )
1433  nCalcHeight = nProgressHeight+2;
1434 
1435  return Size( nCalcWidth, nCalcHeight );
1436 }
1437 
1438 void StatusBar::SetAccessibleName( sal_uInt16 nItemId, const OUString& rName )
1439 {
1440  sal_uInt16 nPos = GetItemPos( nItemId );
1441 
1442  if ( nPos != STATUSBAR_ITEM_NOTFOUND )
1443  {
1444  ImplStatusItem* pItem = mvItemList[ nPos ].get();
1445 
1446  if ( pItem->maAccessibleName != rName )
1447  {
1448  pItem->maAccessibleName = rName;
1449  CallEventListeners( VclEventId::StatusbarNameChanged, reinterpret_cast<void*>(pItem->mnId) );
1450  }
1451  }
1452 }
1453 
1454 const OUString& StatusBar::GetAccessibleName( sal_uInt16 nItemId ) const
1455 {
1456  sal_uInt16 nPos = GetItemPos( nItemId );
1457 
1458  assert ( nPos != STATUSBAR_ITEM_NOTFOUND );
1459 
1460  return mvItemList[ nPos ]->maAccessibleName;
1461 }
1462 
1463 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Point TopLeft() const
const Color & GetTextColor() const
Definition: outdev.hxx:1136
void DrawText(const Point &rStartPt, const OUString &rStr, sal_Int32 nIndex=0, sal_Int32 nLen=-1, MetricVector *pVector=nullptr, OUString *pDisplayText=nullptr, const SalLayoutGlyphs *pLayoutCache=nullptr)
Definition: text.cxx:791
const Color & GetShadowColor() const
SAL_DLLPRIVATE void ImplDrawText(vcl::RenderContext &rRenderContext)
Definition: status.cxx:340
bool IsControlBackground() const
Definition: window2.cxx:1085
const Wallpaper & GetBackground() const
Definition: outdev.hxx:647
void * GetItemData(sal_uInt16 nItemId) const
Definition: status.cxx:1226
OUString maHelpText
Definition: status.cxx:65
void RedrawItem(sal_uInt16 nItemId)
Definition: status.cxx:1236
tools::Rectangle maPrgsFrameRect
Definition: status.hxx:72
SAL_DLLPRIVATE bool ImplIsRecordLayout() const
Definition: outdev.cxx:632
SAL_DLLPRIVATE sal_uInt16 ImplGetFirstVisiblePos() const
Definition: status.cxx:328
tools::Long AdjustRight(tools::Long nHorzMoveDelta)
The parent window is invalidated, too.
bool GetNativeControlRegion(ControlType nType, ControlPart nPart, const tools::Rectangle &rControlRegion, ControlState nState, const ImplControlValue &aValue, tools::Rectangle &rNativeBoundingRegion, tools::Rectangle &rNativeContentRegion) const
Query the native control's actual drawing region (including adornment)
void StartProgressMode(const OUString &rText)
Definition: status.cxx:1311
sal_uInt16 mnId
Definition: status.cxx:58
Definition: help.hxx:60
static Help * GetHelp()
Gets the application's help.
Definition: svapp.cxx:1360
Point BottomLeft() const
tools::Long mnWidth
Definition: status.cxx:60
#define STATUSBAR_PRGS_OFFSET
Definition: status.cxx:39
int mnStatusBarLowerRightOffset
Definition: svdata.hxx:311
Point AbsoluteScreenToOutputPixel(const Point &rPos) const
Definition: window.cxx:2854
sal_uIntPtr sal_uLong
long Long
tools::Long mnX
Definition: status.cxx:63
const StyleSettings & GetStyleSettings() const
TextAlign GetTextAlign() const
Definition: outdev.hxx:1154
const Color & GetFaceColor() const
const OUString & GetItemText(sal_uInt16 nItemId) const
Definition: status.cxx:1172
const OUString & GetHelpText() const
Definition: window.cxx:3082
void DrawFrame(const tools::Rectangle &rRect, const Color &rLeftTopColor, const Color &rRightBottomColor)
Definition: decoview.cxx:837
ImplSVNWFData maNWFData
Definition: svdata.hxx:397
sal_Int64 n
const OUString & GetQuickHelpText() const
Definition: window2.cxx:1230
OUString GetItemCommand(sal_uInt16 nItemId)
Definition: status.cxx:1194
virtual Size GetSizePixel() const
Definition: window.cxx:2394
virtual void SetSizePixel(const Size &rNewSize)
Definition: window2.cxx:1260
WinBits const WB_RIGHT
void SetItemText(sal_uInt16 nItemId, const OUString &rText, int nCharsWidth=-1)
Definition: status.cxx:1121
SAL_DLLPRIVATE WindowImpl * ImplGetWindowImpl() const
Definition: window.hxx:563
void SetTextFillColor()
Definition: text.cxx:697
tools::Long GetWidth() const
DataChangedEventType GetType() const
Definition: event.hxx:356
void IntersectClipRegion(const tools::Rectangle &rRect)
The area is invalidated regardless of overlapping child windows.
Size CalcWindowSizePixel() const
Definition: status.cxx:1398
const Color & GetControlBackground() const
Definition: window2.cxx:1080
bool IsItemVisible(sal_uInt16 nItemId) const
Definition: status.cxx:977
tools::Long mnDY
Definition: status.hxx:76
virtual ~StatusBar() override
Definition: status.cxx:139
sal_uInt16 mnId
Link< StatusBar *, void > maDoubleClickHdl
Definition: status.hxx:88
tools::Long mnItemsWidth
Definition: status.hxx:74
void PaintImmediately()
Definition: paint.cxx:1282
bool IsNativeControlSupported(ControlType nType, ControlPart nPart) const
Query the platform layer for control support.
HelpEventMode GetMode() const
Definition: event.hxx:205
#define STATUSBAR_OFFSET_Y
Definition: status.cxx:36
void AdjustItemWidthsForHiDPI()
Definition: status.cxx:155
void SetRight(tools::Long v)
const Color & GetHighlightColor() const
The invalidated area is painted with the background color/pattern.
virtual void MouseButtonDown(const MouseEvent &rMEvt) override
Definition: status.cxx:654
bool IsEmpty() const
OUString maCommand
Definition: status.cxx:71
void SetHelpText(sal_uInt16 nItemId, const OUString &rText)
Definition: status.cxx:1255
StateChangedType
Definition: window.hxx:317
tools::Long mnDX
Definition: status.hxx:75
virtual void Paint(vcl::RenderContext &rRenderContext, const tools::Rectangle &rRect) override
Definition: status.cxx:688
OUString GetAccessibleName() const
sal_uInt16 GetClicks() const
Definition: event.hxx:123
sal_Int64 WinBits
void SetBackground()
SAL_DLLPRIVATE void ImplDrawProgress(vcl::RenderContext &rRenderContext, sal_uInt16 nNewPerc)
Definition: status.cxx:579
#define STATUSBAR_PRGS_MIN
Definition: status.cxx:41
SAL_DLLPRIVATE void ImplDrawItem(vcl::RenderContext &rRenderContext, bool bOffScreen, sal_uInt16 nPos)
Definition: status.cxx:364
tools::Long Left() const
void SetLeft(tools::Long v)
#define SAL_MAX_UINT16
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
#define STATUSBAR_PRGS_COUNT
Definition: status.cxx:40
const vcl::Font & GetFont() const
Definition: outdev.hxx:653
tools::Rectangle GetItemRect(sal_uInt16 nItemId) const
Definition: status.cxx:1040
bool IsControlForeground() const
Definition: window2.cxx:1075
void SetItemData(sal_uInt16 nItemId, void *pNewData)
Definition: status.cxx:1204
Environment aTo
int nCount
AllSettingsFlags GetFlags() const
Definition: event.hxx:357
bool mbVisible
Definition: status.cxx:69
tools::Long Bottom() const
virtual void DataChanged(const DataChangedEvent &rDCEvt) override
Definition: status.cxx:834
void Click()
Definition: status.cxx:866
sal_uInt16 mnPercentCount
Definition: status.hxx:81
virtual void SetOutputSizePixel(const Size &rNewSize)
Definition: window2.cxx:1272
virtual OUString GetText() const
Definition: window.cxx:3047
virtual void UserDraw(const UserDrawEvent &rUDEvt)
Definition: status.cxx:876
tools::Long mnCalcHeight
Definition: status.hxx:77
tools::Long AdjustBottom(tools::Long nVertMoveDelta)
void DrawLine(const Point &rStartPt, const Point &rEndPt)
Definition: line.cxx:88
static tools::Long ImplCalcProgressWidth(sal_uInt16 nMax, tools::Long nSize)
Definition: status.cxx:75
void DrawRect(const tools::Rectangle &rRect)
Definition: rect.cxx:51
tools::Long GetItemOffset(sal_uInt16 nItemId) const
Definition: status.cxx:1111
SAL_DLLPRIVATE bool ImplIsItemUpdate()
Definition: status.cxx:99
const Color & GetControlForeground() const
Definition: window2.cxx:1070
const Point & GetMousePosPixel() const
Definition: event.hxx:204
sal_uInt16 GetItemCount() const
Definition: status.cxx:999
Point GetItemTextPos(sal_uInt16 nItemId) const
Definition: status.cxx:1063
#define STATUSBAR_ITEM_NOTFOUND
Definition: status.hxx:60
Point BottomRight() const
const Color & GetDarkShadowColor() const
bool mbFrame
Definition: window.h:317
ImplSVData * ImplGetSVData()
Definition: svdata.cxx:74
void EndProgressMode()
Definition: status.cxx:1353
void SetLineColor()
virtual OUString GetHelpText(const OUString &aHelpURL, const vcl::Window *pWindow)
Definition: help.cxx:67
virtual void dispose() override
This is intended to be used to clear any locally held references to other Window-subclass objects...
Definition: status.cxx:144
bool IsRTLEnabled() const
Definition: outdev.hxx:1364
Window(WindowType nType)
Definition: window.cxx:91
void DoubleClick()
Definition: status.cxx:871
SAL_DLLPRIVATE tools::Rectangle ImplGetItemRectPos(sal_uInt16 nPos) const
Definition: status.cxx:313
int i
const vcl::Font & GetToolFont() const
OUString maText
Definition: status.cxx:64
OUString maQuickHelpText
Definition: status.cxx:66
OUString maAccessibleName
Definition: status.cxx:70
bool mbInUserDraw
Definition: status.hxx:85
SAL_DLLPRIVATE void ImplInitSettings()
Definition: status.cxx:195
virtual void Invalidate(InvalidateFlags nFlags=InvalidateFlags::NONE)
Definition: paint.cxx:1158
bool IsUpdateMode() const
Definition: window2.cxx:1171
void SetFillColor()
tools::Long Width() const
Some things multiple-inherit from VclAbstractDialog and OutputDevice, so we need to use virtual inher...
Definition: outdev.hxx:303
bool mbFormat
Definition: status.hxx:83
sal_uInt32 mnLastProgressPaint_ms
Definition: status.hxx:82
void SetTextColor(const Color &rColor)
Definition: text.cxx:662
StatusBar(vcl::Window *pParent, WinBits nWinStyle=WB_BORDER|WB_RIGHT)
Definition: status.cxx:132
bool IsInside(const Point &rPOINT) const
bool DrawNativeControl(ControlType nType, ControlPart nPart, const tools::Rectangle &rControlRegion, ControlState nState, const ImplControlValue &aValue, const OUString &aCaption, const Color &rBackgroundColor=COL_AUTO)
Request rendering of a particular control and/or part.
void SetTop(tools::Long v)
void SetBottom(tools::Long v)
const AllSettings & GetSettings() const
Definition: outdev.hxx:418
Size GetOutputSizePixel() const
Definition: outdev.hxx:441
bool mbAdjustHiDPI
Definition: status.hxx:86
virtual void Resize() override
Definition: status.cxx:735
void HideItem(sal_uInt16 nItemId)
Definition: status.cxx:957
void RemoveItem(sal_uInt16 nItemId)
Definition: status.cxx:922
void SetAccessibleName(sal_uInt16 nItemId, const OUString &rName)
Definition: status.cxx:1438
std::vector< std::unique_ptr< ImplStatusItem > > mvItemList
Definition: status.hxx:68
tools::Long Top() const
OUString maPrgsTxt
Definition: status.hxx:70
virtual void StateChanged(StateChangedType nType) override
Definition: status.cxx:800
Point ScreenToOutputPixel(const Point &rPos) const
Definition: window.cxx:2801
bool KeyboardActivated() const
Definition: event.hxx:206
ControlPart mnNativeBackground
Definition: window.h:296
static void ShowQuickHelp(vcl::Window *pParent, const tools::Rectangle &rScreenRect, const OUString &rHelpText, QuickHelpFlags nStyle=QuickHelpFlags::NONE)
Definition: help.cxx:180
WinBits const WB_LEFT
Point OutputToAbsoluteScreenPixel(const Point &rPos) const
Definition: window.cxx:2844
void DrawSeparator(const Point &rStart, const Point &rStop, bool bVertical=true)
Definition: decoview.cxx:1010
void SetItemCommand(sal_uInt16 nItemId, const OUString &rCommand)
Definition: status.cxx:1181
Size GetSize() const
std::unique_ptr< SalLayout > ImplLayout(const OUString &, sal_Int32 nIndex, sal_Int32 nLen, const Point &rLogicPos=Point(0, 0), tools::Long nLogicWidth=0, const tools::Long *pLogicDXArray=nullptr, SalLayoutFlags flags=SalLayoutFlags::NONE, vcl::TextLayoutCache const *=nullptr, const SalLayoutGlyphs *pGlyphs=nullptr) const
Definition: text.cxx:1241
float GetDPIScaleFactor() const
Definition: outdev.hxx:518
void * mpUserData
Definition: status.cxx:68
StatusBarItemBits GetItemBits(sal_uInt16 nItemId) const
Definition: status.cxx:1101
tools::Long AdjustTop(tools::Long nVertMoveDelta)
void SetProgressValue(sal_uInt16 nPercent)
Definition: status.cxx:1330
StatusBarItemBits
Definition: status.hxx:42
#define STATUSBAR_OFFSET_TEXTY
Definition: status.cxx:37
WinBits const WB_3DLOOK
virtual void ApplySettings(vcl::RenderContext &rRenderContext) override
Definition: status.cxx:160
sal_uLong GetItemWidth(sal_uInt16 nItemId) const
Definition: status.cxx:1091
tools::Long mnOffset
Definition: status.cxx:61
Point maPrgsTxtPos
Definition: status.hxx:71
SAL_DLLPRIVATE void ImplCalcProgressRect()
Definition: status.cxx:602
VclPtr< VirtualDevice > mpVirDev
Definition: status.cxx:48
void SetQuickHelpText(sal_uInt16 nItemId, const OUString &rText)
Definition: status.cxx:1285
void Erase()
Definition: wallpaper.cxx:103
void SetText(const OUString &rText) override
Definition: status.cxx:1367
sal_uInt16 GetItemPos(sal_uInt16 nItemId) const
Definition: status.cxx:1011
WindowType
const Color & GetButtonTextColor() const
#define SAL_WARN_IF(condition, area, stream)
WinBits const WB_BORDER
bool mbProgressNeedsErase
Definition: svdata.hxx:326
#define STATUSBAR_OFFSET_X
Definition: status.cxx:35
void ShowItem(sal_uInt16 nItemId)
Definition: status.cxx:937
OString maHelpId
Definition: status.cxx:67
tools::Long GetTextHeight() const
Height where any character of the current font fits; in logic coordinates.
Definition: text.cxx:891
void EnableChildTransparentMode(bool bEnable=true)
Definition: window2.cxx:1020
bool IsLeft() const
Definition: event.hxx:146
virtual void RequestHelp(const HelpEvent &rHEvt) override
Definition: status.cxx:754
double mnWidth
static VclPtr< reference_type > Create(Arg &&...arg)
A construction helper for VclPtr.
Definition: vclptr.hxx:127
tools::Long mnExtraWidth
Definition: status.cxx:62
StatusBarItemBits mnBits
Definition: status.cxx:59
VclPtr< vcl::Window > mpParent
Definition: window.h:232
tools::Long GetTextWidth(const OUString &rStr, sal_Int32 nIndex=0, sal_Int32 nLen=-1, vcl::TextLayoutCache const *=nullptr, SalLayoutGlyphs const *const pLayoutCache=nullptr) const
Width of the text.
Definition: text.cxx:880
tools::Long Height() const
const Color & GetWindowColor() const
void SetHelpId(sal_uInt16 nItemId, const OString &rHelpId)
Definition: status.cxx:1303
const Point & GetPosPixel() const
Definition: event.hxx:120
virtual void DrawOutDev(const Point &rDestPt, const Size &rDestSize, const Point &rSrcPt, const Size &rSrcSize)
Definition: outdev.cxx:345
std::unique_ptr< ImplData > mpImplData
Definition: status.hxx:69
Link< StatusBar *, void > maClickHdl
Definition: status.hxx:87
void setHeight(tools::Long nHeight)
tools::Long GetHeight() const
sal_uInt16 GetItemId(sal_uInt16 nPos) const
Definition: status.cxx:1004
Event to pass information for UserDraw() handling eg. in comboboxes.
Definition: event.hxx:218
bool IsPaintTransparent() const
Definition: window2.cxx:1035
tools::Long AdjustLeft(tools::Long nHorzMoveDelta)
Environment aFrom
WinBits GetStyle() const
Definition: window2.cxx:951
void ApplyControlFont(vcl::RenderContext &rRenderContext, const vcl::Font &rDefaultFont)
Definition: window2.cxx:447
tools::Long mnPrgsSize
Definition: status.hxx:73
Point OutputToScreenPixel(const Point &rPos) const
Definition: window.cxx:2795
void CallEventListeners(VclEventId nEvent, void *pData=nullptr)
Definition: event.cxx:216
bool IsReallyVisible() const
Definition: window2.cxx:1105
SAL_DLLPRIVATE void ImplInit(vcl::Window *pParent, WinBits nStyle)
Definition: status.cxx:104
virtual const SalLayoutGlyphs * GetGlyphs() const
Definition: sallayout.cxx:1579
void DrawProgress(vcl::Window *pWindow, vcl::RenderContext &rRenderContext, const Point &rPos, tools::Long nOffset, tools::Long nPrgsWidth, tools::Long nPrgsHeight, sal_uInt16 nPercent1, sal_uInt16 nPercent2, sal_uInt16 nPercentCount, const tools::Rectangle &rFramePosSize)
Definition: status.cxx:467
void Push(PushFlags nFlags=PushFlags::ALL)
Definition: outdevstate.cxx:59
The child windows are not invalidated.
void Clear()
Definition: status.cxx:987
tools::Long mnTextY
Definition: status.hxx:78
sal_uInt16 mnPercent
Definition: status.hxx:80
aStr
bool mbProgressMode
Definition: status.hxx:84
const Color & GetWindowTextColor() const
tools::Long Right() const
static Point ImplGetItemTextPos(const Size &rRectSize, const Size &rTextSize, StatusBarItemBits nStyle)
Definition: status.cxx:80
#define STATUSBAR_OFFSET
Definition: status.hxx:61
Point Center() const
std::unique_ptr< SalLayout > mxLayoutCache
Definition: status.cxx:72
sal_uInt16 nPos
bool HasMirroredGraphics() const override
sal_uInt16 mnCurItemId
Definition: status.hxx:79
static void ShowBalloon(vcl::Window *pParent, const Point &rScreenPos, const tools::Rectangle &, const OUString &rHelpText)
Definition: help.cxx:157
SAL_DLLPRIVATE void ImplFormat()
Definition: status.cxx:206
void InsertItem(sal_uInt16 nItemId, sal_uLong nWidth, StatusBarItemBits nBits=StatusBarItemBits::Center|StatusBarItemBits::In, tools::Long nOffset=STATUSBAR_OFFSET, sal_uInt16 nPos=STATUSBAR_APPEND)
Definition: status.cxx:880