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