File: | home/maarten/src/libreoffice/core/vcl/source/window/status.cxx |
Warning: | line 452, column 17 Use of memory after it is freed |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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_OPENGL1 | ||||||
33 | #include <vcl/opengl/OpenGLWrapper.hxx> | ||||||
34 | #endif | ||||||
35 | #include <svdata.hxx> | ||||||
36 | #include <window.h> | ||||||
37 | |||||||
38 | #define STATUSBAR_OFFSET_X(long(5)) STATUSBAR_OFFSET(long(5)) | ||||||
39 | #define STATUSBAR_OFFSET_Y2 2 | ||||||
40 | #define STATUSBAR_OFFSET_TEXTY3 3 | ||||||
41 | |||||||
42 | #define STATUSBAR_PRGS_OFFSET3 3 | ||||||
43 | #define STATUSBAR_PRGS_COUNT100 100 | ||||||
44 | #define STATUSBAR_PRGS_MIN5 5 | ||||||
45 | |||||||
46 | class StatusBar::ImplData | ||||||
47 | { | ||||||
48 | public: | ||||||
49 | ImplData(); | ||||||
50 | |||||||
51 | VclPtr<VirtualDevice> mpVirDev; | ||||||
52 | }; | ||||||
53 | |||||||
54 | StatusBar::ImplData::ImplData() | ||||||
55 | { | ||||||
56 | mpVirDev = nullptr; | ||||||
57 | } | ||||||
58 | |||||||
59 | struct ImplStatusItem | ||||||
60 | { | ||||||
61 | sal_uInt16 mnId; | ||||||
62 | StatusBarItemBits mnBits; | ||||||
63 | long mnWidth; | ||||||
64 | long mnOffset; | ||||||
65 | long mnExtraWidth; | ||||||
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_OFFSET3*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 | |||||||
102 | bool StatusBar::ImplIsItemUpdate() | ||||||
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; | ||||||
124 | mnItemsWidth = STATUSBAR_OFFSET_X(long(5)); | ||||||
125 | mnDX = 0; | ||||||
126 | mnDY = 0; | ||||||
127 | mnCalcHeight = 0; | ||||||
128 | mnTextY = STATUSBAR_OFFSET_TEXTY3; | ||||||
129 | |||||||
130 | ImplInitSettings(); | ||||||
131 | |||||||
132 | SetOutputSizePixel( CalcWindowSizePixel() ); | ||||||
133 | } | ||||||
134 | |||||||
135 | StatusBar::StatusBar( vcl::Window* pParent, WinBits nStyle ) : | ||||||
136 | Window( WindowType::STATUSBAR ), | ||||||
137 | mnLastProgressPaint_ms(osl_getGlobalTimer()) | ||||||
138 | { | ||||||
139 | ImplInit( pParent, nStyle ); | ||||||
140 | } | ||||||
141 | |||||||
142 | StatusBar::~StatusBar() | ||||||
143 | { | ||||||
144 | disposeOnce(); | ||||||
145 | } | ||||||
146 | |||||||
147 | void StatusBar::dispose() | ||||||
148 | { | ||||||
149 | // delete all items | ||||||
150 | mvItemList.clear(); | ||||||
151 | |||||||
152 | // delete VirtualDevice | ||||||
153 | mpImplData->mpVirDev.disposeAndClear(); | ||||||
154 | mpImplData.reset(); | ||||||
155 | Window::dispose(); | ||||||
156 | } | ||||||
157 | |||||||
158 | void StatusBar::AdjustItemWidthsForHiDPI() | ||||||
159 | { | ||||||
160 | mbAdjustHiDPI = true; | ||||||
161 | } | ||||||
162 | |||||||
163 | void StatusBar::ApplySettings(vcl::RenderContext& rRenderContext) | ||||||
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() && | ||||||
191 | rRenderContext.IsNativeControlSupported(ControlType::WindowBackground, ControlPart::BackgroundWindow)) | ||||||
192 | { | ||||||
193 | ImplGetWindowImpl()->mnNativeBackground = ControlPart::BackgroundWindow; | ||||||
194 | EnableChildTransparentMode(); | ||||||
195 | } | ||||||
196 | } | ||||||
197 | |||||||
198 | void StatusBar::ImplInitSettings() | ||||||
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 | |||||||
209 | void StatusBar::ImplFormat() | ||||||
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; | ||||||
220 | mnItemsWidth = STATUSBAR_OFFSET_X(long(5)); | ||||||
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 | { | ||||||
277 | mnItemsWidth += STATUSBAR_OFFSET_X(long(5)); | ||||||
278 | |||||||
279 | // calling AutoSize is potentially necessary for left-aligned text, | ||||||
280 | if ( nAutoSizeItems && (mnDX > (mnItemsWidth - STATUSBAR_OFFSET(long(5)))) ) | ||||||
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(long(5)); | ||||||
291 | |||||||
292 | if( HasMirroredGraphics() && IsRTLEnabled() ) | ||||||
293 | nX += ImplGetSVData()->maNWFData.mnStatusBarLowerRightOffset; | ||||||
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 | |||||||
316 | tools::Rectangle StatusBar::ImplGetItemRectPos( sal_uInt16 nPos ) const | ||||||
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_Y2 ); | ||||||
325 | aRect.SetBottom( mnCalcHeight - STATUSBAR_OFFSET_Y2 ); | ||||||
326 | } | ||||||
327 | |||||||
328 | return aRect; | ||||||
329 | } | ||||||
330 | |||||||
331 | sal_uInt16 StatusBar::ImplGetFirstVisiblePos() const | ||||||
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((sal_uInt16) 0xFFFF); | ||||||
341 | } | ||||||
342 | |||||||
343 | void StatusBar::ImplDrawText(vcl::RenderContext& rRenderContext) | ||||||
344 | { | ||||||
345 | // prevent item box from being overwritten | ||||||
346 | tools::Rectangle aTextRect; | ||||||
347 | aTextRect.SetLeft( STATUSBAR_OFFSET_X(long(5)) + 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 | |||||||
363 | rRenderContext.DrawText(aTextRect, aStr, DrawTextFlags::Left | DrawTextFlags::Top | DrawTextFlags::Clip | DrawTextFlags::EndEllipsis); | ||||||
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 | { | ||||||
475 | if (rRenderContext.IsNativeControlSupported(ControlType::Progress, ControlPart::Entire)) | ||||||
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 | | ||||||
505 | InvalidateFlags::NoClipChildren | | ||||||
506 | InvalidateFlags::Transparent); | ||||||
507 | pEraseWindow->PaintImmediately(); | ||||||
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 | { | ||||||
584 | bool bNative = rRenderContext.IsNativeControlSupported(ControlType::Progress, ControlPart::Entire); | ||||||
585 | // bPaint: draw text also, else only update progress | ||||||
586 | rRenderContext.DrawText(maPrgsTxtPos, maPrgsTxt); | ||||||
587 | if (!bNative) | ||||||
588 | { | ||||||
589 | DecorationView aDecoView(&rRenderContext); | ||||||
590 | aDecoView.DrawFrame(maPrgsFrameRect, DrawFrameStyle::In); | ||||||
591 | } | ||||||
592 | |||||||
593 | Point aPos(maPrgsFrameRect.Left() + STATUSBAR_PRGS_OFFSET3, | ||||||
594 | maPrgsFrameRect.Top() + STATUSBAR_PRGS_OFFSET3); | ||||||
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 | |||||||
605 | void StatusBar::ImplCalcProgressRect() | ||||||
606 | { | ||||||
607 | // calculate text size | ||||||
608 | Size aPrgsTxtSize( GetTextWidth( maPrgsTxt ), GetTextHeight() ); | ||||||
609 | maPrgsTxtPos.setX( STATUSBAR_OFFSET_X(long(5))+1 ); | ||||||
610 | |||||||
611 | // calculate progress frame | ||||||
612 | maPrgsFrameRect.SetLeft( maPrgsTxtPos.X()+aPrgsTxtSize.Width()+STATUSBAR_OFFSET(long(5)) ); | ||||||
613 | maPrgsFrameRect.SetTop( STATUSBAR_OFFSET_Y2 ); | ||||||
614 | maPrgsFrameRect.SetBottom( mnCalcHeight - STATUSBAR_OFFSET_Y2 ); | ||||||
615 | |||||||
616 | // calculate size of progress rects | ||||||
617 | mnPrgsSize = maPrgsFrameRect.Bottom()-maPrgsFrameRect.Top()-(STATUSBAR_PRGS_OFFSET3*2); | ||||||
618 | sal_uInt16 nMaxPercent = STATUSBAR_PRGS_COUNT100; | ||||||
619 | |||||||
620 | long nMaxWidth = mnDX-STATUSBAR_OFFSET(long(5))-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_MIN5 ) | ||||||
627 | break; | ||||||
628 | } | ||||||
629 | maPrgsFrameRect.SetRight( maPrgsFrameRect.Left() + ImplCalcProgressWidth( nMaxPercent, mnPrgsSize ) ); | ||||||
630 | |||||||
631 | // save the divisor for later | ||||||
632 | mnPercentCount = 10000 / nMaxPercent; | ||||||
633 | bool bNativeOK = false; | ||||||
634 | if( IsNativeControlSupported( ControlType::Progress, ControlPart::Entire ) ) | ||||||
635 | { | ||||||
636 | ImplControlValue aValue; | ||||||
637 | tools::Rectangle aControlRegion( tools::Rectangle( Point(), maPrgsFrameRect.GetSize() ) ); | ||||||
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 ) | ||||||
654 | maPrgsTxtPos.setY( mnTextY ); | ||||||
655 | } | ||||||
656 | |||||||
657 | void StatusBar::MouseButtonDown( const MouseEvent& rMEvt ) | ||||||
658 | { | ||||||
659 | // trigger toolbox only for left mouse button | ||||||
660 | if ( !rMEvt.IsLeft() ) | ||||||
661 | return; | ||||||
662 | |||||||
663 | Point aMousePos = rMEvt.GetPosPixel(); | ||||||
664 | |||||||
665 | // search for clicked item | ||||||
666 | for ( size_t i = 0; i < mvItemList.size(); ++i ) | ||||||
667 | { | ||||||
668 | ImplStatusItem* pItem = mvItemList[ i ].get(); | ||||||
669 | // check item for being clicked | ||||||
670 | if ( ImplGetItemRectPos( sal_uInt16(i) ).IsInside( aMousePos ) ) | ||||||
671 | { | ||||||
672 | mnCurItemId = pItem->mnId; | ||||||
673 | if ( rMEvt.GetClicks() == 2 ) | ||||||
674 | DoubleClick(); | ||||||
675 | else | ||||||
676 | Click(); | ||||||
677 | mnCurItemId = 0; | ||||||
678 | |||||||
679 | // Item found | ||||||
680 | return; | ||||||
681 | } | ||||||
682 | } | ||||||
683 | |||||||
684 | // if there's no item, trigger Click or DoubleClick | ||||||
685 | if ( rMEvt.GetClicks() == 2 ) | ||||||
686 | DoubleClick(); | ||||||
687 | else | ||||||
688 | Click(); | ||||||
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 | { | ||||||
700 | rRenderContext.Push(PushFlags::FILLCOLOR | PushFlags::LINECOLOR); | ||||||
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_OPENGL1 | ||||||
727 | if( OpenGLWrapper::isVCLOpenGLEnabled() ) | ||||||
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 | |||||||
745 | void StatusBar::Resize() | ||||||
746 | { | ||||||
747 | // save width and height | ||||||
748 | Size aSize = GetOutputSizePixel(); | ||||||
749 | mnDX = aSize.Width() - ImplGetSVData()->maNWFData.mnStatusBarLowerRightOffset; | ||||||
750 | mnDY = aSize.Height(); | ||||||
751 | mnCalcHeight = mnDY; | ||||||
752 | |||||||
753 | mnTextY = (mnCalcHeight-GetTextHeight())/2; | ||||||
754 | |||||||
755 | // provoke re-formatting | ||||||
756 | mbFormat = true; | ||||||
757 | |||||||
758 | if ( mbProgressMode ) | ||||||
759 | ImplCalcProgressRect(); | ||||||
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 | |||||||
810 | void StatusBar::StateChanged( StateChangedType nType ) | ||||||
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; | ||||||
822 | ImplInitSettings(); | ||||||
823 | Invalidate(); | ||||||
824 | } | ||||||
825 | else if ( nType == StateChangedType::ControlForeground ) | ||||||
826 | { | ||||||
827 | ImplInitSettings(); | ||||||
828 | Invalidate(); | ||||||
829 | } | ||||||
830 | else if ( nType == StateChangedType::ControlBackground ) | ||||||
831 | { | ||||||
832 | ImplInitSettings(); | ||||||
833 | Invalidate(); | ||||||
834 | } | ||||||
835 | |||||||
836 | //invalidate layout cache | ||||||
837 | for (auto & pItem : mvItemList) | ||||||
838 | { | ||||||
839 | pItem->mxLayoutCache.reset(); | ||||||
840 | } | ||||||
841 | |||||||
842 | } | ||||||
843 | |||||||
844 | void StatusBar::DataChanged( const DataChangedEvent& rDCEvt ) | ||||||
845 | { | ||||||
846 | Window::DataChanged( rDCEvt ); | ||||||
847 | |||||||
848 | if ( !((rDCEvt.GetType() == DataChangedEventType::DISPLAY ) | ||||||
849 | || (rDCEvt.GetType() == DataChangedEventType::FONTS ) | ||||||
850 | || (rDCEvt.GetType() == DataChangedEventType::FONTSUBSTITUTION) | ||||||
851 | || ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) | ||||||
852 | && (rDCEvt.GetFlags() & AllSettingsFlags::STYLE ) | ||||||
853 | )) | ||||||
854 | ) | ||||||
855 | return; | ||||||
856 | |||||||
857 | mbFormat = true; | ||||||
858 | ImplInitSettings(); | ||||||
859 | long nFudge = GetTextHeight() / 4; | ||||||
860 | for (auto & pItem : mvItemList) | ||||||
861 | { | ||||||
862 | long nWidth = GetTextWidth( pItem->maText ) + nFudge; | ||||||
863 | if( nWidth > pItem->mnWidth + STATUSBAR_OFFSET(long(5)) ) | ||||||
864 | pItem->mnWidth = nWidth + STATUSBAR_OFFSET(long(5)); | ||||||
865 | |||||||
866 | pItem->mxLayoutCache.reset(); | ||||||
867 | } | ||||||
868 | Size aSize = GetSizePixel(); | ||||||
869 | // do not disturb current width, since | ||||||
870 | // CalcWindowSizePixel calculates a minimum width | ||||||
871 | aSize.setHeight( CalcWindowSizePixel().Height() ); | ||||||
872 | SetSizePixel( aSize ); | ||||||
873 | Invalidate(); | ||||||
874 | } | ||||||
875 | |||||||
876 | void StatusBar::Click() | ||||||
877 | { | ||||||
878 | maClickHdl.Call( this ); | ||||||
879 | } | ||||||
880 | |||||||
881 | void StatusBar::DoubleClick() | ||||||
882 | { | ||||||
883 | maDoubleClickHdl.Call( this ); | ||||||
884 | } | ||||||
885 | |||||||
886 | void StatusBar::UserDraw( const UserDrawEvent& ) | ||||||
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" )do { if (true && (!nItemId)) { switch (sal_detail_log_report (::SAL_DETAIL_LOG_LEVEL_WARN, "vcl")) { case SAL_DETAIL_LOG_ACTION_IGNORE : break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail ::getResult( ::sal::detail::StreamStart() << "StatusBar::InsertItem(): ItemId == 0" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl" ), ("/home/maarten/src/libreoffice/core/vcl/source/window/status.cxx" ":" "894" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "StatusBar::InsertItem(): ItemId == 0" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "StatusBar::InsertItem(): ItemId == 0"; ::sal::detail ::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"), ("/home/maarten/src/libreoffice/core/vcl/source/window/status.cxx" ":" "894" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "StatusBar::InsertItem(): ItemId == 0") == 1) { :: sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"), ("/home/maarten/src/libreoffice/core/vcl/source/window/status.cxx" ":" "894" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "StatusBar::InsertItem(): ItemId == 0" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "StatusBar::InsertItem(): ItemId == 0"; ::sal::detail ::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"), ("/home/maarten/src/libreoffice/core/vcl/source/window/status.cxx" ":" "894" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | ||||||
895 | SAL_WARN_IF( GetItemPos( nItemId ) != STATUSBAR_ITEM_NOTFOUND, "vcl",do { if (true && (GetItemPos( nItemId ) != (sal_uInt16 (0xFFFF)))) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN , "vcl")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "StatusBar::InsertItem(): ItemId already exists") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl" ), ("/home/maarten/src/libreoffice/core/vcl/source/window/status.cxx" ":" "896" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "StatusBar::InsertItem(): ItemId already exists" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "StatusBar::InsertItem(): ItemId already exists"; :: sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"), ("/home/maarten/src/libreoffice/core/vcl/source/window/status.cxx" ":" "896" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "StatusBar::InsertItem(): ItemId already exists") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl" ), ("/home/maarten/src/libreoffice/core/vcl/source/window/status.cxx" ":" "896" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "StatusBar::InsertItem(): ItemId already exists" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "StatusBar::InsertItem(): ItemId already exists"; :: sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"), ("/home/maarten/src/libreoffice/core/vcl/source/window/status.cxx" ":" "896" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false) | ||||||
896 | "StatusBar::InsertItem(): ItemId already exists" )do { if (true && (GetItemPos( nItemId ) != (sal_uInt16 (0xFFFF)))) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN , "vcl")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "StatusBar::InsertItem(): ItemId already exists") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl" ), ("/home/maarten/src/libreoffice/core/vcl/source/window/status.cxx" ":" "896" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "StatusBar::InsertItem(): ItemId already exists" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "StatusBar::InsertItem(): ItemId already exists"; :: sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"), ("/home/maarten/src/libreoffice/core/vcl/source/window/status.cxx" ":" "896" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "StatusBar::InsertItem(): ItemId already exists") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl" ), ("/home/maarten/src/libreoffice/core/vcl/source/window/status.cxx" ":" "896" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "StatusBar::InsertItem(): ItemId already exists" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "StatusBar::InsertItem(): ItemId already exists"; :: sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"), ("/home/maarten/src/libreoffice/core/vcl/source/window/status.cxx" ":" "896" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | ||||||
897 | |||||||
898 | // default: IN and CENTER | ||||||
899 | if ( !(nBits & (StatusBarItemBits::In | StatusBarItemBits::Out | StatusBarItemBits::Flat)) ) | ||||||
900 | nBits |= StatusBarItemBits::In; | ||||||
901 | if ( !(nBits & (StatusBarItemBits::Left | StatusBarItemBits::Right | StatusBarItemBits::Center)) ) | ||||||
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(long(5)); | ||||||
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(sal_uInt16(0xFFFF)) ) | ||||||
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(sal_uInt16(0xFFFF)) ) | ||||||
952 | return; | ||||||
953 | |||||||
954 | ImplStatusItem* pItem = mvItemList[ nPos ].get(); | ||||||
955 | if ( !pItem->mbVisible ) | ||||||
956 | { | ||||||
957 | pItem->mbVisible = true; | ||||||
958 | |||||||
959 | mbFormat = true; | ||||||
960 | if ( ImplIsItemUpdate() ) | ||||||
961 | Invalidate(); | ||||||
962 | |||||||
963 | CallEventListeners( VclEventId::StatusbarShowItem, reinterpret_cast<void*>(nItemId) ); | ||||||
964 | } | ||||||
965 | } | ||||||
966 | |||||||
967 | void StatusBar::HideItem( sal_uInt16 nItemId ) | ||||||
968 | { | ||||||
969 | sal_uInt16 nPos = GetItemPos( nItemId ); | ||||||
970 | |||||||
971 | if ( nPos == STATUSBAR_ITEM_NOTFOUND(sal_uInt16(0xFFFF)) ) | ||||||
972 | return; | ||||||
973 | |||||||
974 | ImplStatusItem* pItem = mvItemList[ nPos ].get(); | ||||||
975 | if ( pItem->mbVisible ) | ||||||
976 | { | ||||||
977 | pItem->mbVisible = false; | ||||||
978 | |||||||
979 | mbFormat = true; | ||||||
980 | if ( ImplIsItemUpdate() ) | ||||||
981 | Invalidate(); | ||||||
982 | |||||||
983 | CallEventListeners( VclEventId::StatusbarHideItem, reinterpret_cast<void*>(nItemId) ); | ||||||
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(sal_uInt16(0xFFFF)) ) | ||||||
992 | return mvItemList[ nPos ]->mbVisible; | ||||||
993 | else | ||||||
994 | return false; | ||||||
995 | } | ||||||
996 | |||||||
997 | void StatusBar::Clear() | ||||||
998 | { | ||||||
999 | // delete all items | ||||||
1000 | mvItemList.clear(); | ||||||
1001 | |||||||
1002 | mbFormat = true; | ||||||
1003 | if ( ImplIsItemUpdate() ) | ||||||
1004 | Invalidate(); | ||||||
1005 | |||||||
1006 | CallEventListeners( VclEventId::StatusbarAllItemsRemoved ); | ||||||
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(sal_uInt16(0xFFFF)); | ||||||
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(sal_uInt16(0xFFFF)) ) | ||||||
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(sal_uInt16(0xFFFF)) ) | ||||||
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(sal_uInt16(0xFFFF)) ) | ||||||
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(sal_uInt16(0xFFFF)) ) | ||||||
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(sal_uInt16(0xFFFF)) ) | ||||||
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(sal_uInt16(0xFFFF)) ) | ||||||
1136 | return; | ||||||
1137 | |||||||
1138 | ImplStatusItem* pItem = mvItemList[ nPos ].get(); | ||||||
1139 | |||||||
1140 | if ( pItem->maText == rText ) | ||||||
1141 | return; | ||||||
1142 | |||||||
1143 | pItem->maText = rText; | ||||||
1144 | |||||||
1145 | // adjust item width - see also DataChanged() | ||||||
1146 | long nFudge = GetTextHeight()/4; | ||||||
1147 | |||||||
1148 | long nWidth; | ||||||
1149 | if (nCharsWidth != -1) | ||||||
1150 | { | ||||||
1151 | std::unique_ptr<SalLayout> pSalLayout = ImplLayout("0",0,-1); | ||||||
1152 | const SalLayoutGlyphs* pGlyphs = pSalLayout ? pSalLayout->GetGlyphs() : nullptr; | ||||||
1153 | nWidth = GetTextWidth("0",0,-1,nullptr,pGlyphs ); | ||||||
1154 | nWidth = nWidth * nCharsWidth + nFudge; | ||||||
1155 | } | ||||||
1156 | else | ||||||
1157 | { | ||||||
1158 | std::unique_ptr<SalLayout> pSalLayout = ImplLayout(pItem->maText,0,-1); | ||||||
1159 | const SalLayoutGlyphs* pGlyphs = pSalLayout ? pSalLayout->GetGlyphs() : nullptr; | ||||||
1160 | nWidth = GetTextWidth( pItem->maText,0,-1,nullptr,pGlyphs ) + nFudge; | ||||||
1161 | // Store the calculated layout. | ||||||
1162 | pItem->mxLayoutCache = std::move(pSalLayout); | ||||||
1163 | } | ||||||
1164 | |||||||
1165 | if( (nWidth > pItem->mnWidth + STATUSBAR_OFFSET(long(5))) || | ||||||
1166 | ((nWidth < pItem->mnWidth) && (mnDX - STATUSBAR_OFFSET(long(5))) < mnItemsWidth )) | ||||||
1167 | { | ||||||
1168 | pItem->mnWidth = nWidth + STATUSBAR_OFFSET(long(5)); | ||||||
1169 | ImplFormat(); | ||||||
1170 | Invalidate(); | ||||||
1171 | } | ||||||
1172 | |||||||
1173 | // re-draw item if StatusBar is visible and UpdateMode active | ||||||
1174 | if ( pItem->mbVisible && !mbFormat && ImplIsItemUpdate() ) | ||||||
1175 | { | ||||||
1176 | tools::Rectangle aRect = ImplGetItemRectPos(nPos); | ||||||
1177 | Invalidate(aRect); | ||||||
1178 | PaintImmediately(); | ||||||
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 )(static_cast <bool> (nPos != (sal_uInt16(0xFFFF))) ? void (0) : __assert_fail ("nPos != STATUSBAR_ITEM_NOTFOUND", "/home/maarten/src/libreoffice/core/vcl/source/window/status.cxx" , 1186, __extension__ __PRETTY_FUNCTION__)); | ||||||
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(sal_uInt16(0xFFFF)) ) | ||||||
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(sal_uInt16(0xFFFF)) ) | ||||||
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(sal_uInt16(0xFFFF)) ) | ||||||
1219 | return; | ||||||
1220 | |||||||
1221 | ImplStatusItem* pItem = mvItemList[ nPos ].get(); | ||||||
1222 | // invalidate cache | ||||||
1223 | pItem->mxLayoutCache.reset(); | ||||||
1224 | pItem->mpUserData = pNewData; | ||||||
1225 | |||||||
1226 | // call Draw-Item if it's a User-Item | ||||||
1227 | if ( (pItem->mnBits & StatusBarItemBits::UserDraw) && pItem->mbVisible && | ||||||
1228 | !mbFormat && ImplIsItemUpdate() ) | ||||||
1229 | { | ||||||
1230 | tools::Rectangle aRect = ImplGetItemRectPos(nPos); | ||||||
1231 | Invalidate(aRect, InvalidateFlags::NoErase); | ||||||
1232 | PaintImmediately(); | ||||||
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(sal_uInt16(0xFFFF)) ) | ||||||
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(sal_uInt16(0xFFFF)) ) | ||||||
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 | PaintImmediately(); | ||||||
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(sal_uInt16(0xFFFF)) ) | ||||||
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 )(static_cast <bool> (nPos != (sal_uInt16(0xFFFF))) ? void (0) : __assert_fail ("nPos != STATUSBAR_ITEM_NOTFOUND", "/home/maarten/src/libreoffice/core/vcl/source/window/status.cxx" , 1277, __extension__ __PRETTY_FUNCTION__)); | ||||||
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(((rtl_TextEncoding) 76)) ), 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(sal_uInt16(0xFFFF)) ) | ||||||
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 )(static_cast <bool> (nPos != (sal_uInt16(0xFFFF))) ? void (0) : __assert_fail ("nPos != STATUSBAR_ITEM_NOTFOUND", "/home/maarten/src/libreoffice/core/vcl/source/window/status.cxx" , 1307, __extension__ __PRETTY_FUNCTION__)); | ||||||
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(sal_uInt16(0xFFFF)) ) | ||||||
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" )do { if (true && (mbProgressMode)) { switch (sal_detail_log_report (::SAL_DETAIL_LOG_LEVEL_WARN, "vcl")) { case SAL_DETAIL_LOG_ACTION_IGNORE : break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail ::getResult( ::sal::detail::StreamStart() << "StatusBar::StartProgressMode(): progress mode is active" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl" ), ("/home/maarten/src/libreoffice/core/vcl/source/window/status.cxx" ":" "1323" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "StatusBar::StartProgressMode(): progress mode is active" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "StatusBar::StartProgressMode(): progress mode is active" ; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"), ("/home/maarten/src/libreoffice/core/vcl/source/window/status.cxx" ":" "1323" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "StatusBar::StartProgressMode(): progress mode is active" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl" ), ("/home/maarten/src/libreoffice/core/vcl/source/window/status.cxx" ":" "1323" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "StatusBar::StartProgressMode(): progress mode is active" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "StatusBar::StartProgressMode(): progress mode is active" ; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"), ("/home/maarten/src/libreoffice/core/vcl/source/window/status.cxx" ":" "1323" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | ||||||
1324 | |||||||
1325 | mbProgressMode = true; | ||||||
1326 | mnPercent = 0; | ||||||
1327 | maPrgsTxt = rText; | ||||||
1328 | |||||||
1329 | // compute size | ||||||
1330 | ImplCalcProgressRect(); | ||||||
1331 | |||||||
1332 | // trigger Paint, which draws text and frame | ||||||
1333 | if ( IsReallyVisible() ) | ||||||
1334 | { | ||||||
1335 | Invalidate(); | ||||||
1336 | PaintImmediately(); | ||||||
1337 | } | ||||||
1338 | } | ||||||
1339 | |||||||
1340 | void StatusBar::SetProgressValue( sal_uInt16 nNewPercent ) | ||||||
1341 | { | ||||||
1342 | SAL_WARN_IF( !mbProgressMode, "vcl", "StatusBar::SetProgressValue(): no progress mode" )do { if (true && (!mbProgressMode)) { switch (sal_detail_log_report (::SAL_DETAIL_LOG_LEVEL_WARN, "vcl")) { case SAL_DETAIL_LOG_ACTION_IGNORE : break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail ::getResult( ::sal::detail::StreamStart() << "StatusBar::SetProgressValue(): no progress mode" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl" ), ("/home/maarten/src/libreoffice/core/vcl/source/window/status.cxx" ":" "1342" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "StatusBar::SetProgressValue(): no progress mode" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "StatusBar::SetProgressValue(): no progress mode"; :: sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"), ("/home/maarten/src/libreoffice/core/vcl/source/window/status.cxx" ":" "1342" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "StatusBar::SetProgressValue(): no progress mode" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl" ), ("/home/maarten/src/libreoffice/core/vcl/source/window/status.cxx" ":" "1342" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "StatusBar::SetProgressValue(): no progress mode" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "StatusBar::SetProgressValue(): no progress mode"; :: sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"), ("/home/maarten/src/libreoffice/core/vcl/source/window/status.cxx" ":" "1342" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | ||||||
1343 | SAL_WARN_IF( nNewPercent > 100, "vcl", "StatusBar::SetProgressValue(): nPercent > 100" )do { if (true && (nNewPercent > 100)) { switch (sal_detail_log_report (::SAL_DETAIL_LOG_LEVEL_WARN, "vcl")) { case SAL_DETAIL_LOG_ACTION_IGNORE : break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail ::getResult( ::sal::detail::StreamStart() << "StatusBar::SetProgressValue(): nPercent > 100" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl" ), ("/home/maarten/src/libreoffice/core/vcl/source/window/status.cxx" ":" "1343" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "StatusBar::SetProgressValue(): nPercent > 100" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "StatusBar::SetProgressValue(): nPercent > 100"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"), ( "/home/maarten/src/libreoffice/core/vcl/source/window/status.cxx" ":" "1343" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "StatusBar::SetProgressValue(): nPercent > 100" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl" ), ("/home/maarten/src/libreoffice/core/vcl/source/window/status.cxx" ":" "1343" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "StatusBar::SetProgressValue(): nPercent > 100" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "StatusBar::SetProgressValue(): nPercent > 100"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"), ( "/home/maarten/src/libreoffice/core/vcl/source/window/status.cxx" ":" "1343" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | ||||||
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 | { | ||||||
1356 | Invalidate(maPrgsFrameRect); | ||||||
1357 | PaintImmediately(); | ||||||
1358 | mnLastProgressPaint_ms = nTime_ms; | ||||||
1359 | } | ||||||
1360 | } | ||||||
1361 | } | ||||||
1362 | |||||||
1363 | void StatusBar::EndProgressMode() | ||||||
1364 | { | ||||||
1365 | SAL_WARN_IF( !mbProgressMode, "vcl", "StatusBar::EndProgressMode(): no progress mode" )do { if (true && (!mbProgressMode)) { switch (sal_detail_log_report (::SAL_DETAIL_LOG_LEVEL_WARN, "vcl")) { case SAL_DETAIL_LOG_ACTION_IGNORE : break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail ::getResult( ::sal::detail::StreamStart() << "StatusBar::EndProgressMode(): no progress mode" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl" ), ("/home/maarten/src/libreoffice/core/vcl/source/window/status.cxx" ":" "1365" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "StatusBar::EndProgressMode(): no progress mode" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "StatusBar::EndProgressMode(): no progress mode"; :: sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"), ("/home/maarten/src/libreoffice/core/vcl/source/window/status.cxx" ":" "1365" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "StatusBar::EndProgressMode(): no progress mode") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl" ), ("/home/maarten/src/libreoffice/core/vcl/source/window/status.cxx" ":" "1365" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "StatusBar::EndProgressMode(): no progress mode" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "StatusBar::EndProgressMode(): no progress mode"; :: sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"), ("/home/maarten/src/libreoffice/core/vcl/source/window/status.cxx" ":" "1365" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | ||||||
1366 | |||||||
1367 | mbProgressMode = false; | ||||||
1368 | maPrgsTxt.clear(); | ||||||
1369 | |||||||
1370 | if ( IsReallyVisible() ) | ||||||
1371 | { | ||||||
1372 | Invalidate(); | ||||||
1373 | PaintImmediately(); | ||||||
1374 | } | ||||||
1375 | } | ||||||
1376 | |||||||
1377 | void StatusBar::SetText(const OUString& rText) | ||||||
1378 | { | ||||||
1379 | if ((GetStyle() & WB_RIGHT) && !mbProgressMode && IsReallyVisible() && IsUpdateMode()) | ||||||
1380 | { | ||||||
1381 | if (mbFormat) | ||||||
1382 | { | ||||||
1383 | Invalidate(); | ||||||
1384 | Window::SetText(rText); | ||||||
1385 | } | ||||||
1386 | else | ||||||
1387 | { | ||||||
1388 | Invalidate(); | ||||||
1389 | Window::SetText(rText); | ||||||
1390 | PaintImmediately(); | ||||||
1391 | } | ||||||
1392 | } | ||||||
1393 | else if (mbProgressMode) | ||||||
1394 | { | ||||||
1395 | maPrgsTxt = rText; | ||||||
1396 | if (IsReallyVisible()) | ||||||
1397 | { | ||||||
1398 | Invalidate(); | ||||||
1399 | PaintImmediately(); | ||||||
1400 | } | ||||||
1401 | } | ||||||
1402 | else | ||||||
1403 | { | ||||||
1404 | Window::SetText(rText); | ||||||
1405 | } | ||||||
1406 | } | ||||||
1407 | |||||||
1408 | Size StatusBar::CalcWindowSizePixel() const | ||||||
1409 | { | ||||||
1410 | size_t i = 0; | ||||||
1411 | size_t nCount = mvItemList.size(); | ||||||
1412 | long nOffset = 0; | ||||||
1413 | long nCalcWidth = STATUSBAR_OFFSET_X(long(5))*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_TEXTY3*2; | ||||||
1426 | long nProgressHeight = nMinHeight + nBarTextOffset; | ||||||
1427 | |||||||
1428 | if( IsNativeControlSupported( ControlType::Progress, ControlPart::Entire ) ) | ||||||
1429 | { | ||||||
1430 | ImplControlValue aValue; | ||||||
1431 | tools::Rectangle aControlRegion( Point(), Size( nCalcWidth, nMinHeight ) ); | ||||||
1432 | tools::Rectangle aNativeControlRegion, aNativeContentRegion; | ||||||
1433 | if( GetNativeControlRegion( ControlType::Progress, ControlPart::Entire, | ||||||
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(sal_uInt16(0xFFFF)) ) | ||||||
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 )(static_cast <bool> (nPos != (sal_uInt16(0xFFFF))) ? void (0) : __assert_fail ("nPos != STATUSBAR_ITEM_NOTFOUND", "/home/maarten/src/libreoffice/core/vcl/source/window/status.cxx" , 1468, __extension__ __PRETTY_FUNCTION__)); | ||||||
1469 | |||||||
1470 | return mvItemList[ nPos ]->maAccessibleName; | ||||||
1471 | } | ||||||
1472 | |||||||
1473 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |
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 | #ifndef INCLUDED_RTL_REF_HXX | ||||||
21 | #define INCLUDED_RTL_REF_HXX | ||||||
22 | |||||||
23 | #include "sal/config.h" | ||||||
24 | |||||||
25 | #include <cassert> | ||||||
26 | #include <cstddef> | ||||||
27 | #include <functional> | ||||||
28 | #ifdef LIBO_INTERNAL_ONLY1 | ||||||
29 | #include <type_traits> | ||||||
30 | #endif | ||||||
31 | |||||||
32 | #include "sal/types.h" | ||||||
33 | |||||||
34 | namespace rtl | ||||||
35 | { | ||||||
36 | |||||||
37 | /** Template reference class for reference type. | ||||||
38 | */ | ||||||
39 | template <class reference_type> | ||||||
40 | class Reference | ||||||
41 | { | ||||||
42 | /** The <b>reference_type</b> body pointer. | ||||||
43 | */ | ||||||
44 | reference_type * m_pBody; | ||||||
45 | |||||||
46 | |||||||
47 | public: | ||||||
48 | /** Constructor... | ||||||
49 | */ | ||||||
50 | Reference() | ||||||
51 | : m_pBody (NULL__null) | ||||||
52 | {} | ||||||
53 | |||||||
54 | |||||||
55 | /** Constructor... | ||||||
56 | */ | ||||||
57 | Reference (reference_type * pBody, __sal_NoAcquire) | ||||||
58 | : m_pBody (pBody) | ||||||
59 | { | ||||||
60 | } | ||||||
61 | |||||||
62 | /** Constructor... | ||||||
63 | */ | ||||||
64 | Reference (reference_type * pBody) | ||||||
65 | : m_pBody (pBody) | ||||||
66 | { | ||||||
67 | if (m_pBody) | ||||||
68 | m_pBody->acquire(); | ||||||
69 | } | ||||||
70 | |||||||
71 | /** Copy constructor... | ||||||
72 | */ | ||||||
73 | Reference (const Reference<reference_type> & handle) | ||||||
74 | : m_pBody (handle.m_pBody) | ||||||
75 | { | ||||||
76 | if (m_pBody) | ||||||
77 | m_pBody->acquire(); | ||||||
78 | } | ||||||
79 | |||||||
80 | #ifdef LIBO_INTERNAL_ONLY1 | ||||||
81 | /** Move constructor... | ||||||
82 | */ | ||||||
83 | Reference (Reference<reference_type> && handle) noexcept | ||||||
84 | : m_pBody (handle.m_pBody) | ||||||
85 | { | ||||||
86 | handle.m_pBody = nullptr; | ||||||
87 | } | ||||||
88 | #endif | ||||||
89 | |||||||
90 | #if defined LIBO_INTERNAL_ONLY1 | ||||||
91 | /** Up-casting conversion constructor: Copies interface reference. | ||||||
92 | |||||||
93 | Does not work for up-casts to ambiguous bases. | ||||||
94 | |||||||
95 | @param rRef another reference | ||||||
96 | */ | ||||||
97 | template< class derived_type > | ||||||
98 | inline Reference( | ||||||
99 | const Reference< derived_type > & rRef, | ||||||
100 | std::enable_if_t<std::is_base_of_v<reference_type, derived_type>, int> = 0 ) | ||||||
101 | : m_pBody (rRef.get()) | ||||||
102 | { | ||||||
103 | if (m_pBody) | ||||||
104 | m_pBody->acquire(); | ||||||
105 | } | ||||||
106 | #endif | ||||||
107 | |||||||
108 | /** Destructor... | ||||||
109 | */ | ||||||
110 | ~Reference() COVERITY_NOEXCEPT_FALSE | ||||||
111 | { | ||||||
112 | if (m_pBody
| ||||||
113 | m_pBody->release(); | ||||||
114 | } | ||||||
115 | |||||||
116 | /** Set... | ||||||
117 | Similar to assignment. | ||||||
118 | */ | ||||||
119 | Reference<reference_type> & | ||||||
120 | SAL_CALL set (reference_type * pBody) | ||||||
121 | { | ||||||
122 | if (pBody) | ||||||
123 | pBody->acquire(); | ||||||
124 | reference_type * const pOld = m_pBody; | ||||||
125 | m_pBody = pBody; | ||||||
126 | if (pOld) | ||||||
127 | pOld->release(); | ||||||
128 | return *this; | ||||||
129 | } | ||||||
130 | |||||||
131 | /** Assignment. | ||||||
132 | Unbinds this instance from its body (if bound) and | ||||||
133 | bind it to the body represented by the handle. | ||||||
134 | */ | ||||||
135 | Reference<reference_type> & | ||||||
136 | SAL_CALL operator= (const Reference<reference_type> & handle) | ||||||
137 | { | ||||||
138 | return set( handle.m_pBody ); | ||||||
139 | } | ||||||
140 | |||||||
141 | #ifdef LIBO_INTERNAL_ONLY1 | ||||||
142 | /** Assignment. | ||||||
143 | * Unbinds this instance from its body (if bound), | ||||||
144 | * bind it to the body represented by the handle, and | ||||||
145 | * set the body represented by the handle to nullptr. | ||||||
146 | */ | ||||||
147 | Reference<reference_type> & | ||||||
148 | operator= (Reference<reference_type> && handle) | ||||||
149 | { | ||||||
150 | // self-movement guts ourself | ||||||
151 | if (m_pBody) | ||||||
152 | m_pBody->release(); | ||||||
153 | m_pBody = handle.m_pBody; | ||||||
154 | handle.m_pBody = nullptr; | ||||||
155 | return *this; | ||||||
156 | } | ||||||
157 | #endif | ||||||
158 | |||||||
159 | /** Assignment... | ||||||
160 | */ | ||||||
161 | Reference<reference_type> & | ||||||
162 | SAL_CALL operator= (reference_type * pBody) | ||||||
163 | { | ||||||
164 | return set( pBody ); | ||||||
165 | } | ||||||
166 | |||||||
167 | /** Unbind the body from this handle. | ||||||
168 | Note that for a handle representing a large body, | ||||||
169 | "handle.clear().set(new body());" _might_ | ||||||
170 | perform a little bit better than "handle.set(new body());", | ||||||
171 | since in the second case two large objects exist in memory | ||||||
172 | (the old body and the new body). | ||||||
173 | */ | ||||||
174 | Reference<reference_type> & SAL_CALL clear() | ||||||
175 | { | ||||||
176 | if (m_pBody) | ||||||
177 | { | ||||||
178 | reference_type * const pOld = m_pBody; | ||||||
179 | m_pBody = NULL__null; | ||||||
180 | pOld->release(); | ||||||
181 | } | ||||||
182 | return *this; | ||||||
183 | } | ||||||
184 | |||||||
185 | |||||||
186 | /** Get the body. Can be used instead of operator->(). | ||||||
187 | I.e. handle->someBodyOp() and handle.get()->someBodyOp() | ||||||
188 | are the same. | ||||||
189 | */ | ||||||
190 | reference_type * SAL_CALL get() const | ||||||
191 | { | ||||||
192 | return m_pBody; | ||||||
193 | } | ||||||
194 | |||||||
195 | |||||||
196 | /** Probably most common used: handle->someBodyOp(). | ||||||
197 | */ | ||||||
198 | reference_type * SAL_CALL operator->() const | ||||||
199 | { | ||||||
200 | assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail ("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx" , 200, __extension__ __PRETTY_FUNCTION__)); | ||||||
201 | return m_pBody; | ||||||
202 | } | ||||||
203 | |||||||
204 | |||||||
205 | /** Allows (*handle).someBodyOp(). | ||||||
206 | */ | ||||||
207 | reference_type & SAL_CALL operator*() const | ||||||
208 | { | ||||||
209 | assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail ("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx" , 209, __extension__ __PRETTY_FUNCTION__)); | ||||||
210 | return *m_pBody; | ||||||
211 | } | ||||||
212 | |||||||
213 | |||||||
214 | /** Returns True if the handle does point to a valid body. | ||||||
215 | */ | ||||||
216 | bool SAL_CALL is() const | ||||||
217 | { | ||||||
218 | return (m_pBody != NULL__null); | ||||||
219 | } | ||||||
220 | |||||||
221 | #if defined LIBO_INTERNAL_ONLY1 | ||||||
222 | /** Returns True if the handle does point to a valid body. | ||||||
223 | */ | ||||||
224 | explicit operator bool() const | ||||||
225 | { | ||||||
226 | return is(); | ||||||
227 | } | ||||||
228 | #endif | ||||||
229 | |||||||
230 | /** Returns True if this points to pBody. | ||||||
231 | */ | ||||||
232 | bool SAL_CALL operator== (const reference_type * pBody) const | ||||||
233 | { | ||||||
234 | return (m_pBody == pBody); | ||||||
235 | } | ||||||
236 | |||||||
237 | |||||||
238 | /** Returns True if handle points to the same body. | ||||||
239 | */ | ||||||
240 | bool | ||||||
241 | SAL_CALL operator== (const Reference<reference_type> & handle) const | ||||||
242 | { | ||||||
243 | return (m_pBody == handle.m_pBody); | ||||||
244 | } | ||||||
245 | |||||||
246 | |||||||
247 | /** Needed to place References into STL collection. | ||||||
248 | */ | ||||||
249 | bool | ||||||
250 | SAL_CALL operator!= (const Reference<reference_type> & handle) const | ||||||
251 | { | ||||||
252 | return (m_pBody != handle.m_pBody); | ||||||
253 | } | ||||||
254 | |||||||
255 | |||||||
256 | /** Needed to place References into STL collection. | ||||||
257 | */ | ||||||
258 | bool | ||||||
259 | SAL_CALL operator< (const Reference<reference_type> & handle) const | ||||||
260 | { | ||||||
261 | return (m_pBody < handle.m_pBody); | ||||||
262 | } | ||||||
263 | |||||||
264 | |||||||
265 | /** Needed to place References into STL collection. | ||||||
266 | */ | ||||||
267 | bool | ||||||
268 | SAL_CALL operator> (const Reference<reference_type> & handle) const | ||||||
269 | { | ||||||
270 | return (m_pBody > handle.m_pBody); | ||||||
271 | } | ||||||
272 | }; | ||||||
273 | |||||||
274 | } // namespace rtl | ||||||
275 | |||||||
276 | #if defined LIBO_INTERNAL_ONLY1 | ||||||
277 | namespace std | ||||||
278 | { | ||||||
279 | |||||||
280 | /// @cond INTERNAL | ||||||
281 | /** | ||||||
282 | Make rtl::Reference hashable by default for use in STL containers. | ||||||
283 | |||||||
284 | @since LibreOffice 6.3 | ||||||
285 | */ | ||||||
286 | template<typename T> | ||||||
287 | struct hash<::rtl::Reference<T>> | ||||||
288 | { | ||||||
289 | std::size_t operator()(::rtl::Reference<T> const & s) const | ||||||
290 | { return std::size_t(s.get()); } | ||||||
291 | }; | ||||||
292 | /// @endcond | ||||||
293 | |||||||
294 | } | ||||||
295 | |||||||
296 | #endif | ||||||
297 | |||||||
298 | #endif /* ! INCLUDED_RTL_REF_HXX */ | ||||||
299 | |||||||
300 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |
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 | #ifndef INCLUDED_VCL_Reference_HXX |
20 | #define INCLUDED_VCL_Reference_HXX |
21 | |
22 | #include <vcl/dllapi.h> |
23 | #include <osl/interlck.h> |
24 | |
25 | class VCL_DLLPUBLIC__attribute__ ((visibility("default"))) VclReferenceBase |
26 | { |
27 | mutable oslInterlockedCount mnRefCnt; |
28 | |
29 | template<typename T> friend class VclPtr; |
30 | |
31 | public: |
32 | void acquire() const |
33 | { |
34 | osl_atomic_increment(&mnRefCnt)__sync_add_and_fetch((&mnRefCnt), 1); |
35 | } |
36 | |
37 | void release() const |
38 | { |
39 | if (osl_atomic_decrement(&mnRefCnt)__sync_sub_and_fetch((&mnRefCnt), 1) == 0) |
40 | delete this; |
41 | } |
42 | #ifdef DBG_UTIL |
43 | #ifndef _WIN32 |
44 | sal_Int32 getRefCount() const { return mnRefCnt; } |
45 | #endif |
46 | #endif |
47 | |
48 | |
49 | private: |
50 | VclReferenceBase(const VclReferenceBase&) = delete; |
51 | VclReferenceBase& operator=(const VclReferenceBase&) = delete; |
52 | |
53 | bool mbDisposed : 1; |
54 | |
55 | protected: |
56 | VclReferenceBase(); |
57 | protected: |
58 | virtual ~VclReferenceBase(); |
59 | |
60 | protected: |
61 | virtual void dispose(); |
62 | |
63 | public: |
64 | void disposeOnce(); |
65 | bool isDisposed() const { return mbDisposed; } |
66 | |
67 | }; |
68 | #endif |