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