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