File: | home/maarten/src/libreoffice/core/vcl/source/window/toolbox.cxx |
Warning: | line 3013, column 22 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 | #include <vcl/toolbox.hxx> | ||||||
21 | #include <vcl/commandinfoprovider.hxx> | ||||||
22 | #include <vcl/event.hxx> | ||||||
23 | #include <vcl/decoview.hxx> | ||||||
24 | #include <vcl/accel.hxx> | ||||||
25 | #include <vcl/svapp.hxx> | ||||||
26 | #include <vcl/help.hxx> | ||||||
27 | #include <vcl/mnemonic.hxx> | ||||||
28 | #include <vcl/gradient.hxx> | ||||||
29 | #include <vcl/layout.hxx> | ||||||
30 | #include <vcl/menu.hxx> | ||||||
31 | #include <vcl/settings.hxx> | ||||||
32 | #include <vclstatuslistener.hxx> | ||||||
33 | #include <vcl/ptrstyle.hxx> | ||||||
34 | #include <bitmaps.hlst> | ||||||
35 | |||||||
36 | #include <tools/poly.hxx> | ||||||
37 | #include <svl/imageitm.hxx> | ||||||
38 | #include <sal/log.hxx> | ||||||
39 | #include <osl/diagnose.h> | ||||||
40 | |||||||
41 | #include <svdata.hxx> | ||||||
42 | #include <window.h> | ||||||
43 | #include <toolbox.h> | ||||||
44 | #include <spin.hxx> | ||||||
45 | #if defined(_WIN32) | ||||||
46 | #include <svsys.h> | ||||||
47 | #endif | ||||||
48 | |||||||
49 | #include <cstdlib> | ||||||
50 | #include <vector> | ||||||
51 | #include <math.h> | ||||||
52 | |||||||
53 | |||||||
54 | #define SMALLBUTTON_HSIZE7 7 | ||||||
55 | #define SMALLBUTTON_VSIZE7 7 | ||||||
56 | |||||||
57 | #define SMALLBUTTON_OFF_NORMAL_X3 3 | ||||||
58 | #define SMALLBUTTON_OFF_NORMAL_Y3 3 | ||||||
59 | |||||||
60 | #define TB_TEXTOFFSET2 2 | ||||||
61 | #define TB_IMAGETEXTOFFSET3 3 | ||||||
62 | #define TB_LINESPACING3 3 | ||||||
63 | #define TB_SPIN_SIZE14 14 | ||||||
64 | #define TB_SPIN_OFFSET2 2 | ||||||
65 | #define TB_BORDER_OFFSET14 4 | ||||||
66 | #define TB_BORDER_OFFSET22 2 | ||||||
67 | #define TB_MAXLINES5 5 | ||||||
68 | #define TB_MAXNOSCROLL32765 32765 | ||||||
69 | |||||||
70 | #define TB_DRAGWIDTH8 8 // the default width of the drag grip | ||||||
71 | |||||||
72 | #define TB_CALCMODE_HORZ1 1 | ||||||
73 | #define TB_CALCMODE_VERT2 2 | ||||||
74 | #define TB_CALCMODE_FLOAT3 3 | ||||||
75 | |||||||
76 | #define TB_WBLINESIZING(WB_SIZEABLE | WB_DOCKABLE | WB_SCROLL) (WB_SIZEABLE | WB_DOCKABLE | WB_SCROLL) | ||||||
77 | |||||||
78 | #define DOCK_LINEHSIZE(sal_uInt16(0x0001)) (sal_uInt16(0x0001)) | ||||||
79 | #define DOCK_LINEVSIZE(sal_uInt16(0x0002)) (sal_uInt16(0x0002)) | ||||||
80 | #define DOCK_LINERIGHT(sal_uInt16(0x1000)) (sal_uInt16(0x1000)) | ||||||
81 | #define DOCK_LINEBOTTOM(sal_uInt16(0x2000)) (sal_uInt16(0x2000)) | ||||||
82 | #define DOCK_LINELEFT(sal_uInt16(0x4000)) (sal_uInt16(0x4000)) | ||||||
83 | #define DOCK_LINETOP(sal_uInt16(0x8000)) (sal_uInt16(0x8000)) | ||||||
84 | #define DOCK_LINEOFFSET3 3 | ||||||
85 | |||||||
86 | class ImplTBDragMgr | ||||||
87 | { | ||||||
88 | private: | ||||||
89 | VclPtr<ToolBox> mpDragBox; | ||||||
90 | Point maMouseOff; | ||||||
91 | tools::Rectangle maRect; | ||||||
92 | tools::Rectangle maStartRect; | ||||||
93 | Accelerator maAccel; | ||||||
94 | sal_uInt16 mnLineMode; | ||||||
95 | ToolBox::ImplToolItems::size_type mnStartLines; | ||||||
96 | |||||||
97 | ImplTBDragMgr(const ImplTBDragMgr&) = delete; | ||||||
98 | ImplTBDragMgr& operator=(const ImplTBDragMgr&) = delete; | ||||||
99 | |||||||
100 | public: | ||||||
101 | ImplTBDragMgr(); | ||||||
102 | |||||||
103 | void StartDragging( ToolBox* pDragBox, const Point& rPos, const tools::Rectangle& rRect, sal_uInt16 nLineMode ); | ||||||
104 | void Dragging( const Point& rPos ); | ||||||
105 | void EndDragging( bool bOK = true ); | ||||||
106 | DECL_LINK( SelectHdl, Accelerator&, void )static void LinkStubSelectHdl(void *, Accelerator&); void SelectHdl(Accelerator&); | ||||||
107 | }; | ||||||
108 | |||||||
109 | |||||||
110 | static ImplTBDragMgr* ImplGetTBDragMgr() | ||||||
111 | { | ||||||
112 | ImplSVData* pSVData = ImplGetSVData(); | ||||||
113 | if ( !pSVData->maCtrlData.mpTBDragMgr ) | ||||||
114 | pSVData->maCtrlData.mpTBDragMgr = new ImplTBDragMgr; | ||||||
115 | return pSVData->maCtrlData.mpTBDragMgr; | ||||||
116 | } | ||||||
117 | |||||||
118 | int ToolBox::ImplGetDragWidth( const vcl::RenderContext& rRenderContext, bool bHorz ) | ||||||
119 | { | ||||||
120 | int nWidth = TB_DRAGWIDTH8; | ||||||
121 | if( rRenderContext.IsNativeControlSupported( ControlType::Toolbar, ControlPart::Entire ) ) | ||||||
122 | { | ||||||
123 | |||||||
124 | ImplControlValue aControlValue; | ||||||
125 | tools::Rectangle aContent, aBound; | ||||||
126 | tools::Rectangle aArea( Point(), rRenderContext.GetOutputSizePixel() ); | ||||||
127 | |||||||
128 | if ( rRenderContext.GetNativeControlRegion(ControlType::Toolbar, | ||||||
129 | bHorz ? ControlPart::ThumbVert : ControlPart::ThumbHorz, | ||||||
130 | aArea, ControlState::NONE, aControlValue, aBound, aContent) ) | ||||||
131 | { | ||||||
132 | nWidth = bHorz ? aContent.GetWidth() : aContent.GetHeight(); | ||||||
133 | } | ||||||
134 | } | ||||||
135 | |||||||
136 | // increase the hit area of the drag handle according to DPI scale factor | ||||||
137 | nWidth *= rRenderContext.GetDPIScaleFactor(); | ||||||
138 | |||||||
139 | return nWidth; | ||||||
140 | } | ||||||
141 | |||||||
142 | int ToolBox::ImplGetDragWidth() const | ||||||
143 | { | ||||||
144 | return ToolBox::ImplGetDragWidth( *this, mbHorz ); | ||||||
145 | } | ||||||
146 | |||||||
147 | static ButtonType determineButtonType( ImplToolItem const * pItem, ButtonType defaultType ) | ||||||
148 | { | ||||||
149 | ButtonType tmpButtonType = defaultType; | ||||||
150 | ToolBoxItemBits nBits = pItem->mnBits & ( ToolBoxItemBits::TEXT_ONLY | ToolBoxItemBits::ICON_ONLY ); | ||||||
151 | if ( nBits != ToolBoxItemBits::NONE ) // item has custom setting | ||||||
152 | { | ||||||
153 | tmpButtonType = ButtonType::SYMBOLTEXT; | ||||||
154 | if ( nBits == ToolBoxItemBits::TEXT_ONLY ) | ||||||
155 | tmpButtonType = ButtonType::TEXT; | ||||||
156 | else if ( nBits == ToolBoxItemBits::ICON_ONLY ) | ||||||
157 | tmpButtonType = ButtonType::SYMBOLONLY; | ||||||
158 | } | ||||||
159 | return tmpButtonType; | ||||||
160 | } | ||||||
161 | |||||||
162 | void ToolBox::ImplUpdateDragArea() const | ||||||
163 | { | ||||||
164 | ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( this ); | ||||||
165 | if( pWrapper ) | ||||||
166 | { | ||||||
167 | if ( ImplIsFloatingMode() || pWrapper->IsLocked() ) | ||||||
168 | pWrapper->SetDragArea( tools::Rectangle() ); | ||||||
169 | else | ||||||
170 | { | ||||||
171 | if( meAlign == WindowAlign::Top || meAlign == WindowAlign::Bottom ) | ||||||
172 | pWrapper->SetDragArea( tools::Rectangle( 0, 0, ImplGetDragWidth(), GetOutputSizePixel().Height() ) ); | ||||||
173 | else | ||||||
174 | pWrapper->SetDragArea( tools::Rectangle( 0, 0, GetOutputSizePixel().Width(), ImplGetDragWidth() ) ); | ||||||
175 | } | ||||||
176 | } | ||||||
177 | } | ||||||
178 | |||||||
179 | void ToolBox::ImplCalcBorder( WindowAlign eAlign, long& rLeft, long& rTop, | ||||||
180 | long& rRight, long& rBottom ) const | ||||||
181 | { | ||||||
182 | if( ImplIsFloatingMode() || !(mnWinStyle & WB_BORDER) ) | ||||||
183 | { | ||||||
184 | // no border in floating mode | ||||||
185 | rLeft = rTop = rRight = rBottom = 0; | ||||||
186 | return; | ||||||
187 | } | ||||||
188 | |||||||
189 | ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( this ); | ||||||
190 | |||||||
191 | // reserve DragArea only for dockable toolbars | ||||||
192 | int dragwidth = ( pWrapper && !pWrapper->IsLocked() ) ? ImplGetDragWidth() : 0; | ||||||
193 | |||||||
194 | // no shadow border for dockable toolbars and toolbars with WB_NOSHADOW bit set, e.g. Calc's formulabar | ||||||
195 | int borderwidth = ( pWrapper || mnWinStyle & WB_NOSHADOW ) ? 0 : 2; | ||||||
196 | |||||||
197 | if ( eAlign == WindowAlign::Top ) | ||||||
198 | { | ||||||
199 | rLeft = borderwidth+dragwidth; | ||||||
200 | rTop = borderwidth; | ||||||
201 | rRight = borderwidth; | ||||||
202 | rBottom = 0; | ||||||
203 | } | ||||||
204 | else if ( eAlign == WindowAlign::Left ) | ||||||
205 | { | ||||||
206 | rLeft = borderwidth; | ||||||
207 | rTop = borderwidth+dragwidth; | ||||||
208 | rRight = 0; | ||||||
209 | rBottom = borderwidth; | ||||||
210 | } | ||||||
211 | else if ( eAlign == WindowAlign::Bottom ) | ||||||
212 | { | ||||||
213 | rLeft = borderwidth+dragwidth; | ||||||
214 | rTop = 0; | ||||||
215 | rRight = borderwidth; | ||||||
216 | rBottom = borderwidth; | ||||||
217 | } | ||||||
218 | else | ||||||
219 | { | ||||||
220 | rLeft = 0; | ||||||
221 | rTop = borderwidth+dragwidth; | ||||||
222 | rRight = borderwidth; | ||||||
223 | rBottom = borderwidth; | ||||||
224 | } | ||||||
225 | } | ||||||
226 | |||||||
227 | void ToolBox::ImplCheckUpdate() | ||||||
228 | { | ||||||
229 | // remove any pending invalidates to avoid | ||||||
230 | // have them triggered when paint is locked (see mpData->mbIsPaintLocked) | ||||||
231 | // which would result in erasing the background only and not painting any items | ||||||
232 | // this must not be done when we're already in Paint() | ||||||
233 | |||||||
234 | // this is only required for transparent toolbars (see ImplDrawTransparentBackground() ) | ||||||
235 | if( !IsBackground() && HasPaintEvent() && !IsInPaint() ) | ||||||
236 | PaintImmediately(); | ||||||
237 | } | ||||||
238 | |||||||
239 | void ToolBox::ImplDrawGrip(vcl::RenderContext& rRenderContext, | ||||||
240 | const tools::Rectangle &aDragArea, int nDragWidth, WindowAlign eAlign, bool bHorz) | ||||||
241 | { | ||||||
242 | bool bNativeOk = false; | ||||||
243 | const ControlPart ePart = bHorz ? ControlPart::ThumbVert : ControlPart::ThumbHorz; | ||||||
244 | const Size aSz( rRenderContext.GetOutputSizePixel() ); | ||||||
245 | if (rRenderContext.IsNativeControlSupported(ControlType::Toolbar, ePart)) | ||||||
246 | { | ||||||
247 | ToolbarValue aToolbarValue; | ||||||
248 | aToolbarValue.maGripRect = aDragArea; | ||||||
249 | |||||||
250 | tools::Rectangle aCtrlRegion(Point(), aSz); | ||||||
251 | |||||||
252 | bNativeOk = rRenderContext.DrawNativeControl( ControlType::Toolbar, ePart, | ||||||
253 | aCtrlRegion, ControlState::ENABLED, aToolbarValue, OUString() ); | ||||||
254 | } | ||||||
255 | |||||||
256 | if( bNativeOk ) | ||||||
257 | return; | ||||||
258 | |||||||
259 | const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings(); | ||||||
260 | rRenderContext.SetLineColor(rStyleSettings.GetShadowColor()); | ||||||
261 | rRenderContext.SetFillColor(rStyleSettings.GetShadowColor()); | ||||||
262 | |||||||
263 | float fScaleFactor = rRenderContext.GetDPIScaleFactor(); | ||||||
264 | |||||||
265 | if (eAlign == WindowAlign::Top || eAlign == WindowAlign::Bottom) | ||||||
266 | { | ||||||
267 | int height = static_cast<int>(0.6 * aSz.Height() + 0.5); | ||||||
268 | int i = (aSz.Height() - height) / 2; | ||||||
269 | height += i; | ||||||
270 | while (i <= height) | ||||||
271 | { | ||||||
272 | int x = nDragWidth / 2; | ||||||
273 | rRenderContext.DrawEllipse(tools::Rectangle(Point(x, i), Size(2 * fScaleFactor, 2 * fScaleFactor))); | ||||||
274 | i += 4 * fScaleFactor; | ||||||
275 | } | ||||||
276 | } | ||||||
277 | else | ||||||
278 | { | ||||||
279 | int width = static_cast<int>(0.6 * aSz.Width() + 0.5); | ||||||
280 | int i = (aSz.Width() - width) / 2; | ||||||
281 | width += i; | ||||||
282 | while (i <= width) | ||||||
283 | { | ||||||
284 | int y = nDragWidth / 2; | ||||||
285 | rRenderContext.DrawEllipse(tools::Rectangle(Point(i, y), Size(2 * fScaleFactor, 2 * fScaleFactor))); | ||||||
286 | i += 4 * fScaleFactor; | ||||||
287 | } | ||||||
288 | } | ||||||
289 | } | ||||||
290 | |||||||
291 | void ToolBox::ImplDrawGrip(vcl::RenderContext& rRenderContext) | ||||||
292 | { | ||||||
293 | ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper(this); | ||||||
294 | if( pWrapper && !pWrapper->GetDragArea().IsEmpty() ) | ||||||
295 | { | ||||||
296 | // execute pending paint requests | ||||||
297 | ImplCheckUpdate(); | ||||||
298 | ImplDrawGrip( rRenderContext, pWrapper->GetDragArea(), | ||||||
299 | ImplGetDragWidth(), meAlign, mbHorz ); | ||||||
300 | } | ||||||
301 | } | ||||||
302 | |||||||
303 | void ToolBox::ImplDrawGradientBackground(vcl::RenderContext& rRenderContext) | ||||||
304 | { | ||||||
305 | // draw a nice gradient | ||||||
306 | |||||||
307 | Color startCol, endCol; | ||||||
308 | const StyleSettings rSettings = rRenderContext.GetSettings().GetStyleSettings(); | ||||||
309 | |||||||
310 | startCol = rSettings.GetFaceGradientColor(); | ||||||
311 | endCol = rSettings.GetFaceColor(); | ||||||
312 | if (rSettings.GetHighContrastMode()) | ||||||
313 | // no 'extreme' gradient when high contrast | ||||||
314 | startCol = endCol; | ||||||
315 | |||||||
316 | Gradient g; | ||||||
317 | g.SetAngle(mbHorz ? 0 : 900); | ||||||
318 | g.SetStyle(GradientStyle::Linear); | ||||||
319 | |||||||
320 | g.SetStartColor(startCol); | ||||||
321 | g.SetEndColor(endCol); | ||||||
322 | |||||||
323 | bool bLineColor = rRenderContext.IsLineColor(); | ||||||
324 | Color aOldCol = rRenderContext.GetLineColor(); | ||||||
325 | rRenderContext.SetLineColor(rRenderContext.GetSettings().GetStyleSettings().GetShadowColor()); | ||||||
326 | |||||||
327 | Size aFullSz(GetOutputSizePixel()); | ||||||
328 | Size aLineSz(aFullSz); | ||||||
329 | |||||||
330 | // use the linesize only when floating | ||||||
331 | // full window height is used when docked (single line) | ||||||
332 | if (ImplIsFloatingMode()) | ||||||
333 | { | ||||||
334 | long nLineSize; | ||||||
335 | if (mbHorz) | ||||||
336 | { | ||||||
337 | nLineSize = mnMaxItemHeight; | ||||||
338 | if (mnWinHeight > mnMaxItemHeight) | ||||||
339 | nLineSize = mnWinHeight; | ||||||
340 | |||||||
341 | aLineSz.setHeight( nLineSize ); | ||||||
342 | } | ||||||
343 | else | ||||||
344 | { | ||||||
345 | nLineSize = mnMaxItemWidth; | ||||||
346 | aLineSz.setWidth( nLineSize ); | ||||||
347 | } | ||||||
348 | } | ||||||
349 | |||||||
350 | long nLeft, nTop, nRight, nBottom; | ||||||
351 | ImplCalcBorder(meAlign, nLeft, nTop, nRight, nBottom); | ||||||
352 | |||||||
353 | Size aTopLineSz(aLineSz); | ||||||
354 | Size aBottomLineSz(aLineSz); | ||||||
355 | |||||||
356 | if (mnWinStyle & WB_BORDER) | ||||||
357 | { | ||||||
358 | if (mbHorz) | ||||||
359 | { | ||||||
360 | aTopLineSz.AdjustHeight(TB_BORDER_OFFSET22 + nTop ); | ||||||
361 | aBottomLineSz.AdjustHeight(TB_BORDER_OFFSET22 + nBottom ); | ||||||
362 | |||||||
363 | if (mnCurLines == 1) | ||||||
364 | aTopLineSz.AdjustHeight(TB_BORDER_OFFSET22 + nBottom ); | ||||||
365 | } | ||||||
366 | else | ||||||
367 | { | ||||||
368 | aTopLineSz.AdjustWidth(TB_BORDER_OFFSET14 + nLeft ); | ||||||
369 | aBottomLineSz.AdjustWidth(TB_BORDER_OFFSET14 + nRight ); | ||||||
370 | |||||||
371 | if (mnCurLines == 1) | ||||||
372 | aTopLineSz.AdjustWidth(TB_BORDER_OFFSET14 + nLeft ); | ||||||
373 | } | ||||||
374 | } | ||||||
375 | |||||||
376 | if (mbLineSpacing) | ||||||
377 | { | ||||||
378 | if (mbHorz) | ||||||
379 | { | ||||||
380 | aLineSz.AdjustHeight(TB_LINESPACING3 ); | ||||||
381 | if (mnCurLines > 1) | ||||||
382 | aTopLineSz.AdjustHeight(TB_LINESPACING3 ); | ||||||
383 | } | ||||||
384 | else | ||||||
385 | { | ||||||
386 | aLineSz.AdjustWidth(TB_LINESPACING3 ); | ||||||
387 | if (mnCurLines > 1) | ||||||
388 | aTopLineSz.AdjustWidth(TB_LINESPACING3 ); | ||||||
389 | } | ||||||
390 | } | ||||||
391 | |||||||
392 | if (mbHorz) | ||||||
393 | { | ||||||
394 | long y = 0; | ||||||
395 | |||||||
396 | rRenderContext.DrawGradient(tools::Rectangle(0, y, aTopLineSz.Width(), y + aTopLineSz.Height()), g); | ||||||
397 | y += aTopLineSz.Height(); | ||||||
398 | |||||||
399 | while (y < (mnDY - aBottomLineSz.Height())) | ||||||
400 | { | ||||||
401 | rRenderContext.DrawGradient(tools::Rectangle(0, y, aLineSz.Width(), y + aLineSz.Height()), g); | ||||||
402 | y += aLineSz.Height(); | ||||||
403 | } | ||||||
404 | |||||||
405 | rRenderContext.DrawGradient(tools::Rectangle(0, y, aBottomLineSz.Width(), y + aBottomLineSz.Height()), g); | ||||||
406 | } | ||||||
407 | else | ||||||
408 | { | ||||||
409 | long x = 0; | ||||||
410 | |||||||
411 | rRenderContext.DrawGradient(tools::Rectangle(x, 0, x + aTopLineSz.Width(), aTopLineSz.Height()), g); | ||||||
412 | x += aTopLineSz.Width(); | ||||||
413 | |||||||
414 | while (x < (mnDX - aBottomLineSz.Width())) | ||||||
415 | { | ||||||
416 | rRenderContext.DrawGradient(tools::Rectangle(x, 0, x + aLineSz.Width(), aLineSz.Height()), g); | ||||||
417 | x += aLineSz.Width(); | ||||||
418 | } | ||||||
419 | |||||||
420 | rRenderContext.DrawGradient(tools::Rectangle( x, 0, x + aBottomLineSz.Width(), aBottomLineSz.Height()), g); | ||||||
421 | } | ||||||
422 | |||||||
423 | if( bLineColor ) | ||||||
424 | rRenderContext.SetLineColor( aOldCol ); | ||||||
425 | |||||||
426 | } | ||||||
427 | |||||||
428 | bool ToolBox::ImplDrawNativeBackground(vcl::RenderContext& rRenderContext) | ||||||
429 | { | ||||||
430 | // use NWF | ||||||
431 | tools::Rectangle aCtrlRegion(Point(), GetOutputSizePixel()); | ||||||
432 | |||||||
433 | return rRenderContext.DrawNativeControl( ControlType::Toolbar, mbHorz ? ControlPart::DrawBackgroundHorz : ControlPart::DrawBackgroundVert, | ||||||
434 | aCtrlRegion, ControlState::ENABLED, ImplControlValue(), OUString() ); | ||||||
435 | } | ||||||
436 | |||||||
437 | void ToolBox::ImplDrawTransparentBackground(const vcl::Region &rRegion) | ||||||
438 | { | ||||||
439 | // just invalidate to trigger paint of the parent | ||||||
440 | const bool bOldPaintLock = mpData->mbIsPaintLocked; | ||||||
441 | mpData->mbIsPaintLocked = true; | ||||||
442 | |||||||
443 | // send an invalidate to the first opaque parent and invalidate the whole hierarchy from there (noclipchildren) | ||||||
444 | Invalidate(rRegion, InvalidateFlags::Update | InvalidateFlags::NoClipChildren); | ||||||
445 | |||||||
446 | mpData->mbIsPaintLocked = bOldPaintLock; | ||||||
447 | } | ||||||
448 | |||||||
449 | void ToolBox::ImplDrawConstantBackground(vcl::RenderContext& rRenderContext, const vcl::Region &rRegion, bool bIsInPopupMode) | ||||||
450 | { | ||||||
451 | // draw a constant color | ||||||
452 | if (!bIsInPopupMode) | ||||||
453 | { | ||||||
454 | // default background | ||||||
455 | rRenderContext.Erase(rRegion.GetBoundRect()); | ||||||
456 | } | ||||||
457 | else | ||||||
458 | { | ||||||
459 | // use different color in popupmode | ||||||
460 | const StyleSettings rSettings = rRenderContext.GetSettings().GetStyleSettings(); | ||||||
461 | Wallpaper aWallpaper(rSettings.GetFaceGradientColor()); | ||||||
462 | rRenderContext.DrawWallpaper(rRegion.GetBoundRect(), aWallpaper); | ||||||
463 | } | ||||||
464 | } | ||||||
465 | |||||||
466 | void ToolBox::ImplDrawBackground(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) | ||||||
467 | { | ||||||
468 | // execute pending paint requests | ||||||
469 | ImplCheckUpdate(); | ||||||
470 | |||||||
471 | ImplDockingWindowWrapper* pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper(this); | ||||||
472 | bool bIsInPopupMode = ImplIsInPopupMode(); | ||||||
473 | |||||||
474 | vcl::Region aPaintRegion(rRect); | ||||||
475 | |||||||
476 | // make sure we do not invalidate/erase too much | ||||||
477 | if (IsInPaint()) | ||||||
478 | aPaintRegion.Intersect(GetActiveClipRegion()); | ||||||
479 | |||||||
480 | rRenderContext.Push(PushFlags::CLIPREGION); | ||||||
481 | rRenderContext.IntersectClipRegion( aPaintRegion ); | ||||||
482 | |||||||
483 | if (!pWrapper) | ||||||
484 | { | ||||||
485 | // no gradient for ordinary toolbars (not dockable) | ||||||
486 | if( !IsBackground() && !IsInPaint() ) | ||||||
487 | ImplDrawTransparentBackground(aPaintRegion); | ||||||
488 | else | ||||||
489 | ImplDrawConstantBackground(rRenderContext, aPaintRegion, bIsInPopupMode); | ||||||
490 | } | ||||||
491 | else | ||||||
492 | { | ||||||
493 | // toolbars known to the dockingmanager will be drawn using NWF or a gradient | ||||||
494 | // docked toolbars are transparent and NWF is already used in the docking area which is their common background | ||||||
495 | // so NWF is used here for floating toolbars only | ||||||
496 | bool bNativeOk = false; | ||||||
497 | if( ImplIsFloatingMode() && rRenderContext.IsNativeControlSupported( ControlType::Toolbar, ControlPart::Entire) ) | ||||||
498 | bNativeOk = ImplDrawNativeBackground(rRenderContext); | ||||||
499 | if (!bNativeOk) | ||||||
500 | { | ||||||
501 | const StyleSettings rSetting = Application::GetSettings().GetStyleSettings(); | ||||||
502 | const bool isHeader = GetAlign() == WindowAlign::Top && !rSetting.GetPersonaHeader().IsEmpty(); | ||||||
503 | const bool isFooter = GetAlign() == WindowAlign::Bottom && !rSetting.GetPersonaFooter().IsEmpty(); | ||||||
504 | if (!IsBackground() || isHeader || isFooter) | ||||||
505 | { | ||||||
506 | if (!IsInPaint()) | ||||||
507 | ImplDrawTransparentBackground(aPaintRegion); | ||||||
508 | } | ||||||
509 | else | ||||||
510 | ImplDrawGradientBackground(rRenderContext); | ||||||
511 | } | ||||||
512 | } | ||||||
513 | |||||||
514 | // restore clip region | ||||||
515 | rRenderContext.Pop(); | ||||||
516 | } | ||||||
517 | |||||||
518 | void ToolBox::ImplErase(vcl::RenderContext& rRenderContext, const tools::Rectangle &rRect, bool bHighlight, bool bHasOpenPopup) | ||||||
519 | { | ||||||
520 | // the background of non NWF buttons is painted in a constant color | ||||||
521 | // to have the same highlight color (transparency in DrawSelectionBackground()) | ||||||
522 | // items with open popups will also painted using a constant color | ||||||
523 | if (!mpData->mbNativeButtons && | ||||||
524 | (bHighlight || !(GetStyle() & WB_3DLOOK))) | ||||||
525 | { | ||||||
526 | if (GetStyle() & WB_3DLOOK) | ||||||
527 | { | ||||||
528 | rRenderContext.Push(PushFlags::LINECOLOR | PushFlags::FILLCOLOR); | ||||||
529 | rRenderContext.SetLineColor(); | ||||||
530 | if (bHasOpenPopup) | ||||||
531 | // choose the same color as the popup will use | ||||||
532 | rRenderContext.SetFillColor(rRenderContext.GetSettings().GetStyleSettings().GetFaceGradientColor()); | ||||||
533 | else | ||||||
534 | rRenderContext.SetFillColor(COL_WHITE); | ||||||
535 | |||||||
536 | rRenderContext.DrawRect(rRect); | ||||||
537 | rRenderContext.Pop(); | ||||||
538 | } | ||||||
539 | else | ||||||
540 | ImplDrawBackground(rRenderContext, rRect); | ||||||
541 | } | ||||||
542 | else | ||||||
543 | ImplDrawBackground(rRenderContext, rRect); | ||||||
544 | } | ||||||
545 | |||||||
546 | void ToolBox::ImplDrawBorder(vcl::RenderContext& rRenderContext) | ||||||
547 | { | ||||||
548 | const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings(); | ||||||
549 | long nDX = mnDX; | ||||||
550 | long nDY = mnDY; | ||||||
551 | |||||||
552 | ImplDockingWindowWrapper* pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper(this); | ||||||
553 | |||||||
554 | // draw borders for ordinary toolbars only (not dockable), do not draw borders for toolbars with WB_NOSHADOW bit set, | ||||||
555 | // e.g. Calc's formulabar | ||||||
556 | |||||||
557 | if( pWrapper || mnWinStyle & WB_NOSHADOW ) | ||||||
558 | return; | ||||||
559 | |||||||
560 | if (meAlign == WindowAlign::Bottom) | ||||||
561 | { | ||||||
562 | // draw bottom border | ||||||
563 | rRenderContext.SetLineColor( rStyleSettings.GetShadowColor() ); | ||||||
564 | rRenderContext.DrawLine( Point( 0, nDY-2 ), Point( nDX-1, nDY-2 ) ); | ||||||
565 | rRenderContext.SetLineColor( rStyleSettings.GetLightColor() ); | ||||||
566 | rRenderContext.DrawLine( Point( 0, nDY-1 ), Point( nDX-1, nDY-1 ) ); | ||||||
567 | } | ||||||
568 | else | ||||||
569 | { | ||||||
570 | // draw top border | ||||||
571 | rRenderContext.SetLineColor( rStyleSettings.GetShadowColor() ); | ||||||
572 | rRenderContext.DrawLine( Point( 0, 0 ), Point( nDX-1, 0 ) ); | ||||||
573 | rRenderContext.SetLineColor( rStyleSettings.GetLightColor() ); | ||||||
574 | rRenderContext.DrawLine( Point( 0, 1 ), Point( nDX-1, 1 ) ); | ||||||
575 | |||||||
576 | if (meAlign == WindowAlign::Left || meAlign == WindowAlign::Right) | ||||||
577 | { | ||||||
578 | if (meAlign == WindowAlign::Left) | ||||||
579 | { | ||||||
580 | // draw left-bottom border | ||||||
581 | rRenderContext.SetLineColor( rStyleSettings.GetShadowColor() ); | ||||||
582 | rRenderContext.DrawLine( Point( 0, 0 ), Point( 0, nDY-1 ) ); | ||||||
583 | rRenderContext.DrawLine( Point( 0, nDY-2 ), Point( nDX-1, nDY-2 ) ); | ||||||
584 | rRenderContext.SetLineColor( rStyleSettings.GetLightColor() ); | ||||||
585 | rRenderContext.DrawLine( Point( 1, 1 ), Point( 1, nDY-3 ) ); | ||||||
586 | rRenderContext.DrawLine( Point( 0, nDY-1 ), Point( nDX-1, nDY-1 ) ); | ||||||
587 | } | ||||||
588 | else | ||||||
589 | { | ||||||
590 | // draw right-bottom border | ||||||
591 | rRenderContext.SetLineColor( rStyleSettings.GetShadowColor() ); | ||||||
592 | rRenderContext.DrawLine( Point( nDX-2, 0 ), Point( nDX-2, nDY-3 ) ); | ||||||
593 | rRenderContext.DrawLine( Point( 0, nDY-2 ), Point( nDX-2, nDY-2 ) ); | ||||||
594 | rRenderContext.SetLineColor( rStyleSettings.GetLightColor() ); | ||||||
595 | rRenderContext.DrawLine( Point( nDX-1, 0 ), Point( nDX-1, nDY-1 ) ); | ||||||
596 | rRenderContext.DrawLine( Point( 0, nDY-1 ), Point( nDX-1, nDY-1 ) ); | ||||||
597 | } | ||||||
598 | } | ||||||
599 | } | ||||||
600 | |||||||
601 | if ( meAlign == WindowAlign::Bottom || meAlign == WindowAlign::Top ) | ||||||
602 | { | ||||||
603 | // draw right border | ||||||
604 | rRenderContext.SetLineColor( rStyleSettings.GetShadowColor() ); | ||||||
605 | rRenderContext.DrawLine( Point( nDX-2, 0 ), Point( nDX-2, nDY-1 ) ); | ||||||
606 | rRenderContext.SetLineColor( rStyleSettings.GetLightColor() ); | ||||||
607 | rRenderContext.DrawLine( Point( nDX-1, 0 ), Point( nDX-1, nDY-1 ) ); | ||||||
608 | } | ||||||
609 | } | ||||||
610 | |||||||
611 | static bool ImplIsFixedControl( const ImplToolItem *pItem ) | ||||||
612 | { | ||||||
613 | return ( pItem->mpWindow && | ||||||
614 | (pItem->mbNonInteractiveWindow || | ||||||
615 | pItem->mpWindow->GetType() == WindowType::FIXEDTEXT || | ||||||
616 | pItem->mpWindow->GetType() == WindowType::FIXEDLINE || | ||||||
617 | pItem->mpWindow->GetType() == WindowType::GROUPBOX) ); | ||||||
618 | } | ||||||
619 | |||||||
620 | const ImplToolItem *ToolBox::ImplGetFirstClippedItem() const | ||||||
621 | { | ||||||
622 | for (auto & item : mpData->m_aItems) | ||||||
623 | { | ||||||
624 | if( item.IsClipped() ) | ||||||
625 | return &item; | ||||||
626 | } | ||||||
627 | return nullptr; | ||||||
628 | } | ||||||
629 | |||||||
630 | Size ToolBox::ImplCalcSize( ImplToolItems::size_type nCalcLines, sal_uInt16 nCalcMode ) | ||||||
631 | { | ||||||
632 | long nMax; | ||||||
633 | long nLeft = 0; | ||||||
634 | long nTop = 0; | ||||||
635 | long nRight = 0; | ||||||
636 | long nBottom = 0; | ||||||
637 | Size aSize; | ||||||
638 | WindowAlign eOldAlign = meAlign; | ||||||
639 | bool bOldHorz = mbHorz; | ||||||
640 | bool bOldAssumeDocked = mpData->mbAssumeDocked; | ||||||
641 | bool bOldAssumeFloating = mpData->mbAssumeFloating; | ||||||
642 | |||||||
643 | if ( nCalcMode ) | ||||||
644 | { | ||||||
645 | bool bOldFloatingMode = ImplIsFloatingMode(); | ||||||
646 | |||||||
647 | mpData->mbAssumeDocked = false; | ||||||
648 | mpData->mbAssumeFloating = false; | ||||||
649 | |||||||
650 | if ( nCalcMode == TB_CALCMODE_HORZ1 ) | ||||||
651 | { | ||||||
652 | mpData->mbAssumeDocked = true; // force non-floating mode during calculation | ||||||
653 | ImplCalcBorder( WindowAlign::Top, nLeft, nTop, nRight, nBottom ); | ||||||
654 | mbHorz = true; | ||||||
655 | if ( mbHorz != bOldHorz ) | ||||||
656 | meAlign = WindowAlign::Top; | ||||||
657 | } | ||||||
658 | else if ( nCalcMode == TB_CALCMODE_VERT2 ) | ||||||
659 | { | ||||||
660 | mpData->mbAssumeDocked = true; // force non-floating mode during calculation | ||||||
661 | ImplCalcBorder( WindowAlign::Left, nLeft, nTop, nRight, nBottom ); | ||||||
662 | mbHorz = false; | ||||||
663 | if ( mbHorz != bOldHorz ) | ||||||
664 | meAlign = WindowAlign::Left; | ||||||
665 | } | ||||||
666 | else if ( nCalcMode == TB_CALCMODE_FLOAT3 ) | ||||||
667 | { | ||||||
668 | mpData->mbAssumeFloating = true; // force non-floating mode during calculation | ||||||
669 | nLeft = nTop = nRight = nBottom = 0; | ||||||
670 | mbHorz = true; | ||||||
671 | if ( mbHorz != bOldHorz ) | ||||||
672 | meAlign = WindowAlign::Top; | ||||||
673 | } | ||||||
674 | |||||||
675 | if ( (meAlign != eOldAlign) || (mbHorz != bOldHorz) || | ||||||
676 | (ImplIsFloatingMode() != bOldFloatingMode ) ) | ||||||
677 | mbCalc = true; | ||||||
678 | } | ||||||
679 | else | ||||||
680 | ImplCalcBorder( meAlign, nLeft, nTop, nRight, nBottom ); | ||||||
681 | |||||||
682 | ImplCalcItem(); | ||||||
683 | |||||||
684 | if( !nCalcMode && ImplIsFloatingMode() ) | ||||||
685 | { | ||||||
686 | aSize = ImplCalcFloatSize( nCalcLines ); | ||||||
687 | } | ||||||
688 | else | ||||||
689 | { | ||||||
690 | if ( mbHorz ) | ||||||
691 | { | ||||||
692 | if ( mnWinHeight > mnMaxItemHeight ) | ||||||
693 | aSize.setHeight( nCalcLines * mnWinHeight ); | ||||||
694 | else | ||||||
695 | aSize.setHeight( nCalcLines * mnMaxItemHeight ); | ||||||
696 | |||||||
697 | if ( mbLineSpacing ) | ||||||
698 | aSize.AdjustHeight((nCalcLines-1)*TB_LINESPACING3 ); | ||||||
699 | |||||||
700 | if ( mnWinStyle & WB_BORDER ) | ||||||
701 | aSize.AdjustHeight((TB_BORDER_OFFSET22*2) + nTop + nBottom ); | ||||||
702 | |||||||
703 | nMax = 0; | ||||||
704 | ImplCalcBreaks( TB_MAXNOSCROLL32765, &nMax, mbHorz ); | ||||||
705 | if ( nMax ) | ||||||
706 | aSize.AdjustWidth(nMax ); | ||||||
707 | |||||||
708 | if ( mnWinStyle & WB_BORDER ) | ||||||
709 | aSize.AdjustWidth((TB_BORDER_OFFSET14*2) + nLeft + nRight ); | ||||||
710 | } | ||||||
711 | else | ||||||
712 | { | ||||||
713 | aSize.setWidth( nCalcLines * mnMaxItemWidth ); | ||||||
714 | |||||||
715 | if ( mbLineSpacing ) | ||||||
716 | aSize.AdjustWidth((nCalcLines-1)*TB_LINESPACING3 ); | ||||||
717 | |||||||
718 | if ( mnWinStyle & WB_BORDER ) | ||||||
719 | aSize.AdjustWidth((TB_BORDER_OFFSET22*2) + nLeft + nRight ); | ||||||
720 | |||||||
721 | nMax = 0; | ||||||
722 | ImplCalcBreaks( TB_MAXNOSCROLL32765, &nMax, mbHorz ); | ||||||
723 | if ( nMax ) | ||||||
724 | aSize.AdjustHeight(nMax ); | ||||||
725 | |||||||
726 | if ( mnWinStyle & WB_BORDER ) | ||||||
727 | aSize.AdjustHeight((TB_BORDER_OFFSET14*2) + nTop + nBottom ); | ||||||
728 | } | ||||||
729 | } | ||||||
730 | // restore previous values | ||||||
731 | if ( nCalcMode ) | ||||||
732 | { | ||||||
733 | mpData->mbAssumeDocked = bOldAssumeDocked; | ||||||
734 | mpData->mbAssumeFloating = bOldAssumeFloating; | ||||||
735 | if ( (meAlign != eOldAlign) || (mbHorz != bOldHorz) ) | ||||||
736 | { | ||||||
737 | meAlign = eOldAlign; | ||||||
738 | mbHorz = bOldHorz; | ||||||
739 | mbCalc = true; | ||||||
740 | } | ||||||
741 | } | ||||||
742 | |||||||
743 | return aSize; | ||||||
744 | } | ||||||
745 | |||||||
746 | void ToolBox::ImplCalcFloatSizes() | ||||||
747 | { | ||||||
748 | if ( !maFloatSizes.empty() ) | ||||||
749 | return; | ||||||
750 | |||||||
751 | // calculate the minimal size, i.e. where the biggest item just fits | ||||||
752 | long nCalcSize = 0; | ||||||
753 | |||||||
754 | for (auto const& item : mpData->m_aItems) | ||||||
755 | { | ||||||
756 | if ( item.mbVisible ) | ||||||
757 | { | ||||||
758 | if ( item.mpWindow ) | ||||||
759 | { | ||||||
760 | long nTempSize = item.mpWindow->GetSizePixel().Width(); | ||||||
761 | if ( nTempSize > nCalcSize ) | ||||||
762 | nCalcSize = nTempSize; | ||||||
763 | } | ||||||
764 | else | ||||||
765 | { | ||||||
766 | if( item.maItemSize.Width() > nCalcSize ) | ||||||
767 | nCalcSize = item.maItemSize.Width(); | ||||||
768 | } | ||||||
769 | } | ||||||
770 | } | ||||||
771 | |||||||
772 | // calc an upper bound for ImplCalcBreaks below | ||||||
773 | long upperBoundWidth = nCalcSize * mpData->m_aItems.size(); | ||||||
774 | |||||||
775 | ImplToolItems::size_type nLines; | ||||||
776 | ImplToolItems::size_type nCalcLines; | ||||||
777 | ImplToolItems::size_type nTempLines; | ||||||
778 | long nMaxLineWidth; | ||||||
779 | nCalcLines = ImplCalcBreaks( nCalcSize, &nMaxLineWidth, true ); | ||||||
780 | |||||||
781 | maFloatSizes.reserve( nCalcLines ); | ||||||
782 | |||||||
783 | nTempLines = nLines = nCalcLines; | ||||||
784 | while ( nLines ) | ||||||
785 | { | ||||||
786 | long nHeight = ImplCalcSize( nTempLines, TB_CALCMODE_FLOAT3 ).Height(); | ||||||
787 | |||||||
788 | ImplToolSize aSize; | ||||||
789 | aSize.mnWidth = nMaxLineWidth+(TB_BORDER_OFFSET14*2); | ||||||
790 | aSize.mnHeight = nHeight; | ||||||
791 | aSize.mnLines = nTempLines; | ||||||
792 | maFloatSizes.push_back( aSize ); | ||||||
793 | nLines--; | ||||||
794 | if ( nLines ) | ||||||
795 | { | ||||||
796 | do | ||||||
797 | { | ||||||
798 | nCalcSize += mnMaxItemWidth; | ||||||
799 | nTempLines = ImplCalcBreaks( nCalcSize, &nMaxLineWidth, true ); | ||||||
800 | } | ||||||
801 | while ((nCalcSize < upperBoundWidth) && (nLines < nTempLines)); // implies nTempLines>1 | ||||||
802 | if ( nTempLines < nLines ) | ||||||
803 | nLines = nTempLines; | ||||||
804 | } | ||||||
805 | } | ||||||
806 | } | ||||||
807 | |||||||
808 | Size ToolBox::ImplCalcFloatSize( ImplToolItems::size_type& rLines ) | ||||||
809 | { | ||||||
810 | ImplCalcFloatSizes(); | ||||||
811 | |||||||
812 | if ( !rLines ) | ||||||
813 | { | ||||||
814 | rLines = mnFloatLines; | ||||||
815 | if ( !rLines ) | ||||||
816 | rLines = mnLines; | ||||||
817 | } | ||||||
818 | |||||||
819 | sal_uInt16 i = 0; | ||||||
820 | while ( i + 1u < maFloatSizes.size() && rLines < maFloatSizes[i].mnLines ) | ||||||
821 | { | ||||||
822 | i++; | ||||||
823 | } | ||||||
824 | |||||||
825 | Size aSize( maFloatSizes[i].mnWidth, maFloatSizes[i].mnHeight ); | ||||||
826 | rLines = maFloatSizes[i].mnLines; | ||||||
827 | |||||||
828 | return aSize; | ||||||
829 | } | ||||||
830 | |||||||
831 | void ToolBox::ImplCalcMinMaxFloatSize( Size& rMinSize, Size& rMaxSize ) | ||||||
832 | { | ||||||
833 | ImplCalcFloatSizes(); | ||||||
834 | |||||||
835 | sal_uInt16 i = 0; | ||||||
836 | rMinSize = Size( maFloatSizes[i].mnWidth, maFloatSizes[i].mnHeight ); | ||||||
837 | rMaxSize = Size( maFloatSizes[i].mnWidth, maFloatSizes[i].mnHeight ); | ||||||
838 | while ( ++i < maFloatSizes.size() ) | ||||||
839 | { | ||||||
840 | if( maFloatSizes[i].mnWidth < rMinSize.Width() ) | ||||||
841 | rMinSize.setWidth( maFloatSizes[i].mnWidth ); | ||||||
842 | if( maFloatSizes[i].mnHeight < rMinSize.Height() ) | ||||||
843 | rMinSize.setHeight( maFloatSizes[i].mnHeight ); | ||||||
844 | |||||||
845 | if( maFloatSizes[i].mnWidth > rMaxSize.Width() ) | ||||||
846 | rMaxSize.setWidth( maFloatSizes[i].mnWidth ); | ||||||
847 | if( maFloatSizes[i].mnHeight > rMaxSize.Height() ) | ||||||
848 | rMaxSize.setHeight( maFloatSizes[i].mnHeight ); | ||||||
849 | } | ||||||
850 | } | ||||||
851 | |||||||
852 | void ToolBox::ImplSetMinMaxFloatSize() | ||||||
853 | { | ||||||
854 | ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( this ); | ||||||
855 | Size aMinSize, aMaxSize; | ||||||
856 | ImplCalcMinMaxFloatSize( aMinSize, aMaxSize ); | ||||||
857 | if( pWrapper ) | ||||||
858 | { | ||||||
859 | pWrapper->SetMinOutputSizePixel( aMinSize ); | ||||||
860 | pWrapper->SetMaxOutputSizePixel( aMaxSize ); | ||||||
861 | pWrapper->ShowTitleButton( TitleButton::Menu, bool( GetMenuType() & ToolBoxMenuType::Customize) ); | ||||||
862 | } | ||||||
863 | else | ||||||
864 | { | ||||||
865 | // TODO: change SetMinOutputSizePixel to be not inline | ||||||
866 | SetMinOutputSizePixel( aMinSize ); | ||||||
867 | SetMaxOutputSizePixel( aMaxSize ); | ||||||
868 | } | ||||||
869 | } | ||||||
870 | |||||||
871 | ToolBox::ImplToolItems::size_type ToolBox::ImplCalcLines( long nToolSize ) const | ||||||
872 | { | ||||||
873 | long nLineHeight; | ||||||
874 | |||||||
875 | if ( mbHorz ) | ||||||
876 | { | ||||||
877 | if ( mnWinHeight > mnMaxItemHeight ) | ||||||
878 | nLineHeight = mnWinHeight; | ||||||
879 | else | ||||||
880 | nLineHeight = mnMaxItemHeight; | ||||||
881 | } | ||||||
882 | else | ||||||
883 | nLineHeight = mnMaxItemWidth; | ||||||
884 | |||||||
885 | if ( mnWinStyle & WB_BORDER ) | ||||||
886 | nToolSize -= TB_BORDER_OFFSET22*2; | ||||||
887 | |||||||
888 | if ( mbLineSpacing ) | ||||||
889 | { | ||||||
890 | nLineHeight += TB_LINESPACING3; | ||||||
891 | nToolSize += TB_LINESPACING3; | ||||||
892 | } | ||||||
893 | |||||||
894 | // #i91917# always report at least one line | ||||||
895 | long nLines = nToolSize/nLineHeight; | ||||||
896 | if( nLines < 1 ) | ||||||
897 | nLines = 1; | ||||||
898 | |||||||
899 | return nLines; | ||||||
900 | } | ||||||
901 | |||||||
902 | sal_uInt16 ToolBox::ImplTestLineSize( const Point& rPos ) const | ||||||
903 | { | ||||||
904 | if ( !ImplIsFloatingMode() && | ||||||
905 | (!mbScroll || (mnLines > 1) || (mnCurLines > mnVisLines)) ) | ||||||
906 | { | ||||||
907 | WindowAlign eAlign = GetAlign(); | ||||||
908 | |||||||
909 | if ( eAlign == WindowAlign::Left ) | ||||||
910 | { | ||||||
911 | if ( rPos.X() > mnDX-DOCK_LINEOFFSET3 ) | ||||||
912 | return DOCK_LINEHSIZE(sal_uInt16(0x0001)) | DOCK_LINERIGHT(sal_uInt16(0x1000)); | ||||||
913 | } | ||||||
914 | else if ( eAlign == WindowAlign::Top ) | ||||||
915 | { | ||||||
916 | if ( rPos.Y() > mnDY-DOCK_LINEOFFSET3 ) | ||||||
917 | return DOCK_LINEVSIZE(sal_uInt16(0x0002)) | DOCK_LINEBOTTOM(sal_uInt16(0x2000)); | ||||||
918 | } | ||||||
919 | else if ( eAlign == WindowAlign::Right ) | ||||||
920 | { | ||||||
921 | if ( rPos.X() < DOCK_LINEOFFSET3 ) | ||||||
922 | return DOCK_LINEHSIZE(sal_uInt16(0x0001)) | DOCK_LINELEFT(sal_uInt16(0x4000)); | ||||||
923 | } | ||||||
924 | else if ( eAlign == WindowAlign::Bottom ) | ||||||
925 | { | ||||||
926 | if ( rPos.Y() < DOCK_LINEOFFSET3 ) | ||||||
927 | return DOCK_LINEVSIZE(sal_uInt16(0x0002)) | DOCK_LINETOP(sal_uInt16(0x8000)); | ||||||
928 | } | ||||||
929 | } | ||||||
930 | |||||||
931 | return 0; | ||||||
932 | } | ||||||
933 | |||||||
934 | void ToolBox::ImplLineSizing( const Point& rPos, tools::Rectangle& rRect, sal_uInt16 nLineMode ) | ||||||
935 | { | ||||||
936 | bool bHorz; | ||||||
937 | long nOneLineSize; | ||||||
938 | long nCurSize; | ||||||
939 | long nMaxSize; | ||||||
940 | long nSize; | ||||||
941 | Size aSize; | ||||||
942 | |||||||
943 | if ( nLineMode & DOCK_LINERIGHT(sal_uInt16(0x1000)) ) | ||||||
944 | { | ||||||
945 | nCurSize = rPos.X() - rRect.Left(); | ||||||
946 | bHorz = false; | ||||||
947 | } | ||||||
948 | else if ( nLineMode & DOCK_LINEBOTTOM(sal_uInt16(0x2000)) ) | ||||||
949 | { | ||||||
950 | nCurSize = rPos.Y() - rRect.Top(); | ||||||
951 | bHorz = true; | ||||||
952 | } | ||||||
953 | else if ( nLineMode & DOCK_LINELEFT(sal_uInt16(0x4000)) ) | ||||||
954 | { | ||||||
955 | nCurSize = rRect.Right() - rPos.X(); | ||||||
956 | bHorz = false; | ||||||
957 | } | ||||||
958 | else if ( nLineMode & DOCK_LINETOP(sal_uInt16(0x8000)) ) | ||||||
959 | { | ||||||
960 | nCurSize = rRect.Bottom() - rPos.Y(); | ||||||
961 | bHorz = true; | ||||||
962 | } | ||||||
963 | else { | ||||||
964 | OSL_FAIL( "ImplLineSizing: Trailing else" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/vcl/source/window/toolbox.cxx" ":" "964" ": "), "%s", "ImplLineSizing: Trailing else"); } } while (false); | ||||||
965 | nCurSize = 0; | ||||||
966 | bHorz = false; | ||||||
967 | } | ||||||
968 | |||||||
969 | Size aWinSize = GetSizePixel(); | ||||||
970 | ImplToolItems::size_type nMaxLines = std::max(mnLines, mnCurLines); | ||||||
971 | if ( nMaxLines > TB_MAXLINES5 ) | ||||||
972 | nMaxLines = TB_MAXLINES5; | ||||||
973 | if ( bHorz ) | ||||||
974 | { | ||||||
975 | nOneLineSize = ImplCalcSize( 1 ).Height(); | ||||||
976 | nMaxSize = - 20; | ||||||
977 | if ( nMaxSize < aWinSize.Height() ) | ||||||
978 | nMaxSize = aWinSize.Height(); | ||||||
979 | } | ||||||
980 | else | ||||||
981 | { | ||||||
982 | nOneLineSize = ImplCalcSize( 1 ).Width(); | ||||||
983 | nMaxSize = - 20; | ||||||
984 | if ( nMaxSize < aWinSize.Width() ) | ||||||
985 | nMaxSize = aWinSize.Width(); | ||||||
986 | } | ||||||
987 | |||||||
988 | ImplToolItems::size_type i = 1; | ||||||
989 | if ( nCurSize <= nOneLineSize ) | ||||||
990 | nSize = nOneLineSize; | ||||||
991 | else | ||||||
992 | { | ||||||
993 | nSize = 0; | ||||||
994 | while ( (nSize < nCurSize) && (i < nMaxLines) ) | ||||||
995 | { | ||||||
996 | i++; | ||||||
997 | aSize = ImplCalcSize( i ); | ||||||
998 | if ( bHorz ) | ||||||
999 | nSize = aSize.Height(); | ||||||
1000 | else | ||||||
1001 | nSize = aSize.Width(); | ||||||
1002 | if ( nSize > nMaxSize ) | ||||||
1003 | { | ||||||
1004 | i--; | ||||||
1005 | aSize = ImplCalcSize( i ); | ||||||
1006 | if ( bHorz ) | ||||||
1007 | nSize = aSize.Height(); | ||||||
1008 | else | ||||||
1009 | nSize = aSize.Width(); | ||||||
1010 | break; | ||||||
1011 | } | ||||||
1012 | } | ||||||
1013 | } | ||||||
1014 | |||||||
1015 | if ( nLineMode & DOCK_LINERIGHT(sal_uInt16(0x1000)) ) | ||||||
1016 | rRect.SetRight( rRect.Left()+nSize-1 ); | ||||||
1017 | else if ( nLineMode & DOCK_LINEBOTTOM(sal_uInt16(0x2000)) ) | ||||||
1018 | rRect.SetBottom( rRect.Top()+nSize-1 ); | ||||||
1019 | else if ( nLineMode & DOCK_LINELEFT(sal_uInt16(0x4000)) ) | ||||||
1020 | rRect.SetLeft( rRect.Right()-nSize ); | ||||||
1021 | else | ||||||
1022 | rRect.SetTop( rRect.Bottom()-nSize ); | ||||||
1023 | |||||||
1024 | mnDockLines = i; | ||||||
1025 | } | ||||||
1026 | |||||||
1027 | ImplTBDragMgr::ImplTBDragMgr() | ||||||
1028 | : mpDragBox(nullptr) | ||||||
1029 | , mnLineMode(0) | ||||||
1030 | , mnStartLines(0) | ||||||
1031 | { | ||||||
1032 | maAccel.InsertItem( KEY_RETURN, vcl::KeyCode( KEY_RETURN ) ); | ||||||
1033 | maAccel.InsertItem( KEY_ESCAPE, vcl::KeyCode( KEY_ESCAPE ) ); | ||||||
1034 | maAccel.SetSelectHdl( LINK( this, ImplTBDragMgr, SelectHdl )::tools::detail::makeLink( ::tools::detail::castTo<ImplTBDragMgr *>(this), &ImplTBDragMgr::LinkStubSelectHdl) ); | ||||||
1035 | } | ||||||
1036 | |||||||
1037 | void ImplTBDragMgr::StartDragging( ToolBox* pToolBox, | ||||||
1038 | const Point& rPos, const tools::Rectangle& rRect, | ||||||
1039 | sal_uInt16 nDragLineMode ) | ||||||
1040 | { | ||||||
1041 | mpDragBox = pToolBox; | ||||||
1042 | pToolBox->CaptureMouse(); | ||||||
1043 | pToolBox->mbDragging = true; | ||||||
1044 | Application::InsertAccel( &maAccel ); | ||||||
1045 | |||||||
1046 | mnLineMode = nDragLineMode; | ||||||
1047 | mnStartLines = pToolBox->mnDockLines; | ||||||
1048 | |||||||
1049 | // calculate MouseOffset | ||||||
1050 | maMouseOff.setX( rRect.Left() - rPos.X() ); | ||||||
1051 | maMouseOff.setY( rRect.Top() - rPos.Y() ); | ||||||
1052 | maRect = rRect; | ||||||
1053 | maStartRect = rRect; | ||||||
1054 | pToolBox->ShowTracking( maRect ); | ||||||
1055 | } | ||||||
1056 | |||||||
1057 | void ImplTBDragMgr::Dragging( const Point& rPos ) | ||||||
1058 | { | ||||||
1059 | mpDragBox->ImplLineSizing( rPos, maRect, mnLineMode ); | ||||||
1060 | Point aOff = mpDragBox->OutputToScreenPixel( Point() ); | ||||||
1061 | maRect.Move( aOff.X(), aOff.Y() ); | ||||||
1062 | mpDragBox->Docking( rPos, maRect ); | ||||||
1063 | maRect.Move( -aOff.X(), -aOff.Y() ); | ||||||
1064 | mpDragBox->ShowTracking( maRect ); | ||||||
1065 | } | ||||||
1066 | |||||||
1067 | void ImplTBDragMgr::EndDragging( bool bOK ) | ||||||
1068 | { | ||||||
1069 | mpDragBox->HideTracking(); | ||||||
1070 | if (mpDragBox->IsMouseCaptured()) | ||||||
1071 | mpDragBox->ReleaseMouse(); | ||||||
1072 | mpDragBox->mbDragging = false; | ||||||
1073 | Application::RemoveAccel( &maAccel ); | ||||||
1074 | |||||||
1075 | if ( !bOK ) | ||||||
1076 | { | ||||||
1077 | mpDragBox->mnDockLines = mnStartLines; | ||||||
1078 | mpDragBox->EndDocking( maStartRect, false ); | ||||||
1079 | } | ||||||
1080 | else | ||||||
1081 | mpDragBox->EndDocking( maRect, false ); | ||||||
1082 | mnStartLines = 0; | ||||||
1083 | |||||||
1084 | mpDragBox = nullptr; | ||||||
1085 | } | ||||||
1086 | |||||||
1087 | IMPL_LINK( ImplTBDragMgr, SelectHdl, Accelerator&, rAccel, void )void ImplTBDragMgr::LinkStubSelectHdl(void * instance, Accelerator & data) { return static_cast<ImplTBDragMgr *>(instance )->SelectHdl(data); } void ImplTBDragMgr::SelectHdl(Accelerator & rAccel) | ||||||
1088 | { | ||||||
1089 | if ( rAccel.GetCurItemId() == KEY_ESCAPE ) | ||||||
1090 | EndDragging( false ); | ||||||
1091 | else | ||||||
1092 | EndDragging(); | ||||||
1093 | } | ||||||
1094 | |||||||
1095 | void ToolBox::ImplInitToolBoxData() | ||||||
1096 | { | ||||||
1097 | // initialize variables | ||||||
1098 | ImplGetWindowImpl()->mbToolBox = true; | ||||||
1099 | mpData.reset(new ImplToolBoxPrivateData); | ||||||
1100 | |||||||
1101 | mpFloatWin = nullptr; | ||||||
1102 | mnDX = 0; | ||||||
1103 | mnDY = 0; | ||||||
1104 | mnMaxItemWidth = 0; | ||||||
1105 | mnMaxItemHeight = 0; | ||||||
1106 | mnWinHeight = 0; | ||||||
1107 | mnLeftBorder = 0; | ||||||
1108 | mnTopBorder = 0; | ||||||
1109 | mnRightBorder = 0; | ||||||
1110 | mnBottomBorder = 0; | ||||||
1111 | mnLastResizeDY = 0; | ||||||
1112 | mnOutStyle = TOOLBOX_STYLE_FLAT; // force flat buttons since NWF | ||||||
1113 | mnHighItemId = 0; | ||||||
1114 | mnCurItemId = 0; | ||||||
1115 | mnDownItemId = 0; | ||||||
1116 | mnCurPos = ITEM_NOTFOUND; | ||||||
1117 | mnLines = 1; | ||||||
1118 | mnCurLine = 1; | ||||||
1119 | mnCurLines = 1; | ||||||
1120 | mnVisLines = 1; | ||||||
1121 | mnFloatLines = 0; | ||||||
1122 | mnDockLines = 0; | ||||||
1123 | mnMouseModifier = 0; | ||||||
1124 | mbDrag = false; | ||||||
1125 | mbUpper = false; | ||||||
1126 | mbLower = false; | ||||||
1127 | mbIn = false; | ||||||
1128 | mbCalc = true; | ||||||
1129 | mbFormat = false; | ||||||
1130 | mbFullPaint = false; | ||||||
1131 | mbHorz = true; | ||||||
1132 | mbScroll = false; | ||||||
1133 | mbLastFloatMode = false; | ||||||
1134 | mbCustomize = false; | ||||||
1135 | mbDragging = false; | ||||||
1136 | mbIsKeyEvent = false; | ||||||
1137 | mbChangingHighlight = false; | ||||||
1138 | mbImagesMirrored = false; | ||||||
1139 | mbLineSpacing = false; | ||||||
1140 | mbIsArranged = false; | ||||||
1141 | meButtonType = ButtonType::SYMBOLONLY; | ||||||
1142 | meAlign = WindowAlign::Top; | ||||||
1143 | meDockAlign = WindowAlign::Top; | ||||||
1144 | meLastStyle = PointerStyle::Arrow; | ||||||
1145 | mnWinStyle = 0; | ||||||
1146 | meLayoutMode = ToolBoxLayoutMode::Normal; | ||||||
1147 | meTextPosition = ToolBoxTextPosition::Right; | ||||||
1148 | mnLastFocusItemId = 0; | ||||||
1149 | mnActivateCount = 0; | ||||||
1150 | mnImagesRotationAngle = 0; | ||||||
1151 | |||||||
1152 | mpStatusListener = new VclStatusListener<ToolBox>(this, ".uno:ImageOrientation"); | ||||||
1153 | mpStatusListener->startListening(); | ||||||
1154 | |||||||
1155 | mpIdle.reset(new Idle("vcl::ToolBox maIdle update")); | ||||||
1156 | mpIdle->SetPriority( TaskPriority::RESIZE ); | ||||||
1157 | mpIdle->SetInvokeHandler( LINK( this, ToolBox, ImplUpdateHdl )::tools::detail::makeLink( ::tools::detail::castTo<ToolBox *>(this), &ToolBox::LinkStubImplUpdateHdl) ); | ||||||
1158 | |||||||
1159 | // set timeout and handler for dropdown items | ||||||
1160 | mpData->maDropdownTimer.SetTimeout( 250 ); | ||||||
1161 | mpData->maDropdownTimer.SetInvokeHandler( LINK( this, ToolBox, ImplDropdownLongClickHdl )::tools::detail::makeLink( ::tools::detail::castTo<ToolBox *>(this), &ToolBox::LinkStubImplDropdownLongClickHdl) ); | ||||||
1162 | mpData->maDropdownTimer.SetDebugName( "vcl::ToolBox mpData->maDropdownTimer" ); | ||||||
1163 | } | ||||||
1164 | |||||||
1165 | void ToolBox::ImplInit( vcl::Window* pParent, WinBits nStyle ) | ||||||
1166 | { | ||||||
1167 | // initialize variables | ||||||
1168 | mbScroll = (nStyle & WB_SCROLL) != 0; | ||||||
1169 | mnWinStyle = nStyle; | ||||||
1170 | |||||||
1171 | DockingWindow::ImplInit( pParent, nStyle & ~WB_BORDER ); | ||||||
1172 | |||||||
1173 | // dockingwindow's ImplInit removes some bits, so restore them here to allow keyboard handling for toolbars | ||||||
1174 | ImplGetWindowImpl()->mnStyle |= WB_TABSTOP|WB_NODIALOGCONTROL; // always set WB_TABSTOP for ToolBars | ||||||
1175 | ImplGetWindowImpl()->mnStyle &= ~WB_DIALOGCONTROL; | ||||||
1176 | |||||||
1177 | ImplInitSettings(true, true, true); | ||||||
1178 | } | ||||||
1179 | |||||||
1180 | void ToolBox::ApplyForegroundSettings(vcl::RenderContext& rRenderContext, const StyleSettings& rStyleSettings) | ||||||
1181 | { | ||||||
1182 | Color aColor; | ||||||
1183 | if (IsControlForeground()) | ||||||
1184 | aColor = GetControlForeground(); | ||||||
1185 | else if (Window::GetStyle() & WB_3DLOOK) | ||||||
1186 | aColor = rStyleSettings.GetButtonTextColor(); | ||||||
1187 | else | ||||||
1188 | aColor = rStyleSettings.GetWindowTextColor(); | ||||||
1189 | rRenderContext.SetTextColor(aColor); | ||||||
1190 | rRenderContext.SetTextFillColor(); | ||||||
1191 | } | ||||||
1192 | |||||||
1193 | void ToolBox::ApplyBackgroundSettings(vcl::RenderContext& rRenderContext, const StyleSettings& rStyleSettings) | ||||||
1194 | { | ||||||
1195 | if (IsControlBackground()) | ||||||
1196 | { | ||||||
1197 | rRenderContext.SetBackground(GetControlBackground()); | ||||||
1198 | SetPaintTransparent(false); | ||||||
1199 | SetParentClipMode(); | ||||||
1200 | } | ||||||
1201 | else | ||||||
1202 | { | ||||||
1203 | if (rRenderContext.IsNativeControlSupported(ControlType::Toolbar, ControlPart::Entire) | ||||||
1204 | || (GetAlign() == WindowAlign::Top && !Application::GetSettings().GetStyleSettings().GetPersonaHeader().IsEmpty()) | ||||||
1205 | || (GetAlign() == WindowAlign::Bottom && !Application::GetSettings().GetStyleSettings().GetPersonaFooter().IsEmpty())) | ||||||
1206 | { | ||||||
1207 | rRenderContext.SetBackground(); | ||||||
1208 | rRenderContext.SetTextColor(rStyleSettings.GetToolTextColor()); | ||||||
1209 | SetPaintTransparent(true); | ||||||
1210 | SetParentClipMode(ParentClipMode::NoClip); | ||||||
1211 | mpData->maDisplayBackground = Wallpaper(rStyleSettings.GetFaceColor()); | ||||||
1212 | } | ||||||
1213 | else | ||||||
1214 | { | ||||||
1215 | Color aColor; | ||||||
1216 | if (Window::GetStyle() & WB_3DLOOK) | ||||||
1217 | aColor = rStyleSettings.GetFaceColor(); | ||||||
1218 | else | ||||||
1219 | aColor = rStyleSettings.GetWindowColor(); | ||||||
1220 | rRenderContext.SetBackground(aColor); | ||||||
1221 | SetPaintTransparent(false); | ||||||
1222 | SetParentClipMode(); | ||||||
1223 | } | ||||||
1224 | } | ||||||
1225 | } | ||||||
1226 | |||||||
1227 | void ToolBox::ApplySettings(vcl::RenderContext& rRenderContext) | ||||||
1228 | { | ||||||
1229 | mpData->mbNativeButtons = rRenderContext.IsNativeControlSupported(ControlType::Toolbar, ControlPart::Button); | ||||||
1230 | |||||||
1231 | const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings(); | ||||||
1232 | |||||||
1233 | ApplyControlFont(rRenderContext, rStyleSettings.GetToolFont()); | ||||||
1234 | ApplyForegroundSettings(rRenderContext, rStyleSettings); | ||||||
1235 | ApplyBackgroundSettings(rRenderContext, rStyleSettings); | ||||||
1236 | } | ||||||
1237 | |||||||
1238 | void ToolBox::ImplInitSettings(bool bFont, bool bForeground, bool bBackground) | ||||||
1239 | { | ||||||
1240 | mpData->mbNativeButtons = IsNativeControlSupported( ControlType::Toolbar, ControlPart::Button ); | ||||||
1241 | |||||||
1242 | const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); | ||||||
1243 | |||||||
1244 | if (bFont) | ||||||
1245 | ApplyControlFont(*this, rStyleSettings.GetToolFont()); | ||||||
1246 | if (bForeground || bFont) | ||||||
1247 | ApplyForegroundSettings(*this, rStyleSettings); | ||||||
1248 | if (bBackground) | ||||||
1249 | { | ||||||
1250 | ApplyBackgroundSettings(*this, rStyleSettings); | ||||||
1251 | EnableChildTransparentMode(IsPaintTransparent()); | ||||||
1252 | } | ||||||
1253 | } | ||||||
1254 | |||||||
1255 | void ToolBox::doDeferredInit(WinBits nBits) | ||||||
1256 | { | ||||||
1257 | VclPtr<vcl::Window> pParent = mpDialogParent; | ||||||
1258 | mpDialogParent = nullptr; | ||||||
1259 | ImplInit(pParent, nBits); | ||||||
1260 | mbIsDeferredInit = false; | ||||||
1261 | } | ||||||
1262 | |||||||
1263 | void ToolBox::queue_resize(StateChangedType eReason) | ||||||
1264 | { | ||||||
1265 | Window::queue_resize(eReason); | ||||||
1266 | } | ||||||
1267 | |||||||
1268 | ToolBox::ToolBox( vcl::Window* pParent, WinBits nStyle ) : | ||||||
1269 | DockingWindow( WindowType::TOOLBOX ) | ||||||
1270 | { | ||||||
1271 | ImplInitToolBoxData(); | ||||||
1272 | ImplInit( pParent, nStyle ); | ||||||
1273 | } | ||||||
1274 | |||||||
1275 | ToolBox::ToolBox(vcl::Window* pParent, const OString& rID, | ||||||
1276 | const OUString& rUIXMLDescription, const css::uno::Reference<css::frame::XFrame> &rFrame) | ||||||
1277 | : DockingWindow(WindowType::TOOLBOX) | ||||||
1278 | { | ||||||
1279 | ImplInitToolBoxData(); | ||||||
1280 | |||||||
1281 | loadUI(pParent, rID, rUIXMLDescription, rFrame); | ||||||
1282 | |||||||
1283 | // calculate size of floating windows and switch if the | ||||||
1284 | // toolbox is initially in floating mode | ||||||
1285 | if ( ImplIsFloatingMode() ) | ||||||
1286 | mbHorz = true; | ||||||
1287 | else | ||||||
1288 | Resize(); | ||||||
1289 | |||||||
1290 | if (!(GetStyle() & WB_HIDE)) | ||||||
1291 | Show(); | ||||||
1292 | } | ||||||
1293 | |||||||
1294 | ToolBox::~ToolBox() | ||||||
1295 | { | ||||||
1296 | disposeOnce(); | ||||||
1297 | } | ||||||
1298 | |||||||
1299 | void ToolBox::dispose() | ||||||
1300 | { | ||||||
1301 | // #103005# make sure our activate/deactivate balance is right | ||||||
1302 | while( mnActivateCount > 0 ) | ||||||
1303 | Deactivate(); | ||||||
1304 | |||||||
1305 | // terminate popupmode if the floating window is | ||||||
1306 | // still connected | ||||||
1307 | if ( mpFloatWin ) | ||||||
1308 | mpFloatWin->EndPopupMode( FloatWinPopupEndFlags::Cancel ); | ||||||
1309 | mpFloatWin = nullptr; | ||||||
1310 | |||||||
1311 | // delete private data | ||||||
1312 | mpData.reset(); | ||||||
1313 | |||||||
1314 | ImplSVData* pSVData = ImplGetSVData(); | ||||||
1315 | delete pSVData->maCtrlData.mpTBDragMgr; | ||||||
1316 | pSVData->maCtrlData.mpTBDragMgr = nullptr; | ||||||
1317 | |||||||
1318 | if (mpStatusListener.is()) | ||||||
1319 | mpStatusListener->dispose(); | ||||||
1320 | |||||||
1321 | mpFloatWin.clear(); | ||||||
1322 | |||||||
1323 | mpIdle.reset(); | ||||||
1324 | |||||||
1325 | DockingWindow::dispose(); | ||||||
1326 | } | ||||||
1327 | |||||||
1328 | ImplToolItem* ToolBox::ImplGetItem( sal_uInt16 nItemId ) const | ||||||
1329 | { | ||||||
1330 | if (!mpData) | ||||||
1331 | return nullptr; | ||||||
1332 | |||||||
1333 | for (auto & item : mpData->m_aItems) | ||||||
1334 | { | ||||||
1335 | if ( item.mnId == nItemId ) | ||||||
1336 | return &item; | ||||||
1337 | } | ||||||
1338 | |||||||
1339 | return nullptr; | ||||||
1340 | } | ||||||
1341 | |||||||
1342 | static void ImplAddButtonBorder( long &rWidth, long& rHeight, bool bNativeButtons ) | ||||||
1343 | { | ||||||
1344 | rWidth += SMALLBUTTON_HSIZE7; | ||||||
1345 | rHeight += SMALLBUTTON_VSIZE7; | ||||||
1346 | |||||||
1347 | if( bNativeButtons ) | ||||||
1348 | { | ||||||
1349 | // give more border space for rounded buttons | ||||||
1350 | rWidth += 2; | ||||||
1351 | rHeight += 4; | ||||||
1352 | } | ||||||
1353 | } | ||||||
1354 | |||||||
1355 | bool ToolBox::ImplCalcItem() | ||||||
1356 | { | ||||||
1357 | // recalc required ? | ||||||
1358 | if ( !mbCalc ) | ||||||
1359 | return false; | ||||||
1360 | |||||||
1361 | ImplDisableFlatButtons(); | ||||||
1362 | |||||||
1363 | OutputDevice *pDefault = Application::GetDefaultDevice(); | ||||||
1364 | float fScaleFactor = pDefault ? pDefault->GetDPIScaleFactor() : 1.0; | ||||||
1365 | |||||||
1366 | long nDefWidth; | ||||||
1367 | long nDefHeight; | ||||||
1368 | long nMaxWidth = 0; | ||||||
1369 | long nMaxHeight = 0; | ||||||
1370 | long nMinWidth = 6; | ||||||
1371 | long nMinHeight = 6; | ||||||
1372 | long nDropDownArrowWidth = TB_DROPDOWNARROWWIDTH11 * fScaleFactor; | ||||||
1373 | #ifdef IOS | ||||||
1374 | nDropDownArrowWidth *= 3; | ||||||
1375 | #endif | ||||||
1376 | |||||||
1377 | // set defaults if image or text is needed but empty | ||||||
1378 | nDefWidth = GetDefaultImageSize().Width(); | ||||||
1379 | nDefHeight = GetDefaultImageSize().Height(); | ||||||
1380 | |||||||
1381 | mnWinHeight = 0; | ||||||
1382 | // determine minimum size necessary in NWF | ||||||
1383 | { | ||||||
1384 | tools::Rectangle aRect( Point( 0, 0 ), Size( nMinWidth, nMinHeight ) ); | ||||||
1385 | tools::Rectangle aReg( aRect ); | ||||||
1386 | ImplControlValue aVal; | ||||||
1387 | tools::Rectangle aNativeBounds, aNativeContent; | ||||||
1388 | if( IsNativeControlSupported( ControlType::Toolbar, ControlPart::Button ) ) | ||||||
1389 | { | ||||||
1390 | if( GetNativeControlRegion( ControlType::Toolbar, ControlPart::Button, | ||||||
1391 | aReg, | ||||||
1392 | ControlState::ENABLED | ControlState::ROLLOVER, | ||||||
1393 | aVal, | ||||||
1394 | aNativeBounds, aNativeContent ) ) | ||||||
1395 | { | ||||||
1396 | aRect = aNativeBounds; | ||||||
1397 | if( aRect.GetWidth() > nMinWidth ) | ||||||
1398 | nMinWidth = aRect.GetWidth(); | ||||||
1399 | if( aRect.GetHeight() > nMinHeight ) | ||||||
1400 | nMinHeight = aRect.GetHeight(); | ||||||
1401 | if( nDropDownArrowWidth < nMinWidth ) | ||||||
1402 | nDropDownArrowWidth = nMinWidth; | ||||||
1403 | if( nMinWidth > mpData->mnMenuButtonWidth ) | ||||||
1404 | mpData->mnMenuButtonWidth = nMinWidth; | ||||||
1405 | else if( nMinWidth < TB_MENUBUTTON_SIZE12 ) | ||||||
1406 | mpData->mnMenuButtonWidth = TB_MENUBUTTON_SIZE12; | ||||||
1407 | } | ||||||
1408 | } | ||||||
1409 | |||||||
1410 | // also calculate the area for comboboxes, drop down list boxes and spinfields | ||||||
1411 | // as these are often inserted into toolboxes; set mnWinHeight to the | ||||||
1412 | // greater of those values to prevent toolbar flickering (#i103385#) | ||||||
1413 | aRect = tools::Rectangle( Point( 0, 0 ), Size( nMinWidth, nMinHeight ) ); | ||||||
1414 | aReg = aRect; | ||||||
1415 | if( GetNativeControlRegion( ControlType::Combobox, ControlPart::Entire, | ||||||
1416 | aReg, | ||||||
1417 | ControlState::ENABLED | ControlState::ROLLOVER, | ||||||
1418 | aVal, | ||||||
1419 | aNativeBounds, aNativeContent ) ) | ||||||
1420 | { | ||||||
1421 | aRect = aNativeBounds; | ||||||
1422 | if( aRect.GetHeight() > mnWinHeight ) | ||||||
1423 | mnWinHeight = aRect.GetHeight(); | ||||||
1424 | } | ||||||
1425 | aRect = tools::Rectangle( Point( 0, 0 ), Size( nMinWidth, nMinHeight ) ); | ||||||
1426 | aReg = aRect; | ||||||
1427 | if( GetNativeControlRegion( ControlType::Listbox, ControlPart::Entire, | ||||||
1428 | aReg, | ||||||
1429 | ControlState::ENABLED | ControlState::ROLLOVER, | ||||||
1430 | aVal, | ||||||
1431 | aNativeBounds, aNativeContent ) ) | ||||||
1432 | { | ||||||
1433 | aRect = aNativeBounds; | ||||||
1434 | if( aRect.GetHeight() > mnWinHeight ) | ||||||
1435 | mnWinHeight = aRect.GetHeight(); | ||||||
1436 | } | ||||||
1437 | aRect = tools::Rectangle( Point( 0, 0 ), Size( nMinWidth, nMinHeight ) ); | ||||||
1438 | aReg = aRect; | ||||||
1439 | if( GetNativeControlRegion( ControlType::Spinbox, ControlPart::Entire, | ||||||
1440 | aReg, | ||||||
1441 | ControlState::ENABLED | ControlState::ROLLOVER, | ||||||
1442 | aVal, | ||||||
1443 | aNativeBounds, aNativeContent ) ) | ||||||
1444 | { | ||||||
1445 | aRect = aNativeBounds; | ||||||
1446 | if( aRect.GetHeight() > mnWinHeight ) | ||||||
1447 | mnWinHeight = aRect.GetHeight(); | ||||||
1448 | } | ||||||
1449 | } | ||||||
1450 | |||||||
1451 | if ( ! mpData->m_aItems.empty() ) | ||||||
1452 | { | ||||||
1453 | for (auto & item : mpData->m_aItems) | ||||||
1454 | { | ||||||
1455 | item.mbVisibleText = false; // indicates if text will definitely be drawn, influences dropdown pos | ||||||
1456 | |||||||
1457 | if ( item.meType == ToolBoxItemType::BUTTON ) | ||||||
1458 | { | ||||||
1459 | bool bImage; | ||||||
1460 | bool bText; | ||||||
1461 | |||||||
1462 | // check if image and/or text exists | ||||||
1463 | bImage = !!item.maImage; | ||||||
1464 | bText = !item.maText.isEmpty(); | ||||||
1465 | ButtonType tmpButtonType = determineButtonType( &item, meButtonType ); // default to toolbox setting | ||||||
1466 | if ( bImage || bText ) | ||||||
1467 | { | ||||||
1468 | |||||||
1469 | item.mbEmptyBtn = false; | ||||||
1470 | |||||||
1471 | if ( tmpButtonType == ButtonType::SYMBOLONLY ) | ||||||
1472 | { | ||||||
1473 | // we're drawing images only | ||||||
1474 | if ( bImage || !bText ) | ||||||
1475 | { | ||||||
1476 | item.maItemSize = item.maImage.GetSizePixel(); | ||||||
1477 | } | ||||||
1478 | else | ||||||
1479 | { | ||||||
1480 | item.maItemSize = Size( GetCtrlTextWidth( item.maText )+TB_TEXTOFFSET2, | ||||||
1481 | GetTextHeight() ); | ||||||
1482 | item.mbVisibleText = true; | ||||||
1483 | } | ||||||
1484 | } | ||||||
1485 | else if ( tmpButtonType == ButtonType::TEXT ) | ||||||
1486 | { | ||||||
1487 | // we're drawing text only | ||||||
1488 | if ( bText || !bImage ) | ||||||
1489 | { | ||||||
1490 | item.maItemSize = Size( GetCtrlTextWidth( item.maText )+TB_TEXTOFFSET2, | ||||||
1491 | GetTextHeight() ); | ||||||
1492 | item.mbVisibleText = true; | ||||||
1493 | } | ||||||
1494 | else | ||||||
1495 | { | ||||||
1496 | item.maItemSize = item.maImage.GetSizePixel(); | ||||||
1497 | } | ||||||
1498 | } | ||||||
1499 | else | ||||||
1500 | { | ||||||
1501 | // we're drawing images and text | ||||||
1502 | item.maItemSize.setWidth( bText ? GetCtrlTextWidth( item.maText )+TB_TEXTOFFSET2 : 0 ); | ||||||
1503 | item.maItemSize.setHeight( bText ? GetTextHeight() : 0 ); | ||||||
1504 | |||||||
1505 | if ( meTextPosition == ToolBoxTextPosition::Right ) | ||||||
1506 | { | ||||||
1507 | // leave space between image and text | ||||||
1508 | if( bText ) | ||||||
1509 | item.maItemSize.AdjustWidth(TB_IMAGETEXTOFFSET3 ); | ||||||
1510 | |||||||
1511 | // image and text side by side | ||||||
1512 | item.maItemSize.AdjustWidth(item.maImage.GetSizePixel().Width() ); | ||||||
1513 | if ( item.maImage.GetSizePixel().Height() > item.maItemSize.Height() ) | ||||||
1514 | item.maItemSize.setHeight( item.maImage.GetSizePixel().Height() ); | ||||||
1515 | } | ||||||
1516 | else | ||||||
1517 | { | ||||||
1518 | // leave space between image and text | ||||||
1519 | if( bText ) | ||||||
1520 | item.maItemSize.AdjustHeight(TB_IMAGETEXTOFFSET3 ); | ||||||
1521 | |||||||
1522 | // text below image | ||||||
1523 | item.maItemSize.AdjustHeight(item.maImage.GetSizePixel().Height() ); | ||||||
1524 | if ( item.maImage.GetSizePixel().Width() > item.maItemSize.Width() ) | ||||||
1525 | item.maItemSize.setWidth( item.maImage.GetSizePixel().Width() ); | ||||||
1526 | } | ||||||
1527 | |||||||
1528 | item.mbVisibleText = bText; | ||||||
1529 | } | ||||||
1530 | } | ||||||
1531 | else | ||||||
1532 | { // no image and no text | ||||||
1533 | item.maItemSize = Size( nDefWidth, nDefHeight ); | ||||||
1534 | item.mbEmptyBtn = true; | ||||||
1535 | } | ||||||
1536 | |||||||
1537 | // save the content size | ||||||
1538 | item.maContentSize = item.maItemSize; | ||||||
1539 | |||||||
1540 | // if required, take window height into consideration | ||||||
1541 | if ( item.mpWindow ) | ||||||
1542 | { | ||||||
1543 | long nHeight = item.mpWindow->GetSizePixel().Height(); | ||||||
1544 | if ( nHeight > mnWinHeight ) | ||||||
1545 | mnWinHeight = nHeight; | ||||||
1546 | } | ||||||
1547 | |||||||
1548 | // add in drop down arrow | ||||||
1549 | if( item.mnBits & ToolBoxItemBits::DROPDOWN ) | ||||||
1550 | { | ||||||
1551 | item.maItemSize.AdjustWidth(nDropDownArrowWidth ); | ||||||
1552 | item.mnDropDownArrowWidth = nDropDownArrowWidth; | ||||||
1553 | } | ||||||
1554 | |||||||
1555 | // text items will be rotated in vertical mode | ||||||
1556 | // -> swap width and height | ||||||
1557 | if( item.mbVisibleText && !mbHorz ) | ||||||
1558 | { | ||||||
1559 | long tmp = item.maItemSize.Width(); | ||||||
1560 | item.maItemSize.setWidth( item.maItemSize.Height() ); | ||||||
1561 | item.maItemSize.setHeight( tmp ); | ||||||
1562 | |||||||
1563 | tmp = item.maContentSize.Width(); | ||||||
1564 | item.maContentSize.setWidth( item.maContentSize.Height() ); | ||||||
1565 | item.maContentSize.setHeight( tmp ); | ||||||
1566 | } | ||||||
1567 | } | ||||||
1568 | else if ( item.meType == ToolBoxItemType::SPACE ) | ||||||
1569 | { | ||||||
1570 | item.maItemSize = Size( nDefWidth, nDefHeight ); | ||||||
1571 | item.maContentSize = item.maItemSize; | ||||||
1572 | } | ||||||
1573 | |||||||
1574 | if ( item.meType == ToolBoxItemType::BUTTON || item.meType == ToolBoxItemType::SPACE ) | ||||||
1575 | { | ||||||
1576 | // add borders | ||||||
1577 | long w = item.maItemSize.Width(); | ||||||
1578 | long h = item.maItemSize.Height(); | ||||||
1579 | ImplAddButtonBorder( w, h, mpData->mbNativeButtons ); | ||||||
1580 | item.maItemSize.setWidth(w); | ||||||
1581 | item.maItemSize.setHeight(h); | ||||||
1582 | |||||||
1583 | if( item.meType == ToolBoxItemType::BUTTON ) | ||||||
1584 | { | ||||||
1585 | long nMinW = std::max(nMinWidth, item.maMinimalItemSize.Width()); | ||||||
1586 | long nMinH = std::max(nMinHeight, item.maMinimalItemSize.Height()); | ||||||
1587 | |||||||
1588 | long nGrowContentWidth = 0; | ||||||
1589 | long nGrowContentHeight = 0; | ||||||
1590 | |||||||
1591 | if( item.maItemSize.Width() < nMinW ) | ||||||
1592 | { | ||||||
1593 | nGrowContentWidth = nMinW - item.maItemSize.Width(); | ||||||
1594 | item.maItemSize.setWidth( nMinW ); | ||||||
1595 | } | ||||||
1596 | if( item.maItemSize.Height() < nMinH ) | ||||||
1597 | { | ||||||
1598 | nGrowContentHeight = nMinH - item.maItemSize.Height(); | ||||||
1599 | item.maItemSize.setHeight( nMinH ); | ||||||
1600 | } | ||||||
1601 | |||||||
1602 | // grow the content size by the additional available space | ||||||
1603 | item.maContentSize.AdjustWidth(nGrowContentWidth ); | ||||||
1604 | item.maContentSize.AdjustHeight(nGrowContentHeight ); | ||||||
1605 | } | ||||||
1606 | |||||||
1607 | // keep track of max item size | ||||||
1608 | if ( item.maItemSize.Width() > nMaxWidth ) | ||||||
1609 | nMaxWidth = item.maItemSize.Width(); | ||||||
1610 | if ( item.maItemSize.Height() > nMaxHeight ) | ||||||
1611 | nMaxHeight = item.maItemSize.Height(); | ||||||
1612 | } | ||||||
1613 | } | ||||||
1614 | } | ||||||
1615 | else | ||||||
1616 | { | ||||||
1617 | nMaxWidth = nDefWidth; | ||||||
1618 | nMaxHeight = nDefHeight; | ||||||
1619 | |||||||
1620 | ImplAddButtonBorder( nMaxWidth, nMaxHeight, mpData->mbNativeButtons ); | ||||||
1621 | } | ||||||
1622 | |||||||
1623 | if( !ImplIsFloatingMode() && GetToolboxButtonSize() != ToolBoxButtonSize::DontCare | ||||||
1624 | && ( meTextPosition == ToolBoxTextPosition::Right ) ) | ||||||
1625 | { | ||||||
1626 | // make sure all vertical toolbars have the same width and horizontal have the same height | ||||||
1627 | // this depends on the used button sizes | ||||||
1628 | // as this is used for alignment of multiple toolbars | ||||||
1629 | // it is only required for docked toolbars | ||||||
1630 | |||||||
1631 | long nFixedWidth = nDefWidth+nDropDownArrowWidth; | ||||||
1632 | long nFixedHeight = nDefHeight; | ||||||
1633 | ImplAddButtonBorder( nFixedWidth, nFixedHeight, mpData->mbNativeButtons ); | ||||||
1634 | |||||||
1635 | if( mbHorz ) | ||||||
1636 | nMaxHeight = nFixedHeight; | ||||||
1637 | else | ||||||
1638 | nMaxWidth = nFixedWidth; | ||||||
1639 | } | ||||||
1640 | |||||||
1641 | mbCalc = false; | ||||||
1642 | mbFormat = true; | ||||||
1643 | |||||||
1644 | // do we have to recalc the sizes ? | ||||||
1645 | if ( (nMaxWidth != mnMaxItemWidth) || (nMaxHeight != mnMaxItemHeight) ) | ||||||
1646 | { | ||||||
1647 | mnMaxItemWidth = nMaxWidth; | ||||||
1648 | mnMaxItemHeight = nMaxHeight; | ||||||
1649 | |||||||
1650 | return true; | ||||||
1651 | } | ||||||
1652 | else | ||||||
1653 | return false; | ||||||
1654 | } | ||||||
1655 | |||||||
1656 | ToolBox::ImplToolItems::size_type ToolBox::ImplCalcBreaks( long nWidth, long* pMaxLineWidth, bool bCalcHorz ) const | ||||||
1657 | { | ||||||
1658 | sal_uLong nLineStart = 0; | ||||||
1659 | sal_uLong nGroupStart = 0; | ||||||
1660 | long nLineWidth = 0; | ||||||
1661 | long nCurWidth; | ||||||
1662 | long nLastGroupLineWidth = 0; | ||||||
1663 | long nMaxLineWidth = 0; | ||||||
1664 | ImplToolItems::size_type nLines = 1; | ||||||
1665 | bool bWindow; | ||||||
1666 | bool bBreak = false; | ||||||
1667 | long nWidthTotal = nWidth; | ||||||
1668 | long nMenuWidth = 0; | ||||||
1669 | |||||||
1670 | // when docked the menubutton will be in the first line | ||||||
1671 | if( IsMenuEnabled() && !ImplIsFloatingMode() ) | ||||||
1672 | nMenuWidth = mpData->maMenubuttonItem.maItemSize.Width(); | ||||||
1673 | |||||||
1674 | // we need to know which item is the last visible one to be able to add | ||||||
1675 | // the menu width in case we are unable to show all the items | ||||||
1676 | ImplToolItems::iterator it, lastVisible; | ||||||
1677 | for ( it = mpData->m_aItems.begin(); it != mpData->m_aItems.end(); ++it ) | ||||||
1678 | { | ||||||
1679 | if ( it->mbVisible ) | ||||||
1680 | lastVisible = it; | ||||||
1681 | } | ||||||
1682 | |||||||
1683 | it = mpData->m_aItems.begin(); | ||||||
1684 | while ( it != mpData->m_aItems.end() ) | ||||||
1685 | { | ||||||
1686 | it->mbBreak = bBreak; | ||||||
1687 | bBreak = false; | ||||||
1688 | |||||||
1689 | if ( it->mbVisible ) | ||||||
1690 | { | ||||||
1691 | bWindow = false; | ||||||
1692 | bBreak = false; | ||||||
1693 | nCurWidth = 0; | ||||||
1694 | |||||||
1695 | if ( it->meType == ToolBoxItemType::BUTTON || it->meType == ToolBoxItemType::SPACE ) | ||||||
1696 | { | ||||||
1697 | if ( bCalcHorz ) | ||||||
1698 | nCurWidth = it->maItemSize.Width(); | ||||||
1699 | else | ||||||
1700 | nCurWidth = it->maItemSize.Height(); | ||||||
1701 | |||||||
1702 | if ( it->mpWindow && bCalcHorz ) | ||||||
1703 | { | ||||||
1704 | long nWinItemWidth = it->mpWindow->GetSizePixel().Width(); | ||||||
1705 | if ( !mbScroll || (nWinItemWidth <= nWidthTotal) ) | ||||||
1706 | { | ||||||
1707 | nCurWidth = nWinItemWidth; | ||||||
1708 | bWindow = true; | ||||||
1709 | } | ||||||
1710 | else | ||||||
1711 | { | ||||||
1712 | if ( it->mbEmptyBtn ) | ||||||
1713 | { | ||||||
1714 | nCurWidth = 0; | ||||||
1715 | } | ||||||
1716 | } | ||||||
1717 | } | ||||||
1718 | |||||||
1719 | // in case we are able to show all the items, we do not want | ||||||
1720 | // to show the toolbar's menu; otherwise yes | ||||||
1721 | if ( ( ( it == lastVisible ) && (nLineWidth+nCurWidth > nWidthTotal) && mbScroll ) || | ||||||
1722 | ( ( it != lastVisible ) && (nLineWidth+nCurWidth+nMenuWidth > nWidthTotal) && mbScroll ) ) | ||||||
1723 | bBreak = true; | ||||||
1724 | } | ||||||
1725 | else if ( it->meType == ToolBoxItemType::SEPARATOR ) | ||||||
1726 | { | ||||||
1727 | nCurWidth = it->mnSepSize; | ||||||
1728 | if ( !ImplIsFloatingMode() && ( it != lastVisible ) && (nLineWidth+nCurWidth+nMenuWidth > nWidthTotal) ) | ||||||
1729 | bBreak = true; | ||||||
1730 | } | ||||||
1731 | // treat breaks as separators, except when using old style toolbars (ie. no menu button) | ||||||
1732 | else if ( (it->meType == ToolBoxItemType::BREAK) && !IsMenuEnabled() ) | ||||||
1733 | bBreak = true; | ||||||
1734 | |||||||
1735 | if ( bBreak ) | ||||||
1736 | { | ||||||
1737 | nLines++; | ||||||
1738 | |||||||
1739 | // Add break before the entire group or take group apart? | ||||||
1740 | if ( (it->meType == ToolBoxItemType::BREAK) || | ||||||
1741 | (nLineStart == nGroupStart) ) | ||||||
1742 | { | ||||||
1743 | if ( nLineWidth > nMaxLineWidth ) | ||||||
1744 | nMaxLineWidth = nLineWidth; | ||||||
1745 | |||||||
1746 | nLineWidth = 0; | ||||||
1747 | nLineStart = it - mpData->m_aItems.begin(); | ||||||
1748 | nGroupStart = nLineStart; | ||||||
1749 | it->mbBreak = true; | ||||||
1750 | bBreak = false; | ||||||
1751 | } | ||||||
1752 | else | ||||||
1753 | { | ||||||
1754 | if ( nLastGroupLineWidth > nMaxLineWidth ) | ||||||
1755 | nMaxLineWidth = nLastGroupLineWidth; | ||||||
1756 | |||||||
1757 | // if the break is added before the group, set it to | ||||||
1758 | // beginning of line and re-calculate | ||||||
1759 | nLineWidth = 0; | ||||||
1760 | nLineStart = nGroupStart; | ||||||
1761 | it = mpData->m_aItems.begin() + nGroupStart; | ||||||
1762 | continue; | ||||||
1763 | } | ||||||
1764 | } | ||||||
1765 | else | ||||||
1766 | { | ||||||
1767 | if( ImplIsFloatingMode() || !IsMenuEnabled() ) // no group breaking when being docked single-line | ||||||
1768 | { | ||||||
1769 | if ( (it->meType != ToolBoxItemType::BUTTON) || bWindow ) | ||||||
1770 | { | ||||||
1771 | // found separator or break | ||||||
1772 | nLastGroupLineWidth = nLineWidth; | ||||||
1773 | nGroupStart = it - mpData->m_aItems.begin(); | ||||||
1774 | if ( !bWindow ) | ||||||
1775 | nGroupStart++; | ||||||
1776 | } | ||||||
1777 | } | ||||||
1778 | } | ||||||
1779 | |||||||
1780 | nLineWidth += nCurWidth; | ||||||
1781 | } | ||||||
1782 | |||||||
1783 | ++it; | ||||||
1784 | } | ||||||
1785 | |||||||
1786 | if ( pMaxLineWidth ) | ||||||
1787 | { | ||||||
1788 | if ( nLineWidth > nMaxLineWidth ) | ||||||
1789 | nMaxLineWidth = nLineWidth; | ||||||
1790 | |||||||
1791 | if( ImplIsFloatingMode() && !ImplIsInPopupMode() ) | ||||||
1792 | { | ||||||
1793 | // leave enough space to display buttons in the decoration | ||||||
1794 | long aMinWidth = 2 * GetSettings().GetStyleSettings().GetFloatTitleHeight(); | ||||||
1795 | if( nMaxLineWidth < aMinWidth ) | ||||||
1796 | nMaxLineWidth = aMinWidth; | ||||||
1797 | } | ||||||
1798 | *pMaxLineWidth = nMaxLineWidth; | ||||||
1799 | } | ||||||
1800 | |||||||
1801 | return nLines; | ||||||
1802 | } | ||||||
1803 | |||||||
1804 | Size ToolBox::ImplGetOptimalFloatingSize() | ||||||
1805 | { | ||||||
1806 | if( !ImplIsFloatingMode() ) | ||||||
1807 | return Size(); | ||||||
1808 | |||||||
1809 | Size aCurrentSize( mnDX, mnDY ); | ||||||
1810 | Size aSize1( aCurrentSize ); | ||||||
1811 | Size aSize2( aCurrentSize ); | ||||||
1812 | |||||||
1813 | // try to preserve current height | ||||||
1814 | |||||||
1815 | // calc number of floating lines for current window height | ||||||
1816 | ImplToolItems::size_type nFloatLinesHeight = ImplCalcLines( mnDY ); | ||||||
1817 | // calc window size according to this number | ||||||
1818 | aSize1 = ImplCalcFloatSize( nFloatLinesHeight ); | ||||||
1819 | |||||||
1820 | if( aCurrentSize == aSize1 ) | ||||||
1821 | return aSize1; | ||||||
1822 | |||||||
1823 | // try to preserve current width | ||||||
1824 | |||||||
1825 | long nLineHeight = std::max( mnWinHeight, mnMaxItemHeight ); | ||||||
1826 | int nBorderX = 2*TB_BORDER_OFFSET14 + mnLeftBorder + mnRightBorder; | ||||||
1827 | int nBorderY = 2*TB_BORDER_OFFSET22 + mnTopBorder + mnBottomBorder; | ||||||
1828 | Size aSz( aCurrentSize ); | ||||||
1829 | long maxX; | ||||||
1830 | ImplToolItems::size_type nLines = ImplCalcBreaks( aSz.Width()-nBorderX, &maxX, mbHorz ); | ||||||
1831 | |||||||
1832 | ImplToolItems::size_type manyLines = 1000; | ||||||
1833 | Size aMinimalFloatSize = ImplCalcFloatSize( manyLines ); | ||||||
1834 | |||||||
1835 | aSz.setHeight( nBorderY + nLineHeight * nLines ); | ||||||
1836 | // line space when more than one line | ||||||
1837 | if ( mbLineSpacing ) | ||||||
1838 | aSz.AdjustHeight((nLines-1)*TB_LINESPACING3 ); | ||||||
1839 | |||||||
1840 | aSz.setWidth( nBorderX + maxX ); | ||||||
1841 | |||||||
1842 | // avoid clipping of any items | ||||||
1843 | if( aSz.Width() < aMinimalFloatSize.Width() ) | ||||||
1844 | aSize2 = ImplCalcFloatSize( nLines ); | ||||||
1845 | else | ||||||
1846 | aSize2 = aSz; | ||||||
1847 | |||||||
1848 | if( aCurrentSize == aSize2 ) | ||||||
1849 | return aSize2; | ||||||
1850 | |||||||
1851 | // set the size with the smallest delta as the current size | ||||||
1852 | long dx1 = std::abs( mnDX - aSize1.Width() ); | ||||||
1853 | long dy1 = std::abs( mnDY - aSize1.Height() ); | ||||||
1854 | |||||||
1855 | long dx2 = std::abs( mnDX - aSize2.Width() ); | ||||||
1856 | long dy2 = std::abs( mnDY - aSize2.Height() ); | ||||||
1857 | |||||||
1858 | if( dx1*dy1 < dx2*dy2 ) | ||||||
1859 | aCurrentSize = aSize1; | ||||||
1860 | else | ||||||
1861 | aCurrentSize = aSize2; | ||||||
1862 | |||||||
1863 | return aCurrentSize; | ||||||
1864 | } | ||||||
1865 | |||||||
1866 | namespace | ||||||
1867 | { | ||||||
1868 | void lcl_hideDoubleSeparators( ToolBox::ImplToolItems& rItems ) | ||||||
1869 | { | ||||||
1870 | bool bLastSep( true ); | ||||||
1871 | ToolBox::ImplToolItems::iterator it; | ||||||
1872 | for ( it = rItems.begin(); it != rItems.end(); ++it ) | ||||||
1873 | { | ||||||
1874 | if ( it->meType == ToolBoxItemType::SEPARATOR ) | ||||||
1875 | { | ||||||
1876 | it->mbVisible = false; | ||||||
1877 | if ( !bLastSep ) | ||||||
1878 | { | ||||||
1879 | // check if any visible items have to appear behind it | ||||||
1880 | if (std::any_of(it + 1, rItems.end(), [](const ImplToolItem& rItem) { | ||||||
1881 | return (rItem.meType == ToolBoxItemType::BUTTON) && rItem.mbVisible; })) | ||||||
1882 | it->mbVisible = true; | ||||||
1883 | } | ||||||
1884 | bLastSep = true; | ||||||
1885 | } | ||||||
1886 | else if ( it->mbVisible ) | ||||||
1887 | bLastSep = false; | ||||||
1888 | } | ||||||
1889 | } | ||||||
1890 | } | ||||||
1891 | |||||||
1892 | void ToolBox::ImplFormat( bool bResize ) | ||||||
1893 | { | ||||||
1894 | // Has to re-formatted | ||||||
1895 | if ( !mbFormat ) | ||||||
1896 | return; | ||||||
1897 | |||||||
1898 | mpData->ImplClearLayoutData(); | ||||||
1899 | |||||||
1900 | // recalculate positions and sizes | ||||||
1901 | tools::Rectangle aEmptyRect; | ||||||
1902 | long nLineSize; | ||||||
1903 | long nLeft; | ||||||
1904 | long nTop; | ||||||
1905 | long nMax; // width of layoutarea in pixels | ||||||
1906 | ImplToolItems::size_type nFormatLine; | ||||||
1907 | bool bMustFullPaint; | ||||||
1908 | |||||||
1909 | ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( this ); | ||||||
1910 | bool bIsInPopupMode = ImplIsInPopupMode(); | ||||||
1911 | |||||||
1912 | maFloatSizes.clear(); | ||||||
1913 | |||||||
1914 | // compute border sizes | ||||||
1915 | ImplCalcBorder( meAlign, mnLeftBorder, mnTopBorder, mnRightBorder, mnBottomBorder ); | ||||||
1916 | |||||||
1917 | // update drag area (where the 'grip' will be placed) | ||||||
1918 | tools::Rectangle aOldDragRect; | ||||||
1919 | if( pWrapper ) | ||||||
1920 | aOldDragRect = pWrapper->GetDragArea(); | ||||||
1921 | ImplUpdateDragArea(); | ||||||
1922 | |||||||
1923 | bMustFullPaint = ImplCalcItem(); | ||||||
1924 | |||||||
1925 | // calculate new size during interactive resize or | ||||||
1926 | // set computed size when formatting only | ||||||
1927 | if ( ImplIsFloatingMode() ) | ||||||
1928 | { | ||||||
1929 | if ( bResize ) | ||||||
1930 | mnFloatLines = ImplCalcLines( mnDY ); | ||||||
1931 | else | ||||||
1932 | SetOutputSizePixel( ImplGetOptimalFloatingSize() ); | ||||||
1933 | } | ||||||
1934 | |||||||
1935 | // Horizontal | ||||||
1936 | if ( mbHorz ) | ||||||
1937 | { | ||||||
1938 | long nBottom; | ||||||
1939 | // nLineSize: height of a single line, will fit highest item | ||||||
1940 | nLineSize = mnMaxItemHeight; | ||||||
1941 | |||||||
1942 | if ( mnWinHeight > mnMaxItemHeight ) | ||||||
1943 | nLineSize = mnWinHeight; | ||||||
1944 | |||||||
1945 | if ( mbScroll ) | ||||||
1946 | { | ||||||
1947 | nMax = mnDX; | ||||||
1948 | mnVisLines = ImplCalcLines( mnDY ); | ||||||
1949 | } | ||||||
1950 | else | ||||||
1951 | { | ||||||
1952 | // layout over all lines | ||||||
1953 | mnVisLines = mnLines; | ||||||
1954 | nMax = TB_MAXNOSCROLL32765; | ||||||
1955 | } | ||||||
1956 | |||||||
1957 | // add in all border offsets | ||||||
1958 | if ( mnWinStyle & WB_BORDER ) | ||||||
1959 | { | ||||||
1960 | nLeft = TB_BORDER_OFFSET14 + mnLeftBorder; | ||||||
1961 | nTop = TB_BORDER_OFFSET22 + mnTopBorder; | ||||||
1962 | nBottom = TB_BORDER_OFFSET14 + mnBottomBorder; | ||||||
1963 | nMax -= nLeft + TB_BORDER_OFFSET14 + mnRightBorder; | ||||||
1964 | } | ||||||
1965 | else | ||||||
1966 | { | ||||||
1967 | nLeft = 0; | ||||||
1968 | nTop = 0; | ||||||
1969 | nBottom = 0; | ||||||
1970 | } | ||||||
1971 | |||||||
1972 | // adjust linesize if docked in single-line mode (i.e. when using a clipped item menu) | ||||||
1973 | // we have to center all items in the window height | ||||||
1974 | if( IsMenuEnabled() && !ImplIsFloatingMode() ) | ||||||
1975 | { | ||||||
1976 | long nWinHeight = mnDY - nTop - nBottom; | ||||||
1977 | if( nWinHeight > nLineSize ) | ||||||
1978 | nLineSize = nWinHeight; | ||||||
1979 | } | ||||||
1980 | } | ||||||
1981 | else | ||||||
1982 | { | ||||||
1983 | long nRight; | ||||||
1984 | nLineSize = mnMaxItemWidth; | ||||||
1985 | |||||||
1986 | if ( mbScroll ) | ||||||
1987 | { | ||||||
1988 | mnVisLines = ImplCalcLines( mnDX ); | ||||||
1989 | nMax = mnDY; | ||||||
1990 | } | ||||||
1991 | else | ||||||
1992 | { | ||||||
1993 | mnVisLines = mnLines; | ||||||
1994 | nMax = TB_MAXNOSCROLL32765; | ||||||
1995 | } | ||||||
1996 | |||||||
1997 | if ( mnWinStyle & WB_BORDER ) | ||||||
1998 | { | ||||||
1999 | nTop = TB_BORDER_OFFSET14 + mnTopBorder; | ||||||
2000 | nLeft = TB_BORDER_OFFSET22 + mnLeftBorder; | ||||||
2001 | nRight = TB_BORDER_OFFSET22 + mnRightBorder; | ||||||
2002 | nMax -= nTop + TB_BORDER_OFFSET14 + mnBottomBorder; | ||||||
2003 | } | ||||||
2004 | else | ||||||
2005 | { | ||||||
2006 | nLeft = 0; | ||||||
2007 | nTop = 0; | ||||||
2008 | nRight = 0; | ||||||
2009 | } | ||||||
2010 | |||||||
2011 | // adjust linesize if docked in single-line mode (i.e. when using a clipped item menu) | ||||||
2012 | // we have to center all items in the window height | ||||||
2013 | if( !ImplIsFloatingMode() && IsMenuEnabled() ) | ||||||
2014 | { | ||||||
2015 | long nWinWidth = mnDX - nLeft - nRight; | ||||||
2016 | if( nWinWidth > nLineSize ) | ||||||
2017 | nLineSize = nWinWidth; | ||||||
2018 | } | ||||||
2019 | } | ||||||
2020 | |||||||
2021 | // no calculation if the window has no size (nMax=0) | ||||||
2022 | // non scrolling toolboxes must be computed though | ||||||
2023 | if ( (nMax <= 0) && mbScroll ) | ||||||
2024 | { | ||||||
2025 | mnVisLines = 1; | ||||||
2026 | mnCurLine = 1; | ||||||
2027 | mnCurLines = 1; | ||||||
2028 | |||||||
2029 | for (auto & item : mpData->m_aItems) | ||||||
2030 | { | ||||||
2031 | item.maRect = aEmptyRect; | ||||||
2032 | } | ||||||
2033 | |||||||
2034 | maLowerRect = aEmptyRect; | ||||||
2035 | maUpperRect = aEmptyRect; | ||||||
2036 | } | ||||||
2037 | else | ||||||
2038 | { | ||||||
2039 | // init start values | ||||||
2040 | long nX = nLeft; // top-left offset | ||||||
2041 | long nY = nTop; | ||||||
2042 | nFormatLine = 1; | ||||||
2043 | |||||||
2044 | // save old scroll rectangles and reset them | ||||||
2045 | tools::Rectangle aOldLowerRect = maLowerRect; | ||||||
2046 | tools::Rectangle aOldUpperRect = maUpperRect; | ||||||
2047 | tools::Rectangle aOldMenubuttonRect = mpData->maMenubuttonItem.maRect; | ||||||
2048 | maUpperRect = aEmptyRect; | ||||||
2049 | maLowerRect = aEmptyRect; | ||||||
2050 | mpData->maMenubuttonItem.maRect = aEmptyRect; | ||||||
2051 | |||||||
2052 | // do we have any toolbox items at all ? | ||||||
2053 | if ( !mpData->m_aItems.empty() || IsMenuEnabled() ) | ||||||
2054 | { | ||||||
2055 | lcl_hideDoubleSeparators( mpData->m_aItems ); | ||||||
2056 | |||||||
2057 | // compute line breaks and visible lines give the current window width (nMax) | ||||||
2058 | // the break indicators will be stored within each item (it->mbBreak) | ||||||
2059 | mnCurLines = ImplCalcBreaks( nMax, nullptr, mbHorz ); | ||||||
2060 | |||||||
2061 | // check for scrollbar buttons or dropdown menu | ||||||
2062 | // (if a menu is enabled, this will be used to store clipped | ||||||
2063 | // items and no scroll buttons will appear) | ||||||
2064 | if ( (!ImplIsFloatingMode() && (mnCurLines > mnVisLines) && mbScroll ) || | ||||||
2065 | IsMenuEnabled() ) | ||||||
2066 | { | ||||||
2067 | // compute linebreaks again, incorporating scrollbar buttons | ||||||
2068 | if( !IsMenuEnabled() ) | ||||||
2069 | { | ||||||
2070 | nMax -= TB_SPIN_SIZE14+TB_SPIN_OFFSET2; | ||||||
2071 | mnCurLines = ImplCalcBreaks( nMax, nullptr, mbHorz ); | ||||||
2072 | } | ||||||
2073 | |||||||
2074 | // compute scroll rectangles or menu button | ||||||
2075 | if ( mbHorz ) | ||||||
2076 | { | ||||||
2077 | if( IsMenuEnabled() && !ImplHasExternalMenubutton() && !bIsInPopupMode ) | ||||||
2078 | { | ||||||
2079 | if( !ImplIsFloatingMode() ) | ||||||
2080 | { | ||||||
2081 | mpData->maMenubuttonItem.maRect.SetRight( mnDX - 2 ); | ||||||
2082 | mpData->maMenubuttonItem.maRect.SetTop( nTop ); | ||||||
2083 | mpData->maMenubuttonItem.maRect.SetBottom( mnDY-mnBottomBorder-TB_BORDER_OFFSET22-1 ); | ||||||
2084 | } | ||||||
2085 | else | ||||||
2086 | { | ||||||
2087 | mpData->maMenubuttonItem.maRect.SetRight( mnDX - mnRightBorder-TB_BORDER_OFFSET14-1 ); | ||||||
2088 | mpData->maMenubuttonItem.maRect.SetTop( nTop ); | ||||||
2089 | mpData->maMenubuttonItem.maRect.SetBottom( mnDY-mnBottomBorder-TB_BORDER_OFFSET22-1 ); | ||||||
2090 | } | ||||||
2091 | mpData->maMenubuttonItem.maRect.SetLeft( mpData->maMenubuttonItem.maRect.Right() - mpData->mnMenuButtonWidth ); | ||||||
2092 | } | ||||||
2093 | else | ||||||
2094 | { | ||||||
2095 | maUpperRect.SetLeft( nLeft+nMax+TB_SPIN_OFFSET2 ); | ||||||
2096 | maUpperRect.SetRight( maUpperRect.Left()+TB_SPIN_SIZE14-1 ); | ||||||
2097 | maUpperRect.SetTop( nTop ); | ||||||
2098 | maLowerRect.SetBottom( mnDY-mnBottomBorder-TB_BORDER_OFFSET22-1 ); | ||||||
2099 | maLowerRect.SetLeft( maUpperRect.Left() ); | ||||||
2100 | maLowerRect.SetRight( maUpperRect.Right() ); | ||||||
2101 | maUpperRect.SetBottom( maUpperRect.Top() + | ||||||
2102 | (maLowerRect.Bottom()-maUpperRect.Top())/2 ); | ||||||
2103 | maLowerRect.SetTop( maUpperRect.Bottom() ); | ||||||
2104 | } | ||||||
2105 | } | ||||||
2106 | else | ||||||
2107 | { | ||||||
2108 | if( IsMenuEnabled() && !ImplHasExternalMenubutton() && !bIsInPopupMode ) | ||||||
2109 | { | ||||||
2110 | if( !ImplIsFloatingMode() ) | ||||||
2111 | { | ||||||
2112 | mpData->maMenubuttonItem.maRect.SetBottom( mnDY - 2 ); | ||||||
2113 | mpData->maMenubuttonItem.maRect.SetLeft( nLeft ); | ||||||
2114 | mpData->maMenubuttonItem.maRect.SetRight( mnDX-mnRightBorder-TB_BORDER_OFFSET22-1 ); | ||||||
2115 | } | ||||||
2116 | else | ||||||
2117 | { | ||||||
2118 | mpData->maMenubuttonItem.maRect.SetBottom( mnDY - mnBottomBorder-TB_BORDER_OFFSET14-1 ); | ||||||
2119 | mpData->maMenubuttonItem.maRect.SetLeft( nLeft ); | ||||||
2120 | mpData->maMenubuttonItem.maRect.SetRight( mnDX-mnRightBorder-TB_BORDER_OFFSET22-1 ); | ||||||
2121 | } | ||||||
2122 | mpData->maMenubuttonItem.maRect.SetTop( mpData->maMenubuttonItem.maRect.Bottom() - mpData->mnMenuButtonWidth ); | ||||||
2123 | } | ||||||
2124 | else | ||||||
2125 | { | ||||||
2126 | maUpperRect.SetTop( nTop+nMax+TB_SPIN_OFFSET2 ); | ||||||
2127 | maUpperRect.SetBottom( maUpperRect.Top()+TB_SPIN_SIZE14-1 ); | ||||||
2128 | maUpperRect.SetLeft( nLeft ); | ||||||
2129 | maLowerRect.SetRight( mnDX-mnRightBorder-TB_BORDER_OFFSET22-1 ); | ||||||
2130 | maLowerRect.SetTop( maUpperRect.Top() ); | ||||||
2131 | maLowerRect.SetBottom( maUpperRect.Bottom() ); | ||||||
2132 | maUpperRect.SetRight( maUpperRect.Left() + | ||||||
2133 | (maLowerRect.Right()-maUpperRect.Left())/2 ); | ||||||
2134 | maLowerRect.SetLeft( maUpperRect.Right() ); | ||||||
2135 | } | ||||||
2136 | } | ||||||
2137 | } | ||||||
2138 | |||||||
2139 | // no scrolling when there is a "more"-menu | ||||||
2140 | // anything will "fit" in a single line then | ||||||
2141 | if( IsMenuEnabled() ) | ||||||
2142 | mnCurLines = 1; | ||||||
2143 | |||||||
2144 | // determine the currently visible line | ||||||
2145 | if ( mnVisLines >= mnCurLines ) | ||||||
2146 | mnCurLine = 1; | ||||||
2147 | else if ( mnCurLine+mnVisLines-1 > mnCurLines ) | ||||||
2148 | mnCurLine = mnCurLines - (mnVisLines-1); | ||||||
2149 | |||||||
2150 | long firstItemCenter = 0; | ||||||
2151 | for (auto & item : mpData->m_aItems) | ||||||
2152 | { | ||||||
2153 | item.mbShowWindow = false; | ||||||
2154 | |||||||
2155 | // check for line break and advance nX/nY accordingly | ||||||
2156 | if ( item.mbBreak ) | ||||||
2157 | { | ||||||
2158 | nFormatLine++; | ||||||
2159 | |||||||
2160 | // increment starting with the second line | ||||||
2161 | if ( nFormatLine > mnCurLine ) | ||||||
2162 | { | ||||||
2163 | if ( mbHorz ) | ||||||
2164 | { | ||||||
2165 | nX = nLeft; | ||||||
2166 | if ( mbLineSpacing ) | ||||||
2167 | nY += nLineSize+TB_LINESPACING3; | ||||||
2168 | else | ||||||
2169 | nY += nLineSize; | ||||||
2170 | } | ||||||
2171 | else | ||||||
2172 | { | ||||||
2173 | nY = nTop; | ||||||
2174 | if ( mbLineSpacing ) | ||||||
2175 | nX += nLineSize+TB_LINESPACING3; | ||||||
2176 | else | ||||||
2177 | nX += nLineSize; | ||||||
2178 | } | ||||||
2179 | } | ||||||
2180 | } | ||||||
2181 | |||||||
2182 | if ( !item.mbVisible || (nFormatLine < mnCurLine) || | ||||||
2183 | (nFormatLine > mnCurLine+mnVisLines-1) ) | ||||||
2184 | // item is not visible | ||||||
2185 | item.maCalcRect = aEmptyRect; | ||||||
2186 | else | ||||||
2187 | { | ||||||
2188 | // 1. determine current item width/height | ||||||
2189 | // take window size and orientation into account, because this affects the size of item windows | ||||||
2190 | |||||||
2191 | Size aCurrentItemSize( item.GetSize( mbHorz, mbScroll, nMax, Size(mnMaxItemWidth, mnMaxItemHeight) ) ); | ||||||
2192 | |||||||
2193 | // 2. position item rect and use size from step 1 | ||||||
2194 | // items will be centered horizontally (if mbHorz) or vertically | ||||||
2195 | // advance nX and nY accordingly | ||||||
2196 | |||||||
2197 | if ( mbHorz ) | ||||||
2198 | { | ||||||
2199 | // In special mode Locked horizontal positions of all items remain unchanged. | ||||||
2200 | |||||||
2201 | if ( mbIsArranged && meLayoutMode == ToolBoxLayoutMode::Locked && mnLines == 1 && item.maRect.Left() > 0 ) | ||||||
2202 | nX = item.maRect.Left(); | ||||||
2203 | item.maCalcRect.SetLeft( nX ); | ||||||
2204 | |||||||
2205 | // In special mode Locked first item's vertical position remains unchanged. Consecutive items vertical | ||||||
2206 | // positions are centered around first item's vertical position. If an item's height exceeds available | ||||||
2207 | // space, item's vertical position remains unchanged too. | ||||||
2208 | |||||||
2209 | if ( mbIsArranged && meLayoutMode == ToolBoxLayoutMode::Locked && mnLines == 1 ) | ||||||
2210 | if ( firstItemCenter > 0 ) | ||||||
2211 | if ( firstItemCenter-aCurrentItemSize.Height()/2 > nY ) | ||||||
2212 | item.maCalcRect.SetTop( firstItemCenter-aCurrentItemSize.Height()/2 ); | ||||||
2213 | else | ||||||
2214 | item.maCalcRect.SetTop( item.maRect.Top() ); | ||||||
2215 | else | ||||||
2216 | { | ||||||
2217 | item.maCalcRect.SetTop( item.maRect.Top() ); | ||||||
2218 | firstItemCenter = item.maRect.Top()+aCurrentItemSize.Height()/2; | ||||||
2219 | } | ||||||
2220 | else | ||||||
2221 | item.maCalcRect.SetTop( nY+(nLineSize-aCurrentItemSize.Height())/2 ); | ||||||
2222 | item.maCalcRect.SetRight( nX+aCurrentItemSize.Width()-1 ); | ||||||
2223 | item.maCalcRect.SetBottom( item.maCalcRect.Top()+aCurrentItemSize.Height()-1 ); | ||||||
2224 | nX += aCurrentItemSize.Width(); | ||||||
2225 | } | ||||||
2226 | else | ||||||
2227 | { | ||||||
2228 | item.maCalcRect.SetLeft( nX+(nLineSize-aCurrentItemSize.Width())/2 ); | ||||||
2229 | item.maCalcRect.SetTop( nY ); | ||||||
2230 | item.maCalcRect.SetRight( item.maCalcRect.Left()+aCurrentItemSize.Width()-1 ); | ||||||
2231 | item.maCalcRect.SetBottom( nY+aCurrentItemSize.Height()-1 ); | ||||||
2232 | nY += aCurrentItemSize.Height(); | ||||||
2233 | } | ||||||
2234 | } | ||||||
2235 | |||||||
2236 | // position window items into calculated item rect | ||||||
2237 | if ( item.mpWindow ) | ||||||
2238 | { | ||||||
2239 | if ( item.mbShowWindow ) | ||||||
2240 | { | ||||||
2241 | Point aPos( item.maCalcRect.Left(), item.maCalcRect.Top() ); | ||||||
2242 | |||||||
2243 | assert( item.maCalcRect.Top() >= 0 )(static_cast <bool> (item.maCalcRect.Top() >= 0) ? void (0) : __assert_fail ("item.maCalcRect.Top() >= 0", "/home/maarten/src/libreoffice/core/vcl/source/window/toolbox.cxx" , 2243, __extension__ __PRETTY_FUNCTION__)); | ||||||
2244 | |||||||
2245 | item.mpWindow->SetPosPixel( aPos ); | ||||||
2246 | item.mpWindow->Show(); | ||||||
2247 | } | ||||||
2248 | else | ||||||
2249 | item.mpWindow->Hide(); | ||||||
2250 | } | ||||||
2251 | } // end of loop over all items | ||||||
2252 | mbIsArranged = true; | ||||||
2253 | } | ||||||
2254 | else | ||||||
2255 | // we have no toolbox items | ||||||
2256 | mnCurLines = 1; | ||||||
2257 | |||||||
2258 | if( IsMenuEnabled() && ImplIsFloatingMode() && !ImplHasExternalMenubutton() && !bIsInPopupMode ) | ||||||
2259 | { | ||||||
2260 | // custom menu will be the last button in floating mode | ||||||
2261 | ImplToolItem &rIt = mpData->maMenubuttonItem; | ||||||
2262 | |||||||
2263 | if ( mbHorz ) | ||||||
2264 | { | ||||||
2265 | rIt.maRect.SetLeft( nX+TB_MENUBUTTON_OFFSET2 ); | ||||||
2266 | rIt.maRect.SetTop( nY ); | ||||||
2267 | rIt.maRect.SetRight( rIt.maRect.Left() + mpData->mnMenuButtonWidth ); | ||||||
2268 | rIt.maRect.SetBottom( nY+nLineSize-1 ); | ||||||
2269 | nX += rIt.maItemSize.Width(); | ||||||
2270 | } | ||||||
2271 | else | ||||||
2272 | { | ||||||
2273 | rIt.maRect.SetLeft( nX ); | ||||||
2274 | rIt.maRect.SetTop( nY+TB_MENUBUTTON_OFFSET2 ); | ||||||
2275 | rIt.maRect.SetRight( nX+nLineSize-1 ); | ||||||
2276 | rIt.maRect.SetBottom( rIt.maRect.Top() + mpData->mnMenuButtonWidth ); | ||||||
2277 | nY += rIt.maItemSize.Height(); | ||||||
2278 | } | ||||||
2279 | } | ||||||
2280 | |||||||
2281 | // if toolbox visible trigger paint for changed regions | ||||||
2282 | if ( IsVisible() && !mbFullPaint ) | ||||||
2283 | { | ||||||
2284 | if ( bMustFullPaint ) | ||||||
2285 | { | ||||||
2286 | maPaintRect = tools::Rectangle( mnLeftBorder, mnTopBorder, | ||||||
2287 | mnDX-mnRightBorder, mnDY-mnBottomBorder ); | ||||||
2288 | } | ||||||
2289 | else | ||||||
2290 | { | ||||||
2291 | if ( aOldLowerRect != maLowerRect ) | ||||||
2292 | { | ||||||
2293 | maPaintRect.Union( maLowerRect ); | ||||||
2294 | maPaintRect.Union( aOldLowerRect ); | ||||||
2295 | } | ||||||
2296 | if ( aOldUpperRect != maUpperRect ) | ||||||
2297 | { | ||||||
2298 | maPaintRect.Union( maUpperRect ); | ||||||
2299 | maPaintRect.Union( aOldUpperRect ); | ||||||
2300 | } | ||||||
2301 | if ( aOldMenubuttonRect != mpData->maMenubuttonItem.maRect ) | ||||||
2302 | { | ||||||
2303 | maPaintRect.Union( mpData->maMenubuttonItem.maRect ); | ||||||
2304 | maPaintRect.Union( aOldMenubuttonRect ); | ||||||
2305 | } | ||||||
2306 | if ( pWrapper && aOldDragRect != pWrapper->GetDragArea() ) | ||||||
2307 | { | ||||||
2308 | maPaintRect.Union( pWrapper->GetDragArea() ); | ||||||
2309 | maPaintRect.Union( aOldDragRect ); | ||||||
2310 | } | ||||||
2311 | |||||||
2312 | for (auto const& item : mpData->m_aItems) | ||||||
2313 | { | ||||||
2314 | if ( item.maRect != item.maCalcRect ) | ||||||
2315 | { | ||||||
2316 | maPaintRect.Union( item.maRect ); | ||||||
2317 | maPaintRect.Union( item.maCalcRect ); | ||||||
2318 | } | ||||||
2319 | } | ||||||
2320 | } | ||||||
2321 | |||||||
2322 | Invalidate( maPaintRect ); | ||||||
2323 | } | ||||||
2324 | |||||||
2325 | // store the new calculated item rects | ||||||
2326 | maPaintRect = aEmptyRect; | ||||||
2327 | for (auto & item : mpData->m_aItems) | ||||||
2328 | item.maRect = item.maCalcRect; | ||||||
2329 | } | ||||||
2330 | |||||||
2331 | // indicate formatting is done | ||||||
2332 | mbFormat = false; | ||||||
2333 | } | ||||||
2334 | |||||||
2335 | IMPL_LINK_NOARG(ToolBox, ImplDropdownLongClickHdl, Timer *, void)void ToolBox::LinkStubImplDropdownLongClickHdl(void * instance , Timer * data) { return static_cast<ToolBox *>(instance )->ImplDropdownLongClickHdl(data); } void ToolBox::ImplDropdownLongClickHdl (__attribute__ ((unused)) Timer *) | ||||||
2336 | { | ||||||
2337 | if (mnCurPos == ITEM_NOTFOUND || | ||||||
2338 | !(mpData->m_aItems[ mnCurPos ].mnBits & ToolBoxItemBits::DROPDOWN)) | ||||||
2339 | return; | ||||||
2340 | |||||||
2341 | mpData->mbDropDownByKeyboard = false; | ||||||
2342 | mpData->maDropdownClickHdl.Call( this ); | ||||||
2343 | |||||||
2344 | // do not reset data if the dropdown handler opened a floating window | ||||||
2345 | // see ImplFloatControl() | ||||||
2346 | if( !mpFloatWin ) | ||||||
2347 | { | ||||||
2348 | // no floater was opened | ||||||
2349 | Deactivate(); | ||||||
2350 | InvalidateItem(mnCurPos); | ||||||
2351 | |||||||
2352 | mnCurPos = ITEM_NOTFOUND; | ||||||
2353 | mnCurItemId = 0; | ||||||
2354 | mnDownItemId = 0; | ||||||
2355 | mnMouseModifier = 0; | ||||||
2356 | mnHighItemId = 0; | ||||||
2357 | } | ||||||
2358 | } | ||||||
2359 | |||||||
2360 | IMPL_LINK_NOARG(ToolBox, ImplUpdateHdl, Timer *, void)void ToolBox::LinkStubImplUpdateHdl(void * instance, Timer * data ) { return static_cast<ToolBox *>(instance)->ImplUpdateHdl (data); } void ToolBox::ImplUpdateHdl(__attribute__ ((unused) ) Timer *) | ||||||
2361 | { | ||||||
2362 | |||||||
2363 | if( mbFormat && mpData ) | ||||||
2364 | ImplFormat(); | ||||||
2365 | } | ||||||
2366 | |||||||
2367 | static void ImplDrawMoreIndicator(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) | ||||||
2368 | { | ||||||
2369 | const Image pImage(StockImage::Yes, CHEVRON"sfx2/res/chevron.png"); | ||||||
2370 | Size aImageSize = pImage.GetSizePixel(); | ||||||
2371 | long x = rRect.Left() + (rRect.getWidth() - aImageSize.Width())/2; | ||||||
2372 | long y = rRect.Top() + (rRect.getHeight() - aImageSize.Height())/2; | ||||||
2373 | DrawImageFlags nImageStyle = DrawImageFlags::NONE; | ||||||
2374 | |||||||
2375 | rRenderContext.DrawImage(Point(x,y), pImage, nImageStyle); | ||||||
2376 | } | ||||||
2377 | |||||||
2378 | static void ImplDrawDropdownArrow(vcl::RenderContext& rRenderContext, const tools::Rectangle& rDropDownRect, bool bSetColor, bool bRotate ) | ||||||
2379 | { | ||||||
2380 | bool bLineColor = rRenderContext.IsLineColor(); | ||||||
2381 | bool bFillColor = rRenderContext.IsFillColor(); | ||||||
2382 | Color aOldFillColor = rRenderContext.GetFillColor(); | ||||||
2383 | Color aOldLineColor = rRenderContext.GetLineColor(); | ||||||
2384 | rRenderContext.SetLineColor(); | ||||||
2385 | |||||||
2386 | if ( bSetColor ) | ||||||
2387 | { | ||||||
2388 | if (rRenderContext.GetSettings().GetStyleSettings().GetFaceColor().IsDark()) | ||||||
2389 | rRenderContext.SetFillColor(COL_WHITE); | ||||||
2390 | else | ||||||
2391 | rRenderContext.SetFillColor(COL_BLACK); | ||||||
2392 | } | ||||||
2393 | |||||||
2394 | tools::Polygon aPoly(4); | ||||||
2395 | |||||||
2396 | // the assumption is, that the width always specifies the size of the expected arrow. | ||||||
2397 | const long nMargin = round(2 * rRenderContext.GetDPIScaleFactor()); | ||||||
2398 | const long nSize = rDropDownRect.getWidth() - 2 * nMargin; | ||||||
2399 | const long nHalfSize = (nSize + 1) / 2; | ||||||
2400 | const long x = rDropDownRect.Left() + nMargin + (bRotate ? (rDropDownRect.getWidth() - nHalfSize) / 2 : 0); | ||||||
2401 | const long y = rDropDownRect.Top() + nMargin + (rDropDownRect.getHeight() - (bRotate ? nSize : nHalfSize)) / 2; | ||||||
2402 | |||||||
2403 | aPoly.SetPoint(Point(x, y), 0); | ||||||
2404 | if (bRotate) // > | ||||||
2405 | { | ||||||
2406 | aPoly.SetPoint(Point(x, y + nSize), 1); | ||||||
2407 | aPoly.SetPoint(Point(x + nHalfSize, y + nHalfSize), 2); | ||||||
2408 | } | ||||||
2409 | else // v | ||||||
2410 | { | ||||||
2411 | aPoly.SetPoint(Point(x + nHalfSize, y + nHalfSize), 1); | ||||||
2412 | aPoly.SetPoint(Point(x + nSize, y), 2); | ||||||
2413 | } | ||||||
2414 | aPoly.SetPoint(Point(x, y), 3); | ||||||
2415 | |||||||
2416 | auto aaflags = rRenderContext.GetAntialiasing(); | ||||||
2417 | rRenderContext.SetAntialiasing(AntialiasingFlags::Enable); | ||||||
2418 | rRenderContext.DrawPolygon( aPoly ); | ||||||
2419 | rRenderContext.SetAntialiasing(aaflags); | ||||||
2420 | |||||||
2421 | if( bFillColor ) | ||||||
2422 | rRenderContext.SetFillColor(aOldFillColor); | ||||||
2423 | else | ||||||
2424 | rRenderContext.SetFillColor(); | ||||||
2425 | if( bLineColor ) | ||||||
2426 | rRenderContext.SetLineColor(aOldLineColor); | ||||||
2427 | else | ||||||
2428 | rRenderContext.SetLineColor(); | ||||||
2429 | } | ||||||
2430 | |||||||
2431 | void ToolBox::ImplDrawMenuButton(vcl::RenderContext& rRenderContext, bool bHighlight) | ||||||
2432 | { | ||||||
2433 | if (mpData->maMenubuttonItem.maRect.IsEmpty()) | ||||||
2434 | return; | ||||||
2435 | |||||||
2436 | // #i53937# paint menu button only if necessary | ||||||
2437 | if (!ImplHasClippedItems()) | ||||||
2438 | return; | ||||||
2439 | |||||||
2440 | // execute pending paint requests | ||||||
2441 | ImplCheckUpdate(); | ||||||
2442 | |||||||
2443 | rRenderContext.Push(PushFlags::FILLCOLOR | PushFlags::LINECOLOR); | ||||||
2444 | |||||||
2445 | // draw the 'more' indicator / button (>>) | ||||||
2446 | ImplErase(rRenderContext, mpData->maMenubuttonItem.maRect, bHighlight); | ||||||
2447 | |||||||
2448 | if (bHighlight) | ||||||
2449 | ImplDrawButton(rRenderContext, mpData->maMenubuttonItem.maRect, 2, false, true, false ); | ||||||
2450 | |||||||
2451 | if (ImplHasClippedItems()) | ||||||
2452 | ImplDrawMoreIndicator(rRenderContext, mpData->maMenubuttonItem.maRect); | ||||||
2453 | |||||||
2454 | // store highlight state | ||||||
2455 | mpData->mbMenubuttonSelected = bHighlight; | ||||||
2456 | |||||||
2457 | // restore colors | ||||||
2458 | rRenderContext.Pop(); | ||||||
2459 | } | ||||||
2460 | |||||||
2461 | void ToolBox::ImplDrawSpin(vcl::RenderContext& rRenderContext) | ||||||
2462 | { | ||||||
2463 | bool bTmpUpper; | ||||||
2464 | bool bTmpLower; | ||||||
2465 | |||||||
2466 | if ( maUpperRect.IsEmpty() || maLowerRect.IsEmpty() ) | ||||||
2467 | return; | ||||||
2468 | |||||||
2469 | bTmpUpper = mnCurLine > 1; | ||||||
2470 | |||||||
2471 | bTmpLower = mnCurLine+mnVisLines-1 < mnCurLines; | ||||||
2472 | |||||||
2473 | if ( !IsEnabled() ) | ||||||
2474 | { | ||||||
2475 | bTmpUpper = false; | ||||||
2476 | bTmpLower = false; | ||||||
2477 | } | ||||||
2478 | |||||||
2479 | ImplDrawUpDownButtons(rRenderContext, maUpperRect, maLowerRect, | ||||||
2480 | false/*bUpperIn*/, false/*bLowerIn*/, bTmpUpper, bTmpLower, !mbHorz); | ||||||
2481 | } | ||||||
2482 | |||||||
2483 | void ToolBox::ImplDrawSeparator(vcl::RenderContext& rRenderContext, ImplToolItems::size_type nPos, const tools::Rectangle& rRect) | ||||||
2484 | { | ||||||
2485 | if ( nPos >= mpData->m_aItems.size() - 1 ) | ||||||
2486 | // no separator if it's the last item | ||||||
2487 | return; | ||||||
2488 | |||||||
2489 | ImplToolItem* pItem = &mpData->m_aItems[nPos]; | ||||||
2490 | ImplToolItem* pPreviousItem = &mpData->m_aItems[nPos-1]; | ||||||
2491 | ImplToolItem* pNextItem = &mpData->m_aItems[nPos+1]; | ||||||
2492 | |||||||
2493 | if ( ( pPreviousItem->mbShowWindow && pNextItem->mbShowWindow ) || pNextItem->mbBreak ) | ||||||
2494 | // no separator between two windows or before a break | ||||||
2495 | return; | ||||||
2496 | |||||||
2497 | bool bNativeOk = false; | ||||||
2498 | ControlPart nPart = IsHorizontal() ? ControlPart::SeparatorVert : ControlPart::SeparatorHorz; | ||||||
2499 | if (rRenderContext.IsNativeControlSupported(ControlType::Toolbar, nPart)) | ||||||
2500 | { | ||||||
2501 | ImplControlValue aControlValue; | ||||||
2502 | bNativeOk = rRenderContext.DrawNativeControl(ControlType::Toolbar, nPart, rRect, ControlState::NONE, aControlValue, OUString()); | ||||||
2503 | } | ||||||
2504 | |||||||
2505 | /* Draw the widget only if it can't be drawn natively. */ | ||||||
2506 | if (bNativeOk) | ||||||
2507 | return; | ||||||
2508 | |||||||
2509 | long nCenterPos, nSlim; | ||||||
2510 | const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings(); | ||||||
2511 | rRenderContext.SetLineColor(rStyleSettings.GetSeparatorColor()); | ||||||
2512 | if (IsHorizontal()) | ||||||
2513 | { | ||||||
2514 | nSlim = (pItem->maRect.Bottom() - pItem->maRect.Top ()) / 4; | ||||||
2515 | nCenterPos = pItem->maRect.Center().X(); | ||||||
2516 | rRenderContext.DrawLine(Point(nCenterPos, pItem->maRect.Top() + nSlim), | ||||||
2517 | Point(nCenterPos, pItem->maRect.Bottom() - nSlim)); | ||||||
2518 | } | ||||||
2519 | else | ||||||
2520 | { | ||||||
2521 | nSlim = (pItem->maRect.Right() - pItem->maRect.Left ()) / 4; | ||||||
2522 | nCenterPos = pItem->maRect.Center().Y(); | ||||||
2523 | rRenderContext.DrawLine(Point(pItem->maRect.Left() + nSlim, nCenterPos), | ||||||
2524 | Point(pItem->maRect.Right() - nSlim, nCenterPos)); | ||||||
2525 | } | ||||||
2526 | } | ||||||
2527 | |||||||
2528 | void ToolBox::ImplDrawButton(vcl::RenderContext& rRenderContext, const tools::Rectangle &rRect, sal_uInt16 highlight, | ||||||
2529 | bool bChecked, bool bEnabled, bool bIsWindow ) | ||||||
2530 | { | ||||||
2531 | // draws toolbar button background either native or using a coloured selection | ||||||
2532 | // if bIsWindow is true, the corresponding item is a control and only a selection border will be drawn | ||||||
2533 | |||||||
2534 | bool bNativeOk = false; | ||||||
2535 | if( !bIsWindow && rRenderContext.IsNativeControlSupported( ControlType::Toolbar, ControlPart::Button ) ) | ||||||
2536 | { | ||||||
2537 | ImplControlValue aControlValue; | ||||||
2538 | ControlState nState = ControlState::NONE; | ||||||
2539 | |||||||
2540 | if ( highlight == 1 ) nState |= ControlState::PRESSED; | ||||||
2541 | if ( highlight == 2 ) nState |= ControlState::ROLLOVER; | ||||||
2542 | if ( bEnabled ) nState |= ControlState::ENABLED; | ||||||
2543 | |||||||
2544 | aControlValue.setTristateVal( bChecked ? ButtonValue::On : ButtonValue::Off ); | ||||||
2545 | |||||||
2546 | bNativeOk = rRenderContext.DrawNativeControl( ControlType::Toolbar, ControlPart::Button, | ||||||
2547 | rRect, nState, aControlValue, OUString() ); | ||||||
2548 | } | ||||||
2549 | |||||||
2550 | if (!bNativeOk) | ||||||
2551 | vcl::RenderTools::DrawSelectionBackground(rRenderContext, *this, rRect, bIsWindow ? 3 : highlight, | ||||||
2552 | bChecked, true, bIsWindow, nullptr, 2); | ||||||
2553 | } | ||||||
2554 | |||||||
2555 | void ToolBox::ImplDrawItem(vcl::RenderContext& rRenderContext, ImplToolItems::size_type nPos, sal_uInt16 nHighlight) | ||||||
2556 | { | ||||||
2557 | if (nPos >= mpData->m_aItems.size()) | ||||||
2558 | return; | ||||||
2559 | |||||||
2560 | // execute pending paint requests | ||||||
2561 | ImplCheckUpdate(); | ||||||
2562 | |||||||
2563 | ImplDisableFlatButtons(); | ||||||
2564 | |||||||
2565 | rRenderContext.SetFillColor(); | ||||||
2566 | |||||||
2567 | ImplToolItem* pItem = &mpData->m_aItems[nPos]; | ||||||
2568 | |||||||
2569 | if (!pItem->mbEnabled) | ||||||
2570 | nHighlight = 0; | ||||||
2571 | |||||||
2572 | // if the rectangle is outside visible area | ||||||
2573 | if (pItem->maRect.IsEmpty()) | ||||||
2574 | return; | ||||||
2575 | |||||||
2576 | const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings(); | ||||||
2577 | |||||||
2578 | // no gradient background for items that have a popup open | ||||||
2579 | bool bHasOpenPopup = mpFloatWin && (mnDownItemId==pItem->mnId); | ||||||
2580 | |||||||
2581 | bool bHighContrastWhite = false; | ||||||
2582 | // check the face color as highcontrast indicator | ||||||
2583 | // because the toolbox itself might have a gradient | ||||||
2584 | if (rStyleSettings.GetFaceColor() == COL_WHITE) | ||||||
2585 | bHighContrastWhite = true; | ||||||
2586 | |||||||
2587 | // Compute buttons area. | ||||||
2588 | Size aBtnSize = pItem->maRect.GetSize(); | ||||||
2589 | |||||||
2590 | /* Compute the button/separator rectangle here, we'll need it for | ||||||
2591 | * both the buttons and the separators. */ | ||||||
2592 | tools::Rectangle aButtonRect( pItem->maRect.TopLeft(), aBtnSize ); | ||||||
2593 | long nOffX = SMALLBUTTON_OFF_NORMAL_X3; | ||||||
2594 | long nOffY = SMALLBUTTON_OFF_NORMAL_Y3; | ||||||
2595 | long nImageOffX = 0; | ||||||
2596 | long nImageOffY = 0; | ||||||
2597 | DrawButtonFlags nStyle = DrawButtonFlags::NONE; | ||||||
2598 | |||||||
2599 | // draw separators in flat style only | ||||||
2600 | if ( (mnOutStyle & TOOLBOX_STYLE_FLAT) && | ||||||
2601 | (pItem->meType == ToolBoxItemType::SEPARATOR) && | ||||||
2602 | nPos > 0 | ||||||
2603 | ) | ||||||
2604 | { | ||||||
2605 | ImplDrawSeparator(rRenderContext, nPos, aButtonRect); | ||||||
2606 | } | ||||||
2607 | |||||||
2608 | // do nothing if item is no button or will be displayed as window | ||||||
2609 | if ( (pItem->meType != ToolBoxItemType::BUTTON) || pItem->mbShowWindow ) | ||||||
2610 | return; | ||||||
2611 | |||||||
2612 | if ( pItem->meState == TRISTATE_TRUE ) | ||||||
2613 | { | ||||||
2614 | nStyle |= DrawButtonFlags::Checked; | ||||||
2615 | } | ||||||
2616 | else if ( pItem->meState == TRISTATE_INDET ) | ||||||
2617 | { | ||||||
2618 | nStyle |= DrawButtonFlags::DontKnow; | ||||||
2619 | } | ||||||
2620 | if ( nHighlight == 1 ) | ||||||
2621 | { | ||||||
2622 | nStyle |= DrawButtonFlags::Pressed; | ||||||
2623 | } | ||||||
2624 | |||||||
2625 | if ( mnOutStyle & TOOLBOX_STYLE_FLAT ) | ||||||
2626 | { | ||||||
2627 | ImplErase(rRenderContext, pItem->maRect, nHighlight != 0, bHasOpenPopup ); | ||||||
2628 | } | ||||||
2629 | else | ||||||
2630 | { | ||||||
2631 | DecorationView aDecoView(&rRenderContext); | ||||||
2632 | aDecoView.DrawButton(aButtonRect, nStyle); | ||||||
2633 | } | ||||||
2634 | |||||||
2635 | nOffX += pItem->maRect.Left(); | ||||||
2636 | nOffY += pItem->maRect.Top(); | ||||||
2637 | |||||||
2638 | // determine what has to be drawn on the button: image, text or both | ||||||
2639 | bool bImage; | ||||||
2640 | bool bText; | ||||||
2641 | ButtonType tmpButtonType = determineButtonType( pItem, meButtonType ); // default to toolbox setting | ||||||
2642 | pItem->DetermineButtonDrawStyle( tmpButtonType, bImage, bText ); | ||||||
2643 | |||||||
2644 | // compute output values | ||||||
2645 | long nBtnWidth = aBtnSize.Width()-SMALLBUTTON_HSIZE7; | ||||||
2646 | long nBtnHeight = aBtnSize.Height()-SMALLBUTTON_VSIZE7; | ||||||
2647 | Size aImageSize; | ||||||
2648 | |||||||
2649 | const bool bDropDown = (pItem->mnBits & ToolBoxItemBits::DROPDOWN) == ToolBoxItemBits::DROPDOWN; | ||||||
2650 | tools::Rectangle aDropDownRect; | ||||||
2651 | if (bDropDown) | ||||||
2652 | aDropDownRect = pItem->GetDropDownRect(mbHorz); | ||||||
2653 | |||||||
2654 | if ( bImage ) | ||||||
2655 | { | ||||||
2656 | const Image* pImage = &(pItem->maImage); | ||||||
2657 | aImageSize = pImage->GetSizePixel(); | ||||||
2658 | |||||||
2659 | // determine drawing flags | ||||||
2660 | DrawImageFlags nImageStyle = DrawImageFlags::NONE; | ||||||
2661 | |||||||
2662 | if ( !pItem->mbEnabled || !IsEnabled() ) | ||||||
2663 | nImageStyle |= DrawImageFlags::Disable; | ||||||
2664 | |||||||
2665 | // #i35563# the dontknow state indicates different states at the same time | ||||||
2666 | // which should not be rendered disabled but normal | ||||||
2667 | |||||||
2668 | // draw the image | ||||||
2669 | nImageOffX = nOffX; | ||||||
2670 | nImageOffY = nOffY; | ||||||
2671 | if ( ( (pItem->mnBits & (ToolBoxItemBits::LEFT|ToolBoxItemBits::DROPDOWN)) || bText ) | ||||||
2672 | && ( meTextPosition == ToolBoxTextPosition::Right ) ) | ||||||
2673 | { | ||||||
2674 | // left align also to leave space for drop down arrow | ||||||
2675 | // and when drawing text+image | ||||||
2676 | // just center in y, except for vertical (ie rotated text) | ||||||
2677 | if( mbHorz || !bText ) | ||||||
2678 | nImageOffY += (nBtnHeight-aImageSize.Height())/2; | ||||||
2679 | } | ||||||
2680 | else | ||||||
2681 | { | ||||||
2682 | nImageOffX += (nBtnWidth-(bDropDown ? aDropDownRect.getWidth() : 0)+SMALLBUTTON_OFF_NORMAL_X3-aImageSize.Width())/2; | ||||||
2683 | if ( meTextPosition == ToolBoxTextPosition::Right ) | ||||||
2684 | nImageOffY += (nBtnHeight-aImageSize.Height())/2; | ||||||
2685 | } | ||||||
2686 | if ( nHighlight != 0 || (pItem->meState == TRISTATE_TRUE) ) | ||||||
2687 | { | ||||||
2688 | if( bHasOpenPopup ) | ||||||
2689 | ImplDrawFloatwinBorder(rRenderContext, pItem); | ||||||
2690 | else | ||||||
2691 | ImplDrawButton(rRenderContext, aButtonRect, nHighlight, pItem->meState == TRISTATE_TRUE, | ||||||
2692 | pItem->mbEnabled && IsEnabled(), pItem->mbShowWindow); | ||||||
2693 | |||||||
2694 | if( nHighlight != 0 ) | ||||||
2695 | { | ||||||
2696 | if( bHighContrastWhite ) | ||||||
2697 | nImageStyle |= DrawImageFlags::ColorTransform; | ||||||
2698 | } | ||||||
2699 | } | ||||||
2700 | rRenderContext.DrawImage(Point( nImageOffX, nImageOffY ), *pImage, nImageStyle); | ||||||
2701 | } | ||||||
2702 | |||||||
2703 | // draw the text | ||||||
2704 | bool bRotate = false; | ||||||
2705 | if ( bText ) | ||||||
2706 | { | ||||||
2707 | const Size aTxtSize(GetCtrlTextWidth(pItem->maText), GetTextHeight()); | ||||||
2708 | long nTextOffX = nOffX; | ||||||
2709 | long nTextOffY = nOffY; | ||||||
2710 | |||||||
2711 | // rotate text when vertically docked | ||||||
2712 | vcl::Font aOldFont = rRenderContext.GetFont(); | ||||||
2713 | if( pItem->mbVisibleText && !ImplIsFloatingMode() && | ||||||
2714 | ((meAlign == WindowAlign::Left) || (meAlign == WindowAlign::Right)) ) | ||||||
2715 | { | ||||||
2716 | bRotate = true; | ||||||
2717 | |||||||
2718 | vcl::Font aRotateFont = aOldFont; | ||||||
2719 | aRotateFont.SetOrientation( 2700 ); | ||||||
2720 | |||||||
2721 | // center horizontally | ||||||
2722 | nTextOffX += aTxtSize.Height(); | ||||||
2723 | nTextOffX += (nBtnWidth-aTxtSize.Height())/2; | ||||||
2724 | |||||||
2725 | // add in image offset | ||||||
2726 | if( bImage ) | ||||||
2727 | nTextOffY = nImageOffY + aImageSize.Height() + TB_IMAGETEXTOFFSET3; | ||||||
2728 | |||||||
2729 | rRenderContext.SetFont(aRotateFont); | ||||||
2730 | } | ||||||
2731 | else | ||||||
2732 | { | ||||||
2733 | if ( meTextPosition == ToolBoxTextPosition::Right ) | ||||||
2734 | { | ||||||
2735 | // center vertically | ||||||
2736 | nTextOffY += (nBtnHeight-aTxtSize.Height())/2; | ||||||
2737 | |||||||
2738 | // add in image offset | ||||||
2739 | if( bImage ) | ||||||
2740 | nTextOffX = nImageOffX + aImageSize.Width() + TB_IMAGETEXTOFFSET3; | ||||||
2741 | } | ||||||
2742 | else | ||||||
2743 | { | ||||||
2744 | // center horizontally | ||||||
2745 | nTextOffX += (nBtnWidth-(bDropDown ? aDropDownRect.getWidth() : 0)+SMALLBUTTON_OFF_NORMAL_X3-aTxtSize.Width() - TB_IMAGETEXTOFFSET3)/2; | ||||||
2746 | // set vertical position | ||||||
2747 | nTextOffY += nBtnHeight - aTxtSize.Height(); | ||||||
2748 | } | ||||||
2749 | } | ||||||
2750 | |||||||
2751 | // draw selection only if not already drawn during image output (see above) | ||||||
2752 | if ( !bImage && (nHighlight != 0 || (pItem->meState == TRISTATE_TRUE) ) ) | ||||||
2753 | { | ||||||
2754 | if( bHasOpenPopup ) | ||||||
2755 | ImplDrawFloatwinBorder(rRenderContext, pItem); | ||||||
2756 | else | ||||||
2757 | ImplDrawButton(rRenderContext, pItem->maRect, nHighlight, pItem->meState == TRISTATE_TRUE, | ||||||
2758 | pItem->mbEnabled && IsEnabled(), pItem->mbShowWindow ); | ||||||
2759 | } | ||||||
2760 | |||||||
2761 | DrawTextFlags nTextStyle = DrawTextFlags::NONE; | ||||||
2762 | if ( !pItem->mbEnabled ) | ||||||
2763 | nTextStyle |= DrawTextFlags::Disable; | ||||||
2764 | rRenderContext.DrawCtrlText( Point( nTextOffX, nTextOffY ), pItem->maText, | ||||||
2765 | 0, pItem->maText.getLength(), nTextStyle ); | ||||||
2766 | if ( bRotate ) | ||||||
2767 | SetFont( aOldFont ); | ||||||
2768 | } | ||||||
2769 | |||||||
2770 | // paint optional drop down arrow | ||||||
2771 | if (!bDropDown) | ||||||
2772 | return; | ||||||
2773 | |||||||
2774 | bool bSetColor = true; | ||||||
2775 | if ( !pItem->mbEnabled || !IsEnabled() ) | ||||||
2776 | { | ||||||
2777 | bSetColor = false; | ||||||
2778 | rRenderContext.SetFillColor(rStyleSettings.GetShadowColor()); | ||||||
2779 | } | ||||||
2780 | |||||||
2781 | // dropdown only will be painted without inner border | ||||||
2782 | if( (pItem->mnBits & ToolBoxItemBits::DROPDOWNONLY) != ToolBoxItemBits::DROPDOWNONLY ) | ||||||
2783 | { | ||||||
2784 | ImplErase(rRenderContext, aDropDownRect, nHighlight != 0, bHasOpenPopup); | ||||||
2785 | |||||||
2786 | if( nHighlight != 0 || (pItem->meState == TRISTATE_TRUE) ) | ||||||
2787 | { | ||||||
2788 | if( bHasOpenPopup ) | ||||||
2789 | ImplDrawFloatwinBorder(rRenderContext, pItem); | ||||||
2790 | else | ||||||
2791 | ImplDrawButton(rRenderContext, aDropDownRect, nHighlight, pItem->meState == TRISTATE_TRUE, | ||||||
2792 | pItem->mbEnabled && IsEnabled(), false); | ||||||
2793 | } | ||||||
2794 | } | ||||||
2795 | ImplDrawDropdownArrow(rRenderContext, aDropDownRect, bSetColor, bRotate); | ||||||
2796 | } | ||||||
2797 | |||||||
2798 | void ToolBox::ImplDrawFloatwinBorder(vcl::RenderContext& rRenderContext, ImplToolItem const * pItem) | ||||||
2799 | { | ||||||
2800 | if ( pItem->maRect.IsEmpty() ) | ||||||
2801 | return; | ||||||
2802 | |||||||
2803 | tools::Rectangle aRect( mpFloatWin->ImplGetItemEdgeClipRect() ); | ||||||
2804 | aRect.SetPos( AbsoluteScreenToOutputPixel( aRect.TopLeft() ) ); | ||||||
2805 | rRenderContext.SetLineColor(rRenderContext.GetSettings().GetStyleSettings().GetShadowColor()); | ||||||
2806 | Point p1, p2; | ||||||
2807 | |||||||
2808 | p1 = pItem->maRect.TopLeft(); | ||||||
2809 | p1.AdjustX( 1 ); | ||||||
2810 | p2 = pItem->maRect.TopRight(); | ||||||
2811 | p2.AdjustX( -1 ); | ||||||
2812 | rRenderContext.DrawLine( p1, p2); | ||||||
2813 | p1 = pItem->maRect.BottomLeft(); | ||||||
2814 | p1.AdjustX( 1 ); | ||||||
2815 | p2 = pItem->maRect.BottomRight(); | ||||||
2816 | p2.AdjustX( -1 ); | ||||||
2817 | rRenderContext.DrawLine( p1, p2); | ||||||
2818 | |||||||
2819 | p1 = pItem->maRect.TopLeft(); | ||||||
2820 | p1.AdjustY( 1 ); | ||||||
2821 | p2 = pItem->maRect.BottomLeft(); | ||||||
2822 | p2.AdjustY( -1 ); | ||||||
2823 | rRenderContext.DrawLine( p1, p2); | ||||||
2824 | p1 = pItem->maRect.TopRight(); | ||||||
2825 | p1.AdjustY( 1 ); | ||||||
2826 | p2 = pItem->maRect.BottomRight(); | ||||||
2827 | p2.AdjustY( -1 ); | ||||||
2828 | rRenderContext.DrawLine( p1, p2); | ||||||
2829 | |||||||
2830 | } | ||||||
2831 | |||||||
2832 | void ToolBox::ImplFloatControl( bool bStart, FloatingWindow* pFloatWindow ) | ||||||
2833 | { | ||||||
2834 | |||||||
2835 | if ( bStart ) | ||||||
2836 | { | ||||||
2837 | mpFloatWin = pFloatWindow; | ||||||
2838 | |||||||
2839 | // redraw item, to trigger drawing of a special border | ||||||
2840 | InvalidateItem(mnCurPos); | ||||||
2841 | |||||||
2842 | mbDrag = false; | ||||||
2843 | EndTracking(); | ||||||
2844 | if (IsMouseCaptured()) | ||||||
2845 | ReleaseMouse(); | ||||||
2846 | } | ||||||
2847 | else | ||||||
2848 | { | ||||||
2849 | mpFloatWin = nullptr; | ||||||
2850 | |||||||
2851 | // if focus is still in this toolbox, then the floater was opened by keyboard | ||||||
2852 | // draw current item with highlight and keep old state | ||||||
2853 | bool bWasKeyboardActivate = mpData->mbDropDownByKeyboard; | ||||||
2854 | |||||||
2855 | if ( mnCurPos != ITEM_NOTFOUND ) | ||||||
2856 | InvalidateItem(mnCurPos); | ||||||
2857 | Deactivate(); | ||||||
2858 | |||||||
2859 | if( !bWasKeyboardActivate ) | ||||||
2860 | { | ||||||
2861 | mnCurPos = ITEM_NOTFOUND; | ||||||
2862 | mnCurItemId = 0; | ||||||
2863 | mnHighItemId = 0; | ||||||
2864 | } | ||||||
2865 | mnDownItemId = 0; | ||||||
2866 | |||||||
2867 | } | ||||||
2868 | } | ||||||
2869 | |||||||
2870 | void ToolBox::ShowLine( bool bNext ) | ||||||
2871 | { | ||||||
2872 | mbFormat = true; | ||||||
2873 | |||||||
2874 | if ( bNext ) | ||||||
2875 | mnCurLine++; | ||||||
2876 | else | ||||||
2877 | mnCurLine--; | ||||||
2878 | |||||||
2879 | ImplFormat(); | ||||||
2880 | } | ||||||
2881 | |||||||
2882 | bool ToolBox::ImplHandleMouseMove( const MouseEvent& rMEvt, bool bRepeat ) | ||||||
2883 | { | ||||||
2884 | Point aMousePos = rMEvt.GetPosPixel(); | ||||||
2885 | |||||||
2886 | if ( !mpData ) | ||||||
2887 | return false; | ||||||
2888 | |||||||
2889 | // ToolBox active? | ||||||
2890 | if ( mbDrag && mnCurPos != ITEM_NOTFOUND ) | ||||||
2891 | { | ||||||
2892 | // is the cursor over the item? | ||||||
2893 | ImplToolItem* pItem = &mpData->m_aItems[mnCurPos]; | ||||||
2894 | if ( pItem->maRect.IsInside( aMousePos ) ) | ||||||
2895 | { | ||||||
2896 | if ( !mnCurItemId ) | ||||||
2897 | { | ||||||
2898 | InvalidateItem(mnCurPos); | ||||||
2899 | mnCurItemId = pItem->mnId; | ||||||
2900 | Highlight(); | ||||||
2901 | } | ||||||
2902 | |||||||
2903 | if ( (pItem->mnBits & ToolBoxItemBits::REPEAT) && bRepeat ) | ||||||
2904 | Select(); | ||||||
2905 | } | ||||||
2906 | else | ||||||
2907 | { | ||||||
2908 | if ( mnCurItemId ) | ||||||
2909 | { | ||||||
2910 | InvalidateItem(mnCurPos); | ||||||
2911 | mnCurItemId = 0; | ||||||
2912 | InvalidateItem(mnCurPos); | ||||||
2913 | Highlight(); | ||||||
2914 | } | ||||||
2915 | } | ||||||
2916 | |||||||
2917 | return true; | ||||||
2918 | } | ||||||
2919 | |||||||
2920 | if ( mbUpper ) | ||||||
2921 | { | ||||||
2922 | bool bNewIn = maUpperRect.IsInside( aMousePos ); | ||||||
2923 | if ( bNewIn != mbIn ) | ||||||
2924 | { | ||||||
2925 | mbIn = bNewIn; | ||||||
2926 | InvalidateSpin(true, false); | ||||||
2927 | } | ||||||
2928 | return true; | ||||||
2929 | } | ||||||
2930 | |||||||
2931 | if ( mbLower ) | ||||||
2932 | { | ||||||
2933 | bool bNewIn = maLowerRect.IsInside( aMousePos ); | ||||||
2934 | if ( bNewIn != mbIn ) | ||||||
2935 | { | ||||||
2936 | mbIn = bNewIn; | ||||||
2937 | InvalidateSpin(false); | ||||||
2938 | } | ||||||
2939 | return true; | ||||||
2940 | } | ||||||
2941 | |||||||
2942 | return false; | ||||||
2943 | } | ||||||
2944 | |||||||
2945 | bool ToolBox::ImplHandleMouseButtonUp( const MouseEvent& rMEvt, bool bCancel ) | ||||||
2946 | { | ||||||
2947 | ImplDisableFlatButtons(); | ||||||
2948 | |||||||
2949 | if ( !mpData ) | ||||||
2950 | return false; | ||||||
2951 | |||||||
2952 | // stop eventual running dropdown timer | ||||||
2953 | if( mnCurPos < mpData->m_aItems.size() && | ||||||
2954 | (mpData->m_aItems[mnCurPos].mnBits & ToolBoxItemBits::DROPDOWN ) ) | ||||||
2955 | { | ||||||
2956 | mpData->maDropdownTimer.Stop(); | ||||||
2957 | } | ||||||
2958 | |||||||
2959 | if ( mbDrag ) | ||||||
2960 | { | ||||||
2961 | Deactivate(); | ||||||
2962 | |||||||
2963 | if ( mbDrag ) | ||||||
2964 | mbDrag = false; | ||||||
2965 | else | ||||||
2966 | { | ||||||
2967 | if ( mnCurPos == ITEM_NOTFOUND ) | ||||||
2968 | return true; | ||||||
2969 | } | ||||||
2970 | |||||||
2971 | // has mouse been released on top of item? | ||||||
2972 | if( mnCurPos < mpData->m_aItems.size() ) | ||||||
2973 | { | ||||||
2974 | ImplToolItem* pItem = &mpData->m_aItems[mnCurPos]; | ||||||
2975 | if ( pItem->maRect.IsInside( rMEvt.GetPosPixel() ) ) | ||||||
2976 | { | ||||||
2977 | mnCurItemId = pItem->mnId; | ||||||
2978 | if ( !bCancel
| ||||||
2979 | { | ||||||
2980 | // execute AutoCheck if required | ||||||
2981 | if ( pItem->mnBits & ToolBoxItemBits::AUTOCHECK ) | ||||||
2982 | { | ||||||
2983 | if ( pItem->mnBits & ToolBoxItemBits::RADIOCHECK ) | ||||||
2984 | { | ||||||
2985 | if ( pItem->meState != TRISTATE_TRUE ) | ||||||
2986 | SetItemState( pItem->mnId, TRISTATE_TRUE ); | ||||||
2987 | } | ||||||
2988 | else | ||||||
2989 | { | ||||||
2990 | if ( pItem->meState != TRISTATE_TRUE ) | ||||||
2991 | pItem->meState = TRISTATE_TRUE; | ||||||
2992 | else | ||||||
2993 | pItem->meState = TRISTATE_FALSE; | ||||||
2994 | } | ||||||
2995 | } | ||||||
2996 | |||||||
2997 | // do not call Select when Repeat is active, as in this | ||||||
2998 | // case that was triggered already in MouseButtonDown | ||||||
2999 | if ( !(pItem->mnBits & ToolBoxItemBits::REPEAT) ) | ||||||
3000 | { | ||||||
3001 | // prevent from being destroyed in the select handler | ||||||
3002 | VclPtr<vcl::Window> xWindow = this; | ||||||
3003 | Select(); | ||||||
3004 | if ( xWindow->IsDisposed() ) | ||||||
3005 | return true; | ||||||
3006 | } | ||||||
3007 | } | ||||||
3008 | |||||||
3009 | { | ||||||
3010 | } | ||||||
3011 | |||||||
3012 | // Items not destroyed, in Select handler | ||||||
3013 | if ( mnCurItemId ) | ||||||
| |||||||
3014 | { | ||||||
3015 | // Get current pos for the case that items are inserted/removed | ||||||
3016 | // in the toolBox | ||||||
3017 | mnCurPos = GetItemPos( mnCurItemId ); | ||||||
3018 | if ( mnCurPos != ITEM_NOTFOUND ) | ||||||
3019 | { | ||||||
3020 | InvalidateItem(mnCurPos); | ||||||
3021 | Flush(); | ||||||
3022 | } | ||||||
3023 | } | ||||||
3024 | } | ||||||
3025 | } | ||||||
3026 | |||||||
3027 | mnCurPos = ITEM_NOTFOUND; | ||||||
3028 | mnCurItemId = 0; | ||||||
3029 | mnDownItemId = 0; | ||||||
3030 | mnMouseModifier = 0; | ||||||
3031 | return true; | ||||||
3032 | } | ||||||
3033 | else if ( mbUpper || mbLower ) | ||||||
3034 | { | ||||||
3035 | if ( mbIn ) | ||||||
3036 | ShowLine( !mbUpper ); | ||||||
3037 | mbUpper = false; | ||||||
3038 | mbLower = false; | ||||||
3039 | mbIn = false; | ||||||
3040 | InvalidateSpin(); | ||||||
3041 | return true; | ||||||
3042 | } | ||||||
3043 | |||||||
3044 | return false; | ||||||
3045 | } | ||||||
3046 | |||||||
3047 | void ToolBox::MouseMove( const MouseEvent& rMEvt ) | ||||||
3048 | { | ||||||
3049 | // pressing a modifier generates synthetic mouse moves | ||||||
3050 | // ignore it if keyboard selection is active | ||||||
3051 | if( HasFocus() && ( rMEvt.GetMode() & MouseEventModifiers::MODIFIERCHANGED ) ) | ||||||
3052 | return; | ||||||
3053 | |||||||
3054 | if ( ImplHandleMouseMove( rMEvt ) ) | ||||||
3055 | return; | ||||||
3056 | |||||||
3057 | ImplDisableFlatButtons(); | ||||||
3058 | |||||||
3059 | Point aMousePos = rMEvt.GetPosPixel(); | ||||||
3060 | |||||||
3061 | // only highlight when the focus is not inside a child window of a toolbox | ||||||
3062 | // eg, in an edit control | ||||||
3063 | // and do not highlight when focus is in a different toolbox | ||||||
3064 | bool bDrawHotSpot = true; | ||||||
3065 | vcl::Window *pFocusWin = Application::GetFocusWindow(); | ||||||
3066 | |||||||
3067 | bool bFocusWindowIsAToolBoxChild = false; | ||||||
3068 | if (pFocusWin) | ||||||
3069 | { | ||||||
3070 | vcl::Window *pWin = pFocusWin->GetParent(); | ||||||
3071 | while (pWin) | ||||||
3072 | { | ||||||
3073 | if(pWin->ImplGetWindowImpl()->mbToolBox) | ||||||
3074 | { | ||||||
3075 | bFocusWindowIsAToolBoxChild = true; | ||||||
3076 | break; | ||||||
3077 | } | ||||||
3078 | pWin = pWin->GetParent(); | ||||||
3079 | } | ||||||
3080 | } | ||||||
3081 | |||||||
3082 | if( bFocusWindowIsAToolBoxChild || (pFocusWin && pFocusWin->ImplGetWindowImpl()->mbToolBox && pFocusWin != this) ) | ||||||
3083 | bDrawHotSpot = false; | ||||||
3084 | |||||||
3085 | if ( mbDragging ) | ||||||
3086 | { | ||||||
3087 | ImplTBDragMgr* pMgr = ImplGetTBDragMgr(); | ||||||
3088 | pMgr->Dragging( aMousePos ); | ||||||
3089 | return; | ||||||
3090 | } | ||||||
3091 | |||||||
3092 | PointerStyle eStyle = PointerStyle::Arrow; | ||||||
3093 | |||||||
3094 | // change mouse cursor over drag area | ||||||
3095 | ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( this ); | ||||||
3096 | if( pWrapper && pWrapper->GetDragArea().IsInside( rMEvt.GetPosPixel() ) ) | ||||||
3097 | eStyle = PointerStyle::Move; | ||||||
3098 | |||||||
3099 | if ( (mnWinStyle & TB_WBLINESIZING(WB_SIZEABLE | WB_DOCKABLE | WB_SCROLL)) == TB_WBLINESIZING(WB_SIZEABLE | WB_DOCKABLE | WB_SCROLL) ) | ||||||
3100 | { | ||||||
3101 | if ( rMEvt.GetMode() & MouseEventModifiers::SIMPLEMOVE ) | ||||||
3102 | { | ||||||
3103 | sal_uInt16 nLinePtr = ImplTestLineSize( rMEvt.GetPosPixel() ); | ||||||
3104 | if ( nLinePtr & DOCK_LINEHSIZE(sal_uInt16(0x0001)) ) | ||||||
3105 | { | ||||||
3106 | if ( meAlign == WindowAlign::Left ) | ||||||
3107 | eStyle = PointerStyle::WindowESize; | ||||||
3108 | else | ||||||
3109 | eStyle = PointerStyle::WindowWSize; | ||||||
3110 | } | ||||||
3111 | else if ( nLinePtr & DOCK_LINEVSIZE(sal_uInt16(0x0002)) ) | ||||||
3112 | { | ||||||
3113 | if ( meAlign == WindowAlign::Top ) | ||||||
3114 | eStyle = PointerStyle::WindowSSize; | ||||||
3115 | else | ||||||
3116 | eStyle = PointerStyle::WindowNSize; | ||||||
3117 | } | ||||||
3118 | } | ||||||
3119 | } | ||||||
3120 | |||||||
3121 | if ( bDrawHotSpot && ( (mnOutStyle & TOOLBOX_STYLE_FLAT) || !mnOutStyle ) ) | ||||||
3122 | { | ||||||
3123 | bool bClearHigh = true; | ||||||
3124 | if ( !rMEvt.IsLeaveWindow() && (mnCurPos == ITEM_NOTFOUND) ) | ||||||
3125 | { | ||||||
3126 | ImplToolItems::size_type nTempPos = 0; | ||||||
3127 | for (auto const& item : mpData->m_aItems) | ||||||
3128 | { | ||||||
3129 | if ( item.maRect.IsInside( aMousePos ) ) | ||||||
3130 | { | ||||||
3131 | if ( (item.meType == ToolBoxItemType::BUTTON) && item.mbEnabled ) | ||||||
3132 | { | ||||||
3133 | if ( !mnOutStyle || (mnOutStyle & TOOLBOX_STYLE_FLAT) ) | ||||||
3134 | { | ||||||
3135 | bClearHigh = false; | ||||||
3136 | if ( mnHighItemId != item.mnId ) | ||||||
3137 | { | ||||||
3138 | if ( mnHighItemId ) | ||||||
3139 | { | ||||||
3140 | ImplHideFocus(); | ||||||
3141 | ImplToolItems::size_type nPos = GetItemPos( mnHighItemId ); | ||||||
3142 | InvalidateItem(nPos); | ||||||
3143 | CallEventListeners( VclEventId::ToolboxHighlightOff, reinterpret_cast< void* >( nPos ) ); | ||||||
3144 | } | ||||||
3145 | if ( mpData->mbMenubuttonSelected ) | ||||||
3146 | { | ||||||
3147 | // remove highlight from menubutton | ||||||
3148 | InvalidateMenuButton(); | ||||||
3149 | } | ||||||
3150 | mnHighItemId = item.mnId; | ||||||
3151 | InvalidateItem(nTempPos); | ||||||
3152 | ImplShowFocus(); | ||||||
3153 | CallEventListeners( VclEventId::ToolboxHighlight ); | ||||||
3154 | } | ||||||
3155 | } | ||||||
3156 | } | ||||||
3157 | break; | ||||||
3158 | } | ||||||
3159 | ++nTempPos; | ||||||
3160 | } | ||||||
3161 | } | ||||||
3162 | |||||||
3163 | // only clear highlight when focus is not in toolbar | ||||||
3164 | bool bMenuButtonHit = mpData->maMenubuttonItem.maRect.IsInside( aMousePos ) && ImplHasClippedItems(); | ||||||
3165 | if ( !HasFocus() && (bClearHigh || bMenuButtonHit) ) | ||||||
3166 | { | ||||||
3167 | if ( !bMenuButtonHit && mpData->mbMenubuttonSelected ) | ||||||
3168 | { | ||||||
3169 | // remove highlight from menubutton | ||||||
3170 | InvalidateMenuButton(); | ||||||
3171 | } | ||||||
3172 | |||||||
3173 | if( mnHighItemId ) | ||||||
3174 | { | ||||||
3175 | ImplToolItems::size_type nClearPos = GetItemPos( mnHighItemId ); | ||||||
3176 | if ( nClearPos != ITEM_NOTFOUND ) | ||||||
3177 | { | ||||||
3178 | InvalidateItem(nClearPos); | ||||||
3179 | if( nClearPos != mnCurPos ) | ||||||
3180 | CallEventListeners( VclEventId::ToolboxHighlightOff, reinterpret_cast< void* >( nClearPos ) ); | ||||||
3181 | } | ||||||
3182 | ImplHideFocus(); | ||||||
3183 | mnHighItemId = 0; | ||||||
3184 | } | ||||||
3185 | |||||||
3186 | if( bMenuButtonHit ) | ||||||
3187 | { | ||||||
3188 | InvalidateMenuButton(); | ||||||
3189 | } | ||||||
3190 | } | ||||||
3191 | } | ||||||
3192 | |||||||
3193 | if ( meLastStyle != eStyle ) | ||||||
3194 | { | ||||||
3195 | meLastStyle = eStyle; | ||||||
3196 | SetPointer( eStyle ); | ||||||
3197 | } | ||||||
3198 | |||||||
3199 | DockingWindow::MouseMove( rMEvt ); | ||||||
3200 | } | ||||||
3201 | |||||||
3202 | void ToolBox::MouseButtonDown( const MouseEvent& rMEvt ) | ||||||
3203 | { | ||||||
3204 | // only trigger toolbox for left mouse button and when | ||||||
3205 | // we're not in normal operation | ||||||
3206 | if ( rMEvt.IsLeft() && !mbDrag && (mnCurPos == ITEM_NOTFOUND) ) | ||||||
3207 | { | ||||||
3208 | // call activate already here, as items could | ||||||
3209 | // be exchanged | ||||||
3210 | Activate(); | ||||||
3211 | |||||||
3212 | // update ToolBox here, such that user knows it | ||||||
3213 | if ( mbFormat ) | ||||||
3214 | { | ||||||
3215 | ImplFormat(); | ||||||
3216 | PaintImmediately(); | ||||||
3217 | } | ||||||
3218 | |||||||
3219 | Point aMousePos = rMEvt.GetPosPixel(); | ||||||
3220 | ImplToolItems::size_type i = 0; | ||||||
3221 | ImplToolItems::size_type nNewPos = ITEM_NOTFOUND; | ||||||
3222 | |||||||
3223 | // search for item that was clicked | ||||||
3224 | for (auto const& item : mpData->m_aItems) | ||||||
3225 | { | ||||||
3226 | // is this the item? | ||||||
3227 | if ( item.maRect.IsInside( aMousePos ) ) | ||||||
3228 | { | ||||||
3229 | // do nothing if it is a separator or | ||||||
3230 | // if the item has been disabled | ||||||
3231 | if ( (item.meType == ToolBoxItemType::BUTTON) && | ||||||
3232 | !item.mbShowWindow ) | ||||||
3233 | nNewPos = i; | ||||||
3234 | |||||||
3235 | break; | ||||||
3236 | } | ||||||
3237 | |||||||
3238 | i++; | ||||||
3239 | } | ||||||
3240 | |||||||
3241 | // item found | ||||||
3242 | if ( nNewPos != ITEM_NOTFOUND ) | ||||||
3243 | { | ||||||
3244 | if ( !mpData->m_aItems[nNewPos].mbEnabled ) | ||||||
3245 | { | ||||||
3246 | Deactivate(); | ||||||
3247 | return; | ||||||
3248 | } | ||||||
3249 | |||||||
3250 | // update actual data | ||||||
3251 | StartTrackingFlags nTrackFlags = StartTrackingFlags::NONE; | ||||||
3252 | mnCurPos = i; | ||||||
3253 | mnCurItemId = mpData->m_aItems[nNewPos].mnId; | ||||||
3254 | mnDownItemId = mnCurItemId; | ||||||
3255 | mnMouseModifier = rMEvt.GetModifier(); | ||||||
3256 | if ( mpData->m_aItems[nNewPos].mnBits & ToolBoxItemBits::REPEAT ) | ||||||
3257 | nTrackFlags |= StartTrackingFlags::ButtonRepeat; | ||||||
3258 | |||||||
3259 | // update bDrag here, as it is evaluated in the EndSelection | ||||||
3260 | mbDrag = true; | ||||||
3261 | |||||||
3262 | // on double-click: only call the handler, but do so before the button | ||||||
3263 | // is hit, as in the handler dragging | ||||||
3264 | // can be terminated | ||||||
3265 | if ( rMEvt.GetClicks() == 2 ) | ||||||
3266 | DoubleClick(); | ||||||
3267 | |||||||
3268 | if ( mbDrag ) | ||||||
3269 | { | ||||||
3270 | InvalidateItem(mnCurPos); | ||||||
3271 | Highlight(); | ||||||
3272 | } | ||||||
3273 | |||||||
3274 | // was dropdown arrow pressed | ||||||
3275 | if( mpData->m_aItems[nNewPos].mnBits & ToolBoxItemBits::DROPDOWN ) | ||||||
3276 | { | ||||||
3277 | if( ( (mpData->m_aItems[nNewPos].mnBits & ToolBoxItemBits::DROPDOWNONLY) == ToolBoxItemBits::DROPDOWNONLY) | ||||||
3278 | || mpData->m_aItems[nNewPos].GetDropDownRect( mbHorz ).IsInside( aMousePos )) | ||||||
3279 | { | ||||||
3280 | // dropdownonly always triggers the dropdown handler, over the whole button area | ||||||
3281 | |||||||
3282 | // the drop down arrow should not trigger the item action | ||||||
3283 | mpData->mbDropDownByKeyboard = false; | ||||||
3284 | mpData->maDropdownClickHdl.Call( this ); | ||||||
3285 | |||||||
3286 | // do not reset data if the dropdown handler opened a floating window | ||||||
3287 | // see ImplFloatControl() | ||||||
3288 | if( !mpFloatWin ) | ||||||
3289 | { | ||||||
3290 | // no floater was opened | ||||||
3291 | Deactivate(); | ||||||
3292 | InvalidateItem(mnCurPos); | ||||||
3293 | |||||||
3294 | mnCurPos = ITEM_NOTFOUND; | ||||||
3295 | mnCurItemId = 0; | ||||||
3296 | mnDownItemId = 0; | ||||||
3297 | mnMouseModifier = 0; | ||||||
3298 | mnHighItemId = 0; | ||||||
3299 | } | ||||||
3300 | return; | ||||||
3301 | } | ||||||
3302 | else // activate long click timer | ||||||
3303 | mpData->maDropdownTimer.Start(); | ||||||
3304 | } | ||||||
3305 | |||||||
3306 | // call Click handler | ||||||
3307 | if ( rMEvt.GetClicks() != 2 ) | ||||||
3308 | Click(); | ||||||
3309 | |||||||
3310 | // also call Select handler at repeat | ||||||
3311 | if ( nTrackFlags & StartTrackingFlags::ButtonRepeat ) | ||||||
3312 | Select(); | ||||||
3313 | |||||||
3314 | // if the actions was not aborted in Click handler | ||||||
3315 | if ( mbDrag ) | ||||||
3316 | StartTracking( nTrackFlags ); | ||||||
3317 | |||||||
3318 | // if mouse was clicked over an item we | ||||||
3319 | // can abort here | ||||||
3320 | return; | ||||||
3321 | } | ||||||
3322 | |||||||
3323 | Deactivate(); | ||||||
3324 | |||||||
3325 | // menu button hit ? | ||||||
3326 | if( mpData->maMenubuttonItem.maRect.IsInside( aMousePos ) && ImplHasClippedItems() ) | ||||||
3327 | { | ||||||
3328 | if ( maMenuButtonHdl.IsSet() ) | ||||||
3329 | maMenuButtonHdl.Call( this ); | ||||||
3330 | else | ||||||
3331 | ExecuteCustomMenu( mpData->maMenubuttonItem.maRect ); | ||||||
3332 | return; | ||||||
3333 | } | ||||||
3334 | |||||||
3335 | // check scroll- and next-buttons here | ||||||
3336 | if ( maUpperRect.IsInside( aMousePos ) ) | ||||||
3337 | { | ||||||
3338 | if ( mnCurLine > 1 ) | ||||||
3339 | { | ||||||
3340 | StartTracking(); | ||||||
3341 | mbUpper = true; | ||||||
3342 | mbIn = true; | ||||||
3343 | InvalidateSpin(true, false); | ||||||
3344 | } | ||||||
3345 | return; | ||||||
3346 | } | ||||||
3347 | if ( maLowerRect.IsInside( aMousePos ) ) | ||||||
3348 | { | ||||||
3349 | if ( mnCurLine+mnVisLines-1 < mnCurLines ) | ||||||
3350 | { | ||||||
3351 | StartTracking(); | ||||||
3352 | mbLower = true; | ||||||
3353 | mbIn = true; | ||||||
3354 | InvalidateSpin(false); | ||||||
3355 | } | ||||||
3356 | return; | ||||||
3357 | } | ||||||
3358 | |||||||
3359 | // Linesizing testen | ||||||
3360 | if ( (mnWinStyle & TB_WBLINESIZING(WB_SIZEABLE | WB_DOCKABLE | WB_SCROLL)) == TB_WBLINESIZING(WB_SIZEABLE | WB_DOCKABLE | WB_SCROLL) ) | ||||||
3361 | { | ||||||
3362 | sal_uInt16 nLineMode = ImplTestLineSize( aMousePos ); | ||||||
3363 | if ( nLineMode ) | ||||||
3364 | { | ||||||
3365 | ImplTBDragMgr* pMgr = ImplGetTBDragMgr(); | ||||||
3366 | |||||||
3367 | // call handler, such that we can set the | ||||||
3368 | // dock rectangles | ||||||
3369 | StartDocking(); | ||||||
3370 | |||||||
3371 | Point aPos = GetParent()->OutputToScreenPixel( GetPosPixel() ); | ||||||
3372 | Size aSize = GetSizePixel(); | ||||||
3373 | aPos = ScreenToOutputPixel( aPos ); | ||||||
3374 | |||||||
3375 | // start dragging | ||||||
3376 | pMgr->StartDragging( this, aMousePos, tools::Rectangle( aPos, aSize ), | ||||||
3377 | nLineMode ); | ||||||
3378 | return; | ||||||
3379 | } | ||||||
3380 | } | ||||||
3381 | |||||||
3382 | // no item, then only click or double click | ||||||
3383 | if ( rMEvt.GetClicks() == 2 ) | ||||||
3384 | DoubleClick(); | ||||||
3385 | else | ||||||
3386 | Click(); | ||||||
3387 | } | ||||||
3388 | |||||||
3389 | if ( !mbDrag && (mnCurPos == ITEM_NOTFOUND) ) | ||||||
3390 | DockingWindow::MouseButtonDown( rMEvt ); | ||||||
3391 | } | ||||||
3392 | |||||||
3393 | void ToolBox::MouseButtonUp( const MouseEvent& rMEvt ) | ||||||
3394 | { | ||||||
3395 | if ( ImplHandleMouseButtonUp( rMEvt ) ) | ||||||
| |||||||
3396 | return; | ||||||
3397 | |||||||
3398 | if ( mbDragging && rMEvt.IsLeft() ) | ||||||
3399 | { | ||||||
3400 | ImplTBDragMgr* pMgr = ImplGetTBDragMgr(); | ||||||
3401 | pMgr->EndDragging(); | ||||||
3402 | return; | ||||||
3403 | } | ||||||
3404 | |||||||
3405 | DockingWindow::MouseButtonUp( rMEvt ); | ||||||
3406 | } | ||||||
3407 | |||||||
3408 | void ToolBox::Tracking( const TrackingEvent& rTEvt ) | ||||||
3409 | { | ||||||
3410 | VclPtr<vcl::Window> xWindow = this; | ||||||
3411 | |||||||
3412 | if ( rTEvt.IsTrackingEnded() ) | ||||||
3413 | ImplHandleMouseButtonUp( rTEvt.GetMouseEvent(), rTEvt.IsTrackingCanceled() ); | ||||||
3414 | else | ||||||
3415 | ImplHandleMouseMove( rTEvt.GetMouseEvent(), rTEvt.IsTrackingRepeat() ); | ||||||
3416 | |||||||
3417 | if ( xWindow->IsDisposed() ) | ||||||
3418 | // toolbox was deleted | ||||||
3419 | return; | ||||||
3420 | DockingWindow::Tracking( rTEvt ); | ||||||
3421 | } | ||||||
3422 | |||||||
3423 | void ToolBox::InvalidateItem(ImplToolItems::size_type nPosition) | ||||||
3424 | { | ||||||
3425 | if (mpData && nPosition < mpData->m_aItems.size()) | ||||||
3426 | { | ||||||
3427 | ImplToolItem* pItem = &mpData->m_aItems[nPosition]; | ||||||
3428 | Invalidate(pItem->maRect); | ||||||
3429 | } | ||||||
3430 | } | ||||||
3431 | |||||||
3432 | void ToolBox::InvalidateMenuButton() | ||||||
3433 | { | ||||||
3434 | if (!mpData->maMenubuttonItem.maRect.IsEmpty()) | ||||||
3435 | Invalidate(mpData->maMenubuttonItem.maRect); | ||||||
3436 | } | ||||||
3437 | |||||||
3438 | void ToolBox::InvalidateSpin(bool bUpperIn, bool bLowerIn) | ||||||
3439 | { | ||||||
3440 | if (bUpperIn && !maUpperRect.IsEmpty()) | ||||||
3441 | Invalidate(maUpperRect); | ||||||
3442 | |||||||
3443 | if (bLowerIn && !maLowerRect.IsEmpty()) | ||||||
3444 | Invalidate(maLowerRect); | ||||||
3445 | } | ||||||
3446 | |||||||
3447 | void ToolBox::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rPaintRect) | ||||||
3448 | { | ||||||
3449 | if( mpData->mbIsPaintLocked ) | ||||||
3450 | return; | ||||||
3451 | |||||||
3452 | if (rPaintRect == tools::Rectangle(0, 0, mnDX-1, mnDY-1)) | ||||||
3453 | mbFullPaint = true; | ||||||
3454 | ImplFormat(); | ||||||
3455 | mbFullPaint = false; | ||||||
3456 | |||||||
3457 | ImplDrawBackground(rRenderContext, rPaintRect); | ||||||
3458 | |||||||
3459 | if ( (mnWinStyle & WB_BORDER) && !ImplIsFloatingMode() ) | ||||||
3460 | ImplDrawBorder(rRenderContext); | ||||||
3461 | |||||||
3462 | if( !ImplIsFloatingMode() ) | ||||||
3463 | ImplDrawGrip(rRenderContext); | ||||||
3464 | |||||||
3465 | ImplDrawMenuButton(rRenderContext, mpData->mbMenubuttonSelected); | ||||||
3466 | |||||||
3467 | // draw SpinButtons | ||||||
3468 | if (mnWinStyle & WB_SCROLL) | ||||||
3469 | { | ||||||
3470 | if (mnCurLines > mnLines) | ||||||
3471 | ImplDrawSpin(rRenderContext); | ||||||
3472 | } | ||||||
3473 | |||||||
3474 | // draw buttons | ||||||
3475 | ImplToolItems::size_type nHighPos; | ||||||
3476 | if ( mnHighItemId ) | ||||||
3477 | nHighPos = GetItemPos( mnHighItemId ); | ||||||
3478 | else | ||||||
3479 | nHighPos = ITEM_NOTFOUND; | ||||||
3480 | |||||||
3481 | ImplToolItems::size_type nCount = mpData->m_aItems.size(); | ||||||
3482 | for( ImplToolItems::size_type i = 0; i < nCount; i++ ) | ||||||
3483 | { | ||||||
3484 | ImplToolItem* pItem = &mpData->m_aItems[i]; | ||||||
3485 | |||||||
3486 | // only draw when the rectangle is in the draw rectangle | ||||||
3487 | if ( !pItem->maRect.IsEmpty() && rPaintRect.IsOver( pItem->maRect ) ) | ||||||
3488 | { | ||||||
3489 | sal_uInt16 nHighlight = 0; | ||||||
3490 | if ( i == mnCurPos ) | ||||||
3491 | nHighlight = 1; | ||||||
3492 | else if ( i == nHighPos ) | ||||||
3493 | nHighlight = 2; | ||||||
3494 | ImplDrawItem(rRenderContext, i, nHighlight); | ||||||
3495 | } | ||||||
3496 | } | ||||||
3497 | ImplShowFocus(); | ||||||
3498 | } | ||||||
3499 | |||||||
3500 | void ToolBox::Resize() | ||||||
3501 | { | ||||||
3502 | Size aSize = GetOutputSizePixel(); | ||||||
3503 | // #i31422# some WindowManagers send (0,0) sizes when | ||||||
3504 | // switching virtual desktops - ignore this and avoid reformatting | ||||||
3505 | if( !aSize.Width() && !aSize.Height() ) | ||||||
3506 | return; | ||||||
3507 | |||||||
3508 | long nOldDX = mnDX; | ||||||
3509 | long nOldDY = mnDY; | ||||||
3510 | mnDX = aSize.Width(); | ||||||
3511 | mnDY = aSize.Height(); | ||||||
3512 | |||||||
3513 | mnLastResizeDY = 0; | ||||||
3514 | |||||||
3515 | // invalidate everything to have gradient backgrounds properly drawn | ||||||
3516 | Invalidate(); | ||||||
3517 | |||||||
3518 | // If we have any expandable entries, then force a reformat first using | ||||||
3519 | // their optimal sizes, then share out the excess space evenly across those | ||||||
3520 | // expandables and reformat again | ||||||
3521 | std::vector<size_t> aExpandables; | ||||||
3522 | for (size_t i = 0; i < mpData->m_aItems.size(); ++i) | ||||||
3523 | { | ||||||
3524 | if (mpData->m_aItems[i].mbExpand) | ||||||
3525 | { | ||||||
3526 | vcl::Window *pWindow = mpData->m_aItems[i].mpWindow; | ||||||
3527 | SAL_INFO_IF(!pWindow, "vcl.layout", "only tabitems with window supported at the moment")do { if (true && (!pWindow)) { switch (sal_detail_log_report (::SAL_DETAIL_LOG_LEVEL_INFO, "vcl.layout")) { case SAL_DETAIL_LOG_ACTION_IGNORE : break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail ::getResult( ::sal::detail::StreamStart() << "only tabitems with window supported at the moment" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("vcl.layout" ), ("/home/maarten/src/libreoffice/core/vcl/source/window/toolbox.cxx" ":" "3527" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "only tabitems with window supported at the moment" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "only tabitems with window supported at the moment" ; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("vcl.layout" ), ("/home/maarten/src/libreoffice/core/vcl/source/window/toolbox.cxx" ":" "3527" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "only tabitems with window supported at the moment" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("vcl.layout" ), ("/home/maarten/src/libreoffice/core/vcl/source/window/toolbox.cxx" ":" "3527" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "only tabitems with window supported at the moment" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "only tabitems with window supported at the moment" ; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("vcl.layout" ), ("/home/maarten/src/libreoffice/core/vcl/source/window/toolbox.cxx" ":" "3527" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | ||||||
3528 | if (!pWindow) | ||||||
3529 | continue; | ||||||
3530 | Size aWinSize(pWindow->GetSizePixel()); | ||||||
3531 | Size aPrefSize(pWindow->get_preferred_size()); | ||||||
3532 | aWinSize.setWidth( aPrefSize.Width() ); | ||||||
3533 | pWindow->SetSizePixel(aWinSize); | ||||||
3534 | aExpandables.push_back(i); | ||||||
3535 | } | ||||||
3536 | } | ||||||
3537 | |||||||
3538 | // re-format or re-draw | ||||||
3539 | if ( mbScroll || !aExpandables.empty() ) | ||||||
3540 | { | ||||||
3541 | if ( !mbFormat || !aExpandables.empty() ) | ||||||
3542 | { | ||||||
3543 | mbFormat = true; | ||||||
3544 | if( IsReallyVisible() || !aExpandables.empty() ) | ||||||
3545 | { | ||||||
3546 | ImplFormat(true); | ||||||
3547 | |||||||
3548 | if (!aExpandables.empty()) | ||||||
3549 | { | ||||||
3550 | //Get how big the optimal size is | ||||||
3551 | tools::Rectangle aBounds; | ||||||
3552 | for (const ImplToolItem & rItem : mpData->m_aItems) | ||||||
3553 | { | ||||||
3554 | aBounds.Union( rItem.maRect ); | ||||||
3555 | } | ||||||
3556 | |||||||
3557 | auto nOptimalWidth = aBounds.GetWidth(); | ||||||
3558 | auto nDiff = aSize.Width() - nOptimalWidth; | ||||||
3559 | decltype(nDiff) nExpandablesSize = aExpandables.size(); | ||||||
3560 | nDiff /= nExpandablesSize; | ||||||
3561 | |||||||
3562 | //share out the diff from optimal to real across | ||||||
3563 | //expandable entries | ||||||
3564 | for (size_t nIndex : aExpandables) | ||||||
3565 | { | ||||||
3566 | vcl::Window *pWindow = mpData->m_aItems[nIndex].mpWindow; | ||||||
3567 | Size aWinSize(pWindow->GetSizePixel()); | ||||||
3568 | Size aPrefSize(pWindow->get_preferred_size()); | ||||||
3569 | aWinSize.setWidth( aPrefSize.Width() + nDiff ); | ||||||
3570 | pWindow->SetSizePixel(aWinSize); | ||||||
3571 | } | ||||||
3572 | |||||||
3573 | //now reformat with final sizes | ||||||
3574 | mbFormat = true; | ||||||
3575 | ImplFormat(true); | ||||||
3576 | } | ||||||
3577 | } | ||||||
3578 | } | ||||||
3579 | } | ||||||
3580 | |||||||
3581 | // redraw border | ||||||
3582 | if ( !(mnWinStyle & WB_BORDER) ) | ||||||
3583 | return; | ||||||
3584 | |||||||
3585 | // as otherwise, when painting we might think we have to re-draw everything | ||||||
3586 | if ( mbFormat && IsReallyVisible() ) | ||||||
3587 | Invalidate(); | ||||||
3588 | else | ||||||
3589 | { | ||||||
3590 | if ( mnRightBorder ) | ||||||
3591 | { | ||||||
3592 | if ( nOldDX > mnDX ) | ||||||
3593 | Invalidate( tools::Rectangle( mnDX-mnRightBorder-1, 0, mnDX, mnDY ) ); | ||||||
3594 | else | ||||||
3595 | Invalidate( tools::Rectangle( nOldDX-mnRightBorder-1, 0, nOldDX, nOldDY ) ); | ||||||
3596 | } | ||||||
3597 | |||||||
3598 | if ( mnBottomBorder ) | ||||||
3599 | { | ||||||
3600 | if ( nOldDY > mnDY ) | ||||||
3601 | Invalidate( tools::Rectangle( 0, mnDY-mnBottomBorder-1, mnDX, mnDY ) ); | ||||||
3602 | else | ||||||
3603 | Invalidate( tools::Rectangle( 0, nOldDY-mnBottomBorder-1, nOldDX, nOldDY ) ); | ||||||
3604 | } | ||||||
3605 | } | ||||||
3606 | } | ||||||
3607 | |||||||
3608 | namespace | ||||||
3609 | { | ||||||
3610 | bool DispatchableCommand(const OUString& rName) | ||||||
3611 | { | ||||||
3612 | return rName.startsWith(".uno") || | ||||||
3613 | rName.startsWith("slot:") || | ||||||
3614 | rName.startsWith("macro:") || | ||||||
3615 | rName.startsWith("vnd.sun.star.script"); | ||||||
3616 | } | ||||||
3617 | } | ||||||
3618 | |||||||
3619 | const OUString& ToolBox::ImplGetHelpText( sal_uInt16 nItemId ) const | ||||||
3620 | { | ||||||
3621 | ImplToolItem* pItem = ImplGetItem( nItemId ); | ||||||
3622 | |||||||
3623 | assert( pItem )(static_cast <bool> (pItem) ? void (0) : __assert_fail ( "pItem", "/home/maarten/src/libreoffice/core/vcl/source/window/toolbox.cxx" , 3623, __extension__ __PRETTY_FUNCTION__)); | ||||||
3624 | |||||||
3625 | if ( pItem->maHelpText.isEmpty() && ( !pItem->maHelpId.isEmpty() || pItem->maCommandStr.getLength() )) | ||||||
3626 | { | ||||||
3627 | Help* pHelp = Application::GetHelp(); | ||||||
3628 | if ( pHelp ) | ||||||
3629 | { | ||||||
3630 | if (DispatchableCommand(pItem->maCommandStr)) | ||||||
3631 | pItem->maHelpText = pHelp->GetHelpText( pItem->maCommandStr, this ); | ||||||
3632 | if ( pItem->maHelpText.isEmpty() && !pItem->maHelpId.isEmpty() ) | ||||||
3633 | pItem->maHelpText = pHelp->GetHelpText( OStringToOUString( pItem->maHelpId, RTL_TEXTENCODING_UTF8(((rtl_TextEncoding) 76)) ), this ); | ||||||
3634 | } | ||||||
3635 | } | ||||||
3636 | |||||||
3637 | return pItem->maHelpText; | ||||||
3638 | } | ||||||
3639 | |||||||
3640 | void ToolBox::RequestHelp( const HelpEvent& rHEvt ) | ||||||
3641 | { | ||||||
3642 | sal_uInt16 nItemId; | ||||||
3643 | Point aHelpPos; | ||||||
3644 | |||||||
3645 | if( !rHEvt.KeyboardActivated() ) | ||||||
3646 | { | ||||||
3647 | nItemId = GetItemId( ScreenToOutputPixel( rHEvt.GetMousePosPixel() ) ); | ||||||
3648 | aHelpPos = rHEvt.GetMousePosPixel(); | ||||||
3649 | } | ||||||
3650 | else | ||||||
3651 | { | ||||||
3652 | if( !mnHighItemId ) | ||||||
3653 | return; | ||||||
3654 | else | ||||||
3655 | nItemId = mnHighItemId; | ||||||
3656 | tools::Rectangle aRect( GetItemRect( nItemId ) ); | ||||||
3657 | if( aRect.IsEmpty() ) | ||||||
3658 | return; | ||||||
3659 | else | ||||||
3660 | aHelpPos = OutputToScreenPixel( aRect.Center() ); | ||||||
3661 | } | ||||||
3662 | |||||||
3663 | if ( nItemId ) | ||||||
3664 | { | ||||||
3665 | if ( rHEvt.GetMode() & (HelpEventMode::BALLOON | HelpEventMode::QUICK) ) | ||||||
3666 | { | ||||||
3667 | // get rectangle | ||||||
3668 | tools::Rectangle aTempRect = GetItemRect( nItemId ); | ||||||
3669 | Point aPt = OutputToScreenPixel( aTempRect.TopLeft() ); | ||||||
3670 | aTempRect.SetLeft( aPt.X() ); | ||||||
3671 | aTempRect.SetTop( aPt.Y() ); | ||||||
3672 | aPt = OutputToScreenPixel( aTempRect.BottomRight() ); | ||||||
3673 | aTempRect.SetRight( aPt.X() ); | ||||||
3674 | aTempRect.SetBottom( aPt.Y() ); | ||||||
3675 | |||||||
3676 | // get text and display it | ||||||
3677 | OUString aStr = GetQuickHelpText( nItemId ); | ||||||
3678 | if (aStr.isEmpty()) | ||||||
3679 | aStr = MnemonicGenerator::EraseAllMnemonicChars( GetItemText( nItemId ) ); | ||||||
3680 | if ( rHEvt.GetMode() & HelpEventMode::BALLOON ) | ||||||
3681 | { | ||||||
3682 | const OUString& rHelpStr = GetHelpText( nItemId ); | ||||||
3683 | if (!rHelpStr.isEmpty()) | ||||||
3684 | aStr = rHelpStr; | ||||||
3685 | Help::ShowBalloon( this, aHelpPos, aTempRect, aStr ); | ||||||
3686 | } | ||||||
3687 | else | ||||||
3688 | Help::ShowQuickHelp( this, aTempRect, aStr, QuickHelpFlags::CtrlText ); | ||||||
3689 | return; | ||||||
3690 | } | ||||||
3691 | } | ||||||
3692 | |||||||
3693 | DockingWindow::RequestHelp( rHEvt ); | ||||||
3694 | } | ||||||
3695 | |||||||
3696 | bool ToolBox::EventNotify( NotifyEvent& rNEvt ) | ||||||
3697 | { | ||||||
3698 | if ( rNEvt.GetType() == MouseNotifyEvent::KEYINPUT ) | ||||||
3699 | { | ||||||
3700 | KeyEvent aKEvt = *rNEvt.GetKeyEvent(); | ||||||
3701 | vcl::KeyCode aKeyCode = aKEvt.GetKeyCode(); | ||||||
3702 | sal_uInt16 nKeyCode = aKeyCode.GetCode(); | ||||||
3703 | switch( nKeyCode ) | ||||||
3704 | { | ||||||
3705 | case KEY_TAB: | ||||||
3706 | { | ||||||
3707 | // internal TAB cycling only if parent is not a dialog or if we are the only child | ||||||
3708 | // otherwise the dialog control will take over | ||||||
3709 | vcl::Window *pParent = ImplGetParent(); | ||||||
3710 | bool bOldSchoolContainer = | ||||||
3711 | ((pParent->GetStyle() & (WB_DIALOGCONTROL | WB_NODIALOGCONTROL)) == WB_DIALOGCONTROL && | ||||||
3712 | pParent->GetChildCount() != 1); | ||||||
3713 | bool bNoTabCycling = bOldSchoolContainer || isContainerWindow(pParent); | ||||||
3714 | |||||||
3715 | if( bNoTabCycling ) | ||||||
3716 | return DockingWindow::EventNotify( rNEvt ); | ||||||
3717 | else if( ImplChangeHighlightUpDn( aKeyCode.IsShift() , bNoTabCycling ) ) | ||||||
3718 | return true; | ||||||
3719 | else | ||||||
3720 | return DockingWindow::EventNotify( rNEvt ); | ||||||
3721 | } | ||||||
3722 | default: | ||||||
3723 | break; | ||||||
3724 | } | ||||||
3725 | } | ||||||
3726 | else if( rNEvt.GetType() == MouseNotifyEvent::GETFOCUS ) | ||||||
3727 | { | ||||||
3728 | if( rNEvt.GetWindow() == this ) | ||||||
3729 | { | ||||||
3730 | // the toolbar itself got the focus | ||||||
3731 | if( mnLastFocusItemId != 0 || mpData->mbMenubuttonWasLastSelected ) | ||||||
3732 | { | ||||||
3733 | // restore last item | ||||||
3734 | if( mpData->mbMenubuttonWasLastSelected ) | ||||||
3735 | { | ||||||
3736 | ImplChangeHighlight( nullptr ); | ||||||
3737 | mpData->mbMenubuttonSelected = true; | ||||||
3738 | InvalidateMenuButton(); | ||||||
3739 | } | ||||||
3740 | else | ||||||
3741 | { | ||||||
3742 | ImplChangeHighlight( ImplGetItem( mnLastFocusItemId ) ); | ||||||
3743 | mnLastFocusItemId = 0; | ||||||
3744 | } | ||||||
3745 | } | ||||||
3746 | else if( (GetGetFocusFlags() & (GetFocusFlags::Backward|GetFocusFlags::Tab) ) == (GetFocusFlags::Backward|GetFocusFlags::Tab)) | ||||||
3747 | // Shift-TAB was pressed in the parent | ||||||
3748 | ImplChangeHighlightUpDn( false ); | ||||||
3749 | else | ||||||
3750 | ImplChangeHighlightUpDn( true ); | ||||||
3751 | |||||||
3752 | mnLastFocusItemId = 0; | ||||||
3753 | |||||||
3754 | return true; | ||||||
3755 | } | ||||||
3756 | else | ||||||
3757 | { | ||||||
3758 | // a child window got the focus so update current item to | ||||||
3759 | // allow for proper lose focus handling in keyboard navigation | ||||||
3760 | for (auto const& item : mpData->m_aItems) | ||||||
3761 | { | ||||||
3762 | if ( item.mbVisible ) | ||||||
3763 | { | ||||||
3764 | if ( item.mpWindow && item.mpWindow->ImplIsWindowOrChild( rNEvt.GetWindow() ) ) | ||||||
3765 | { | ||||||
3766 | mnHighItemId = item.mnId; | ||||||
3767 | break; | ||||||
3768 | } | ||||||
3769 | } | ||||||
3770 | } | ||||||
3771 | return DockingWindow::EventNotify( rNEvt ); | ||||||
3772 | } | ||||||
3773 | } | ||||||
3774 | else if( rNEvt.GetType() == MouseNotifyEvent::LOSEFOCUS ) | ||||||
3775 | { | ||||||
3776 | // deselect | ||||||
3777 | ImplHideFocus(); | ||||||
3778 | mpData->mbMenubuttonWasLastSelected = false; | ||||||
3779 | mnHighItemId = 0; | ||||||
3780 | mnCurPos = ITEM_NOTFOUND; | ||||||
3781 | } | ||||||
3782 | |||||||
3783 | return DockingWindow::EventNotify( rNEvt ); | ||||||
3784 | } | ||||||
3785 | |||||||
3786 | void ToolBox::Command( const CommandEvent& rCEvt ) | ||||||
3787 | { | ||||||
3788 | if ( rCEvt.GetCommand() == CommandEventId::Wheel ) | ||||||
3789 | { | ||||||
3790 | if ( (mnCurLine > 1) || (mnCurLine+mnVisLines-1 < mnCurLines) ) | ||||||
3791 | { | ||||||
3792 | const CommandWheelData* pData = rCEvt.GetWheelData(); | ||||||
3793 | if ( pData->GetMode() == CommandWheelMode::SCROLL ) | ||||||
3794 | { | ||||||
3795 | if ( (mnCurLine > 1) && (pData->GetDelta() > 0) ) | ||||||
3796 | ShowLine( false ); | ||||||
3797 | else if ( (mnCurLine+mnVisLines-1 < mnCurLines) && (pData->GetDelta() < 0) ) | ||||||
3798 | ShowLine( true ); | ||||||
3799 | InvalidateSpin(); | ||||||
3800 | return; | ||||||
3801 | } | ||||||
3802 | } | ||||||
3803 | } | ||||||
3804 | else if ( rCEvt.GetCommand() == CommandEventId::ContextMenu ) | ||||||
3805 | { | ||||||
3806 | ExecuteCustomMenu( tools::Rectangle( rCEvt.GetMousePosPixel(), rCEvt.GetMousePosPixel() ) ); | ||||||
3807 | return; | ||||||
3808 | } | ||||||
3809 | |||||||
3810 | DockingWindow::Command( rCEvt ); | ||||||
3811 | } | ||||||
3812 | |||||||
3813 | void ToolBox::StateChanged( StateChangedType nType ) | ||||||
3814 | { | ||||||
3815 | DockingWindow::StateChanged( nType ); | ||||||
3816 | |||||||
3817 | if ( nType == StateChangedType::InitShow ) | ||||||
3818 | ImplFormat(); | ||||||
3819 | else if ( nType == StateChangedType::Enable ) | ||||||
3820 | ImplUpdateItem(); | ||||||
3821 | else if ( nType == StateChangedType::UpdateMode ) | ||||||
3822 | { | ||||||
3823 | if ( IsUpdateMode() ) | ||||||
3824 | Invalidate(); | ||||||
3825 | } | ||||||
3826 | else if ( (nType == StateChangedType::Zoom) || | ||||||
3827 | (nType == StateChangedType::ControlFont) ) | ||||||
3828 | { | ||||||
3829 | mbCalc = true; | ||||||
3830 | mbFormat = true; | ||||||
3831 | ImplInitSettings( true, false, false ); | ||||||
3832 | Invalidate(); | ||||||
3833 | } | ||||||
3834 | else if ( nType == StateChangedType::ControlForeground ) | ||||||
3835 | { | ||||||
3836 | ImplInitSettings( false, true, false ); | ||||||
3837 | Invalidate(); | ||||||
3838 | } | ||||||
3839 | else if ( nType == StateChangedType::ControlBackground ) | ||||||
3840 | { | ||||||
3841 | ImplInitSettings( false, false, true ); // font, foreground, background | ||||||
3842 | Invalidate(); | ||||||
3843 | } | ||||||
3844 | |||||||
3845 | maStateChangedHandler.Call( &nType ); | ||||||
3846 | } | ||||||
3847 | |||||||
3848 | void ToolBox::DataChanged( const DataChangedEvent& rDCEvt ) | ||||||
3849 | { | ||||||
3850 | DockingWindow::DataChanged( rDCEvt ); | ||||||
3851 | |||||||
3852 | if ( (rDCEvt.GetType() == DataChangedEventType::DISPLAY) || | ||||||
3853 | (rDCEvt.GetType() == DataChangedEventType::FONTS) || | ||||||
3854 | (rDCEvt.GetType() == DataChangedEventType::FONTSUBSTITUTION) || | ||||||
3855 | ((rDCEvt.GetType() == DataChangedEventType::SETTINGS) && | ||||||
3856 | (rDCEvt.GetFlags() & AllSettingsFlags::STYLE)) ) | ||||||
3857 | { | ||||||
3858 | mbCalc = true; | ||||||
3859 | mbFormat = true; | ||||||
3860 | ImplInitSettings( true, true, true ); | ||||||
3861 | Invalidate(); | ||||||
3862 | } | ||||||
3863 | |||||||
3864 | maDataChangedHandler.Call( &rDCEvt ); | ||||||
3865 | } | ||||||
3866 | |||||||
3867 | void ToolBox::statusChanged( const css::frame::FeatureStateEvent& Event ) | ||||||
3868 | { | ||||||
3869 | // Update image mirroring/rotation | ||||||
3870 | if ( Event.FeatureURL.Complete != ".uno:ImageOrientation" ) | ||||||
3871 | return; | ||||||
3872 | |||||||
3873 | SfxImageItem aItem( 1 ); | ||||||
3874 | aItem.PutValue( Event.State, 0 ); | ||||||
3875 | |||||||
3876 | mbImagesMirrored = aItem.IsMirrored(); | ||||||
3877 | mnImagesRotationAngle = aItem.GetRotation(); | ||||||
3878 | |||||||
3879 | // update image orientation | ||||||
3880 | OUString aModuleName(vcl::CommandInfoProvider::GetModuleIdentifier(mpStatusListener->getFrame())); | ||||||
3881 | for (auto const& item : mpData->m_aItems) | ||||||
3882 | { | ||||||
3883 | if (vcl::CommandInfoProvider::IsMirrored(item.maCommandStr, aModuleName)) | ||||||
3884 | SetItemImageMirrorMode(item.mnId, mbImagesMirrored); | ||||||
3885 | if (vcl::CommandInfoProvider::IsRotated(item.maCommandStr, aModuleName)) | ||||||
3886 | SetItemImageAngle(item.mnId, mnImagesRotationAngle); | ||||||
3887 | } | ||||||
3888 | } | ||||||
3889 | |||||||
3890 | void ToolBox::SetStyle(WinBits nNewStyle) | ||||||
3891 | { | ||||||
3892 | mnWinStyle = nNewStyle; | ||||||
3893 | if (!ImplIsFloatingMode()) | ||||||
3894 | { | ||||||
3895 | bool bOldScroll = mbScroll; | ||||||
3896 | mbScroll = (mnWinStyle & WB_SCROLL) != 0; | ||||||
3897 | if (mbScroll != bOldScroll) | ||||||
3898 | { | ||||||
3899 | mbFormat = true; | ||||||
3900 | ImplFormat(); | ||||||
3901 | } | ||||||
3902 | } | ||||||
3903 | } | ||||||
3904 | |||||||
3905 | void ToolBox::ToggleFloatingMode() | ||||||
3906 | { | ||||||
3907 | DockingWindow::ToggleFloatingMode(); | ||||||
3908 | |||||||
3909 | if (!mpData) | ||||||
3910 | return; | ||||||
3911 | |||||||
3912 | bool bOldHorz = mbHorz; | ||||||
3913 | |||||||
3914 | if ( ImplIsFloatingMode() ) | ||||||
3915 | { | ||||||
3916 | mbHorz = true; | ||||||
3917 | meAlign = WindowAlign::Top; | ||||||
3918 | mbScroll = true; | ||||||
3919 | |||||||
3920 | if( bOldHorz != mbHorz ) | ||||||
3921 | mbCalc = true; // orientation was changed ! | ||||||
3922 | |||||||
3923 | ImplSetMinMaxFloatSize(); | ||||||
3924 | SetOutputSizePixel( ImplCalcFloatSize( mnFloatLines ) ); | ||||||
3925 | } | ||||||
3926 | else | ||||||
3927 | { | ||||||
3928 | mbScroll = (mnWinStyle & WB_SCROLL) != 0; | ||||||
3929 | if ( (meAlign == WindowAlign::Top) || (meAlign == WindowAlign::Bottom) ) | ||||||
3930 | mbHorz = true; | ||||||
3931 | else | ||||||
3932 | mbHorz = false; | ||||||
3933 | |||||||
3934 | // set focus back to document | ||||||
3935 | ImplGetFrameWindow()->GetWindow( GetWindowType::Client )->GrabFocus(); | ||||||
3936 | } | ||||||
3937 | |||||||
3938 | if( bOldHorz != mbHorz ) | ||||||
3939 | { | ||||||
3940 | // if orientation changes, the toolbox has to be initialized again | ||||||
3941 | // to update the direction of the gradient | ||||||
3942 | mbCalc = true; | ||||||
3943 | ImplInitSettings( true, true, true ); | ||||||
3944 | } | ||||||
3945 | |||||||
3946 | mbFormat = true; | ||||||
3947 | ImplFormat(); | ||||||
3948 | } | ||||||
3949 | |||||||
3950 | void ToolBox::StartDocking() | ||||||
3951 | { | ||||||
3952 | meDockAlign = meAlign; | ||||||
3953 | mnDockLines = mnLines; | ||||||
3954 | mbLastFloatMode = ImplIsFloatingMode(); | ||||||
3955 | DockingWindow::StartDocking(); | ||||||
3956 | } | ||||||
3957 | |||||||
3958 | bool ToolBox::Docking( const Point& rPos, tools::Rectangle& rRect ) | ||||||
3959 | { | ||||||
3960 | // do nothing during dragging, it was calculated before | ||||||
3961 | if ( mbDragging ) | ||||||
3962 | return false; | ||||||
3963 | |||||||
3964 | bool bFloatMode = false; | ||||||
3965 | |||||||
3966 | DockingWindow::Docking( rPos, rRect ); | ||||||
3967 | |||||||
3968 | // if the mouse is outside the area, it can only become a floating window | ||||||
3969 | tools::Rectangle aDockingRect( rRect ); | ||||||
3970 | if ( !ImplIsFloatingMode() ) | ||||||
3971 | { | ||||||
3972 | // don't use tracking rectangle for alignment check, because it will be too large | ||||||
3973 | // to get a floating mode as result - switch to floating size | ||||||
3974 | // so the calculation only depends on the position of the rectangle, not the current | ||||||
3975 | // docking state of the window | ||||||
3976 | ImplToolItems::size_type nTemp = 0; | ||||||
3977 | aDockingRect.SetSize( ImplCalcFloatSize( nTemp ) ); | ||||||
3978 | |||||||
3979 | // in this mode docking is never done by keyboard, so it's OK to use the mouse position | ||||||
3980 | aDockingRect.SetPos( ImplGetFrameWindow()->GetPointerPosPixel() ); | ||||||
3981 | } | ||||||
3982 | |||||||
3983 | bFloatMode = true; | ||||||
3984 | |||||||
3985 | meDockAlign = meAlign; | ||||||
3986 | if ( !mbLastFloatMode ) | ||||||
3987 | { | ||||||
3988 | ImplToolItems::size_type nTemp = 0; | ||||||
3989 | aDockingRect.SetSize( ImplCalcFloatSize( nTemp ) ); | ||||||
3990 | } | ||||||
3991 | |||||||
3992 | rRect = aDockingRect; | ||||||
3993 | mbLastFloatMode = bFloatMode; | ||||||
3994 | |||||||
3995 | return bFloatMode; | ||||||
3996 | } | ||||||
3997 | |||||||
3998 | void ToolBox::EndDocking( const tools::Rectangle& rRect, bool bFloatMode ) | ||||||
3999 | { | ||||||
4000 | if ( !IsDockingCanceled() ) | ||||||
4001 | { | ||||||
4002 | if ( mnLines != mnDockLines ) | ||||||
4003 | SetLineCount( mnDockLines ); | ||||||
4004 | if ( meAlign != meDockAlign ) | ||||||
4005 | SetAlign( meDockAlign ); | ||||||
4006 | } | ||||||
4007 | if ( bFloatMode || (bFloatMode != ImplIsFloatingMode()) ) | ||||||
4008 | DockingWindow::EndDocking( rRect, bFloatMode ); | ||||||
4009 | } | ||||||
4010 | |||||||
4011 | void ToolBox::Resizing( Size& rSize ) | ||||||
4012 | { | ||||||
4013 | ImplToolItems::size_type nCalcLines; | ||||||
4014 | ImplToolItems::size_type nTemp; | ||||||
4015 | |||||||
4016 | // calculate all floating sizes | ||||||
4017 | ImplCalcFloatSizes(); | ||||||
4018 | |||||||
4019 | if ( !mnLastResizeDY ) | ||||||
4020 | mnLastResizeDY = mnDY; | ||||||
4021 | |||||||
4022 | // is vertical resizing needed | ||||||
4023 | if ( (mnLastResizeDY != rSize.Height()) && (mnDY != rSize.Height()) ) | ||||||
4024 | { | ||||||
4025 | nCalcLines = ImplCalcLines( rSize.Height() ); | ||||||
4026 | if ( nCalcLines < 1 ) | ||||||
4027 | nCalcLines = 1; | ||||||
4028 | rSize = ImplCalcFloatSize( nCalcLines ); | ||||||
4029 | } | ||||||
4030 | else | ||||||
4031 | { | ||||||
4032 | nCalcLines = 1; | ||||||
4033 | nTemp = nCalcLines; | ||||||
4034 | Size aTempSize = ImplCalcFloatSize( nTemp ); | ||||||
4035 | while ( (aTempSize.Width() > rSize.Width()) && | ||||||
4036 | (nCalcLines <= maFloatSizes[0].mnLines) ) | ||||||
4037 | { | ||||||
4038 | nCalcLines++; | ||||||
4039 | nTemp = nCalcLines; | ||||||
4040 | aTempSize = ImplCalcFloatSize( nTemp ); | ||||||
4041 | } | ||||||
4042 | rSize = aTempSize; | ||||||
4043 | } | ||||||
4044 | |||||||
4045 | mnLastResizeDY = rSize.Height(); | ||||||
4046 | } | ||||||
4047 | |||||||
4048 | Size ToolBox::GetOptimalSize() const | ||||||
4049 | { | ||||||
4050 | // If we have any expandable entries, then force them to their | ||||||
4051 | // optimal sizes, then reset them afterwards | ||||||
4052 | std::map<vcl::Window*, Size> aExpandables; | ||||||
4053 | for (const ImplToolItem & rItem : mpData->m_aItems) | ||||||
4054 | { | ||||||
4055 | if (rItem.mbExpand) | ||||||
4056 | { | ||||||
4057 | vcl::Window *pWindow = rItem.mpWindow; | ||||||
4058 | SAL_INFO_IF(!pWindow, "vcl.layout", "only tabitems with window supported at the moment")do { if (true && (!pWindow)) { switch (sal_detail_log_report (::SAL_DETAIL_LOG_LEVEL_INFO, "vcl.layout")) { case SAL_DETAIL_LOG_ACTION_IGNORE : break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail ::getResult( ::sal::detail::StreamStart() << "only tabitems with window supported at the moment" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("vcl.layout" ), ("/home/maarten/src/libreoffice/core/vcl/source/window/toolbox.cxx" ":" "4058" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "only tabitems with window supported at the moment" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "only tabitems with window supported at the moment" ; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("vcl.layout" ), ("/home/maarten/src/libreoffice/core/vcl/source/window/toolbox.cxx" ":" "4058" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "only tabitems with window supported at the moment" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("vcl.layout" ), ("/home/maarten/src/libreoffice/core/vcl/source/window/toolbox.cxx" ":" "4058" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "only tabitems with window supported at the moment" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "only tabitems with window supported at the moment" ; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("vcl.layout" ), ("/home/maarten/src/libreoffice/core/vcl/source/window/toolbox.cxx" ":" "4058" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | ||||||
4059 | if (!pWindow) | ||||||
4060 | continue; | ||||||
4061 | Size aWinSize(pWindow->GetSizePixel()); | ||||||
4062 | aExpandables[pWindow] = aWinSize; | ||||||
4063 | Size aPrefSize(pWindow->get_preferred_size()); | ||||||
4064 | aWinSize.setWidth( aPrefSize.Width() ); | ||||||
4065 | pWindow->SetSizePixel(aWinSize); | ||||||
4066 | } | ||||||
4067 | } | ||||||
4068 | |||||||
4069 | Size aSize(const_cast<ToolBox *>(this)->ImplCalcSize( mnLines )); | ||||||
4070 | |||||||
4071 | for (auto const& expandable : aExpandables) | ||||||
4072 | { | ||||||
4073 | vcl::Window *pWindow = expandable.first; | ||||||
4074 | Size aWinSize = expandable.second; | ||||||
4075 | pWindow->SetSizePixel(aWinSize); | ||||||
4076 | } | ||||||
4077 | |||||||
4078 | return aSize; | ||||||
4079 | } | ||||||
4080 | |||||||
4081 | Size ToolBox::CalcWindowSizePixel( ImplToolItems::size_type nCalcLines ) | ||||||
4082 | { | ||||||
4083 | return ImplCalcSize( nCalcLines ); | ||||||
4084 | } | ||||||
4085 | |||||||
4086 | Size ToolBox::CalcWindowSizePixel( ImplToolItems::size_type nCalcLines, WindowAlign eAlign ) | ||||||
4087 | { | ||||||
4088 | return ImplCalcSize( nCalcLines, | ||||||
4089 | (eAlign == WindowAlign::Top || eAlign == WindowAlign::Bottom) ? TB_CALCMODE_HORZ1 : TB_CALCMODE_VERT2 ); | ||||||
4090 | } | ||||||
4091 | |||||||
4092 | ToolBox::ImplToolItems::size_type ToolBox::ImplCountLineBreaks() const | ||||||
4093 | { | ||||||
4094 | ImplToolItems::size_type nLines = 0; | ||||||
4095 | |||||||
4096 | for (auto const& item : mpData->m_aItems) | ||||||
4097 | { | ||||||
4098 | if( item.meType == ToolBoxItemType::BREAK ) | ||||||
4099 | ++nLines; | ||||||
4100 | } | ||||||
4101 | return nLines; | ||||||
4102 | } | ||||||
4103 | |||||||
4104 | Size ToolBox::CalcPopupWindowSizePixel() | ||||||
4105 | { | ||||||
4106 | // count number of breaks and calc corresponding floating window size | ||||||
4107 | ImplToolItems::size_type nLines = ImplCountLineBreaks(); | ||||||
4108 | |||||||
4109 | if( nLines ) | ||||||
4110 | ++nLines; // add the first line | ||||||
4111 | else | ||||||
4112 | { | ||||||
4113 | // no breaks found: use quadratic layout | ||||||
4114 | nLines = static_cast<ImplToolItems::size_type>(ceil( sqrt( static_cast<double>(GetItemCount()) ) )); | ||||||
4115 | } | ||||||
4116 | |||||||
4117 | bool bPopup = mpData->mbAssumePopupMode; | ||||||
4118 | mpData->mbAssumePopupMode = true; | ||||||
4119 | |||||||
4120 | Size aSize = CalcFloatingWindowSizePixel( nLines ); | ||||||
4121 | |||||||
4122 | mpData->mbAssumePopupMode = bPopup; | ||||||
4123 | return aSize; | ||||||
4124 | } | ||||||
4125 | |||||||
4126 | Size ToolBox::CalcFloatingWindowSizePixel() | ||||||
4127 | { | ||||||
4128 | ImplToolItems::size_type nLines = ImplCountLineBreaks(); | ||||||
4129 | ++nLines; // add the first line | ||||||
4130 | return CalcFloatingWindowSizePixel( nLines ); | ||||||
4131 | } | ||||||
4132 | |||||||
4133 | Size ToolBox::CalcFloatingWindowSizePixel( ImplToolItems::size_type nCalcLines ) | ||||||
4134 | { | ||||||
4135 | bool bFloat = mpData->mbAssumeFloating; | ||||||
4136 | bool bDocking = mpData->mbAssumeDocked; | ||||||
4137 | |||||||
4138 | // simulate floating mode and force reformat before calculating | ||||||
4139 | mpData->mbAssumeFloating = true; | ||||||
4140 | mpData->mbAssumeDocked = false; | ||||||
4141 | |||||||
4142 | Size aSize = ImplCalcFloatSize( nCalcLines ); | ||||||
4143 | |||||||
4144 | mbFormat = true; | ||||||
4145 | mpData->mbAssumeFloating = bFloat; | ||||||
4146 | mpData->mbAssumeDocked = bDocking; | ||||||
4147 | |||||||
4148 | return aSize; | ||||||
4149 | } | ||||||
4150 | |||||||
4151 | Size ToolBox::CalcMinimumWindowSizePixel() | ||||||
4152 | { | ||||||
4153 | if( ImplIsFloatingMode() ) | ||||||
4154 | return ImplCalcSize( mnFloatLines ); | ||||||
4155 | else | ||||||
4156 | { | ||||||
4157 | // create dummy toolbox for measurements | ||||||
4158 | VclPtrInstance< ToolBox > pToolBox( GetParent(), GetStyle() ); | ||||||
4159 | |||||||
4160 | // copy until first useful item | ||||||
4161 | for (auto const& item : mpData->m_aItems) | ||||||
4162 | { | ||||||
4163 | pToolBox->CopyItem( *this, item.mnId ); | ||||||
4164 | if( (item.meType == ToolBoxItemType::BUTTON) && | ||||||
4165 | item.mbVisible && !ImplIsFixedControl( &item ) ) | ||||||
4166 | break; | ||||||
4167 | } | ||||||
4168 | |||||||
4169 | // add to docking manager if required to obtain a drag area | ||||||
4170 | // (which is accounted for in calcwindowsizepixel) | ||||||
4171 | if( ImplGetDockingManager()->GetDockingWindowWrapper( this ) ) | ||||||
4172 | ImplGetDockingManager()->AddWindow( pToolBox ); | ||||||
4173 | |||||||
4174 | // account for menu | ||||||
4175 | if( IsMenuEnabled() ) | ||||||
4176 | pToolBox->SetMenuType( GetMenuType() ); | ||||||
4177 | |||||||
4178 | pToolBox->SetAlign( GetAlign() ); | ||||||
4179 | Size aSize = pToolBox->CalcWindowSizePixel( 1 ); | ||||||
4180 | |||||||
4181 | ImplGetDockingManager()->RemoveWindow( pToolBox ); | ||||||
4182 | pToolBox->Clear(); | ||||||
4183 | |||||||
4184 | pToolBox.disposeAndClear(); | ||||||
4185 | |||||||
4186 | return aSize; | ||||||
4187 | } | ||||||
4188 | } | ||||||
4189 | |||||||
4190 | void ToolBox::EnableCustomize( bool bEnable ) | ||||||
4191 | { | ||||||
4192 | mbCustomize = bEnable; | ||||||
4193 | } | ||||||
4194 | |||||||
4195 | void ToolBox::LoseFocus() | ||||||
4196 | { | ||||||
4197 | ImplChangeHighlight( nullptr, true ); | ||||||
4198 | |||||||
4199 | DockingWindow::LoseFocus(); | ||||||
4200 | } | ||||||
4201 | |||||||
4202 | // performs the action associated with an item, ie simulates clicking the item | ||||||
4203 | void ToolBox::TriggerItem( sal_uInt16 nItemId ) | ||||||
4204 | { | ||||||
4205 | mnHighItemId = nItemId; | ||||||
4206 | vcl::KeyCode aKeyCode( 0, 0 ); | ||||||
4207 | ImplActivateItem( aKeyCode ); | ||||||
4208 | } | ||||||
4209 | |||||||
4210 | // calls the button's action handler | ||||||
4211 | // returns true if action was called | ||||||
4212 | bool ToolBox::ImplActivateItem( vcl::KeyCode aKeyCode ) | ||||||
4213 | { | ||||||
4214 | bool bRet = true; | ||||||
4215 | if( mnHighItemId ) | ||||||
4216 | { | ||||||
4217 | ImplToolItem *pToolItem = ImplGetItem( mnHighItemId ); | ||||||
4218 | |||||||
4219 | // #107712#, activate can also be called for disabled entries | ||||||
4220 | if( pToolItem && !pToolItem->mbEnabled ) | ||||||
4221 | return true; | ||||||
4222 | |||||||
4223 | if( pToolItem && pToolItem->mpWindow && HasFocus() ) | ||||||
4224 | { | ||||||
4225 | ImplHideFocus(); | ||||||
4226 | mbChangingHighlight = true; // avoid focus change due to loss of focus | ||||||
4227 | pToolItem->mpWindow->ImplControlFocus( GetFocusFlags::Tab ); | ||||||
4228 | mbChangingHighlight = false; | ||||||
4229 | } | ||||||
4230 | else | ||||||
4231 | { | ||||||
4232 | mnDownItemId = mnCurItemId = mnHighItemId; | ||||||
4233 | if (pToolItem && (pToolItem->mnBits & ToolBoxItemBits::AUTOCHECK)) | ||||||
4234 | { | ||||||
4235 | if ( pToolItem->mnBits & ToolBoxItemBits::RADIOCHECK ) | ||||||
4236 | { | ||||||
4237 | if ( pToolItem->meState != TRISTATE_TRUE ) | ||||||
4238 | SetItemState( pToolItem->mnId, TRISTATE_TRUE ); | ||||||
4239 | } | ||||||
4240 | else | ||||||
4241 | { | ||||||
4242 | if ( pToolItem->meState != TRISTATE_TRUE ) | ||||||
4243 | pToolItem->meState = TRISTATE_TRUE; | ||||||
4244 | else | ||||||
4245 | pToolItem->meState = TRISTATE_FALSE; | ||||||
4246 | } | ||||||
4247 | } | ||||||
4248 | mnMouseModifier = aKeyCode.GetModifier(); | ||||||
4249 | mbIsKeyEvent = true; | ||||||
4250 | Activate(); | ||||||
4251 | Click(); | ||||||
4252 | |||||||
4253 | // #107776# we might be destroyed in the selecthandler | ||||||
4254 | VclPtr<vcl::Window> xWindow = this; | ||||||
4255 | Select(); | ||||||
4256 | if ( xWindow->IsDisposed() ) | ||||||
4257 | return bRet; | ||||||
4258 | |||||||
4259 | Deactivate(); | ||||||
4260 | mbIsKeyEvent = false; | ||||||
4261 | mnMouseModifier = 0; | ||||||
4262 | } | ||||||
4263 | } | ||||||
4264 | else | ||||||
4265 | bRet = false; | ||||||
4266 | return bRet; | ||||||
4267 | } | ||||||
4268 | |||||||
4269 | static bool ImplCloseLastPopup( vcl::Window const *pParent ) | ||||||
4270 | { | ||||||
4271 | // close last popup toolbox (see also: | ||||||
4272 | // ImplHandleMouseFloatMode(...) in winproc.cxx ) | ||||||
4273 | |||||||
4274 | if (ImplGetSVData()->mpWinData->mpFirstFloat) | ||||||
4275 | { | ||||||
4276 | FloatingWindow* pLastLevelFloat = ImplGetSVData()->mpWinData->mpFirstFloat->ImplFindLastLevelFloat(); | ||||||
4277 | // only close the floater if it is not our direct parent, which would kill ourself | ||||||
4278 | if( pLastLevelFloat && pLastLevelFloat != pParent ) | ||||||
4279 | { | ||||||
4280 | pLastLevelFloat->EndPopupMode( FloatWinPopupEndFlags::Cancel | FloatWinPopupEndFlags::CloseAll ); | ||||||
4281 | return true; | ||||||
4282 | } | ||||||
4283 | } | ||||||
4284 | return false; | ||||||
4285 | } | ||||||
4286 | |||||||
4287 | // opens a drop down toolbox item | ||||||
4288 | // returns true if item was opened | ||||||
4289 | bool ToolBox::ImplOpenItem( vcl::KeyCode aKeyCode ) | ||||||
4290 | { | ||||||
4291 | sal_uInt16 nCode = aKeyCode.GetCode(); | ||||||
4292 | bool bRet = true; | ||||||
4293 | |||||||
4294 | // arrow keys should work only in the opposite direction of alignment (to not break cursor travelling) | ||||||
4295 | if ( ((nCode == KEY_LEFT || nCode == KEY_RIGHT) && IsHorizontal()) | ||||||
4296 | || ((nCode == KEY_UP || nCode == KEY_DOWN) && !IsHorizontal()) ) | ||||||
4297 | return false; | ||||||
4298 | |||||||
4299 | if( mpData->mbMenubuttonSelected ) | ||||||
4300 | { | ||||||
4301 | if( ImplCloseLastPopup( GetParent() ) ) | ||||||
4302 | return bRet; | ||||||
4303 | mbIsKeyEvent = true; | ||||||
4304 | if ( maMenuButtonHdl.IsSet() ) | ||||||
4305 | maMenuButtonHdl.Call( this ); | ||||||
4306 | else | ||||||
4307 | ExecuteCustomMenu( mpData->maMenubuttonItem.maRect ); | ||||||
4308 | mpData->mbMenubuttonWasLastSelected = true; | ||||||
4309 | mbIsKeyEvent = false; | ||||||
4310 | } | ||||||
4311 | else if( mnHighItemId && ImplGetItem( mnHighItemId ) && | ||||||
4312 | (ImplGetItem( mnHighItemId )->mnBits & ToolBoxItemBits::DROPDOWN) ) | ||||||
4313 | { | ||||||
4314 | mnDownItemId = mnCurItemId = mnHighItemId; | ||||||
4315 | mnCurPos = GetItemPos( mnCurItemId ); | ||||||
4316 | mnLastFocusItemId = mnCurItemId; // save item id for possible later focus restore | ||||||
4317 | mnMouseModifier = aKeyCode.GetModifier(); | ||||||
4318 | mbIsKeyEvent = true; | ||||||
4319 | Activate(); | ||||||
4320 | |||||||
4321 | mpData->mbDropDownByKeyboard = true; | ||||||
4322 | mpData->maDropdownClickHdl.Call( this ); | ||||||
4323 | |||||||
4324 | mbIsKeyEvent = false; | ||||||
4325 | mnMouseModifier = 0; | ||||||
4326 | } | ||||||
4327 | else | ||||||
4328 | bRet = false; | ||||||
4329 | |||||||
4330 | return bRet; | ||||||
4331 | } | ||||||
4332 | |||||||
4333 | void ToolBox::KeyInput( const KeyEvent& rKEvt ) | ||||||
4334 | { | ||||||
4335 | vcl::KeyCode aKeyCode = rKEvt.GetKeyCode(); | ||||||
4336 | sal_uInt16 nCode = aKeyCode.GetCode(); | ||||||
4337 | |||||||
4338 | vcl::Window *pParent = ImplGetParent(); | ||||||
4339 | bool bOldSchoolContainer = ((pParent->GetStyle() & (WB_DIALOGCONTROL | WB_NODIALOGCONTROL)) == WB_DIALOGCONTROL); | ||||||
4340 | bool bParentIsContainer = bOldSchoolContainer || isContainerWindow(pParent); | ||||||
4341 | |||||||
4342 | bool bForwardKey = false; | ||||||
4343 | bool bGrabFocusToDocument = false; | ||||||
4344 | |||||||
4345 | // #107776# we might be destroyed in the keyhandler | ||||||
4346 | VclPtr<vcl::Window> xWindow = this; | ||||||
4347 | |||||||
4348 | switch ( nCode ) | ||||||
4349 | { | ||||||
4350 | case KEY_UP: | ||||||
4351 | { | ||||||
4352 | // Ctrl-Cursor activates next toolbox, indicated by a blue arrow pointing to the left/up | ||||||
4353 | if( aKeyCode.GetModifier() ) // allow only pure cursor keys | ||||||
4354 | break; | ||||||
4355 | if( !IsHorizontal() ) | ||||||
4356 | ImplChangeHighlightUpDn( true ); | ||||||
4357 | else | ||||||
4358 | ImplOpenItem( aKeyCode ); | ||||||
4359 | } | ||||||
4360 | break; | ||||||
4361 | case KEY_LEFT: | ||||||
4362 | { | ||||||
4363 | if( aKeyCode.GetModifier() ) // allow only pure cursor keys | ||||||
4364 | break; | ||||||
4365 | if( IsHorizontal() ) | ||||||
4366 | ImplChangeHighlightUpDn( true ); | ||||||
4367 | else | ||||||
4368 | ImplOpenItem( aKeyCode ); | ||||||
4369 | } | ||||||
4370 | break; | ||||||
4371 | case KEY_DOWN: | ||||||
4372 | { | ||||||
4373 | if( aKeyCode.GetModifier() ) // allow only pure cursor keys | ||||||
4374 | break; | ||||||
4375 | if( !IsHorizontal() ) | ||||||
4376 | ImplChangeHighlightUpDn( false ); | ||||||
4377 | else | ||||||
4378 | ImplOpenItem( aKeyCode ); | ||||||
4379 | } | ||||||
4380 | break; | ||||||
4381 | case KEY_RIGHT: | ||||||
4382 | { | ||||||
4383 | if( aKeyCode.GetModifier() ) // allow only pure cursor keys | ||||||
4384 | break; | ||||||
4385 | if( IsHorizontal() ) | ||||||
4386 | ImplChangeHighlightUpDn( false ); | ||||||
4387 | else | ||||||
4388 | ImplOpenItem( aKeyCode ); | ||||||
4389 | } | ||||||
4390 | break; | ||||||
4391 | case KEY_PAGEUP: | ||||||
4392 | if ( mnCurLine > 1 ) | ||||||
4393 | { | ||||||
4394 | if( mnCurLine > mnVisLines ) | ||||||
4395 | mnCurLine = mnCurLine - mnVisLines; | ||||||
4396 | else | ||||||
4397 | mnCurLine = 1; | ||||||
4398 | mbFormat = true; | ||||||
4399 | ImplFormat(); | ||||||
4400 | InvalidateSpin(); | ||||||
4401 | ImplChangeHighlight( ImplGetFirstValidItem( mnCurLine ) ); | ||||||
4402 | } | ||||||
4403 | break; | ||||||
4404 | case KEY_PAGEDOWN: | ||||||
4405 | if ( mnCurLine+mnVisLines-1 < mnCurLines ) | ||||||
4406 | { | ||||||
4407 | if( mnCurLine + 2*mnVisLines-1 < mnCurLines ) | ||||||
4408 | mnCurLine = mnCurLine + mnVisLines; | ||||||
4409 | else | ||||||
4410 | mnCurLine = mnCurLines; | ||||||
4411 | mbFormat = true; | ||||||
4412 | ImplFormat(); | ||||||
4413 | InvalidateSpin(); | ||||||
4414 | ImplChangeHighlight( ImplGetFirstValidItem( mnCurLine ) ); | ||||||
4415 | } | ||||||
4416 | break; | ||||||
4417 | case KEY_END: | ||||||
4418 | { | ||||||
4419 | ImplChangeHighlight( nullptr ); | ||||||
4420 | ImplChangeHighlightUpDn( false ); | ||||||
4421 | } | ||||||
4422 | break; | ||||||
4423 | case KEY_HOME: | ||||||
4424 | { | ||||||
4425 | ImplChangeHighlight( nullptr ); | ||||||
4426 | ImplChangeHighlightUpDn( true ); | ||||||
4427 | } | ||||||
4428 | break; | ||||||
4429 | case KEY_ESCAPE: | ||||||
4430 | { | ||||||
4431 | if( !ImplIsFloatingMode() && bParentIsContainer ) | ||||||
4432 | DockingWindow::KeyInput( rKEvt ); | ||||||
4433 | else | ||||||
4434 | { | ||||||
4435 | // send focus to document pane | ||||||
4436 | vcl::Window *pWin = this; | ||||||
4437 | while( pWin ) | ||||||
4438 | { | ||||||
4439 | if( !pWin->GetParent() ) | ||||||
4440 | { | ||||||
4441 | pWin->ImplGetFrameWindow()->GetWindow( GetWindowType::Client )->GrabFocus(); | ||||||
4442 | break; | ||||||
4443 | } | ||||||
4444 | pWin = pWin->GetParent(); | ||||||
4445 | } | ||||||
4446 | } | ||||||
4447 | } | ||||||
4448 | break; | ||||||
4449 | case KEY_RETURN: | ||||||
4450 | { | ||||||
4451 | // #107712#, disabled entries are selectable now | ||||||
4452 | // leave toolbox and move focus to document | ||||||
4453 | if( mnHighItemId ) | ||||||
4454 | { | ||||||
4455 | ImplToolItem *pItem = ImplGetItem(mnHighItemId); | ||||||
4456 | if (!pItem || !pItem->mbEnabled) | ||||||
4457 | { | ||||||
4458 | bGrabFocusToDocument = true; | ||||||
4459 | } | ||||||
4460 | } | ||||||
4461 | if( !bGrabFocusToDocument ) | ||||||
4462 | bForwardKey = !ImplActivateItem( aKeyCode ); | ||||||
4463 | } | ||||||
4464 | break; | ||||||
4465 | case KEY_SPACE: | ||||||
4466 | { | ||||||
4467 | ImplOpenItem( aKeyCode ); | ||||||
4468 | } | ||||||
4469 | break; | ||||||
4470 | default: | ||||||
4471 | { | ||||||
4472 | sal_uInt16 aKeyGroup = aKeyCode.GetGroup(); | ||||||
4473 | ImplToolItem *pItem = nullptr; | ||||||
4474 | if( mnHighItemId ) | ||||||
4475 | pItem = ImplGetItem( mnHighItemId ); | ||||||
4476 | // #i13931# forward alphanum keyinput into embedded control | ||||||
4477 | if( (aKeyGroup == KEYGROUP_NUM || aKeyGroup == KEYGROUP_ALPHA ) && pItem && pItem->mpWindow && pItem->mbEnabled ) | ||||||
4478 | { | ||||||
4479 | vcl::Window *pFocusWindow = Application::GetFocusWindow(); | ||||||
4480 | ImplHideFocus(); | ||||||
4481 | mbChangingHighlight = true; // avoid focus change due to loss of focus | ||||||
4482 | pItem->mpWindow->ImplControlFocus( GetFocusFlags::Tab ); | ||||||
4483 | mbChangingHighlight = false; | ||||||
4484 | if( pFocusWindow != Application::GetFocusWindow() ) | ||||||
4485 | Application::GetFocusWindow()->KeyInput( rKEvt ); | ||||||
4486 | } | ||||||
4487 | else | ||||||
4488 | { | ||||||
4489 | // do nothing to avoid key presses going into the document | ||||||
4490 | // while the toolbox has the focus | ||||||
4491 | // just forward function and special keys and combinations with Alt-key | ||||||
4492 | if( aKeyGroup == KEYGROUP_FKEYS || aKeyGroup == KEYGROUP_MISC || aKeyCode.IsMod2() ) | ||||||
4493 | bForwardKey = true; | ||||||
4494 | } | ||||||
4495 | } | ||||||
4496 | } | ||||||
4497 | |||||||
4498 | if ( xWindow->IsDisposed() ) | ||||||
4499 | return; | ||||||
4500 | |||||||
4501 | // #107251# move focus away if this toolbox was disabled during keyinput | ||||||
4502 | if (HasFocus() && mpData->mbKeyInputDisabled && bParentIsContainer) | ||||||
4503 | { | ||||||
4504 | vcl::Window *pFocusControl = pParent->ImplGetDlgWindow( 0, GetDlgWindowType::First ); | ||||||
4505 | if ( pFocusControl && pFocusControl != this ) | ||||||
4506 | pFocusControl->ImplControlFocus( GetFocusFlags::Init ); | ||||||
4507 | } | ||||||
4508 | |||||||
4509 | // #107712#, leave toolbox | ||||||
4510 | if( bGrabFocusToDocument ) | ||||||
4511 | { | ||||||
4512 | GrabFocusToDocument(); | ||||||
4513 | return; | ||||||
4514 | } | ||||||
4515 | |||||||
4516 | if( bForwardKey ) | ||||||
4517 | DockingWindow::KeyInput( rKEvt ); | ||||||
4518 | } | ||||||
4519 | |||||||
4520 | // returns the current toolbox line of the item | ||||||
4521 | ToolBox::ImplToolItems::size_type ToolBox::ImplGetItemLine( ImplToolItem const * pCurrentItem ) | ||||||
4522 | { | ||||||
4523 | ImplToolItems::size_type nLine = 1; | ||||||
4524 | for (auto const& item : mpData->m_aItems) | ||||||
4525 | { | ||||||
4526 | if ( item.mbBreak ) | ||||||
4527 | ++nLine; | ||||||
4528 | if( &item == pCurrentItem) | ||||||
4529 | break; | ||||||
4530 | } | ||||||
4531 | return nLine; | ||||||
4532 | } | ||||||
4533 | |||||||
4534 | // returns the first displayable item in the given line | ||||||
4535 | ImplToolItem* ToolBox::ImplGetFirstValidItem( ImplToolItems::size_type nLine ) | ||||||
4536 | { | ||||||
4537 | if( !nLine || nLine > mnCurLines ) | ||||||
4538 | return nullptr; | ||||||
4539 | |||||||
4540 | nLine--; | ||||||
4541 | |||||||
4542 | ImplToolItems::iterator it = mpData->m_aItems.begin(); | ||||||
4543 | while( it != mpData->m_aItems.end() ) | ||||||
4544 | { | ||||||
4545 | // find correct line | ||||||
4546 | if ( it->mbBreak ) | ||||||
4547 | nLine--; | ||||||
4548 | if( !nLine ) | ||||||
4549 | { | ||||||
4550 | // find first useful item | ||||||
4551 | while( it != mpData->m_aItems.end() && ((it->meType != ToolBoxItemType::BUTTON) || | ||||||
4552 | /*!it->mbEnabled ||*/ !it->mbVisible || ImplIsFixedControl( &(*it) )) ) | ||||||
4553 | { | ||||||
4554 | ++it; | ||||||
4555 | if( it == mpData->m_aItems.end() || it->mbBreak ) | ||||||
4556 | return nullptr; // no valid items in this line | ||||||
4557 | } | ||||||
4558 | return &(*it); | ||||||
4559 | } | ||||||
4560 | ++it; | ||||||
4561 | } | ||||||
4562 | |||||||
4563 | return (it == mpData->m_aItems.end()) ? nullptr : &(*it); | ||||||
4564 | } | ||||||
4565 | |||||||
4566 | ToolBox::ImplToolItems::size_type ToolBox::ImplFindItemPos( const ImplToolItem* pItem, const ImplToolItems& rList ) | ||||||
4567 | { | ||||||
4568 | if( pItem ) | ||||||
4569 | { | ||||||
4570 | for( ImplToolItems::size_type nPos = 0; nPos < rList.size(); ++nPos ) | ||||||
4571 | if( &rList[ nPos ] == pItem ) | ||||||
4572 | return nPos; | ||||||
4573 | } | ||||||
4574 | return ITEM_NOTFOUND; | ||||||
4575 | } | ||||||
4576 | |||||||
4577 | void ToolBox::ChangeHighlight( ImplToolItems::size_type nPos ) | ||||||
4578 | { | ||||||
4579 | if ( nPos < GetItemCount() ) { | ||||||
4580 | ImplGrabFocus( GetFocusFlags::NONE ); | ||||||
4581 | ImplChangeHighlight ( ImplGetItem ( GetItemId ( nPos ) ) ); | ||||||
4582 | } | ||||||
4583 | } | ||||||
4584 | |||||||
4585 | void ToolBox::ImplChangeHighlight( ImplToolItem const * pItem, bool bNoGrabFocus ) | ||||||
4586 | { | ||||||
4587 | // avoid recursion due to focus change | ||||||
4588 | if( mbChangingHighlight ) | ||||||
4589 | return; | ||||||
4590 | |||||||
4591 | mbChangingHighlight = true; | ||||||
4592 | |||||||
4593 | ImplToolItem* pOldItem = nullptr; | ||||||
4594 | |||||||
4595 | if ( mnHighItemId ) | ||||||
4596 | { | ||||||
4597 | ImplHideFocus(); | ||||||
4598 | ImplToolItems::size_type nPos = GetItemPos( mnHighItemId ); | ||||||
4599 | pOldItem = ImplGetItem( mnHighItemId ); | ||||||
4600 | // #i89962# ImplDrawItem can cause Invalidate/Update | ||||||
4601 | // which will in turn ImplShowFocus again | ||||||
4602 | // set mnHighItemId to 0 already to prevent this hen/egg problem | ||||||
4603 | mnHighItemId = 0; | ||||||
4604 | InvalidateItem(nPos); | ||||||
4605 | CallEventListeners( VclEventId::ToolboxHighlightOff, reinterpret_cast< void* >( nPos ) ); | ||||||
4606 | } | ||||||
4607 | |||||||
4608 | if( !bNoGrabFocus && pItem != pOldItem && pOldItem && pOldItem->mpWindow ) | ||||||
4609 | { | ||||||
4610 | // move focus into toolbox | ||||||
4611 | GrabFocus(); | ||||||
4612 | } | ||||||
4613 | |||||||
4614 | if( pItem ) | ||||||
4615 | { | ||||||
4616 | ImplToolItems::size_type aPos = ToolBox::ImplFindItemPos( pItem, mpData->m_aItems ); | ||||||
4617 | if( aPos != ITEM_NOTFOUND) | ||||||
4618 | { | ||||||
4619 | // check for line breaks | ||||||
4620 | ImplToolItems::size_type nLine = ImplGetItemLine( pItem ); | ||||||
4621 | |||||||
4622 | if( nLine >= mnCurLine + mnVisLines ) | ||||||
4623 | { | ||||||
4624 | mnCurLine = nLine - mnVisLines + 1; | ||||||
4625 | mbFormat = true; | ||||||
4626 | } | ||||||
4627 | else if ( nLine < mnCurLine ) | ||||||
4628 | { | ||||||
4629 | mnCurLine = nLine; | ||||||
4630 | mbFormat = true; | ||||||
4631 | } | ||||||
4632 | |||||||
4633 | if( mbFormat ) | ||||||
4634 | { | ||||||
4635 | ImplFormat(); | ||||||
4636 | } | ||||||
4637 | |||||||
4638 | mnHighItemId = pItem->mnId; | ||||||
4639 | InvalidateItem(aPos); | ||||||
4640 | |||||||
4641 | ImplShowFocus(); | ||||||
4642 | |||||||
4643 | if( pItem->mpWindow ) | ||||||
4644 | pItem->mpWindow->GrabFocus(); | ||||||
4645 | if( pItem != pOldItem ) | ||||||
4646 | CallEventListeners( VclEventId::ToolboxHighlight ); | ||||||
4647 | } | ||||||
4648 | } | ||||||
4649 | else | ||||||
4650 | { | ||||||
4651 | ImplHideFocus(); | ||||||
4652 | mnHighItemId = 0; | ||||||
4653 | mnCurPos = ITEM_NOTFOUND; | ||||||
4654 | } | ||||||
4655 | |||||||
4656 | mbChangingHighlight = false; | ||||||
4657 | } | ||||||
4658 | |||||||
4659 | // check for keyboard accessible items | ||||||
4660 | static bool ImplIsValidItem( const ImplToolItem* pItem, bool bNotClipped ) | ||||||
4661 | { | ||||||
4662 | bool bValid = (pItem && pItem->meType == ToolBoxItemType::BUTTON && pItem->mbVisible && !ImplIsFixedControl( pItem ) | ||||||
4663 | && pItem->mbEnabled); | ||||||
4664 | if( bValid && bNotClipped && pItem->IsClipped() ) | ||||||
4665 | bValid = false; | ||||||
4666 | return bValid; | ||||||
4667 | } | ||||||
4668 | |||||||
4669 | bool ToolBox::ImplChangeHighlightUpDn( bool bUp, bool bNoCycle ) | ||||||
4670 | { | ||||||
4671 | ImplToolItem* pToolItem = ImplGetItem( mnHighItemId ); | ||||||
4672 | |||||||
4673 | if( !pToolItem || !mnHighItemId ) | ||||||
4674 | { | ||||||
4675 | // menubutton highlighted ? | ||||||
4676 | if( mpData->mbMenubuttonSelected ) | ||||||
4677 | { | ||||||
4678 | mpData->mbMenubuttonSelected = false; | ||||||
4679 | if( bUp ) | ||||||
4680 | { | ||||||
4681 | // select last valid non-clipped item | ||||||
4682 | ImplToolItem* pItem = nullptr; | ||||||
4683 | auto it = std::find_if(mpData->m_aItems.rbegin(), mpData->m_aItems.rend(), | ||||||
4684 | [](const ImplToolItem& rItem) { return ImplIsValidItem( &rItem, true ); }); | ||||||
4685 | if( it != mpData->m_aItems.rend() ) | ||||||
4686 | pItem = &(*it); | ||||||
4687 | |||||||
4688 | InvalidateMenuButton(); | ||||||
4689 | ImplChangeHighlight( pItem ); | ||||||
4690 | } | ||||||
4691 | else | ||||||
4692 | { | ||||||
4693 | // select first valid non-clipped item | ||||||
4694 | ImplToolItems::iterator it = std::find_if(mpData->m_aItems.begin(), mpData->m_aItems.end(), | ||||||
4695 | [](const ImplToolItem& rItem) { return ImplIsValidItem( &rItem, true ); }); | ||||||
4696 | if( it != mpData->m_aItems.end() ) | ||||||
4697 | { | ||||||
4698 | InvalidateMenuButton(); | ||||||
4699 | ImplChangeHighlight( &(*it) ); | ||||||
4700 | } | ||||||
4701 | } | ||||||
4702 | return true; | ||||||
4703 | } | ||||||
4704 | |||||||
4705 | if( bUp ) | ||||||
4706 | { | ||||||
4707 | // Select first valid item | ||||||
4708 | ImplToolItems::iterator it = std::find_if(mpData->m_aItems.begin(), mpData->m_aItems.end(), | ||||||
4709 | [](const ImplToolItem& rItem) { return ImplIsValidItem( &rItem, false ); }); | ||||||
4710 | |||||||
4711 | // select the menu button if a clipped item would be selected | ||||||
4712 | if( (it != mpData->m_aItems.end() && &(*it) == ImplGetFirstClippedItem()) && IsMenuEnabled() ) | ||||||
4713 | { | ||||||
4714 | ImplChangeHighlight( nullptr ); | ||||||
4715 | mpData->mbMenubuttonSelected = true; | ||||||
4716 | InvalidateMenuButton(); | ||||||
4717 | } | ||||||
4718 | else | ||||||
4719 | ImplChangeHighlight( (it != mpData->m_aItems.end()) ? &(*it) : nullptr ); | ||||||
4720 | return true; | ||||||
4721 | } | ||||||
4722 | else | ||||||
4723 | { | ||||||
4724 | // Select last valid item | ||||||
4725 | |||||||
4726 | // docked toolbars have the menubutton as last item - if this button is enabled | ||||||
4727 | if( ImplHasClippedItems() && IsMenuEnabled() && !ImplIsFloatingMode() ) | ||||||
4728 | { | ||||||
4729 | ImplChangeHighlight( nullptr ); | ||||||
4730 | mpData->mbMenubuttonSelected = true; | ||||||
4731 | InvalidateMenuButton(); | ||||||
4732 | } | ||||||
4733 | else | ||||||
4734 | { | ||||||
4735 | ImplToolItem* pItem = nullptr; | ||||||
4736 | auto it = std::find_if(mpData->m_aItems.rbegin(), mpData->m_aItems.rend(), | ||||||
4737 | [](const ImplToolItem& rItem) { return ImplIsValidItem( &rItem, false ); }); | ||||||
4738 | if( it != mpData->m_aItems.rend() ) | ||||||
4739 | pItem = &(*it); | ||||||
4740 | |||||||
4741 | ImplChangeHighlight( pItem ); | ||||||
4742 | } | ||||||
4743 | return true; | ||||||
4744 | } | ||||||
4745 | } | ||||||
4746 | |||||||
4747 | assert(pToolItem)(static_cast <bool> (pToolItem) ? void (0) : __assert_fail ("pToolItem", "/home/maarten/src/libreoffice/core/vcl/source/window/toolbox.cxx" , 4747, __extension__ __PRETTY_FUNCTION__)); | ||||||
4748 | |||||||
4749 | ImplToolItems::size_type pos = ToolBox::ImplFindItemPos( pToolItem, mpData->m_aItems ); | ||||||
4750 | ImplToolItems::size_type nCount = mpData->m_aItems.size(); | ||||||
4751 | |||||||
4752 | ImplToolItems::size_type i=0; | ||||||
4753 | do | ||||||
4754 | { | ||||||
4755 | if( bUp ) | ||||||
4756 | { | ||||||
4757 | if( !pos-- ) | ||||||
4758 | { | ||||||
4759 | if( bNoCycle ) | ||||||
4760 | return false; | ||||||
4761 | |||||||
4762 | // highlight the menu button if it is the last item | ||||||
4763 | if( ImplHasClippedItems() && IsMenuEnabled() && !ImplIsFloatingMode() ) | ||||||
4764 | { | ||||||
4765 | ImplChangeHighlight( nullptr ); | ||||||
4766 | mpData->mbMenubuttonSelected = true; | ||||||
4767 | InvalidateMenuButton(); | ||||||
4768 | return true; | ||||||
4769 | } | ||||||
4770 | else | ||||||
4771 | pos = nCount-1; | ||||||
4772 | } | ||||||
4773 | } | ||||||
4774 | else | ||||||
4775 | { | ||||||
4776 | if( ++pos >= nCount ) | ||||||
4777 | { | ||||||
4778 | if( bNoCycle ) | ||||||
4779 | return false; | ||||||
4780 | |||||||
4781 | // highlight the menu button if it is the last item | ||||||
4782 | if( ImplHasClippedItems() && IsMenuEnabled() && !ImplIsFloatingMode() ) | ||||||
4783 | { | ||||||
4784 | ImplChangeHighlight( nullptr ); | ||||||
4785 | mpData->mbMenubuttonSelected = true; | ||||||
4786 | InvalidateMenuButton(); | ||||||
4787 | return true; | ||||||
4788 | } | ||||||
4789 | else | ||||||
4790 | pos = 0; | ||||||
4791 | } | ||||||
4792 | } | ||||||
4793 | |||||||
4794 | pToolItem = &mpData->m_aItems[pos]; | ||||||
4795 | |||||||
4796 | if ( ImplIsValidItem( pToolItem, false ) ) | ||||||
4797 | break; | ||||||
4798 | |||||||
4799 | } while( ++i < nCount); | ||||||
4800 | |||||||
4801 | if( pToolItem->IsClipped() && IsMenuEnabled() ) | ||||||
4802 | { | ||||||
4803 | // select the menu button if a clipped item would be selected | ||||||
4804 | ImplChangeHighlight( nullptr ); | ||||||
4805 | mpData->mbMenubuttonSelected = true; | ||||||
4806 | InvalidateMenuButton(); | ||||||
4807 | } | ||||||
4808 | else if( i != nCount ) | ||||||
4809 | ImplChangeHighlight( pToolItem ); | ||||||
4810 | else | ||||||
4811 | return false; | ||||||
4812 | |||||||
4813 | return true; | ||||||
4814 | } | ||||||
4815 | |||||||
4816 | void ToolBox::ImplShowFocus() | ||||||
4817 | { | ||||||
4818 | if( mnHighItemId && HasFocus() ) | ||||||
4819 | { | ||||||
4820 | ImplToolItem* pItem = ImplGetItem( mnHighItemId ); | ||||||
4821 | if (pItem && pItem->mpWindow && !pItem->mpWindow->IsDisposed()) | ||||||
4822 | { | ||||||
4823 | vcl::Window *pWin = pItem->mpWindow->ImplGetWindowImpl()->mpBorderWindow ? pItem->mpWindow->ImplGetWindowImpl()->mpBorderWindow.get() : pItem->mpWindow.get(); | ||||||
4824 | pWin->ImplGetWindowImpl()->mbDrawSelectionBackground = true; | ||||||
4825 | pWin->Invalidate(); | ||||||
4826 | } | ||||||
4827 | } | ||||||
4828 | } | ||||||
4829 | |||||||
4830 | void ToolBox::ImplHideFocus() | ||||||
4831 | { | ||||||
4832 | if( mnHighItemId ) | ||||||
4833 | { | ||||||
4834 | mpData->mbMenubuttonWasLastSelected = false; | ||||||
4835 | ImplToolItem* pItem = ImplGetItem( mnHighItemId ); | ||||||
4836 | if( pItem && pItem->mpWindow ) | ||||||
4837 | { | ||||||
4838 | vcl::Window *pWin = pItem->mpWindow->ImplGetWindowImpl()->mpBorderWindow ? pItem->mpWindow->ImplGetWindowImpl()->mpBorderWindow.get() : pItem->mpWindow.get(); | ||||||
4839 | pWin->ImplGetWindowImpl()->mbDrawSelectionBackground = false; | ||||||
4840 | pWin->Invalidate(); | ||||||
4841 | } | ||||||
4842 | } | ||||||
4843 | |||||||
4844 | if ( mpData && mpData->mbMenubuttonSelected ) | ||||||
4845 | { | ||||||
4846 | mpData->mbMenubuttonWasLastSelected = true; | ||||||
4847 | // remove highlight from menubutton | ||||||
4848 | mpData->mbMenubuttonSelected = false; | ||||||
4849 | InvalidateMenuButton(); | ||||||
4850 | } | ||||||
4851 | } | ||||||
4852 | |||||||
4853 | void ToolBox::ImplDisableFlatButtons() | ||||||
4854 | { | ||||||
4855 | #ifdef _WIN32 // Check in the Windows registry if an AT tool wants no flat toolboxes | ||||||
4856 | static bool bInit = false, bValue = false; | ||||||
4857 | if( ! bInit ) | ||||||
4858 | { | ||||||
4859 | bInit = true; | ||||||
4860 | HKEY hkey; | ||||||
4861 | |||||||
4862 | if( ERROR_SUCCESS == RegOpenKeyW(HKEY_CURRENT_USER, L"Software\\LibreOffice\\Accessibility\\AtToolSupport", &hkey) ) | ||||||
4863 | { | ||||||
4864 | DWORD dwType = 0; | ||||||
4865 | wchar_t Data[6]; // possible values: "true", "false", "1", "0", DWORD | ||||||
4866 | DWORD cbData = sizeof(Data); | ||||||
4867 | |||||||
4868 | if( ERROR_SUCCESS == RegQueryValueExW(hkey, L"DisableFlatToolboxButtons", | ||||||
4869 | nullptr, &dwType, reinterpret_cast<LPBYTE>(Data), &cbData) ) | ||||||
4870 | { | ||||||
4871 | switch (dwType) | ||||||
4872 | { | ||||||
4873 | case REG_SZ: | ||||||
4874 | bValue = ((0 == wcsicmp(Data, L"1")) || (0 == wcsicmp(Data, L"true"))); | ||||||
4875 | break; | ||||||
4876 | case REG_DWORD: | ||||||
4877 | bValue = static_cast<bool>(reinterpret_cast<DWORD *>(Data)[0]); | ||||||
4878 | break; | ||||||
4879 | } | ||||||
4880 | } | ||||||
4881 | RegCloseKey(hkey); | ||||||
4882 | } | ||||||
4883 | } | ||||||
4884 | if( bValue ) | ||||||
4885 | mnOutStyle &= ~TOOLBOX_STYLE_FLAT; | ||||||
4886 | #else | ||||||
4887 | (void) this; // loplugin:staticmethods | ||||||
4888 | #endif | ||||||
4889 | } | ||||||
4890 | |||||||
4891 | void ToolBox::SetToolbarLayoutMode( ToolBoxLayoutMode eLayout ) | ||||||
4892 | { | ||||||
4893 | if ( meLayoutMode != eLayout ) | ||||||
4894 | meLayoutMode = eLayout; | ||||||
4895 | } | ||||||
4896 | |||||||
4897 | void ToolBox::SetToolBoxTextPosition( ToolBoxTextPosition ePosition ) | ||||||
4898 | { | ||||||
4899 | meTextPosition = ePosition; | ||||||
4900 | } | ||||||
4901 | |||||||
4902 | /* 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 |