Bug Summary

File:home/maarten/src/libreoffice/core/framework/source/layoutmanager/toolbarlayoutmanager.cxx
Warning:line 1680, column 5
Use of memory after it is freed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name toolbarlayoutmanager.cxx -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -D BOOST_ERROR_CODE_HEADER_ONLY -D BOOST_SYSTEM_NO_DEPRECATED -D CPPU_ENV=gcc3 -D LINUX -D OSL_DEBUG_LEVEL=1 -D SAL_LOG_INFO -D SAL_LOG_WARN -D UNIX -D UNX -D X86_64 -D _PTHREADS -D _REENTRANT -D FWK_DLLIMPLEMENTATION -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/framework/source/inc -I /home/maarten/src/libreoffice/core/framework/inc -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/officecfg/registry -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/officecfg/registry -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-missing-braces -std=c++17 -fdeprecated-macro -fdebug-compilation-dir /home/maarten/src/libreoffice/core -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -debug-info-kind=constructor -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c++ /home/maarten/src/libreoffice/core/framework/source/layoutmanager/toolbarlayoutmanager.cxx

/home/maarten/src/libreoffice/core/framework/source/layoutmanager/toolbarlayoutmanager.cxx

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 "toolbarlayoutmanager.hxx"
21#include <uiconfiguration/windowstateproperties.hxx>
22#include <uielement/addonstoolbarwrapper.hxx>
23#include "helpers.hxx"
24#include <services/layoutmanager.hxx>
25#include <strings.hrc>
26#include <classes/fwkresid.hxx>
27
28#include <com/sun/star/awt/PosSize.hpp>
29#include <com/sun/star/beans/XPropertySet.hpp>
30#include <com/sun/star/ui/UIElementType.hpp>
31#include <com/sun/star/container/XNameReplace.hpp>
32#include <com/sun/star/container/XNameContainer.hpp>
33#include <com/sun/star/ui/XUIElementSettings.hpp>
34#include <com/sun/star/ui/XUIFunctionListener.hpp>
35
36#include <cppuhelper/queryinterface.hxx>
37#include <unotools/cmdoptions.hxx>
38#include <toolkit/helper/vclunohelper.hxx>
39#include <toolkit/helper/convert.hxx>
40#include <vcl/i18nhelp.hxx>
41#include <vcl/dockingarea.hxx>
42#include <vcl/settings.hxx>
43#include <vcl/svapp.hxx>
44#include <sal/log.hxx>
45#include <tools/gen.hxx>
46
47
48using namespace ::com::sun::star;
49
50namespace framework
51{
52
53ToolbarLayoutManager::ToolbarLayoutManager(
54 const uno::Reference< uno::XComponentContext >& rxContext,
55 const uno::Reference< ui::XUIElementFactory >& xUIElementFactory,
56 LayoutManager* pParentLayouter ):
57 m_xContext( rxContext),
58 m_xUIElementFactoryManager( xUIElementFactory ),
59 m_pParentLayouter( pParentLayouter ),
60 m_eDockOperation( DOCKOP_ON_COLROW ),
61 m_ePreviewDetection( PREVIEWFRAME_UNKNOWN ),
62 m_bComponentAttached( false ),
63 m_bLayoutDirty( false ),
64 m_bGlobalSettings( false ),
65 m_bDockingInProgress( false ),
66 m_bLayoutInProgress( false ),
67 m_bToolbarCreation( false )
68{
69 // initialize rectangles to zero values
70 setZeroRectangle( m_aDockingAreaOffsets );
71 setZeroRectangle( m_aDockingArea );
72}
73
74ToolbarLayoutManager::~ToolbarLayoutManager()
75{
76 m_pGlobalSettings.reset();
77 m_pAddonOptions.reset();
78}
79
80// XInterface
81
82void SAL_CALL ToolbarLayoutManager::acquire() throw()
83{
84 OWeakObject::acquire();
85}
86
87void SAL_CALL ToolbarLayoutManager::release() throw()
88{
89 OWeakObject::release();
90}
91
92uno::Any SAL_CALL ToolbarLayoutManager::queryInterface( const uno::Type & rType )
93{
94 uno::Any a = ::cppu::queryInterface( rType,
95 static_cast< awt::XDockableWindowListener* >(this),
96 static_cast< ui::XUIConfigurationListener* >(this),
97 static_cast< awt::XWindowListener* >(this));
98
99 if ( a.hasValue() )
100 return a;
101
102 return OWeakObject::queryInterface( rType );
103}
104
105void SAL_CALL ToolbarLayoutManager::disposing( const lang::EventObject& aEvent )
106{
107 if ( aEvent.Source == m_xFrame )
108 {
109 // Reset all internal references
110 reset();
111 implts_destroyDockingAreaWindows();
112 }
113}
114
115awt::Rectangle ToolbarLayoutManager::getDockingArea()
116{
117 SolarMutexResettableGuard aWriteLock;
118 tools::Rectangle aNewDockingArea( m_aDockingArea );
119 aWriteLock.clear();
120
121 if ( isLayoutDirty() )
122 aNewDockingArea = implts_calcDockingArea();
123
124 aWriteLock.reset();
125 m_aDockingArea = aNewDockingArea;
126 aWriteLock.clear();
127
128 return putRectangleValueToAWT(aNewDockingArea);
129}
130
131void ToolbarLayoutManager::setDockingArea( const awt::Rectangle& rDockingArea )
132{
133 SolarMutexGuard g;
134 m_aDockingArea = putAWTToRectangle( rDockingArea );
135 m_bLayoutDirty = true;
136}
137
138void ToolbarLayoutManager::implts_setDockingAreaWindowSizes( const awt::Rectangle& rBorderSpace )
139{
140 SolarMutexClearableGuard aReadLock;
141 tools::Rectangle aDockOffsets = m_aDockingAreaOffsets;
142 uno::Reference< awt::XWindow2 > xContainerWindow( m_xContainerWindow );
143 uno::Reference< awt::XWindow > xTopDockAreaWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_TOP)] );
144 uno::Reference< awt::XWindow > xBottomDockAreaWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_BOTTOM)] );
145 uno::Reference< awt::XWindow > xLeftDockAreaWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_LEFT)] );
146 uno::Reference< awt::XWindow > xRightDockAreaWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_RIGHT)] );
147 aReadLock.clear();
148
149 uno::Reference< awt::XDevice > xDevice( xContainerWindow, uno::UNO_QUERY );
150
151 // Convert relative size to output size.
152 awt::Rectangle aRectangle = xContainerWindow->getPosSize();
153 awt::DeviceInfo aInfo = xDevice->getInfo();
154 awt::Size aContainerClientSize( aRectangle.Width - aInfo.LeftInset - aInfo.RightInset ,
155 aRectangle.Height - aInfo.TopInset - aInfo.BottomInset );
156 long aStatusBarHeight = aDockOffsets.GetHeight();
157
158 sal_Int32 nLeftRightDockingAreaHeight( aContainerClientSize.Height );
159 if ( rBorderSpace.Y >= 0 )
160 {
161 // Top docking area window
162 xTopDockAreaWindow->setPosSize( 0, 0, aContainerClientSize.Width, rBorderSpace.Y, awt::PosSize::POSSIZE );
163 xTopDockAreaWindow->setVisible( true );
164 nLeftRightDockingAreaHeight -= rBorderSpace.Y;
165 }
166
167 if ( rBorderSpace.Height >= 0 )
168 {
169 // Bottom docking area window
170 sal_Int32 nBottomPos = std::max( sal_Int32( aContainerClientSize.Height - rBorderSpace.Height - aStatusBarHeight + 1 ), sal_Int32( 0 ));
171 sal_Int32 nHeight = ( nBottomPos == 0 ) ? 0 : rBorderSpace.Height;
172
173 xBottomDockAreaWindow->setPosSize( 0, nBottomPos, aContainerClientSize.Width, nHeight, awt::PosSize::POSSIZE );
174 xBottomDockAreaWindow->setVisible( true );
175 nLeftRightDockingAreaHeight -= nHeight - 1;
176 }
177
178 nLeftRightDockingAreaHeight -= aStatusBarHeight;
179 if ( rBorderSpace.X >= 0 || nLeftRightDockingAreaHeight > 0 )
180 {
181 // Left docking area window
182 // We also have to change our right docking area window if the top or bottom area has changed. They have a higher priority!
183 sal_Int32 nHeight = std::max<sal_Int32>( 0, nLeftRightDockingAreaHeight );
184
185 xLeftDockAreaWindow->setPosSize( 0, rBorderSpace.Y, rBorderSpace.X, nHeight, awt::PosSize::POSSIZE );
186 xLeftDockAreaWindow->setVisible( true );
187 }
188 if ( rBorderSpace.Width >= 0 || nLeftRightDockingAreaHeight > 0 )
189 {
190 // Right docking area window
191 // We also have to change our right docking area window if the top or bottom area has changed. They have a higher priority!
192 sal_Int32 nLeftPos = std::max<sal_Int32>( 0, aContainerClientSize.Width - rBorderSpace.Width );
193 sal_Int32 nHeight = std::max<sal_Int32>( 0, nLeftRightDockingAreaHeight );
194 sal_Int32 nWidth = ( nLeftPos == 0 ) ? 0 : rBorderSpace.Width;
195
196 xRightDockAreaWindow->setPosSize( nLeftPos, rBorderSpace.Y, nWidth, nHeight, awt::PosSize::POSSIZE );
197 xRightDockAreaWindow->setVisible( true );
198 }
199}
200
201
202void ToolbarLayoutManager::doLayout(const ::Size& aContainerSize)
203{
204 SolarMutexResettableGuard aWriteLock;
205 bool bLayoutInProgress( m_bLayoutInProgress );
206 m_bLayoutInProgress = true;
207 awt::Rectangle aDockingArea = putRectangleValueToAWT( m_aDockingArea );
208 aWriteLock.clear();
209
210 if ( bLayoutInProgress )
211 return;
212
213 // Retrieve row/column dependent data from all docked user-interface elements
214 for ( sal_Int32 i = 0; i < DOCKINGAREAS_COUNT; i++ )
215 {
216 bool bReverse( isReverseOrderDockingArea( i ));
217 std::vector< SingleRowColumnWindowData > aRowColumnsWindowData;
218
219 implts_getDockingAreaElementInfos( static_cast<ui::DockingArea>(i), aRowColumnsWindowData );
220
221 sal_Int32 nOffset( 0 );
222 const sal_uInt32 nCount = aRowColumnsWindowData.size();
223 for ( sal_uInt32 j = 0; j < nCount; ++j )
224 {
225 sal_uInt32 nIndex = bReverse ? nCount-j-1 : j;
226 implts_calcWindowPosSizeOnSingleRowColumn( i, nOffset, aRowColumnsWindowData[nIndex], aContainerSize );
227 nOffset += aRowColumnsWindowData[j].nStaticSize;
228 }
229 }
230
231 implts_setDockingAreaWindowSizes( aDockingArea );
232
233 aWriteLock.reset();
234 m_bLayoutDirty = false;
235 m_bLayoutInProgress = false;
236 aWriteLock.clear();
237}
238
239bool ToolbarLayoutManager::implts_isParentWindowVisible() const
240{
241 SolarMutexGuard g;
242 bool bVisible( false );
243 if ( m_xContainerWindow.is() )
244 bVisible = m_xContainerWindow->isVisible();
245
246 return bVisible;
247}
248
249tools::Rectangle ToolbarLayoutManager::implts_calcDockingArea()
250{
251 SolarMutexClearableGuard aReadLock;
252 UIElementVector aWindowVector( m_aUIElements );
253 aReadLock.clear();
254
255 tools::Rectangle aBorderSpace;
256 sal_Int32 nCurrRowColumn( 0 );
257 sal_Int32 nCurrPos( 0 );
258 ui::DockingArea nCurrDockingArea( ui::DockingArea_DOCKINGAREA_TOP );
259 std::vector< sal_Int32 > aRowColumnSizes[DOCKINGAREAS_COUNT];
260
261 // initialize rectangle with zero values!
262 aBorderSpace.setWidth(0);
263 aBorderSpace.setHeight(0);
264
265 aRowColumnSizes[static_cast<int>(nCurrDockingArea)].clear();
266 aRowColumnSizes[static_cast<int>(nCurrDockingArea)].push_back( 0 );
267
268 for (auto const& window : aWindowVector)
269 {
270 if ( window.m_xUIElement.is() )
271 {
272 uno::Reference< awt::XWindow > xWindow( window.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
273 uno::Reference< awt::XDockableWindow > xDockWindow( xWindow, uno::UNO_QUERY );
274 if ( xWindow.is() && xDockWindow.is() )
275 {
276 SolarMutexGuard aGuard;
277
278 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
279 if ( pWindow && !xDockWindow->isFloating() && window.m_bVisible && !window.m_bMasterHide )
280 {
281 awt::Rectangle aPosSize = xWindow->getPosSize();
282 if ( window.m_aDockedData.m_nDockedArea != nCurrDockingArea )
283 {
284 nCurrDockingArea = window.m_aDockedData.m_nDockedArea;
285 nCurrRowColumn = 0;
286 nCurrPos = 0;
287 aRowColumnSizes[static_cast<int>(nCurrDockingArea)].clear();
288 aRowColumnSizes[static_cast<int>(nCurrDockingArea)].push_back( 0 );
289 }
290
291 if ( window.m_aDockedData.m_nDockedArea == nCurrDockingArea )
292 {
293 if ( isHorizontalDockingArea( window.m_aDockedData.m_nDockedArea ))
294 {
295 if ( window.m_aDockedData.m_aPos.Y > nCurrPos )
296 {
297 ++nCurrRowColumn;
298 nCurrPos = window.m_aDockedData.m_aPos.Y;
299 aRowColumnSizes[static_cast<int>(nCurrDockingArea)].push_back( 0 );
300 }
301
302 if ( aPosSize.Height > aRowColumnSizes[static_cast<int>(nCurrDockingArea)][nCurrRowColumn] )
303 aRowColumnSizes[static_cast<int>(nCurrDockingArea)][nCurrRowColumn] = aPosSize.Height;
304 }
305 else
306 {
307 if ( window.m_aDockedData.m_aPos.X > nCurrPos )
308 {
309 ++nCurrRowColumn;
310 nCurrPos = window.m_aDockedData.m_aPos.X;
311 aRowColumnSizes[static_cast<int>(nCurrDockingArea)].push_back( 0 );
312 }
313
314 if ( aPosSize.Width > aRowColumnSizes[static_cast<int>(nCurrDockingArea)][nCurrRowColumn] )
315 aRowColumnSizes[static_cast<int>(nCurrDockingArea)][nCurrRowColumn] = aPosSize.Width;
316 }
317 }
318 }
319 }
320 }
321 }
322
323 // Sum up max heights from every row/column
324 if ( !aWindowVector.empty() )
325 {
326 for ( sal_Int32 i = 0; i <= sal_Int32(ui::DockingArea_DOCKINGAREA_RIGHT); i++ )
327 {
328 sal_Int32 nSize( 0 );
329 const sal_uInt32 nCount = aRowColumnSizes[i].size();
330 for ( sal_uInt32 j = 0; j < nCount; j++ )
331 nSize += aRowColumnSizes[i][j];
332
333 if ( i == sal_Int32(ui::DockingArea_DOCKINGAREA_TOP) )
334 aBorderSpace.SetTop( nSize );
335 else if ( i == sal_Int32(ui::DockingArea_DOCKINGAREA_BOTTOM) )
336 aBorderSpace.SetBottom( nSize );
337 else if ( i == sal_Int32(ui::DockingArea_DOCKINGAREA_LEFT) )
338 aBorderSpace.SetLeft( nSize );
339 else
340 aBorderSpace.SetRight( nSize );
341 }
342 }
343
344 return aBorderSpace;
345}
346
347void ToolbarLayoutManager::reset()
348{
349 {
350 SolarMutexGuard aWriteLock;
351 m_xModuleCfgMgr.clear();
352 m_xDocCfgMgr.clear();
353 m_ePreviewDetection = PREVIEWFRAME_UNKNOWN;
354 m_bComponentAttached = false;
355 }
356
357 destroyToolbars();
358 resetDockingArea();
359}
360
361void ToolbarLayoutManager::attach(
362 const uno::Reference< frame::XFrame >& xFrame,
363 const uno::Reference< ui::XUIConfigurationManager >& xModuleCfgMgr,
364 const uno::Reference< ui::XUIConfigurationManager >& xDocCfgMgr,
365 const uno::Reference< container::XNameAccess >& xPersistentWindowState )
366{
367 // reset toolbar manager if we lose our current frame
368 if ( m_xFrame.is() && m_xFrame != xFrame )
369 reset();
370
371 SolarMutexGuard g;
372 m_xFrame = xFrame;
373 m_xModuleCfgMgr = xModuleCfgMgr;
374 m_xDocCfgMgr = xDocCfgMgr;
375 m_xPersistentWindowState = xPersistentWindowState;
376 m_bComponentAttached = true;
377}
378
379bool ToolbarLayoutManager::isPreviewFrame()
380{
381 SolarMutexGuard g;
382 if (m_ePreviewDetection == PREVIEWFRAME_UNKNOWN)
383 {
384 uno::Reference< frame::XFrame > xFrame( m_xFrame );
385
386 uno::Reference< frame::XModel > xModel( impl_getModelFromFrame( xFrame ));
387
388 m_ePreviewDetection = (implts_isPreviewModel( xModel ) ? PREVIEWFRAME_YES : PREVIEWFRAME_NO);
389 }
390 return m_ePreviewDetection == PREVIEWFRAME_YES;
391}
392
393void ToolbarLayoutManager::createStaticToolbars()
394{
395 resetDockingArea();
396 implts_createCustomToolBars();
397 implts_createAddonsToolBars();
398 implts_createNonContextSensitiveToolBars();
399 implts_sortUIElements();
400}
401
402bool ToolbarLayoutManager::requestToolbar( const OUString& rResourceURL )
403{
404 if (isPreviewFrame())
405 return false; // no toolbars for preview frame!
406
407 bool bNotify( false );
408 bool bMustCallCreate( false );
409 uno::Reference< ui::XUIElement > xUIElement;
410
411 UIElement aRequestedToolbar = impl_findToolbar( rResourceURL );
412 if ( aRequestedToolbar.m_aName != rResourceURL )
413 {
414 bMustCallCreate = true;
415 aRequestedToolbar.m_aName = rResourceURL;
416 aRequestedToolbar.m_aType = UIRESOURCETYPE_TOOLBAR"toolbar";
417 aRequestedToolbar.m_xUIElement = xUIElement;
418 implts_readWindowStateData( rResourceURL, aRequestedToolbar );
419 }
420
421 xUIElement = aRequestedToolbar.m_xUIElement;
422 if ( !xUIElement.is() )
423 bMustCallCreate = true;
424
425 bool bCreateOrShowToolbar( aRequestedToolbar.m_bVisible && !aRequestedToolbar.m_bMasterHide );
426
427 if ( bCreateOrShowToolbar )
428 bNotify = bMustCallCreate ? createToolbar( rResourceURL ) : showToolbar( rResourceURL );
429
430 return bNotify;
431}
432
433bool ToolbarLayoutManager::createToolbar( const OUString& rResourceURL )
434{
435 bool bNotify( false );
436
437 uno::Reference<frame::XFrame> xFrame;
438 uno::Reference<awt::XWindow2> xContainerWindow;
439 {
440 SolarMutexGuard aReadLock;
441 xFrame.set(m_xFrame);
442 xContainerWindow.set(m_xContainerWindow);
443 }
444
445 if ( !xFrame.is() || !xContainerWindow.is() )
446 return false;
447
448 UIElement aToolbarElement = implts_findToolbar( rResourceURL );
449 if ( !aToolbarElement.m_xUIElement.is() )
450 {
451 uno::Reference< ui::XUIElement > xUIElement;
452
453 uno::Sequence< beans::PropertyValue > aPropSeq( 2 );
454 aPropSeq[0].Name = "Frame";
455 aPropSeq[0].Value <<= xFrame;
456 aPropSeq[1].Name = "Persistent";
457 aPropSeq[1].Value <<= true;
458 uno::Reference<ui::XUIElementFactory> xUIElementFactory;
459 {
460 SolarMutexGuard aReadLock;
461 xUIElementFactory.set(m_xUIElementFactoryManager);
462 }
463
464 implts_setToolbarCreation();
465 try
466 {
467 if ( xUIElementFactory.is() )
468 xUIElement = xUIElementFactory->createUIElement( rResourceURL, aPropSeq );
469 }
470 catch (const container::NoSuchElementException&)
471 {
472 }
473 catch (const lang::IllegalArgumentException&)
474 {
475 }
476 implts_setToolbarCreation( false );
477
478 if ( xUIElement.is() )
479 {
480 uno::Reference< awt::XWindow > xWindow( xUIElement->getRealInterface(), uno::UNO_QUERY );
481 uno::Reference< awt::XDockableWindow > xDockWindow( xWindow, uno::UNO_QUERY );
482 if ( xDockWindow.is() && xWindow.is() )
483 {
484 try
485 {
486 xDockWindow->addDockableWindowListener( uno::Reference< awt::XDockableWindowListener >(
487 static_cast< OWeakObject * >( this ), uno::UNO_QUERY ));
488 xWindow->addWindowListener( uno::Reference< awt::XWindowListener >(
489 static_cast< OWeakObject * >( this ), uno::UNO_QUERY ));
490 xDockWindow->enableDocking( true );
491 }
492 catch (const uno::Exception&)
493 {
494 }
495 }
496
497 bool bVisible = false;
498 bool bFloating = false;
499
500 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
501 {
502 SolarMutexClearableGuard aWriteLock;
503
504 UIElement& rElement = impl_findToolbar(rResourceURL);
505 if (rElement.m_xUIElement.is())
506 {
507 // somebody else must have created it while we released
508 // the SolarMutex - just dispose our new instance and
509 // do nothing. (We have to dispose either the new or the
510 // existing m_xUIElement.)
511 aWriteLock.clear();
512 uno::Reference<lang::XComponent> const xC(xUIElement, uno::UNO_QUERY);
513 xC->dispose();
514 return false;
515 }
516 if (!rElement.m_aName.isEmpty())
517 {
518 // Reuse a local entry so we are able to use the latest
519 // UI changes for this document.
520 implts_setElementData(rElement, xDockWindow);
521 rElement.m_xUIElement = xUIElement;
522 bVisible = rElement.m_bVisible;
523 bFloating = rElement.m_bFloating;
524 }
525 else
526 {
527 // Create new UI element and try to read its state data
528 UIElement aNewToolbar(rResourceURL, UIRESOURCETYPE_TOOLBAR"toolbar", xUIElement);
529 implts_readWindowStateData(rResourceURL, aNewToolbar);
530 implts_setElementData(aNewToolbar, xDockWindow);
531 implts_insertToolbar(aNewToolbar);
532 bVisible = aNewToolbar.m_bVisible;
533 bFloating = rElement.m_bFloating;
534 }
535 }
536 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
537
538 // set toolbar menu style according to customize command state
539 SvtCommandOptions aCmdOptions;
540
541 SolarMutexGuard aGuard;
542 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
543 if ( pWindow && pWindow->GetType() == WindowType::TOOLBOX )
544 {
545 ToolBox* pToolbar = static_cast<ToolBox *>(pWindow.get());
546 ToolBoxMenuType nMenuType = pToolbar->GetMenuType();
547 if ( aCmdOptions.Lookup( SvtCommandOptions::CMDOPTION_DISABLED, "ConfigureDialog" ))
548 pToolbar->SetMenuType( nMenuType & ~ToolBoxMenuType::Customize );
549 else
550 pToolbar->SetMenuType( nMenuType | ToolBoxMenuType::Customize );
551 }
552 bNotify = true;
553
554 implts_sortUIElements();
555
556 if ( bVisible && !bFloating )
557 implts_setLayoutDirty();
558 }
559 }
560
561 return bNotify;
562}
563
564bool ToolbarLayoutManager::destroyToolbar( const OUString& rResourceURL )
565{
566 uno::Reference< lang::XComponent > xComponent;
567
568 bool bNotify( false );
569 bool bMustBeSorted( false );
570 bool bMustLayouted( false );
571 bool bMustBeDestroyed( !rResourceURL.startsWith("private:resource/toolbar/addon_") );
572
573 {
574 SolarMutexGuard aWriteLock;
575 for (auto & elem : m_aUIElements)
576 {
577 if (elem.m_aName == rResourceURL)
578 {
579 xComponent.set(elem.m_xUIElement, uno::UNO_QUERY);
580 if (bMustBeDestroyed)
581 elem.m_xUIElement.clear();
582 else
583 elem.m_bVisible = false;
584 break;
585 }
586 }
587 }
588
589 uno::Reference< ui::XUIElement > xUIElement( xComponent, uno::UNO_QUERY );
590 if ( xUIElement.is() )
591 {
592 uno::Reference< awt::XWindow > xWindow( xUIElement->getRealInterface(), uno::UNO_QUERY );
593 uno::Reference< awt::XDockableWindow > xDockWindow( xWindow, uno::UNO_QUERY );
594
595 if ( bMustBeDestroyed )
596 {
597 try
598 {
599 if ( xWindow.is() )
600 xWindow->removeWindowListener( uno::Reference< awt::XWindowListener >(
601 static_cast< OWeakObject * >( this ), uno::UNO_QUERY ));
602 }
603 catch (const uno::Exception&)
604 {
605 }
606
607 try
608 {
609 if ( xDockWindow.is() )
610 xDockWindow->removeDockableWindowListener( uno::Reference< awt::XDockableWindowListener >(
611 static_cast< OWeakObject * >( this ), uno::UNO_QUERY ));
612 }
613 catch (const uno::Exception&)
614 {
615 }
616 }
617 else
618 {
619 if ( xWindow.is() )
620 xWindow->setVisible( false );
621 bNotify = true;
622 }
623
624 if ( !xDockWindow->isFloating() )
625 bMustLayouted = true;
626 bMustBeSorted = true;
627 }
628
629 if ( bMustBeDestroyed )
630 {
631 if ( xComponent.is() )
632 xComponent->dispose();
633 bNotify = true;
634 }
635
636 if ( bMustLayouted )
637 implts_setLayoutDirty();
638
639 if ( bMustBeSorted )
640 implts_sortUIElements();
641
642 return bNotify;
643}
644
645void ToolbarLayoutManager::destroyToolbars()
646{
647 UIElementVector aUIElementVector;
648 implts_getUIElementVectorCopy( aUIElementVector );
649
650 {
651 SolarMutexGuard aWriteLock;
652 m_aUIElements.clear();
653 m_bLayoutDirty = true;
654 }
655
656 for (auto const& elem : aUIElementVector)
657 {
658 uno::Reference< lang::XComponent > xComponent( elem.m_xUIElement, uno::UNO_QUERY );
659 if ( xComponent.is() )
660 xComponent->dispose();
661 }
662}
663
664bool ToolbarLayoutManager::showToolbar( const OUString& rResourceURL )
665{
666 UIElement aUIElement = implts_findToolbar( rResourceURL );
667
668 SolarMutexGuard aGuard;
669 vcl::Window* pWindow = getWindowFromXUIElement( aUIElement.m_xUIElement );
670
671 // Addons appear to need to be populated at start, but we don't
672 // want to populate them with (scaled) images until later.
673 AddonsToolBarWrapper *pAddOns;
674 pAddOns = dynamic_cast<AddonsToolBarWrapper *>( aUIElement.m_xUIElement.get());
675 if (pAddOns)
676 pAddOns->populateImages();
677
678 if ( pWindow )
679 {
680 if ( !aUIElement.m_bFloating )
681 implts_setLayoutDirty();
682 else
683 pWindow->Show( true, ShowFlags::NoFocusChange | ShowFlags::NoActivate );
684
685 aUIElement.m_bVisible = true;
686 implts_writeWindowStateData( aUIElement );
687 implts_setToolbar( aUIElement );
688 implts_sortUIElements();
689 return true;
690 }
691
692 return false;
693}
694
695bool ToolbarLayoutManager::hideToolbar( const OUString& rResourceURL )
696{
697 UIElement aUIElement = implts_findToolbar( rResourceURL );
698
699 SolarMutexGuard aGuard;
700 vcl::Window* pWindow = getWindowFromXUIElement( aUIElement.m_xUIElement );
701 if ( pWindow )
702 {
703 pWindow->Show( false );
704 if ( !aUIElement.m_bFloating )
705 implts_setLayoutDirty();
706
707 aUIElement.m_bVisible = false;
708 implts_writeWindowStateData( aUIElement );
709 implts_setToolbar( aUIElement );
710 return true;
711 }
712
713 return false;
714}
715
716void ToolbarLayoutManager::refreshToolbarsVisibility( bool bAutomaticToolbars )
717{
718 UIElementVector aUIElementVector;
719
720 if ( !bAutomaticToolbars )
721 return;
722
723 implts_getUIElementVectorCopy( aUIElementVector );
724
725 UIElement aUIElement;
726 SolarMutexGuard aGuard;
727 for (auto const& elem : aUIElementVector)
728 {
729 if ( implts_readWindowStateData( elem.m_aName, aUIElement ) &&
730 ( elem.m_bVisible != aUIElement.m_bVisible ) && !elem.m_bMasterHide )
731 {
732 SolarMutexGuard g;
733 UIElement& rUIElement = impl_findToolbar( elem.m_aName );
734 if ( rUIElement.m_aName == elem.m_aName )
735 {
736 rUIElement.m_bVisible = aUIElement.m_bVisible;
737 implts_setLayoutDirty();
738 }
739 }
740 }
741}
742
743void ToolbarLayoutManager::setFloatingToolbarsVisibility( bool bVisible )
744{
745 UIElementVector aUIElementVector;
746 implts_getUIElementVectorCopy( aUIElementVector );
747
748 SolarMutexGuard aGuard;
749 for (auto const& elem : aUIElementVector)
750 {
751 vcl::Window* pWindow = getWindowFromXUIElement( elem.m_xUIElement );
752 if ( pWindow && elem.m_bFloating )
753 {
754 if ( bVisible )
755 {
756 if ( elem.m_bVisible && !elem.m_bMasterHide )
757 pWindow->Show( true, ShowFlags::NoFocusChange | ShowFlags::NoActivate );
758 }
759 else
760 pWindow->Show( false );
761 }
762 }
763}
764
765void ToolbarLayoutManager::setVisible( bool bVisible )
766{
767 UIElementVector aUIElementVector;
768 implts_getUIElementVectorCopy( aUIElementVector );
769
770 SolarMutexGuard aGuard;
771 for (auto & elem : aUIElementVector)
772 {
773 if (!elem.m_bFloating)
774 {
775 elem.m_bMasterHide = !bVisible;
776 implts_setToolbar(elem);
777 implts_setLayoutDirty();
778 }
779
780 vcl::Window* pWindow = getWindowFromXUIElement( elem.m_xUIElement );
781 if ( pWindow )
782 {
783 bool bSetVisible( elem.m_bVisible && bVisible );
784 if ( !bSetVisible )
785 pWindow->Hide();
786 else
787 {
788 if ( elem.m_bFloating )
789 pWindow->Show(true, ShowFlags::NoFocusChange | ShowFlags::NoActivate );
790 }
791 }
792 }
793
794 if ( !bVisible )
795 resetDockingArea();
796}
797
798bool ToolbarLayoutManager::dockToolbar( const OUString& rResourceURL, ui::DockingArea eDockingArea, const awt::Point& aPos )
799{
800 UIElement aUIElement = implts_findToolbar( rResourceURL );
801
802 if ( aUIElement.m_xUIElement.is() )
803 {
804 try
805 {
806 uno::Reference< awt::XWindow > xWindow( aUIElement.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
807 uno::Reference< awt::XDockableWindow > xDockWindow( xWindow, uno::UNO_QUERY );
808 if ( xDockWindow.is() )
809 {
810 if ( eDockingArea != ui::DockingArea_DOCKINGAREA_DEFAULT )
811 aUIElement.m_aDockedData.m_nDockedArea = eDockingArea;
812
813 if ( !isDefaultPos( aPos ))
814 aUIElement.m_aDockedData.m_aPos = aPos;
815
816 if ( !xDockWindow->isFloating() )
817 {
818 vcl::Window* pWindow( nullptr );
819 ToolBox* pToolBox( nullptr );
820
821 {
822 SolarMutexGuard aGuard;
823 pWindow = VCLUnoHelper::GetWindow( xWindow ).get();
824 if ( pWindow && pWindow->GetType() == WindowType::TOOLBOX )
825 {
826 pToolBox = static_cast<ToolBox *>(pWindow);
827
828 // We have to set the alignment of the toolbox. It's possible that the toolbox is moved from a
829 // horizontal to a vertical docking area!
830 pToolBox->SetAlign( ImplConvertAlignment( aUIElement.m_aDockedData.m_nDockedArea ));
831 }
832 }
833
834 if ( hasDefaultPosValue( aUIElement.m_aDockedData.m_aPos ))
835 {
836 // Docking on its default position without a preset position -
837 // we have to find a good place for it.
838 ::Size aSize;
839
840 SolarMutexGuard aGuard;
841 {
842 if (pToolBox)
843 aSize = pToolBox->CalcWindowSizePixel( 1, ImplConvertAlignment( aUIElement.m_aDockedData.m_nDockedArea ) );
844 else if (pWindow)
845 aSize = pWindow->GetSizePixel();
846 }
847
848 ::Point aPixelPos;
849 awt::Point aDockPos;
850 implts_findNextDockingPos(aUIElement.m_aDockedData.m_nDockedArea, aSize, aDockPos, aPixelPos );
851 aUIElement.m_aDockedData.m_aPos = aDockPos;
852 }
853 }
854
855 implts_setToolbar( aUIElement );
856
857 if ( xDockWindow->isFloating() )
858 {
859 // ATTENTION: This will call toggleFloatingMode() via notifications which
860 // sets the floating member of the UIElement correctly!
861 xDockWindow->setFloatingMode( false );
862 }
863 else
864 {
865 implts_writeWindowStateData( aUIElement );
866 implts_sortUIElements();
867
868 if ( aUIElement.m_bVisible )
869 implts_setLayoutDirty();
870 }
871 return true;
872 }
873 }
874 catch (const lang::DisposedException&)
875 {
876 }
877 }
878
879 return false;
880}
881
882bool ToolbarLayoutManager::dockAllToolbars()
883{
884 std::vector< OUString > aToolBarNameVector;
885
886 {
887 SolarMutexGuard aReadLock;
888 for (auto const& elem : m_aUIElements)
889 {
890 if (elem.m_aType == "toolbar" && elem.m_xUIElement.is() && elem.m_bFloating
891 && elem.m_bVisible)
892 aToolBarNameVector.push_back(elem.m_aName);
893 }
894 }
895
896 bool bResult(true);
897 const sal_uInt32 nCount = aToolBarNameVector.size();
898 for ( sal_uInt32 i = 0; i < nCount; ++i )
899 {
900 awt::Point aPoint;
901 aPoint.X = aPoint.Y = SAL_MAX_INT32((sal_Int32) 0x7FFFFFFF);
902 bResult &= dockToolbar( aToolBarNameVector[i], ui::DockingArea_DOCKINGAREA_DEFAULT, aPoint );
903 }
904
905 return bResult;
906}
907
908void ToolbarLayoutManager::childWindowEvent( VclSimpleEvent const * pEvent )
909{
910 // To enable toolbar controllers to change their image when a sub-toolbar function
911 // is activated, we need this mechanism. We have NO connection between these toolbars
912 // anymore!
913 auto pWindowEvent = dynamic_cast< const VclWindowEvent* >(pEvent);
914 if (!pWindowEvent)
915 return;
916
917 if ( pEvent->GetId() == VclEventId::ToolboxSelect )
918 {
919 OUString aToolbarName;
920 OUString aCommand;
921 ToolBox* pToolBox = getToolboxPtr( pWindowEvent->GetWindow() );
922
923 if ( pToolBox )
924 {
925 aToolbarName = retrieveToolbarNameFromHelpURL( pToolBox );
926 sal_uInt16 nId = pToolBox->GetCurItemId();
927 if ( nId > 0 )
928 aCommand = pToolBox->GetItemCommand( nId );
929 }
930
931 if ( !aToolbarName.isEmpty() && !aCommand.isEmpty() )
932 {
933 SolarMutexClearableGuard aReadLock;
934 ::std::vector< uno::Reference< ui::XUIFunctionListener > > aListenerArray;
935
936 for (auto const& elem : m_aUIElements)
937 {
938 if ( elem.m_xUIElement.is() )
939 {
940 uno::Reference< ui::XUIFunctionListener > xListener( elem.m_xUIElement, uno::UNO_QUERY );
941 if ( xListener.is() )
942 aListenerArray.push_back( xListener );
943 }
944 }
945 aReadLock.clear();
946
947 const sal_uInt32 nCount = aListenerArray.size();
948 for ( sal_uInt32 i = 0; i < nCount; ++i )
949 {
950 try
951 {
952 aListenerArray[i]->functionExecute( aToolbarName, aCommand );
953 }
954 catch (const uno::RuntimeException&)
955 {
956 throw;
957 }
958 catch (const uno::Exception&)
959 {
960 }
961 }
962 }
963 }
964 else if ( pEvent->GetId() == VclEventId::ToolboxFormatChanged )
965 {
966 if ( !implts_isToolbarCreationActive() )
967 {
968 ToolBox* pToolBox = getToolboxPtr( static_cast<VclWindowEvent const *>(pEvent)->GetWindow() );
969 if ( pToolBox )
970 {
971 OUString aToolbarName = retrieveToolbarNameFromHelpURL( pToolBox );
972 if ( !aToolbarName.isEmpty() )
973 {
974 OUString aToolbarUrl = "private:resource/toolbar/" + aToolbarName;
975
976 UIElement aToolbar = implts_findToolbar( aToolbarUrl );
977 if ( aToolbar.m_xUIElement.is() && !aToolbar.m_bFloating )
978 {
979 implts_setLayoutDirty();
980 m_pParentLayouter->requestLayout();
981 }
982 }
983 }
984 }
985 }
986}
987
988void ToolbarLayoutManager::resetDockingArea()
989{
990 SolarMutexClearableGuard aReadLock;
991 uno::Reference< awt::XWindow > xTopDockingWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_TOP)] );
992 uno::Reference< awt::XWindow > xLeftDockingWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_LEFT)] );
993 uno::Reference< awt::XWindow > xRightDockingWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_RIGHT)] );
994 uno::Reference< awt::XWindow > xBottomDockingWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_BOTTOM)] );
995 aReadLock.clear();
996
997 if ( xTopDockingWindow.is() )
998 xTopDockingWindow->setPosSize( 0, 0, 0, 0, awt::PosSize::POSSIZE );
999 if ( xLeftDockingWindow.is() )
1000 xLeftDockingWindow->setPosSize( 0, 0, 0, 0, awt::PosSize::POSSIZE );
1001 if ( xRightDockingWindow.is() )
1002 xRightDockingWindow->setPosSize( 0, 0, 0, 0, awt::PosSize::POSSIZE );
1003 if ( xBottomDockingWindow.is() )
1004 xBottomDockingWindow->setPosSize( 0, 0, 0, 0, awt::PosSize::POSSIZE );
1005}
1006
1007void ToolbarLayoutManager::setParentWindow(
1008 const uno::Reference< awt::XWindowPeer >& xParentWindow )
1009{
1010 static const char DOCKINGAREASTRING[] = "dockingarea";
1011
1012 uno::Reference< awt::XWindow > xTopDockWindow( createToolkitWindow( m_xContext, xParentWindow, DOCKINGAREASTRING ), uno::UNO_QUERY );
1013 uno::Reference< awt::XWindow > xLeftDockWindow( createToolkitWindow( m_xContext, xParentWindow, DOCKINGAREASTRING ), uno::UNO_QUERY );
1014 uno::Reference< awt::XWindow > xRightDockWindow( createToolkitWindow( m_xContext, xParentWindow, DOCKINGAREASTRING ), uno::UNO_QUERY );
1015 uno::Reference< awt::XWindow > xBottomDockWindow( createToolkitWindow( m_xContext, xParentWindow, DOCKINGAREASTRING ), uno::UNO_QUERY );
1016
1017 {
1018 SolarMutexGuard aWriteLock;
1019 m_xContainerWindow.set(xParentWindow, uno::UNO_QUERY);
1020 m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_TOP)] = xTopDockWindow;
1021 m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_LEFT)] = xLeftDockWindow;
1022 m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_RIGHT)] = xRightDockWindow;
1023 m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_BOTTOM)] = xBottomDockWindow;
1024 }
1025
1026 if ( xParentWindow.is() )
1027 {
1028 SolarMutexGuard aGuard;
1029 VclPtr< ::DockingAreaWindow > pWindow = dynamic_cast< ::DockingAreaWindow* >(VCLUnoHelper::GetWindow( xTopDockWindow ).get() );
1030 if( pWindow )
1031 pWindow->SetAlign( WindowAlign::Top );
1032 pWindow = dynamic_cast< ::DockingAreaWindow* >(VCLUnoHelper::GetWindow( xBottomDockWindow ).get() );
1033 if( pWindow )
1034 pWindow->SetAlign( WindowAlign::Bottom );
1035 pWindow = dynamic_cast< ::DockingAreaWindow* >(VCLUnoHelper::GetWindow( xLeftDockWindow ).get() );
1036 if( pWindow )
1037 pWindow->SetAlign( WindowAlign::Left );
1038 pWindow = dynamic_cast< ::DockingAreaWindow* >(VCLUnoHelper::GetWindow( xRightDockWindow ).get() );
1039 if( pWindow )
1040 pWindow->SetAlign( WindowAlign::Right );
1041 implts_reparentToolbars();
1042 }
1043 else
1044 {
1045 destroyToolbars();
1046 resetDockingArea();
1047 }
1048}
1049
1050void ToolbarLayoutManager::setDockingAreaOffsets( const ::tools::Rectangle& rOffsets )
1051{
1052 SolarMutexGuard g;
1053 m_aDockingAreaOffsets = rOffsets;
1054 m_bLayoutDirty = true;
1055}
1056
1057OUString ToolbarLayoutManager::implts_generateGenericAddonToolbarTitle( sal_Int32 nNumber ) const
1058{
1059 OUString aAddonGenericTitle(FwkResId(STR_TOOLBAR_TITLE_ADDONreinterpret_cast<char const *>("STR_TOOLBAR_TITLE_ADDON"
"\004" u8"Add-On %num%")
));
1060 const vcl::I18nHelper& rI18nHelper = Application::GetSettings().GetUILocaleI18nHelper();
1061
1062 OUString aNumStr = rI18nHelper.GetNum( nNumber, 0, false, false );
1063 aAddonGenericTitle = aAddonGenericTitle.replaceFirst( "%num%", aNumStr );
1064
1065 return aAddonGenericTitle;
1066}
1067
1068void ToolbarLayoutManager::implts_createAddonsToolBars()
1069{
1070 SolarMutexClearableGuard aWriteLock;
1071 if ( !m_pAddonOptions )
1072 m_pAddonOptions.reset( new AddonsOptions );
1073
1074 uno::Reference< ui::XUIElementFactory > xUIElementFactory( m_xUIElementFactoryManager );
1075 uno::Reference< frame::XFrame > xFrame( m_xFrame );
1076 aWriteLock.clear();
1077
1078 if (isPreviewFrame())
1079 return; // no addon toolbars for preview frame!
1080
1081 uno::Sequence< uno::Sequence< beans::PropertyValue > > aAddonToolBarData;
1082 uno::Reference< ui::XUIElement > xUIElement;
1083
1084 sal_uInt32 nCount = m_pAddonOptions->GetAddonsToolBarCount();
1085
1086 uno::Sequence< beans::PropertyValue > aPropSeq( 2 );
1087 aPropSeq[0].Name = "Frame";
1088 aPropSeq[0].Value <<= xFrame;
1089 aPropSeq[1].Name = "ConfigurationData";
1090 for ( sal_uInt32 i = 0; i < nCount; i++ )
1091 {
1092 OUString aAddonToolBarName( "private:resource/toolbar/addon_" +
1093 m_pAddonOptions->GetAddonsToolbarResourceName(i) );
1094 aAddonToolBarData = m_pAddonOptions->GetAddonsToolBarPart( i );
1095 aPropSeq[1].Value <<= aAddonToolBarData;
1096
1097 UIElement aElement = implts_findToolbar( aAddonToolBarName );
1098
1099 // #i79828
1100 // It's now possible that we are called more than once. Be sure to not create
1101 // add-on toolbars more than once!
1102 if ( aElement.m_xUIElement.is() )
1103 continue;
1104
1105 try
1106 {
1107 xUIElement = xUIElementFactory->createUIElement( aAddonToolBarName, aPropSeq );
1108 if ( xUIElement.is() )
1109 {
1110 uno::Reference< awt::XDockableWindow > xDockWindow( xUIElement->getRealInterface(), uno::UNO_QUERY );
1111 if ( xDockWindow.is() )
1112 {
1113 try
1114 {
1115 xDockWindow->addDockableWindowListener( uno::Reference< awt::XDockableWindowListener >( static_cast< OWeakObject * >( this ), uno::UNO_QUERY ));
1116 xDockWindow->enableDocking( true );
1117 uno::Reference< awt::XWindow > xWindow( xDockWindow, uno::UNO_QUERY );
1118 if ( xWindow.is() )
1119 xWindow->addWindowListener( uno::Reference< awt::XWindowListener >( static_cast< OWeakObject * >( this ), uno::UNO_QUERY ));
1120 }
1121 catch (const uno::Exception&)
1122 {
1123 }
1124 }
1125
1126 OUString aGenericAddonTitle = implts_generateGenericAddonToolbarTitle( i+1 );
1127
1128 if ( !aElement.m_aName.isEmpty() )
1129 {
1130 // Reuse a local entry so we are able to use the latest
1131 // UI changes for this document.
1132 implts_setElementData( aElement, xDockWindow );
1133 aElement.m_xUIElement = xUIElement;
1134 if ( aElement.m_aUIName.isEmpty() )
1135 {
1136 aElement.m_aUIName = aGenericAddonTitle;
1137 implts_writeWindowStateData( aElement );
1138 }
1139 }
1140 else
1141 {
1142 // Create new UI element and try to read its state data
1143 UIElement aNewToolbar( aAddonToolBarName, "toolbar", xUIElement );
1144 aNewToolbar.m_bFloating = true;
1145 implts_readWindowStateData( aAddonToolBarName, aNewToolbar );
1146 implts_setElementData( aNewToolbar, xDockWindow );
1147 if ( aNewToolbar.m_aUIName.isEmpty() )
1148 {
1149 aNewToolbar.m_aUIName = aGenericAddonTitle;
1150 implts_writeWindowStateData( aNewToolbar );
1151 }
1152 implts_insertToolbar( aNewToolbar );
1153 }
1154
1155 uno::Reference< awt::XWindow > xWindow( xDockWindow, uno::UNO_QUERY );
1156 if ( xWindow.is() )
1157 {
1158 // Set generic title for add-on toolbar
1159 SolarMutexGuard aGuard;
1160 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
1161 if ( pWindow->GetText().isEmpty() )
1162 pWindow->SetText( aGenericAddonTitle );
1163 if ( pWindow->GetType() == WindowType::TOOLBOX )
1164 {
1165 ToolBox* pToolbar = static_cast<ToolBox *>(pWindow.get());
1166 pToolbar->SetMenuType();
1167 }
1168 }
1169 }
1170 }
1171 catch (const container::NoSuchElementException&)
1172 {
1173 }
1174 catch (const lang::IllegalArgumentException&)
1175 {
1176 }
1177 }
1178}
1179
1180void ToolbarLayoutManager::implts_createCustomToolBars()
1181{
1182 SolarMutexClearableGuard aReadLock;
1183 if ( !m_bComponentAttached )
1184 return;
1185
1186 uno::Reference< frame::XFrame > xFrame( m_xFrame );
1187 uno::Reference< ui::XUIConfigurationManager > xModuleCfgMgr = m_xModuleCfgMgr;
1188 uno::Reference< ui::XUIConfigurationManager > xDocCfgMgr = m_xDocCfgMgr;
1189 aReadLock.clear();
1190
1191 if ( !xFrame.is() )
1192 return;
1193
1194 if (isPreviewFrame())
1195 return; // no custom toolbars for preview frame!
1196
1197 uno::Sequence< uno::Sequence< beans::PropertyValue > > aTbxSeq;
1198 if ( xDocCfgMgr.is() )
1199 {
1200 aTbxSeq = xDocCfgMgr->getUIElementsInfo( ui::UIElementType::TOOLBAR );
1201 implts_createCustomToolBars( aTbxSeq ); // first create all document based toolbars
1202 }
1203 if ( xModuleCfgMgr.is() )
1204 {
1205 aTbxSeq = xModuleCfgMgr->getUIElementsInfo( ui::UIElementType::TOOLBAR );
1206 implts_createCustomToolBars( aTbxSeq ); // second create module based toolbars
1207 }
1208}
1209
1210void ToolbarLayoutManager::implts_createNonContextSensitiveToolBars()
1211{
1212 SolarMutexClearableGuard aReadLock;
1213
1214 if ( !m_xPersistentWindowState.is() || !m_xFrame.is() || !m_bComponentAttached )
1215 return;
1216
1217 uno::Reference< container::XNameAccess > xPersistentWindowState( m_xPersistentWindowState );
1218 aReadLock.clear();
1219
1220 if (isPreviewFrame())
1221 return;
1222
1223 std::vector< OUString > aMakeVisibleToolbars;
1224
1225 try
1226 {
1227 const uno::Sequence< OUString > aToolbarNames = xPersistentWindowState->getElementNames();
1228
1229 if ( aToolbarNames.hasElements() )
1230 {
1231 OUString aElementType;
1232 OUString aElementName;
1233
1234 aMakeVisibleToolbars.reserve(aToolbarNames.getLength());
1235
1236 SolarMutexGuard g;
1237
1238 for ( OUString const & aName : aToolbarNames )
1239 {
1240 parseResourceURL( aName, aElementType, aElementName );
1241
1242 // Check that we only create:
1243 // - Toolbars (the statusbar is also member of the persistent window state)
1244 // - Not custom toolbars, there are created with their own method (implts_createCustomToolbars)
1245 if ( aElementType.equalsIgnoreAsciiCase("toolbar") &&
1246 aElementName.indexOf( "custom_" ) == -1 )
1247 {
1248 UIElement aNewToolbar = implts_findToolbar( aName );
1249 bool bFound = ( aNewToolbar.m_aName == aName );
1250 if ( !bFound )
1251 implts_readWindowStateData( aName, aNewToolbar );
1252
1253 if ( aNewToolbar.m_bVisible && !aNewToolbar.m_bContextSensitive )
1254 {
1255 if ( !bFound )
1256 implts_insertToolbar( aNewToolbar );
1257 aMakeVisibleToolbars.push_back( aName );
1258 }
1259 }
1260 }
1261 }
1262 }
1263 catch (const uno::RuntimeException&)
1264 {
1265 throw;
1266 }
1267 catch (const uno::Exception&)
1268 {
1269 }
1270
1271 for (auto const& rURL : aMakeVisibleToolbars)
1272 {
1273 requestToolbar(rURL);
1274 }
1275}
1276
1277void ToolbarLayoutManager::implts_createCustomToolBars( const uno::Sequence< uno::Sequence< beans::PropertyValue > >& aTbxSeqSeq )
1278{
1279 for ( const uno::Sequence< beans::PropertyValue >& rTbxSeq : aTbxSeqSeq )
1280 {
1281 OUString aTbxResName;
1282 OUString aTbxTitle;
1283 for ( const beans::PropertyValue& rProp : rTbxSeq )
1284 {
1285 if ( rProp.Name == "ResourceURL" )
1286 rProp.Value >>= aTbxResName;
1287 else if ( rProp.Name == "UIName" )
1288 rProp.Value >>= aTbxTitle;
1289 }
1290
1291 // Only create custom toolbars. Their name have to start with "custom_"!
1292 if ( !aTbxResName.isEmpty() && ( aTbxResName.indexOf( "custom_" ) != -1 ) )
1293 implts_createCustomToolBar( aTbxResName, aTbxTitle );
1294 }
1295}
1296
1297void ToolbarLayoutManager::implts_createCustomToolBar( const OUString& aTbxResName, const OUString& aTitle )
1298{
1299 if ( aTbxResName.isEmpty() )
1300 return;
1301
1302 if ( !createToolbar( aTbxResName ) )
1303 SAL_WARN("fwk.uielement", "ToolbarLayoutManager cannot create custom toolbar")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "fwk.uielement")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break
; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "ToolbarLayoutManager cannot create custom toolbar"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("fwk.uielement"
), ("/home/maarten/src/libreoffice/core/framework/source/layoutmanager/toolbarlayoutmanager.cxx"
":" "1303" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "ToolbarLayoutManager cannot create custom toolbar"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "ToolbarLayoutManager cannot create custom toolbar"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("fwk.uielement"
), ("/home/maarten/src/libreoffice/core/framework/source/layoutmanager/toolbarlayoutmanager.cxx"
":" "1303" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "ToolbarLayoutManager cannot create custom toolbar"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("fwk.uielement"
), ("/home/maarten/src/libreoffice/core/framework/source/layoutmanager/toolbarlayoutmanager.cxx"
":" "1303" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "ToolbarLayoutManager cannot create custom toolbar"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "ToolbarLayoutManager cannot create custom toolbar"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("fwk.uielement"
), ("/home/maarten/src/libreoffice/core/framework/source/layoutmanager/toolbarlayoutmanager.cxx"
":" "1303" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
1304
1305 uno::Reference< ui::XUIElement > xUIElement = getToolbar( aTbxResName );
1306
1307 if ( !aTitle.isEmpty() && xUIElement.is() )
1308 {
1309 SolarMutexGuard aGuard;
1310
1311 vcl::Window* pWindow = getWindowFromXUIElement( xUIElement );
1312 if ( pWindow )
1313 pWindow->SetText( aTitle );
1314 }
1315}
1316
1317void ToolbarLayoutManager::implts_reparentToolbars()
1318{
1319 SolarMutexClearableGuard aWriteLock;
1320 UIElementVector aUIElementVector = m_aUIElements;
1321 VclPtr<vcl::Window> pContainerWindow = VCLUnoHelper::GetWindow( m_xContainerWindow );
1322 VclPtr<vcl::Window> pTopDockWindow = VCLUnoHelper::GetWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_TOP)] );
1323 VclPtr<vcl::Window> pBottomDockWindow = VCLUnoHelper::GetWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_BOTTOM)] );
1324 VclPtr<vcl::Window> pLeftDockWindow = VCLUnoHelper::GetWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_LEFT)] );
1325 VclPtr<vcl::Window> pRightDockWindow = VCLUnoHelper::GetWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_RIGHT)] );
1326 aWriteLock.clear();
1327
1328 SolarMutexGuard aGuard;
1329 if ( !pContainerWindow )
1330 return;
1331
1332 for (auto const& elem : aUIElementVector)
1333 {
1334 uno::Reference< ui::XUIElement > xUIElement( elem.m_xUIElement );
1335 if ( xUIElement.is() )
1336 {
1337 uno::Reference< awt::XWindow > xWindow;
1338 try
1339 {
1340 // We have to retrieve the window reference with try/catch as it is
1341 // possible that all elements have been disposed!
1342 xWindow.set( xUIElement->getRealInterface(), uno::UNO_QUERY );
1343 }
1344 catch (const uno::RuntimeException&)
1345 {
1346 throw;
1347 }
1348 catch (const uno::Exception&)
1349 {
1350 }
1351
1352 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
1353 if ( pWindow )
1354 {
1355 // Reparent our child windows according to their current state.
1356 if ( elem.m_bFloating )
1357 pWindow->SetParent( pContainerWindow );
1358 else
1359 {
1360 if ( elem.m_aDockedData.m_nDockedArea == ui::DockingArea_DOCKINGAREA_TOP )
1361 pWindow->SetParent( pTopDockWindow );
1362 else if ( elem.m_aDockedData.m_nDockedArea == ui::DockingArea_DOCKINGAREA_BOTTOM )
1363 pWindow->SetParent( pBottomDockWindow );
1364 else if ( elem.m_aDockedData.m_nDockedArea == ui::DockingArea_DOCKINGAREA_LEFT )
1365 pWindow->SetParent( pLeftDockWindow );
1366 else
1367 pWindow->SetParent( pRightDockWindow );
1368 }
1369 }
1370 }
1371 }
1372}
1373
1374void ToolbarLayoutManager::implts_setToolbarCreation( bool bStart )
1375{
1376 SolarMutexGuard g;
1377 m_bToolbarCreation = bStart;
1378}
1379
1380bool ToolbarLayoutManager::implts_isToolbarCreationActive()
1381{
1382 SolarMutexGuard g;
1383 return m_bToolbarCreation;
1384}
1385
1386void ToolbarLayoutManager::implts_setElementData( UIElement& rElement, const uno::Reference< awt::XDockableWindow >& rDockWindow )
1387{
1388 SolarMutexClearableGuard aReadLock;
1389 bool bShowElement( rElement.m_bVisible && !rElement.m_bMasterHide && implts_isParentWindowVisible() );
1390 aReadLock.clear();
1391
1392 uno::Reference< awt::XWindow2 > xWindow( rDockWindow, uno::UNO_QUERY );
1393
1394 vcl::Window* pWindow( nullptr );
1395 ToolBox* pToolBox( nullptr );
1396
1397 if ( !(rDockWindow.is() && xWindow.is()) )
1398 return;
1399
1400 {
1401 SolarMutexGuard aGuard;
1402 pWindow = VCLUnoHelper::GetWindow( xWindow ).get();
1403 if ( pWindow )
1404 {
1405 OUString aText = pWindow->GetText();
1406 if ( aText.isEmpty() )
1407 pWindow->SetText( rElement.m_aUIName );
1408 if ( rElement.m_bNoClose )
1409 pWindow->SetStyle( pWindow->GetStyle() & ~WB_CLOSEABLE );
1410 if ( pWindow->GetType() == WindowType::TOOLBOX )
1411 pToolBox = static_cast<ToolBox *>(pWindow);
1412 }
1413 if ( pToolBox )
1414 {
1415 pToolBox->SetButtonType( rElement.m_nStyle );
1416 if ( rElement.m_bNoClose )
1417 pToolBox->SetFloatStyle( pToolBox->GetFloatStyle() & ~WB_CLOSEABLE );
1418 }
1419 }
1420
1421 if ( rElement.m_bFloating )
1422 {
1423 if ( pWindow )
1424 {
1425 SolarMutexGuard aGuard;
1426 OUString aText = pWindow->GetText();
1427 if ( aText.isEmpty() )
1428 pWindow->SetText( rElement.m_aUIName );
1429 }
1430
1431 awt::Point aPos(rElement.m_aFloatingData.m_aPos);
1432 bool bWriteData( false );
1433 bool bUndefPos = hasDefaultPosValue( rElement.m_aFloatingData.m_aPos );
1434 bool bSetSize = ( rElement.m_aFloatingData.m_aSize.Width != 0 &&
1435 rElement.m_aFloatingData.m_aSize.Height != 0 );
1436 rDockWindow->setFloatingMode( true );
1437 if ( bUndefPos )
1438 {
1439 aPos = implts_findNextCascadeFloatingPos();
1440 rElement.m_aFloatingData.m_aPos = aPos; // set new cascaded position
1441 bWriteData = true;
1442 }
1443
1444 if( bSetSize )
1445 xWindow->setOutputSize(rElement.m_aFloatingData.m_aSize);
1446 else
1447 {
1448 if( pToolBox )
1449 {
1450 // set an optimal initial floating size
1451 SolarMutexGuard aGuard;
1452 ::Size aSize( pToolBox->CalcFloatingWindowSizePixel() );
1453 pToolBox->SetOutputSizePixel( aSize );
1454 }
1455 }
1456
1457 // #i60882# IMPORTANT: Set position after size as it is
1458 // possible that we position some part of the toolbar
1459 // outside of the desktop. A default constructed toolbar
1460 // always has one line. Now VCL automatically
1461 // position the toolbar back into the desktop. Therefore
1462 // we resize the toolbar with the new (wrong) position.
1463 // To fix this problem we have to set the size BEFORE the
1464 // position.
1465 xWindow->setPosSize( aPos.X, aPos.Y, 0, 0, awt::PosSize::POS );
1466
1467 if ( bWriteData )
1468 implts_writeWindowStateData( rElement );
1469 if ( bShowElement && pWindow )
1470 {
1471 SolarMutexGuard aGuard;
1472 pWindow->Show( true, ShowFlags::NoFocusChange | ShowFlags::NoActivate );
1473 }
1474 }
1475 else
1476 {
1477 bool bSetSize( false );
1478 ::Point aPixelPos;
1479 ::Size aSize;
1480
1481 if ( pToolBox )
1482 {
1483 SolarMutexGuard aGuard;
1484 pToolBox->SetAlign( ImplConvertAlignment(rElement.m_aDockedData.m_nDockedArea ) );
1485 pToolBox->SetLineCount( 1 );
1486 rDockWindow->setFloatingMode( false );
1487 if ( rElement.m_aDockedData.m_bLocked )
1488 rDockWindow->lock();
1489 aSize = pToolBox->CalcWindowSizePixel();
1490 bSetSize = true;
1491
1492 if ( isDefaultPos( rElement.m_aDockedData.m_aPos ))
1493 {
1494 awt::Point aDockPos;
1495 implts_findNextDockingPos( rElement.m_aDockedData.m_nDockedArea, aSize, aDockPos, aPixelPos );
1496 rElement.m_aDockedData.m_aPos = aDockPos;
1497 }
1498 }
1499
1500 xWindow->setPosSize( aPixelPos.X(), aPixelPos.Y(), 0, 0, awt::PosSize::POS );
1501 if( bSetSize )
1502 xWindow->setOutputSize( AWTSize( aSize) );
1503
1504 if ( pWindow )
1505 {
1506 SolarMutexGuard aGuard;
1507 if ( !bShowElement )
1508 pWindow->Hide();
1509 }
1510 }
1511}
1512
1513void ToolbarLayoutManager::implts_destroyDockingAreaWindows()
1514{
1515 SolarMutexClearableGuard aWriteLock;
1516 uno::Reference< awt::XWindow > xTopDockingWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_TOP)] );
1517 uno::Reference< awt::XWindow > xLeftDockingWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_LEFT)] );
1518 uno::Reference< awt::XWindow > xRightDockingWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_RIGHT)] );
1519 uno::Reference< awt::XWindow > xBottomDockingWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_BOTTOM)] );
1520 m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_TOP)].clear();
1521 m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_LEFT)].clear();
1522 m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_RIGHT)].clear();
1523 m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_BOTTOM)].clear();
1524 aWriteLock.clear();
1525
1526 // destroy windows
1527 xTopDockingWindow->dispose();
1528 xLeftDockingWindow->dispose();
1529 xRightDockingWindow->dispose();
1530 xBottomDockingWindow->dispose();
1531}
1532
1533// persistence methods
1534
1535bool ToolbarLayoutManager::implts_readWindowStateData( const OUString& aName, UIElement& rElementData )
1536{
1537 return LayoutManager::readWindowStateData( aName, rElementData, m_xPersistentWindowState,
1538 m_pGlobalSettings, m_bGlobalSettings, m_xContext );
1539}
1540
1541void ToolbarLayoutManager::implts_writeWindowStateData( const UIElement& rElementData )
1542{
1543 SolarMutexClearableGuard aWriteLock;
1544 uno::Reference< container::XNameAccess > xPersistentWindowState( m_xPersistentWindowState );
1545 aWriteLock.clear();
1546
1547 bool bPersistent( false );
1548 uno::Reference< beans::XPropertySet > xPropSet( rElementData.m_xUIElement, uno::UNO_QUERY );
1549 if ( xPropSet.is() )
1550 {
1551 try
1552 {
1553 // Check persistent flag of the user interface element
1554 xPropSet->getPropertyValue("Persistent") >>= bPersistent;
1555 }
1556 catch (const beans::UnknownPropertyException&)
1557 {
1558 bPersistent = true; // Non-configurable elements should at least store their dimension/position
1559 }
1560 catch (const lang::WrappedTargetException&)
1561 {
1562 }
1563 }
1564
1565 if ( !(bPersistent && xPersistentWindowState.is()) )
1566 return;
1567
1568 try
1569 {
1570 uno::Sequence< beans::PropertyValue > aWindowState( 9 );
1571
1572 aWindowState[0].Name = WINDOWSTATE_PROPERTY_DOCKED"Docked";
1573 aWindowState[0].Value <<= !rElementData.m_bFloating;
1574 aWindowState[1].Name = WINDOWSTATE_PROPERTY_VISIBLE"Visible";
1575 aWindowState[1].Value <<= rElementData.m_bVisible;
1576 aWindowState[2].Name = WINDOWSTATE_PROPERTY_DOCKINGAREA"DockingArea";
1577 aWindowState[2].Value <<= rElementData.m_aDockedData.m_nDockedArea;
1578
1579 awt::Point aPos = rElementData.m_aDockedData.m_aPos;
1580 aWindowState[3].Name = WINDOWSTATE_PROPERTY_DOCKPOS"DockPos";
1581 aWindowState[3].Value <<= aPos;
1582
1583 aPos = rElementData.m_aFloatingData.m_aPos;
1584 aWindowState[4].Name = WINDOWSTATE_PROPERTY_POS"Pos";
1585 aWindowState[4].Value <<= aPos;
1586
1587 aWindowState[5].Name = WINDOWSTATE_PROPERTY_SIZE"Size";
1588 aWindowState[5].Value <<= rElementData.m_aFloatingData.m_aSize;
1589 aWindowState[6].Name = WINDOWSTATE_PROPERTY_UINAME"UIName";
1590 aWindowState[6].Value <<= rElementData.m_aUIName;
1591 aWindowState[7].Name = WINDOWSTATE_PROPERTY_LOCKED"Locked";
1592 aWindowState[7].Value <<= rElementData.m_aDockedData.m_bLocked;
1593 aWindowState[8].Name = WINDOWSTATE_PROPERTY_STYLE"Style";
1594 aWindowState[8].Value <<= static_cast<sal_uInt16>(rElementData.m_nStyle);
1595
1596 OUString aName = rElementData.m_aName;
1597 if ( xPersistentWindowState->hasByName( aName ))
1598 {
1599 uno::Reference< container::XNameReplace > xReplace( xPersistentWindowState, uno::UNO_QUERY );
1600 xReplace->replaceByName( aName, uno::makeAny( aWindowState ));
1601 }
1602 else
1603 {
1604 uno::Reference< container::XNameContainer > xInsert( xPersistentWindowState, uno::UNO_QUERY );
1605 xInsert->insertByName( aName, uno::makeAny( aWindowState ));
1606 }
1607 }
1608 catch (const uno::Exception&)
1609 {
1610 }
1611}
1612
1613/******************************************************************************
1614 LOOKUP PART FOR TOOLBARS
1615******************************************************************************/
1616
1617UIElement& ToolbarLayoutManager::impl_findToolbar( const OUString& aName )
1618{
1619 static UIElement aEmptyElement;
1620
1621 SolarMutexGuard g;
1622 for (auto & elem : m_aUIElements)
1623 {
1624 if ( elem.m_aName == aName )
1625 return elem;
1626 }
1627
1628 return aEmptyElement;
1629}
1630
1631UIElement ToolbarLayoutManager::implts_findToolbar( const OUString& aName )
1632{
1633 SolarMutexGuard g;
1634 return impl_findToolbar( aName );
1635}
1636
1637UIElement ToolbarLayoutManager::implts_findToolbar( const uno::Reference< uno::XInterface >& xToolbar )
1638{
1639 UIElement aToolbar;
1640
1641 SolarMutexGuard g;
1642 for (auto const& elem : m_aUIElements)
1643 {
1644 if ( elem.m_xUIElement.is() )
1645 {
1646 uno::Reference< uno::XInterface > xIfac( elem.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
1647 if ( xIfac == xToolbar )
1648 {
1649 aToolbar = elem;
1650 break;
1651 }
1652 }
1653 }
1654
1655 return aToolbar;
1656}
1657
1658uno::Reference< awt::XWindow > ToolbarLayoutManager::implts_getXWindow( const OUString& aName )
1659{
1660 uno::Reference< awt::XWindow > xWindow;
1661
1662 SolarMutexGuard g;
1663 for (auto const& elem : m_aUIElements)
1664 {
1665 if ( elem.m_aName == aName && elem.m_xUIElement.is() )
1666 {
1667 xWindow.set( elem.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
1668 break;
1669 }
1670 }
1671
1672 return xWindow;
1673}
1674
1675vcl::Window* ToolbarLayoutManager::implts_getWindow( const OUString& aName )
1676{
1677 uno::Reference< awt::XWindow > xWindow = implts_getXWindow( aName );
1678 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
1679
1680 return pWindow;
2
Calling implicit destructor for 'VclPtr<vcl::Window>'
3
Calling '~Reference'
11
Returning from '~Reference'
12
Returning from destructor for 'VclPtr<vcl::Window>'
13
Use of memory after it is freed
1681}
1682
1683bool ToolbarLayoutManager::implts_insertToolbar( const UIElement& rUIElement )
1684{
1685 UIElement aTempData;
1686 bool bFound( false );
1687 bool bResult( false );
1688
1689 aTempData = implts_findToolbar( rUIElement.m_aName );
1690 if ( aTempData.m_aName == rUIElement.m_aName )
1691 bFound = true;
1692
1693 if ( !bFound )
1694 {
1695 SolarMutexGuard g;
1696 m_aUIElements.push_back( rUIElement );
1697 bResult = true;
1698 }
1699
1700 return bResult;
1701}
1702
1703void ToolbarLayoutManager::implts_setToolbar( const UIElement& rUIElement )
1704{
1705 SolarMutexGuard g;
1706 UIElement& rData = impl_findToolbar( rUIElement.m_aName );
1707 if ( rData.m_aName == rUIElement.m_aName )
1708 rData = rUIElement;
1709 else
1710 m_aUIElements.push_back( rUIElement );
1711}
1712
1713/******************************************************************************
1714 LAYOUT CODE PART FOR TOOLBARS
1715******************************************************************************/
1716
1717awt::Point ToolbarLayoutManager::implts_findNextCascadeFloatingPos()
1718{
1719 const sal_Int32 nHotZoneX = 50;
1720 const sal_Int32 nHotZoneY = 50;
1721 const sal_Int32 nCascadeIndentX = 15;
1722 const sal_Int32 nCascadeIndentY = 15;
1723
1724 SolarMutexClearableGuard aReadLock;
1725 uno::Reference< awt::XWindow2 > xContainerWindow( m_xContainerWindow );
1726 uno::Reference< awt::XWindow > xTopDockingWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_TOP)] );
1727 uno::Reference< awt::XWindow > xLeftDockingWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_LEFT)] );
1728 aReadLock.clear();
1729
1730 awt::Point aStartPos( nCascadeIndentX, nCascadeIndentY );
1731 awt::Point aCurrPos( aStartPos );
1732
1733 if ( xContainerWindow.is() )
1734 {
1735 SolarMutexGuard aGuard;
1736 VclPtr<vcl::Window> pContainerWindow = VCLUnoHelper::GetWindow( xContainerWindow );
1737 if ( pContainerWindow )
1738 aStartPos = AWTPoint(pContainerWindow->OutputToScreenPixel(VCLPoint(aStartPos)));
1739 }
1740
1741 // Determine size of top and left docking area
1742 awt::Rectangle aTopRect( xTopDockingWindow->getPosSize() );
1743 awt::Rectangle aLeftRect( xLeftDockingWindow->getPosSize() );
1744
1745 aStartPos.X += aLeftRect.Width + nCascadeIndentX;
1746 aStartPos.Y += aTopRect.Height + nCascadeIndentY;
1747 aCurrPos = aStartPos;
1748
1749 // Try to find a cascaded position for the new floating window
1750 for (auto const& elem : m_aUIElements)
1751 {
1752 if ( elem.m_xUIElement.is() )
1753 {
1754 uno::Reference< awt::XDockableWindow > xDockWindow( elem.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
1755 uno::Reference< awt::XWindow > xWindow( xDockWindow, uno::UNO_QUERY );
1756 if ( xDockWindow.is() && xDockWindow->isFloating() )
1757 {
1758 SolarMutexGuard aGuard;
1759 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
1760 if ( pWindow && pWindow->IsVisible() )
1761 {
1762 awt::Rectangle aFloatRect = xWindow->getPosSize();
1763 if ((( aFloatRect.X - nHotZoneX ) <= aCurrPos.X ) &&
1764 ( aFloatRect.X >= aCurrPos.X ) &&
1765 (( aFloatRect.Y - nHotZoneY ) <= aCurrPos.Y ) &&
1766 ( aFloatRect.Y >= aCurrPos.Y ))
1767 {
1768 aCurrPos.X = aFloatRect.X + nCascadeIndentX;
1769 aCurrPos.Y = aFloatRect.Y + nCascadeIndentY;
1770 }
1771 }
1772 }
1773 }
1774 }
1775
1776 return aCurrPos;
1777}
1778
1779void ToolbarLayoutManager::implts_sortUIElements()
1780{
1781 SolarMutexGuard g;
1782
1783 std::stable_sort( m_aUIElements.begin(), m_aUIElements.end()); // first created element should first
1784
1785 // We have to reset our temporary flags.
1786 for (auto & elem : m_aUIElements)
1787 elem.m_bUserActive = false;
1788}
1789
1790void ToolbarLayoutManager::implts_getUIElementVectorCopy( UIElementVector& rCopy )
1791{
1792 SolarMutexGuard g;
1793 rCopy = m_aUIElements;
1794}
1795
1796::Size ToolbarLayoutManager::implts_getTopBottomDockingAreaSizes()
1797{
1798 ::Size aSize;
1799 uno::Reference< awt::XWindow > xTopDockingAreaWindow;
1800 uno::Reference< awt::XWindow > xBottomDockingAreaWindow;
1801
1802 {
1803 SolarMutexGuard aReadLock;
1804 xTopDockingAreaWindow = m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_TOP)];
1805 xBottomDockingAreaWindow = m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_BOTTOM)];
1806 }
1807
1808 if ( xTopDockingAreaWindow.is() )
1809 aSize.setWidth( xTopDockingAreaWindow->getPosSize().Height );
1810 if ( xBottomDockingAreaWindow.is() )
1811 aSize.setHeight( xBottomDockingAreaWindow->getPosSize().Height );
1812
1813 return aSize;
1814}
1815
1816void ToolbarLayoutManager::implts_getDockingAreaElementInfos( ui::DockingArea eDockingArea, std::vector< SingleRowColumnWindowData >& rRowColumnsWindowData )
1817{
1818 std::vector< UIElement > aWindowVector;
1819
1820 if (( eDockingArea < ui::DockingArea_DOCKINGAREA_TOP ) || ( eDockingArea > ui::DockingArea_DOCKINGAREA_RIGHT ))
1821 eDockingArea = ui::DockingArea_DOCKINGAREA_TOP;
1822
1823 uno::Reference< awt::XWindow > xDockAreaWindow;
1824
1825 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
1826 {
1827 SolarMutexGuard aReadLock;
1828 aWindowVector.reserve(m_aUIElements.size());
1829 xDockAreaWindow = m_xDockAreaWindows[static_cast<int>(eDockingArea)];
1830 for (auto const& elem : m_aUIElements)
1831 {
1832 if (elem.m_aDockedData.m_nDockedArea == eDockingArea && elem.m_bVisible)
1833 {
1834 uno::Reference<ui::XUIElement> xUIElement(elem.m_xUIElement);
1835 if (xUIElement.is())
1836 {
1837 uno::Reference<awt::XWindow> xWindow(xUIElement->getRealInterface(),
1838 uno::UNO_QUERY);
1839 uno::Reference<awt::XDockableWindow> xDockWindow(xWindow, uno::UNO_QUERY);
1840 if (xDockWindow.is())
1841 {
1842 if (!elem.m_bFloating)
1843 {
1844 // docked windows
1845 aWindowVector.push_back(elem);
1846 }
1847 else
1848 {
1849 // floating windows
1850 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow(xWindow);
1851 DockingManager* pDockMgr = vcl::Window::GetDockingManager();
1852 if (pDockMgr != nullptr)
1853 {
1854 ImplDockingWindowWrapper* pWrapper
1855 = pDockMgr->GetDockingWindowWrapper(pWindow);
1856 if (pWrapper != nullptr && pWrapper->GetFloatingWindow())
1857 {
1858 // update the position data of the floating window
1859 if (pWrapper->GetFloatingWindow()->UpdatePositionData())
1860 {
1861 awt::Rectangle aTmpRect = xWindow->getPosSize();
1862 UIElement uiElem = elem;
1863 uiElem.m_aFloatingData.m_aPos
1864 = awt::Point(aTmpRect.X, aTmpRect.Y);
1865 implts_setToolbar(uiElem);
1866 implts_writeWindowStateData(uiElem);
1867 }
1868 }
1869 }
1870 }
1871 }
1872 }
1873 }
1874 }
1875 }
1876 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
1877
1878 rRowColumnsWindowData.clear();
1879
1880 // Collect data from windows that are on the same row/column
1881 sal_Int32 j;
1882 sal_Int32 nIndex( 0 );
1883 sal_Int32 nLastPos( 0 );
1884 sal_Int32 nCurrPos( -1 );
1885 sal_Int32 nLastRowColPixelPos( 0 );
1886 awt::Rectangle aDockAreaRect;
1887
1888 if ( xDockAreaWindow.is() )
1889 aDockAreaRect = xDockAreaWindow->getPosSize();
1890
1891 if ( eDockingArea == ui::DockingArea_DOCKINGAREA_TOP )
1892 nLastRowColPixelPos = 0;
1893 else if ( eDockingArea == ui::DockingArea_DOCKINGAREA_BOTTOM )
1894 nLastRowColPixelPos = aDockAreaRect.Height;
1895 else if ( eDockingArea == ui::DockingArea_DOCKINGAREA_LEFT )
1896 nLastRowColPixelPos = 0;
1897 else
1898 nLastRowColPixelPos = aDockAreaRect.Width;
1899
1900 const sal_uInt32 nCount = aWindowVector.size();
1901 for ( j = 0; j < sal_Int32( nCount); j++ )
1902 {
1903 const UIElement& rElement = aWindowVector[j];
1904 uno::Reference< awt::XWindow > xWindow;
1905 uno::Reference< ui::XUIElement > xUIElement( rElement.m_xUIElement );
1906 awt::Rectangle aPosSize;
1907
1908 if ( !lcl_checkUIElement(xUIElement,aPosSize,xWindow) )
1909 continue;
1910 if ( isHorizontalDockingArea( eDockingArea ))
1911 {
1912 if ( nCurrPos == -1 )
1913 {
1914 nCurrPos = rElement.m_aDockedData.m_aPos.Y;
1915 nLastPos = 0;
1916
1917 SingleRowColumnWindowData aRowColumnWindowData;
1918 aRowColumnWindowData.nRowColumn = nCurrPos;
1919 rRowColumnsWindowData.push_back( aRowColumnWindowData );
1920 }
1921
1922 sal_Int32 nSpace( 0 );
1923 if ( rElement.m_aDockedData.m_aPos.Y != nCurrPos )
1924 {
1925 if ( eDockingArea == ui::DockingArea_DOCKINGAREA_TOP )
1926 nLastRowColPixelPos += rRowColumnsWindowData[nIndex].nStaticSize;
1927 else
1928 nLastRowColPixelPos -= rRowColumnsWindowData[nIndex].nStaticSize;
1929 ++nIndex;
1930 nLastPos = 0;
1931 nCurrPos = rElement.m_aDockedData.m_aPos.Y;
1932 SingleRowColumnWindowData aRowColumnWindowData;
1933 aRowColumnWindowData.nRowColumn = nCurrPos;
1934 rRowColumnsWindowData.push_back( aRowColumnWindowData );
1935 }
1936
1937 // Calc space before an element and store it
1938 nSpace = ( rElement.m_aDockedData.m_aPos.X - nLastPos );
1939 if ( rElement.m_aDockedData.m_aPos.X >= nLastPos )
1940 {
1941 rRowColumnsWindowData[nIndex].nSpace += nSpace;
1942 nLastPos = rElement.m_aDockedData.m_aPos.X + aPosSize.Width;
1943 }
1944 else
1945 {
1946 nSpace = 0;
1947 nLastPos += aPosSize.Width;
1948 }
1949 rRowColumnsWindowData[nIndex].aRowColumnSpace.push_back( nSpace );
1950
1951 rRowColumnsWindowData[nIndex].aRowColumnWindows.push_back( xWindow );
1952 rRowColumnsWindowData[nIndex].aUIElementNames.push_back( rElement.m_aName );
1953 rRowColumnsWindowData[nIndex].aRowColumnWindowSizes.emplace_back(
1954 rElement.m_aDockedData.m_aPos.X,
1955 rElement.m_aDockedData.m_aPos.Y,
1956 aPosSize.Width,
1957 aPosSize.Height );
1958 if ( rRowColumnsWindowData[nIndex].nStaticSize < aPosSize.Height )
1959 rRowColumnsWindowData[nIndex].nStaticSize = aPosSize.Height;
1960 if ( eDockingArea == ui::DockingArea_DOCKINGAREA_TOP )
1961 rRowColumnsWindowData[nIndex].aRowColumnRect = awt::Rectangle( 0, nLastRowColPixelPos,
1962 aDockAreaRect.Width, aPosSize.Height );
1963 else
1964 rRowColumnsWindowData[nIndex].aRowColumnRect = awt::Rectangle( 0, ( nLastRowColPixelPos - aPosSize.Height ),
1965 aDockAreaRect.Width, aPosSize.Height );
1966 rRowColumnsWindowData[nIndex].nVarSize += aPosSize.Width + nSpace;
1967 }
1968 else
1969 {
1970 if ( nCurrPos == -1 )
1971 {
1972 nCurrPos = rElement.m_aDockedData.m_aPos.X;
1973 nLastPos = 0;
1974
1975 SingleRowColumnWindowData aRowColumnWindowData;
1976 aRowColumnWindowData.nRowColumn = nCurrPos;
1977 rRowColumnsWindowData.push_back( aRowColumnWindowData );
1978 }
1979
1980 sal_Int32 nSpace( 0 );
1981 if ( rElement.m_aDockedData.m_aPos.X != nCurrPos )
1982 {
1983 if ( eDockingArea == ui::DockingArea_DOCKINGAREA_LEFT )
1984 nLastRowColPixelPos += rRowColumnsWindowData[nIndex].nStaticSize;
1985 else
1986 nLastRowColPixelPos -= rRowColumnsWindowData[nIndex].nStaticSize;
1987 ++nIndex;
1988 nLastPos = 0;
1989 nCurrPos = rElement.m_aDockedData.m_aPos.X;
1990 SingleRowColumnWindowData aRowColumnWindowData;
1991 aRowColumnWindowData.nRowColumn = nCurrPos;
1992 rRowColumnsWindowData.push_back( aRowColumnWindowData );
1993 }
1994
1995 // Calc space before an element and store it
1996 nSpace = ( rElement.m_aDockedData.m_aPos.Y - nLastPos );
1997 if ( rElement.m_aDockedData.m_aPos.Y > nLastPos )
1998 {
1999 rRowColumnsWindowData[nIndex].nSpace += nSpace;
2000 nLastPos = rElement.m_aDockedData.m_aPos.Y + aPosSize.Height;
2001 }
2002 else
2003 {
2004 nSpace = 0;
2005 nLastPos += aPosSize.Height;
2006 }
2007 rRowColumnsWindowData[nIndex].aRowColumnSpace.push_back( nSpace );
2008
2009 rRowColumnsWindowData[nIndex].aRowColumnWindows.push_back( xWindow );
2010 rRowColumnsWindowData[nIndex].aUIElementNames.push_back( rElement.m_aName );
2011 rRowColumnsWindowData[nIndex].aRowColumnWindowSizes.emplace_back(
2012 rElement.m_aDockedData.m_aPos.X,
2013 rElement.m_aDockedData.m_aPos.Y,
2014 aPosSize.Width,
2015 aPosSize.Height );
2016 if ( rRowColumnsWindowData[nIndex].nStaticSize < aPosSize.Width )
2017 rRowColumnsWindowData[nIndex].nStaticSize = aPosSize.Width;
2018 if ( eDockingArea == ui::DockingArea_DOCKINGAREA_LEFT )
2019 rRowColumnsWindowData[nIndex].aRowColumnRect = awt::Rectangle( nLastRowColPixelPos, 0,
2020 aPosSize.Width, aDockAreaRect.Height );
2021 else
2022 rRowColumnsWindowData[nIndex].aRowColumnRect = awt::Rectangle( ( nLastRowColPixelPos - aPosSize.Width ), 0,
2023 aPosSize.Width, aDockAreaRect.Height );
2024 rRowColumnsWindowData[nIndex].nVarSize += aPosSize.Height + nSpace;
2025 }
2026 }
2027}
2028
2029void ToolbarLayoutManager::implts_getDockingAreaElementInfoOnSingleRowCol( ui::DockingArea eDockingArea, sal_Int32 nRowCol, SingleRowColumnWindowData& rRowColumnWindowData )
2030{
2031 std::vector< UIElement > aWindowVector;
2032
2033 if (( eDockingArea < ui::DockingArea_DOCKINGAREA_TOP ) || ( eDockingArea > ui::DockingArea_DOCKINGAREA_RIGHT ))
2034 eDockingArea = ui::DockingArea_DOCKINGAREA_TOP;
2035
2036 bool bHorzDockArea = isHorizontalDockingArea( eDockingArea );
2037
2038 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
2039 {
2040 SolarMutexGuard aReadLock;
2041 for (auto const& elem : m_aUIElements)
2042 {
2043 if (elem.m_aDockedData.m_nDockedArea == eDockingArea)
2044 {
2045 bool bSameRowCol = bHorzDockArea ? (elem.m_aDockedData.m_aPos.Y == nRowCol)
2046 : (elem.m_aDockedData.m_aPos.X == nRowCol);
2047 uno::Reference<ui::XUIElement> xUIElement(elem.m_xUIElement);
2048
2049 if (bSameRowCol && xUIElement.is())
2050 {
2051 uno::Reference<awt::XWindow> xWindow(xUIElement->getRealInterface(),
2052 uno::UNO_QUERY);
2053 if (xWindow.is())
2054 {
2055 SolarMutexGuard aGuard;
2056 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow(xWindow);
2057 uno::Reference<awt::XDockableWindow> xDockWindow(xWindow, uno::UNO_QUERY);
2058 if (pWindow && elem.m_bVisible && xDockWindow.is() && !elem.m_bFloating)
2059 aWindowVector.push_back(elem); // docked windows
2060 }
2061 }
2062 }
2063 }
2064 }
2065 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
2066
2067 // Initialize structure
2068 rRowColumnWindowData.aUIElementNames.clear();
2069 rRowColumnWindowData.aRowColumnWindows.clear();
2070 rRowColumnWindowData.aRowColumnWindowSizes.clear();
2071 rRowColumnWindowData.aRowColumnSpace.clear();
2072 rRowColumnWindowData.nVarSize = 0;
2073 rRowColumnWindowData.nStaticSize = 0;
2074 rRowColumnWindowData.nSpace = 0;
2075 rRowColumnWindowData.nRowColumn = nRowCol;
2076
2077 // Collect data from windows that are on the same row/column
2078 sal_Int32 j;
2079 sal_Int32 nLastPos( 0 );
2080
2081 const sal_uInt32 nCount = aWindowVector.size();
2082 for ( j = 0; j < sal_Int32( nCount); j++ )
2083 {
2084 const UIElement& rElement = aWindowVector[j];
2085 uno::Reference< awt::XWindow > xWindow;
2086 uno::Reference< ui::XUIElement > xUIElement( rElement.m_xUIElement );
2087 awt::Rectangle aPosSize;
2088 if ( !lcl_checkUIElement(xUIElement,aPosSize,xWindow) )
2089 continue;
2090
2091 sal_Int32 nSpace;
2092 if ( isHorizontalDockingArea( eDockingArea ))
2093 {
2094 nSpace = ( rElement.m_aDockedData.m_aPos.X - nLastPos );
2095
2096 // Calc space before an element and store it
2097 if ( rElement.m_aDockedData.m_aPos.X > nLastPos )
2098 rRowColumnWindowData.nSpace += nSpace;
2099 else
2100 nSpace = 0;
2101
2102 nLastPos = rElement.m_aDockedData.m_aPos.X + aPosSize.Width;
2103
2104 rRowColumnWindowData.aRowColumnWindowSizes.emplace_back(
2105 rElement.m_aDockedData.m_aPos.X, rElement.m_aDockedData.m_aPos.Y,
2106 aPosSize.Width, aPosSize.Height );
2107 if ( rRowColumnWindowData.nStaticSize < aPosSize.Height )
2108 rRowColumnWindowData.nStaticSize = aPosSize.Height;
2109 rRowColumnWindowData.nVarSize += aPosSize.Width;
2110 }
2111 else
2112 {
2113 // Calc space before an element and store it
2114 nSpace = ( rElement.m_aDockedData.m_aPos.Y - nLastPos );
2115 if ( rElement.m_aDockedData.m_aPos.Y > nLastPos )
2116 rRowColumnWindowData.nSpace += nSpace;
2117 else
2118 nSpace = 0;
2119
2120 nLastPos = rElement.m_aDockedData.m_aPos.Y + aPosSize.Height;
2121
2122 rRowColumnWindowData.aRowColumnWindowSizes.emplace_back(
2123 rElement.m_aDockedData.m_aPos.X, rElement.m_aDockedData.m_aPos.Y,
2124 aPosSize.Width, aPosSize.Height );
2125 if ( rRowColumnWindowData.nStaticSize < aPosSize.Width )
2126 rRowColumnWindowData.nStaticSize = aPosSize.Width;
2127 rRowColumnWindowData.nVarSize += aPosSize.Height;
2128 }
2129
2130 rRowColumnWindowData.aUIElementNames.push_back( rElement.m_aName );
2131 rRowColumnWindowData.aRowColumnWindows.push_back( xWindow );
2132 rRowColumnWindowData.aRowColumnSpace.push_back( nSpace );
2133 rRowColumnWindowData.nVarSize += nSpace;
2134 }
2135}
2136
2137::tools::Rectangle ToolbarLayoutManager::implts_getWindowRectFromRowColumn(
2138 ui::DockingArea DockingArea,
2139 const SingleRowColumnWindowData& rRowColumnWindowData,
2140 const ::Point& rMousePos,
2141 const OUString& rExcludeElementName )
2142{
2143 ::tools::Rectangle aWinRect;
2144
2145 if (( DockingArea < ui::DockingArea_DOCKINGAREA_TOP ) || ( DockingArea > ui::DockingArea_DOCKINGAREA_RIGHT ))
2146 DockingArea = ui::DockingArea_DOCKINGAREA_TOP;
2147
2148 if ( rRowColumnWindowData.aRowColumnWindows.empty() )
2149 return aWinRect;
2150 else
2151 {
2152 SolarMutexClearableGuard aReadLock;
2153 VclPtr<vcl::Window> pContainerWindow( VCLUnoHelper::GetWindow( m_xContainerWindow ));
2154 VclPtr<vcl::Window> pDockingAreaWindow( VCLUnoHelper::GetWindow( m_xDockAreaWindows[static_cast<int>(DockingArea)] ));
2155 aReadLock.clear();
2156
2157 // Calc correct position of the column/row rectangle to be able to compare it with mouse pos/tracking rect
2158 SolarMutexGuard aGuard;
2159
2160 // Retrieve output size from container Window
2161 if ( pDockingAreaWindow && pContainerWindow )
2162 {
2163 const sal_uInt32 nCount = rRowColumnWindowData.aRowColumnWindows.size();
2164 for ( sal_uInt32 i = 0; i < nCount; i++ )
2165 {
2166 awt::Rectangle aWindowRect = rRowColumnWindowData.aRowColumnWindows[i]->getPosSize();
2167 ::tools::Rectangle aRect( aWindowRect.X, aWindowRect.Y, aWindowRect.X+aWindowRect.Width, aWindowRect.Y+aWindowRect.Height );
2168 aRect.SetPos( pContainerWindow->ScreenToOutputPixel( pDockingAreaWindow->OutputToScreenPixel( aRect.TopLeft() )));
2169 if ( aRect.IsInside( rMousePos ))
2170 {
2171 // Check if we have found the excluded element. If yes, we have to provide an empty rectangle.
2172 // We prevent that a toolbar cannot be moved when the mouse pointer is inside its own rectangle!
2173 if ( rExcludeElementName != rRowColumnWindowData.aUIElementNames[i] )
2174 return aRect;
2175 else
2176 break;
2177 }
2178 }
2179 }
2180 }
2181
2182 return aWinRect;
2183}
2184
2185::tools::Rectangle ToolbarLayoutManager::implts_determineFrontDockingRect(
2186 ui::DockingArea eDockingArea,
2187 sal_Int32 nRowCol,
2188 const ::tools::Rectangle& rDockedElementRect,
2189 const OUString& rMovedElementName,
2190 const ::tools::Rectangle& rMovedElementRect )
2191{
2192 SingleRowColumnWindowData aRowColumnWindowData;
2193
2194 bool bHorzDockArea( isHorizontalDockingArea( eDockingArea ));
2195 implts_getDockingAreaElementInfoOnSingleRowCol( eDockingArea, nRowCol, aRowColumnWindowData );
2196 if ( aRowColumnWindowData.aRowColumnWindows.empty() )
2197 return rMovedElementRect;
2198 else
2199 {
2200 sal_Int32 nSpace( 0 );
2201 ::tools::Rectangle aFrontDockingRect( rMovedElementRect );
2202 const sal_uInt32 nCount = aRowColumnWindowData.aRowColumnWindows.size();
2203 for ( sal_uInt32 i = 0; i < nCount; i++ )
2204 {
2205 if ( bHorzDockArea )
2206 {
2207 if ( aRowColumnWindowData.aRowColumnWindowSizes[i].X >= rDockedElementRect.Left() )
2208 {
2209 nSpace += aRowColumnWindowData.aRowColumnSpace[i];
2210 break;
2211 }
2212 else if ( aRowColumnWindowData.aUIElementNames[i] == rMovedElementName )
2213 nSpace += aRowColumnWindowData.aRowColumnWindowSizes[i].Width +
2214 aRowColumnWindowData.aRowColumnSpace[i];
2215 else
2216 nSpace = 0;
2217 }
2218 else
2219 {
2220 if ( aRowColumnWindowData.aRowColumnWindowSizes[i].Y >= rDockedElementRect.Top() )
2221 {
2222 nSpace += aRowColumnWindowData.aRowColumnSpace[i];
2223 break;
2224 }
2225 else if ( aRowColumnWindowData.aUIElementNames[i] == rMovedElementName )
2226 nSpace += aRowColumnWindowData.aRowColumnWindowSizes[i].Height +
2227 aRowColumnWindowData.aRowColumnSpace[i];
2228 else
2229 nSpace = 0;
2230 }
2231 }
2232
2233 if ( nSpace > 0 )
2234 {
2235 sal_Int32 nMove = std::min( nSpace, static_cast<sal_Int32>(aFrontDockingRect.getWidth()) );
2236 if ( bHorzDockArea )
2237 aFrontDockingRect.Move( -nMove, 0 );
2238 else
2239 aFrontDockingRect.Move( 0, -nMove );
2240 }
2241
2242 return aFrontDockingRect;
2243 }
2244}
2245
2246void ToolbarLayoutManager::implts_findNextDockingPos( ui::DockingArea DockingArea, const ::Size& aUIElementSize, awt::Point& rVirtualPos, ::Point& rPixelPos )
2247{
2248 SolarMutexClearableGuard aReadLock;
2249 if (( DockingArea < ui::DockingArea_DOCKINGAREA_TOP ) || ( DockingArea > ui::DockingArea_DOCKINGAREA_RIGHT ))
2250 DockingArea = ui::DockingArea_DOCKINGAREA_TOP;
2251 uno::Reference< awt::XWindow > xDockingWindow( m_xDockAreaWindows[static_cast<int>(DockingArea)] );
2252 ::Size aDockingWinSize;
2253
2254 // Retrieve output size from container Window
2255 vcl::Window* pDockingWindow = VCLUnoHelper::GetWindow( xDockingWindow ).get();
2256 if ( pDockingWindow )
2257 aDockingWinSize = pDockingWindow->GetOutputSizePixel();
2258 aReadLock.clear();
2259
2260 sal_Int32 nFreeRowColPixelPos( 0 );
2261 sal_Int32 nMaxSpace( 0 );
2262 sal_Int32 nNeededSpace( 0 );
2263 sal_Int32 nTopDockingAreaSize( 0 );
2264
2265 if ( isHorizontalDockingArea( DockingArea ))
2266 {
2267 nMaxSpace = aDockingWinSize.Width();
2268 nNeededSpace = aUIElementSize.Width();
2269 }
2270 else
2271 {
2272 nMaxSpace = aDockingWinSize.Height();
2273 nNeededSpace = aUIElementSize.Height();
2274 nTopDockingAreaSize = implts_getTopBottomDockingAreaSizes().Width();
2275 }
2276
2277 std::vector< SingleRowColumnWindowData > aRowColumnsWindowData;
2278
2279 implts_getDockingAreaElementInfos( DockingArea, aRowColumnsWindowData );
2280 sal_Int32 nPixelPos( 0 );
2281 const sal_uInt32 nCount = aRowColumnsWindowData.size();
2282 for ( sal_uInt32 i = 0; i < nCount; i++ )
2283 {
2284 SingleRowColumnWindowData& rRowColumnWindowData = aRowColumnsWindowData[i];
2285
2286 if (( DockingArea == ui::DockingArea_DOCKINGAREA_BOTTOM ) ||
2287 ( DockingArea == ui::DockingArea_DOCKINGAREA_RIGHT ))
2288 nPixelPos += rRowColumnWindowData.nStaticSize;
2289
2290 if ((( nMaxSpace - rRowColumnWindowData.nVarSize ) >= nNeededSpace ) ||
2291 ( rRowColumnWindowData.nSpace >= nNeededSpace ))
2292 {
2293 // Check current row where we can find the needed space
2294 sal_Int32 nCurrPos( 0 );
2295 const sal_uInt32 nWindowSizesCount = rRowColumnWindowData.aRowColumnWindowSizes.size();
2296 for ( sal_uInt32 j = 0; j < nWindowSizesCount; j++ )
2297 {
2298 awt::Rectangle rRect = rRowColumnWindowData.aRowColumnWindowSizes[j];
2299 sal_Int32& rSpace = rRowColumnWindowData.aRowColumnSpace[j];
2300 if ( isHorizontalDockingArea( DockingArea ))
2301 {
2302 if ( rSpace >= nNeededSpace )
2303 {
2304 rVirtualPos = awt::Point( nCurrPos, rRowColumnWindowData.nRowColumn );
2305 if ( DockingArea == ui::DockingArea_DOCKINGAREA_TOP )
2306 rPixelPos = ::Point( nCurrPos, nPixelPos );
2307 else
2308 rPixelPos = ::Point( nCurrPos, aDockingWinSize.Height() - nPixelPos );
2309 return;
2310 }
2311 nCurrPos = rRect.X + rRect.Width;
2312 }
2313 else
2314 {
2315 if ( rSpace >= nNeededSpace )
2316 {
2317 rVirtualPos = awt::Point( rRowColumnWindowData.nRowColumn, nCurrPos );
2318 if ( DockingArea == ui::DockingArea_DOCKINGAREA_LEFT )
2319 rPixelPos = ::Point( nPixelPos, nTopDockingAreaSize + nCurrPos );
2320 else
2321 rPixelPos = ::Point( aDockingWinSize.Width() - nPixelPos , nTopDockingAreaSize + nCurrPos );
2322 return;
2323 }
2324 nCurrPos = rRect.Y + rRect.Height;
2325 }
2326 }
2327
2328 if (( nCurrPos + nNeededSpace ) <= nMaxSpace )
2329 {
2330 if ( isHorizontalDockingArea( DockingArea ))
2331 {
2332 rVirtualPos = awt::Point( nCurrPos, rRowColumnWindowData.nRowColumn );
2333 if ( DockingArea == ui::DockingArea_DOCKINGAREA_TOP )
2334 rPixelPos = ::Point( nCurrPos, nPixelPos );
2335 else
2336 rPixelPos = ::Point( nCurrPos, aDockingWinSize.Height() - nPixelPos );
2337 return;
2338 }
2339 else
2340 {
2341 rVirtualPos = awt::Point( rRowColumnWindowData.nRowColumn, nCurrPos );
2342 if ( DockingArea == ui::DockingArea_DOCKINGAREA_LEFT )
2343 rPixelPos = ::Point( nPixelPos, nTopDockingAreaSize + nCurrPos );
2344 else
2345 rPixelPos = ::Point( aDockingWinSize.Width() - nPixelPos , nTopDockingAreaSize + nCurrPos );
2346 return;
2347 }
2348 }
2349 }
2350
2351 if (( DockingArea == ui::DockingArea_DOCKINGAREA_TOP ) || ( DockingArea == ui::DockingArea_DOCKINGAREA_LEFT ))
2352 nPixelPos += rRowColumnWindowData.nStaticSize;
2353 }
2354
2355 sal_Int32 nNextFreeRowCol( 0 );
2356 sal_Int32 nRowColumnsCount = aRowColumnsWindowData.size();
2357 if ( nRowColumnsCount > 0 )
2358 nNextFreeRowCol = aRowColumnsWindowData[nRowColumnsCount-1].nRowColumn+1;
2359 else
2360 nNextFreeRowCol = 0;
2361
2362 if ( nNextFreeRowCol == 0 )
2363 {
2364 if ( DockingArea == ui::DockingArea_DOCKINGAREA_BOTTOM )
2365 nFreeRowColPixelPos = aDockingWinSize.Height() - aUIElementSize.Height();
2366 else if ( DockingArea == ui::DockingArea_DOCKINGAREA_RIGHT )
2367 nFreeRowColPixelPos = aDockingWinSize.Width() - aUIElementSize.Width();
2368 }
2369
2370 if ( isHorizontalDockingArea( DockingArea ))
2371 {
2372 rVirtualPos = awt::Point( 0, nNextFreeRowCol );
2373 if ( DockingArea == ui::DockingArea_DOCKINGAREA_TOP )
2374 rPixelPos = ::Point( 0, nFreeRowColPixelPos );
2375 else
2376 rPixelPos = ::Point( 0, aDockingWinSize.Height() - nFreeRowColPixelPos );
2377 }
2378 else
2379 {
2380 rVirtualPos = awt::Point( nNextFreeRowCol, 0 );
2381 rPixelPos = ::Point( aDockingWinSize.Width() - nFreeRowColPixelPos, 0 );
2382 }
2383}
2384
2385void ToolbarLayoutManager::implts_calcWindowPosSizeOnSingleRowColumn(
2386 sal_Int32 nDockingArea,
2387 sal_Int32 nOffset,
2388 SingleRowColumnWindowData& rRowColumnWindowData,
2389 const ::Size& rContainerSize )
2390{
2391 sal_Int32 nDiff(0);
2392 sal_Int32 nRCSpace( rRowColumnWindowData.nSpace );
2393 sal_Int32 nContainerClientSize(0);
2394
2395 if ( rRowColumnWindowData.aRowColumnWindows.empty() )
2396 return;
2397
2398 if ( isHorizontalDockingArea( nDockingArea ))
2399 {
2400 nContainerClientSize = rContainerSize.Width();
2401 nDiff = nContainerClientSize - rRowColumnWindowData.nVarSize;
2402 }
2403 else
2404 {
2405 sal_Int32 nTopDockingAreaSize = implts_getTopBottomDockingAreaSizes().Width();
2406 sal_Int32 nBottomDockingAreaSize = implts_getTopBottomDockingAreaSizes().Height();
2407 nContainerClientSize = ( rContainerSize.Height() - nTopDockingAreaSize - nBottomDockingAreaSize );
2408 nDiff = nContainerClientSize - rRowColumnWindowData.nVarSize;
2409 }
2410
2411 const sal_uInt32 nCount = rRowColumnWindowData.aRowColumnWindowSizes.size();
2412 if (( nDiff < 0 ) && ( nRCSpace > 0 ))
2413 {
2414 // First we try to reduce the size of blank space before/behind docked windows
2415 sal_Int32 i = nCount - 1;
2416 while ( i >= 0 )
2417 {
2418 sal_Int32 nSpace = rRowColumnWindowData.aRowColumnSpace[i];
2419 if ( nSpace >= -nDiff )
2420 {
2421 if ( isHorizontalDockingArea( nDockingArea ))
2422 {
2423 // Try to move this and all user elements behind with the calculated difference
2424 for ( sal_uInt32 j = i; j < nCount; j++ )
2425 rRowColumnWindowData.aRowColumnWindowSizes[j].X += nDiff;
2426 }
2427 else
2428 {
2429 // Try to move this and all user elements behind with the calculated difference
2430 for ( sal_uInt32 j = i; j < nCount; j++ )
2431 rRowColumnWindowData.aRowColumnWindowSizes[j].Y += nDiff;
2432 }
2433 nDiff = 0;
2434
2435 break;
2436 }
2437 else if ( nSpace > 0 )
2438 {
2439 if ( isHorizontalDockingArea( nDockingArea ))
2440 {
2441 // Try to move this and all user elements behind with the calculated difference
2442 for ( sal_uInt32 j = i; j < nCount; j++ )
2443 rRowColumnWindowData.aRowColumnWindowSizes[j].X -= nSpace;
2444 }
2445 else
2446 {
2447 // Try to move this and all user elements behind with the calculated difference
2448 for ( sal_uInt32 j = i; j < nCount; j++ )
2449 rRowColumnWindowData.aRowColumnWindowSizes[j].Y -= nSpace;
2450 }
2451 nDiff += nSpace;
2452 }
2453 --i;
2454 }
2455 }
2456
2457 // Check if we have to reduce further
2458 if ( nDiff < 0 )
2459 {
2460 // Now we have to reduce the size of certain docked windows
2461 sal_Int32 i = sal_Int32( nCount - 1 );
2462 while ( i >= 0 )
2463 {
2464 awt::Rectangle& rWinRect = rRowColumnWindowData.aRowColumnWindowSizes[i];
2465 ::Size aMinSize;
2466
2467 SolarMutexGuard aGuard;
2468 {
2469 uno::Reference< awt::XWindow > xWindow = rRowColumnWindowData.aRowColumnWindows[i];
2470 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
2471 if ( pWindow && pWindow->GetType() == WindowType::TOOLBOX )
2472 aMinSize = static_cast<ToolBox *>(pWindow.get())->CalcMinimumWindowSizePixel();
2473 }
2474
2475 if ( !aMinSize.IsEmpty() )
2476 {
2477 if ( isHorizontalDockingArea( nDockingArea ))
2478 {
2479 sal_Int32 nMaxReducation = rWinRect.Width - aMinSize.Width();
2480 if ( nMaxReducation >= -nDiff )
2481 {
2482 rWinRect.Width = rWinRect.Width + nDiff;
2483 nDiff = 0;
2484 }
2485 else
2486 {
2487 rWinRect.Width = aMinSize.Width();
2488 nDiff += nMaxReducation;
2489 }
2490
2491 // Try to move this and all user elements behind with the calculated difference
2492 for ( sal_uInt32 j = i; j < nCount; j++ )
2493 rRowColumnWindowData.aRowColumnWindowSizes[j].X += nDiff;
2494 }
2495 else
2496 {
2497 sal_Int32 nMaxReducation = rWinRect.Height - aMinSize.Height();
2498 if ( nMaxReducation >= -nDiff )
2499 {
2500 rWinRect.Height = rWinRect.Height + nDiff;
2501 nDiff = 0;
2502 }
2503 else
2504 {
2505 rWinRect.Height = aMinSize.Height();
2506 nDiff += nMaxReducation;
2507 }
2508
2509 // Try to move this and all user elements behind with the calculated difference
2510 for ( sal_uInt32 j = i; j < nCount; j++ )
2511 rRowColumnWindowData.aRowColumnWindowSizes[j].Y += nDiff;
2512 }
2513 }
2514
2515 if ( nDiff >= 0 )
2516 break;
2517
2518 --i;
2519 }
2520 }
2521
2522 SolarMutexClearableGuard aReadLock;
2523 VclPtr<vcl::Window> pDockAreaWindow = VCLUnoHelper::GetWindow( m_xDockAreaWindows[nDockingArea] );
2524 aReadLock.clear();
2525
2526 sal_Int32 nCurrPos( 0 );
2527
2528 SolarMutexGuard aGuard;
2529 for ( sal_uInt32 i = 0; i < nCount; i++ )
2530 {
2531 uno::Reference< awt::XWindow > xWindow = rRowColumnWindowData.aRowColumnWindows[i];
2532 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
2533 vcl::Window* pOldParentWindow = pWindow->GetParent();
2534
2535 if ( pDockAreaWindow != pOldParentWindow )
2536 pWindow->SetParent( pDockAreaWindow );
2537
2538 awt::Rectangle aWinRect = rRowColumnWindowData.aRowColumnWindowSizes[i];
2539 if ( isHorizontalDockingArea( nDockingArea ))
2540 {
2541 if ( aWinRect.X < nCurrPos )
2542 aWinRect.X = nCurrPos;
2543 pWindow->SetPosSizePixel( ::Point( aWinRect.X, nOffset ), ::Size( aWinRect.Width, rRowColumnWindowData.nStaticSize ));
2544 pWindow->Show( true, ShowFlags::NoFocusChange | ShowFlags::NoActivate );
2545 nCurrPos += ( aWinRect.X - nCurrPos ) + aWinRect.Width;
2546 }
2547 else
2548 {
2549 if ( aWinRect.Y < nCurrPos )
2550 aWinRect.Y = nCurrPos;
2551 pWindow->SetPosSizePixel( ::Point( nOffset, aWinRect.Y ), ::Size( rRowColumnWindowData.nStaticSize, aWinRect.Height ));
2552 pWindow->Show( true, ShowFlags::NoFocusChange | ShowFlags::NoActivate );
2553 nCurrPos += ( aWinRect.Y - nCurrPos ) + aWinRect.Height;
2554 }
2555 }
2556}
2557
2558void ToolbarLayoutManager::implts_setLayoutDirty()
2559{
2560 SolarMutexGuard g;
2561 m_bLayoutDirty = true;
2562}
2563
2564void ToolbarLayoutManager::implts_setLayoutInProgress( bool bInProgress )
2565{
2566 SolarMutexGuard g;
2567 m_bLayoutInProgress = bInProgress;
2568}
2569
2570::tools::Rectangle ToolbarLayoutManager::implts_calcHotZoneRect( const ::tools::Rectangle& rRect, sal_Int32 nHotZoneOffset )
2571{
2572 ::tools::Rectangle aRect( rRect );
2573
2574 aRect.AdjustLeft( -nHotZoneOffset );
2575 aRect.AdjustTop( -nHotZoneOffset );
2576 aRect.AdjustRight(nHotZoneOffset );
2577 aRect.AdjustBottom(nHotZoneOffset );
2578
2579 return aRect;
2580}
2581
2582void ToolbarLayoutManager::implts_calcDockingPosSize(
2583 UIElement& rUIElement,
2584 DockingOperation& rDockingOperation,
2585 ::tools::Rectangle& rTrackingRect,
2586 const Point& rMousePos )
2587{
2588 SolarMutexResettableGuard aReadLock;
2589 uno::Reference< awt::XWindow2 > xContainerWindow( m_xContainerWindow );
2590 ::Size aContainerWinSize;
2591 vcl::Window* pContainerWindow( nullptr );
2592 ::tools::Rectangle aDockingAreaOffsets( m_aDockingAreaOffsets );
2593 aReadLock.clear();
2594
2595 if ( !rUIElement.m_xUIElement.is() )
2596 {
2597 rTrackingRect = ::tools::Rectangle();
2598 return;
2599 }
2600
2601 {
2602 // Retrieve output size from container Window
2603 SolarMutexGuard aGuard;
2604 pContainerWindow = VCLUnoHelper::GetWindow( xContainerWindow ).get();
2605 aContainerWinSize = pContainerWindow->GetOutputSizePixel();
2606 }
2607
2608 vcl::Window* pDockingAreaWindow( nullptr );
2609 uno::Reference< awt::XWindow > xWindow( rUIElement.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
2610 uno::Reference< awt::XWindow > xDockingAreaWindow;
2611 ::tools::Rectangle aTrackingRect( rTrackingRect );
2612 ui::DockingArea eDockedArea( rUIElement.m_aDockedData.m_nDockedArea );
2613 sal_Int32 nTopDockingAreaSize( implts_getTopBottomDockingAreaSizes().Width() );
2614 sal_Int32 nBottomDockingAreaSize( implts_getTopBottomDockingAreaSizes().Height() );
2615 bool bHorizontalDockArea(( eDockedArea == ui::DockingArea_DOCKINGAREA_TOP ) ||
2616 ( eDockedArea == ui::DockingArea_DOCKINGAREA_BOTTOM ));
2617 sal_Int32 nMaxLeftRightDockAreaSize = aContainerWinSize.Height() -
2618 nTopDockingAreaSize -
2619 nBottomDockingAreaSize -
2620 aDockingAreaOffsets.Top() -
2621 aDockingAreaOffsets.Bottom();
2622 ::tools::Rectangle aDockingAreaRect;
2623
2624 aReadLock.reset();
2625 xDockingAreaWindow = m_xDockAreaWindows[static_cast<int>(eDockedArea)];
2626 aReadLock.clear();
2627
2628 {
2629 SolarMutexGuard aGuard;
2630 pDockingAreaWindow = VCLUnoHelper::GetWindow( xDockingAreaWindow ).get();
2631 VclPtr<vcl::Window> pDockWindow = VCLUnoHelper::GetWindow( xWindow );
2632 ToolBox* pToolBox( nullptr );
2633 if ( pDockWindow && pDockWindow->GetType() == WindowType::TOOLBOX )
2634 pToolBox = static_cast<ToolBox *>(pDockWindow.get());
2635
2636 aDockingAreaRect = ::tools::Rectangle( pDockingAreaWindow->GetPosPixel(), pDockingAreaWindow->GetSizePixel() );
2637 if ( pToolBox )
2638 {
2639 // docked toolbars always have one line
2640 ::Size aSize = pToolBox->CalcWindowSizePixel( 1, ImplConvertAlignment( eDockedArea ) );
2641 aTrackingRect.SetSize( ::Size( aSize.Width(), aSize.Height() ));
2642 }
2643 }
2644
2645 // default docking operation, dock on the given row/column
2646 bool bOpOutsideOfDockingArea( !aDockingAreaRect.IsInside( rMousePos ));
2647
2648 std::vector< SingleRowColumnWindowData > aRowColumnsWindowData;
2649
2650 rDockingOperation = DOCKOP_ON_COLROW;
2651 implts_getDockingAreaElementInfos( eDockedArea, aRowColumnsWindowData );
2652
2653 // determine current first row/column and last row/column
2654 sal_Int32 nMaxRowCol( -1 );
2655 sal_Int32 nMinRowCol( SAL_MAX_INT32((sal_Int32) 0x7FFFFFFF) );
2656 const sal_uInt32 nCount = aRowColumnsWindowData.size();
2657 for ( sal_uInt32 i = 0; i < nCount; i++ )
2658 {
2659 if ( aRowColumnsWindowData[i].nRowColumn > nMaxRowCol )
2660 nMaxRowCol = aRowColumnsWindowData[i].nRowColumn;
2661 if ( aRowColumnsWindowData[i].nRowColumn < nMinRowCol )
2662 nMinRowCol = aRowColumnsWindowData[i].nRowColumn;
2663 }
2664
2665 if ( !bOpOutsideOfDockingArea )
2666 {
2667 // docking inside our docking area
2668 sal_Int32 nIndex( -1 );
2669 sal_Int32 nRowCol( -1 );
2670 ::tools::Rectangle aWindowRect;
2671 ::tools::Rectangle aRowColumnRect;
2672
2673 const sal_uInt32 nWindowDataCount = aRowColumnsWindowData.size();
2674 for ( sal_uInt32 i = 0; i < nWindowDataCount; i++ )
2675 {
2676 ::tools::Rectangle aRect( aRowColumnsWindowData[i].aRowColumnRect.X,
2677 aRowColumnsWindowData[i].aRowColumnRect.Y,
2678 aRowColumnsWindowData[i].aRowColumnRect.X + aRowColumnsWindowData[i].aRowColumnRect.Width,
2679 aRowColumnsWindowData[i].aRowColumnRect.Y + aRowColumnsWindowData[i].aRowColumnRect.Height );
2680
2681 {
2682 // Calc correct position of the column/row rectangle to be able to compare it with mouse pos/tracking rect
2683 SolarMutexGuard aGuard;
2684 aRect.SetPos( pContainerWindow->ScreenToOutputPixel( pDockingAreaWindow->OutputToScreenPixel( aRect.TopLeft() )));
2685 }
2686
2687 bool bIsInsideRowCol( aRect.IsInside( rMousePos ) );
2688 if ( bIsInsideRowCol )
2689 {
2690 nIndex = i;
2691 nRowCol = aRowColumnsWindowData[i].nRowColumn;
2692 rDockingOperation = implts_determineDockingOperation( eDockedArea, aRect, rMousePos );
2693 aWindowRect = implts_getWindowRectFromRowColumn( eDockedArea, aRowColumnsWindowData[i], rMousePos, rUIElement.m_aName );
2694 aRowColumnRect = aRect;
2695 break;
2696 }
2697 }
2698
2699 OSL_ENSURE( ( nIndex >= 0 ) && ( nRowCol >= 0 ), "Impossible case - no row/column found but mouse pointer is inside our docking area" )do { if (true && (!(( nIndex >= 0 ) && ( nRowCol
>= 0 )))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/framework/source/layoutmanager/toolbarlayoutmanager.cxx"
":" "2699" ": "), "%s", "Impossible case - no row/column found but mouse pointer is inside our docking area"
); } } while (false)
;
2700 if (( nIndex >= 0 ) && ( nRowCol >= 0 ))
2701 {
2702 if ( rDockingOperation == DOCKOP_ON_COLROW )
2703 {
2704 if ( !aWindowRect.IsEmpty())
2705 {
2706 // Tracking rect is on a row/column and mouse is over a docked toolbar.
2707 // Determine if the tracking rect must be located before/after the docked toolbar.
2708
2709 ::tools::Rectangle aUIElementRect( aWindowRect );
2710 sal_Int32 nMiddle( bHorizontalDockArea ? ( aWindowRect.Left() + aWindowRect.getWidth() / 2 ) :
2711 ( aWindowRect.Top() + aWindowRect.getHeight() / 2 ));
2712 bool bInsertBefore( bHorizontalDockArea ? ( rMousePos.X() < nMiddle ) : ( rMousePos.Y() < nMiddle ));
2713 if ( bInsertBefore )
2714 {
2715 if ( bHorizontalDockArea )
2716 {
2717 sal_Int32 nSize = ::std::max( sal_Int32( 0 ), std::min( sal_Int32( aContainerWinSize.Width() - aWindowRect.Left() ),
2718 sal_Int32( aTrackingRect.getWidth() )));
2719 if ( nSize == 0 )
2720 nSize = aWindowRect.getWidth();
2721
2722 aUIElementRect.SetSize( ::Size( nSize, aWindowRect.getHeight() ));
2723 aWindowRect = implts_determineFrontDockingRect( eDockedArea, nRowCol, aWindowRect,rUIElement.m_aName, aUIElementRect );
2724
2725 // Set virtual position
2726 rUIElement.m_aDockedData.m_aPos.X = aWindowRect.Left();
2727 rUIElement.m_aDockedData.m_aPos.Y = nRowCol;
2728 }
2729 else
2730 {
2731 sal_Int32 nSize = ::std::max( sal_Int32( 0 ), std::min( sal_Int32(
2732 nTopDockingAreaSize + nMaxLeftRightDockAreaSize - aWindowRect.Top() ),
2733 sal_Int32( aTrackingRect.getHeight() )));
2734 if ( nSize == 0 )
2735 nSize = aWindowRect.getHeight();
2736
2737 aUIElementRect.SetSize( ::Size( aWindowRect.getWidth(), nSize ));
2738 aWindowRect = implts_determineFrontDockingRect( eDockedArea, nRowCol, aWindowRect, rUIElement.m_aName, aUIElementRect );
2739
2740 // Set virtual position
2741 sal_Int32 nPosY = pDockingAreaWindow->ScreenToOutputPixel(
2742 pContainerWindow->OutputToScreenPixel( aWindowRect.TopLeft() )).Y();
2743 rUIElement.m_aDockedData.m_aPos.X = nRowCol;
2744 rUIElement.m_aDockedData.m_aPos.Y = nPosY;
2745 }
2746
2747 rTrackingRect = aWindowRect;
2748 return;
2749 }
2750 else
2751 {
2752 if ( bHorizontalDockArea )
2753 {
2754 sal_Int32 nSize = ::std::max( sal_Int32( 0 ), std::min( sal_Int32(( aContainerWinSize.Width() ) - aWindowRect.Right() ),
2755 sal_Int32( aTrackingRect.getWidth() )));
2756 if ( nSize == 0 )
2757 {
2758 aUIElementRect.SetPos( ::Point( aContainerWinSize.Width() - aTrackingRect.getWidth(), aWindowRect.Top() ));
2759 aUIElementRect.SetSize( ::Size( aTrackingRect.getWidth(), aWindowRect.getHeight() ));
2760 rUIElement.m_aDockedData.m_aPos.X = aUIElementRect.Left();
2761
2762 }
2763 else
2764 {
2765 aUIElementRect.SetPos( ::Point( aWindowRect.Right(), aWindowRect.Top() ));
2766 aUIElementRect.SetSize( ::Size( nSize, aWindowRect.getHeight() ));
2767 rUIElement.m_aDockedData.m_aPos.X = aWindowRect.Right();
2768 }
2769
2770 // Set virtual position
2771 rUIElement.m_aDockedData.m_aPos.Y = nRowCol;
2772 }
2773 else
2774 {
2775 sal_Int32 nSize = ::std::max( sal_Int32( 0 ), std::min( sal_Int32( nTopDockingAreaSize + nMaxLeftRightDockAreaSize - aWindowRect.Bottom() ),
2776 sal_Int32( aTrackingRect.getHeight() )));
2777 aUIElementRect.SetPos( ::Point( aWindowRect.Left(), aWindowRect.Bottom() ));
2778 aUIElementRect.SetSize( ::Size( aWindowRect.getWidth(), nSize ));
2779
2780 // Set virtual position
2781 sal_Int32 nPosY( 0 );
2782 {
2783 SolarMutexGuard aGuard;
2784 nPosY = pDockingAreaWindow->ScreenToOutputPixel(
2785 pContainerWindow->OutputToScreenPixel( aWindowRect.BottomRight() )).Y();
2786 }
2787 rUIElement.m_aDockedData.m_aPos.X = nRowCol;
2788 rUIElement.m_aDockedData.m_aPos.Y = nPosY;
2789 }
2790
2791 rTrackingRect = aUIElementRect;
2792 return;
2793 }
2794 }
2795 else
2796 {
2797 implts_setTrackingRect( eDockedArea, rMousePos, aTrackingRect );
2798 rTrackingRect = implts_calcTrackingAndElementRect(
2799 eDockedArea, nRowCol, rUIElement,
2800 aTrackingRect, aRowColumnRect, aContainerWinSize );
2801 return;
2802 }
2803 }
2804 else
2805 {
2806 if ((( nRowCol == nMinRowCol ) && ( rDockingOperation == DOCKOP_BEFORE_COLROW )) ||
2807 (( nRowCol == nMaxRowCol ) && ( rDockingOperation == DOCKOP_AFTER_COLROW )))
2808 bOpOutsideOfDockingArea = true;
2809 else
2810 {
2811 // handle docking before/after a row
2812 implts_setTrackingRect( eDockedArea, rMousePos, aTrackingRect );
2813 rTrackingRect = implts_calcTrackingAndElementRect(
2814 eDockedArea, nRowCol, rUIElement,
2815 aTrackingRect, aRowColumnRect, aContainerWinSize );
2816
2817 sal_Int32 nOffsetX( 0 );
2818 sal_Int32 nOffsetY( 0 );
2819 if ( bHorizontalDockArea )
2820 nOffsetY = sal_Int32( floor( aRowColumnRect.getHeight() / 2.0 + 0.5 ));
2821 else
2822 nOffsetX = sal_Int32( floor( aRowColumnRect.getWidth() / 2.0 + 0.5 ));
2823
2824 if ( rDockingOperation == DOCKOP_BEFORE_COLROW )
2825 {
2826 if (( eDockedArea == ui::DockingArea_DOCKINGAREA_TOP ) || ( eDockedArea == ui::DockingArea_DOCKINGAREA_LEFT ))
2827 {
2828 // Docking before/after means move track rectangle half column/row.
2829 // As left and top are ordered 0...n instead of right and bottom
2830 // which uses n...0, we have to use negative values for top/left.
2831 nOffsetX *= -1;
2832 nOffsetY *= -1;
2833 }
2834 }
2835 else
2836 {
2837 if (( eDockedArea == ui::DockingArea_DOCKINGAREA_BOTTOM ) || ( eDockedArea == ui::DockingArea_DOCKINGAREA_RIGHT ))
2838 {
2839 // Docking before/after means move track rectangle half column/row.
2840 // As left and top are ordered 0...n instead of right and bottom
2841 // which uses n...0, we have to use negative values for top/left.
2842 nOffsetX *= -1;
2843 nOffsetY *= -1;
2844 }
2845 nRowCol++;
2846 }
2847
2848 if ( bHorizontalDockArea )
2849 rUIElement.m_aDockedData.m_aPos.Y = nRowCol;
2850 else
2851 rUIElement.m_aDockedData.m_aPos.X = nRowCol;
2852
2853 rTrackingRect.Move( nOffsetX, nOffsetY );
2854 rTrackingRect.SetSize( aTrackingRect.GetSize() );
2855 }
2856 }
2857 }
2858 }
2859
2860 // Docking outside of our docking window area =>
2861 // Users want to dock before/after first/last docked element or to an empty docking area
2862 if ( !bOpOutsideOfDockingArea )
2863 return;
2864
2865 // set correct size for docking
2866 implts_setTrackingRect( eDockedArea, rMousePos, aTrackingRect );
2867 rTrackingRect = aTrackingRect;
2868
2869 if ( bHorizontalDockArea )
2870 {
2871 sal_Int32 nPosX( std::max( sal_Int32( rTrackingRect.Left()), sal_Int32( 0 )));
2872 if (( nPosX + rTrackingRect.getWidth()) > aContainerWinSize.Width() )
2873 nPosX = std::min( nPosX,
2874 std::max( sal_Int32( aContainerWinSize.Width() - rTrackingRect.getWidth() ),
2875 sal_Int32( 0 )));
2876
2877 sal_Int32 nSize = std::min( aContainerWinSize.Width(), rTrackingRect.getWidth() );
2878 sal_Int32 nDockHeight = std::max( static_cast<sal_Int32>(aDockingAreaRect.getHeight()), sal_Int32( 0 ));
2879 if ( nDockHeight == 0 )
2880 {
2881 sal_Int32 nPosY( std::max( aDockingAreaRect.Top(), aDockingAreaRect.Bottom() ));
2882 if ( eDockedArea == ui::DockingArea_DOCKINGAREA_BOTTOM )
2883 nPosY -= rTrackingRect.getHeight();
2884 rTrackingRect.SetPos( Point( nPosX, nPosY ));
2885 rUIElement.m_aDockedData.m_aPos.Y = 0;
2886 }
2887 else if ( rMousePos.Y() < ( aDockingAreaRect.Top() + ( nDockHeight / 2 )))
2888 {
2889 rTrackingRect.SetPos( Point( nPosX, aDockingAreaRect.Top() - rTrackingRect.getHeight() ));
2890 if ( eDockedArea == ui::DockingArea_DOCKINGAREA_TOP )
2891 rUIElement.m_aDockedData.m_aPos.Y = 0;
2892 else
2893 rUIElement.m_aDockedData.m_aPos.Y = ( nMaxRowCol >= 0 ) ? nMaxRowCol+1 : 0;
2894 rDockingOperation = DOCKOP_BEFORE_COLROW;
2895 }
2896 else
2897 {
2898 rTrackingRect.SetPos( Point( nPosX, aDockingAreaRect.Bottom() ));
2899 if ( eDockedArea == ui::DockingArea_DOCKINGAREA_TOP )
2900 rUIElement.m_aDockedData.m_aPos.Y = ( nMaxRowCol >= 0 ) ? nMaxRowCol+1 : 0;
2901 else
2902 rUIElement.m_aDockedData.m_aPos.Y = 0;
2903 rDockingOperation = DOCKOP_AFTER_COLROW;
2904 }
2905 rTrackingRect.setWidth( nSize );
2906
2907 {
2908 SolarMutexGuard aGuard;
2909 nPosX = pDockingAreaWindow->ScreenToOutputPixel(
2910 pContainerWindow->OutputToScreenPixel( rTrackingRect.TopLeft() )).X();
2911 }
2912 rUIElement.m_aDockedData.m_aPos.X = nPosX;
2913 }
2914 else
2915 {
2916 sal_Int32 nMaxDockingAreaHeight = std::max<sal_Int32>( 0, nMaxLeftRightDockAreaSize );
2917 sal_Int32 nPosY( std::max<sal_Int32>( aTrackingRect.Top(), nTopDockingAreaSize ));
2918 if (( nPosY + aTrackingRect.getHeight()) > ( nTopDockingAreaSize + nMaxDockingAreaHeight ))
2919 nPosY = std::min( nPosY,
2920 std::max<sal_Int32>( nTopDockingAreaSize + ( nMaxDockingAreaHeight - aTrackingRect.getHeight() ),
2921 nTopDockingAreaSize ));
2922
2923 sal_Int32 nSize = std::min( nMaxDockingAreaHeight, static_cast<sal_Int32>(aTrackingRect.getHeight()) );
2924 sal_Int32 nDockWidth = std::max( static_cast<sal_Int32>(aDockingAreaRect.getWidth()), sal_Int32( 0 ));
2925 if ( nDockWidth == 0 )
2926 {
2927 sal_Int32 nPosX( std::max( aDockingAreaRect.Left(), aDockingAreaRect.Right() ));
2928 if ( eDockedArea == ui::DockingArea_DOCKINGAREA_RIGHT )
2929 nPosX -= rTrackingRect.getWidth();
2930 rTrackingRect.SetPos( Point( nPosX, nPosY ));
2931 rUIElement.m_aDockedData.m_aPos.X = 0;
2932 }
2933 else if ( rMousePos.X() < ( aDockingAreaRect.Left() + ( nDockWidth / 2 )))
2934 {
2935 rTrackingRect.SetPos( Point( aDockingAreaRect.Left() - rTrackingRect.getWidth(), nPosY ));
2936 if ( eDockedArea == ui::DockingArea_DOCKINGAREA_LEFT )
2937 rUIElement.m_aDockedData.m_aPos.X = 0;
2938 else
2939 rUIElement.m_aDockedData.m_aPos.X = ( nMaxRowCol >= 0 ) ? nMaxRowCol+1 : 0;
2940 rDockingOperation = DOCKOP_BEFORE_COLROW;
2941 }
2942 else
2943 {
2944 rTrackingRect.SetPos( Point( aDockingAreaRect.Right(), nPosY ));
2945 if ( eDockedArea == ui::DockingArea_DOCKINGAREA_LEFT )
2946 rUIElement.m_aDockedData.m_aPos.X = ( nMaxRowCol >= 0 ) ? nMaxRowCol+1 : 0;
2947 else
2948 rUIElement.m_aDockedData.m_aPos.X = 0;
2949 rDockingOperation = DOCKOP_AFTER_COLROW;
2950 }
2951 rTrackingRect.setHeight( nSize );
2952
2953 {
2954 SolarMutexGuard aGuard;
2955 nPosY = pDockingAreaWindow->ScreenToOutputPixel(
2956 pContainerWindow->OutputToScreenPixel( rTrackingRect.TopLeft() )).Y();
2957 }
2958 rUIElement.m_aDockedData.m_aPos.Y = nPosY;
2959 }
2960}
2961
2962framework::ToolbarLayoutManager::DockingOperation ToolbarLayoutManager::implts_determineDockingOperation(
2963 ui::DockingArea DockingArea,
2964 const ::tools::Rectangle& rRowColRect,
2965 const Point& rMousePos )
2966{
2967 constexpr sal_Int32 nHorzVerticalRegionSize = 6;
2968 constexpr sal_Int32 nHorzVerticalMoveRegion = 4;
2969
2970 if ( rRowColRect.IsInside( rMousePos ))
2971 {
2972 if ( isHorizontalDockingArea( DockingArea ))
2973 {
2974 sal_Int32 nRegion = rRowColRect.getHeight() / nHorzVerticalRegionSize;
2975 sal_Int32 nPosY = rRowColRect.Top() + nRegion;
2976
2977 if ( rMousePos.Y() < nPosY )
2978 return ( DockingArea == ui::DockingArea_DOCKINGAREA_TOP ) ? DOCKOP_BEFORE_COLROW : DOCKOP_AFTER_COLROW;
2979 else if ( rMousePos.Y() < ( nPosY + nRegion*nHorzVerticalMoveRegion ))
2980 return DOCKOP_ON_COLROW;
2981 else
2982 return ( DockingArea == ui::DockingArea_DOCKINGAREA_TOP ) ? DOCKOP_AFTER_COLROW : DOCKOP_BEFORE_COLROW;
2983 }
2984 else
2985 {
2986 sal_Int32 nRegion = rRowColRect.getWidth() / nHorzVerticalRegionSize;
2987 sal_Int32 nPosX = rRowColRect.Left() + nRegion;
2988
2989 if ( rMousePos.X() < nPosX )
2990 return ( DockingArea == ui::DockingArea_DOCKINGAREA_LEFT ) ? DOCKOP_BEFORE_COLROW : DOCKOP_AFTER_COLROW;
2991 else if ( rMousePos.X() < ( nPosX + nRegion*nHorzVerticalMoveRegion ))
2992 return DOCKOP_ON_COLROW;
2993 else
2994 return ( DockingArea == ui::DockingArea_DOCKINGAREA_LEFT ) ? DOCKOP_AFTER_COLROW : DOCKOP_BEFORE_COLROW;
2995 }
2996 }
2997 else
2998 return DOCKOP_ON_COLROW;
2999}
3000
3001::tools::Rectangle ToolbarLayoutManager::implts_calcTrackingAndElementRect(
3002 ui::DockingArea eDockingArea,
3003 sal_Int32 nRowCol,
3004 UIElement& rUIElement,
3005 const ::tools::Rectangle& rTrackingRect,
3006 const ::tools::Rectangle& rRowColumnRect,
3007 const ::Size& rContainerWinSize )
3008{
3009 SolarMutexResettableGuard aReadGuard;
3010 ::tools::Rectangle aDockingAreaOffsets( m_aDockingAreaOffsets );
3011 aReadGuard.clear();
3012
3013 bool bHorizontalDockArea( isHorizontalDockingArea( eDockingArea ));
3014
3015 sal_Int32 nTopDockingAreaSize( implts_getTopBottomDockingAreaSizes().Width() );
3016 sal_Int32 nBottomDockingAreaSize( implts_getTopBottomDockingAreaSizes().Height() );
3017
3018 sal_Int32 nMaxLeftRightDockAreaSize = rContainerWinSize.Height() -
3019 nTopDockingAreaSize -
3020 nBottomDockingAreaSize -
3021 aDockingAreaOffsets.Top() -
3022 aDockingAreaOffsets.Bottom();
3023
3024 ::tools::Rectangle aTrackingRect( rTrackingRect );
3025 if ( bHorizontalDockArea )
3026 {
3027 sal_Int32 nPosX( std::max( sal_Int32( rTrackingRect.Left()), sal_Int32( 0 )));
3028 if (( nPosX + rTrackingRect.getWidth()) > rContainerWinSize.Width() )
3029 nPosX = std::min( nPosX,
3030 std::max( sal_Int32( rContainerWinSize.Width() - rTrackingRect.getWidth() ),
3031 sal_Int32( 0 )));
3032
3033 sal_Int32 nSize = std::min( rContainerWinSize.Width(), rTrackingRect.getWidth() );
3034
3035 aTrackingRect.SetPos( ::Point( nPosX, rRowColumnRect.Top() ));
3036 aTrackingRect.setWidth( nSize );
3037 aTrackingRect.setHeight( rRowColumnRect.getHeight() );
3038
3039 // Set virtual position
3040 rUIElement.m_aDockedData.m_aPos.X = nPosX;
3041 rUIElement.m_aDockedData.m_aPos.Y = nRowCol;
3042 }
3043 else
3044 {
3045 sal_Int32 nMaxDockingAreaHeight = std::max<sal_Int32>( 0, nMaxLeftRightDockAreaSize );
3046
3047 sal_Int32 nPosY( std::max<sal_Int32>( aTrackingRect.Top(), nTopDockingAreaSize ));
3048 if (( nPosY + aTrackingRect.getHeight()) > ( nTopDockingAreaSize + nMaxDockingAreaHeight ))
3049 nPosY = std::min( nPosY,
3050 std::max<sal_Int32>( nTopDockingAreaSize + ( nMaxDockingAreaHeight - aTrackingRect.getHeight() ),
3051 nTopDockingAreaSize ));
3052
3053 sal_Int32 nSize = std::min( nMaxDockingAreaHeight, static_cast<sal_Int32>(aTrackingRect.getHeight()) );
3054
3055 aTrackingRect.SetPos( ::Point( rRowColumnRect.Left(), nPosY ));
3056 aTrackingRect.setWidth( rRowColumnRect.getWidth() );
3057 aTrackingRect.setHeight( nSize );
3058
3059 aReadGuard.reset();
3060 uno::Reference< awt::XWindow > xDockingAreaWindow( m_xDockAreaWindows[static_cast<int>(eDockingArea)] );
3061 uno::Reference< awt::XWindow2 > xContainerWindow( m_xContainerWindow );
3062 aReadGuard.clear();
3063
3064 sal_Int32 nDockPosY( 0 );
3065 {
3066 SolarMutexGuard aGuard;
3067 vcl::Window* pDockingAreaWindow = VCLUnoHelper::GetWindow( xDockingAreaWindow ).get();
3068 VclPtr<vcl::Window> pContainerWindow = VCLUnoHelper::GetWindow( xContainerWindow );
3069 nDockPosY = pDockingAreaWindow->ScreenToOutputPixel( pContainerWindow->OutputToScreenPixel( ::Point( 0, nPosY ))).Y();
3070 }
3071
3072 // Set virtual position
3073 rUIElement.m_aDockedData.m_aPos.X = nRowCol;
3074 rUIElement.m_aDockedData.m_aPos.Y = nDockPosY;
3075 }
3076
3077 return aTrackingRect;
3078}
3079
3080void ToolbarLayoutManager::implts_setTrackingRect( ui::DockingArea eDockingArea, const ::Point& rMousePos, ::tools::Rectangle& rTrackingRect )
3081{
3082 ::Point aPoint( rTrackingRect.TopLeft());
3083 if ( isHorizontalDockingArea( eDockingArea ))
3084 aPoint.setX( rMousePos.X() );
3085 else
3086 aPoint.setY( rMousePos.Y() );
3087 rTrackingRect.SetPos( aPoint );
3088}
3089
3090void ToolbarLayoutManager::implts_renumberRowColumnData(
3091 ui::DockingArea eDockingArea,
3092 const UIElement& rUIElement )
3093{
3094 SolarMutexClearableGuard aReadLock;
3095 uno::Reference< container::XNameAccess > xPersistentWindowState( m_xPersistentWindowState );
3096 aReadLock.clear();
3097
3098 bool bHorzDockingArea( isHorizontalDockingArea( eDockingArea ));
3099 sal_Int32 nRowCol( bHorzDockingArea ? rUIElement.m_aDockedData.m_aPos.Y : rUIElement.m_aDockedData.m_aPos.X );
3100
3101 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
3102 {
3103 SolarMutexGuard aWriteLock;
3104 for (auto& elem : m_aUIElements)
3105 {
3106 if ((elem.m_aDockedData.m_nDockedArea == eDockingArea)
3107 && (elem.m_aName != rUIElement.m_aName))
3108 {
3109 // Don't change toolbars without a valid docking position!
3110 if (isDefaultPos(elem.m_aDockedData.m_aPos))
3111 continue;
3112
3113 sal_Int32 nWindowRowCol
3114 = bHorzDockingArea ? elem.m_aDockedData.m_aPos.Y : elem.m_aDockedData.m_aPos.X;
3115 if (nWindowRowCol >= nRowCol)
3116 {
3117 if (bHorzDockingArea)
3118 elem.m_aDockedData.m_aPos.Y += 1;
3119 else
3120 elem.m_aDockedData.m_aPos.X += 1;
3121 }
3122 }
3123 }
3124 }
3125 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
3126
3127 // We have to change the persistent window state part
3128 if ( !xPersistentWindowState.is() )
3129 return;
3130
3131 try
3132 {
3133 const uno::Sequence< OUString > aWindowElements = xPersistentWindowState->getElementNames();
3134 for ( OUString const & rWindowElementName : aWindowElements )
3135 {
3136 if ( rUIElement.m_aName != rWindowElementName )
3137 {
3138 try
3139 {
3140 uno::Sequence< beans::PropertyValue > aPropValueSeq;
3141 awt::Point aDockedPos;
3142 ui::DockingArea nDockedArea( ui::DockingArea_DOCKINGAREA_DEFAULT );
3143
3144 xPersistentWindowState->getByName( rWindowElementName ) >>= aPropValueSeq;
3145 for ( beans::PropertyValue const & rProp : std::as_const(aPropValueSeq) )
3146 {
3147 if ( rProp.Name == WINDOWSTATE_PROPERTY_DOCKINGAREA"DockingArea" )
3148 rProp.Value >>= nDockedArea;
3149 else if ( rProp.Name == WINDOWSTATE_PROPERTY_DOCKPOS"DockPos" )
3150 rProp.Value >>= aDockedPos;
3151 }
3152
3153 // Don't change toolbars without a valid docking position!
3154 if ( isDefaultPos( aDockedPos ))
3155 continue;
3156
3157 sal_Int32 nWindowRowCol = bHorzDockingArea ? aDockedPos.Y : aDockedPos.X;
3158 if (( nDockedArea == eDockingArea ) && ( nWindowRowCol >= nRowCol ))
3159 {
3160 if ( bHorzDockingArea )
3161 aDockedPos.Y += 1;
3162 else
3163 aDockedPos.X += 1;
3164
3165 uno::Reference< container::XNameReplace > xReplace( xPersistentWindowState, uno::UNO_QUERY );
3166 xReplace->replaceByName( rWindowElementName, makeAny( aPropValueSeq ));
3167 }
3168 }
3169 catch (const uno::Exception&)
3170 {
3171 }
3172 }
3173 }
3174 }
3175 catch (const uno::Exception&)
3176 {
3177 }
3178}
3179
3180// XWindowListener
3181
3182void SAL_CALL ToolbarLayoutManager::windowResized( const awt::WindowEvent& aEvent )
3183{
3184 SolarMutexClearableGuard aWriteLock;
3185 bool bLocked( m_bDockingInProgress );
3186 bool bLayoutInProgress( m_bLayoutInProgress );
3187 aWriteLock.clear();
3188
3189 // Do not do anything if we are in the middle of a docking process. This would interfere all other
3190 // operations. We will store the new position and size in the docking handlers.
3191 // Do not do anything if we are in the middle of our layouting process. We will adapt the position
3192 // and size of the user interface elements.
3193 if ( bLocked || bLayoutInProgress )
3194 return;
3195
3196 bool bNotify( false );
3197 uno::Reference< awt::XWindow > xWindow( aEvent.Source, uno::UNO_QUERY );
3198
3199 UIElement aUIElement = implts_findToolbar( aEvent.Source );
3200 if ( aUIElement.m_xUIElement.is() )
3201 {
3202 if ( aUIElement.m_bFloating )
3203 {
3204 uno::Reference< awt::XWindow2 > xWindow2( xWindow, uno::UNO_QUERY );
3205
3206 if( xWindow2.is() )
3207 {
3208 awt::Rectangle aPos = xWindow2->getPosSize();
3209 awt::Size aSize = xWindow2->getOutputSize(); // always use output size for consistency
3210 bool bVisible = xWindow2->isVisible();
3211
3212 // update element data
3213 aUIElement.m_aFloatingData.m_aPos = awt::Point(aPos.X, aPos.Y);
3214 aUIElement.m_aFloatingData.m_aSize = aSize;
3215 aUIElement.m_bVisible = bVisible;
3216 }
3217
3218 implts_writeWindowStateData( aUIElement );
3219 }
3220 else
3221 {
3222 implts_setLayoutDirty();
3223 bNotify = true;
3224 }
3225 }
3226
3227 if ( bNotify )
3228 m_pParentLayouter->requestLayout();
3229}
3230
3231void SAL_CALL ToolbarLayoutManager::windowMoved( const awt::WindowEvent& /*aEvent*/ )
3232{
3233}
3234
3235void SAL_CALL ToolbarLayoutManager::windowShown( const lang::EventObject& /*aEvent*/ )
3236{
3237}
3238
3239void SAL_CALL ToolbarLayoutManager::windowHidden( const lang::EventObject& /*aEvent*/ )
3240{
3241}
3242
3243// XDockableWindowListener
3244
3245void SAL_CALL ToolbarLayoutManager::startDocking( const awt::DockingEvent& e )
3246{
3247 bool bWinFound( false );
3248
3249 SolarMutexClearableGuard aReadGuard;
3250 uno::Reference< awt::XWindow2 > xContainerWindow( m_xContainerWindow );
3251 uno::Reference< awt::XWindow2 > xWindow( e.Source, uno::UNO_QUERY );
3252 aReadGuard.clear();
3253
3254 UIElement aUIElement = implts_findToolbar( e.Source );
3255
3256 if ( aUIElement.m_xUIElement.is() && xWindow.is() )
3257 {
3258 bWinFound = true;
3259 uno::Reference< awt::XDockableWindow > xDockWindow( xWindow, uno::UNO_QUERY );
3260 if ( xDockWindow->isFloating() )
3261 {
3262 awt::Rectangle aPos = xWindow->getPosSize();
3263 awt::Size aSize = xWindow->getOutputSize();
3264
3265 aUIElement.m_aFloatingData.m_aPos = awt::Point(aPos.X, aPos.Y);
3266 aUIElement.m_aFloatingData.m_aSize = aSize;
3267
3268 SolarMutexGuard aGuard;
3269
3270 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
3271 if ( pWindow && pWindow->GetType() == WindowType::TOOLBOX )
3272 {
3273 ToolBox* pToolBox = static_cast<ToolBox *>(pWindow.get());
3274 aUIElement.m_aFloatingData.m_nLines = pToolBox->GetFloatingLines();
3275 aUIElement.m_aFloatingData.m_bIsHorizontal = isToolboxHorizontalAligned( pToolBox );
3276 }
3277 }
3278 }
3279
3280 SolarMutexGuard g;
3281 m_bDockingInProgress = bWinFound;
3282 m_aDockUIElement = aUIElement;
3283 m_aDockUIElement.m_bUserActive = true;
3284}
3285
3286awt::DockingData SAL_CALL ToolbarLayoutManager::docking( const awt::DockingEvent& e )
3287{
3288 constexpr sal_Int32 MAGNETIC_DISTANCE_UNDOCK = 25;
3289 constexpr sal_Int32 MAGNETIC_DISTANCE_DOCK = 20;
3290
3291 SolarMutexClearableGuard aReadLock;
3292 awt::DockingData aDockingData;
3293 uno::Reference< awt::XDockableWindow > xDockWindow( e.Source, uno::UNO_QUERY );
3294 uno::Reference< awt::XWindow > xWindow( e.Source, uno::UNO_QUERY );
3295 uno::Reference< awt::XWindow > xTopDockingWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_TOP)] );
3296 uno::Reference< awt::XWindow > xLeftDockingWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_LEFT)] );
3297 uno::Reference< awt::XWindow > xRightDockingWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_RIGHT)] );
3298 uno::Reference< awt::XWindow > xBottomDockingWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_BOTTOM)] );
3299 uno::Reference< awt::XWindow2 > xContainerWindow( m_xContainerWindow );
3300 UIElement aUIDockingElement( m_aDockUIElement );
3301
3302 bool bDockingInProgress( m_bDockingInProgress );
3303 aReadLock.clear();
3304
3305 if ( bDockingInProgress )
3306 aDockingData.TrackingRectangle = e.TrackingRectangle;
3307
3308 if ( bDockingInProgress && xDockWindow.is() && xWindow.is() )
3309 {
3310 try
3311 {
3312 SolarMutexGuard aGuard;
3313
3314 DockingOperation eDockingOperation( DOCKOP_ON_COLROW );
3315 ui::DockingArea eDockingArea( ui::DockingArea(-1) ); // none
3316 sal_Int32 nMagneticZone( aUIDockingElement.m_bFloating ? MAGNETIC_DISTANCE_DOCK : MAGNETIC_DISTANCE_UNDOCK );
3317 ::tools::Rectangle aTrackingRect( e.TrackingRectangle.X, e.TrackingRectangle.Y,
3318 ( e.TrackingRectangle.X + e.TrackingRectangle.Width ),
3319 ( e.TrackingRectangle.Y + e.TrackingRectangle.Height ));
3320
3321 awt::Rectangle aTmpRect = xTopDockingWindow->getPosSize();
3322 ::tools::Rectangle aTopDockRect( aTmpRect.X, aTmpRect.Y, aTmpRect.Width, aTmpRect.Height );
3323 ::tools::Rectangle aHotZoneTopDockRect( implts_calcHotZoneRect( aTopDockRect, nMagneticZone ));
3324
3325 aTmpRect = xBottomDockingWindow->getPosSize();
3326 ::tools::Rectangle aBottomDockRect( aTmpRect.X, aTmpRect.Y, ( aTmpRect.X + aTmpRect.Width), ( aTmpRect.Y + aTmpRect.Height ));
3327 ::tools::Rectangle aHotZoneBottomDockRect( implts_calcHotZoneRect( aBottomDockRect, nMagneticZone ));
3328
3329 aTmpRect = xLeftDockingWindow->getPosSize();
3330 ::tools::Rectangle aLeftDockRect( aTmpRect.X, aTmpRect.Y, ( aTmpRect.X + aTmpRect.Width ), ( aTmpRect.Y + aTmpRect.Height ));
3331 ::tools::Rectangle aHotZoneLeftDockRect( implts_calcHotZoneRect( aLeftDockRect, nMagneticZone ));
3332
3333 aTmpRect = xRightDockingWindow->getPosSize();
3334 ::tools::Rectangle aRightDockRect( aTmpRect.X, aTmpRect.Y, ( aTmpRect.X + aTmpRect.Width ), ( aTmpRect.Y + aTmpRect.Height ));
3335 ::tools::Rectangle aHotZoneRightDockRect( implts_calcHotZoneRect( aRightDockRect, nMagneticZone ));
3336
3337 VclPtr<vcl::Window> pContainerWindow( VCLUnoHelper::GetWindow( xContainerWindow ) );
3338 ::Point aMousePos( pContainerWindow->ScreenToOutputPixel( ::Point( e.MousePos.X, e.MousePos.Y )));
3339
3340 if ( aHotZoneTopDockRect.IsInside( aMousePos ))
3341 eDockingArea = ui::DockingArea_DOCKINGAREA_TOP;
3342 else if ( aHotZoneBottomDockRect.IsInside( aMousePos ))
3343 eDockingArea = ui::DockingArea_DOCKINGAREA_BOTTOM;
3344 else if ( aHotZoneLeftDockRect.IsInside( aMousePos ))
3345 eDockingArea = ui::DockingArea_DOCKINGAREA_LEFT;
3346 else if ( aHotZoneRightDockRect.IsInside( aMousePos ))
3347 eDockingArea = ui::DockingArea_DOCKINGAREA_RIGHT;
3348
3349 // Higher priority for movements inside the real docking area
3350 if ( aTopDockRect.IsInside( aMousePos ))
3351 eDockingArea = ui::DockingArea_DOCKINGAREA_TOP;
3352 else if ( aBottomDockRect.IsInside( aMousePos ))
3353 eDockingArea = ui::DockingArea_DOCKINGAREA_BOTTOM;
3354 else if ( aLeftDockRect.IsInside( aMousePos ))
3355 eDockingArea = ui::DockingArea_DOCKINGAREA_LEFT;
3356 else if ( aRightDockRect.IsInside( aMousePos ))
3357 eDockingArea = ui::DockingArea_DOCKINGAREA_RIGHT;
3358
3359 // Determine if we have a toolbar and set alignment according to the docking area!
3360 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
3361 ToolBox* pToolBox = nullptr;
3362 if ( pWindow && pWindow->GetType() == WindowType::TOOLBOX )
3363 pToolBox = static_cast<ToolBox *>(pWindow.get());
3364
3365 if ( eDockingArea != ui::DockingArea(-1) )
3366 {
3367 if ( eDockingArea == ui::DockingArea_DOCKINGAREA_TOP )
3368 {
3369 aUIDockingElement.m_aDockedData.m_nDockedArea = ui::DockingArea_DOCKINGAREA_TOP;
3370 aUIDockingElement.m_bFloating = false;
3371 }
3372 else if ( eDockingArea == ui::DockingArea_DOCKINGAREA_BOTTOM )
3373 {
3374 aUIDockingElement.m_aDockedData.m_nDockedArea = ui::DockingArea_DOCKINGAREA_BOTTOM;
3375 aUIDockingElement.m_bFloating = false;
3376 }
3377 else if ( eDockingArea == ui::DockingArea_DOCKINGAREA_LEFT )
3378 {
3379 aUIDockingElement.m_aDockedData.m_nDockedArea = ui::DockingArea_DOCKINGAREA_LEFT;
3380 aUIDockingElement.m_bFloating = false;
3381 }
3382 else if ( eDockingArea == ui::DockingArea_DOCKINGAREA_RIGHT )
3383 {
3384 aUIDockingElement.m_aDockedData.m_nDockedArea = ui::DockingArea_DOCKINGAREA_RIGHT;
3385 aUIDockingElement.m_bFloating = false;
3386 }
3387
3388 ::Point aOutputPos = pContainerWindow->ScreenToOutputPixel( aTrackingRect.TopLeft() );
3389 aTrackingRect.SetPos( aOutputPos );
3390
3391 ::tools::Rectangle aNewDockingRect( aTrackingRect );
3392
3393 implts_calcDockingPosSize( aUIDockingElement, eDockingOperation, aNewDockingRect, aMousePos );
3394
3395 ::Point aScreenPos = pContainerWindow->OutputToScreenPixel( aNewDockingRect.TopLeft() );
3396 aDockingData.TrackingRectangle = awt::Rectangle( aScreenPos.X(), aScreenPos.Y(),
3397 aNewDockingRect.getWidth(), aNewDockingRect.getHeight() );
3398 }
3399 else if (pToolBox)
3400 {
3401 bool bIsHorizontal = isToolboxHorizontalAligned( pToolBox );
3402 awt::Size aFloatSize = aUIDockingElement.m_aFloatingData.m_aSize;
3403 if ( aFloatSize.Width > 0 && aFloatSize.Height > 0 )
3404 {
3405 aUIDockingElement.m_aFloatingData.m_aPos = AWTPoint(pContainerWindow->ScreenToOutputPixel(VCLPoint(e.MousePos)));
3406 aDockingData.TrackingRectangle.Height = aFloatSize.Height;
3407 aDockingData.TrackingRectangle.Width = aFloatSize.Width;
3408 }
3409 else
3410 {
3411 aFloatSize = AWTSize(pToolBox->CalcWindowSizePixel());
3412 if ( !bIsHorizontal )
3413 {
3414 // Floating toolbars are always horizontal aligned! We have to swap
3415 // width/height if we have a vertical aligned toolbar.
3416 sal_Int32 nTemp = aFloatSize.Height;
3417 aFloatSize.Height = aFloatSize.Width;
3418 aFloatSize.Width = nTemp;
3419 }
3420
3421 aDockingData.TrackingRectangle.Height = aFloatSize.Height;
3422 aDockingData.TrackingRectangle.Width = aFloatSize.Width;
3423
3424 // For the first time we don't have any data about the floating size of a toolbar.
3425 // We calculate it and store it for later use.
3426 aUIDockingElement.m_aFloatingData.m_aPos = AWTPoint(pContainerWindow->ScreenToOutputPixel(VCLPoint(e.MousePos)));
3427 aUIDockingElement.m_aFloatingData.m_aSize = aFloatSize;
3428 aUIDockingElement.m_aFloatingData.m_nLines = pToolBox->GetFloatingLines();
3429 aUIDockingElement.m_aFloatingData.m_bIsHorizontal = isToolboxHorizontalAligned( pToolBox );
3430 }
3431 aDockingData.TrackingRectangle.X = e.MousePos.X;
3432 aDockingData.TrackingRectangle.Y = e.MousePos.Y;
3433 }
3434
3435 aDockingData.bFloating = ( eDockingArea == ui::DockingArea(-1) );
3436
3437 // Write current data to the member docking progress data
3438 SolarMutexGuard g;
3439 m_aDockUIElement.m_bFloating = aDockingData.bFloating;
3440 if ( !aDockingData.bFloating )
3441 {
3442 m_aDockUIElement.m_aDockedData = aUIDockingElement.m_aDockedData;
3443
3444 m_eDockOperation = eDockingOperation;
3445 }
3446 else
3447 m_aDockUIElement.m_aFloatingData = aUIDockingElement.m_aFloatingData;
3448 }
3449 catch (const uno::Exception&)
3450 {
3451 }
3452 }
3453
3454 return aDockingData;
3455}
3456
3457void SAL_CALL ToolbarLayoutManager::endDocking( const awt::EndDockingEvent& e )
3458{
3459 if (e.bCancelled)
3460 return;
3461
3462 bool bDockingInProgress( false );
3463 bool bStartDockFloated( false );
3464 bool bFloating( false );
3465 UIElement aUIDockingElement;
3466
3467 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
3468 SolarMutexResettableGuard aWriteLock;
3469 bDockingInProgress = m_bDockingInProgress;
3470 aUIDockingElement = m_aDockUIElement;
3471 bFloating = aUIDockingElement.m_bFloating;
3472
3473 UIElement& rUIElement = impl_findToolbar( aUIDockingElement.m_aName );
3474 if ( rUIElement.m_aName == aUIDockingElement.m_aName )
3475 {
3476 if ( aUIDockingElement.m_bFloating )
3477 {
3478 // Write last position into position data
3479 uno::Reference< awt::XWindow > xWindow( aUIDockingElement.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
3480 rUIElement.m_aFloatingData = aUIDockingElement.m_aFloatingData;
3481 awt::Rectangle aTmpRect = xWindow->getPosSize();
3482 rUIElement.m_aFloatingData.m_aPos = awt::Point(aTmpRect.X, aTmpRect.Y);
3483 // make changes also for our local data as we use it to make data persistent
3484 aUIDockingElement.m_aFloatingData = rUIElement.m_aFloatingData;
3485 }
3486 else
3487 {
3488 rUIElement.m_aDockedData = aUIDockingElement.m_aDockedData;
3489 rUIElement.m_aFloatingData.m_aSize = aUIDockingElement.m_aFloatingData.m_aSize;
3490
3491 if ( m_eDockOperation != DOCKOP_ON_COLROW )
3492 {
3493 // we have to renumber our row/column data to insert a new row/column
3494 implts_renumberRowColumnData(aUIDockingElement.m_aDockedData.m_nDockedArea, aUIDockingElement );
3495 }
3496 }
3497
3498 bStartDockFloated = rUIElement.m_bFloating;
3499 rUIElement.m_bFloating = m_aDockUIElement.m_bFloating;
3500 rUIElement.m_bUserActive = true;
3501 }
3502
3503 // reset member for next docking operation
3504 m_aDockUIElement.m_xUIElement.clear();
3505 m_eDockOperation = DOCKOP_ON_COLROW;
3506 aWriteLock.clear();
3507 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
3508
3509 implts_writeWindowStateData( aUIDockingElement );
3510
3511 if ( bDockingInProgress )
3512 {
3513 SolarMutexGuard aGuard;
3514 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( uno::Reference< awt::XWindow >( e.Source, uno::UNO_QUERY ));
3515 ToolBox* pToolBox = nullptr;
3516 if ( pWindow && pWindow->GetType() == WindowType::TOOLBOX )
3517 pToolBox = static_cast<ToolBox *>(pWindow.get());
3518
3519 if ( pToolBox )
3520 {
3521 if( e.bFloating )
3522 {
3523 if ( aUIDockingElement.m_aFloatingData.m_bIsHorizontal )
3524 pToolBox->SetAlign();
3525 else
3526 pToolBox->SetAlign( WindowAlign::Left );
3527 }
3528 else
3529 {
3530 ::Size aSize;
3531
3532 pToolBox->SetAlign( ImplConvertAlignment( aUIDockingElement.m_aDockedData.m_nDockedArea) );
3533
3534 // Docked toolbars have always one line
3535 aSize = pToolBox->CalcWindowSizePixel( 1 );
3536
3537 // Lock layouting updates as our listener would be called due to SetSizePixel
3538 pToolBox->SetOutputSizePixel( aSize );
3539 }
3540 }
3541 }
3542
3543 implts_sortUIElements();
3544
3545 aWriteLock.reset();
3546 m_bDockingInProgress = false;
3547 m_bLayoutDirty = !bStartDockFloated || !bFloating;
3548 bool bNotify = m_bLayoutDirty;
3549 aWriteLock.clear();
3550
3551 if ( bNotify )
3552 m_pParentLayouter->requestLayout();
3553}
3554
3555sal_Bool SAL_CALL ToolbarLayoutManager::prepareToggleFloatingMode( const lang::EventObject& e )
3556{
3557 SolarMutexClearableGuard aReadLock;
3558 bool bDockingInProgress = m_bDockingInProgress;
3559 aReadLock.clear();
3560
3561 UIElement aUIDockingElement = implts_findToolbar( e.Source );
3562 bool bWinFound( !aUIDockingElement.m_aName.isEmpty() );
3563 uno::Reference< awt::XWindow > xWindow( e.Source, uno::UNO_QUERY );
3564
3565 if ( bWinFound && xWindow.is() )
3566 {
3567 if ( !bDockingInProgress )
3568 {
3569 uno::Reference< awt::XDockableWindow > xDockWindow( xWindow, uno::UNO_QUERY );
3570 if ( xDockWindow->isFloating() )
3571 {
3572 {
3573 SolarMutexGuard aGuard;
3574 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
3575 if ( pWindow && pWindow->GetType() == WindowType::TOOLBOX )
3576 {
3577 ToolBox* pToolBox = static_cast< ToolBox *>( pWindow.get() );
3578 aUIDockingElement.m_aFloatingData.m_aPos = AWTPoint(pToolBox->GetPosPixel());
3579 aUIDockingElement.m_aFloatingData.m_aSize = AWTSize(pToolBox->GetOutputSizePixel());
3580 aUIDockingElement.m_aFloatingData.m_nLines = pToolBox->GetFloatingLines();
3581 aUIDockingElement.m_aFloatingData.m_bIsHorizontal = isToolboxHorizontalAligned( pToolBox );
3582 }
3583 }
3584
3585 UIElement aUIElement = implts_findToolbar( aUIDockingElement.m_aName );
3586 if ( aUIElement.m_aName == aUIDockingElement.m_aName )
3587 implts_setToolbar( aUIDockingElement );
3588 }
3589 }
3590 }
3591
3592 return true;
3593}
3594
3595void SAL_CALL ToolbarLayoutManager::toggleFloatingMode( const lang::EventObject& e )
3596{
3597 UIElement aUIDockingElement;
3598
3599 SolarMutexResettableGuard aReadLock;
3600 bool bDockingInProgress( m_bDockingInProgress );
3601 if ( bDockingInProgress )
3602 aUIDockingElement = m_aDockUIElement;
3603 aReadLock.clear();
3604
3605 vcl::Window* pWindow( nullptr );
3606 ToolBox* pToolBox( nullptr );
3607 uno::Reference< awt::XWindow2 > xWindow;
3608
3609 {
3610 SolarMutexGuard aGuard;
3611 xWindow.set( e.Source, uno::UNO_QUERY );
3612 pWindow = VCLUnoHelper::GetWindow( xWindow ).get();
3613
3614 if ( pWindow && pWindow->GetType() == WindowType::TOOLBOX )
3615 pToolBox = static_cast<ToolBox *>(pWindow);
3616 }
3617
3618 if ( !bDockingInProgress )
3619 {
3620 aUIDockingElement = implts_findToolbar( e.Source );
3621 bool bWinFound = !aUIDockingElement.m_aName.isEmpty();
3622
3623 if ( bWinFound && xWindow.is() )
3624 {
3625 aUIDockingElement.m_bFloating = !aUIDockingElement.m_bFloating;
3626 aUIDockingElement.m_bUserActive = true;
3627
3628 implts_setLayoutInProgress();
3629 if ( aUIDockingElement.m_bFloating )
3630 {
3631 SolarMutexGuard aGuard;
3632 if ( pToolBox )
3633 {
3634 pToolBox->SetLineCount( aUIDockingElement.m_aFloatingData.m_nLines );
3635 if ( aUIDockingElement.m_aFloatingData.m_bIsHorizontal )
3636 pToolBox->SetAlign();
3637 else
3638 pToolBox->SetAlign( WindowAlign::Left );
3639 }
3640
3641 bool bUndefPos = hasDefaultPosValue( aUIDockingElement.m_aFloatingData.m_aPos );
3642 bool bSetSize = !hasEmptySize( aUIDockingElement.m_aFloatingData.m_aSize );
3643
3644 if ( bUndefPos )
3645 aUIDockingElement.m_aFloatingData.m_aPos = implts_findNextCascadeFloatingPos();
3646
3647 if ( !bSetSize )
3648 {
3649 if ( pToolBox )
3650 aUIDockingElement.m_aFloatingData.m_aSize = AWTSize(pToolBox->CalcFloatingWindowSizePixel());
3651 else if ( pWindow )
3652 aUIDockingElement.m_aFloatingData.m_aSize = AWTSize(pWindow->GetOutputSizePixel());
3653 }
3654
3655 xWindow->setPosSize( aUIDockingElement.m_aFloatingData.m_aPos.X,
3656 aUIDockingElement.m_aFloatingData.m_aPos.Y,
3657 0, 0, awt::PosSize::POS );
3658 xWindow->setOutputSize(aUIDockingElement.m_aFloatingData.m_aSize);
3659 }
3660 else
3661 {
3662 if ( isDefaultPos( aUIDockingElement.m_aDockedData.m_aPos ))
3663 {
3664 // Docking on its default position without a preset position -
3665 // we have to find a good place for it.
3666 ::Point aPixelPos;
3667 awt::Point aDockPos;
3668 ::Size aSize;
3669
3670 {
3671 SolarMutexGuard aGuard;
3672 if ( pToolBox )
3673 aSize = pToolBox->CalcWindowSizePixel( 1, ImplConvertAlignment( aUIDockingElement.m_aDockedData.m_nDockedArea ) );
3674 else if ( pWindow )
3675 aSize = pWindow->GetSizePixel();
3676 }
3677
3678 implts_findNextDockingPos(aUIDockingElement.m_aDockedData.m_nDockedArea, aSize, aDockPos, aPixelPos );
3679 aUIDockingElement.m_aDockedData.m_aPos = aDockPos;
3680 }
3681
3682 SolarMutexGuard aGuard;
3683 if ( pToolBox )
3684 {
3685 pToolBox->SetAlign( ImplConvertAlignment( aUIDockingElement.m_aDockedData.m_nDockedArea) );
3686 ::Size aSize = pToolBox->CalcWindowSizePixel( 1 );
3687 awt::Rectangle aRect = xWindow->getPosSize();
3688 xWindow->setPosSize( aRect.X, aRect.Y, 0, 0, awt::PosSize::POS );
3689 xWindow->setOutputSize( AWTSize( aSize ) );
3690 }
3691 }
3692
3693 implts_setLayoutInProgress( false );
3694 implts_setToolbar( aUIDockingElement );
3695 implts_writeWindowStateData( aUIDockingElement );
3696 implts_sortUIElements();
3697 implts_setLayoutDirty();
3698
3699 aReadLock.reset();
3700 LayoutManager* pParentLayouter( m_pParentLayouter );
3701 aReadLock.clear();
3702
3703 if ( pParentLayouter )
3704 pParentLayouter->requestLayout();
3705 }
3706 }
3707 else
3708 {
3709 SolarMutexGuard aGuard;
3710 if ( pToolBox )
3711 {
3712 if ( aUIDockingElement.m_bFloating )
3713 {
3714 if ( aUIDockingElement.m_aFloatingData.m_bIsHorizontal )
3715 pToolBox->SetAlign();
3716 else
3717 pToolBox->SetAlign( WindowAlign::Left );
3718 }
3719 else
3720 pToolBox->SetAlign( ImplConvertAlignment( aUIDockingElement.m_aDockedData.m_nDockedArea) );
3721 }
3722 }
3723}
3724
3725void SAL_CALL ToolbarLayoutManager::closed( const lang::EventObject& e )
3726{
3727 OUString aName;
3728 UIElement aUIElement;
3729
3730 {
3731 SolarMutexGuard aWriteLock;
3732 for (auto& elem : m_aUIElements)
3733 {
3734 uno::Reference<ui::XUIElement> xUIElement(elem.m_xUIElement);
3735 if (xUIElement.is())
3736 {
3737 uno::Reference<uno::XInterface> xIfac(xUIElement->getRealInterface(),
3738 uno::UNO_QUERY);
3739 if (xIfac == e.Source)
3740 {
3741 aName = elem.m_aName;
3742
3743 // user closes a toolbar =>
3744 // context sensitive toolbar: only destroy toolbar and store state.
3745 // non context sensitive toolbar: make it invisible, store state and destroy it.
3746 if (!elem.m_bContextSensitive)
3747 elem.m_bVisible = false;
3748
3749 aUIElement = elem;
3750 break;
3751 }
3752 }
3753 }
3754 }
3755
3756 // destroy element
3757 if ( aName.isEmpty() )
3758 return;
3759
3760 implts_writeWindowStateData( aUIElement );
3761 destroyToolbar( aName );
3762
3763 SolarMutexClearableGuard aReadLock;
3764 bool bLayoutDirty = m_bLayoutDirty;
3765 LayoutManager* pParentLayouter( m_pParentLayouter );
3766 aReadLock.clear();
3767
3768 if ( bLayoutDirty && pParentLayouter )
3769 pParentLayouter->requestLayout();
3770}
3771
3772void SAL_CALL ToolbarLayoutManager::endPopupMode( const awt::EndPopupModeEvent& /*e*/ )
3773{
3774}
3775
3776// XUIConfigurationListener
3777
3778void SAL_CALL ToolbarLayoutManager::elementInserted( const ui::ConfigurationEvent& rEvent )
3779{
3780 UIElement aUIElement = implts_findToolbar( rEvent.ResourceURL );
3781
3782 uno::Reference< ui::XUIElementSettings > xElementSettings( aUIElement.m_xUIElement, uno::UNO_QUERY );
3783 if ( xElementSettings.is() )
3784 {
3785 uno::Reference< beans::XPropertySet > xPropSet( xElementSettings, uno::UNO_QUERY );
3786 if ( xPropSet.is() )
3787 {
3788 if ( rEvent.Source == uno::Reference< uno::XInterface >( m_xDocCfgMgr, uno::UNO_QUERY ))
3789 xPropSet->setPropertyValue( "ConfigurationSource", makeAny( m_xDocCfgMgr ));
3790 }
3791 xElementSettings->updateSettings();
3792 }
3793 else
3794 {
3795 OUString aElementType;
3796 OUString aElementName;
3797 parseResourceURL( rEvent.ResourceURL, aElementType, aElementName );
3798 if ( aElementName.indexOf( "custom_" ) != -1 )
3799 {
3800 // custom toolbar must be directly created, shown and layouted!
3801 createToolbar( rEvent.ResourceURL );
3802 uno::Reference< ui::XUIElement > xUIElement = getToolbar( rEvent.ResourceURL );
3803 if ( xUIElement.is() )
3804 {
3805 OUString aUIName;
3806 uno::Reference< ui::XUIConfigurationManager > xCfgMgr;
3807 uno::Reference< beans::XPropertySet > xPropSet;
3808
3809 try
3810 {
3811 xCfgMgr.set( rEvent.Source, uno::UNO_QUERY );
3812 xPropSet.set( xCfgMgr->getSettings( rEvent.ResourceURL, false ), uno::UNO_QUERY );
3813
3814 if ( xPropSet.is() )
3815 xPropSet->getPropertyValue("UIName") >>= aUIName;
3816 }
3817 catch (const container::NoSuchElementException&)
3818 {
3819 }
3820 catch (const beans::UnknownPropertyException&)
3821 {
3822 }
3823 catch (const lang::WrappedTargetException&)
3824 {
3825 }
3826
3827 {
3828 SolarMutexGuard aGuard;
3829 vcl::Window* pWindow = getWindowFromXUIElement( xUIElement );
3830 if ( pWindow )
3831 pWindow->SetText( aUIName );
3832 }
3833
3834 showToolbar( rEvent.ResourceURL );
3835 }
3836 }
3837 }
3838}
3839
3840void SAL_CALL ToolbarLayoutManager::elementRemoved( const ui::ConfigurationEvent& rEvent )
3841{
3842 SolarMutexClearableGuard aReadLock;
3843 uno::Reference< awt::XWindow > xContainerWindow = m_xContainerWindow;
3844 uno::Reference< ui::XUIConfigurationManager > xModuleCfgMgr( m_xModuleCfgMgr );
3845 uno::Reference< ui::XUIConfigurationManager > xDocCfgMgr( m_xDocCfgMgr );
3846 aReadLock.clear();
3847
3848 UIElement aUIElement = implts_findToolbar( rEvent.ResourceURL );
3849 uno::Reference< ui::XUIElementSettings > xElementSettings( aUIElement.m_xUIElement, uno::UNO_QUERY );
3850 if ( !xElementSettings.is() )
3851 return;
3852
3853 bool bNoSettings( false );
3854 OUString aConfigSourcePropName( "ConfigurationSource" );
3855 uno::Reference< uno::XInterface > xElementCfgMgr;
3856 uno::Reference< beans::XPropertySet > xPropSet( xElementSettings, uno::UNO_QUERY );
3857
3858 if ( xPropSet.is() )
3859 xPropSet->getPropertyValue( aConfigSourcePropName ) >>= xElementCfgMgr;
3860
3861 if ( !xElementCfgMgr.is() )
3862 return;
3863
3864 // Check if the same UI configuration manager has changed => check further
3865 if ( rEvent.Source == xElementCfgMgr )
3866 {
3867 // Same UI configuration manager where our element has its settings
3868 if ( rEvent.Source == uno::Reference< uno::XInterface >( xDocCfgMgr, uno::UNO_QUERY ))
3869 {
3870 // document settings removed
3871 if ( xModuleCfgMgr->hasSettings( rEvent.ResourceURL ))
3872 {
3873 xPropSet->setPropertyValue( aConfigSourcePropName, makeAny( xModuleCfgMgr ));
3874 xElementSettings->updateSettings();
3875 return;
3876 }
3877 }
3878
3879 bNoSettings = true;
3880 }
3881
3882 // No settings anymore, element must be destroyed
3883 if ( xContainerWindow.is() && bNoSettings )
3884 destroyToolbar( rEvent.ResourceURL );
3885}
3886
3887void SAL_CALL ToolbarLayoutManager::elementReplaced( const ui::ConfigurationEvent& rEvent )
3888{
3889 UIElement aUIElement = implts_findToolbar( rEvent.ResourceURL );
3890
3891 uno::Reference< ui::XUIElementSettings > xElementSettings( aUIElement.m_xUIElement, uno::UNO_QUERY );
3892 if ( !xElementSettings.is() )
3893 return;
3894
3895 uno::Reference< uno::XInterface > xElementCfgMgr;
3896 uno::Reference< beans::XPropertySet > xPropSet( xElementSettings, uno::UNO_QUERY );
3897
3898 if ( xPropSet.is() )
3899 xPropSet->getPropertyValue( "ConfigurationSource" ) >>= xElementCfgMgr;
3900
3901 if ( !xElementCfgMgr.is() )
3902 return;
3903
3904 // Check if the same UI configuration manager has changed => update settings
3905 if ( rEvent.Source != xElementCfgMgr )
3906 return;
3907
3908 xElementSettings->updateSettings();
3909
3910 SolarMutexClearableGuard aWriteLock;
3911 bool bNotify = !aUIElement.m_bFloating;
3912 m_bLayoutDirty = bNotify;
3913 LayoutManager* pParentLayouter( m_pParentLayouter );
3914 aWriteLock.clear();
3915
3916 if ( bNotify && pParentLayouter )
3917 pParentLayouter->requestLayout();
3918}
3919
3920uno::Reference< ui::XUIElement > ToolbarLayoutManager::getToolbar( const OUString& aName )
3921{
3922 return implts_findToolbar( aName ).m_xUIElement;
3923}
3924
3925uno::Sequence< uno::Reference< ui::XUIElement > > ToolbarLayoutManager::getToolbars()
3926{
3927 uno::Sequence< uno::Reference< ui::XUIElement > > aSeq;
3928
3929 SolarMutexGuard g;
3930 if ( !m_aUIElements.empty() )
3931 {
3932 sal_uInt32 nCount(0);
3933 for (auto const& elem : m_aUIElements)
3934 {
3935 if ( elem.m_xUIElement.is() )
3936 {
3937 ++nCount;
3938 aSeq.realloc( nCount );
3939 aSeq[nCount-1] = elem.m_xUIElement;
3940 }
3941 }
3942 }
3943
3944 return aSeq;
3945}
3946
3947bool ToolbarLayoutManager::floatToolbar( const OUString& rResourceURL )
3948{
3949 UIElement aUIElement = implts_findToolbar( rResourceURL );
3950 if ( aUIElement.m_xUIElement.is() )
3951 {
3952 try
3953 {
3954 uno::Reference< awt::XDockableWindow > xDockWindow( aUIElement.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
3955 if ( xDockWindow.is() && !xDockWindow->isFloating() )
3956 {
3957 aUIElement.m_bFloating = true;
3958 implts_writeWindowStateData( aUIElement );
3959 xDockWindow->setFloatingMode( true );
3960
3961 implts_setLayoutDirty();
3962 implts_setToolbar( aUIElement );
3963 return true;
3964 }
3965 }
3966 catch (const lang::DisposedException&)
3967 {
3968 }
3969 }
3970
3971 return false;
3972}
3973
3974bool ToolbarLayoutManager::lockToolbar( const OUString& rResourceURL )
3975{
3976 UIElement aUIElement = implts_findToolbar( rResourceURL );
3977 if ( aUIElement.m_xUIElement.is() )
3978 {
3979 try
3980 {
3981 uno::Reference< awt::XDockableWindow > xDockWindow( aUIElement.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
3982 if ( xDockWindow.is() && !xDockWindow->isFloating() && !xDockWindow->isLocked() )
3983 {
3984 aUIElement.m_aDockedData.m_bLocked = true;
3985 implts_writeWindowStateData( aUIElement );
3986 xDockWindow->lock();
3987
3988 implts_setLayoutDirty();
3989 implts_setToolbar( aUIElement );
3990 return true;
3991 }
3992 }
3993 catch (const lang::DisposedException&)
3994 {
3995 }
3996 }
3997
3998 return false;
3999}
4000
4001bool ToolbarLayoutManager::unlockToolbar( const OUString& rResourceURL )
4002{
4003 UIElement aUIElement = implts_findToolbar( rResourceURL );
4004 if ( aUIElement.m_xUIElement.is() )
4005 {
4006 try
4007 {
4008 uno::Reference< awt::XDockableWindow > xDockWindow( aUIElement.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
4009 if ( xDockWindow.is() && !xDockWindow->isFloating() && xDockWindow->isLocked() )
4010 {
4011 aUIElement.m_aDockedData.m_bLocked = false;
4012 implts_writeWindowStateData( aUIElement );
4013 xDockWindow->unlock();
4014
4015 implts_setLayoutDirty();
4016 implts_setToolbar( aUIElement );
4017 return true;
4018 }
4019 }
4020 catch (const lang::DisposedException&)
4021 {
4022 }
4023 }
4024
4025 return false;
4026}
4027
4028bool ToolbarLayoutManager::isToolbarVisible( const OUString& rResourceURL )
4029{
4030 uno::Reference< awt::XWindow2 > xWindow2( implts_getXWindow( rResourceURL ), uno::UNO_QUERY );
4031 return ( xWindow2.is() && xWindow2->isVisible() );
4032}
4033
4034bool ToolbarLayoutManager::isToolbarFloating( const OUString& rResourceURL )
4035{
4036 uno::Reference< awt::XDockableWindow > xDockWindow( implts_getXWindow( rResourceURL ), uno::UNO_QUERY );
4037 return ( xDockWindow.is() && xDockWindow->isFloating() );
4038}
4039
4040bool ToolbarLayoutManager::isToolbarDocked( const OUString& rResourceURL )
4041{
4042 return !isToolbarFloating( rResourceURL );
4043}
4044
4045bool ToolbarLayoutManager::isToolbarLocked( const OUString& rResourceURL )
4046{
4047 uno::Reference< awt::XDockableWindow > xDockWindow( implts_getXWindow( rResourceURL ), uno::UNO_QUERY );
4048 return ( xDockWindow.is() && xDockWindow->isLocked() );
4049}
4050
4051awt::Size ToolbarLayoutManager::getToolbarSize( const OUString& rResourceURL )
4052{
4053 vcl::Window* pWindow = implts_getWindow( rResourceURL );
1
Calling 'ToolbarLayoutManager::implts_getWindow'
4054
4055 SolarMutexGuard aGuard;
4056 if ( pWindow )
4057 {
4058 ::Size aSize = pWindow->GetSizePixel();
4059 awt::Size aWinSize;
4060 aWinSize.Width = aSize.Width();
4061 aWinSize.Height = aSize.Height();
4062 return aWinSize;
4063 }
4064
4065 return awt::Size();
4066}
4067
4068awt::Point ToolbarLayoutManager::getToolbarPos( const OUString& rResourceURL )
4069{
4070 awt::Point aPos;
4071 UIElement aUIElement = implts_findToolbar( rResourceURL );
4072
4073 uno::Reference< awt::XWindow > xWindow( implts_getXWindow( rResourceURL ));
4074 if ( xWindow.is() )
4075 {
4076 if ( aUIElement.m_bFloating )
4077 {
4078 awt::Rectangle aRect = xWindow->getPosSize();
4079 aPos.X = aRect.X;
4080 aPos.Y = aRect.Y;
4081 }
4082 else
4083 aPos = aUIElement.m_aDockedData.m_aPos;
4084 }
4085
4086 return aPos;
4087}
4088
4089void ToolbarLayoutManager::setToolbarSize( const OUString& rResourceURL, const awt::Size& aSize )
4090{
4091 uno::Reference< awt::XWindow2 > xWindow( implts_getXWindow( rResourceURL ), uno::UNO_QUERY );
4092 uno::Reference< awt::XDockableWindow > xDockWindow( xWindow, uno::UNO_QUERY );
4093 UIElement aUIElement = implts_findToolbar( rResourceURL );
4094
4095 if ( xWindow.is() && xDockWindow.is() && xDockWindow->isFloating() )
4096 {
4097 xWindow->setOutputSize( aSize );
4098 aUIElement.m_aFloatingData.m_aSize = aSize;
4099 implts_setToolbar( aUIElement );
4100 implts_writeWindowStateData( aUIElement );
4101 implts_sortUIElements();
4102 }
4103}
4104
4105void ToolbarLayoutManager::setToolbarPos( const OUString& rResourceURL, const awt::Point& aPos )
4106{
4107 uno::Reference< awt::XWindow > xWindow( implts_getXWindow( rResourceURL ));
4108 uno::Reference< awt::XDockableWindow > xDockWindow( xWindow, uno::UNO_QUERY );
4109 UIElement aUIElement = implts_findToolbar( rResourceURL );
4110
4111 if ( xWindow.is() && xDockWindow.is() && xDockWindow->isFloating() )
4112 {
4113 xWindow->setPosSize( aPos.X, aPos.Y, 0, 0, awt::PosSize::POS );
4114 aUIElement.m_aFloatingData.m_aPos = aPos;
4115 implts_setToolbar( aUIElement );
4116 implts_writeWindowStateData( aUIElement );
4117 implts_sortUIElements();
4118 }
4119}
4120
4121void ToolbarLayoutManager::setToolbarPosSize( const OUString& rResourceURL, const awt::Point& aPos, const awt::Size& aSize )
4122{
4123 setToolbarPos( rResourceURL, aPos );
4124 setToolbarSize( rResourceURL, aSize );
4125}
4126
4127} // namespace framework
4128
4129/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/rtl/ref.hxx

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
34namespace rtl
35{
36
37/** Template reference class for reference type.
38*/
39template <class reference_type>
40class Reference
41{
42 /** The <b>reference_type</b> body pointer.
43 */
44 reference_type * m_pBody;
45
46
47public:
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)
4
Assuming field 'm_pBody' is non-null
5
Taking true branch
113 m_pBody->release();
6
Calling 'VclReferenceBase::release'
10
Returning; memory was released
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
277namespace 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*/
286template<typename T>
287struct 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: */

/home/maarten/src/libreoffice/core/include/vcl/vclreferencebase.hxx

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
25class VCL_DLLPUBLIC__attribute__ ((visibility("default"))) VclReferenceBase
26{
27 mutable oslInterlockedCount mnRefCnt;
28
29 template<typename T> friend class VclPtr;
30
31public:
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)
7
Assuming the condition is true
8
Taking true branch
40 delete this;
9
Memory is released
41 }
42#ifdef DBG_UTIL
43#ifndef _WIN32
44 sal_Int32 getRefCount() const { return mnRefCnt; }
45#endif
46#endif
47
48
49private:
50 VclReferenceBase(const VclReferenceBase&) = delete;
51 VclReferenceBase& operator=(const VclReferenceBase&) = delete;
52
53 bool mbDisposed : 1;
54
55protected:
56 VclReferenceBase();
57protected:
58 virtual ~VclReferenceBase();
59
60protected:
61 virtual void dispose();
62
63public:
64 void disposeOnce();
65 bool isDisposed() const { return mbDisposed; }
66
67};
68#endif