Avoid potential negative array index access to cached text.
[LibreOffice.git] / framework / source / layoutmanager / toolbarlayoutmanager.cxx
blob846b111d58256c6a614bae7f94ab2f9619dab19f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
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>
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>
36 #include <comphelper/propertyvalue.hxx>
37 #include <cppuhelper/queryinterface.hxx>
38 #include <o3tl/string_view.hxx>
39 #include <unotools/cmdoptions.hxx>
40 #include <toolkit/helper/vclunohelper.hxx>
41 #include <toolkit/helper/convert.hxx>
42 #include <utility>
43 #include <vcl/i18nhelp.hxx>
44 #include <vcl/dockingarea.hxx>
45 #include <vcl/settings.hxx>
46 #include <vcl/svapp.hxx>
47 #include <sal/log.hxx>
48 #include <tools/gen.hxx>
51 using namespace ::com::sun::star;
53 namespace framework
56 ToolbarLayoutManager::ToolbarLayoutManager(
57 uno::Reference< uno::XComponentContext > xContext,
58 uno::Reference< ui::XUIElementFactory > xUIElementFactory,
59 LayoutManager* pParentLayouter ):
60 m_xContext(std::move( xContext)),
61 m_xUIElementFactoryManager(std::move( xUIElementFactory )),
62 m_pParentLayouter( pParentLayouter ),
63 m_aDockingArea(0, 0, 0, 0),
64 m_aDockingAreaOffsets(0, 0, 0, 0),
65 m_eDockOperation( DOCKOP_ON_COLROW ),
66 m_ePreviewDetection( PREVIEWFRAME_UNKNOWN ),
67 m_bComponentAttached( false ),
68 m_bLayoutDirty( false ),
69 m_bGlobalSettings( false ),
70 m_bDockingInProgress( false ),
71 m_bLayoutInProgress( false ),
72 m_bToolbarCreation( false )
76 ToolbarLayoutManager::~ToolbarLayoutManager()
78 m_pGlobalSettings.reset();
79 m_pAddonOptions.reset();
82 // XInterface
84 void SAL_CALL ToolbarLayoutManager::acquire() noexcept
86 OWeakObject::acquire();
89 void SAL_CALL ToolbarLayoutManager::release() noexcept
91 OWeakObject::release();
94 uno::Any SAL_CALL ToolbarLayoutManager::queryInterface( const uno::Type & rType )
96 uno::Any a = ::cppu::queryInterface( rType,
97 static_cast< awt::XDockableWindowListener* >(this),
98 static_cast< ui::XUIConfigurationListener* >(this),
99 static_cast< awt::XWindowListener* >(this));
101 if ( a.hasValue() )
102 return a;
104 return OWeakObject::queryInterface( rType );
107 void SAL_CALL ToolbarLayoutManager::disposing( const lang::EventObject& aEvent )
109 if ( aEvent.Source == m_xFrame )
111 // Reset all internal references
112 reset();
113 implts_destroyDockingAreaWindows();
117 awt::Rectangle ToolbarLayoutManager::getDockingArea()
119 SolarMutexResettableGuard aWriteLock;
120 tools::Rectangle aNewDockingArea( m_aDockingArea );
121 aWriteLock.clear();
123 if ( isLayoutDirty() )
124 aNewDockingArea = implts_calcDockingArea();
126 aWriteLock.reset();
127 m_aDockingArea = aNewDockingArea;
128 aWriteLock.clear();
130 return putRectangleValueToAWT(aNewDockingArea);
133 void ToolbarLayoutManager::setDockingArea( const awt::Rectangle& rDockingArea )
135 SolarMutexGuard g;
136 m_aDockingArea = putAWTToRectangle( rDockingArea );
137 m_bLayoutDirty = true;
140 void ToolbarLayoutManager::implts_setDockingAreaWindowSizes( const awt::Rectangle& rBorderSpace )
142 SolarMutexClearableGuard aReadLock;
143 tools::Rectangle aDockOffsets = m_aDockingAreaOffsets;
144 uno::Reference< awt::XWindow2 > xContainerWindow( m_xContainerWindow );
145 uno::Reference< awt::XWindow > xTopDockAreaWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_TOP)] );
146 uno::Reference< awt::XWindow > xBottomDockAreaWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_BOTTOM)] );
147 uno::Reference< awt::XWindow > xLeftDockAreaWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_LEFT)] );
148 uno::Reference< awt::XWindow > xRightDockAreaWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_RIGHT)] );
149 aReadLock.clear();
151 uno::Reference< awt::XDevice > xDevice( xContainerWindow, uno::UNO_QUERY );
153 // Convert relative size to output size.
154 awt::Rectangle aRectangle = xContainerWindow->getPosSize();
155 awt::DeviceInfo aInfo = xDevice->getInfo();
156 awt::Size aContainerClientSize( aRectangle.Width - aInfo.LeftInset - aInfo.RightInset ,
157 aRectangle.Height - aInfo.TopInset - aInfo.BottomInset );
158 tools::Long aStatusBarHeight = aDockOffsets.GetHeight();
160 sal_Int32 nLeftRightDockingAreaHeight( aContainerClientSize.Height );
161 if ( rBorderSpace.Y >= 0 )
163 // Top docking area window
164 xTopDockAreaWindow->setPosSize( 0, 0, aContainerClientSize.Width, rBorderSpace.Y, awt::PosSize::POSSIZE );
165 xTopDockAreaWindow->setVisible( true );
166 nLeftRightDockingAreaHeight -= rBorderSpace.Y;
169 if ( rBorderSpace.Height >= 0 )
171 // Bottom docking area window
172 sal_Int32 nBottomPos = std::max( sal_Int32( aContainerClientSize.Height - rBorderSpace.Height - aStatusBarHeight + 1 ), sal_Int32( 0 ));
173 sal_Int32 nHeight = ( nBottomPos == 0 ) ? 0 : rBorderSpace.Height;
175 xBottomDockAreaWindow->setPosSize( 0, nBottomPos, aContainerClientSize.Width, nHeight, awt::PosSize::POSSIZE );
176 xBottomDockAreaWindow->setVisible( true );
177 nLeftRightDockingAreaHeight -= nHeight - 1;
180 nLeftRightDockingAreaHeight -= aStatusBarHeight;
181 if ( rBorderSpace.X >= 0 || nLeftRightDockingAreaHeight > 0 )
183 // Left docking area window
184 // We also have to change our right docking area window if the top or bottom area has changed. They have a higher priority!
185 sal_Int32 nHeight = std::max<sal_Int32>( 0, nLeftRightDockingAreaHeight );
187 xLeftDockAreaWindow->setPosSize( 0, rBorderSpace.Y, rBorderSpace.X, nHeight, awt::PosSize::POSSIZE );
188 xLeftDockAreaWindow->setVisible( true );
190 if ( rBorderSpace.Width >= 0 || nLeftRightDockingAreaHeight > 0 )
192 // Right docking area window
193 // We also have to change our right docking area window if the top or bottom area has changed. They have a higher priority!
194 sal_Int32 nLeftPos = std::max<sal_Int32>( 0, aContainerClientSize.Width - rBorderSpace.Width );
195 sal_Int32 nHeight = std::max<sal_Int32>( 0, nLeftRightDockingAreaHeight );
196 sal_Int32 nWidth = ( nLeftPos == 0 ) ? 0 : rBorderSpace.Width;
198 xRightDockAreaWindow->setPosSize( nLeftPos, rBorderSpace.Y, nWidth, nHeight, awt::PosSize::POSSIZE );
199 xRightDockAreaWindow->setVisible( true );
204 void ToolbarLayoutManager::doLayout(const ::Size& aContainerSize)
206 SolarMutexResettableGuard aWriteLock;
207 bool bLayoutInProgress( m_bLayoutInProgress );
208 m_bLayoutInProgress = true;
209 awt::Rectangle aDockingArea = putRectangleValueToAWT( m_aDockingArea );
210 aWriteLock.clear();
212 if ( bLayoutInProgress )
213 return;
215 // Retrieve row/column dependent data from all docked user-interface elements
216 for ( sal_Int32 i = 0; i < DOCKINGAREAS_COUNT; i++ )
218 bool bReverse( isReverseOrderDockingArea( i ));
219 std::vector< SingleRowColumnWindowData > aRowColumnsWindowData;
221 implts_getDockingAreaElementInfos( static_cast<ui::DockingArea>(i), aRowColumnsWindowData );
223 sal_Int32 nOffset( 0 );
224 const sal_uInt32 nCount = aRowColumnsWindowData.size();
225 for ( sal_uInt32 j = 0; j < nCount; ++j )
227 sal_uInt32 nIndex = bReverse ? nCount-j-1 : j;
228 implts_calcWindowPosSizeOnSingleRowColumn( i, nOffset, aRowColumnsWindowData[nIndex], aContainerSize );
229 nOffset += aRowColumnsWindowData[j].nStaticSize;
233 implts_setDockingAreaWindowSizes( aDockingArea );
235 aWriteLock.reset();
236 m_bLayoutDirty = false;
237 m_bLayoutInProgress = false;
238 aWriteLock.clear();
241 bool ToolbarLayoutManager::implts_isParentWindowVisible() const
243 SolarMutexGuard g;
244 bool bVisible( false );
245 if ( m_xContainerWindow.is() )
246 bVisible = m_xContainerWindow->isVisible();
248 return bVisible;
251 tools::Rectangle ToolbarLayoutManager::implts_calcDockingArea()
253 SolarMutexClearableGuard aReadLock;
254 UIElementVector aWindowVector( m_aUIElements );
255 aReadLock.clear();
257 tools::Rectangle aBorderSpace;
258 sal_Int32 nCurrRowColumn( 0 );
259 sal_Int32 nCurrPos( 0 );
260 ui::DockingArea nCurrDockingArea( ui::DockingArea_DOCKINGAREA_TOP );
261 std::vector< sal_Int32 > aRowColumnSizes[DOCKINGAREAS_COUNT];
263 // initialize rectangle with zero values!
264 aBorderSpace.setWidth(0);
265 aBorderSpace.setHeight(0);
267 aRowColumnSizes[static_cast<int>(nCurrDockingArea)].clear();
268 aRowColumnSizes[static_cast<int>(nCurrDockingArea)].push_back( 0 );
270 for (auto const& window : aWindowVector)
272 if ( window.m_xUIElement.is() )
274 uno::Reference< awt::XWindow > xWindow( window.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
275 uno::Reference< awt::XDockableWindow > xDockWindow( xWindow, uno::UNO_QUERY );
276 if ( xWindow.is() && xDockWindow.is() )
278 SolarMutexGuard aGuard;
280 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
281 if ( pWindow && !xDockWindow->isFloating() && window.m_bVisible && !window.m_bMasterHide )
283 awt::Rectangle aPosSize = xWindow->getPosSize();
284 if ( window.m_aDockedData.m_nDockedArea != nCurrDockingArea )
286 nCurrDockingArea = window.m_aDockedData.m_nDockedArea;
287 nCurrRowColumn = 0;
288 nCurrPos = 0;
289 aRowColumnSizes[static_cast<int>(nCurrDockingArea)].clear();
290 aRowColumnSizes[static_cast<int>(nCurrDockingArea)].push_back( 0 );
293 if ( window.m_aDockedData.m_nDockedArea == nCurrDockingArea )
295 if ( isHorizontalDockingArea( window.m_aDockedData.m_nDockedArea ))
297 if ( window.m_aDockedData.m_aPos.Y > nCurrPos )
299 ++nCurrRowColumn;
300 nCurrPos = window.m_aDockedData.m_aPos.Y;
301 aRowColumnSizes[static_cast<int>(nCurrDockingArea)].push_back( 0 );
304 if ( aPosSize.Height > aRowColumnSizes[static_cast<int>(nCurrDockingArea)][nCurrRowColumn] )
305 aRowColumnSizes[static_cast<int>(nCurrDockingArea)][nCurrRowColumn] = aPosSize.Height;
307 else
309 if ( window.m_aDockedData.m_aPos.X > nCurrPos )
311 ++nCurrRowColumn;
312 nCurrPos = window.m_aDockedData.m_aPos.X;
313 aRowColumnSizes[static_cast<int>(nCurrDockingArea)].push_back( 0 );
316 if ( aPosSize.Width > aRowColumnSizes[static_cast<int>(nCurrDockingArea)][nCurrRowColumn] )
317 aRowColumnSizes[static_cast<int>(nCurrDockingArea)][nCurrRowColumn] = aPosSize.Width;
325 // Sum up max heights from every row/column
326 if ( !aWindowVector.empty() )
328 for ( sal_Int32 i = 0; i <= sal_Int32(ui::DockingArea_DOCKINGAREA_RIGHT); i++ )
330 sal_Int32 nSize( 0 );
331 const sal_uInt32 nCount = aRowColumnSizes[i].size();
332 for ( sal_uInt32 j = 0; j < nCount; j++ )
333 nSize += aRowColumnSizes[i][j];
335 if ( i == sal_Int32(ui::DockingArea_DOCKINGAREA_TOP) )
336 aBorderSpace.SetTop( nSize );
337 else if ( i == sal_Int32(ui::DockingArea_DOCKINGAREA_BOTTOM) )
338 aBorderSpace.SetBottom( nSize );
339 else if ( i == sal_Int32(ui::DockingArea_DOCKINGAREA_LEFT) )
340 aBorderSpace.SetLeft( nSize );
341 else
342 aBorderSpace.SetRight( nSize );
346 return aBorderSpace;
349 void ToolbarLayoutManager::reset()
352 SolarMutexGuard aWriteLock;
353 m_xModuleCfgMgr.clear();
354 m_xDocCfgMgr.clear();
355 m_ePreviewDetection = PREVIEWFRAME_UNKNOWN;
356 m_bComponentAttached = false;
359 destroyToolbars();
360 resetDockingArea();
363 void ToolbarLayoutManager::attach(
364 const uno::Reference< frame::XFrame >& xFrame,
365 const uno::Reference< ui::XUIConfigurationManager >& xModuleCfgMgr,
366 const uno::Reference< ui::XUIConfigurationManager >& xDocCfgMgr,
367 const uno::Reference< container::XNameAccess >& xPersistentWindowState )
369 // reset toolbar manager if we lose our current frame
370 if ( m_xFrame.is() && m_xFrame != xFrame )
371 reset();
373 SolarMutexGuard g;
374 m_xFrame = xFrame;
375 m_xModuleCfgMgr = xModuleCfgMgr;
376 m_xDocCfgMgr = xDocCfgMgr;
377 m_xPersistentWindowState = xPersistentWindowState;
378 m_bComponentAttached = true;
381 bool ToolbarLayoutManager::isPreviewFrame()
383 SolarMutexGuard g;
384 if (m_ePreviewDetection == PREVIEWFRAME_UNKNOWN)
386 uno::Reference< frame::XFrame > xFrame( m_xFrame );
388 uno::Reference< frame::XModel > xModel( impl_getModelFromFrame( xFrame ));
390 m_ePreviewDetection = (implts_isPreviewModel( xModel ) ? PREVIEWFRAME_YES : PREVIEWFRAME_NO);
392 return m_ePreviewDetection == PREVIEWFRAME_YES;
395 void ToolbarLayoutManager::createStaticToolbars()
397 resetDockingArea();
398 implts_createCustomToolBars();
399 implts_createAddonsToolBars();
400 implts_createNonContextSensitiveToolBars();
401 implts_sortUIElements();
404 bool ToolbarLayoutManager::requestToolbar( const OUString& rResourceURL )
406 if (isPreviewFrame())
407 return false; // no toolbars for preview frame!
409 bool bNotify( false );
410 bool bMustCallCreate( false );
411 uno::Reference< ui::XUIElement > xUIElement;
413 UIElement aRequestedToolbar = impl_findToolbar( rResourceURL );
414 if ( aRequestedToolbar.m_aName != rResourceURL )
416 bMustCallCreate = true;
417 aRequestedToolbar.m_aName = rResourceURL;
418 aRequestedToolbar.m_aType = UIRESOURCETYPE_TOOLBAR;
419 aRequestedToolbar.m_xUIElement = xUIElement;
420 implts_readWindowStateData( rResourceURL, aRequestedToolbar );
423 xUIElement = aRequestedToolbar.m_xUIElement;
424 if ( !xUIElement.is() )
425 bMustCallCreate = true;
427 bool bCreateOrShowToolbar( aRequestedToolbar.m_bVisible && !aRequestedToolbar.m_bMasterHide );
429 if ( bCreateOrShowToolbar )
430 bNotify = bMustCallCreate ? createToolbar( rResourceURL ) : showToolbar( rResourceURL );
432 return bNotify;
435 bool ToolbarLayoutManager::createToolbar( const OUString& rResourceURL )
437 bool bNotify( false );
439 uno::Reference<frame::XFrame> xFrame;
440 uno::Reference<awt::XWindow2> xContainerWindow;
442 SolarMutexGuard aReadLock;
443 xFrame.set(m_xFrame);
444 xContainerWindow.set(m_xContainerWindow);
447 if ( !xFrame.is() || !xContainerWindow.is() )
448 return false;
450 UIElement aToolbarElement = implts_findToolbar( rResourceURL );
451 if ( !aToolbarElement.m_xUIElement.is() )
453 uno::Reference< ui::XUIElement > xUIElement;
455 uno::Sequence< beans::PropertyValue > aPropSeq{
456 comphelper::makePropertyValue("Frame", xFrame),
457 comphelper::makePropertyValue("Persistent", true)
459 uno::Reference<ui::XUIElementFactory> xUIElementFactory;
461 SolarMutexGuard aReadLock;
462 xUIElementFactory.set(m_xUIElementFactoryManager);
465 implts_setToolbarCreation();
468 if ( xUIElementFactory.is() )
469 xUIElement = xUIElementFactory->createUIElement( rResourceURL, aPropSeq );
471 catch (const container::NoSuchElementException&)
474 catch (const lang::IllegalArgumentException&)
477 implts_setToolbarCreation( false );
479 if ( xUIElement.is() )
481 uno::Reference< awt::XWindow > xWindow( xUIElement->getRealInterface(), uno::UNO_QUERY );
482 uno::Reference< awt::XDockableWindow > xDockWindow( xWindow, uno::UNO_QUERY );
483 if ( xDockWindow.is() && xWindow.is() )
487 xDockWindow->addDockableWindowListener( uno::Reference< awt::XDockableWindowListener >(this) );
488 xWindow->addWindowListener( uno::Reference< awt::XWindowListener >(this) );
489 xDockWindow->enableDocking( true );
491 catch (const uno::Exception&)
496 bool bVisible = false;
497 bool bFloating = false;
499 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
501 SolarMutexClearableGuard aWriteLock;
503 UIElement& rElement = impl_findToolbar(rResourceURL);
504 if (rElement.m_xUIElement.is())
506 // somebody else must have created it while we released
507 // the SolarMutex - just dispose our new instance and
508 // do nothing. (We have to dispose either the new or the
509 // existing m_xUIElement.)
510 aWriteLock.clear();
511 uno::Reference<lang::XComponent> const xC(xUIElement, uno::UNO_QUERY);
512 xC->dispose();
513 return false;
515 if (!rElement.m_aName.isEmpty())
517 // Reuse a local entry so we are able to use the latest
518 // UI changes for this document.
519 implts_setElementData(rElement, xDockWindow);
520 rElement.m_xUIElement = xUIElement;
521 bVisible = rElement.m_bVisible;
522 bFloating = rElement.m_bFloating;
524 else
526 // Create new UI element and try to read its state data
527 UIElement aNewToolbar(rResourceURL, UIRESOURCETYPE_TOOLBAR, xUIElement);
528 implts_readWindowStateData(rResourceURL, aNewToolbar);
529 implts_setElementData(aNewToolbar, xDockWindow);
530 implts_insertToolbar(aNewToolbar);
531 bVisible = aNewToolbar.m_bVisible;
532 bFloating = rElement.m_bFloating;
535 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
537 // set toolbar menu style according to customize command state
538 SvtCommandOptions aCmdOptions;
540 SolarMutexGuard aGuard;
541 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
542 if ( pWindow && pWindow->GetType() == WindowType::TOOLBOX )
544 ToolBox* pToolbar = static_cast<ToolBox *>(pWindow.get());
545 ToolBoxMenuType nMenuType = pToolbar->GetMenuType();
546 if ( aCmdOptions.LookupDisabled( "ConfigureDialog" ))
547 pToolbar->SetMenuType( nMenuType & ~ToolBoxMenuType::Customize );
548 else
549 pToolbar->SetMenuType( nMenuType | ToolBoxMenuType::Customize );
551 bNotify = true;
553 implts_sortUIElements();
555 if ( bVisible && !bFloating )
556 implts_setLayoutDirty();
560 return bNotify;
563 bool ToolbarLayoutManager::destroyToolbar( std::u16string_view rResourceURL )
565 uno::Reference< lang::XComponent > xComponent;
567 bool bNotify( false );
568 bool bMustBeSorted( false );
569 bool bMustLayouted( false );
570 bool bMustBeDestroyed( !o3tl::starts_with(rResourceURL, u"private:resource/toolbar/addon_") );
573 SolarMutexGuard aWriteLock;
574 for (auto & elem : m_aUIElements)
576 if (elem.m_aName == rResourceURL)
578 xComponent.set(elem.m_xUIElement, uno::UNO_QUERY);
579 if (bMustBeDestroyed)
580 elem.m_xUIElement.clear();
581 else
582 elem.m_bVisible = false;
583 break;
588 uno::Reference< ui::XUIElement > xUIElement( xComponent, uno::UNO_QUERY );
589 if ( xUIElement.is() )
591 uno::Reference< awt::XWindow > xWindow( xUIElement->getRealInterface(), uno::UNO_QUERY );
592 uno::Reference< awt::XDockableWindow > xDockWindow( xWindow, uno::UNO_QUERY );
594 if ( bMustBeDestroyed )
598 if ( xWindow.is() )
599 xWindow->removeWindowListener( uno::Reference< awt::XWindowListener >(this) );
601 catch (const uno::Exception&)
607 if ( xDockWindow.is() )
608 xDockWindow->removeDockableWindowListener( uno::Reference< awt::XDockableWindowListener >(this) );
610 catch (const uno::Exception&)
614 else
616 if ( xWindow.is() )
617 xWindow->setVisible( false );
618 bNotify = true;
621 if ( !xDockWindow->isFloating() )
622 bMustLayouted = true;
623 bMustBeSorted = true;
626 if ( bMustBeDestroyed )
628 if ( xComponent.is() )
629 xComponent->dispose();
630 bNotify = true;
633 if ( bMustLayouted )
634 implts_setLayoutDirty();
636 if ( bMustBeSorted )
637 implts_sortUIElements();
639 return bNotify;
642 void ToolbarLayoutManager::destroyToolbars()
644 UIElementVector aUIElementVector;
645 implts_getUIElementVectorCopy( aUIElementVector );
648 SolarMutexGuard aWriteLock;
649 m_aUIElements.clear();
650 m_bLayoutDirty = true;
653 for (auto const& elem : aUIElementVector)
655 uno::Reference< lang::XComponent > xComponent( elem.m_xUIElement, uno::UNO_QUERY );
656 if ( xComponent.is() )
657 xComponent->dispose();
661 bool ToolbarLayoutManager::showToolbar( std::u16string_view rResourceURL )
663 UIElement aUIElement = implts_findToolbar( rResourceURL );
665 SolarMutexGuard aGuard;
666 vcl::Window* pWindow = getWindowFromXUIElement( aUIElement.m_xUIElement );
668 // Addons appear to need to be populated at start, but we don't
669 // want to populate them with (scaled) images until later.
670 AddonsToolBarWrapper *pAddOns;
671 pAddOns = dynamic_cast<AddonsToolBarWrapper *>( aUIElement.m_xUIElement.get());
672 if (pAddOns)
673 pAddOns->populateImages();
675 if ( pWindow )
677 if ( !aUIElement.m_bFloating )
678 implts_setLayoutDirty();
679 else
680 pWindow->Show( true, ShowFlags::NoFocusChange | ShowFlags::NoActivate );
682 aUIElement.m_bVisible = true;
683 implts_writeWindowStateData( aUIElement );
684 implts_setToolbar( aUIElement );
685 implts_sortUIElements();
686 return true;
689 return false;
692 bool ToolbarLayoutManager::hideToolbar( std::u16string_view rResourceURL )
694 UIElement aUIElement = implts_findToolbar( rResourceURL );
696 SolarMutexGuard aGuard;
697 vcl::Window* pWindow = getWindowFromXUIElement( aUIElement.m_xUIElement );
698 if ( pWindow )
700 pWindow->Show( false );
701 if ( !aUIElement.m_bFloating )
702 implts_setLayoutDirty();
704 aUIElement.m_bVisible = false;
705 implts_writeWindowStateData( aUIElement );
706 implts_setToolbar( aUIElement );
707 return true;
710 return false;
713 void ToolbarLayoutManager::refreshToolbarsVisibility( bool bAutomaticToolbars )
715 UIElementVector aUIElementVector;
717 if ( !bAutomaticToolbars )
718 return;
720 implts_getUIElementVectorCopy( aUIElementVector );
722 UIElement aUIElement;
723 SolarMutexGuard aGuard;
724 for (auto const& elem : aUIElementVector)
726 if ( implts_readWindowStateData( elem.m_aName, aUIElement ) &&
727 ( elem.m_bVisible != aUIElement.m_bVisible ) && !elem.m_bMasterHide )
729 SolarMutexGuard g;
730 UIElement& rUIElement = impl_findToolbar( elem.m_aName );
731 if ( rUIElement.m_aName == elem.m_aName )
733 rUIElement.m_bVisible = aUIElement.m_bVisible;
734 implts_setLayoutDirty();
740 void ToolbarLayoutManager::setFloatingToolbarsVisibility( bool bVisible )
742 UIElementVector aUIElementVector;
743 implts_getUIElementVectorCopy( aUIElementVector );
745 SolarMutexGuard aGuard;
746 for (auto const& elem : aUIElementVector)
748 vcl::Window* pWindow = getWindowFromXUIElement( elem.m_xUIElement );
749 if ( pWindow && elem.m_bFloating )
751 if ( bVisible )
753 if ( elem.m_bVisible && !elem.m_bMasterHide )
754 pWindow->Show( true, ShowFlags::NoFocusChange | ShowFlags::NoActivate );
756 else
757 pWindow->Show( false );
762 void ToolbarLayoutManager::setVisible( bool bVisible )
764 UIElementVector aUIElementVector;
765 implts_getUIElementVectorCopy( aUIElementVector );
767 SolarMutexGuard aGuard;
768 for (auto & elem : aUIElementVector)
770 if (!elem.m_bFloating)
772 elem.m_bMasterHide = !bVisible;
773 implts_setToolbar(elem);
774 implts_setLayoutDirty();
777 vcl::Window* pWindow = getWindowFromXUIElement( elem.m_xUIElement );
778 if ( pWindow )
780 bool bSetVisible( elem.m_bVisible && bVisible );
781 if ( !bSetVisible )
782 pWindow->Hide();
783 else
785 if ( elem.m_bFloating )
786 pWindow->Show(true, ShowFlags::NoFocusChange | ShowFlags::NoActivate );
791 if ( !bVisible )
792 resetDockingArea();
795 bool ToolbarLayoutManager::dockToolbar( std::u16string_view rResourceURL, ui::DockingArea eDockingArea, const awt::Point& aPos )
797 UIElement aUIElement = implts_findToolbar( rResourceURL );
799 if ( !aUIElement.m_xUIElement.is() )
800 return false;
804 uno::Reference< awt::XWindow > xWindow( aUIElement.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
805 uno::Reference< awt::XDockableWindow > xDockWindow( xWindow, uno::UNO_QUERY );
806 if ( xDockWindow.is() )
808 if ( eDockingArea != ui::DockingArea_DOCKINGAREA_DEFAULT )
809 aUIElement.m_aDockedData.m_nDockedArea = eDockingArea;
811 if ( !isDefaultPos( aPos ))
812 aUIElement.m_aDockedData.m_aPos = aPos;
814 if ( !xDockWindow->isFloating() )
816 vcl::Window* pWindow( nullptr );
817 ToolBox* pToolBox( nullptr );
820 SolarMutexGuard aGuard;
821 pWindow = VCLUnoHelper::GetWindow( xWindow );
822 if ( pWindow && pWindow->GetType() == WindowType::TOOLBOX )
824 pToolBox = static_cast<ToolBox *>(pWindow);
826 // We have to set the alignment of the toolbox. It's possible that the toolbox is moved from a
827 // horizontal to a vertical docking area!
828 pToolBox->SetAlign( ImplConvertAlignment( aUIElement.m_aDockedData.m_nDockedArea ));
832 if ( hasDefaultPosValue( aUIElement.m_aDockedData.m_aPos ))
834 // Docking on its default position without a preset position -
835 // we have to find a good place for it.
836 ::Size aSize;
838 SolarMutexGuard aGuard;
840 if (pToolBox)
841 aSize = pToolBox->CalcWindowSizePixel( 1, ImplConvertAlignment( aUIElement.m_aDockedData.m_nDockedArea ) );
842 else if (pWindow)
843 aSize = pWindow->GetSizePixel();
846 ::Point aPixelPos;
847 awt::Point aDockPos;
848 implts_findNextDockingPos(aUIElement.m_aDockedData.m_nDockedArea, aSize, aDockPos, aPixelPos );
849 aUIElement.m_aDockedData.m_aPos = aDockPos;
853 implts_setToolbar( aUIElement );
855 if ( xDockWindow->isFloating() )
857 // ATTENTION: This will call toggleFloatingMode() via notifications which
858 // sets the floating member of the UIElement correctly!
859 xDockWindow->setFloatingMode( false );
861 else
863 implts_writeWindowStateData( aUIElement );
864 implts_sortUIElements();
866 if ( aUIElement.m_bVisible )
867 implts_setLayoutDirty();
869 return true;
872 catch (const lang::DisposedException&)
876 return false;
879 bool ToolbarLayoutManager::dockAllToolbars()
881 std::vector< OUString > aToolBarNameVector;
884 SolarMutexGuard aReadLock;
885 for (auto const& elem : m_aUIElements)
887 if (elem.m_aType == "toolbar" && elem.m_xUIElement.is() && elem.m_bFloating
888 && elem.m_bVisible)
889 aToolBarNameVector.push_back(elem.m_aName);
893 bool bResult(true);
894 const sal_uInt32 nCount = aToolBarNameVector.size();
895 for ( sal_uInt32 i = 0; i < nCount; ++i )
897 awt::Point aPoint;
898 aPoint.X = aPoint.Y = SAL_MAX_INT32;
899 bResult &= dockToolbar( aToolBarNameVector[i], ui::DockingArea_DOCKINGAREA_DEFAULT, aPoint );
902 return bResult;
905 void ToolbarLayoutManager::childWindowEvent( VclSimpleEvent const * pEvent )
907 // To enable toolbar controllers to change their image when a sub-toolbar function
908 // is activated, we need this mechanism. We have NO connection between these toolbars
909 // anymore!
910 auto pWindowEvent = dynamic_cast< const VclWindowEvent* >(pEvent);
911 if (!pWindowEvent)
912 return;
914 if ( pEvent->GetId() == VclEventId::ToolboxSelect )
916 OUString aToolbarName;
917 OUString aCommand;
918 ToolBox* pToolBox = getToolboxPtr( pWindowEvent->GetWindow() );
920 if ( pToolBox )
922 aToolbarName = retrieveToolbarNameFromHelpURL( pToolBox );
923 ToolBoxItemId nId = pToolBox->GetCurItemId();
924 if ( nId > ToolBoxItemId(0) )
925 aCommand = pToolBox->GetItemCommand( nId );
928 if ( !aToolbarName.isEmpty() && !aCommand.isEmpty() )
930 SolarMutexClearableGuard aReadLock;
931 ::std::vector< uno::Reference< ui::XUIFunctionListener > > aListenerArray;
933 for (auto const& elem : m_aUIElements)
935 if ( elem.m_xUIElement.is() )
937 uno::Reference< ui::XUIFunctionListener > xListener( elem.m_xUIElement, uno::UNO_QUERY );
938 if ( xListener.is() )
939 aListenerArray.push_back( xListener );
942 aReadLock.clear();
944 const sal_uInt32 nCount = aListenerArray.size();
945 for ( sal_uInt32 i = 0; i < nCount; ++i )
949 aListenerArray[i]->functionExecute( aToolbarName, aCommand );
951 catch (const uno::RuntimeException&)
953 throw;
955 catch (const uno::Exception&)
961 else if ( pEvent->GetId() == VclEventId::ToolboxFormatChanged )
963 if ( !implts_isToolbarCreationActive() )
965 ToolBox* pToolBox = getToolboxPtr( pWindowEvent->GetWindow() );
966 if ( pToolBox )
968 OUString aToolbarName = retrieveToolbarNameFromHelpURL( pToolBox );
969 if ( !aToolbarName.isEmpty() )
971 OUString aToolbarUrl = "private:resource/toolbar/" + aToolbarName;
973 UIElement aToolbar = implts_findToolbar( aToolbarUrl );
974 if ( aToolbar.m_xUIElement.is() && !aToolbar.m_bFloating )
976 implts_setLayoutDirty();
977 m_pParentLayouter->requestLayout();
985 void ToolbarLayoutManager::resetDockingArea()
987 SolarMutexClearableGuard aReadLock;
988 uno::Reference< awt::XWindow > xTopDockingWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_TOP)] );
989 uno::Reference< awt::XWindow > xLeftDockingWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_LEFT)] );
990 uno::Reference< awt::XWindow > xRightDockingWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_RIGHT)] );
991 uno::Reference< awt::XWindow > xBottomDockingWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_BOTTOM)] );
992 aReadLock.clear();
994 if ( xTopDockingWindow.is() )
995 xTopDockingWindow->setPosSize( 0, 0, 0, 0, awt::PosSize::POSSIZE );
996 if ( xLeftDockingWindow.is() )
997 xLeftDockingWindow->setPosSize( 0, 0, 0, 0, awt::PosSize::POSSIZE );
998 if ( xRightDockingWindow.is() )
999 xRightDockingWindow->setPosSize( 0, 0, 0, 0, awt::PosSize::POSSIZE );
1000 if ( xBottomDockingWindow.is() )
1001 xBottomDockingWindow->setPosSize( 0, 0, 0, 0, awt::PosSize::POSSIZE );
1004 void ToolbarLayoutManager::setParentWindow(
1005 const uno::Reference< awt::XVclWindowPeer >& xParentWindow )
1007 static const char DOCKINGAREASTRING[] = "dockingarea";
1009 uno::Reference< awt::XWindow > xTopDockWindow( createToolkitWindow( m_xContext, xParentWindow, DOCKINGAREASTRING ), uno::UNO_QUERY );
1010 uno::Reference< awt::XWindow > xLeftDockWindow( createToolkitWindow( m_xContext, xParentWindow, DOCKINGAREASTRING ), uno::UNO_QUERY );
1011 uno::Reference< awt::XWindow > xRightDockWindow( createToolkitWindow( m_xContext, xParentWindow, DOCKINGAREASTRING ), uno::UNO_QUERY );
1012 uno::Reference< awt::XWindow > xBottomDockWindow( createToolkitWindow( m_xContext, xParentWindow, DOCKINGAREASTRING ), uno::UNO_QUERY );
1015 SolarMutexGuard aWriteLock;
1016 m_xContainerWindow.set(xParentWindow, uno::UNO_QUERY);
1017 m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_TOP)] = xTopDockWindow;
1018 m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_LEFT)] = xLeftDockWindow;
1019 m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_RIGHT)] = xRightDockWindow;
1020 m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_BOTTOM)] = xBottomDockWindow;
1023 if ( xParentWindow.is() )
1025 SolarMutexGuard aGuard;
1026 VclPtr< ::DockingAreaWindow > pWindow = dynamic_cast< ::DockingAreaWindow* >(VCLUnoHelper::GetWindow( xTopDockWindow ) );
1027 if( pWindow )
1028 pWindow->SetAlign( WindowAlign::Top );
1029 pWindow = dynamic_cast< ::DockingAreaWindow* >(VCLUnoHelper::GetWindow( xBottomDockWindow ) );
1030 if( pWindow )
1031 pWindow->SetAlign( WindowAlign::Bottom );
1032 pWindow = dynamic_cast< ::DockingAreaWindow* >(VCLUnoHelper::GetWindow( xLeftDockWindow ) );
1033 if( pWindow )
1034 pWindow->SetAlign( WindowAlign::Left );
1035 pWindow = dynamic_cast< ::DockingAreaWindow* >(VCLUnoHelper::GetWindow( xRightDockWindow ) );
1036 if( pWindow )
1037 pWindow->SetAlign( WindowAlign::Right );
1038 implts_reparentToolbars();
1040 else
1042 destroyToolbars();
1043 resetDockingArea();
1047 void ToolbarLayoutManager::setDockingAreaOffsets( const ::tools::Rectangle& rOffsets )
1049 SolarMutexGuard g;
1050 m_aDockingAreaOffsets = rOffsets;
1051 m_bLayoutDirty = true;
1054 OUString ToolbarLayoutManager::implts_generateGenericAddonToolbarTitle( sal_Int32 nNumber ) const
1056 OUString aAddonGenericTitle(FwkResId(STR_TOOLBAR_TITLE_ADDON));
1057 const vcl::I18nHelper& rI18nHelper = Application::GetSettings().GetUILocaleI18nHelper();
1059 OUString aNumStr = rI18nHelper.GetNum( nNumber, 0, false, false );
1060 aAddonGenericTitle = aAddonGenericTitle.replaceFirst( "%num%", aNumStr );
1062 return aAddonGenericTitle;
1065 void ToolbarLayoutManager::implts_createAddonsToolBars()
1067 SolarMutexClearableGuard aWriteLock;
1068 if ( !m_pAddonOptions )
1069 m_pAddonOptions.reset( new AddonsOptions );
1071 uno::Reference< ui::XUIElementFactory > xUIElementFactory( m_xUIElementFactoryManager );
1072 uno::Reference< frame::XFrame > xFrame( m_xFrame );
1073 aWriteLock.clear();
1075 if (isPreviewFrame())
1076 return; // no addon toolbars for preview frame!
1078 uno::Sequence< uno::Sequence< beans::PropertyValue > > aAddonToolBarData;
1079 uno::Reference< ui::XUIElement > xUIElement;
1081 sal_uInt32 nCount = m_pAddonOptions->GetAddonsToolBarCount();
1083 uno::Sequence< beans::PropertyValue > aPropSeq( 2 );
1084 auto pPropSeq = aPropSeq.getArray();
1085 pPropSeq[0].Name = "Frame";
1086 pPropSeq[0].Value <<= xFrame;
1087 pPropSeq[1].Name = "ConfigurationData";
1088 for ( sal_uInt32 i = 0; i < nCount; i++ )
1090 OUString aAddonToolBarName( "private:resource/toolbar/addon_" +
1091 m_pAddonOptions->GetAddonsToolbarResourceName(i) );
1092 aAddonToolBarData = m_pAddonOptions->GetAddonsToolBarPart( i );
1093 pPropSeq[1].Value <<= aAddonToolBarData;
1095 UIElement aElement = implts_findToolbar( aAddonToolBarName );
1097 // #i79828
1098 // It's now possible that we are called more than once. Be sure to not create
1099 // add-on toolbars more than once!
1100 if ( aElement.m_xUIElement.is() )
1101 continue;
1105 xUIElement = xUIElementFactory->createUIElement( aAddonToolBarName, aPropSeq );
1106 if ( xUIElement.is() )
1108 uno::Reference< awt::XDockableWindow > xDockWindow( xUIElement->getRealInterface(), uno::UNO_QUERY );
1109 if ( xDockWindow.is() )
1113 xDockWindow->addDockableWindowListener( uno::Reference< awt::XDockableWindowListener >(this) );
1114 xDockWindow->enableDocking( true );
1115 uno::Reference< awt::XWindow > xWindow( xDockWindow, uno::UNO_QUERY );
1116 if ( xWindow.is() )
1117 xWindow->addWindowListener( uno::Reference< awt::XWindowListener >(this) );
1119 catch (const uno::Exception&)
1124 OUString aGenericAddonTitle = implts_generateGenericAddonToolbarTitle( i+1 );
1126 if ( !aElement.m_aName.isEmpty() )
1128 // Reuse a local entry so we are able to use the latest
1129 // UI changes for this document.
1130 implts_setElementData( aElement, xDockWindow );
1131 aElement.m_xUIElement = xUIElement;
1132 if ( aElement.m_aUIName.isEmpty() )
1134 aElement.m_aUIName = aGenericAddonTitle;
1135 implts_writeWindowStateData( aElement );
1138 else
1140 // Create new UI element and try to read its state data
1141 UIElement aNewToolbar( aAddonToolBarName, "toolbar", xUIElement );
1142 aNewToolbar.m_bFloating = true;
1143 implts_readWindowStateData( aAddonToolBarName, aNewToolbar );
1144 implts_setElementData( aNewToolbar, xDockWindow );
1145 if ( aNewToolbar.m_aUIName.isEmpty() )
1147 aNewToolbar.m_aUIName = aGenericAddonTitle;
1148 implts_writeWindowStateData( aNewToolbar );
1150 implts_insertToolbar( aNewToolbar );
1153 uno::Reference< awt::XWindow > xWindow( xDockWindow, uno::UNO_QUERY );
1154 if ( xWindow.is() )
1156 // Set generic title for add-on toolbar
1157 SolarMutexGuard aGuard;
1158 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
1159 if ( pWindow->GetText().isEmpty() )
1160 pWindow->SetText( aGenericAddonTitle );
1161 if ( pWindow->GetType() == WindowType::TOOLBOX )
1163 ToolBox* pToolbar = static_cast<ToolBox *>(pWindow.get());
1164 pToolbar->SetMenuType();
1169 catch (const container::NoSuchElementException&)
1172 catch (const lang::IllegalArgumentException&)
1178 void ToolbarLayoutManager::implts_createCustomToolBars()
1180 SolarMutexClearableGuard aReadLock;
1181 if ( !m_bComponentAttached )
1182 return;
1184 uno::Reference< frame::XFrame > xFrame( m_xFrame );
1185 uno::Reference< ui::XUIConfigurationManager > xModuleCfgMgr = m_xModuleCfgMgr;
1186 uno::Reference< ui::XUIConfigurationManager > xDocCfgMgr = m_xDocCfgMgr;
1187 aReadLock.clear();
1189 if ( !xFrame.is() )
1190 return;
1192 if (isPreviewFrame())
1193 return; // no custom toolbars for preview frame!
1195 uno::Sequence< uno::Sequence< beans::PropertyValue > > aTbxSeq;
1196 if ( xDocCfgMgr.is() )
1198 aTbxSeq = xDocCfgMgr->getUIElementsInfo( ui::UIElementType::TOOLBAR );
1199 implts_createCustomToolBars( aTbxSeq ); // first create all document based toolbars
1201 if ( xModuleCfgMgr.is() )
1203 aTbxSeq = xModuleCfgMgr->getUIElementsInfo( ui::UIElementType::TOOLBAR );
1204 implts_createCustomToolBars( aTbxSeq ); // second create module based toolbars
1208 void ToolbarLayoutManager::implts_createNonContextSensitiveToolBars()
1210 SolarMutexClearableGuard aReadLock;
1212 if ( !m_xPersistentWindowState.is() || !m_xFrame.is() || !m_bComponentAttached )
1213 return;
1215 uno::Reference< container::XNameAccess > xPersistentWindowState( m_xPersistentWindowState );
1216 aReadLock.clear();
1218 if (isPreviewFrame())
1219 return;
1221 std::vector< OUString > aMakeVisibleToolbars;
1225 const uno::Sequence< OUString > aToolbarNames = xPersistentWindowState->getElementNames();
1227 if ( aToolbarNames.hasElements() )
1229 OUString aElementType;
1230 OUString aElementName;
1232 aMakeVisibleToolbars.reserve(aToolbarNames.getLength());
1234 SolarMutexGuard g;
1236 for ( OUString const & aName : aToolbarNames )
1238 parseResourceURL( aName, aElementType, aElementName );
1240 // Check that we only create:
1241 // - Toolbars (the statusbar is also member of the persistent window state)
1242 // - Not custom toolbars, there are created with their own method (implts_createCustomToolbars)
1243 if ( aElementType.equalsIgnoreAsciiCase("toolbar") &&
1244 aElementName.indexOf( "custom_" ) == -1 )
1246 UIElement aNewToolbar = implts_findToolbar( aName );
1247 bool bFound = ( aNewToolbar.m_aName == aName );
1248 if ( !bFound )
1249 implts_readWindowStateData( aName, aNewToolbar );
1251 if ( aNewToolbar.m_bVisible && !aNewToolbar.m_bContextSensitive )
1253 if ( !bFound )
1254 implts_insertToolbar( aNewToolbar );
1255 aMakeVisibleToolbars.push_back( aName );
1261 catch (const uno::RuntimeException&)
1263 throw;
1265 catch (const uno::Exception&)
1269 for (auto const& rURL : aMakeVisibleToolbars)
1271 requestToolbar(rURL);
1275 void ToolbarLayoutManager::implts_createCustomToolBars( const uno::Sequence< uno::Sequence< beans::PropertyValue > >& aTbxSeqSeq )
1277 for ( const uno::Sequence< beans::PropertyValue >& rTbxSeq : aTbxSeqSeq )
1279 OUString aTbxResName;
1280 OUString aTbxTitle;
1281 for ( const beans::PropertyValue& rProp : rTbxSeq )
1283 if ( rProp.Name == "ResourceURL" )
1284 rProp.Value >>= aTbxResName;
1285 else if ( rProp.Name == "UIName" )
1286 rProp.Value >>= aTbxTitle;
1289 // Only create custom toolbars. Their name have to start with "custom_"!
1290 if ( !aTbxResName.isEmpty() && ( aTbxResName.indexOf( "custom_" ) != -1 ) )
1291 implts_createCustomToolBar( aTbxResName, aTbxTitle );
1295 void ToolbarLayoutManager::implts_createCustomToolBar( const OUString& aTbxResName, const OUString& aTitle )
1297 if ( aTbxResName.isEmpty() )
1298 return;
1300 if ( !createToolbar( aTbxResName ) )
1301 SAL_WARN("fwk.uielement", "ToolbarLayoutManager cannot create custom toolbar");
1303 uno::Reference< ui::XUIElement > xUIElement = getToolbar( aTbxResName );
1305 if ( !aTitle.isEmpty() && xUIElement.is() )
1307 SolarMutexGuard aGuard;
1309 vcl::Window* pWindow = getWindowFromXUIElement( xUIElement );
1310 if ( pWindow )
1311 pWindow->SetText( aTitle );
1315 void ToolbarLayoutManager::implts_reparentToolbars()
1317 SolarMutexClearableGuard aWriteLock;
1318 UIElementVector aUIElementVector = m_aUIElements;
1319 VclPtr<vcl::Window> pContainerWindow = VCLUnoHelper::GetWindow( m_xContainerWindow );
1320 VclPtr<vcl::Window> pTopDockWindow = VCLUnoHelper::GetWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_TOP)] );
1321 VclPtr<vcl::Window> pBottomDockWindow = VCLUnoHelper::GetWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_BOTTOM)] );
1322 VclPtr<vcl::Window> pLeftDockWindow = VCLUnoHelper::GetWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_LEFT)] );
1323 VclPtr<vcl::Window> pRightDockWindow = VCLUnoHelper::GetWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_RIGHT)] );
1324 aWriteLock.clear();
1326 SolarMutexGuard aGuard;
1327 if ( !pContainerWindow )
1328 return;
1330 for (auto const& elem : aUIElementVector)
1332 uno::Reference< ui::XUIElement > xUIElement( elem.m_xUIElement );
1333 if ( xUIElement.is() )
1335 uno::Reference< awt::XWindow > xWindow;
1338 // We have to retrieve the window reference with try/catch as it is
1339 // possible that all elements have been disposed!
1340 xWindow.set( xUIElement->getRealInterface(), uno::UNO_QUERY );
1342 catch (const uno::RuntimeException&)
1344 throw;
1346 catch (const uno::Exception&)
1350 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
1351 if ( pWindow )
1353 // Reparent our child windows according to their current state.
1354 if ( elem.m_bFloating )
1355 pWindow->SetParent( pContainerWindow );
1356 else
1358 if ( elem.m_aDockedData.m_nDockedArea == ui::DockingArea_DOCKINGAREA_TOP )
1359 pWindow->SetParent( pTopDockWindow );
1360 else if ( elem.m_aDockedData.m_nDockedArea == ui::DockingArea_DOCKINGAREA_BOTTOM )
1361 pWindow->SetParent( pBottomDockWindow );
1362 else if ( elem.m_aDockedData.m_nDockedArea == ui::DockingArea_DOCKINGAREA_LEFT )
1363 pWindow->SetParent( pLeftDockWindow );
1364 else
1365 pWindow->SetParent( pRightDockWindow );
1372 void ToolbarLayoutManager::implts_setToolbarCreation( bool bStart )
1374 SolarMutexGuard g;
1375 m_bToolbarCreation = bStart;
1378 bool ToolbarLayoutManager::implts_isToolbarCreationActive()
1380 SolarMutexGuard g;
1381 return m_bToolbarCreation;
1384 void ToolbarLayoutManager::implts_setElementData( UIElement& rElement, const uno::Reference< awt::XDockableWindow >& rDockWindow )
1386 SolarMutexClearableGuard aReadLock;
1387 bool bShowElement( rElement.m_bVisible && !rElement.m_bMasterHide && implts_isParentWindowVisible() );
1388 aReadLock.clear();
1390 uno::Reference< awt::XWindow2 > xWindow( rDockWindow, uno::UNO_QUERY );
1392 vcl::Window* pWindow( nullptr );
1393 ToolBox* pToolBox( nullptr );
1395 if ( !(rDockWindow.is() && xWindow.is()) )
1396 return;
1399 SolarMutexGuard aGuard;
1400 pWindow = VCLUnoHelper::GetWindow( xWindow );
1401 if ( pWindow )
1403 OUString aText = pWindow->GetText();
1404 if ( aText.isEmpty() )
1405 pWindow->SetText( rElement.m_aUIName );
1406 if ( rElement.m_bNoClose )
1407 pWindow->SetStyle( pWindow->GetStyle() & ~WB_CLOSEABLE );
1408 if ( pWindow->GetType() == WindowType::TOOLBOX )
1409 pToolBox = static_cast<ToolBox *>(pWindow);
1411 if ( pToolBox )
1413 pToolBox->SetButtonType( rElement.m_nStyle );
1414 if ( rElement.m_bNoClose )
1415 pToolBox->SetFloatStyle( pToolBox->GetFloatStyle() & ~WB_CLOSEABLE );
1419 if ( rElement.m_bFloating )
1421 if ( pWindow )
1423 SolarMutexGuard aGuard;
1424 OUString aText = pWindow->GetText();
1425 if ( aText.isEmpty() )
1426 pWindow->SetText( rElement.m_aUIName );
1429 awt::Point aPos(rElement.m_aFloatingData.m_aPos);
1430 bool bWriteData( false );
1431 bool bUndefPos = hasDefaultPosValue( rElement.m_aFloatingData.m_aPos );
1432 bool bSetSize = ( rElement.m_aFloatingData.m_aSize.Width != 0 &&
1433 rElement.m_aFloatingData.m_aSize.Height != 0 );
1434 rDockWindow->setFloatingMode( true );
1435 if ( bUndefPos )
1437 aPos = implts_findNextCascadeFloatingPos();
1438 rElement.m_aFloatingData.m_aPos = aPos; // set new cascaded position
1439 bWriteData = true;
1442 if( bSetSize )
1443 xWindow->setOutputSize(rElement.m_aFloatingData.m_aSize);
1444 else
1446 if( pToolBox )
1448 // set an optimal initial floating size
1449 SolarMutexGuard aGuard;
1450 ::Size aSize( pToolBox->CalcFloatingWindowSizePixel() );
1451 pToolBox->SetOutputSizePixel( aSize );
1455 // #i60882# IMPORTANT: Set position after size as it is
1456 // possible that we position some part of the toolbar
1457 // outside of the desktop. A default constructed toolbar
1458 // always has one line. Now VCL automatically
1459 // position the toolbar back into the desktop. Therefore
1460 // we resize the toolbar with the new (wrong) position.
1461 // To fix this problem we have to set the size BEFORE the
1462 // position.
1463 xWindow->setPosSize( aPos.X, aPos.Y, 0, 0, awt::PosSize::POS );
1465 if ( bWriteData )
1466 implts_writeWindowStateData( rElement );
1467 if ( bShowElement && pWindow )
1469 SolarMutexGuard aGuard;
1470 pWindow->Show( true, ShowFlags::NoFocusChange | ShowFlags::NoActivate );
1473 else
1475 bool bSetSize( false );
1476 ::Point aPixelPos;
1477 ::Size aSize;
1479 if ( pToolBox )
1481 SolarMutexGuard aGuard;
1482 pToolBox->SetAlign( ImplConvertAlignment(rElement.m_aDockedData.m_nDockedArea ) );
1483 pToolBox->SetLineCount( 1 );
1484 rDockWindow->setFloatingMode( false );
1485 if ( rElement.m_aDockedData.m_bLocked )
1486 rDockWindow->lock();
1487 aSize = pToolBox->CalcWindowSizePixel();
1488 bSetSize = true;
1490 if ( isDefaultPos( rElement.m_aDockedData.m_aPos ))
1492 awt::Point aDockPos;
1493 implts_findNextDockingPos( rElement.m_aDockedData.m_nDockedArea, aSize, aDockPos, aPixelPos );
1494 rElement.m_aDockedData.m_aPos = aDockPos;
1498 xWindow->setPosSize( aPixelPos.X(), aPixelPos.Y(), 0, 0, awt::PosSize::POS );
1499 if( bSetSize )
1500 xWindow->setOutputSize( AWTSize( aSize) );
1502 if ( pWindow )
1504 SolarMutexGuard aGuard;
1505 if ( !bShowElement )
1506 pWindow->Hide();
1511 void ToolbarLayoutManager::implts_destroyDockingAreaWindows()
1513 SolarMutexClearableGuard aWriteLock;
1514 uno::Reference< awt::XWindow > xTopDockingWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_TOP)] );
1515 uno::Reference< awt::XWindow > xLeftDockingWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_LEFT)] );
1516 uno::Reference< awt::XWindow > xRightDockingWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_RIGHT)] );
1517 uno::Reference< awt::XWindow > xBottomDockingWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_BOTTOM)] );
1518 m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_TOP)].clear();
1519 m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_LEFT)].clear();
1520 m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_RIGHT)].clear();
1521 m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_BOTTOM)].clear();
1522 aWriteLock.clear();
1524 // destroy windows
1525 xTopDockingWindow->dispose();
1526 xLeftDockingWindow->dispose();
1527 xRightDockingWindow->dispose();
1528 xBottomDockingWindow->dispose();
1531 // persistence methods
1533 bool ToolbarLayoutManager::implts_readWindowStateData( const OUString& aName, UIElement& rElementData )
1535 return LayoutManager::readWindowStateData( aName, rElementData, m_xPersistentWindowState,
1536 m_pGlobalSettings, m_bGlobalSettings, m_xContext );
1539 void ToolbarLayoutManager::implts_writeWindowStateData( const UIElement& rElementData )
1541 SolarMutexClearableGuard aWriteLock;
1542 uno::Reference< container::XNameAccess > xPersistentWindowState( m_xPersistentWindowState );
1543 aWriteLock.clear();
1545 bool bPersistent( false );
1546 uno::Reference< beans::XPropertySet > xPropSet( rElementData.m_xUIElement, uno::UNO_QUERY );
1547 if ( xPropSet.is() )
1551 // Check persistent flag of the user interface element
1552 xPropSet->getPropertyValue("Persistent") >>= bPersistent;
1554 catch (const beans::UnknownPropertyException&)
1556 bPersistent = true; // Non-configurable elements should at least store their dimension/position
1558 catch (const lang::WrappedTargetException&)
1563 if ( !(bPersistent && xPersistentWindowState.is()) )
1564 return;
1568 uno::Sequence<beans::PropertyValue> aWindowState{
1569 comphelper::makePropertyValue(WINDOWSTATE_PROPERTY_DOCKED, !rElementData.m_bFloating),
1570 comphelper::makePropertyValue(WINDOWSTATE_PROPERTY_VISIBLE, rElementData.m_bVisible),
1571 comphelper::makePropertyValue(WINDOWSTATE_PROPERTY_DOCKINGAREA,
1572 rElementData.m_aDockedData.m_nDockedArea),
1573 comphelper::makePropertyValue(WINDOWSTATE_PROPERTY_DOCKPOS,
1574 rElementData.m_aDockedData.m_aPos),
1575 comphelper::makePropertyValue(WINDOWSTATE_PROPERTY_POS,
1576 rElementData.m_aFloatingData.m_aPos),
1577 comphelper::makePropertyValue(WINDOWSTATE_PROPERTY_SIZE,
1578 rElementData.m_aFloatingData.m_aSize),
1579 comphelper::makePropertyValue(WINDOWSTATE_PROPERTY_UINAME, rElementData.m_aUIName),
1580 comphelper::makePropertyValue(WINDOWSTATE_PROPERTY_LOCKED,
1581 rElementData.m_aDockedData.m_bLocked),
1582 comphelper::makePropertyValue(WINDOWSTATE_PROPERTY_STYLE,
1583 static_cast<sal_uInt16>(rElementData.m_nStyle))
1586 OUString aName = rElementData.m_aName;
1587 if ( xPersistentWindowState->hasByName( aName ))
1589 uno::Reference< container::XNameReplace > xReplace( xPersistentWindowState, uno::UNO_QUERY );
1590 xReplace->replaceByName( aName, uno::Any( aWindowState ));
1592 else
1594 uno::Reference< container::XNameContainer > xInsert( xPersistentWindowState, uno::UNO_QUERY );
1595 xInsert->insertByName( aName, uno::Any( aWindowState ));
1598 catch (const uno::Exception&)
1603 /******************************************************************************
1604 LOOKUP PART FOR TOOLBARS
1605 ******************************************************************************/
1607 UIElement& ToolbarLayoutManager::impl_findToolbar( std::u16string_view aName )
1609 static UIElement aEmptyElement;
1611 SolarMutexGuard g;
1612 for (auto & elem : m_aUIElements)
1614 if ( elem.m_aName == aName )
1615 return elem;
1618 return aEmptyElement;
1621 UIElement ToolbarLayoutManager::implts_findToolbar( std::u16string_view aName )
1623 SolarMutexGuard g;
1624 return impl_findToolbar( aName );
1627 UIElement ToolbarLayoutManager::implts_findToolbar( const uno::Reference< uno::XInterface >& xToolbar )
1629 UIElement aToolbar;
1631 SolarMutexGuard g;
1632 for (auto const& elem : m_aUIElements)
1634 if ( elem.m_xUIElement.is() )
1636 uno::Reference< uno::XInterface > xIfac( elem.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
1637 if ( xIfac == xToolbar )
1639 aToolbar = elem;
1640 break;
1645 return aToolbar;
1648 uno::Reference< awt::XWindow > ToolbarLayoutManager::implts_getXWindow( std::u16string_view aName )
1650 uno::Reference< awt::XWindow > xWindow;
1652 SolarMutexGuard g;
1653 for (auto const& elem : m_aUIElements)
1655 if ( elem.m_aName == aName && elem.m_xUIElement.is() )
1657 xWindow.set( elem.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
1658 break;
1662 return xWindow;
1665 vcl::Window* ToolbarLayoutManager::implts_getWindow( std::u16string_view aName )
1667 uno::Reference< awt::XWindow > xWindow = implts_getXWindow( aName );
1668 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
1670 return pWindow;
1673 bool ToolbarLayoutManager::implts_insertToolbar( const UIElement& rUIElement )
1675 UIElement aTempData;
1676 bool bFound( false );
1677 bool bResult( false );
1679 aTempData = implts_findToolbar( rUIElement.m_aName );
1680 if ( aTempData.m_aName == rUIElement.m_aName )
1681 bFound = true;
1683 if ( !bFound )
1685 SolarMutexGuard g;
1686 m_aUIElements.push_back( rUIElement );
1687 bResult = true;
1690 return bResult;
1693 void ToolbarLayoutManager::implts_setToolbar( const UIElement& rUIElement )
1695 SolarMutexGuard g;
1696 UIElement& rData = impl_findToolbar( rUIElement.m_aName );
1697 if ( rData.m_aName == rUIElement.m_aName )
1698 rData = rUIElement;
1699 else
1700 m_aUIElements.push_back( rUIElement );
1703 /******************************************************************************
1704 LAYOUT CODE PART FOR TOOLBARS
1705 ******************************************************************************/
1707 awt::Point ToolbarLayoutManager::implts_findNextCascadeFloatingPos()
1709 const sal_Int32 nHotZoneX = 50;
1710 const sal_Int32 nHotZoneY = 50;
1711 const sal_Int32 nCascadeIndentX = 15;
1712 const sal_Int32 nCascadeIndentY = 15;
1714 SolarMutexClearableGuard aReadLock;
1715 uno::Reference< awt::XWindow2 > xContainerWindow( m_xContainerWindow );
1716 uno::Reference< awt::XWindow > xTopDockingWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_TOP)] );
1717 uno::Reference< awt::XWindow > xLeftDockingWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_LEFT)] );
1718 aReadLock.clear();
1720 awt::Point aStartPos( nCascadeIndentX, nCascadeIndentY );
1721 awt::Point aCurrPos( aStartPos );
1723 if ( xContainerWindow.is() )
1725 SolarMutexGuard aGuard;
1726 VclPtr<vcl::Window> pContainerWindow = VCLUnoHelper::GetWindow( xContainerWindow );
1727 if ( pContainerWindow )
1728 aStartPos = AWTPoint(pContainerWindow->OutputToScreenPixel(VCLPoint(aStartPos)));
1731 // Determine size of top and left docking area
1732 awt::Rectangle aTopRect( xTopDockingWindow->getPosSize() );
1733 awt::Rectangle aLeftRect( xLeftDockingWindow->getPosSize() );
1735 aStartPos.X += aLeftRect.Width + nCascadeIndentX;
1736 aStartPos.Y += aTopRect.Height + nCascadeIndentY;
1737 aCurrPos = aStartPos;
1739 // Try to find a cascaded position for the new floating window
1740 for (auto const& elem : m_aUIElements)
1742 if ( elem.m_xUIElement.is() )
1744 uno::Reference< awt::XDockableWindow > xDockWindow( elem.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
1745 uno::Reference< awt::XWindow > xWindow( xDockWindow, uno::UNO_QUERY );
1746 if ( xDockWindow.is() && xDockWindow->isFloating() )
1748 SolarMutexGuard aGuard;
1749 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
1750 if ( pWindow && pWindow->IsVisible() )
1752 awt::Rectangle aFloatRect = xWindow->getPosSize();
1753 if ((( aFloatRect.X - nHotZoneX ) <= aCurrPos.X ) &&
1754 ( aFloatRect.X >= aCurrPos.X ) &&
1755 (( aFloatRect.Y - nHotZoneY ) <= aCurrPos.Y ) &&
1756 ( aFloatRect.Y >= aCurrPos.Y ))
1758 aCurrPos.X = aFloatRect.X + nCascadeIndentX;
1759 aCurrPos.Y = aFloatRect.Y + nCascadeIndentY;
1766 return aCurrPos;
1769 void ToolbarLayoutManager::implts_sortUIElements()
1771 SolarMutexGuard g;
1773 std::stable_sort( m_aUIElements.begin(), m_aUIElements.end()); // first created element should first
1775 // We have to reset our temporary flags.
1776 for (auto & elem : m_aUIElements)
1777 elem.m_bUserActive = false;
1780 void ToolbarLayoutManager::implts_getUIElementVectorCopy( UIElementVector& rCopy )
1782 SolarMutexGuard g;
1783 rCopy = m_aUIElements;
1786 ::Size ToolbarLayoutManager::implts_getTopBottomDockingAreaSizes()
1788 ::Size aSize;
1789 uno::Reference< awt::XWindow > xTopDockingAreaWindow;
1790 uno::Reference< awt::XWindow > xBottomDockingAreaWindow;
1793 SolarMutexGuard aReadLock;
1794 xTopDockingAreaWindow = m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_TOP)];
1795 xBottomDockingAreaWindow = m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_BOTTOM)];
1798 if ( xTopDockingAreaWindow.is() )
1799 aSize.setWidth( xTopDockingAreaWindow->getPosSize().Height );
1800 if ( xBottomDockingAreaWindow.is() )
1801 aSize.setHeight( xBottomDockingAreaWindow->getPosSize().Height );
1803 return aSize;
1806 void ToolbarLayoutManager::implts_getDockingAreaElementInfos( ui::DockingArea eDockingArea, std::vector< SingleRowColumnWindowData >& rRowColumnsWindowData )
1808 std::vector< UIElement > aWindowVector;
1810 if (( eDockingArea < ui::DockingArea_DOCKINGAREA_TOP ) || ( eDockingArea > ui::DockingArea_DOCKINGAREA_RIGHT ))
1811 eDockingArea = ui::DockingArea_DOCKINGAREA_TOP;
1813 uno::Reference< awt::XWindow > xDockAreaWindow;
1815 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
1817 SolarMutexGuard aReadLock;
1818 aWindowVector.reserve(m_aUIElements.size());
1819 xDockAreaWindow = m_xDockAreaWindows[static_cast<int>(eDockingArea)];
1820 for (auto const& elem : m_aUIElements)
1822 if (elem.m_aDockedData.m_nDockedArea == eDockingArea && elem.m_bVisible)
1824 uno::Reference<ui::XUIElement> xUIElement(elem.m_xUIElement);
1825 if (xUIElement.is())
1827 uno::Reference<awt::XWindow> xWindow(xUIElement->getRealInterface(),
1828 uno::UNO_QUERY);
1829 uno::Reference<awt::XDockableWindow> xDockWindow(xWindow, uno::UNO_QUERY);
1830 if (xDockWindow.is())
1832 if (!elem.m_bFloating)
1834 // docked windows
1835 aWindowVector.push_back(elem);
1837 else
1839 // floating windows
1840 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow(xWindow);
1841 DockingManager* pDockMgr = vcl::Window::GetDockingManager();
1842 if (pDockMgr != nullptr)
1844 SystemWindow* pFloatingWindow = pDockMgr->GetFloatingWindow(pWindow);
1845 if (pFloatingWindow)
1847 // update the position data of the floating window
1848 if (pFloatingWindow->UpdatePositionData())
1850 awt::Rectangle aTmpRect = xWindow->getPosSize();
1851 UIElement uiElem = elem;
1852 uiElem.m_aFloatingData.m_aPos
1853 = awt::Point(aTmpRect.X, aTmpRect.Y);
1854 implts_setToolbar(uiElem);
1855 implts_writeWindowStateData(uiElem);
1865 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
1867 rRowColumnsWindowData.clear();
1869 // Collect data from windows that are on the same row/column
1870 sal_Int32 j;
1871 sal_Int32 nIndex( 0 );
1872 sal_Int32 nLastPos( 0 );
1873 sal_Int32 nCurrPos( -1 );
1874 sal_Int32 nLastRowColPixelPos( 0 );
1875 awt::Rectangle aDockAreaRect;
1877 if ( xDockAreaWindow.is() )
1878 aDockAreaRect = xDockAreaWindow->getPosSize();
1880 if ( eDockingArea == ui::DockingArea_DOCKINGAREA_TOP )
1881 nLastRowColPixelPos = 0;
1882 else if ( eDockingArea == ui::DockingArea_DOCKINGAREA_BOTTOM )
1883 nLastRowColPixelPos = aDockAreaRect.Height;
1884 else if ( eDockingArea == ui::DockingArea_DOCKINGAREA_LEFT )
1885 nLastRowColPixelPos = 0;
1886 else
1887 nLastRowColPixelPos = aDockAreaRect.Width;
1889 const sal_uInt32 nCount = aWindowVector.size();
1890 for ( j = 0; j < sal_Int32( nCount); j++ )
1892 const UIElement& rElement = aWindowVector[j];
1893 uno::Reference< awt::XWindow > xWindow;
1894 uno::Reference< ui::XUIElement > xUIElement( rElement.m_xUIElement );
1895 awt::Rectangle aPosSize;
1897 if ( !lcl_checkUIElement(xUIElement,aPosSize,xWindow) )
1898 continue;
1899 if ( isHorizontalDockingArea( eDockingArea ))
1901 if ( nCurrPos == -1 )
1903 nCurrPos = rElement.m_aDockedData.m_aPos.Y;
1904 nLastPos = 0;
1906 SingleRowColumnWindowData aRowColumnWindowData;
1907 aRowColumnWindowData.nRowColumn = nCurrPos;
1908 rRowColumnsWindowData.push_back( aRowColumnWindowData );
1911 sal_Int32 nSpace( 0 );
1912 if ( rElement.m_aDockedData.m_aPos.Y != nCurrPos )
1914 if ( eDockingArea == ui::DockingArea_DOCKINGAREA_TOP )
1915 nLastRowColPixelPos += rRowColumnsWindowData[nIndex].nStaticSize;
1916 else
1917 nLastRowColPixelPos -= rRowColumnsWindowData[nIndex].nStaticSize;
1918 ++nIndex;
1919 nLastPos = 0;
1920 nCurrPos = rElement.m_aDockedData.m_aPos.Y;
1921 SingleRowColumnWindowData aRowColumnWindowData;
1922 aRowColumnWindowData.nRowColumn = nCurrPos;
1923 rRowColumnsWindowData.push_back( aRowColumnWindowData );
1926 // Calc space before an element and store it
1927 nSpace = ( rElement.m_aDockedData.m_aPos.X - nLastPos );
1928 if ( rElement.m_aDockedData.m_aPos.X >= nLastPos )
1930 rRowColumnsWindowData[nIndex].nSpace += nSpace;
1931 nLastPos = rElement.m_aDockedData.m_aPos.X + aPosSize.Width;
1933 else
1935 nSpace = 0;
1936 nLastPos += aPosSize.Width;
1938 rRowColumnsWindowData[nIndex].aRowColumnSpace.push_back( nSpace );
1940 rRowColumnsWindowData[nIndex].aRowColumnWindows.push_back( xWindow );
1941 rRowColumnsWindowData[nIndex].aUIElementNames.push_back( rElement.m_aName );
1942 rRowColumnsWindowData[nIndex].aRowColumnWindowSizes.emplace_back(
1943 rElement.m_aDockedData.m_aPos.X,
1944 rElement.m_aDockedData.m_aPos.Y,
1945 aPosSize.Width,
1946 aPosSize.Height );
1947 if ( rRowColumnsWindowData[nIndex].nStaticSize < aPosSize.Height )
1948 rRowColumnsWindowData[nIndex].nStaticSize = aPosSize.Height;
1949 if ( eDockingArea == ui::DockingArea_DOCKINGAREA_TOP )
1950 rRowColumnsWindowData[nIndex].aRowColumnRect = awt::Rectangle( 0, nLastRowColPixelPos,
1951 aDockAreaRect.Width, aPosSize.Height );
1952 else
1953 rRowColumnsWindowData[nIndex].aRowColumnRect = awt::Rectangle( 0, ( nLastRowColPixelPos - aPosSize.Height ),
1954 aDockAreaRect.Width, aPosSize.Height );
1955 rRowColumnsWindowData[nIndex].nVarSize += aPosSize.Width + nSpace;
1957 else
1959 if ( nCurrPos == -1 )
1961 nCurrPos = rElement.m_aDockedData.m_aPos.X;
1962 nLastPos = 0;
1964 SingleRowColumnWindowData aRowColumnWindowData;
1965 aRowColumnWindowData.nRowColumn = nCurrPos;
1966 rRowColumnsWindowData.push_back( aRowColumnWindowData );
1969 sal_Int32 nSpace( 0 );
1970 if ( rElement.m_aDockedData.m_aPos.X != nCurrPos )
1972 if ( eDockingArea == ui::DockingArea_DOCKINGAREA_LEFT )
1973 nLastRowColPixelPos += rRowColumnsWindowData[nIndex].nStaticSize;
1974 else
1975 nLastRowColPixelPos -= rRowColumnsWindowData[nIndex].nStaticSize;
1976 ++nIndex;
1977 nLastPos = 0;
1978 nCurrPos = rElement.m_aDockedData.m_aPos.X;
1979 SingleRowColumnWindowData aRowColumnWindowData;
1980 aRowColumnWindowData.nRowColumn = nCurrPos;
1981 rRowColumnsWindowData.push_back( aRowColumnWindowData );
1984 // Calc space before an element and store it
1985 nSpace = ( rElement.m_aDockedData.m_aPos.Y - nLastPos );
1986 if ( rElement.m_aDockedData.m_aPos.Y > nLastPos )
1988 rRowColumnsWindowData[nIndex].nSpace += nSpace;
1989 nLastPos = rElement.m_aDockedData.m_aPos.Y + aPosSize.Height;
1991 else
1993 nSpace = 0;
1994 nLastPos += aPosSize.Height;
1996 rRowColumnsWindowData[nIndex].aRowColumnSpace.push_back( nSpace );
1998 rRowColumnsWindowData[nIndex].aRowColumnWindows.push_back( xWindow );
1999 rRowColumnsWindowData[nIndex].aUIElementNames.push_back( rElement.m_aName );
2000 rRowColumnsWindowData[nIndex].aRowColumnWindowSizes.emplace_back(
2001 rElement.m_aDockedData.m_aPos.X,
2002 rElement.m_aDockedData.m_aPos.Y,
2003 aPosSize.Width,
2004 aPosSize.Height );
2005 if ( rRowColumnsWindowData[nIndex].nStaticSize < aPosSize.Width )
2006 rRowColumnsWindowData[nIndex].nStaticSize = aPosSize.Width;
2007 if ( eDockingArea == ui::DockingArea_DOCKINGAREA_LEFT )
2008 rRowColumnsWindowData[nIndex].aRowColumnRect = awt::Rectangle( nLastRowColPixelPos, 0,
2009 aPosSize.Width, aDockAreaRect.Height );
2010 else
2011 rRowColumnsWindowData[nIndex].aRowColumnRect = awt::Rectangle( ( nLastRowColPixelPos - aPosSize.Width ), 0,
2012 aPosSize.Width, aDockAreaRect.Height );
2013 rRowColumnsWindowData[nIndex].nVarSize += aPosSize.Height + nSpace;
2018 void ToolbarLayoutManager::implts_getDockingAreaElementInfoOnSingleRowCol( ui::DockingArea eDockingArea, sal_Int32 nRowCol, SingleRowColumnWindowData& rRowColumnWindowData )
2020 std::vector< UIElement > aWindowVector;
2022 if (( eDockingArea < ui::DockingArea_DOCKINGAREA_TOP ) || ( eDockingArea > ui::DockingArea_DOCKINGAREA_RIGHT ))
2023 eDockingArea = ui::DockingArea_DOCKINGAREA_TOP;
2025 bool bHorzDockArea = isHorizontalDockingArea( eDockingArea );
2027 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
2029 SolarMutexGuard aReadLock;
2030 for (auto const& elem : m_aUIElements)
2032 if (elem.m_aDockedData.m_nDockedArea == eDockingArea)
2034 bool bSameRowCol = bHorzDockArea ? (elem.m_aDockedData.m_aPos.Y == nRowCol)
2035 : (elem.m_aDockedData.m_aPos.X == nRowCol);
2036 uno::Reference<ui::XUIElement> xUIElement(elem.m_xUIElement);
2038 if (bSameRowCol && xUIElement.is())
2040 uno::Reference<awt::XWindow> xWindow(xUIElement->getRealInterface(),
2041 uno::UNO_QUERY);
2042 if (xWindow.is())
2044 SolarMutexGuard aGuard;
2045 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow(xWindow);
2046 uno::Reference<awt::XDockableWindow> xDockWindow(xWindow, uno::UNO_QUERY);
2047 if (pWindow && elem.m_bVisible && xDockWindow.is() && !elem.m_bFloating)
2048 aWindowVector.push_back(elem); // docked windows
2054 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
2056 // Initialize structure
2057 rRowColumnWindowData.aUIElementNames.clear();
2058 rRowColumnWindowData.aRowColumnWindows.clear();
2059 rRowColumnWindowData.aRowColumnWindowSizes.clear();
2060 rRowColumnWindowData.aRowColumnSpace.clear();
2061 rRowColumnWindowData.nVarSize = 0;
2062 rRowColumnWindowData.nStaticSize = 0;
2063 rRowColumnWindowData.nSpace = 0;
2064 rRowColumnWindowData.nRowColumn = nRowCol;
2066 // Collect data from windows that are on the same row/column
2067 sal_Int32 j;
2068 sal_Int32 nLastPos( 0 );
2070 const sal_uInt32 nCount = aWindowVector.size();
2071 for ( j = 0; j < sal_Int32( nCount); j++ )
2073 const UIElement& rElement = aWindowVector[j];
2074 uno::Reference< awt::XWindow > xWindow;
2075 uno::Reference< ui::XUIElement > xUIElement( rElement.m_xUIElement );
2076 awt::Rectangle aPosSize;
2077 if ( !lcl_checkUIElement(xUIElement,aPosSize,xWindow) )
2078 continue;
2080 sal_Int32 nSpace;
2081 if ( isHorizontalDockingArea( eDockingArea ))
2083 nSpace = ( rElement.m_aDockedData.m_aPos.X - nLastPos );
2085 // Calc space before an element and store it
2086 if ( rElement.m_aDockedData.m_aPos.X > nLastPos )
2087 rRowColumnWindowData.nSpace += nSpace;
2088 else
2089 nSpace = 0;
2091 nLastPos = rElement.m_aDockedData.m_aPos.X + aPosSize.Width;
2093 rRowColumnWindowData.aRowColumnWindowSizes.emplace_back(
2094 rElement.m_aDockedData.m_aPos.X, rElement.m_aDockedData.m_aPos.Y,
2095 aPosSize.Width, aPosSize.Height );
2096 if ( rRowColumnWindowData.nStaticSize < aPosSize.Height )
2097 rRowColumnWindowData.nStaticSize = aPosSize.Height;
2098 rRowColumnWindowData.nVarSize += aPosSize.Width;
2100 else
2102 // Calc space before an element and store it
2103 nSpace = ( rElement.m_aDockedData.m_aPos.Y - nLastPos );
2104 if ( rElement.m_aDockedData.m_aPos.Y > nLastPos )
2105 rRowColumnWindowData.nSpace += nSpace;
2106 else
2107 nSpace = 0;
2109 nLastPos = rElement.m_aDockedData.m_aPos.Y + aPosSize.Height;
2111 rRowColumnWindowData.aRowColumnWindowSizes.emplace_back(
2112 rElement.m_aDockedData.m_aPos.X, rElement.m_aDockedData.m_aPos.Y,
2113 aPosSize.Width, aPosSize.Height );
2114 if ( rRowColumnWindowData.nStaticSize < aPosSize.Width )
2115 rRowColumnWindowData.nStaticSize = aPosSize.Width;
2116 rRowColumnWindowData.nVarSize += aPosSize.Height;
2119 rRowColumnWindowData.aUIElementNames.push_back( rElement.m_aName );
2120 rRowColumnWindowData.aRowColumnWindows.push_back( xWindow );
2121 rRowColumnWindowData.aRowColumnSpace.push_back( nSpace );
2122 rRowColumnWindowData.nVarSize += nSpace;
2126 ::tools::Rectangle ToolbarLayoutManager::implts_getWindowRectFromRowColumn(
2127 ui::DockingArea DockingArea,
2128 const SingleRowColumnWindowData& rRowColumnWindowData,
2129 const ::Point& rMousePos,
2130 std::u16string_view rExcludeElementName )
2132 ::tools::Rectangle aWinRect;
2134 if (( DockingArea < ui::DockingArea_DOCKINGAREA_TOP ) || ( DockingArea > ui::DockingArea_DOCKINGAREA_RIGHT ))
2135 DockingArea = ui::DockingArea_DOCKINGAREA_TOP;
2137 if ( rRowColumnWindowData.aRowColumnWindows.empty() )
2138 return aWinRect;
2139 else
2141 SolarMutexClearableGuard aReadLock;
2142 VclPtr<vcl::Window> pContainerWindow( VCLUnoHelper::GetWindow( m_xContainerWindow ));
2143 VclPtr<vcl::Window> pDockingAreaWindow( VCLUnoHelper::GetWindow( m_xDockAreaWindows[static_cast<int>(DockingArea)] ));
2144 aReadLock.clear();
2146 // Calc correct position of the column/row rectangle to be able to compare it with mouse pos/tracking rect
2147 SolarMutexGuard aGuard;
2149 // Retrieve output size from container Window
2150 if ( pDockingAreaWindow && pContainerWindow )
2152 const sal_uInt32 nCount = rRowColumnWindowData.aRowColumnWindows.size();
2153 for ( sal_uInt32 i = 0; i < nCount; i++ )
2155 awt::Rectangle aWindowRect = rRowColumnWindowData.aRowColumnWindows[i]->getPosSize();
2156 ::tools::Rectangle aRect( aWindowRect.X, aWindowRect.Y, aWindowRect.X+aWindowRect.Width, aWindowRect.Y+aWindowRect.Height );
2157 aRect.SetPos( pContainerWindow->ScreenToOutputPixel( pDockingAreaWindow->OutputToScreenPixel( aRect.TopLeft() )));
2158 if ( aRect.Contains( rMousePos ))
2160 // Check if we have found the excluded element. If yes, we have to provide an empty rectangle.
2161 // We prevent that a toolbar cannot be moved when the mouse pointer is inside its own rectangle!
2162 if ( rExcludeElementName != rRowColumnWindowData.aUIElementNames[i] )
2163 return aRect;
2164 else
2165 break;
2171 return aWinRect;
2174 ::tools::Rectangle ToolbarLayoutManager::implts_determineFrontDockingRect(
2175 ui::DockingArea eDockingArea,
2176 sal_Int32 nRowCol,
2177 const ::tools::Rectangle& rDockedElementRect,
2178 std::u16string_view rMovedElementName,
2179 const ::tools::Rectangle& rMovedElementRect )
2181 SingleRowColumnWindowData aRowColumnWindowData;
2183 bool bHorzDockArea( isHorizontalDockingArea( eDockingArea ));
2184 implts_getDockingAreaElementInfoOnSingleRowCol( eDockingArea, nRowCol, aRowColumnWindowData );
2185 if ( aRowColumnWindowData.aRowColumnWindows.empty() )
2186 return rMovedElementRect;
2187 else
2189 sal_Int32 nSpace( 0 );
2190 ::tools::Rectangle aFrontDockingRect( rMovedElementRect );
2191 const sal_uInt32 nCount = aRowColumnWindowData.aRowColumnWindows.size();
2192 for ( sal_uInt32 i = 0; i < nCount; i++ )
2194 if ( bHorzDockArea )
2196 if ( aRowColumnWindowData.aRowColumnWindowSizes[i].X >= rDockedElementRect.Left() )
2198 nSpace += aRowColumnWindowData.aRowColumnSpace[i];
2199 break;
2201 else if ( aRowColumnWindowData.aUIElementNames[i] == rMovedElementName )
2202 nSpace += aRowColumnWindowData.aRowColumnWindowSizes[i].Width +
2203 aRowColumnWindowData.aRowColumnSpace[i];
2204 else
2205 nSpace = 0;
2207 else
2209 if ( aRowColumnWindowData.aRowColumnWindowSizes[i].Y >= rDockedElementRect.Top() )
2211 nSpace += aRowColumnWindowData.aRowColumnSpace[i];
2212 break;
2214 else if ( aRowColumnWindowData.aUIElementNames[i] == rMovedElementName )
2215 nSpace += aRowColumnWindowData.aRowColumnWindowSizes[i].Height +
2216 aRowColumnWindowData.aRowColumnSpace[i];
2217 else
2218 nSpace = 0;
2222 if ( nSpace > 0 )
2224 sal_Int32 nMove = std::min( nSpace, static_cast<sal_Int32>(aFrontDockingRect.getOpenWidth()) );
2225 if ( bHorzDockArea )
2226 aFrontDockingRect.Move( -nMove, 0 );
2227 else
2228 aFrontDockingRect.Move( 0, -nMove );
2231 return aFrontDockingRect;
2235 void ToolbarLayoutManager::implts_findNextDockingPos( ui::DockingArea DockingArea, const ::Size& aUIElementSize, awt::Point& rVirtualPos, ::Point& rPixelPos )
2237 SolarMutexClearableGuard aReadLock;
2238 if (( DockingArea < ui::DockingArea_DOCKINGAREA_TOP ) || ( DockingArea > ui::DockingArea_DOCKINGAREA_RIGHT ))
2239 DockingArea = ui::DockingArea_DOCKINGAREA_TOP;
2240 uno::Reference< awt::XWindow > xDockingWindow( m_xDockAreaWindows[static_cast<int>(DockingArea)] );
2241 ::Size aDockingWinSize;
2243 // Retrieve output size from container Window
2244 vcl::Window* pDockingWindow = VCLUnoHelper::GetWindow( xDockingWindow );
2245 if ( pDockingWindow )
2246 aDockingWinSize = pDockingWindow->GetOutputSizePixel();
2247 aReadLock.clear();
2249 sal_Int32 nFreeRowColPixelPos( 0 );
2250 sal_Int32 nMaxSpace( 0 );
2251 sal_Int32 nNeededSpace( 0 );
2252 sal_Int32 nTopDockingAreaSize( 0 );
2254 if ( isHorizontalDockingArea( DockingArea ))
2256 nMaxSpace = aDockingWinSize.Width();
2257 nNeededSpace = aUIElementSize.Width();
2259 else
2261 nMaxSpace = aDockingWinSize.Height();
2262 nNeededSpace = aUIElementSize.Height();
2263 nTopDockingAreaSize = implts_getTopBottomDockingAreaSizes().Width();
2266 std::vector< SingleRowColumnWindowData > aRowColumnsWindowData;
2268 implts_getDockingAreaElementInfos( DockingArea, aRowColumnsWindowData );
2269 sal_Int32 nPixelPos( 0 );
2270 const sal_uInt32 nCount = aRowColumnsWindowData.size();
2271 for ( sal_uInt32 i = 0; i < nCount; i++ )
2273 SingleRowColumnWindowData& rRowColumnWindowData = aRowColumnsWindowData[i];
2275 if (( DockingArea == ui::DockingArea_DOCKINGAREA_BOTTOM ) ||
2276 ( DockingArea == ui::DockingArea_DOCKINGAREA_RIGHT ))
2277 nPixelPos += rRowColumnWindowData.nStaticSize;
2279 if ((( nMaxSpace - rRowColumnWindowData.nVarSize ) >= nNeededSpace ) ||
2280 ( rRowColumnWindowData.nSpace >= nNeededSpace ))
2282 // Check current row where we can find the needed space
2283 sal_Int32 nCurrPos( 0 );
2284 const sal_uInt32 nWindowSizesCount = rRowColumnWindowData.aRowColumnWindowSizes.size();
2285 for ( sal_uInt32 j = 0; j < nWindowSizesCount; j++ )
2287 awt::Rectangle rRect = rRowColumnWindowData.aRowColumnWindowSizes[j];
2288 sal_Int32& rSpace = rRowColumnWindowData.aRowColumnSpace[j];
2289 if ( isHorizontalDockingArea( DockingArea ))
2291 if ( rSpace >= nNeededSpace )
2293 rVirtualPos = awt::Point( nCurrPos, rRowColumnWindowData.nRowColumn );
2294 if ( DockingArea == ui::DockingArea_DOCKINGAREA_TOP )
2295 rPixelPos = ::Point( nCurrPos, nPixelPos );
2296 else
2297 rPixelPos = ::Point( nCurrPos, aDockingWinSize.Height() - nPixelPos );
2298 return;
2300 nCurrPos = rRect.X + rRect.Width;
2302 else
2304 if ( rSpace >= nNeededSpace )
2306 rVirtualPos = awt::Point( rRowColumnWindowData.nRowColumn, nCurrPos );
2307 if ( DockingArea == ui::DockingArea_DOCKINGAREA_LEFT )
2308 rPixelPos = ::Point( nPixelPos, nTopDockingAreaSize + nCurrPos );
2309 else
2310 rPixelPos = ::Point( aDockingWinSize.Width() - nPixelPos , nTopDockingAreaSize + nCurrPos );
2311 return;
2313 nCurrPos = rRect.Y + rRect.Height;
2317 if (( nCurrPos + nNeededSpace ) <= nMaxSpace )
2319 if ( isHorizontalDockingArea( DockingArea ))
2321 rVirtualPos = awt::Point( nCurrPos, rRowColumnWindowData.nRowColumn );
2322 if ( DockingArea == ui::DockingArea_DOCKINGAREA_TOP )
2323 rPixelPos = ::Point( nCurrPos, nPixelPos );
2324 else
2325 rPixelPos = ::Point( nCurrPos, aDockingWinSize.Height() - nPixelPos );
2326 return;
2328 else
2330 rVirtualPos = awt::Point( rRowColumnWindowData.nRowColumn, nCurrPos );
2331 if ( DockingArea == ui::DockingArea_DOCKINGAREA_LEFT )
2332 rPixelPos = ::Point( nPixelPos, nTopDockingAreaSize + nCurrPos );
2333 else
2334 rPixelPos = ::Point( aDockingWinSize.Width() - nPixelPos , nTopDockingAreaSize + nCurrPos );
2335 return;
2340 if (( DockingArea == ui::DockingArea_DOCKINGAREA_TOP ) || ( DockingArea == ui::DockingArea_DOCKINGAREA_LEFT ))
2341 nPixelPos += rRowColumnWindowData.nStaticSize;
2344 sal_Int32 nNextFreeRowCol( 0 );
2345 sal_Int32 nRowColumnsCount = aRowColumnsWindowData.size();
2346 if ( nRowColumnsCount > 0 )
2347 nNextFreeRowCol = aRowColumnsWindowData[nRowColumnsCount-1].nRowColumn+1;
2348 else
2349 nNextFreeRowCol = 0;
2351 if ( nNextFreeRowCol == 0 )
2353 if ( DockingArea == ui::DockingArea_DOCKINGAREA_BOTTOM )
2354 nFreeRowColPixelPos = aDockingWinSize.Height() - aUIElementSize.Height();
2355 else if ( DockingArea == ui::DockingArea_DOCKINGAREA_RIGHT )
2356 nFreeRowColPixelPos = aDockingWinSize.Width() - aUIElementSize.Width();
2359 if ( isHorizontalDockingArea( DockingArea ))
2361 rVirtualPos = awt::Point( 0, nNextFreeRowCol );
2362 if ( DockingArea == ui::DockingArea_DOCKINGAREA_TOP )
2363 rPixelPos = ::Point( 0, nFreeRowColPixelPos );
2364 else
2365 rPixelPos = ::Point( 0, aDockingWinSize.Height() - nFreeRowColPixelPos );
2367 else
2369 rVirtualPos = awt::Point( nNextFreeRowCol, 0 );
2370 rPixelPos = ::Point( aDockingWinSize.Width() - nFreeRowColPixelPos, 0 );
2374 void ToolbarLayoutManager::implts_calcWindowPosSizeOnSingleRowColumn(
2375 sal_Int32 nDockingArea,
2376 sal_Int32 nOffset,
2377 SingleRowColumnWindowData& rRowColumnWindowData,
2378 const ::Size& rContainerSize )
2380 sal_Int32 nDiff(0);
2381 sal_Int32 nRCSpace( rRowColumnWindowData.nSpace );
2382 sal_Int32 nContainerClientSize(0);
2384 if ( rRowColumnWindowData.aRowColumnWindows.empty() )
2385 return;
2387 if ( isHorizontalDockingArea( nDockingArea ))
2389 nContainerClientSize = rContainerSize.Width();
2390 nDiff = nContainerClientSize - rRowColumnWindowData.nVarSize;
2392 else
2394 sal_Int32 nTopDockingAreaSize = implts_getTopBottomDockingAreaSizes().Width();
2395 sal_Int32 nBottomDockingAreaSize = implts_getTopBottomDockingAreaSizes().Height();
2396 nContainerClientSize = ( rContainerSize.Height() - nTopDockingAreaSize - nBottomDockingAreaSize );
2397 nDiff = nContainerClientSize - rRowColumnWindowData.nVarSize;
2400 const sal_uInt32 nCount = rRowColumnWindowData.aRowColumnWindowSizes.size();
2401 if (( nDiff < 0 ) && ( nRCSpace > 0 ))
2403 // First we try to reduce the size of blank space before/behind docked windows
2404 sal_Int32 i = nCount - 1;
2405 while ( i >= 0 )
2407 sal_Int32 nSpace = rRowColumnWindowData.aRowColumnSpace[i];
2408 if ( nSpace >= -nDiff )
2410 if ( isHorizontalDockingArea( nDockingArea ))
2412 // Try to move this and all user elements behind with the calculated difference
2413 for ( sal_uInt32 j = i; j < nCount; j++ )
2414 rRowColumnWindowData.aRowColumnWindowSizes[j].X += nDiff;
2416 else
2418 // Try to move this and all user elements behind with the calculated difference
2419 for ( sal_uInt32 j = i; j < nCount; j++ )
2420 rRowColumnWindowData.aRowColumnWindowSizes[j].Y += nDiff;
2422 nDiff = 0;
2424 break;
2426 else if ( nSpace > 0 )
2428 if ( isHorizontalDockingArea( nDockingArea ))
2430 // Try to move this and all user elements behind with the calculated difference
2431 for ( sal_uInt32 j = i; j < nCount; j++ )
2432 rRowColumnWindowData.aRowColumnWindowSizes[j].X -= nSpace;
2434 else
2436 // Try to move this and all user elements behind with the calculated difference
2437 for ( sal_uInt32 j = i; j < nCount; j++ )
2438 rRowColumnWindowData.aRowColumnWindowSizes[j].Y -= nSpace;
2440 nDiff += nSpace;
2442 --i;
2446 // Check if we have to reduce further
2447 if ( nDiff < 0 )
2449 // Now we have to reduce the size of certain docked windows
2450 sal_Int32 i = sal_Int32( nCount - 1 );
2451 while ( i >= 0 )
2453 awt::Rectangle& rWinRect = rRowColumnWindowData.aRowColumnWindowSizes[i];
2454 ::Size aMinSize;
2456 SolarMutexGuard aGuard;
2458 uno::Reference< awt::XWindow > xWindow = rRowColumnWindowData.aRowColumnWindows[i];
2459 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
2460 if ( pWindow && pWindow->GetType() == WindowType::TOOLBOX )
2461 aMinSize = static_cast<ToolBox *>(pWindow.get())->CalcMinimumWindowSizePixel();
2464 if ( !aMinSize.IsEmpty() )
2466 if ( isHorizontalDockingArea( nDockingArea ))
2468 sal_Int32 nMaxReducation = rWinRect.Width - aMinSize.Width();
2469 if ( nMaxReducation >= -nDiff )
2471 rWinRect.Width = rWinRect.Width + nDiff;
2472 nDiff = 0;
2474 else
2476 rWinRect.Width = aMinSize.Width();
2477 nDiff += nMaxReducation;
2480 // Try to move this and all user elements behind with the calculated difference
2481 for ( sal_uInt32 j = i; j < nCount; j++ )
2482 rRowColumnWindowData.aRowColumnWindowSizes[j].X += nDiff;
2484 else
2486 sal_Int32 nMaxReducation = rWinRect.Height - aMinSize.Height();
2487 if ( nMaxReducation >= -nDiff )
2489 rWinRect.Height = rWinRect.Height + nDiff;
2490 nDiff = 0;
2492 else
2494 rWinRect.Height = aMinSize.Height();
2495 nDiff += nMaxReducation;
2498 // Try to move this and all user elements behind with the calculated difference
2499 for ( sal_uInt32 j = i; j < nCount; j++ )
2500 rRowColumnWindowData.aRowColumnWindowSizes[j].Y += nDiff;
2504 if ( nDiff >= 0 )
2505 break;
2507 --i;
2511 SolarMutexClearableGuard aReadLock;
2512 VclPtr<vcl::Window> pDockAreaWindow = VCLUnoHelper::GetWindow( m_xDockAreaWindows[nDockingArea] );
2513 aReadLock.clear();
2515 sal_Int32 nCurrPos( 0 );
2517 SolarMutexGuard aGuard;
2518 for ( sal_uInt32 i = 0; i < nCount; i++ )
2520 uno::Reference< awt::XWindow > xWindow = rRowColumnWindowData.aRowColumnWindows[i];
2521 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
2522 vcl::Window* pOldParentWindow = pWindow->GetParent();
2524 if ( pDockAreaWindow != pOldParentWindow )
2525 pWindow->SetParent( pDockAreaWindow );
2527 awt::Rectangle aWinRect = rRowColumnWindowData.aRowColumnWindowSizes[i];
2528 if ( isHorizontalDockingArea( nDockingArea ))
2530 if ( aWinRect.X < nCurrPos )
2531 aWinRect.X = nCurrPos;
2532 pWindow->SetPosSizePixel( ::Point( aWinRect.X, nOffset ), ::Size( aWinRect.Width, rRowColumnWindowData.nStaticSize ));
2533 pWindow->Show( true, ShowFlags::NoFocusChange | ShowFlags::NoActivate );
2534 nCurrPos += ( aWinRect.X - nCurrPos ) + aWinRect.Width;
2536 else
2538 if ( aWinRect.Y < nCurrPos )
2539 aWinRect.Y = nCurrPos;
2540 pWindow->SetPosSizePixel( ::Point( nOffset, aWinRect.Y ), ::Size( rRowColumnWindowData.nStaticSize, aWinRect.Height ));
2541 pWindow->Show( true, ShowFlags::NoFocusChange | ShowFlags::NoActivate );
2542 nCurrPos += ( aWinRect.Y - nCurrPos ) + aWinRect.Height;
2547 void ToolbarLayoutManager::implts_setLayoutDirty()
2549 SolarMutexGuard g;
2550 m_bLayoutDirty = true;
2553 void ToolbarLayoutManager::implts_setLayoutInProgress( bool bInProgress )
2555 SolarMutexGuard g;
2556 m_bLayoutInProgress = bInProgress;
2559 ::tools::Rectangle ToolbarLayoutManager::implts_calcHotZoneRect( const ::tools::Rectangle& rRect, sal_Int32 nHotZoneOffset )
2561 ::tools::Rectangle aRect( rRect );
2563 aRect.AdjustLeft( -nHotZoneOffset );
2564 aRect.AdjustTop( -nHotZoneOffset );
2565 aRect.AdjustRight(nHotZoneOffset );
2566 aRect.AdjustBottom(nHotZoneOffset );
2568 return aRect;
2571 void ToolbarLayoutManager::implts_calcDockingPosSize(
2572 UIElement& rUIElement,
2573 DockingOperation& rDockingOperation,
2574 ::tools::Rectangle& rTrackingRect,
2575 const Point& rMousePos )
2577 SolarMutexResettableGuard aReadLock;
2578 uno::Reference< awt::XWindow2 > xContainerWindow( m_xContainerWindow );
2579 ::Size aContainerWinSize;
2580 vcl::Window* pContainerWindow( nullptr );
2581 ::tools::Rectangle aDockingAreaOffsets( m_aDockingAreaOffsets );
2582 aReadLock.clear();
2584 if ( !rUIElement.m_xUIElement.is() )
2586 rTrackingRect = ::tools::Rectangle();
2587 return;
2591 // Retrieve output size from container Window
2592 SolarMutexGuard aGuard;
2593 pContainerWindow = VCLUnoHelper::GetWindow( xContainerWindow );
2594 aContainerWinSize = pContainerWindow->GetOutputSizePixel();
2597 vcl::Window* pDockingAreaWindow( nullptr );
2598 uno::Reference< awt::XWindow > xWindow( rUIElement.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
2599 uno::Reference< awt::XWindow > xDockingAreaWindow;
2600 ::tools::Rectangle aTrackingRect( rTrackingRect );
2601 ui::DockingArea eDockedArea( rUIElement.m_aDockedData.m_nDockedArea );
2602 sal_Int32 nTopDockingAreaSize( implts_getTopBottomDockingAreaSizes().Width() );
2603 sal_Int32 nBottomDockingAreaSize( implts_getTopBottomDockingAreaSizes().Height() );
2604 bool bHorizontalDockArea(( eDockedArea == ui::DockingArea_DOCKINGAREA_TOP ) ||
2605 ( eDockedArea == ui::DockingArea_DOCKINGAREA_BOTTOM ));
2606 sal_Int32 nMaxLeftRightDockAreaSize = aContainerWinSize.Height() -
2607 nTopDockingAreaSize -
2608 nBottomDockingAreaSize -
2609 aDockingAreaOffsets.Top() -
2610 aDockingAreaOffsets.Bottom();
2611 ::tools::Rectangle aDockingAreaRect;
2613 aReadLock.reset();
2614 xDockingAreaWindow = m_xDockAreaWindows[static_cast<int>(eDockedArea)];
2615 aReadLock.clear();
2618 SolarMutexGuard aGuard;
2619 pDockingAreaWindow = VCLUnoHelper::GetWindow( xDockingAreaWindow );
2620 VclPtr<vcl::Window> pDockWindow = VCLUnoHelper::GetWindow( xWindow );
2621 ToolBox* pToolBox( nullptr );
2622 if ( pDockWindow && pDockWindow->GetType() == WindowType::TOOLBOX )
2623 pToolBox = static_cast<ToolBox *>(pDockWindow.get());
2625 aDockingAreaRect = ::tools::Rectangle( pDockingAreaWindow->GetPosPixel(), pDockingAreaWindow->GetSizePixel() );
2626 if ( pToolBox )
2628 // docked toolbars always have one line
2629 ::Size aSize = pToolBox->CalcWindowSizePixel( 1, ImplConvertAlignment( eDockedArea ) );
2630 aTrackingRect.SetSize( ::Size( aSize.Width(), aSize.Height() ));
2634 // default docking operation, dock on the given row/column
2635 bool bOpOutsideOfDockingArea( !aDockingAreaRect.Contains( rMousePos ));
2637 std::vector< SingleRowColumnWindowData > aRowColumnsWindowData;
2639 rDockingOperation = DOCKOP_ON_COLROW;
2640 implts_getDockingAreaElementInfos( eDockedArea, aRowColumnsWindowData );
2642 // determine current first row/column and last row/column
2643 sal_Int32 nMaxRowCol( -1 );
2644 sal_Int32 nMinRowCol( SAL_MAX_INT32 );
2645 const sal_uInt32 nCount = aRowColumnsWindowData.size();
2646 for ( sal_uInt32 i = 0; i < nCount; i++ )
2648 if ( aRowColumnsWindowData[i].nRowColumn > nMaxRowCol )
2649 nMaxRowCol = aRowColumnsWindowData[i].nRowColumn;
2650 if ( aRowColumnsWindowData[i].nRowColumn < nMinRowCol )
2651 nMinRowCol = aRowColumnsWindowData[i].nRowColumn;
2654 if ( !bOpOutsideOfDockingArea )
2656 // docking inside our docking area
2657 sal_Int32 nIndex( -1 );
2658 sal_Int32 nRowCol( -1 );
2659 ::tools::Rectangle aWindowRect;
2660 ::tools::Rectangle aRowColumnRect;
2662 const sal_uInt32 nWindowDataCount = aRowColumnsWindowData.size();
2663 for ( sal_uInt32 i = 0; i < nWindowDataCount; i++ )
2665 ::tools::Rectangle aRect( aRowColumnsWindowData[i].aRowColumnRect.X,
2666 aRowColumnsWindowData[i].aRowColumnRect.Y,
2667 aRowColumnsWindowData[i].aRowColumnRect.X + aRowColumnsWindowData[i].aRowColumnRect.Width,
2668 aRowColumnsWindowData[i].aRowColumnRect.Y + aRowColumnsWindowData[i].aRowColumnRect.Height );
2671 // Calc correct position of the column/row rectangle to be able to compare it with mouse pos/tracking rect
2672 SolarMutexGuard aGuard;
2673 aRect.SetPos( pContainerWindow->ScreenToOutputPixel( pDockingAreaWindow->OutputToScreenPixel( aRect.TopLeft() )));
2676 bool bIsInsideRowCol( aRect.Contains( rMousePos ) );
2677 if ( bIsInsideRowCol )
2679 nIndex = i;
2680 nRowCol = aRowColumnsWindowData[i].nRowColumn;
2681 rDockingOperation = implts_determineDockingOperation( eDockedArea, aRect, rMousePos );
2682 aWindowRect = implts_getWindowRectFromRowColumn( eDockedArea, aRowColumnsWindowData[i], rMousePos, rUIElement.m_aName );
2683 aRowColumnRect = aRect;
2684 break;
2688 OSL_ENSURE( ( nIndex >= 0 ) && ( nRowCol >= 0 ), "Impossible case - no row/column found but mouse pointer is inside our docking area" );
2689 if (( nIndex >= 0 ) && ( nRowCol >= 0 ))
2691 if ( rDockingOperation == DOCKOP_ON_COLROW )
2693 if ( !aWindowRect.IsEmpty())
2695 // Tracking rect is on a row/column and mouse is over a docked toolbar.
2696 // Determine if the tracking rect must be located before/after the docked toolbar.
2698 ::tools::Rectangle aUIElementRect( aWindowRect );
2699 sal_Int32 nMiddle( bHorizontalDockArea ? ( aWindowRect.Left() + aWindowRect.getOpenWidth() / 2 ) :
2700 ( aWindowRect.Top() + aWindowRect.getOpenHeight() / 2 ));
2701 bool bInsertBefore( bHorizontalDockArea ? ( rMousePos.X() < nMiddle ) : ( rMousePos.Y() < nMiddle ));
2702 if ( bInsertBefore )
2704 if ( bHorizontalDockArea )
2706 sal_Int32 nSize = std::clamp( sal_Int32(aContainerWinSize.Width() - aWindowRect.Left()),
2707 sal_Int32(0), sal_Int32(aTrackingRect.getOpenWidth()) );
2708 if ( nSize == 0 )
2709 nSize = aWindowRect.getOpenWidth();
2711 aUIElementRect.SetSize( ::Size( nSize, aWindowRect.getOpenHeight() ));
2712 aWindowRect = implts_determineFrontDockingRect( eDockedArea, nRowCol, aWindowRect,rUIElement.m_aName, aUIElementRect );
2714 // Set virtual position
2715 rUIElement.m_aDockedData.m_aPos.X = aWindowRect.Left();
2716 rUIElement.m_aDockedData.m_aPos.Y = nRowCol;
2718 else
2720 sal_Int32 nSize = std::clamp( sal_Int32(nTopDockingAreaSize + nMaxLeftRightDockAreaSize - aWindowRect.Top()),
2721 sal_Int32(0), sal_Int32(aTrackingRect.getOpenHeight()) );
2722 if ( nSize == 0 )
2723 nSize = aWindowRect.getOpenHeight();
2725 aUIElementRect.SetSize( ::Size( aWindowRect.getOpenWidth(), nSize ));
2726 aWindowRect = implts_determineFrontDockingRect( eDockedArea, nRowCol, aWindowRect, rUIElement.m_aName, aUIElementRect );
2728 // Set virtual position
2729 sal_Int32 nPosY = pDockingAreaWindow->ScreenToOutputPixel(
2730 pContainerWindow->OutputToScreenPixel( aWindowRect.TopLeft() )).Y();
2731 rUIElement.m_aDockedData.m_aPos.X = nRowCol;
2732 rUIElement.m_aDockedData.m_aPos.Y = nPosY;
2735 rTrackingRect = aWindowRect;
2736 return;
2738 else
2740 if ( bHorizontalDockArea )
2742 sal_Int32 nSize = ::std::clamp( sal_Int32(aContainerWinSize.Width() - aWindowRect.Right()),
2743 sal_Int32(0), sal_Int32(aTrackingRect.getOpenWidth()) );
2744 if ( nSize == 0 )
2746 aUIElementRect.SetPos( ::Point( aContainerWinSize.Width() - aTrackingRect.getOpenWidth(), aWindowRect.Top() ));
2747 aUIElementRect.SetSize( ::Size( aTrackingRect.getOpenWidth(), aWindowRect.getOpenHeight() ));
2748 rUIElement.m_aDockedData.m_aPos.X = aUIElementRect.Left();
2751 else
2753 aUIElementRect.SetPos( ::Point( aWindowRect.Right(), aWindowRect.Top() ));
2754 aUIElementRect.SetSize( ::Size( nSize, aWindowRect.getOpenHeight() ));
2755 rUIElement.m_aDockedData.m_aPos.X = aWindowRect.Right();
2758 // Set virtual position
2759 rUIElement.m_aDockedData.m_aPos.Y = nRowCol;
2761 else
2763 sal_Int32 nSize = std::clamp( sal_Int32(nTopDockingAreaSize + nMaxLeftRightDockAreaSize - aWindowRect.Bottom()),
2764 sal_Int32(0), sal_Int32(aTrackingRect.getOpenHeight()) );
2765 aUIElementRect.SetPos( ::Point( aWindowRect.Left(), aWindowRect.Bottom() ));
2766 aUIElementRect.SetSize( ::Size( aWindowRect.getOpenWidth(), nSize ));
2768 // Set virtual position
2769 sal_Int32 nPosY( 0 );
2771 SolarMutexGuard aGuard;
2772 nPosY = pDockingAreaWindow->ScreenToOutputPixel(
2773 pContainerWindow->OutputToScreenPixel( aWindowRect.BottomRight() )).Y();
2775 rUIElement.m_aDockedData.m_aPos.X = nRowCol;
2776 rUIElement.m_aDockedData.m_aPos.Y = nPosY;
2779 rTrackingRect = aUIElementRect;
2780 return;
2783 else
2785 implts_setTrackingRect( eDockedArea, rMousePos, aTrackingRect );
2786 rTrackingRect = implts_calcTrackingAndElementRect(
2787 eDockedArea, nRowCol, rUIElement,
2788 aTrackingRect, aRowColumnRect, aContainerWinSize );
2789 return;
2792 else
2794 if ((( nRowCol == nMinRowCol ) && ( rDockingOperation == DOCKOP_BEFORE_COLROW )) ||
2795 (( nRowCol == nMaxRowCol ) && ( rDockingOperation == DOCKOP_AFTER_COLROW )))
2796 bOpOutsideOfDockingArea = true;
2797 else
2799 // handle docking before/after a row
2800 implts_setTrackingRect( eDockedArea, rMousePos, aTrackingRect );
2801 rTrackingRect = implts_calcTrackingAndElementRect(
2802 eDockedArea, nRowCol, rUIElement,
2803 aTrackingRect, aRowColumnRect, aContainerWinSize );
2805 sal_Int32 nOffsetX( 0 );
2806 sal_Int32 nOffsetY( 0 );
2807 if ( bHorizontalDockArea )
2808 nOffsetY = sal_Int32( floor( aRowColumnRect.getOpenHeight() / 2.0 + 0.5 ));
2809 else
2810 nOffsetX = sal_Int32( floor( aRowColumnRect.getOpenWidth() / 2.0 + 0.5 ));
2812 if ( rDockingOperation == DOCKOP_BEFORE_COLROW )
2814 if (( eDockedArea == ui::DockingArea_DOCKINGAREA_TOP ) || ( eDockedArea == ui::DockingArea_DOCKINGAREA_LEFT ))
2816 // Docking before/after means move track rectangle half column/row.
2817 // As left and top are ordered 0...n instead of right and bottom
2818 // which uses n...0, we have to use negative values for top/left.
2819 nOffsetX *= -1;
2820 nOffsetY *= -1;
2823 else
2825 if (( eDockedArea == ui::DockingArea_DOCKINGAREA_BOTTOM ) || ( eDockedArea == ui::DockingArea_DOCKINGAREA_RIGHT ))
2827 // Docking before/after means move track rectangle half column/row.
2828 // As left and top are ordered 0...n instead of right and bottom
2829 // which uses n...0, we have to use negative values for top/left.
2830 nOffsetX *= -1;
2831 nOffsetY *= -1;
2833 nRowCol++;
2836 if ( bHorizontalDockArea )
2837 rUIElement.m_aDockedData.m_aPos.Y = nRowCol;
2838 else
2839 rUIElement.m_aDockedData.m_aPos.X = nRowCol;
2841 rTrackingRect.Move( nOffsetX, nOffsetY );
2842 rTrackingRect.SetSize( aTrackingRect.GetSize() );
2848 // Docking outside of our docking window area =>
2849 // Users want to dock before/after first/last docked element or to an empty docking area
2850 if ( !bOpOutsideOfDockingArea )
2851 return;
2853 // set correct size for docking
2854 implts_setTrackingRect( eDockedArea, rMousePos, aTrackingRect );
2855 rTrackingRect = aTrackingRect;
2857 if ( bHorizontalDockArea )
2859 sal_Int32 nPosX( std::max( sal_Int32( rTrackingRect.Left()), sal_Int32( 0 )));
2860 if (( nPosX + rTrackingRect.getOpenWidth()) > aContainerWinSize.Width() )
2861 nPosX = std::min( nPosX,
2862 std::max( sal_Int32( aContainerWinSize.Width() - rTrackingRect.getOpenWidth() ),
2863 sal_Int32( 0 )));
2865 sal_Int32 nSize = std::min( aContainerWinSize.Width(), rTrackingRect.getOpenWidth() );
2866 sal_Int32 nDockHeight = std::max( static_cast<sal_Int32>(aDockingAreaRect.getOpenHeight()), sal_Int32( 0 ));
2867 if ( nDockHeight == 0 )
2869 sal_Int32 nPosY( std::max( aDockingAreaRect.Top(), aDockingAreaRect.Bottom() ));
2870 if ( eDockedArea == ui::DockingArea_DOCKINGAREA_BOTTOM )
2871 nPosY -= rTrackingRect.getOpenHeight();
2872 rTrackingRect.SetPos( Point( nPosX, nPosY ));
2873 rUIElement.m_aDockedData.m_aPos.Y = 0;
2875 else if ( rMousePos.Y() < ( aDockingAreaRect.Top() + ( nDockHeight / 2 )))
2877 rTrackingRect.SetPos( Point( nPosX, aDockingAreaRect.Top() - rTrackingRect.getOpenHeight() ));
2878 if ( eDockedArea == ui::DockingArea_DOCKINGAREA_TOP )
2879 rUIElement.m_aDockedData.m_aPos.Y = 0;
2880 else
2881 rUIElement.m_aDockedData.m_aPos.Y = ( nMaxRowCol >= 0 ) ? nMaxRowCol+1 : 0;
2882 rDockingOperation = DOCKOP_BEFORE_COLROW;
2884 else
2886 rTrackingRect.SetPos( Point( nPosX, aDockingAreaRect.Bottom() ));
2887 if ( eDockedArea == ui::DockingArea_DOCKINGAREA_TOP )
2888 rUIElement.m_aDockedData.m_aPos.Y = ( nMaxRowCol >= 0 ) ? nMaxRowCol+1 : 0;
2889 else
2890 rUIElement.m_aDockedData.m_aPos.Y = 0;
2891 rDockingOperation = DOCKOP_AFTER_COLROW;
2893 rTrackingRect.setWidth( nSize );
2896 SolarMutexGuard aGuard;
2897 nPosX = pDockingAreaWindow->ScreenToOutputPixel(
2898 pContainerWindow->OutputToScreenPixel( rTrackingRect.TopLeft() )).X();
2900 rUIElement.m_aDockedData.m_aPos.X = nPosX;
2902 else
2904 sal_Int32 nMaxDockingAreaHeight = std::max<sal_Int32>( 0, nMaxLeftRightDockAreaSize );
2905 sal_Int32 nPosY( std::max<sal_Int32>( aTrackingRect.Top(), nTopDockingAreaSize ));
2906 if (( nPosY + aTrackingRect.getOpenHeight()) > ( nTopDockingAreaSize + nMaxDockingAreaHeight ))
2907 nPosY = std::min( nPosY,
2908 std::max<sal_Int32>( nTopDockingAreaSize + ( nMaxDockingAreaHeight - aTrackingRect.getOpenHeight() ),
2909 nTopDockingAreaSize ));
2911 sal_Int32 nSize = std::min( nMaxDockingAreaHeight, static_cast<sal_Int32>(aTrackingRect.getOpenHeight()) );
2912 sal_Int32 nDockWidth = std::max( static_cast<sal_Int32>(aDockingAreaRect.getOpenWidth()), sal_Int32( 0 ));
2913 if ( nDockWidth == 0 )
2915 sal_Int32 nPosX( std::max( aDockingAreaRect.Left(), aDockingAreaRect.Right() ));
2916 if ( eDockedArea == ui::DockingArea_DOCKINGAREA_RIGHT )
2917 nPosX -= rTrackingRect.getOpenWidth();
2918 rTrackingRect.SetPos( Point( nPosX, nPosY ));
2919 rUIElement.m_aDockedData.m_aPos.X = 0;
2921 else if ( rMousePos.X() < ( aDockingAreaRect.Left() + ( nDockWidth / 2 )))
2923 rTrackingRect.SetPos( Point( aDockingAreaRect.Left() - rTrackingRect.getOpenWidth(), nPosY ));
2924 if ( eDockedArea == ui::DockingArea_DOCKINGAREA_LEFT )
2925 rUIElement.m_aDockedData.m_aPos.X = 0;
2926 else
2927 rUIElement.m_aDockedData.m_aPos.X = ( nMaxRowCol >= 0 ) ? nMaxRowCol+1 : 0;
2928 rDockingOperation = DOCKOP_BEFORE_COLROW;
2930 else
2932 rTrackingRect.SetPos( Point( aDockingAreaRect.Right(), nPosY ));
2933 if ( eDockedArea == ui::DockingArea_DOCKINGAREA_LEFT )
2934 rUIElement.m_aDockedData.m_aPos.X = ( nMaxRowCol >= 0 ) ? nMaxRowCol+1 : 0;
2935 else
2936 rUIElement.m_aDockedData.m_aPos.X = 0;
2937 rDockingOperation = DOCKOP_AFTER_COLROW;
2939 rTrackingRect.setHeight( nSize );
2942 SolarMutexGuard aGuard;
2943 nPosY = pDockingAreaWindow->ScreenToOutputPixel(
2944 pContainerWindow->OutputToScreenPixel( rTrackingRect.TopLeft() )).Y();
2946 rUIElement.m_aDockedData.m_aPos.Y = nPosY;
2950 framework::ToolbarLayoutManager::DockingOperation ToolbarLayoutManager::implts_determineDockingOperation(
2951 ui::DockingArea DockingArea,
2952 const ::tools::Rectangle& rRowColRect,
2953 const Point& rMousePos )
2955 constexpr sal_Int32 nHorzVerticalRegionSize = 6;
2956 constexpr sal_Int32 nHorzVerticalMoveRegion = 4;
2958 if ( rRowColRect.Contains( rMousePos ))
2960 if ( isHorizontalDockingArea( DockingArea ))
2962 sal_Int32 nRegion = rRowColRect.getOpenHeight() / nHorzVerticalRegionSize;
2963 sal_Int32 nPosY = rRowColRect.Top() + nRegion;
2965 if ( rMousePos.Y() < nPosY )
2966 return ( DockingArea == ui::DockingArea_DOCKINGAREA_TOP ) ? DOCKOP_BEFORE_COLROW : DOCKOP_AFTER_COLROW;
2967 else if ( rMousePos.Y() < ( nPosY + nRegion*nHorzVerticalMoveRegion ))
2968 return DOCKOP_ON_COLROW;
2969 else
2970 return ( DockingArea == ui::DockingArea_DOCKINGAREA_TOP ) ? DOCKOP_AFTER_COLROW : DOCKOP_BEFORE_COLROW;
2972 else
2974 sal_Int32 nRegion = rRowColRect.getOpenWidth() / nHorzVerticalRegionSize;
2975 sal_Int32 nPosX = rRowColRect.Left() + nRegion;
2977 if ( rMousePos.X() < nPosX )
2978 return ( DockingArea == ui::DockingArea_DOCKINGAREA_LEFT ) ? DOCKOP_BEFORE_COLROW : DOCKOP_AFTER_COLROW;
2979 else if ( rMousePos.X() < ( nPosX + nRegion*nHorzVerticalMoveRegion ))
2980 return DOCKOP_ON_COLROW;
2981 else
2982 return ( DockingArea == ui::DockingArea_DOCKINGAREA_LEFT ) ? DOCKOP_AFTER_COLROW : DOCKOP_BEFORE_COLROW;
2985 else
2986 return DOCKOP_ON_COLROW;
2989 ::tools::Rectangle ToolbarLayoutManager::implts_calcTrackingAndElementRect(
2990 ui::DockingArea eDockingArea,
2991 sal_Int32 nRowCol,
2992 UIElement& rUIElement,
2993 const ::tools::Rectangle& rTrackingRect,
2994 const ::tools::Rectangle& rRowColumnRect,
2995 const ::Size& rContainerWinSize )
2997 SolarMutexResettableGuard aReadGuard;
2998 ::tools::Rectangle aDockingAreaOffsets( m_aDockingAreaOffsets );
2999 aReadGuard.clear();
3001 bool bHorizontalDockArea( isHorizontalDockingArea( eDockingArea ));
3003 sal_Int32 nTopDockingAreaSize( implts_getTopBottomDockingAreaSizes().Width() );
3004 sal_Int32 nBottomDockingAreaSize( implts_getTopBottomDockingAreaSizes().Height() );
3006 sal_Int32 nMaxLeftRightDockAreaSize = rContainerWinSize.Height() -
3007 nTopDockingAreaSize -
3008 nBottomDockingAreaSize -
3009 aDockingAreaOffsets.Top() -
3010 aDockingAreaOffsets.Bottom();
3012 ::tools::Rectangle aTrackingRect( rTrackingRect );
3013 if ( bHorizontalDockArea )
3015 sal_Int32 nPosX( std::max( sal_Int32( rTrackingRect.Left()), sal_Int32( 0 )));
3016 if (( nPosX + rTrackingRect.getOpenWidth()) > rContainerWinSize.Width() )
3017 nPosX = std::min( nPosX,
3018 std::max( sal_Int32( rContainerWinSize.Width() - rTrackingRect.getOpenWidth() ),
3019 sal_Int32( 0 )));
3021 sal_Int32 nSize = std::min( rContainerWinSize.Width(), rTrackingRect.getOpenWidth() );
3023 aTrackingRect.SetPos( ::Point( nPosX, rRowColumnRect.Top() ));
3024 aTrackingRect.setWidth( nSize );
3025 aTrackingRect.setHeight( rRowColumnRect.getOpenHeight() );
3027 // Set virtual position
3028 rUIElement.m_aDockedData.m_aPos.X = nPosX;
3029 rUIElement.m_aDockedData.m_aPos.Y = nRowCol;
3031 else
3033 sal_Int32 nMaxDockingAreaHeight = std::max<sal_Int32>( 0, nMaxLeftRightDockAreaSize );
3035 sal_Int32 nPosY( std::max<sal_Int32>( aTrackingRect.Top(), nTopDockingAreaSize ));
3036 if (( nPosY + aTrackingRect.getOpenHeight()) > ( nTopDockingAreaSize + nMaxDockingAreaHeight ))
3037 nPosY = std::min( nPosY,
3038 std::max<sal_Int32>( nTopDockingAreaSize + ( nMaxDockingAreaHeight - aTrackingRect.getOpenHeight() ),
3039 nTopDockingAreaSize ));
3041 sal_Int32 nSize = std::min( nMaxDockingAreaHeight, static_cast<sal_Int32>(aTrackingRect.getOpenHeight()) );
3043 aTrackingRect.SetPos( ::Point( rRowColumnRect.Left(), nPosY ));
3044 aTrackingRect.setWidth( rRowColumnRect.getOpenWidth() );
3045 aTrackingRect.setHeight( nSize );
3047 aReadGuard.reset();
3048 uno::Reference< awt::XWindow > xDockingAreaWindow( m_xDockAreaWindows[static_cast<int>(eDockingArea)] );
3049 uno::Reference< awt::XWindow2 > xContainerWindow( m_xContainerWindow );
3050 aReadGuard.clear();
3052 sal_Int32 nDockPosY( 0 );
3054 SolarMutexGuard aGuard;
3055 vcl::Window* pDockingAreaWindow = VCLUnoHelper::GetWindow( xDockingAreaWindow );
3056 VclPtr<vcl::Window> pContainerWindow = VCLUnoHelper::GetWindow( xContainerWindow );
3057 nDockPosY = pDockingAreaWindow->ScreenToOutputPixel( pContainerWindow->OutputToScreenPixel( ::Point( 0, nPosY ))).Y();
3060 // Set virtual position
3061 rUIElement.m_aDockedData.m_aPos.X = nRowCol;
3062 rUIElement.m_aDockedData.m_aPos.Y = nDockPosY;
3065 return aTrackingRect;
3068 void ToolbarLayoutManager::implts_setTrackingRect( ui::DockingArea eDockingArea, const ::Point& rMousePos, ::tools::Rectangle& rTrackingRect )
3070 ::Point aPoint( rTrackingRect.TopLeft());
3071 if ( isHorizontalDockingArea( eDockingArea ))
3072 aPoint.setX( rMousePos.X() );
3073 else
3074 aPoint.setY( rMousePos.Y() );
3075 rTrackingRect.SetPos( aPoint );
3078 void ToolbarLayoutManager::implts_renumberRowColumnData(
3079 ui::DockingArea eDockingArea,
3080 const UIElement& rUIElement )
3082 SolarMutexClearableGuard aReadLock;
3083 uno::Reference< container::XNameAccess > xPersistentWindowState( m_xPersistentWindowState );
3084 aReadLock.clear();
3086 bool bHorzDockingArea( isHorizontalDockingArea( eDockingArea ));
3087 sal_Int32 nRowCol( bHorzDockingArea ? rUIElement.m_aDockedData.m_aPos.Y : rUIElement.m_aDockedData.m_aPos.X );
3089 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
3091 SolarMutexGuard aWriteLock;
3092 for (auto& elem : m_aUIElements)
3094 if ((elem.m_aDockedData.m_nDockedArea == eDockingArea)
3095 && (elem.m_aName != rUIElement.m_aName))
3097 // Don't change toolbars without a valid docking position!
3098 if (isDefaultPos(elem.m_aDockedData.m_aPos))
3099 continue;
3101 sal_Int32 nWindowRowCol
3102 = bHorzDockingArea ? elem.m_aDockedData.m_aPos.Y : elem.m_aDockedData.m_aPos.X;
3103 if (nWindowRowCol >= nRowCol)
3105 if (bHorzDockingArea)
3106 elem.m_aDockedData.m_aPos.Y += 1;
3107 else
3108 elem.m_aDockedData.m_aPos.X += 1;
3113 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
3115 // We have to change the persistent window state part
3116 if ( !xPersistentWindowState.is() )
3117 return;
3121 const uno::Sequence< OUString > aWindowElements = xPersistentWindowState->getElementNames();
3122 for ( OUString const & rWindowElementName : aWindowElements )
3124 if ( rUIElement.m_aName != rWindowElementName )
3128 uno::Sequence< beans::PropertyValue > aPropValueSeq;
3129 awt::Point aDockedPos;
3130 ui::DockingArea nDockedArea( ui::DockingArea_DOCKINGAREA_DEFAULT );
3132 xPersistentWindowState->getByName( rWindowElementName ) >>= aPropValueSeq;
3133 for ( beans::PropertyValue const & rProp : std::as_const(aPropValueSeq) )
3135 if ( rProp.Name == WINDOWSTATE_PROPERTY_DOCKINGAREA )
3136 rProp.Value >>= nDockedArea;
3137 else if ( rProp.Name == WINDOWSTATE_PROPERTY_DOCKPOS )
3138 rProp.Value >>= aDockedPos;
3141 // Don't change toolbars without a valid docking position!
3142 if ( isDefaultPos( aDockedPos ))
3143 continue;
3145 sal_Int32 nWindowRowCol = bHorzDockingArea ? aDockedPos.Y : aDockedPos.X;
3146 if (( nDockedArea == eDockingArea ) && ( nWindowRowCol >= nRowCol ))
3148 if ( bHorzDockingArea )
3149 aDockedPos.Y += 1;
3150 else
3151 aDockedPos.X += 1;
3153 uno::Reference< container::XNameReplace > xReplace( xPersistentWindowState, uno::UNO_QUERY );
3154 xReplace->replaceByName( rWindowElementName, css::uno::Any( aPropValueSeq ));
3157 catch (const uno::Exception&)
3163 catch (const uno::Exception&)
3168 // XWindowListener
3170 void SAL_CALL ToolbarLayoutManager::windowResized( const awt::WindowEvent& aEvent )
3172 SolarMutexClearableGuard aWriteLock;
3173 bool bLocked( m_bDockingInProgress );
3174 bool bLayoutInProgress( m_bLayoutInProgress );
3175 aWriteLock.clear();
3177 // Do not do anything if we are in the middle of a docking process. This would interfere all other
3178 // operations. We will store the new position and size in the docking handlers.
3179 // Do not do anything if we are in the middle of our layouting process. We will adapt the position
3180 // and size of the user interface elements.
3181 if ( bLocked || bLayoutInProgress )
3182 return;
3184 bool bNotify( false );
3185 uno::Reference< awt::XWindow > xWindow( aEvent.Source, uno::UNO_QUERY );
3187 UIElement aUIElement = implts_findToolbar( aEvent.Source );
3188 if ( aUIElement.m_xUIElement.is() )
3190 if ( aUIElement.m_bFloating )
3192 uno::Reference< awt::XWindow2 > xWindow2( xWindow, uno::UNO_QUERY );
3194 if( xWindow2.is() )
3196 awt::Rectangle aPos = xWindow2->getPosSize();
3197 awt::Size aSize = xWindow2->getOutputSize(); // always use output size for consistency
3198 bool bVisible = xWindow2->isVisible();
3200 // update element data
3201 aUIElement.m_aFloatingData.m_aPos = awt::Point(aPos.X, aPos.Y);
3202 aUIElement.m_aFloatingData.m_aSize = aSize;
3203 aUIElement.m_bVisible = bVisible;
3206 implts_writeWindowStateData( aUIElement );
3208 else
3210 implts_setLayoutDirty();
3211 bNotify = true;
3215 if ( bNotify )
3216 m_pParentLayouter->requestLayout();
3219 void SAL_CALL ToolbarLayoutManager::windowMoved( const awt::WindowEvent& /*aEvent*/ )
3223 void SAL_CALL ToolbarLayoutManager::windowShown( const lang::EventObject& /*aEvent*/ )
3227 void SAL_CALL ToolbarLayoutManager::windowHidden( const lang::EventObject& /*aEvent*/ )
3231 // XDockableWindowListener
3233 void SAL_CALL ToolbarLayoutManager::startDocking( const awt::DockingEvent& e )
3235 bool bWinFound( false );
3237 SolarMutexClearableGuard aReadGuard;
3238 uno::Reference< awt::XWindow2 > xWindow( e.Source, uno::UNO_QUERY );
3239 aReadGuard.clear();
3241 UIElement aUIElement = implts_findToolbar( e.Source );
3243 if ( aUIElement.m_xUIElement.is() && xWindow.is() )
3245 bWinFound = true;
3246 uno::Reference< awt::XDockableWindow > xDockWindow( xWindow, uno::UNO_QUERY );
3247 if ( xDockWindow->isFloating() )
3249 awt::Rectangle aPos = xWindow->getPosSize();
3250 awt::Size aSize = xWindow->getOutputSize();
3252 aUIElement.m_aFloatingData.m_aPos = awt::Point(aPos.X, aPos.Y);
3253 aUIElement.m_aFloatingData.m_aSize = aSize;
3255 SolarMutexGuard aGuard;
3257 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
3258 if ( pWindow && pWindow->GetType() == WindowType::TOOLBOX )
3260 ToolBox* pToolBox = static_cast<ToolBox *>(pWindow.get());
3261 aUIElement.m_aFloatingData.m_nLines = pToolBox->GetFloatingLines();
3262 aUIElement.m_aFloatingData.m_bIsHorizontal = isToolboxHorizontalAligned( pToolBox );
3267 SolarMutexGuard g;
3268 m_bDockingInProgress = bWinFound;
3269 m_aDockUIElement = aUIElement;
3270 m_aDockUIElement.m_bUserActive = true;
3273 awt::DockingData SAL_CALL ToolbarLayoutManager::docking( const awt::DockingEvent& e )
3275 constexpr sal_Int32 MAGNETIC_DISTANCE_UNDOCK = 25;
3276 constexpr sal_Int32 MAGNETIC_DISTANCE_DOCK = 20;
3278 SolarMutexClearableGuard aReadLock;
3279 awt::DockingData aDockingData;
3280 uno::Reference< awt::XDockableWindow > xDockWindow( e.Source, uno::UNO_QUERY );
3281 uno::Reference< awt::XWindow > xWindow( e.Source, uno::UNO_QUERY );
3282 uno::Reference< awt::XWindow > xTopDockingWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_TOP)] );
3283 uno::Reference< awt::XWindow > xLeftDockingWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_LEFT)] );
3284 uno::Reference< awt::XWindow > xRightDockingWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_RIGHT)] );
3285 uno::Reference< awt::XWindow > xBottomDockingWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_BOTTOM)] );
3286 uno::Reference< awt::XWindow2 > xContainerWindow( m_xContainerWindow );
3287 UIElement aUIDockingElement( m_aDockUIElement );
3289 bool bDockingInProgress( m_bDockingInProgress );
3290 aReadLock.clear();
3292 if ( bDockingInProgress )
3293 aDockingData.TrackingRectangle = e.TrackingRectangle;
3295 if ( bDockingInProgress && xDockWindow.is() && xWindow.is() )
3299 SolarMutexGuard aGuard;
3301 DockingOperation eDockingOperation( DOCKOP_ON_COLROW );
3302 ui::DockingArea eDockingArea( ui::DockingArea(-1) ); // none
3303 sal_Int32 nMagneticZone( aUIDockingElement.m_bFloating ? MAGNETIC_DISTANCE_DOCK : MAGNETIC_DISTANCE_UNDOCK );
3304 ::tools::Rectangle aTrackingRect( e.TrackingRectangle.X, e.TrackingRectangle.Y,
3305 ( e.TrackingRectangle.X + e.TrackingRectangle.Width ),
3306 ( e.TrackingRectangle.Y + e.TrackingRectangle.Height ));
3308 awt::Rectangle aTmpRect = xTopDockingWindow->getPosSize();
3309 ::tools::Rectangle aTopDockRect( aTmpRect.X, aTmpRect.Y, aTmpRect.Width, aTmpRect.Height );
3310 ::tools::Rectangle aHotZoneTopDockRect( implts_calcHotZoneRect( aTopDockRect, nMagneticZone ));
3312 aTmpRect = xBottomDockingWindow->getPosSize();
3313 ::tools::Rectangle aBottomDockRect( aTmpRect.X, aTmpRect.Y, ( aTmpRect.X + aTmpRect.Width), ( aTmpRect.Y + aTmpRect.Height ));
3314 ::tools::Rectangle aHotZoneBottomDockRect( implts_calcHotZoneRect( aBottomDockRect, nMagneticZone ));
3316 aTmpRect = xLeftDockingWindow->getPosSize();
3317 ::tools::Rectangle aLeftDockRect( aTmpRect.X, aTmpRect.Y, ( aTmpRect.X + aTmpRect.Width ), ( aTmpRect.Y + aTmpRect.Height ));
3318 ::tools::Rectangle aHotZoneLeftDockRect( implts_calcHotZoneRect( aLeftDockRect, nMagneticZone ));
3320 aTmpRect = xRightDockingWindow->getPosSize();
3321 ::tools::Rectangle aRightDockRect( aTmpRect.X, aTmpRect.Y, ( aTmpRect.X + aTmpRect.Width ), ( aTmpRect.Y + aTmpRect.Height ));
3322 ::tools::Rectangle aHotZoneRightDockRect( implts_calcHotZoneRect( aRightDockRect, nMagneticZone ));
3324 VclPtr<vcl::Window> pContainerWindow( VCLUnoHelper::GetWindow( xContainerWindow ) );
3325 ::Point aMousePos( pContainerWindow->ScreenToOutputPixel( ::Point( e.MousePos.X, e.MousePos.Y )));
3327 if ( aHotZoneTopDockRect.Contains( aMousePos ))
3328 eDockingArea = ui::DockingArea_DOCKINGAREA_TOP;
3329 else if ( aHotZoneBottomDockRect.Contains( aMousePos ))
3330 eDockingArea = ui::DockingArea_DOCKINGAREA_BOTTOM;
3331 else if ( aHotZoneLeftDockRect.Contains( aMousePos ))
3332 eDockingArea = ui::DockingArea_DOCKINGAREA_LEFT;
3333 else if ( aHotZoneRightDockRect.Contains( aMousePos ))
3334 eDockingArea = ui::DockingArea_DOCKINGAREA_RIGHT;
3336 // Higher priority for movements inside the real docking area
3337 if ( aTopDockRect.Contains( aMousePos ))
3338 eDockingArea = ui::DockingArea_DOCKINGAREA_TOP;
3339 else if ( aBottomDockRect.Contains( aMousePos ))
3340 eDockingArea = ui::DockingArea_DOCKINGAREA_BOTTOM;
3341 else if ( aLeftDockRect.Contains( aMousePos ))
3342 eDockingArea = ui::DockingArea_DOCKINGAREA_LEFT;
3343 else if ( aRightDockRect.Contains( aMousePos ))
3344 eDockingArea = ui::DockingArea_DOCKINGAREA_RIGHT;
3346 // Determine if we have a toolbar and set alignment according to the docking area!
3347 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
3348 ToolBox* pToolBox = nullptr;
3349 if ( pWindow && pWindow->GetType() == WindowType::TOOLBOX )
3350 pToolBox = static_cast<ToolBox *>(pWindow.get());
3352 if ( eDockingArea != ui::DockingArea(-1) )
3354 if ( eDockingArea == ui::DockingArea_DOCKINGAREA_TOP )
3356 aUIDockingElement.m_aDockedData.m_nDockedArea = ui::DockingArea_DOCKINGAREA_TOP;
3357 aUIDockingElement.m_bFloating = false;
3359 else if ( eDockingArea == ui::DockingArea_DOCKINGAREA_BOTTOM )
3361 aUIDockingElement.m_aDockedData.m_nDockedArea = ui::DockingArea_DOCKINGAREA_BOTTOM;
3362 aUIDockingElement.m_bFloating = false;
3364 else if ( eDockingArea == ui::DockingArea_DOCKINGAREA_LEFT )
3366 aUIDockingElement.m_aDockedData.m_nDockedArea = ui::DockingArea_DOCKINGAREA_LEFT;
3367 aUIDockingElement.m_bFloating = false;
3369 else if ( eDockingArea == ui::DockingArea_DOCKINGAREA_RIGHT )
3371 aUIDockingElement.m_aDockedData.m_nDockedArea = ui::DockingArea_DOCKINGAREA_RIGHT;
3372 aUIDockingElement.m_bFloating = false;
3375 ::Point aOutputPos = pContainerWindow->ScreenToOutputPixel( aTrackingRect.TopLeft() );
3376 aTrackingRect.SetPos( aOutputPos );
3378 ::tools::Rectangle aNewDockingRect( aTrackingRect );
3380 implts_calcDockingPosSize( aUIDockingElement, eDockingOperation, aNewDockingRect, aMousePos );
3382 ::Point aScreenPos = pContainerWindow->OutputToScreenPixel( aNewDockingRect.TopLeft() );
3383 aDockingData.TrackingRectangle = awt::Rectangle( aScreenPos.X(), aScreenPos.Y(),
3384 aNewDockingRect.getOpenWidth(), aNewDockingRect.getOpenHeight() );
3386 else if (pToolBox)
3388 bool bIsHorizontal = isToolboxHorizontalAligned( pToolBox );
3389 awt::Size aFloatSize = aUIDockingElement.m_aFloatingData.m_aSize;
3390 if ( aFloatSize.Width > 0 && aFloatSize.Height > 0 )
3392 aUIDockingElement.m_aFloatingData.m_aPos = AWTPoint(pContainerWindow->ScreenToOutputPixel(VCLPoint(e.MousePos)));
3393 aDockingData.TrackingRectangle.Height = aFloatSize.Height;
3394 aDockingData.TrackingRectangle.Width = aFloatSize.Width;
3396 else
3398 aFloatSize = AWTSize(pToolBox->CalcWindowSizePixel());
3399 if ( !bIsHorizontal )
3401 // Floating toolbars are always horizontal aligned! We have to swap
3402 // width/height if we have a vertical aligned toolbar.
3403 sal_Int32 nTemp = aFloatSize.Height;
3404 aFloatSize.Height = aFloatSize.Width;
3405 aFloatSize.Width = nTemp;
3408 aDockingData.TrackingRectangle.Height = aFloatSize.Height;
3409 aDockingData.TrackingRectangle.Width = aFloatSize.Width;
3411 // For the first time we don't have any data about the floating size of a toolbar.
3412 // We calculate it and store it for later use.
3413 aUIDockingElement.m_aFloatingData.m_aPos = AWTPoint(pContainerWindow->ScreenToOutputPixel(VCLPoint(e.MousePos)));
3414 aUIDockingElement.m_aFloatingData.m_aSize = aFloatSize;
3415 aUIDockingElement.m_aFloatingData.m_nLines = pToolBox->GetFloatingLines();
3416 aUIDockingElement.m_aFloatingData.m_bIsHorizontal = isToolboxHorizontalAligned( pToolBox );
3418 aDockingData.TrackingRectangle.X = e.MousePos.X;
3419 aDockingData.TrackingRectangle.Y = e.MousePos.Y;
3422 aDockingData.bFloating = ( eDockingArea == ui::DockingArea(-1) );
3424 // Write current data to the member docking progress data
3425 SolarMutexGuard g;
3426 m_aDockUIElement.m_bFloating = aDockingData.bFloating;
3427 if ( !aDockingData.bFloating )
3429 m_aDockUIElement.m_aDockedData = aUIDockingElement.m_aDockedData;
3431 m_eDockOperation = eDockingOperation;
3433 else
3434 m_aDockUIElement.m_aFloatingData = aUIDockingElement.m_aFloatingData;
3436 catch (const uno::Exception&)
3441 return aDockingData;
3444 void SAL_CALL ToolbarLayoutManager::endDocking( const awt::EndDockingEvent& e )
3446 if (e.bCancelled)
3447 return;
3449 bool bDockingInProgress( false );
3450 bool bStartDockFloated( false );
3451 bool bFloating( false );
3452 UIElement aUIDockingElement;
3454 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
3455 SolarMutexResettableGuard aWriteLock;
3456 bDockingInProgress = m_bDockingInProgress;
3457 aUIDockingElement = m_aDockUIElement;
3458 bFloating = aUIDockingElement.m_bFloating;
3460 UIElement& rUIElement = impl_findToolbar( aUIDockingElement.m_aName );
3461 if ( rUIElement.m_aName == aUIDockingElement.m_aName )
3463 if ( aUIDockingElement.m_bFloating )
3465 // Write last position into position data
3466 uno::Reference< awt::XWindow > xWindow( aUIDockingElement.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
3467 rUIElement.m_aFloatingData = aUIDockingElement.m_aFloatingData;
3468 awt::Rectangle aTmpRect = xWindow->getPosSize();
3469 rUIElement.m_aFloatingData.m_aPos = awt::Point(aTmpRect.X, aTmpRect.Y);
3470 // make changes also for our local data as we use it to make data persistent
3471 aUIDockingElement.m_aFloatingData = rUIElement.m_aFloatingData;
3473 else
3475 rUIElement.m_aDockedData = aUIDockingElement.m_aDockedData;
3476 rUIElement.m_aFloatingData.m_aSize = aUIDockingElement.m_aFloatingData.m_aSize;
3478 if ( m_eDockOperation != DOCKOP_ON_COLROW )
3480 // we have to renumber our row/column data to insert a new row/column
3481 implts_renumberRowColumnData(aUIDockingElement.m_aDockedData.m_nDockedArea, aUIDockingElement );
3485 bStartDockFloated = rUIElement.m_bFloating;
3486 rUIElement.m_bFloating = m_aDockUIElement.m_bFloating;
3487 rUIElement.m_bUserActive = true;
3490 // reset member for next docking operation
3491 m_aDockUIElement.m_xUIElement.clear();
3492 m_eDockOperation = DOCKOP_ON_COLROW;
3493 aWriteLock.clear();
3494 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
3496 implts_writeWindowStateData( aUIDockingElement );
3498 if ( bDockingInProgress )
3500 SolarMutexGuard aGuard;
3501 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( uno::Reference< awt::XWindow >( e.Source, uno::UNO_QUERY ));
3502 ToolBox* pToolBox = nullptr;
3503 if ( pWindow && pWindow->GetType() == WindowType::TOOLBOX )
3504 pToolBox = static_cast<ToolBox *>(pWindow.get());
3506 if ( pToolBox )
3508 if( e.bFloating )
3510 if ( aUIDockingElement.m_aFloatingData.m_bIsHorizontal )
3511 pToolBox->SetAlign();
3512 else
3513 pToolBox->SetAlign( WindowAlign::Left );
3515 else
3517 ::Size aSize;
3519 pToolBox->SetAlign( ImplConvertAlignment( aUIDockingElement.m_aDockedData.m_nDockedArea) );
3521 // Docked toolbars have always one line
3522 aSize = pToolBox->CalcWindowSizePixel( 1 );
3524 // Lock layouting updates as our listener would be called due to SetSizePixel
3525 pToolBox->SetOutputSizePixel( aSize );
3530 implts_sortUIElements();
3532 aWriteLock.reset();
3533 m_bDockingInProgress = false;
3534 m_bLayoutDirty = !bStartDockFloated || !bFloating;
3535 bool bNotify = m_bLayoutDirty;
3536 aWriteLock.clear();
3538 if ( bNotify )
3539 m_pParentLayouter->requestLayout();
3542 sal_Bool SAL_CALL ToolbarLayoutManager::prepareToggleFloatingMode( const lang::EventObject& e )
3544 SolarMutexClearableGuard aReadLock;
3545 bool bDockingInProgress = m_bDockingInProgress;
3546 aReadLock.clear();
3548 UIElement aUIDockingElement = implts_findToolbar( e.Source );
3549 bool bWinFound( !aUIDockingElement.m_aName.isEmpty() );
3550 uno::Reference< awt::XWindow > xWindow( e.Source, uno::UNO_QUERY );
3552 if ( !bWinFound || !xWindow.is() )
3553 return true;
3555 if ( bDockingInProgress )
3556 return true;
3558 uno::Reference< awt::XDockableWindow > xDockWindow( xWindow, uno::UNO_QUERY );
3559 if ( !xDockWindow->isFloating() )
3560 return true;
3563 SolarMutexGuard aGuard;
3564 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
3565 if ( pWindow && pWindow->GetType() == WindowType::TOOLBOX )
3567 ToolBox* pToolBox = static_cast< ToolBox *>( pWindow.get() );
3568 aUIDockingElement.m_aFloatingData.m_aPos = AWTPoint(pToolBox->GetPosPixel());
3569 aUIDockingElement.m_aFloatingData.m_aSize = AWTSize(pToolBox->GetOutputSizePixel());
3570 aUIDockingElement.m_aFloatingData.m_nLines = pToolBox->GetFloatingLines();
3571 aUIDockingElement.m_aFloatingData.m_bIsHorizontal = isToolboxHorizontalAligned( pToolBox );
3575 UIElement aUIElement = implts_findToolbar( aUIDockingElement.m_aName );
3576 if ( aUIElement.m_aName == aUIDockingElement.m_aName )
3577 implts_setToolbar( aUIDockingElement );
3579 return true;
3582 void SAL_CALL ToolbarLayoutManager::toggleFloatingMode( const lang::EventObject& e )
3584 UIElement aUIDockingElement;
3586 SolarMutexResettableGuard aReadLock;
3587 bool bDockingInProgress( m_bDockingInProgress );
3588 if ( bDockingInProgress )
3589 aUIDockingElement = m_aDockUIElement;
3590 aReadLock.clear();
3592 vcl::Window* pWindow( nullptr );
3593 ToolBox* pToolBox( nullptr );
3594 uno::Reference< awt::XWindow2 > xWindow;
3597 SolarMutexGuard aGuard;
3598 xWindow.set( e.Source, uno::UNO_QUERY );
3599 pWindow = VCLUnoHelper::GetWindow( xWindow );
3601 if ( pWindow && pWindow->GetType() == WindowType::TOOLBOX )
3602 pToolBox = static_cast<ToolBox *>(pWindow);
3605 if ( !bDockingInProgress )
3607 aUIDockingElement = implts_findToolbar( e.Source );
3608 bool bWinFound = !aUIDockingElement.m_aName.isEmpty();
3610 if ( bWinFound && xWindow.is() )
3612 aUIDockingElement.m_bFloating = !aUIDockingElement.m_bFloating;
3613 aUIDockingElement.m_bUserActive = true;
3615 implts_setLayoutInProgress();
3616 if ( aUIDockingElement.m_bFloating )
3618 SolarMutexGuard aGuard;
3619 if ( pToolBox )
3621 pToolBox->SetLineCount( aUIDockingElement.m_aFloatingData.m_nLines );
3622 if ( aUIDockingElement.m_aFloatingData.m_bIsHorizontal )
3623 pToolBox->SetAlign();
3624 else
3625 pToolBox->SetAlign( WindowAlign::Left );
3628 bool bUndefPos = hasDefaultPosValue( aUIDockingElement.m_aFloatingData.m_aPos );
3629 bool bSetSize = !hasEmptySize( aUIDockingElement.m_aFloatingData.m_aSize );
3631 if ( bUndefPos )
3632 aUIDockingElement.m_aFloatingData.m_aPos = implts_findNextCascadeFloatingPos();
3634 if ( !bSetSize )
3636 if ( pToolBox )
3637 aUIDockingElement.m_aFloatingData.m_aSize = AWTSize(pToolBox->CalcFloatingWindowSizePixel());
3638 else if ( pWindow )
3639 aUIDockingElement.m_aFloatingData.m_aSize = AWTSize(pWindow->GetOutputSizePixel());
3642 xWindow->setPosSize( aUIDockingElement.m_aFloatingData.m_aPos.X,
3643 aUIDockingElement.m_aFloatingData.m_aPos.Y,
3644 0, 0, awt::PosSize::POS );
3645 xWindow->setOutputSize(aUIDockingElement.m_aFloatingData.m_aSize);
3647 else
3649 if ( isDefaultPos( aUIDockingElement.m_aDockedData.m_aPos ))
3651 // Docking on its default position without a preset position -
3652 // we have to find a good place for it.
3653 ::Point aPixelPos;
3654 awt::Point aDockPos;
3655 ::Size aSize;
3658 SolarMutexGuard aGuard;
3659 if ( pToolBox )
3660 aSize = pToolBox->CalcWindowSizePixel( 1, ImplConvertAlignment( aUIDockingElement.m_aDockedData.m_nDockedArea ) );
3661 else if ( pWindow )
3662 aSize = pWindow->GetSizePixel();
3665 implts_findNextDockingPos(aUIDockingElement.m_aDockedData.m_nDockedArea, aSize, aDockPos, aPixelPos );
3666 aUIDockingElement.m_aDockedData.m_aPos = aDockPos;
3669 SolarMutexGuard aGuard;
3670 if ( pToolBox )
3672 pToolBox->SetAlign( ImplConvertAlignment( aUIDockingElement.m_aDockedData.m_nDockedArea) );
3673 ::Size aSize = pToolBox->CalcWindowSizePixel( 1 );
3674 awt::Rectangle aRect = xWindow->getPosSize();
3675 xWindow->setPosSize( aRect.X, aRect.Y, 0, 0, awt::PosSize::POS );
3676 xWindow->setOutputSize( AWTSize( aSize ) );
3680 implts_setLayoutInProgress( false );
3681 implts_setToolbar( aUIDockingElement );
3682 implts_writeWindowStateData( aUIDockingElement );
3683 implts_sortUIElements();
3684 implts_setLayoutDirty();
3686 aReadLock.reset();
3687 LayoutManager* pParentLayouter( m_pParentLayouter );
3688 aReadLock.clear();
3690 if ( pParentLayouter )
3691 pParentLayouter->requestLayout();
3694 else
3696 SolarMutexGuard aGuard;
3697 if ( pToolBox )
3699 if ( aUIDockingElement.m_bFloating )
3701 if ( aUIDockingElement.m_aFloatingData.m_bIsHorizontal )
3702 pToolBox->SetAlign();
3703 else
3704 pToolBox->SetAlign( WindowAlign::Left );
3706 else
3707 pToolBox->SetAlign( ImplConvertAlignment( aUIDockingElement.m_aDockedData.m_nDockedArea) );
3712 void SAL_CALL ToolbarLayoutManager::closed( const lang::EventObject& e )
3714 OUString aName;
3715 UIElement aUIElement;
3718 SolarMutexGuard aWriteLock;
3719 for (auto& elem : m_aUIElements)
3721 uno::Reference<ui::XUIElement> xUIElement(elem.m_xUIElement);
3722 if (xUIElement.is())
3724 uno::Reference<uno::XInterface> xIfac(xUIElement->getRealInterface(),
3725 uno::UNO_QUERY);
3726 if (xIfac == e.Source)
3728 aName = elem.m_aName;
3730 // user closes a toolbar =>
3731 // context sensitive toolbar: only destroy toolbar and store state.
3732 // non context sensitive toolbar: make it invisible, store state and destroy it.
3733 if (!elem.m_bContextSensitive)
3734 elem.m_bVisible = false;
3736 aUIElement = elem;
3737 break;
3743 // destroy element
3744 if ( aName.isEmpty() )
3745 return;
3747 implts_writeWindowStateData( aUIElement );
3748 destroyToolbar( aName );
3750 SolarMutexClearableGuard aReadLock;
3751 bool bLayoutDirty = m_bLayoutDirty;
3752 LayoutManager* pParentLayouter( m_pParentLayouter );
3753 aReadLock.clear();
3755 if ( bLayoutDirty && pParentLayouter )
3756 pParentLayouter->requestLayout();
3759 void SAL_CALL ToolbarLayoutManager::endPopupMode( const awt::EndPopupModeEvent& /*e*/ )
3763 // XUIConfigurationListener
3765 void SAL_CALL ToolbarLayoutManager::elementInserted( const ui::ConfigurationEvent& rEvent )
3767 UIElement aUIElement = implts_findToolbar( rEvent.ResourceURL );
3769 uno::Reference< ui::XUIElementSettings > xElementSettings( aUIElement.m_xUIElement, uno::UNO_QUERY );
3770 if ( xElementSettings.is() )
3772 uno::Reference< beans::XPropertySet > xPropSet( xElementSettings, uno::UNO_QUERY );
3773 if ( xPropSet.is() )
3775 if ( rEvent.Source == uno::Reference< uno::XInterface >( m_xDocCfgMgr, uno::UNO_QUERY ))
3776 xPropSet->setPropertyValue( "ConfigurationSource", css::uno::Any( m_xDocCfgMgr ));
3778 xElementSettings->updateSettings();
3780 else
3782 OUString aElementType;
3783 OUString aElementName;
3784 parseResourceURL( rEvent.ResourceURL, aElementType, aElementName );
3785 if ( aElementName.indexOf( "custom_" ) != -1 )
3787 // custom toolbar must be directly created, shown and layouted!
3788 createToolbar( rEvent.ResourceURL );
3789 uno::Reference< ui::XUIElement > xUIElement = getToolbar( rEvent.ResourceURL );
3790 if ( xUIElement.is() )
3792 OUString aUIName;
3793 uno::Reference< ui::XUIConfigurationManager > xCfgMgr;
3794 uno::Reference< beans::XPropertySet > xPropSet;
3798 xCfgMgr.set( rEvent.Source, uno::UNO_QUERY );
3799 xPropSet.set( xCfgMgr->getSettings( rEvent.ResourceURL, false ), uno::UNO_QUERY );
3801 if ( xPropSet.is() )
3802 xPropSet->getPropertyValue("UIName") >>= aUIName;
3804 catch (const container::NoSuchElementException&)
3807 catch (const beans::UnknownPropertyException&)
3810 catch (const lang::WrappedTargetException&)
3815 SolarMutexGuard aGuard;
3816 vcl::Window* pWindow = getWindowFromXUIElement( xUIElement );
3817 if ( pWindow )
3818 pWindow->SetText( aUIName );
3821 showToolbar( rEvent.ResourceURL );
3827 void SAL_CALL ToolbarLayoutManager::elementRemoved( const ui::ConfigurationEvent& rEvent )
3829 SolarMutexClearableGuard aReadLock;
3830 uno::Reference< awt::XWindow > xContainerWindow = m_xContainerWindow;
3831 uno::Reference< ui::XUIConfigurationManager > xModuleCfgMgr( m_xModuleCfgMgr );
3832 uno::Reference< ui::XUIConfigurationManager > xDocCfgMgr( m_xDocCfgMgr );
3833 aReadLock.clear();
3835 UIElement aUIElement = implts_findToolbar( rEvent.ResourceURL );
3836 uno::Reference< ui::XUIElementSettings > xElementSettings( aUIElement.m_xUIElement, uno::UNO_QUERY );
3837 if ( !xElementSettings.is() )
3838 return;
3840 bool bNoSettings( false );
3841 OUString aConfigSourcePropName( "ConfigurationSource" );
3842 uno::Reference< uno::XInterface > xElementCfgMgr;
3843 uno::Reference< beans::XPropertySet > xPropSet( xElementSettings, uno::UNO_QUERY );
3845 if ( xPropSet.is() )
3846 xPropSet->getPropertyValue( aConfigSourcePropName ) >>= xElementCfgMgr;
3848 if ( !xElementCfgMgr.is() )
3849 return;
3851 // Check if the same UI configuration manager has changed => check further
3852 if ( rEvent.Source == xElementCfgMgr )
3854 // Same UI configuration manager where our element has its settings
3855 if ( rEvent.Source == uno::Reference< uno::XInterface >( xDocCfgMgr, uno::UNO_QUERY ))
3857 // document settings removed
3858 if ( xModuleCfgMgr->hasSettings( rEvent.ResourceURL ))
3860 xPropSet->setPropertyValue( aConfigSourcePropName, css::uno::Any( xModuleCfgMgr ));
3861 xElementSettings->updateSettings();
3862 return;
3866 bNoSettings = true;
3869 // No settings anymore, element must be destroyed
3870 if ( xContainerWindow.is() && bNoSettings )
3871 destroyToolbar( rEvent.ResourceURL );
3874 void SAL_CALL ToolbarLayoutManager::elementReplaced( const ui::ConfigurationEvent& rEvent )
3876 UIElement aUIElement = implts_findToolbar( rEvent.ResourceURL );
3878 uno::Reference< ui::XUIElementSettings > xElementSettings( aUIElement.m_xUIElement, uno::UNO_QUERY );
3879 if ( !xElementSettings.is() )
3880 return;
3882 uno::Reference< uno::XInterface > xElementCfgMgr;
3883 uno::Reference< beans::XPropertySet > xPropSet( xElementSettings, uno::UNO_QUERY );
3885 if ( xPropSet.is() )
3886 xPropSet->getPropertyValue( "ConfigurationSource" ) >>= xElementCfgMgr;
3888 if ( !xElementCfgMgr.is() )
3889 return;
3891 // Check if the same UI configuration manager has changed => update settings
3892 if ( rEvent.Source != xElementCfgMgr )
3893 return;
3895 xElementSettings->updateSettings();
3897 SolarMutexClearableGuard aWriteLock;
3898 bool bNotify = !aUIElement.m_bFloating;
3899 m_bLayoutDirty = bNotify;
3900 LayoutManager* pParentLayouter( m_pParentLayouter );
3901 aWriteLock.clear();
3903 if ( bNotify && pParentLayouter )
3904 pParentLayouter->requestLayout();
3907 void ToolbarLayoutManager::updateToolbarsTips()
3909 SolarMutexGuard g;
3911 for (auto& elem : m_aUIElements)
3913 uno::Reference< ui::XUIElementSettings > xElementSettings(elem.m_xUIElement, uno::UNO_QUERY);
3914 if (!xElementSettings.is())
3915 continue;
3916 xElementSettings->updateSettings();
3921 uno::Reference< ui::XUIElement > ToolbarLayoutManager::getToolbar( std::u16string_view aName )
3923 return implts_findToolbar( aName ).m_xUIElement;
3926 uno::Sequence< uno::Reference< ui::XUIElement > > ToolbarLayoutManager::getToolbars()
3928 uno::Sequence< uno::Reference< ui::XUIElement > > aSeq;
3930 SolarMutexGuard g;
3931 if ( !m_aUIElements.empty() )
3933 sal_uInt32 nCount(0);
3934 for (auto const& elem : m_aUIElements)
3936 if ( elem.m_xUIElement.is() )
3938 ++nCount;
3939 aSeq.realloc( nCount );
3940 aSeq.getArray()[nCount-1] = elem.m_xUIElement;
3945 return aSeq;
3948 bool ToolbarLayoutManager::floatToolbar( std::u16string_view rResourceURL )
3950 UIElement aUIElement = implts_findToolbar( rResourceURL );
3951 if ( !aUIElement.m_xUIElement.is() )
3952 return false;
3956 uno::Reference< awt::XDockableWindow > xDockWindow( aUIElement.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
3957 if ( xDockWindow.is() && !xDockWindow->isFloating() )
3959 aUIElement.m_bFloating = true;
3960 implts_writeWindowStateData( aUIElement );
3961 xDockWindow->setFloatingMode( true );
3963 implts_setLayoutDirty();
3964 implts_setToolbar( aUIElement );
3965 return true;
3968 catch (const lang::DisposedException&)
3972 return false;
3975 bool ToolbarLayoutManager::lockToolbar( std::u16string_view rResourceURL )
3977 UIElement aUIElement = implts_findToolbar( rResourceURL );
3978 if ( !aUIElement.m_xUIElement.is() )
3979 return false;
3983 uno::Reference< awt::XDockableWindow > xDockWindow( aUIElement.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
3984 if ( xDockWindow.is() && !xDockWindow->isFloating() && !xDockWindow->isLocked() )
3986 aUIElement.m_aDockedData.m_bLocked = true;
3987 implts_writeWindowStateData( aUIElement );
3988 xDockWindow->lock();
3990 implts_setLayoutDirty();
3991 implts_setToolbar( aUIElement );
3992 return true;
3995 catch (const lang::DisposedException&)
3999 return false;
4002 bool ToolbarLayoutManager::unlockToolbar( std::u16string_view rResourceURL )
4004 UIElement aUIElement = implts_findToolbar( rResourceURL );
4005 if ( !aUIElement.m_xUIElement.is() )
4006 return false;
4010 uno::Reference< awt::XDockableWindow > xDockWindow( aUIElement.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
4011 if ( xDockWindow.is() && !xDockWindow->isFloating() && xDockWindow->isLocked() )
4013 aUIElement.m_aDockedData.m_bLocked = false;
4014 implts_writeWindowStateData( aUIElement );
4015 xDockWindow->unlock();
4017 implts_setLayoutDirty();
4018 implts_setToolbar( aUIElement );
4019 return true;
4022 catch (const lang::DisposedException&)
4026 return false;
4029 bool ToolbarLayoutManager::isToolbarVisible( std::u16string_view rResourceURL )
4031 uno::Reference< awt::XWindow2 > xWindow2( implts_getXWindow( rResourceURL ), uno::UNO_QUERY );
4032 return ( xWindow2.is() && xWindow2->isVisible() );
4035 bool ToolbarLayoutManager::isToolbarFloating( std::u16string_view rResourceURL )
4037 uno::Reference< awt::XDockableWindow > xDockWindow( implts_getXWindow( rResourceURL ), uno::UNO_QUERY );
4038 return ( xDockWindow.is() && xDockWindow->isFloating() );
4041 bool ToolbarLayoutManager::isToolbarDocked( std::u16string_view rResourceURL )
4043 return !isToolbarFloating( rResourceURL );
4046 bool ToolbarLayoutManager::isToolbarLocked( std::u16string_view rResourceURL )
4048 uno::Reference< awt::XDockableWindow > xDockWindow( implts_getXWindow( rResourceURL ), uno::UNO_QUERY );
4049 return ( xDockWindow.is() && xDockWindow->isLocked() );
4052 awt::Size ToolbarLayoutManager::getToolbarSize( std::u16string_view rResourceURL )
4054 vcl::Window* pWindow = implts_getWindow( rResourceURL );
4056 SolarMutexGuard aGuard;
4057 if ( pWindow )
4059 ::Size aSize = pWindow->GetSizePixel();
4060 awt::Size aWinSize;
4061 aWinSize.Width = aSize.Width();
4062 aWinSize.Height = aSize.Height();
4063 return aWinSize;
4066 return awt::Size();
4069 awt::Point ToolbarLayoutManager::getToolbarPos( std::u16string_view rResourceURL )
4071 awt::Point aPos;
4072 UIElement aUIElement = implts_findToolbar( rResourceURL );
4074 uno::Reference< awt::XWindow > xWindow( implts_getXWindow( rResourceURL ));
4075 if ( xWindow.is() )
4077 if ( aUIElement.m_bFloating )
4079 awt::Rectangle aRect = xWindow->getPosSize();
4080 aPos.X = aRect.X;
4081 aPos.Y = aRect.Y;
4083 else
4084 aPos = aUIElement.m_aDockedData.m_aPos;
4087 return aPos;
4090 void ToolbarLayoutManager::setToolbarSize( std::u16string_view rResourceURL, const awt::Size& aSize )
4092 uno::Reference< awt::XWindow2 > xWindow( implts_getXWindow( rResourceURL ), uno::UNO_QUERY );
4093 uno::Reference< awt::XDockableWindow > xDockWindow( xWindow, uno::UNO_QUERY );
4094 UIElement aUIElement = implts_findToolbar( rResourceURL );
4096 if ( xWindow.is() && xDockWindow.is() && xDockWindow->isFloating() )
4098 xWindow->setOutputSize( aSize );
4099 aUIElement.m_aFloatingData.m_aSize = aSize;
4100 implts_setToolbar( aUIElement );
4101 implts_writeWindowStateData( aUIElement );
4102 implts_sortUIElements();
4106 void ToolbarLayoutManager::setToolbarPos( std::u16string_view rResourceURL, const awt::Point& aPos )
4108 uno::Reference< awt::XWindow > xWindow( implts_getXWindow( rResourceURL ));
4109 uno::Reference< awt::XDockableWindow > xDockWindow( xWindow, uno::UNO_QUERY );
4110 UIElement aUIElement = implts_findToolbar( rResourceURL );
4112 if ( xWindow.is() && xDockWindow.is() && xDockWindow->isFloating() )
4114 xWindow->setPosSize( aPos.X, aPos.Y, 0, 0, awt::PosSize::POS );
4115 aUIElement.m_aFloatingData.m_aPos = aPos;
4116 implts_setToolbar( aUIElement );
4117 implts_writeWindowStateData( aUIElement );
4118 implts_sortUIElements();
4122 void ToolbarLayoutManager::setToolbarPosSize( std::u16string_view rResourceURL, const awt::Point& aPos, const awt::Size& aSize )
4124 setToolbarPos( rResourceURL, aPos );
4125 setToolbarSize( rResourceURL, aSize );
4128 } // namespace framework
4130 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */