LibreOffice Module framework (master) 1
toolbarlayoutmanager.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
23#include "helpers.hxx"
25#include <strings.hrc>
26#include <classes/fwkresid.hxx>
27
28#include <com/sun/star/awt/PosSize.hpp>
29#include <com/sun/star/beans/XPropertySet.hpp>
30#include <com/sun/star/ui/UIElementType.hpp>
31#include <com/sun/star/container/XNameReplace.hpp>
32#include <com/sun/star/container/XNameContainer.hpp>
33#include <com/sun/star/ui/XUIElementSettings.hpp>
34#include <com/sun/star/ui/XUIFunctionListener.hpp>
35
38#include <o3tl/string_view.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>
49
50
51using namespace ::com::sun::star;
52
53namespace framework
54{
55
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 )
73{
74}
75
77{
78 m_pGlobalSettings.reset();
79 m_pAddonOptions.reset();
80}
81
82// XInterface
83
84void SAL_CALL ToolbarLayoutManager::acquire() noexcept
85{
86 OWeakObject::acquire();
87}
88
89void SAL_CALL ToolbarLayoutManager::release() noexcept
90{
91 OWeakObject::release();
92}
93
95{
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));
100
101 if ( a.hasValue() )
102 return a;
103
104 return OWeakObject::queryInterface( rType );
105}
106
107void SAL_CALL ToolbarLayoutManager::disposing( const lang::EventObject& aEvent )
108{
109 if ( aEvent.Source == m_xFrame )
110 {
111 // Reset all internal references
112 reset();
114 }
115}
116
118{
119 SolarMutexResettableGuard aWriteLock;
120 tools::Rectangle aNewDockingArea( m_aDockingArea );
121 aWriteLock.clear();
122
123 if ( isLayoutDirty() )
124 aNewDockingArea = implts_calcDockingArea();
125
126 aWriteLock.reset();
127 m_aDockingArea = aNewDockingArea;
128 aWriteLock.clear();
129
130 return putRectangleValueToAWT(aNewDockingArea);
131}
132
133void ToolbarLayoutManager::setDockingArea( const awt::Rectangle& rDockingArea )
134{
136 m_aDockingArea = putAWTToRectangle( rDockingArea );
137 m_bLayoutDirty = true;
138}
139
140void ToolbarLayoutManager::implts_setDockingAreaWindowSizes( const awt::Rectangle& rBorderSpace )
141{
142 SolarMutexClearableGuard aReadLock;
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();
150
151 uno::Reference< awt::XDevice > xDevice( xContainerWindow, uno::UNO_QUERY );
152
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();
159
160 sal_Int32 nLeftRightDockingAreaHeight( aContainerClientSize.Height );
161 if ( rBorderSpace.Y >= 0 )
162 {
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;
167 }
168
169 if ( rBorderSpace.Height >= 0 )
170 {
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;
174
175 xBottomDockAreaWindow->setPosSize( 0, nBottomPos, aContainerClientSize.Width, nHeight, awt::PosSize::POSSIZE );
176 xBottomDockAreaWindow->setVisible( true );
177 nLeftRightDockingAreaHeight -= nHeight - 1;
178 }
179
180 nLeftRightDockingAreaHeight -= aStatusBarHeight;
181 if ( rBorderSpace.X >= 0 || nLeftRightDockingAreaHeight > 0 )
182 {
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 );
186
187 xLeftDockAreaWindow->setPosSize( 0, rBorderSpace.Y, rBorderSpace.X, nHeight, awt::PosSize::POSSIZE );
188 xLeftDockAreaWindow->setVisible( true );
189 }
190 if ( rBorderSpace.Width >= 0 || nLeftRightDockingAreaHeight > 0 )
191 {
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;
197
198 xRightDockAreaWindow->setPosSize( nLeftPos, rBorderSpace.Y, nWidth, nHeight, awt::PosSize::POSSIZE );
199 xRightDockAreaWindow->setVisible( true );
200 }
201}
202
203
204void ToolbarLayoutManager::doLayout(const ::Size& aContainerSize)
205{
206 SolarMutexResettableGuard aWriteLock;
207 bool bLayoutInProgress( m_bLayoutInProgress );
208 m_bLayoutInProgress = true;
209 awt::Rectangle aDockingArea = putRectangleValueToAWT( m_aDockingArea );
210 aWriteLock.clear();
211
212 if ( bLayoutInProgress )
213 return;
214
215 // Retrieve row/column dependent data from all docked user-interface elements
216 for ( sal_Int32 i = 0; i < DOCKINGAREAS_COUNT; i++ )
217 {
218 bool bReverse( isReverseOrderDockingArea( i ));
219 std::vector< SingleRowColumnWindowData > aRowColumnsWindowData;
220
221 implts_getDockingAreaElementInfos( static_cast<ui::DockingArea>(i), aRowColumnsWindowData );
222
223 sal_Int32 nOffset( 0 );
224 const sal_uInt32 nCount = aRowColumnsWindowData.size();
225 for ( sal_uInt32 j = 0; j < nCount; ++j )
226 {
227 sal_uInt32 nIndex = bReverse ? nCount-j-1 : j;
228 implts_calcWindowPosSizeOnSingleRowColumn( i, nOffset, aRowColumnsWindowData[nIndex], aContainerSize );
229 nOffset += aRowColumnsWindowData[j].nStaticSize;
230 }
231 }
232
233 implts_setDockingAreaWindowSizes( aDockingArea );
234
235 aWriteLock.reset();
236 m_bLayoutDirty = false;
237 m_bLayoutInProgress = false;
238 aWriteLock.clear();
239}
240
242{
244 bool bVisible( false );
245 if ( m_xContainerWindow.is() )
246 bVisible = m_xContainerWindow->isVisible();
247
248 return bVisible;
249}
250
252{
253 SolarMutexClearableGuard aReadLock;
254 UIElementVector aWindowVector( m_aUIElements );
255 aReadLock.clear();
256
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];
262
263 // initialize rectangle with zero values!
264 aBorderSpace.setWidth(0);
265 aBorderSpace.setHeight(0);
266
267 aRowColumnSizes[static_cast<int>(nCurrDockingArea)].clear();
268 aRowColumnSizes[static_cast<int>(nCurrDockingArea)].push_back( 0 );
269
270 for (auto const& window : aWindowVector)
271 {
272 if ( window.m_xUIElement.is() )
273 {
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() )
277 {
278 SolarMutexGuard aGuard;
279
280 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
281 if ( pWindow && !xDockWindow->isFloating() && window.m_bVisible && !window.m_bMasterHide )
282 {
283 awt::Rectangle aPosSize = xWindow->getPosSize();
284 if ( window.m_aDockedData.m_nDockedArea != nCurrDockingArea )
285 {
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 );
291 }
292
293 if ( window.m_aDockedData.m_nDockedArea == nCurrDockingArea )
294 {
295 if ( isHorizontalDockingArea( window.m_aDockedData.m_nDockedArea ))
296 {
297 if ( window.m_aDockedData.m_aPos.Y > nCurrPos )
298 {
299 ++nCurrRowColumn;
300 nCurrPos = window.m_aDockedData.m_aPos.Y;
301 aRowColumnSizes[static_cast<int>(nCurrDockingArea)].push_back( 0 );
302 }
303
304 if ( aPosSize.Height > aRowColumnSizes[static_cast<int>(nCurrDockingArea)][nCurrRowColumn] )
305 aRowColumnSizes[static_cast<int>(nCurrDockingArea)][nCurrRowColumn] = aPosSize.Height;
306 }
307 else
308 {
309 if ( window.m_aDockedData.m_aPos.X > nCurrPos )
310 {
311 ++nCurrRowColumn;
312 nCurrPos = window.m_aDockedData.m_aPos.X;
313 aRowColumnSizes[static_cast<int>(nCurrDockingArea)].push_back( 0 );
314 }
315
316 if ( aPosSize.Width > aRowColumnSizes[static_cast<int>(nCurrDockingArea)][nCurrRowColumn] )
317 aRowColumnSizes[static_cast<int>(nCurrDockingArea)][nCurrRowColumn] = aPosSize.Width;
318 }
319 }
320 }
321 }
322 }
323 }
324
325 // Sum up max heights from every row/column
326 if ( !aWindowVector.empty() )
327 {
328 for ( sal_Int32 i = 0; i <= sal_Int32(ui::DockingArea_DOCKINGAREA_RIGHT); i++ )
329 {
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];
334
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 );
343 }
344 }
345
346 return aBorderSpace;
347}
348
350{
351 {
352 SolarMutexGuard aWriteLock;
353 m_xModuleCfgMgr.clear();
354 m_xDocCfgMgr.clear();
356 m_bComponentAttached = false;
357 }
358
361}
362
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 )
368{
369 // reset toolbar manager if we lose our current frame
370 if ( m_xFrame.is() && m_xFrame != xFrame )
371 reset();
372
375 m_xModuleCfgMgr = xModuleCfgMgr;
376 m_xDocCfgMgr = xDocCfgMgr;
377 m_xPersistentWindowState = xPersistentWindowState;
379}
380
382{
385 {
386 uno::Reference< frame::XFrame > xFrame( m_xFrame );
387
388 uno::Reference< frame::XModel > xModel( impl_getModelFromFrame( xFrame ));
389
391 }
393}
394
396{
402}
403
404bool ToolbarLayoutManager::requestToolbar( const OUString& rResourceURL )
405{
406 if (isPreviewFrame())
407 return false; // no toolbars for preview frame!
408
409 bool bNotify( false );
410 bool bMustCallCreate( false );
411 uno::Reference< ui::XUIElement > xUIElement;
412
413 UIElement aRequestedToolbar = impl_findToolbar( rResourceURL );
414 if ( aRequestedToolbar.m_aName != rResourceURL )
415 {
416 bMustCallCreate = true;
417 aRequestedToolbar.m_aName = rResourceURL;
418 aRequestedToolbar.m_aType = UIRESOURCETYPE_TOOLBAR;
419 aRequestedToolbar.m_xUIElement = xUIElement;
420 implts_readWindowStateData( rResourceURL, aRequestedToolbar );
421 }
422
423 xUIElement = aRequestedToolbar.m_xUIElement;
424 if ( !xUIElement.is() )
425 bMustCallCreate = true;
426
427 bool bCreateOrShowToolbar( aRequestedToolbar.m_bVisible && !aRequestedToolbar.m_bMasterHide );
428
429 if ( bCreateOrShowToolbar )
430 bNotify = bMustCallCreate ? createToolbar( rResourceURL ) : showToolbar( rResourceURL );
431
432 return bNotify;
433}
434
435bool ToolbarLayoutManager::createToolbar( const OUString& rResourceURL )
436{
437 bool bNotify( false );
438
439 uno::Reference<frame::XFrame> xFrame;
440 uno::Reference<awt::XWindow2> xContainerWindow;
441 {
442 SolarMutexGuard aReadLock;
443 xFrame.set(m_xFrame);
444 xContainerWindow.set(m_xContainerWindow);
445 }
446
447 if ( !xFrame.is() || !xContainerWindow.is() )
448 return false;
449
450 UIElement aToolbarElement = implts_findToolbar( rResourceURL );
451 if ( !aToolbarElement.m_xUIElement.is() )
452 {
453 uno::Reference< ui::XUIElement > xUIElement;
454
455 uno::Sequence< beans::PropertyValue > aPropSeq{
457 comphelper::makePropertyValue("Persistent", true)
458 };
459 uno::Reference<ui::XUIElementFactory> xUIElementFactory;
460 {
461 SolarMutexGuard aReadLock;
462 xUIElementFactory.set(m_xUIElementFactoryManager);
463 }
464
466 try
467 {
468 if ( xUIElementFactory.is() )
469 xUIElement = xUIElementFactory->createUIElement( rResourceURL, aPropSeq );
470 }
471 catch (const container::NoSuchElementException&)
472 {
473 }
474 catch (const lang::IllegalArgumentException&)
475 {
476 }
478
479 if ( xUIElement.is() )
480 {
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() )
484 {
485 try
486 {
487 xDockWindow->addDockableWindowListener( uno::Reference< awt::XDockableWindowListener >(this) );
488 xWindow->addWindowListener( uno::Reference< awt::XWindowListener >(this) );
489 xDockWindow->enableDocking( true );
490 }
491 catch (const uno::Exception&)
492 {
493 }
494 }
495
496 bool bVisible = false;
497 bool bFloating = false;
498
499 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
500 {
501 SolarMutexClearableGuard aWriteLock;
502
503 UIElement& rElement = impl_findToolbar(rResourceURL);
504 if (rElement.m_xUIElement.is())
505 {
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;
514 }
515 if (!rElement.m_aName.isEmpty())
516 {
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;
523 }
524 else
525 {
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;
533 }
534 }
535 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
536
537 // set toolbar menu style according to customize command state
538 SvtCommandOptions aCmdOptions;
539
540 SolarMutexGuard aGuard;
541 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
542 if ( pWindow && pWindow->GetType() == WindowType::TOOLBOX )
543 {
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 );
550 }
551 bNotify = true;
552
554
555 if ( bVisible && !bFloating )
557 }
558 }
559
560 return bNotify;
561}
562
563bool ToolbarLayoutManager::destroyToolbar( std::u16string_view rResourceURL )
564{
565 uno::Reference< lang::XComponent > xComponent;
566
567 bool bNotify( false );
568 bool bMustBeSorted( false );
569 bool bMustLayouted( false );
570 bool bMustBeDestroyed( !o3tl::starts_with(rResourceURL, u"private:resource/toolbar/addon_") );
571
572 {
573 SolarMutexGuard aWriteLock;
574 for (auto & elem : m_aUIElements)
575 {
576 if (elem.m_aName == rResourceURL)
577 {
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;
584 }
585 }
586 }
587
588 uno::Reference< ui::XUIElement > xUIElement( xComponent, uno::UNO_QUERY );
589 if ( xUIElement.is() )
590 {
591 uno::Reference< awt::XWindow > xWindow( xUIElement->getRealInterface(), uno::UNO_QUERY );
592 uno::Reference< awt::XDockableWindow > xDockWindow( xWindow, uno::UNO_QUERY );
593
594 if ( bMustBeDestroyed )
595 {
596 try
597 {
598 if ( xWindow.is() )
599 xWindow->removeWindowListener( uno::Reference< awt::XWindowListener >(this) );
600 }
601 catch (const uno::Exception&)
602 {
603 }
604
605 try
606 {
607 if ( xDockWindow.is() )
608 xDockWindow->removeDockableWindowListener( uno::Reference< awt::XDockableWindowListener >(this) );
609 }
610 catch (const uno::Exception&)
611 {
612 }
613 }
614 else
615 {
616 if ( xWindow.is() )
617 xWindow->setVisible( false );
618 bNotify = true;
619 }
620
621 if ( !xDockWindow->isFloating() )
622 bMustLayouted = true;
623 bMustBeSorted = true;
624 }
625
626 if ( bMustBeDestroyed )
627 {
628 if ( xComponent.is() )
629 xComponent->dispose();
630 bNotify = true;
631 }
632
633 if ( bMustLayouted )
635
636 if ( bMustBeSorted )
638
639 return bNotify;
640}
641
643{
644 UIElementVector aUIElementVector;
645 implts_getUIElementVectorCopy( aUIElementVector );
646
647 {
648 SolarMutexGuard aWriteLock;
649 m_aUIElements.clear();
650 m_bLayoutDirty = true;
651 }
652
653 for (auto const& elem : aUIElementVector)
654 {
655 uno::Reference< lang::XComponent > xComponent( elem.m_xUIElement, uno::UNO_QUERY );
656 if ( xComponent.is() )
657 xComponent->dispose();
658 }
659}
660
661bool ToolbarLayoutManager::showToolbar( std::u16string_view rResourceURL )
662{
663 UIElement aUIElement = implts_findToolbar( rResourceURL );
664
665 SolarMutexGuard aGuard;
666 vcl::Window* pWindow = getWindowFromXUIElement( aUIElement.m_xUIElement );
667
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();
674
675 if ( pWindow )
676 {
677 if ( !aUIElement.m_bFloating )
679 else
680 pWindow->Show( true, ShowFlags::NoFocusChange | ShowFlags::NoActivate );
681
682 aUIElement.m_bVisible = true;
683 implts_writeWindowStateData( aUIElement );
684 implts_setToolbar( aUIElement );
686 return true;
687 }
688
689 return false;
690}
691
692bool ToolbarLayoutManager::hideToolbar( std::u16string_view rResourceURL )
693{
694 UIElement aUIElement = implts_findToolbar( rResourceURL );
695
696 SolarMutexGuard aGuard;
697 vcl::Window* pWindow = getWindowFromXUIElement( aUIElement.m_xUIElement );
698 if ( pWindow )
699 {
700 pWindow->Show( false );
701 if ( !aUIElement.m_bFloating )
703
704 aUIElement.m_bVisible = false;
705 implts_writeWindowStateData( aUIElement );
706 implts_setToolbar( aUIElement );
707 return true;
708 }
709
710 return false;
711}
712
714{
715 UIElementVector aUIElementVector;
716
717 if ( !bAutomaticToolbars )
718 return;
719
720 implts_getUIElementVectorCopy( aUIElementVector );
721
722 UIElement aUIElement;
723 SolarMutexGuard aGuard;
724 for (auto const& elem : aUIElementVector)
725 {
726 if ( implts_readWindowStateData( elem.m_aName, aUIElement ) &&
727 ( elem.m_bVisible != aUIElement.m_bVisible ) && !elem.m_bMasterHide )
728 {
730 UIElement& rUIElement = impl_findToolbar( elem.m_aName );
731 if ( rUIElement.m_aName == elem.m_aName )
732 {
733 rUIElement.m_bVisible = aUIElement.m_bVisible;
735 }
736 }
737 }
738}
739
741{
742 UIElementVector aUIElementVector;
743 implts_getUIElementVectorCopy( aUIElementVector );
744
745 SolarMutexGuard aGuard;
746 for (auto const& elem : aUIElementVector)
747 {
748 vcl::Window* pWindow = getWindowFromXUIElement( elem.m_xUIElement );
749 if ( pWindow && elem.m_bFloating )
750 {
751 if ( bVisible )
752 {
753 if ( elem.m_bVisible && !elem.m_bMasterHide )
754 pWindow->Show( true, ShowFlags::NoFocusChange | ShowFlags::NoActivate );
755 }
756 else
757 pWindow->Show( false );
758 }
759 }
760}
761
763{
764 UIElementVector aUIElementVector;
765 implts_getUIElementVectorCopy( aUIElementVector );
766
767 SolarMutexGuard aGuard;
768 for (auto & elem : aUIElementVector)
769 {
770 if (!elem.m_bFloating)
771 {
772 elem.m_bMasterHide = !bVisible;
773 implts_setToolbar(elem);
775 }
776
777 vcl::Window* pWindow = getWindowFromXUIElement( elem.m_xUIElement );
778 if ( pWindow )
779 {
780 bool bSetVisible( elem.m_bVisible && bVisible );
781 if ( !bSetVisible )
782 pWindow->Hide();
783 else
784 {
785 if ( elem.m_bFloating )
786 pWindow->Show(true, ShowFlags::NoFocusChange | ShowFlags::NoActivate );
787 }
788 }
789 }
790
791 if ( !bVisible )
793}
794
795bool ToolbarLayoutManager::dockToolbar( std::u16string_view rResourceURL, ui::DockingArea eDockingArea, const awt::Point& aPos )
796{
797 UIElement aUIElement = implts_findToolbar( rResourceURL );
798
799 if ( !aUIElement.m_xUIElement.is() )
800 return false;
801
802 try
803 {
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() )
807 {
808 if ( eDockingArea != ui::DockingArea_DOCKINGAREA_DEFAULT )
809 aUIElement.m_aDockedData.m_nDockedArea = eDockingArea;
810
811 if ( !isDefaultPos( aPos ))
812 aUIElement.m_aDockedData.m_aPos = aPos;
813
814 if ( !xDockWindow->isFloating() )
815 {
816 vcl::Window* pWindow( nullptr );
817 ToolBox* pToolBox( nullptr );
818
819 {
820 SolarMutexGuard aGuard;
821 pWindow = VCLUnoHelper::GetWindow( xWindow );
822 if ( pWindow && pWindow->GetType() == WindowType::TOOLBOX )
823 {
824 pToolBox = static_cast<ToolBox *>(pWindow);
825
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!
829 }
830 }
831
832 if ( hasDefaultPosValue( aUIElement.m_aDockedData.m_aPos ))
833 {
834 // Docking on its default position without a preset position -
835 // we have to find a good place for it.
836 ::Size aSize;
837
838 SolarMutexGuard aGuard;
839 {
840 if (pToolBox)
841 aSize = pToolBox->CalcWindowSizePixel( 1, ImplConvertAlignment( aUIElement.m_aDockedData.m_nDockedArea ) );
842 else if (pWindow)
843 aSize = pWindow->GetSizePixel();
844 }
845
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;
850 }
851 }
852
853 implts_setToolbar( aUIElement );
854
855 if ( xDockWindow->isFloating() )
856 {
857 // ATTENTION: This will call toggleFloatingMode() via notifications which
858 // sets the floating member of the UIElement correctly!
859 xDockWindow->setFloatingMode( false );
860 }
861 else
862 {
863 implts_writeWindowStateData( aUIElement );
865
866 if ( aUIElement.m_bVisible )
868 }
869 return true;
870 }
871 }
872 catch (const lang::DisposedException&)
873 {
874 }
875
876 return false;
877}
878
880{
881 std::vector< OUString > aToolBarNameVector;
882
883 {
884 SolarMutexGuard aReadLock;
885 for (auto const& elem : m_aUIElements)
886 {
887 if (elem.m_aType == "toolbar" && elem.m_xUIElement.is() && elem.m_bFloating
888 && elem.m_bVisible)
889 aToolBarNameVector.push_back(elem.m_aName);
890 }
891 }
892
893 bool bResult(true);
894 const sal_uInt32 nCount = aToolBarNameVector.size();
895 for ( sal_uInt32 i = 0; i < nCount; ++i )
896 {
897 awt::Point aPoint;
898 aPoint.X = aPoint.Y = SAL_MAX_INT32;
899 bResult &= dockToolbar( aToolBarNameVector[i], ui::DockingArea_DOCKINGAREA_DEFAULT, aPoint );
900 }
901
902 return bResult;
903}
904
906{
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;
913
914 if ( pEvent->GetId() == VclEventId::ToolboxSelect )
915 {
916 OUString aToolbarName;
917 OUString aCommand;
918 ToolBox* pToolBox = getToolboxPtr( pWindowEvent->GetWindow() );
919
920 if ( pToolBox )
921 {
922 aToolbarName = retrieveToolbarNameFromHelpURL( pToolBox );
923 ToolBoxItemId nId = pToolBox->GetCurItemId();
924 if ( nId > ToolBoxItemId(0) )
925 aCommand = pToolBox->GetItemCommand( nId );
926 }
927
928 if ( !aToolbarName.isEmpty() && !aCommand.isEmpty() )
929 {
930 SolarMutexClearableGuard aReadLock;
931 ::std::vector< uno::Reference< ui::XUIFunctionListener > > aListenerArray;
932
933 for (auto const& elem : m_aUIElements)
934 {
935 if ( elem.m_xUIElement.is() )
936 {
937 uno::Reference< ui::XUIFunctionListener > xListener( elem.m_xUIElement, uno::UNO_QUERY );
938 if ( xListener.is() )
939 aListenerArray.push_back( xListener );
940 }
941 }
942 aReadLock.clear();
943
944 const sal_uInt32 nCount = aListenerArray.size();
945 for ( sal_uInt32 i = 0; i < nCount; ++i )
946 {
947 try
948 {
949 aListenerArray[i]->functionExecute( aToolbarName, aCommand );
950 }
951 catch (const uno::RuntimeException&)
952 {
953 throw;
954 }
955 catch (const uno::Exception&)
956 {
957 }
958 }
959 }
960 }
961 else if ( pEvent->GetId() == VclEventId::ToolboxFormatChanged )
962 {
964 {
965 ToolBox* pToolBox = getToolboxPtr( pWindowEvent->GetWindow() );
966 if ( pToolBox )
967 {
968 OUString aToolbarName = retrieveToolbarNameFromHelpURL( pToolBox );
969 if ( !aToolbarName.isEmpty() )
970 {
971 OUString aToolbarUrl = "private:resource/toolbar/" + aToolbarName;
972
973 UIElement aToolbar = implts_findToolbar( aToolbarUrl );
974 if ( aToolbar.m_xUIElement.is() && !aToolbar.m_bFloating )
975 {
978 }
979 }
980 }
981 }
982 }
983}
984
986{
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();
993
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 );
1002}
1003
1005 const uno::Reference< awt::XVclWindowPeer >& xParentWindow )
1006{
1007 static const char DOCKINGAREASTRING[] = "dockingarea";
1008
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 );
1013
1014 {
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;
1021 }
1022
1023 if ( xParentWindow.is() )
1024 {
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 );
1039 }
1040 else
1041 {
1044 }
1045}
1046
1047void ToolbarLayoutManager::setDockingAreaOffsets( const ::tools::Rectangle& rOffsets )
1048{
1050 m_aDockingAreaOffsets = rOffsets;
1051 m_bLayoutDirty = true;
1052}
1053
1055{
1056 OUString aAddonGenericTitle(FwkResId(STR_TOOLBAR_TITLE_ADDON));
1058
1059 OUString aNumStr = rI18nHelper.GetNum( nNumber, 0, false, false );
1060 aAddonGenericTitle = aAddonGenericTitle.replaceFirst( "%num%", aNumStr );
1061
1062 return aAddonGenericTitle;
1063}
1064
1066{
1067 SolarMutexClearableGuard aWriteLock;
1068 if ( !m_pAddonOptions )
1069 m_pAddonOptions.reset( new AddonsOptions );
1070
1071 uno::Reference< ui::XUIElementFactory > xUIElementFactory( m_xUIElementFactoryManager );
1072 uno::Reference< frame::XFrame > xFrame( m_xFrame );
1073 aWriteLock.clear();
1074
1075 if (isPreviewFrame())
1076 return; // no addon toolbars for preview frame!
1077
1078 uno::Sequence< uno::Sequence< beans::PropertyValue > > aAddonToolBarData;
1079 uno::Reference< ui::XUIElement > xUIElement;
1080
1081 sal_uInt32 nCount = m_pAddonOptions->GetAddonsToolBarCount();
1082
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++ )
1089 {
1090 OUString aAddonToolBarName( "private:resource/toolbar/addon_" +
1091 m_pAddonOptions->GetAddonsToolbarResourceName(i) );
1092 aAddonToolBarData = m_pAddonOptions->GetAddonsToolBarPart( i );
1093 pPropSeq[1].Value <<= aAddonToolBarData;
1094
1095 UIElement aElement = implts_findToolbar( aAddonToolBarName );
1096
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;
1102
1103 try
1104 {
1105 xUIElement = xUIElementFactory->createUIElement( aAddonToolBarName, aPropSeq );
1106 if ( xUIElement.is() )
1107 {
1108 uno::Reference< awt::XDockableWindow > xDockWindow( xUIElement->getRealInterface(), uno::UNO_QUERY );
1109 if ( xDockWindow.is() )
1110 {
1111 try
1112 {
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) );
1118 }
1119 catch (const uno::Exception&)
1120 {
1121 }
1122 }
1123
1124 OUString aGenericAddonTitle = implts_generateGenericAddonToolbarTitle( i+1 );
1125
1126 if ( !aElement.m_aName.isEmpty() )
1127 {
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() )
1133 {
1134 aElement.m_aUIName = aGenericAddonTitle;
1135 implts_writeWindowStateData( aElement );
1136 }
1137 }
1138 else
1139 {
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() )
1146 {
1147 aNewToolbar.m_aUIName = aGenericAddonTitle;
1148 implts_writeWindowStateData( aNewToolbar );
1149 }
1150 implts_insertToolbar( aNewToolbar );
1151 }
1152
1153 uno::Reference< awt::XWindow > xWindow( xDockWindow, uno::UNO_QUERY );
1154 if ( xWindow.is() )
1155 {
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 )
1162 {
1163 ToolBox* pToolbar = static_cast<ToolBox *>(pWindow.get());
1164 pToolbar->SetMenuType();
1165 }
1166 }
1167 }
1168 }
1169 catch (const container::NoSuchElementException&)
1170 {
1171 }
1172 catch (const lang::IllegalArgumentException&)
1173 {
1174 }
1175 }
1176}
1177
1179{
1180 SolarMutexClearableGuard aReadLock;
1181 if ( !m_bComponentAttached )
1182 return;
1183
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();
1188
1189 if ( !xFrame.is() )
1190 return;
1191
1192 if (isPreviewFrame())
1193 return; // no custom toolbars for preview frame!
1194
1195 uno::Sequence< uno::Sequence< beans::PropertyValue > > aTbxSeq;
1196 if ( xDocCfgMgr.is() )
1197 {
1198 aTbxSeq = xDocCfgMgr->getUIElementsInfo( ui::UIElementType::TOOLBAR );
1199 implts_createCustomToolBars( aTbxSeq ); // first create all document based toolbars
1200 }
1201 if ( xModuleCfgMgr.is() )
1202 {
1203 aTbxSeq = xModuleCfgMgr->getUIElementsInfo( ui::UIElementType::TOOLBAR );
1204 implts_createCustomToolBars( aTbxSeq ); // second create module based toolbars
1205 }
1206}
1207
1209{
1210 SolarMutexClearableGuard aReadLock;
1211
1213 return;
1214
1215 uno::Reference< container::XNameAccess > xPersistentWindowState( m_xPersistentWindowState );
1216 aReadLock.clear();
1217
1218 if (isPreviewFrame())
1219 return;
1220
1221 std::vector< OUString > aMakeVisibleToolbars;
1222
1223 try
1224 {
1225 const uno::Sequence< OUString > aToolbarNames = xPersistentWindowState->getElementNames();
1226
1227 if ( aToolbarNames.hasElements() )
1228 {
1229 OUString aElementType;
1230 OUString aElementName;
1231
1232 aMakeVisibleToolbars.reserve(aToolbarNames.getLength());
1233
1235
1236 for ( OUString const & aName : aToolbarNames )
1237 {
1238 parseResourceURL( aName, aElementType, aElementName );
1239
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 )
1245 {
1246 UIElement aNewToolbar = implts_findToolbar( aName );
1247 bool bFound = ( aNewToolbar.m_aName == aName );
1248 if ( !bFound )
1249 implts_readWindowStateData( aName, aNewToolbar );
1250
1251 if ( aNewToolbar.m_bVisible && !aNewToolbar.m_bContextSensitive )
1252 {
1253 if ( !bFound )
1254 implts_insertToolbar( aNewToolbar );
1255 aMakeVisibleToolbars.push_back( aName );
1256 }
1257 }
1258 }
1259 }
1260 }
1261 catch (const uno::RuntimeException&)
1262 {
1263 throw;
1264 }
1265 catch (const uno::Exception&)
1266 {
1267 }
1268
1269 for (auto const& rURL : aMakeVisibleToolbars)
1270 {
1271 requestToolbar(rURL);
1272 }
1273}
1274
1275void ToolbarLayoutManager::implts_createCustomToolBars( const uno::Sequence< uno::Sequence< beans::PropertyValue > >& aTbxSeqSeq )
1276{
1277 for ( const uno::Sequence< beans::PropertyValue >& rTbxSeq : aTbxSeqSeq )
1278 {
1279 OUString aTbxResName;
1280 OUString aTbxTitle;
1281 for ( const beans::PropertyValue& rProp : rTbxSeq )
1282 {
1283 if ( rProp.Name == "ResourceURL" )
1284 rProp.Value >>= aTbxResName;
1285 else if ( rProp.Name == "UIName" )
1286 rProp.Value >>= aTbxTitle;
1287 }
1288
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 );
1292 }
1293}
1294
1295void ToolbarLayoutManager::implts_createCustomToolBar( const OUString& aTbxResName, const OUString& aTitle )
1296{
1297 if ( aTbxResName.isEmpty() )
1298 return;
1299
1300 if ( !createToolbar( aTbxResName ) )
1301 SAL_WARN("fwk.uielement", "ToolbarLayoutManager cannot create custom toolbar");
1302
1303 uno::Reference< ui::XUIElement > xUIElement = getToolbar( aTbxResName );
1304
1305 if ( !aTitle.isEmpty() && xUIElement.is() )
1306 {
1307 SolarMutexGuard aGuard;
1308
1309 vcl::Window* pWindow = getWindowFromXUIElement( xUIElement );
1310 if ( pWindow )
1311 pWindow->SetText( aTitle );
1312 }
1313}
1314
1316{
1317 SolarMutexClearableGuard aWriteLock;
1318 UIElementVector aUIElementVector = m_aUIElements;
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();
1325
1326 SolarMutexGuard aGuard;
1327 if ( !pContainerWindow )
1328 return;
1329
1330 for (auto const& elem : aUIElementVector)
1331 {
1332 uno::Reference< ui::XUIElement > xUIElement( elem.m_xUIElement );
1333 if ( xUIElement.is() )
1334 {
1335 uno::Reference< awt::XWindow > xWindow;
1336 try
1337 {
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 );
1341 }
1342 catch (const uno::RuntimeException&)
1343 {
1344 throw;
1345 }
1346 catch (const uno::Exception&)
1347 {
1348 }
1349
1350 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
1351 if ( pWindow )
1352 {
1353 // Reparent our child windows according to their current state.
1354 if ( elem.m_bFloating )
1355 pWindow->SetParent( pContainerWindow );
1356 else
1357 {
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 );
1366 }
1367 }
1368 }
1369 }
1370}
1371
1373{
1375 m_bToolbarCreation = bStart;
1376}
1377
1379{
1381 return m_bToolbarCreation;
1382}
1383
1384void ToolbarLayoutManager::implts_setElementData( UIElement& rElement, const uno::Reference< awt::XDockableWindow >& rDockWindow )
1385{
1386 SolarMutexClearableGuard aReadLock;
1387 bool bShowElement( rElement.m_bVisible && !rElement.m_bMasterHide && implts_isParentWindowVisible() );
1388 aReadLock.clear();
1389
1390 uno::Reference< awt::XWindow2 > xWindow( rDockWindow, uno::UNO_QUERY );
1391
1392 vcl::Window* pWindow( nullptr );
1393 ToolBox* pToolBox( nullptr );
1394
1395 if ( !(rDockWindow.is() && xWindow.is()) )
1396 return;
1397
1398 {
1399 SolarMutexGuard aGuard;
1400 pWindow = VCLUnoHelper::GetWindow( xWindow );
1401 if ( pWindow )
1402 {
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);
1410 }
1411 if ( pToolBox )
1412 {
1413 pToolBox->SetButtonType( rElement.m_nStyle );
1414 if ( rElement.m_bNoClose )
1415 pToolBox->SetFloatStyle( pToolBox->GetFloatStyle() & ~WB_CLOSEABLE );
1416 }
1417 }
1418
1419 if ( rElement.m_bFloating )
1420 {
1421 if ( pWindow )
1422 {
1423 SolarMutexGuard aGuard;
1424 OUString aText = pWindow->GetText();
1425 if ( aText.isEmpty() )
1426 pWindow->SetText( rElement.m_aUIName );
1427 }
1428
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 )
1436 {
1438 rElement.m_aFloatingData.m_aPos = aPos; // set new cascaded position
1439 bWriteData = true;
1440 }
1441
1442 if( bSetSize )
1443 xWindow->setOutputSize(rElement.m_aFloatingData.m_aSize);
1444 else
1445 {
1446 if( pToolBox )
1447 {
1448 // set an optimal initial floating size
1449 SolarMutexGuard aGuard;
1450 ::Size aSize( pToolBox->CalcFloatingWindowSizePixel() );
1451 pToolBox->SetOutputSizePixel( aSize );
1452 }
1453 }
1454
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 );
1464
1465 if ( bWriteData )
1466 implts_writeWindowStateData( rElement );
1467 if ( bShowElement && pWindow )
1468 {
1469 SolarMutexGuard aGuard;
1470 pWindow->Show( true, ShowFlags::NoFocusChange | ShowFlags::NoActivate );
1471 }
1472 }
1473 else
1474 {
1475 bool bSetSize( false );
1476 ::Point aPixelPos;
1477 ::Size aSize;
1478
1479 if ( pToolBox )
1480 {
1481 SolarMutexGuard aGuard;
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;
1489
1490 if ( isDefaultPos( rElement.m_aDockedData.m_aPos ))
1491 {
1492 awt::Point aDockPos;
1493 implts_findNextDockingPos( rElement.m_aDockedData.m_nDockedArea, aSize, aDockPos, aPixelPos );
1494 rElement.m_aDockedData.m_aPos = aDockPos;
1495 }
1496 }
1497
1498 xWindow->setPosSize( aPixelPos.X(), aPixelPos.Y(), 0, 0, awt::PosSize::POS );
1499 if( bSetSize )
1500 xWindow->setOutputSize( AWTSize( aSize) );
1501
1502 if ( pWindow )
1503 {
1504 SolarMutexGuard aGuard;
1505 if ( !bShowElement )
1506 pWindow->Hide();
1507 }
1508 }
1509}
1510
1512{
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();
1523
1524 // destroy windows
1525 xTopDockingWindow->dispose();
1526 xLeftDockingWindow->dispose();
1527 xRightDockingWindow->dispose();
1528 xBottomDockingWindow->dispose();
1529}
1530
1531// persistence methods
1532
1533bool ToolbarLayoutManager::implts_readWindowStateData( const OUString& aName, UIElement& rElementData )
1534{
1537}
1538
1540{
1541 SolarMutexClearableGuard aWriteLock;
1542 uno::Reference< container::XNameAccess > xPersistentWindowState( m_xPersistentWindowState );
1543 aWriteLock.clear();
1544
1545 bool bPersistent( false );
1546 uno::Reference< beans::XPropertySet > xPropSet( rElementData.m_xUIElement, uno::UNO_QUERY );
1547 if ( xPropSet.is() )
1548 {
1549 try
1550 {
1551 // Check persistent flag of the user interface element
1552 xPropSet->getPropertyValue("Persistent") >>= bPersistent;
1553 }
1554 catch (const beans::UnknownPropertyException&)
1555 {
1556 bPersistent = true; // Non-configurable elements should at least store their dimension/position
1557 }
1558 catch (const lang::WrappedTargetException&)
1559 {
1560 }
1561 }
1562
1563 if ( !(bPersistent && xPersistentWindowState.is()) )
1564 return;
1565
1566 try
1567 {
1568 uno::Sequence<beans::PropertyValue> aWindowState{
1572 rElementData.m_aDockedData.m_nDockedArea),
1574 rElementData.m_aDockedData.m_aPos),
1576 rElementData.m_aFloatingData.m_aPos),
1578 rElementData.m_aFloatingData.m_aSize),
1581 rElementData.m_aDockedData.m_bLocked),
1583 static_cast<sal_uInt16>(rElementData.m_nStyle))
1584 };
1585
1586 OUString aName = rElementData.m_aName;
1587 if ( xPersistentWindowState->hasByName( aName ))
1588 {
1589 uno::Reference< container::XNameReplace > xReplace( xPersistentWindowState, uno::UNO_QUERY );
1590 xReplace->replaceByName( aName, uno::Any( aWindowState ));
1591 }
1592 else
1593 {
1594 uno::Reference< container::XNameContainer > xInsert( xPersistentWindowState, uno::UNO_QUERY );
1595 xInsert->insertByName( aName, uno::Any( aWindowState ));
1596 }
1597 }
1598 catch (const uno::Exception&)
1599 {
1600 }
1601}
1602
1603/******************************************************************************
1604 LOOKUP PART FOR TOOLBARS
1605******************************************************************************/
1606
1608{
1609 static UIElement aEmptyElement;
1610
1612 for (auto & elem : m_aUIElements)
1613 {
1614 if ( elem.m_aName == aName )
1615 return elem;
1616 }
1617
1618 return aEmptyElement;
1619}
1620
1622{
1624 return impl_findToolbar( aName );
1625}
1626
1627UIElement ToolbarLayoutManager::implts_findToolbar( const uno::Reference< uno::XInterface >& xToolbar )
1628{
1629 UIElement aToolbar;
1630
1632 for (auto const& elem : m_aUIElements)
1633 {
1634 if ( elem.m_xUIElement.is() )
1635 {
1636 uno::Reference< uno::XInterface > xIfac( elem.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
1637 if ( xIfac == xToolbar )
1638 {
1639 aToolbar = elem;
1640 break;
1641 }
1642 }
1643 }
1644
1645 return aToolbar;
1646}
1647
1648uno::Reference< awt::XWindow > ToolbarLayoutManager::implts_getXWindow( std::u16string_view aName )
1649{
1650 uno::Reference< awt::XWindow > xWindow;
1651
1653 for (auto const& elem : m_aUIElements)
1654 {
1655 if ( elem.m_aName == aName && elem.m_xUIElement.is() )
1656 {
1657 xWindow.set( elem.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
1658 break;
1659 }
1660 }
1661
1662 return xWindow;
1663}
1664
1666{
1667 uno::Reference< awt::XWindow > xWindow = implts_getXWindow( aName );
1668 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
1669
1670 return pWindow;
1671}
1672
1674{
1675 UIElement aTempData;
1676 bool bFound( false );
1677 bool bResult( false );
1678
1679 aTempData = implts_findToolbar( rUIElement.m_aName );
1680 if ( aTempData.m_aName == rUIElement.m_aName )
1681 bFound = true;
1682
1683 if ( !bFound )
1684 {
1686 m_aUIElements.push_back( rUIElement );
1687 bResult = true;
1688 }
1689
1690 return bResult;
1691}
1692
1694{
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 );
1701}
1702
1703/******************************************************************************
1704 LAYOUT CODE PART FOR TOOLBARS
1705******************************************************************************/
1706
1708{
1709 const sal_Int32 nHotZoneX = 50;
1710 const sal_Int32 nHotZoneY = 50;
1711 const sal_Int32 nCascadeIndentX = 15;
1712 const sal_Int32 nCascadeIndentY = 15;
1713
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();
1719
1720 awt::Point aStartPos( nCascadeIndentX, nCascadeIndentY );
1721 awt::Point aCurrPos( aStartPos );
1722
1723 if ( xContainerWindow.is() )
1724 {
1725 SolarMutexGuard aGuard;
1726 VclPtr<vcl::Window> pContainerWindow = VCLUnoHelper::GetWindow( xContainerWindow );
1727 if ( pContainerWindow )
1728 aStartPos = AWTPoint(pContainerWindow->OutputToScreenPixel(VCLPoint(aStartPos)));
1729 }
1730
1731 // Determine size of top and left docking area
1732 awt::Rectangle aTopRect( xTopDockingWindow->getPosSize() );
1733 awt::Rectangle aLeftRect( xLeftDockingWindow->getPosSize() );
1734
1735 aStartPos.X += aLeftRect.Width + nCascadeIndentX;
1736 aStartPos.Y += aTopRect.Height + nCascadeIndentY;
1737 aCurrPos = aStartPos;
1738
1739 // Try to find a cascaded position for the new floating window
1740 for (auto const& elem : m_aUIElements)
1741 {
1742 if ( elem.m_xUIElement.is() )
1743 {
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() )
1747 {
1748 SolarMutexGuard aGuard;
1749 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
1750 if ( pWindow && pWindow->IsVisible() )
1751 {
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 ))
1757 {
1758 aCurrPos.X = aFloatRect.X + nCascadeIndentX;
1759 aCurrPos.Y = aFloatRect.Y + nCascadeIndentY;
1760 }
1761 }
1762 }
1763 }
1764 }
1765
1766 return aCurrPos;
1767}
1768
1770{
1772
1773 std::stable_sort( m_aUIElements.begin(), m_aUIElements.end()); // first created element should first
1774
1775 // We have to reset our temporary flags.
1776 for (auto & elem : m_aUIElements)
1777 elem.m_bUserActive = false;
1778}
1779
1781{
1783 rCopy = m_aUIElements;
1784}
1785
1787{
1788 ::Size aSize;
1789 uno::Reference< awt::XWindow > xTopDockingAreaWindow;
1790 uno::Reference< awt::XWindow > xBottomDockingAreaWindow;
1791
1792 {
1793 SolarMutexGuard aReadLock;
1794 xTopDockingAreaWindow = m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_TOP)];
1795 xBottomDockingAreaWindow = m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_BOTTOM)];
1796 }
1797
1798 if ( xTopDockingAreaWindow.is() )
1799 aSize.setWidth( xTopDockingAreaWindow->getPosSize().Height );
1800 if ( xBottomDockingAreaWindow.is() )
1801 aSize.setHeight( xBottomDockingAreaWindow->getPosSize().Height );
1802
1803 return aSize;
1804}
1805
1806void ToolbarLayoutManager::implts_getDockingAreaElementInfos( ui::DockingArea eDockingArea, std::vector< SingleRowColumnWindowData >& rRowColumnsWindowData )
1807{
1808 std::vector< UIElement > aWindowVector;
1809
1810 if (( eDockingArea < ui::DockingArea_DOCKINGAREA_TOP ) || ( eDockingArea > ui::DockingArea_DOCKINGAREA_RIGHT ))
1811 eDockingArea = ui::DockingArea_DOCKINGAREA_TOP;
1812
1813 uno::Reference< awt::XWindow > xDockAreaWindow;
1814
1815 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
1816 {
1817 SolarMutexGuard aReadLock;
1818 aWindowVector.reserve(m_aUIElements.size());
1819 xDockAreaWindow = m_xDockAreaWindows[static_cast<int>(eDockingArea)];
1820 for (auto const& elem : m_aUIElements)
1821 {
1822 if (elem.m_aDockedData.m_nDockedArea == eDockingArea && elem.m_bVisible)
1823 {
1824 uno::Reference<ui::XUIElement> xUIElement(elem.m_xUIElement);
1825 if (xUIElement.is())
1826 {
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())
1831 {
1832 if (!elem.m_bFloating)
1833 {
1834 // docked windows
1835 aWindowVector.push_back(elem);
1836 }
1837 else
1838 {
1839 // floating windows
1842 if (pDockMgr != nullptr)
1843 {
1844 SystemWindow* pFloatingWindow = pDockMgr->GetFloatingWindow(pWindow);
1845 if (pFloatingWindow)
1846 {
1847 // update the position data of the floating window
1848 if (pFloatingWindow->UpdatePositionData())
1849 {
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);
1856 }
1857 }
1858 }
1859 }
1860 }
1861 }
1862 }
1863 }
1864 }
1865 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
1866
1867 rRowColumnsWindowData.clear();
1868
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;
1876
1877 if ( xDockAreaWindow.is() )
1878 aDockAreaRect = xDockAreaWindow->getPosSize();
1879
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;
1888
1889 const sal_uInt32 nCount = aWindowVector.size();
1890 for ( j = 0; j < sal_Int32( nCount); j++ )
1891 {
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;
1896
1897 if ( !lcl_checkUIElement(xUIElement,aPosSize,xWindow) )
1898 continue;
1899 if ( isHorizontalDockingArea( eDockingArea ))
1900 {
1901 if ( nCurrPos == -1 )
1902 {
1903 nCurrPos = rElement.m_aDockedData.m_aPos.Y;
1904 nLastPos = 0;
1905
1906 SingleRowColumnWindowData aRowColumnWindowData;
1907 aRowColumnWindowData.nRowColumn = nCurrPos;
1908 rRowColumnsWindowData.push_back( aRowColumnWindowData );
1909 }
1910
1911 sal_Int32 nSpace( 0 );
1912 if ( rElement.m_aDockedData.m_aPos.Y != nCurrPos )
1913 {
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 );
1924 }
1925
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 )
1929 {
1930 rRowColumnsWindowData[nIndex].nSpace += nSpace;
1931 nLastPos = rElement.m_aDockedData.m_aPos.X + aPosSize.Width;
1932 }
1933 else
1934 {
1935 nSpace = 0;
1936 nLastPos += aPosSize.Width;
1937 }
1938 rRowColumnsWindowData[nIndex].aRowColumnSpace.push_back( nSpace );
1939
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;
1956 }
1957 else
1958 {
1959 if ( nCurrPos == -1 )
1960 {
1961 nCurrPos = rElement.m_aDockedData.m_aPos.X;
1962 nLastPos = 0;
1963
1964 SingleRowColumnWindowData aRowColumnWindowData;
1965 aRowColumnWindowData.nRowColumn = nCurrPos;
1966 rRowColumnsWindowData.push_back( aRowColumnWindowData );
1967 }
1968
1969 sal_Int32 nSpace( 0 );
1970 if ( rElement.m_aDockedData.m_aPos.X != nCurrPos )
1971 {
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 );
1982 }
1983
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 )
1987 {
1988 rRowColumnsWindowData[nIndex].nSpace += nSpace;
1989 nLastPos = rElement.m_aDockedData.m_aPos.Y + aPosSize.Height;
1990 }
1991 else
1992 {
1993 nSpace = 0;
1994 nLastPos += aPosSize.Height;
1995 }
1996 rRowColumnsWindowData[nIndex].aRowColumnSpace.push_back( nSpace );
1997
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;
2014 }
2015 }
2016}
2017
2018void ToolbarLayoutManager::implts_getDockingAreaElementInfoOnSingleRowCol( ui::DockingArea eDockingArea, sal_Int32 nRowCol, SingleRowColumnWindowData& rRowColumnWindowData )
2019{
2020 std::vector< UIElement > aWindowVector;
2021
2022 if (( eDockingArea < ui::DockingArea_DOCKINGAREA_TOP ) || ( eDockingArea > ui::DockingArea_DOCKINGAREA_RIGHT ))
2023 eDockingArea = ui::DockingArea_DOCKINGAREA_TOP;
2024
2025 bool bHorzDockArea = isHorizontalDockingArea( eDockingArea );
2026
2027 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
2028 {
2029 SolarMutexGuard aReadLock;
2030 for (auto const& elem : m_aUIElements)
2031 {
2032 if (elem.m_aDockedData.m_nDockedArea == eDockingArea)
2033 {
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);
2037
2038 if (bSameRowCol && xUIElement.is())
2039 {
2040 uno::Reference<awt::XWindow> xWindow(xUIElement->getRealInterface(),
2041 uno::UNO_QUERY);
2042 if (xWindow.is())
2043 {
2044 SolarMutexGuard aGuard;
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
2049 }
2050 }
2051 }
2052 }
2053 }
2054 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
2055
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;
2065
2066 // Collect data from windows that are on the same row/column
2067 sal_Int32 j;
2068 sal_Int32 nLastPos( 0 );
2069
2070 const sal_uInt32 nCount = aWindowVector.size();
2071 for ( j = 0; j < sal_Int32( nCount); j++ )
2072 {
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;
2079
2080 sal_Int32 nSpace;
2081 if ( isHorizontalDockingArea( eDockingArea ))
2082 {
2083 nSpace = ( rElement.m_aDockedData.m_aPos.X - nLastPos );
2084
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;
2090
2091 nLastPos = rElement.m_aDockedData.m_aPos.X + aPosSize.Width;
2092
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;
2099 }
2100 else
2101 {
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;
2108
2109 nLastPos = rElement.m_aDockedData.m_aPos.Y + aPosSize.Height;
2110
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;
2117 }
2118
2119 rRowColumnWindowData.aUIElementNames.push_back( rElement.m_aName );
2120 rRowColumnWindowData.aRowColumnWindows.push_back( xWindow );
2121 rRowColumnWindowData.aRowColumnSpace.push_back( nSpace );
2122 rRowColumnWindowData.nVarSize += nSpace;
2123 }
2124}
2125
2127 ui::DockingArea DockingArea,
2128 const SingleRowColumnWindowData& rRowColumnWindowData,
2129 const ::Point& rMousePos,
2130 std::u16string_view rExcludeElementName )
2131{
2132 ::tools::Rectangle aWinRect;
2133
2134 if (( DockingArea < ui::DockingArea_DOCKINGAREA_TOP ) || ( DockingArea > ui::DockingArea_DOCKINGAREA_RIGHT ))
2135 DockingArea = ui::DockingArea_DOCKINGAREA_TOP;
2136
2137 if ( rRowColumnWindowData.aRowColumnWindows.empty() )
2138 return aWinRect;
2139 else
2140 {
2141 SolarMutexClearableGuard aReadLock;
2143 VclPtr<vcl::Window> pDockingAreaWindow( VCLUnoHelper::GetWindow( m_xDockAreaWindows[static_cast<int>(DockingArea)] ));
2144 aReadLock.clear();
2145
2146 // Calc correct position of the column/row rectangle to be able to compare it with mouse pos/tracking rect
2147 SolarMutexGuard aGuard;
2148
2149 // Retrieve output size from container Window
2150 if ( pDockingAreaWindow && pContainerWindow )
2151 {
2152 const sal_uInt32 nCount = rRowColumnWindowData.aRowColumnWindows.size();
2153 for ( sal_uInt32 i = 0; i < nCount; i++ )
2154 {
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 ))
2159 {
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;
2166 }
2167 }
2168 }
2169 }
2170
2171 return aWinRect;
2172}
2173
2175 ui::DockingArea eDockingArea,
2176 sal_Int32 nRowCol,
2177 const ::tools::Rectangle& rDockedElementRect,
2178 std::u16string_view rMovedElementName,
2179 const ::tools::Rectangle& rMovedElementRect )
2180{
2181 SingleRowColumnWindowData aRowColumnWindowData;
2182
2183 bool bHorzDockArea( isHorizontalDockingArea( eDockingArea ));
2184 implts_getDockingAreaElementInfoOnSingleRowCol( eDockingArea, nRowCol, aRowColumnWindowData );
2185 if ( aRowColumnWindowData.aRowColumnWindows.empty() )
2186 return rMovedElementRect;
2187 else
2188 {
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++ )
2193 {
2194 if ( bHorzDockArea )
2195 {
2196 if ( aRowColumnWindowData.aRowColumnWindowSizes[i].X >= rDockedElementRect.Left() )
2197 {
2198 nSpace += aRowColumnWindowData.aRowColumnSpace[i];
2199 break;
2200 }
2201 else if ( aRowColumnWindowData.aUIElementNames[i] == rMovedElementName )
2202 nSpace += aRowColumnWindowData.aRowColumnWindowSizes[i].Width +
2203 aRowColumnWindowData.aRowColumnSpace[i];
2204 else
2205 nSpace = 0;
2206 }
2207 else
2208 {
2209 if ( aRowColumnWindowData.aRowColumnWindowSizes[i].Y >= rDockedElementRect.Top() )
2210 {
2211 nSpace += aRowColumnWindowData.aRowColumnSpace[i];
2212 break;
2213 }
2214 else if ( aRowColumnWindowData.aUIElementNames[i] == rMovedElementName )
2215 nSpace += aRowColumnWindowData.aRowColumnWindowSizes[i].Height +
2216 aRowColumnWindowData.aRowColumnSpace[i];
2217 else
2218 nSpace = 0;
2219 }
2220 }
2221
2222 if ( nSpace > 0 )
2223 {
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 );
2229 }
2230
2231 return aFrontDockingRect;
2232 }
2233}
2234
2235void ToolbarLayoutManager::implts_findNextDockingPos( ui::DockingArea DockingArea, const ::Size& aUIElementSize, awt::Point& rVirtualPos, ::Point& rPixelPos )
2236{
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;
2242
2243 // Retrieve output size from container Window
2244 vcl::Window* pDockingWindow = VCLUnoHelper::GetWindow( xDockingWindow );
2245 if ( pDockingWindow )
2246 aDockingWinSize = pDockingWindow->GetOutputSizePixel();
2247 aReadLock.clear();
2248
2249 sal_Int32 nFreeRowColPixelPos( 0 );
2250 sal_Int32 nMaxSpace( 0 );
2251 sal_Int32 nNeededSpace( 0 );
2252 sal_Int32 nTopDockingAreaSize( 0 );
2253
2254 if ( isHorizontalDockingArea( DockingArea ))
2255 {
2256 nMaxSpace = aDockingWinSize.Width();
2257 nNeededSpace = aUIElementSize.Width();
2258 }
2259 else
2260 {
2261 nMaxSpace = aDockingWinSize.Height();
2262 nNeededSpace = aUIElementSize.Height();
2263 nTopDockingAreaSize = implts_getTopBottomDockingAreaSizes().Width();
2264 }
2265
2266 std::vector< SingleRowColumnWindowData > aRowColumnsWindowData;
2267
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++ )
2272 {
2273 SingleRowColumnWindowData& rRowColumnWindowData = aRowColumnsWindowData[i];
2274
2275 if (( DockingArea == ui::DockingArea_DOCKINGAREA_BOTTOM ) ||
2276 ( DockingArea == ui::DockingArea_DOCKINGAREA_RIGHT ))
2277 nPixelPos += rRowColumnWindowData.nStaticSize;
2278
2279 if ((( nMaxSpace - rRowColumnWindowData.nVarSize ) >= nNeededSpace ) ||
2280 ( rRowColumnWindowData.nSpace >= nNeededSpace ))
2281 {
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++ )
2286 {
2287 awt::Rectangle rRect = rRowColumnWindowData.aRowColumnWindowSizes[j];
2288 sal_Int32& rSpace = rRowColumnWindowData.aRowColumnSpace[j];
2289 if ( isHorizontalDockingArea( DockingArea ))
2290 {
2291 if ( rSpace >= nNeededSpace )
2292 {
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;
2299 }
2300 nCurrPos = rRect.X + rRect.Width;
2301 }
2302 else
2303 {
2304 if ( rSpace >= nNeededSpace )
2305 {
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;
2312 }
2313 nCurrPos = rRect.Y + rRect.Height;
2314 }
2315 }
2316
2317 if (( nCurrPos + nNeededSpace ) <= nMaxSpace )
2318 {
2319 if ( isHorizontalDockingArea( DockingArea ))
2320 {
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;
2327 }
2328 else
2329 {
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;
2336 }
2337 }
2338 }
2339
2340 if (( DockingArea == ui::DockingArea_DOCKINGAREA_TOP ) || ( DockingArea == ui::DockingArea_DOCKINGAREA_LEFT ))
2341 nPixelPos += rRowColumnWindowData.nStaticSize;
2342 }
2343
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;
2350
2351 if ( nNextFreeRowCol == 0 )
2352 {
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();
2357 }
2358
2359 if ( isHorizontalDockingArea( DockingArea ))
2360 {
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 );
2366 }
2367 else
2368 {
2369 rVirtualPos = awt::Point( nNextFreeRowCol, 0 );
2370 rPixelPos = ::Point( aDockingWinSize.Width() - nFreeRowColPixelPos, 0 );
2371 }
2372}
2373
2375 sal_Int32 nDockingArea,
2376 sal_Int32 nOffset,
2377 SingleRowColumnWindowData& rRowColumnWindowData,
2378 const ::Size& rContainerSize )
2379{
2380 sal_Int32 nDiff(0);
2381 sal_Int32 nRCSpace( rRowColumnWindowData.nSpace );
2382 sal_Int32 nContainerClientSize(0);
2383
2384 if ( rRowColumnWindowData.aRowColumnWindows.empty() )
2385 return;
2386
2387 if ( isHorizontalDockingArea( nDockingArea ))
2388 {
2389 nContainerClientSize = rContainerSize.Width();
2390 nDiff = nContainerClientSize - rRowColumnWindowData.nVarSize;
2391 }
2392 else
2393 {
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;
2398 }
2399
2400 const sal_uInt32 nCount = rRowColumnWindowData.aRowColumnWindowSizes.size();
2401 if (( nDiff < 0 ) && ( nRCSpace > 0 ))
2402 {
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 )
2406 {
2407 sal_Int32 nSpace = rRowColumnWindowData.aRowColumnSpace[i];
2408 if ( nSpace >= -nDiff )
2409 {
2410 if ( isHorizontalDockingArea( nDockingArea ))
2411 {
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;
2415 }
2416 else
2417 {
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;
2421 }
2422 nDiff = 0;
2423
2424 break;
2425 }
2426 else if ( nSpace > 0 )
2427 {
2428 if ( isHorizontalDockingArea( nDockingArea ))
2429 {
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;
2433 }
2434 else
2435 {
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;
2439 }
2440 nDiff += nSpace;
2441 }
2442 --i;
2443 }
2444 }
2445
2446 // Check if we have to reduce further
2447 if ( nDiff < 0 )
2448 {
2449 // Now we have to reduce the size of certain docked windows
2450 sal_Int32 i = sal_Int32( nCount - 1 );
2451 while ( i >= 0 )
2452 {
2453 awt::Rectangle& rWinRect = rRowColumnWindowData.aRowColumnWindowSizes[i];
2454 ::Size aMinSize;
2455
2456 SolarMutexGuard aGuard;
2457 {
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();
2462 }
2463
2464 if ( !aMinSize.IsEmpty() )
2465 {
2466 if ( isHorizontalDockingArea( nDockingArea ))
2467 {
2468 sal_Int32 nMaxReducation = rWinRect.Width - aMinSize.Width();
2469 if ( nMaxReducation >= -nDiff )
2470 {
2471 rWinRect.Width = rWinRect.Width + nDiff;
2472 nDiff = 0;
2473 }
2474 else
2475 {
2476 rWinRect.Width = aMinSize.Width();
2477 nDiff += nMaxReducation;
2478 }
2479
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;
2483 }
2484 else
2485 {
2486 sal_Int32 nMaxReducation = rWinRect.Height - aMinSize.Height();
2487 if ( nMaxReducation >= -nDiff )
2488 {
2489 rWinRect.Height = rWinRect.Height + nDiff;
2490 nDiff = 0;
2491 }
2492 else
2493 {
2494 rWinRect.Height = aMinSize.Height();
2495 nDiff += nMaxReducation;
2496 }
2497
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;
2501 }
2502 }
2503
2504 if ( nDiff >= 0 )
2505 break;
2506
2507 --i;
2508 }
2509 }
2510
2511 SolarMutexClearableGuard aReadLock;
2512 VclPtr<vcl::Window> pDockAreaWindow = VCLUnoHelper::GetWindow( m_xDockAreaWindows[nDockingArea] );
2513 aReadLock.clear();
2514
2515 sal_Int32 nCurrPos( 0 );
2516
2517 SolarMutexGuard aGuard;
2518 for ( sal_uInt32 i = 0; i < nCount; i++ )
2519 {
2520 uno::Reference< awt::XWindow > xWindow = rRowColumnWindowData.aRowColumnWindows[i];
2521 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
2522 vcl::Window* pOldParentWindow = pWindow->GetParent();
2523
2524 if ( pDockAreaWindow != pOldParentWindow )
2525 pWindow->SetParent( pDockAreaWindow );
2526
2527 awt::Rectangle aWinRect = rRowColumnWindowData.aRowColumnWindowSizes[i];
2528 if ( isHorizontalDockingArea( nDockingArea ))
2529 {
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;
2535 }
2536 else
2537 {
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;
2543 }
2544 }
2545}
2546
2548{
2550 m_bLayoutDirty = true;
2551}
2552
2554{
2556 m_bLayoutInProgress = bInProgress;
2557}
2558
2559::tools::Rectangle ToolbarLayoutManager::implts_calcHotZoneRect( const ::tools::Rectangle& rRect, sal_Int32 nHotZoneOffset )
2560{
2561 ::tools::Rectangle aRect( rRect );
2562
2563 aRect.AdjustLeft( -nHotZoneOffset );
2564 aRect.AdjustTop( -nHotZoneOffset );
2565 aRect.AdjustRight(nHotZoneOffset );
2566 aRect.AdjustBottom(nHotZoneOffset );
2567
2568 return aRect;
2569}
2570
2572 UIElement& rUIElement,
2573 DockingOperation& rDockingOperation,
2574 ::tools::Rectangle& rTrackingRect,
2575 const Point& rMousePos )
2576{
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();
2583
2584 if ( !rUIElement.m_xUIElement.is() )
2585 {
2586 rTrackingRect = ::tools::Rectangle();
2587 return;
2588 }
2589
2590 {
2591 // Retrieve output size from container Window
2592 SolarMutexGuard aGuard;
2593 pContainerWindow = VCLUnoHelper::GetWindow( xContainerWindow );
2594 aContainerWinSize = pContainerWindow->GetOutputSizePixel();
2595 }
2596
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;
2612
2613 aReadLock.reset();
2614 xDockingAreaWindow = m_xDockAreaWindows[static_cast<int>(eDockedArea)];
2615 aReadLock.clear();
2616
2617 {
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());
2624
2625 aDockingAreaRect = ::tools::Rectangle( pDockingAreaWindow->GetPosPixel(), pDockingAreaWindow->GetSizePixel() );
2626 if ( pToolBox )
2627 {
2628 // docked toolbars always have one line
2629 ::Size aSize = pToolBox->CalcWindowSizePixel( 1, ImplConvertAlignment( eDockedArea ) );
2630 aTrackingRect.SetSize( ::Size( aSize.Width(), aSize.Height() ));
2631 }
2632 }
2633
2634 // default docking operation, dock on the given row/column
2635 bool bOpOutsideOfDockingArea( !aDockingAreaRect.Contains( rMousePos ));
2636
2637 std::vector< SingleRowColumnWindowData > aRowColumnsWindowData;
2638
2639 rDockingOperation = DOCKOP_ON_COLROW;
2640 implts_getDockingAreaElementInfos( eDockedArea, aRowColumnsWindowData );
2641
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++ )
2647 {
2648 if ( aRowColumnsWindowData[i].nRowColumn > nMaxRowCol )
2649 nMaxRowCol = aRowColumnsWindowData[i].nRowColumn;
2650 if ( aRowColumnsWindowData[i].nRowColumn < nMinRowCol )
2651 nMinRowCol = aRowColumnsWindowData[i].nRowColumn;
2652 }
2653
2654 if ( !bOpOutsideOfDockingArea )
2655 {
2656 // docking inside our docking area
2657 sal_Int32 nIndex( -1 );
2658 sal_Int32 nRowCol( -1 );
2659 ::tools::Rectangle aWindowRect;
2660 ::tools::Rectangle aRowColumnRect;
2661
2662 const sal_uInt32 nWindowDataCount = aRowColumnsWindowData.size();
2663 for ( sal_uInt32 i = 0; i < nWindowDataCount; i++ )
2664 {
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 );
2669
2670 {
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() )));
2674 }
2675
2676 bool bIsInsideRowCol( aRect.Contains( rMousePos ) );
2677 if ( bIsInsideRowCol )
2678 {
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;
2685 }
2686 }
2687
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 ))
2690 {
2691 if ( rDockingOperation == DOCKOP_ON_COLROW )
2692 {
2693 if ( !aWindowRect.IsEmpty())
2694 {
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.
2697
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 )
2703 {
2704 if ( bHorizontalDockArea )
2705 {
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();
2710
2711 aUIElementRect.SetSize( ::Size( nSize, aWindowRect.getOpenHeight() ));
2712 aWindowRect = implts_determineFrontDockingRect( eDockedArea, nRowCol, aWindowRect,rUIElement.m_aName, aUIElementRect );
2713
2714 // Set virtual position
2715 rUIElement.m_aDockedData.m_aPos.X = aWindowRect.Left();
2716 rUIElement.m_aDockedData.m_aPos.Y = nRowCol;
2717 }
2718 else
2719 {
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();
2724
2725 aUIElementRect.SetSize( ::Size( aWindowRect.getOpenWidth(), nSize ));
2726 aWindowRect = implts_determineFrontDockingRect( eDockedArea, nRowCol, aWindowRect, rUIElement.m_aName, aUIElementRect );
2727
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;
2733 }
2734
2735 rTrackingRect = aWindowRect;
2736 return;
2737 }
2738 else
2739 {
2740 if ( bHorizontalDockArea )
2741 {
2742 sal_Int32 nSize = ::std::clamp( sal_Int32(aContainerWinSize.Width() - aWindowRect.Right()),
2743 sal_Int32(0), sal_Int32(aTrackingRect.getOpenWidth()) );
2744 if ( nSize == 0 )
2745 {
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();
2749
2750 }
2751 else
2752 {
2753 aUIElementRect.SetPos( ::Point( aWindowRect.Right(), aWindowRect.Top() ));
2754 aUIElementRect.SetSize( ::Size( nSize, aWindowRect.getOpenHeight() ));
2755 rUIElement.m_aDockedData.m_aPos.X = aWindowRect.Right();
2756 }
2757
2758 // Set virtual position
2759 rUIElement.m_aDockedData.m_aPos.Y = nRowCol;
2760 }
2761 else
2762 {
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 ));
2767
2768 // Set virtual position
2769 sal_Int32 nPosY( 0 );
2770 {
2771 SolarMutexGuard aGuard;
2772 nPosY = pDockingAreaWindow->ScreenToOutputPixel(
2773 pContainerWindow->OutputToScreenPixel( aWindowRect.BottomRight() )).Y();
2774 }
2775 rUIElement.m_aDockedData.m_aPos.X = nRowCol;
2776 rUIElement.m_aDockedData.m_aPos.Y = nPosY;
2777 }
2778
2779 rTrackingRect = aUIElementRect;
2780 return;
2781 }
2782 }
2783 else
2784 {
2785 implts_setTrackingRect( eDockedArea, rMousePos, aTrackingRect );
2786 rTrackingRect = implts_calcTrackingAndElementRect(
2787 eDockedArea, nRowCol, rUIElement,
2788 aTrackingRect, aRowColumnRect, aContainerWinSize );
2789 return;
2790 }
2791 }
2792 else
2793 {
2794 if ((( nRowCol == nMinRowCol ) && ( rDockingOperation == DOCKOP_BEFORE_COLROW )) ||
2795 (( nRowCol == nMaxRowCol ) && ( rDockingOperation == DOCKOP_AFTER_COLROW )))
2796 bOpOutsideOfDockingArea = true;
2797 else
2798 {
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 );
2804
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 ));
2811
2812 if ( rDockingOperation == DOCKOP_BEFORE_COLROW )
2813 {
2814 if (( eDockedArea == ui::DockingArea_DOCKINGAREA_TOP ) || ( eDockedArea == ui::DockingArea_DOCKINGAREA_LEFT ))
2815 {
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;
2821 }
2822 }
2823 else
2824 {
2825 if (( eDockedArea == ui::DockingArea_DOCKINGAREA_BOTTOM ) || ( eDockedArea == ui::DockingArea_DOCKINGAREA_RIGHT ))
2826 {
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;
2832 }
2833 nRowCol++;
2834 }
2835
2836 if ( bHorizontalDockArea )
2837 rUIElement.m_aDockedData.m_aPos.Y = nRowCol;
2838 else
2839 rUIElement.m_aDockedData.m_aPos.X = nRowCol;
2840
2841 rTrackingRect.Move( nOffsetX, nOffsetY );
2842 rTrackingRect.SetSize( aTrackingRect.GetSize() );
2843 }
2844 }
2845 }
2846 }
2847
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;
2852
2853 // set correct size for docking
2854 implts_setTrackingRect( eDockedArea, rMousePos, aTrackingRect );
2855 rTrackingRect = aTrackingRect;
2856
2857 if ( bHorizontalDockArea )
2858 {
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 )));
2864
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 )
2868 {
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;
2874 }
2875 else if ( rMousePos.Y() < ( aDockingAreaRect.Top() + ( nDockHeight / 2 )))
2876 {
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;
2883 }
2884 else
2885 {
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;
2892 }
2893 rTrackingRect.setWidth( nSize );
2894
2895 {
2896 SolarMutexGuard aGuard;
2897 nPosX = pDockingAreaWindow->ScreenToOutputPixel(
2898 pContainerWindow->OutputToScreenPixel( rTrackingRect.TopLeft() )).X();
2899 }
2900 rUIElement.m_aDockedData.m_aPos.X = nPosX;
2901 }
2902 else
2903 {
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 ));
2910
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 )
2914 {
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;
2920 }
2921 else if ( rMousePos.X() < ( aDockingAreaRect.Left() + ( nDockWidth / 2 )))
2922 {
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;
2929 }
2930 else
2931 {
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;
2938 }
2939 rTrackingRect.setHeight( nSize );
2940
2941 {
2942 SolarMutexGuard aGuard;
2943 nPosY = pDockingAreaWindow->ScreenToOutputPixel(
2944 pContainerWindow->OutputToScreenPixel( rTrackingRect.TopLeft() )).Y();
2945 }
2946 rUIElement.m_aDockedData.m_aPos.Y = nPosY;
2947 }
2948}
2949
2951 ui::DockingArea DockingArea,
2952 const ::tools::Rectangle& rRowColRect,
2953 const Point& rMousePos )
2954{
2955 constexpr sal_Int32 nHorzVerticalRegionSize = 6;
2956 constexpr sal_Int32 nHorzVerticalMoveRegion = 4;
2957
2958 if ( rRowColRect.Contains( rMousePos ))
2959 {
2960 if ( isHorizontalDockingArea( DockingArea ))
2961 {
2962 sal_Int32 nRegion = rRowColRect.getOpenHeight() / nHorzVerticalRegionSize;
2963 sal_Int32 nPosY = rRowColRect.Top() + nRegion;
2964
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;
2971 }
2972 else
2973 {
2974 sal_Int32 nRegion = rRowColRect.getOpenWidth() / nHorzVerticalRegionSize;
2975 sal_Int32 nPosX = rRowColRect.Left() + nRegion;
2976
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;
2983 }
2984 }
2985 else
2986 return DOCKOP_ON_COLROW;
2987}
2988
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 )
2996{
2997 SolarMutexResettableGuard aReadGuard;
2998 ::tools::Rectangle aDockingAreaOffsets( m_aDockingAreaOffsets );
2999 aReadGuard.clear();
3000
3001 bool bHorizontalDockArea( isHorizontalDockingArea( eDockingArea ));
3002
3003 sal_Int32 nTopDockingAreaSize( implts_getTopBottomDockingAreaSizes().Width() );
3004 sal_Int32 nBottomDockingAreaSize( implts_getTopBottomDockingAreaSizes().Height() );
3005
3006 sal_Int32 nMaxLeftRightDockAreaSize = rContainerWinSize.Height() -
3007 nTopDockingAreaSize -
3008 nBottomDockingAreaSize -
3009 aDockingAreaOffsets.Top() -
3010 aDockingAreaOffsets.Bottom();
3011
3012 ::tools::Rectangle aTrackingRect( rTrackingRect );
3013 if ( bHorizontalDockArea )
3014 {
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 )));
3020
3021 sal_Int32 nSize = std::min( rContainerWinSize.Width(), rTrackingRect.getOpenWidth() );
3022
3023 aTrackingRect.SetPos( ::Point( nPosX, rRowColumnRect.Top() ));
3024 aTrackingRect.setWidth( nSize );
3025 aTrackingRect.setHeight( rRowColumnRect.getOpenHeight() );
3026
3027 // Set virtual position
3028 rUIElement.m_aDockedData.m_aPos.X = nPosX;
3029 rUIElement.m_aDockedData.m_aPos.Y = nRowCol;
3030 }
3031 else
3032 {
3033 sal_Int32 nMaxDockingAreaHeight = std::max<sal_Int32>( 0, nMaxLeftRightDockAreaSize );
3034
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 ));
3040
3041 sal_Int32 nSize = std::min( nMaxDockingAreaHeight, static_cast<sal_Int32>(aTrackingRect.getOpenHeight()) );
3042
3043 aTrackingRect.SetPos( ::Point( rRowColumnRect.Left(), nPosY ));
3044 aTrackingRect.setWidth( rRowColumnRect.getOpenWidth() );
3045 aTrackingRect.setHeight( nSize );
3046
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();
3051
3052 sal_Int32 nDockPosY( 0 );
3053 {
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();
3058 }
3059
3060 // Set virtual position
3061 rUIElement.m_aDockedData.m_aPos.X = nRowCol;
3062 rUIElement.m_aDockedData.m_aPos.Y = nDockPosY;
3063 }
3064
3065 return aTrackingRect;
3066}
3067
3068void ToolbarLayoutManager::implts_setTrackingRect( ui::DockingArea eDockingArea, const ::Point& rMousePos, ::tools::Rectangle& rTrackingRect )
3069{
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 );
3076}
3077
3079 ui::DockingArea eDockingArea,
3080 const UIElement& rUIElement )
3081{
3082 SolarMutexClearableGuard aReadLock;
3083 uno::Reference< container::XNameAccess > xPersistentWindowState( m_xPersistentWindowState );
3084 aReadLock.clear();
3085
3086 bool bHorzDockingArea( isHorizontalDockingArea( eDockingArea ));
3087 sal_Int32 nRowCol( bHorzDockingArea ? rUIElement.m_aDockedData.m_aPos.Y : rUIElement.m_aDockedData.m_aPos.X );
3088
3089 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
3090 {
3091 SolarMutexGuard aWriteLock;
3092 for (auto& elem : m_aUIElements)
3093 {
3094 if ((elem.m_aDockedData.m_nDockedArea == eDockingArea)
3095 && (elem.m_aName != rUIElement.m_aName))
3096 {
3097 // Don't change toolbars without a valid docking position!
3098 if (isDefaultPos(elem.m_aDockedData.m_aPos))
3099 continue;
3100
3101 sal_Int32 nWindowRowCol
3102 = bHorzDockingArea ? elem.m_aDockedData.m_aPos.Y : elem.m_aDockedData.m_aPos.X;
3103 if (nWindowRowCol >= nRowCol)
3104 {
3105 if (bHorzDockingArea)
3106 elem.m_aDockedData.m_aPos.Y += 1;
3107 else
3108 elem.m_aDockedData.m_aPos.X += 1;
3109 }
3110 }
3111 }
3112 }
3113 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
3114
3115 // We have to change the persistent window state part
3116 if ( !xPersistentWindowState.is() )
3117 return;
3118
3119 try
3120 {
3121 const uno::Sequence< OUString > aWindowElements = xPersistentWindowState->getElementNames();
3122 for ( OUString const & rWindowElementName : aWindowElements )
3123 {
3124 if ( rUIElement.m_aName != rWindowElementName )
3125 {
3126 try
3127 {
3128 uno::Sequence< beans::PropertyValue > aPropValueSeq;
3129 awt::Point aDockedPos;
3130 ui::DockingArea nDockedArea( ui::DockingArea_DOCKINGAREA_DEFAULT );
3131
3132 xPersistentWindowState->getByName( rWindowElementName ) >>= aPropValueSeq;
3133 for ( beans::PropertyValue const & rProp : std::as_const(aPropValueSeq) )
3134 {
3135 if ( rProp.Name == WINDOWSTATE_PROPERTY_DOCKINGAREA )
3136 rProp.Value >>= nDockedArea;
3137 else if ( rProp.Name == WINDOWSTATE_PROPERTY_DOCKPOS )
3138 rProp.Value >>= aDockedPos;
3139 }
3140
3141 // Don't change toolbars without a valid docking position!
3142 if ( isDefaultPos( aDockedPos ))
3143 continue;
3144
3145 sal_Int32 nWindowRowCol = bHorzDockingArea ? aDockedPos.Y : aDockedPos.X;
3146 if (( nDockedArea == eDockingArea ) && ( nWindowRowCol >= nRowCol ))
3147 {
3148 if ( bHorzDockingArea )
3149 aDockedPos.Y += 1;
3150 else
3151 aDockedPos.X += 1;
3152
3153 uno::Reference< container::XNameReplace > xReplace( xPersistentWindowState, uno::UNO_QUERY );
3154 xReplace->replaceByName( rWindowElementName, css::uno::Any( aPropValueSeq ));
3155 }
3156 }
3157 catch (const uno::Exception&)
3158 {
3159 }
3160 }
3161 }
3162 }
3163 catch (const uno::Exception&)
3164 {
3165 }
3166}
3167
3168// XWindowListener
3169
3170void SAL_CALL ToolbarLayoutManager::windowResized( const awt::WindowEvent& aEvent )
3171{
3172 SolarMutexClearableGuard aWriteLock;
3173 bool bLocked( m_bDockingInProgress );
3174 bool bLayoutInProgress( m_bLayoutInProgress );
3175 aWriteLock.clear();
3176
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;
3183
3184 bool bNotify( false );
3185 uno::Reference< awt::XWindow > xWindow( aEvent.Source, uno::UNO_QUERY );
3186
3187 UIElement aUIElement = implts_findToolbar( aEvent.Source );
3188 if ( aUIElement.m_xUIElement.is() )
3189 {
3190 if ( aUIElement.m_bFloating )
3191 {
3192 uno::Reference< awt::XWindow2 > xWindow2( xWindow, uno::UNO_QUERY );
3193
3194 if( xWindow2.is() )
3195 {
3196 awt::Rectangle aPos = xWindow2->getPosSize();
3197 awt::Size aSize = xWindow2->getOutputSize(); // always use output size for consistency
3198 bool bVisible = xWindow2->isVisible();
3199
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;
3204 }
3205
3206 implts_writeWindowStateData( aUIElement );
3207 }
3208 else
3209 {
3211 bNotify = true;
3212 }
3213 }
3214
3215 if ( bNotify )
3217}
3218
3219void SAL_CALL ToolbarLayoutManager::windowMoved( const awt::WindowEvent& /*aEvent*/ )
3220{
3221}
3222
3223void SAL_CALL ToolbarLayoutManager::windowShown( const lang::EventObject& /*aEvent*/ )
3224{
3225}
3226
3227void SAL_CALL ToolbarLayoutManager::windowHidden( const lang::EventObject& /*aEvent*/ )
3228{
3229}
3230
3231// XDockableWindowListener
3232
3233void SAL_CALL ToolbarLayoutManager::startDocking( const awt::DockingEvent& e )
3234{
3235 bool bWinFound( false );
3236
3237 SolarMutexClearableGuard aReadGuard;
3238 uno::Reference< awt::XWindow2 > xWindow( e.Source, uno::UNO_QUERY );
3239 aReadGuard.clear();
3240
3241 UIElement aUIElement = implts_findToolbar( e.Source );
3242
3243 if ( aUIElement.m_xUIElement.is() && xWindow.is() )
3244 {
3245 bWinFound = true;
3246 uno::Reference< awt::XDockableWindow > xDockWindow( xWindow, uno::UNO_QUERY );
3247 if ( xDockWindow->isFloating() )
3248 {
3249 awt::Rectangle aPos = xWindow->getPosSize();
3250 awt::Size aSize = xWindow->getOutputSize();
3251
3252 aUIElement.m_aFloatingData.m_aPos = awt::Point(aPos.X, aPos.Y);
3253 aUIElement.m_aFloatingData.m_aSize = aSize;
3254
3255 SolarMutexGuard aGuard;
3256
3257 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
3258 if ( pWindow && pWindow->GetType() == WindowType::TOOLBOX )
3259 {
3260 ToolBox* pToolBox = static_cast<ToolBox *>(pWindow.get());
3261 aUIElement.m_aFloatingData.m_nLines = pToolBox->GetFloatingLines();
3263 }
3264 }
3265 }
3266
3268 m_bDockingInProgress = bWinFound;
3269 m_aDockUIElement = aUIElement;
3271}
3272
3273awt::DockingData SAL_CALL ToolbarLayoutManager::docking( const awt::DockingEvent& e )
3274{
3275 constexpr sal_Int32 MAGNETIC_DISTANCE_UNDOCK = 25;
3276 constexpr sal_Int32 MAGNETIC_DISTANCE_DOCK = 20;
3277
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 );
3288
3289 bool bDockingInProgress( m_bDockingInProgress );
3290 aReadLock.clear();
3291
3292 if ( bDockingInProgress )
3293 aDockingData.TrackingRectangle = e.TrackingRectangle;
3294
3295 if ( bDockingInProgress && xDockWindow.is() && xWindow.is() )
3296 {
3297 try
3298 {
3299 SolarMutexGuard aGuard;
3300
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 ));
3307
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 ));
3311
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 ));
3315
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 ));
3319
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 ));
3323
3324 VclPtr<vcl::Window> pContainerWindow( VCLUnoHelper::GetWindow( xContainerWindow ) );
3325 ::Point aMousePos( pContainerWindow->ScreenToOutputPixel( ::Point( e.MousePos.X, e.MousePos.Y )));
3326
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;
3335
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;
3345
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());
3351
3352 if ( eDockingArea != ui::DockingArea(-1) )
3353 {
3354 if ( eDockingArea == ui::DockingArea_DOCKINGAREA_TOP )
3355 {
3356 aUIDockingElement.m_aDockedData.m_nDockedArea = ui::DockingArea_DOCKINGAREA_TOP;
3357 aUIDockingElement.m_bFloating = false;
3358 }
3359 else if ( eDockingArea == ui::DockingArea_DOCKINGAREA_BOTTOM )
3360 {
3361 aUIDockingElement.m_aDockedData.m_nDockedArea = ui::DockingArea_DOCKINGAREA_BOTTOM;
3362 aUIDockingElement.m_bFloating = false;
3363 }
3364 else if ( eDockingArea == ui::DockingArea_DOCKINGAREA_LEFT )
3365 {
3366 aUIDockingElement.m_aDockedData.m_nDockedArea = ui::DockingArea_DOCKINGAREA_LEFT;
3367 aUIDockingElement.m_bFloating = false;
3368 }
3369 else if ( eDockingArea == ui::DockingArea_DOCKINGAREA_RIGHT )
3370 {
3371 aUIDockingElement.m_aDockedData.m_nDockedArea = ui::DockingArea_DOCKINGAREA_RIGHT;
3372 aUIDockingElement.m_bFloating = false;
3373 }
3374
3375 ::Point aOutputPos = pContainerWindow->ScreenToOutputPixel( aTrackingRect.TopLeft() );
3376 aTrackingRect.SetPos( aOutputPos );
3377
3378 ::tools::Rectangle aNewDockingRect( aTrackingRect );
3379
3380 implts_calcDockingPosSize( aUIDockingElement, eDockingOperation, aNewDockingRect, aMousePos );
3381
3382 ::Point aScreenPos = pContainerWindow->OutputToScreenPixel( aNewDockingRect.TopLeft() );
3383 aDockingData.TrackingRectangle = awt::Rectangle( aScreenPos.X(), aScreenPos.Y(),
3384 aNewDockingRect.getOpenWidth(), aNewDockingRect.getOpenHeight() );
3385 }
3386 else if (pToolBox)
3387 {
3388 bool bIsHorizontal = isToolboxHorizontalAligned( pToolBox );
3389 awt::Size aFloatSize = aUIDockingElement.m_aFloatingData.m_aSize;
3390 if ( aFloatSize.Width > 0 && aFloatSize.Height > 0 )
3391 {
3392 aUIDockingElement.m_aFloatingData.m_aPos = AWTPoint(pContainerWindow->ScreenToOutputPixel(VCLPoint(e.MousePos)));
3393 aDockingData.TrackingRectangle.Height = aFloatSize.Height;
3394 aDockingData.TrackingRectangle.Width = aFloatSize.Width;
3395 }
3396 else
3397 {
3398 aFloatSize = AWTSize(pToolBox->CalcWindowSizePixel());
3399 if ( !bIsHorizontal )
3400 {
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;
3406 }
3407
3408 aDockingData.TrackingRectangle.Height = aFloatSize.Height;
3409 aDockingData.TrackingRectangle.Width = aFloatSize.Width;
3410
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 );
3417 }
3418 aDockingData.TrackingRectangle.X = e.MousePos.X;
3419 aDockingData.TrackingRectangle.Y = e.MousePos.Y;
3420 }
3421
3422 aDockingData.bFloating = ( eDockingArea == ui::DockingArea(-1) );
3423
3424 // Write current data to the member docking progress data
3426 m_aDockUIElement.m_bFloating = aDockingData.bFloating;
3427 if ( !aDockingData.bFloating )
3428 {
3429 m_aDockUIElement.m_aDockedData = aUIDockingElement.m_aDockedData;
3430
3431 m_eDockOperation = eDockingOperation;
3432 }
3433 else
3435 }
3436 catch (const uno::Exception&)
3437 {
3438 }
3439 }
3440
3441 return aDockingData;
3442}
3443
3444void SAL_CALL ToolbarLayoutManager::endDocking( const awt::EndDockingEvent& e )
3445{
3446 if (e.bCancelled)
3447 return;
3448
3449 bool bDockingInProgress( false );
3450 bool bStartDockFloated( false );
3451 bool bFloating( false );
3452 UIElement aUIDockingElement;
3453
3454 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
3455 SolarMutexResettableGuard aWriteLock;
3456 bDockingInProgress = m_bDockingInProgress;
3457 aUIDockingElement = m_aDockUIElement;
3458 bFloating = aUIDockingElement.m_bFloating;
3459
3460 UIElement& rUIElement = impl_findToolbar( aUIDockingElement.m_aName );
3461 if ( rUIElement.m_aName == aUIDockingElement.m_aName )
3462 {
3463 if ( aUIDockingElement.m_bFloating )
3464 {
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;
3472 }
3473 else
3474 {
3475 rUIElement.m_aDockedData = aUIDockingElement.m_aDockedData;
3476 rUIElement.m_aFloatingData.m_aSize = aUIDockingElement.m_aFloatingData.m_aSize;
3477
3479 {
3480 // we have to renumber our row/column data to insert a new row/column
3481 implts_renumberRowColumnData(aUIDockingElement.m_aDockedData.m_nDockedArea, aUIDockingElement );
3482 }
3483 }
3484
3485 bStartDockFloated = rUIElement.m_bFloating;
3487 rUIElement.m_bUserActive = true;
3488 }
3489
3490 // reset member for next docking operation
3493 aWriteLock.clear();
3494 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
3495
3496 implts_writeWindowStateData( aUIDockingElement );
3497
3498 if ( bDockingInProgress )
3499 {
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());
3505
3506 if ( pToolBox )
3507 {
3508 if( e.bFloating )
3509 {
3510 if ( aUIDockingElement.m_aFloatingData.m_bIsHorizontal )
3511 pToolBox->SetAlign();
3512 else
3513 pToolBox->SetAlign( WindowAlign::Left );
3514 }
3515 else
3516 {
3517 ::Size aSize;
3518
3519 pToolBox->SetAlign( ImplConvertAlignment( aUIDockingElement.m_aDockedData.m_nDockedArea) );
3520
3521 // Docked toolbars have always one line
3522 aSize = pToolBox->CalcWindowSizePixel( 1 );
3523
3524 // Lock layouting updates as our listener would be called due to SetSizePixel
3525 pToolBox->SetOutputSizePixel( aSize );
3526 }
3527 }
3528 }
3529
3531
3532 aWriteLock.reset();
3533 m_bDockingInProgress = false;
3534 m_bLayoutDirty = !bStartDockFloated || !bFloating;
3535 bool bNotify = m_bLayoutDirty;
3536 aWriteLock.clear();
3537
3538 if ( bNotify )
3540}
3541
3542sal_Bool SAL_CALL ToolbarLayoutManager::prepareToggleFloatingMode( const lang::EventObject& e )
3543{
3544 SolarMutexClearableGuard aReadLock;
3545 bool bDockingInProgress = m_bDockingInProgress;
3546 aReadLock.clear();
3547
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 );
3551
3552 if ( !bWinFound || !xWindow.is() )
3553 return true;
3554
3555 if ( bDockingInProgress )
3556 return true;
3557
3558 uno::Reference< awt::XDockableWindow > xDockWindow( xWindow, uno::UNO_QUERY );
3559 if ( !xDockWindow->isFloating() )
3560 return true;
3561
3562 {
3563 SolarMutexGuard aGuard;
3564 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
3565 if ( pWindow && pWindow->GetType() == WindowType::TOOLBOX )
3566 {
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 );
3572 }
3573 }
3574
3575 UIElement aUIElement = implts_findToolbar( aUIDockingElement.m_aName );
3576 if ( aUIElement.m_aName == aUIDockingElement.m_aName )
3577 implts_setToolbar( aUIDockingElement );
3578
3579 return true;
3580}
3581
3582void SAL_CALL ToolbarLayoutManager::toggleFloatingMode( const lang::EventObject& e )
3583{
3584 UIElement aUIDockingElement;
3585
3586 SolarMutexResettableGuard aReadLock;
3587 bool bDockingInProgress( m_bDockingInProgress );
3588 if ( bDockingInProgress )
3589 aUIDockingElement = m_aDockUIElement;
3590 aReadLock.clear();
3591
3592 vcl::Window* pWindow( nullptr );
3593 ToolBox* pToolBox( nullptr );
3594 uno::Reference< awt::XWindow2 > xWindow;
3595
3596 {
3597 SolarMutexGuard aGuard;
3598 xWindow.set( e.Source, uno::UNO_QUERY );
3599 pWindow = VCLUnoHelper::GetWindow( xWindow );
3600
3601 if ( pWindow && pWindow->GetType() == WindowType::TOOLBOX )
3602 pToolBox = static_cast<ToolBox *>(pWindow);
3603 }
3604
3605 if ( !bDockingInProgress )
3606 {
3607 aUIDockingElement = implts_findToolbar( e.Source );
3608 bool bWinFound = !aUIDockingElement.m_aName.isEmpty();
3609
3610 if ( bWinFound && xWindow.is() )
3611 {
3612 aUIDockingElement.m_bFloating = !aUIDockingElement.m_bFloating;
3613 aUIDockingElement.m_bUserActive = true;
3614
3616 if ( aUIDockingElement.m_bFloating )
3617 {
3618 SolarMutexGuard aGuard;
3619 if ( pToolBox )
3620 {
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 );
3626 }
3627
3628 bool bUndefPos = hasDefaultPosValue( aUIDockingElement.m_aFloatingData.m_aPos );
3629 bool bSetSize = !hasEmptySize( aUIDockingElement.m_aFloatingData.m_aSize );
3630
3631 if ( bUndefPos )
3633
3634 if ( !bSetSize )
3635 {
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());
3640 }
3641
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);
3646 }
3647 else
3648 {
3649 if ( isDefaultPos( aUIDockingElement.m_aDockedData.m_aPos ))
3650 {
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;
3656
3657 {
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();
3663 }
3664
3665 implts_findNextDockingPos(aUIDockingElement.m_aDockedData.m_nDockedArea, aSize, aDockPos, aPixelPos );
3666 aUIDockingElement.m_aDockedData.m_aPos = aDockPos;
3667 }
3668
3669 SolarMutexGuard aGuard;
3670 if ( pToolBox )
3671 {
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 ) );
3677 }
3678 }
3679
3681 implts_setToolbar( aUIDockingElement );
3682 implts_writeWindowStateData( aUIDockingElement );
3685
3686 aReadLock.reset();
3687 LayoutManager* pParentLayouter( m_pParentLayouter );
3688 aReadLock.clear();
3689
3690 if ( pParentLayouter )
3691 pParentLayouter->requestLayout();
3692 }
3693 }
3694 else
3695 {
3696 SolarMutexGuard aGuard;
3697 if ( pToolBox )
3698 {
3699 if ( aUIDockingElement.m_bFloating )
3700 {
3701 if ( aUIDockingElement.m_aFloatingData.m_bIsHorizontal )
3702 pToolBox->SetAlign();
3703 else
3704 pToolBox->SetAlign( WindowAlign::Left );
3705 }
3706 else
3707 pToolBox->SetAlign( ImplConvertAlignment( aUIDockingElement.m_aDockedData.m_nDockedArea) );
3708 }
3709 }
3710}
3711
3712void SAL_CALL ToolbarLayoutManager::closed( const lang::EventObject& e )
3713{
3714 OUString aName;
3715 UIElement aUIElement;
3716
3717 {
3718 SolarMutexGuard aWriteLock;
3719 for (auto& elem : m_aUIElements)
3720 {
3721 uno::Reference<ui::XUIElement> xUIElement(elem.m_xUIElement);
3722 if (xUIElement.is())
3723 {
3724 uno::Reference<uno::XInterface> xIfac(xUIElement->getRealInterface(),
3725 uno::UNO_QUERY);
3726 if (xIfac == e.Source)
3727 {
3728 aName = elem.m_aName;
3729
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;
3735
3736 aUIElement = elem;
3737 break;
3738 }
3739 }
3740 }
3741 }
3742
3743 // destroy element
3744 if ( aName.isEmpty() )
3745 return;
3746
3747 implts_writeWindowStateData( aUIElement );
3749
3750 SolarMutexClearableGuard aReadLock;
3751 bool bLayoutDirty = m_bLayoutDirty;
3752 LayoutManager* pParentLayouter( m_pParentLayouter );
3753 aReadLock.clear();
3754
3755 if ( bLayoutDirty && pParentLayouter )
3756 pParentLayouter->requestLayout();
3757}
3758
3759void SAL_CALL ToolbarLayoutManager::endPopupMode( const awt::EndPopupModeEvent& /*e*/ )
3760{
3761}
3762
3763// XUIConfigurationListener
3764
3765void SAL_CALL ToolbarLayoutManager::elementInserted( const ui::ConfigurationEvent& rEvent )
3766{
3767 UIElement aUIElement = implts_findToolbar( rEvent.ResourceURL );
3768
3769 uno::Reference< ui::XUIElementSettings > xElementSettings( aUIElement.m_xUIElement, uno::UNO_QUERY );
3770 if ( xElementSettings.is() )
3771 {
3772 uno::Reference< beans::XPropertySet > xPropSet( xElementSettings, uno::UNO_QUERY );
3773 if ( xPropSet.is() )
3774 {
3775 if ( rEvent.Source == uno::Reference< uno::XInterface >( m_xDocCfgMgr, uno::UNO_QUERY ))
3776 xPropSet->setPropertyValue( "ConfigurationSource", css::uno::Any( m_xDocCfgMgr ));
3777 }
3778 xElementSettings->updateSettings();
3779 }
3780 else
3781 {
3782 OUString aElementType;
3783 OUString aElementName;
3784 parseResourceURL( rEvent.ResourceURL, aElementType, aElementName );
3785 if ( aElementName.indexOf( "custom_" ) != -1 )
3786 {
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() )
3791 {
3792 OUString aUIName;
3793 uno::Reference< ui::XUIConfigurationManager > xCfgMgr;
3794 uno::Reference< beans::XPropertySet > xPropSet;
3795
3796 try
3797 {
3798 xCfgMgr.set( rEvent.Source, uno::UNO_QUERY );
3799 xPropSet.set( xCfgMgr->getSettings( rEvent.ResourceURL, false ), uno::UNO_QUERY );
3800
3801 if ( xPropSet.is() )
3802 xPropSet->getPropertyValue("UIName") >>= aUIName;
3803 }
3804 catch (const container::NoSuchElementException&)
3805 {
3806 }
3807 catch (const beans::UnknownPropertyException&)
3808 {
3809 }
3810 catch (const lang::WrappedTargetException&)
3811 {
3812 }
3813
3814 {
3815 SolarMutexGuard aGuard;
3816 vcl::Window* pWindow = getWindowFromXUIElement( xUIElement );
3817 if ( pWindow )
3818 pWindow->SetText( aUIName );
3819 }
3820
3821 showToolbar( rEvent.ResourceURL );
3822 }
3823 }
3824 }
3825}
3826
3827void SAL_CALL ToolbarLayoutManager::elementRemoved( const ui::ConfigurationEvent& rEvent )
3828{
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();
3834
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;
3839
3840 bool bNoSettings( false );
3841 OUString aConfigSourcePropName( "ConfigurationSource" );
3842 uno::Reference< uno::XInterface > xElementCfgMgr;
3843 uno::Reference< beans::XPropertySet > xPropSet( xElementSettings, uno::UNO_QUERY );
3844
3845 if ( xPropSet.is() )
3846 xPropSet->getPropertyValue( aConfigSourcePropName ) >>= xElementCfgMgr;
3847
3848 if ( !xElementCfgMgr.is() )
3849 return;
3850
3851 // Check if the same UI configuration manager has changed => check further
3852 if ( rEvent.Source == xElementCfgMgr )
3853 {
3854 // Same UI configuration manager where our element has its settings
3855 if ( rEvent.Source == uno::Reference< uno::XInterface >( xDocCfgMgr, uno::UNO_QUERY ))
3856 {
3857 // document settings removed
3858 if ( xModuleCfgMgr->hasSettings( rEvent.ResourceURL ))
3859 {
3860 xPropSet->setPropertyValue( aConfigSourcePropName, css::uno::Any( xModuleCfgMgr ));
3861 xElementSettings->updateSettings();
3862 return;
3863 }
3864 }
3865
3866 bNoSettings = true;
3867 }
3868
3869 // No settings anymore, element must be destroyed
3870 if ( xContainerWindow.is() && bNoSettings )
3871 destroyToolbar( rEvent.ResourceURL );
3872}
3873
3874void SAL_CALL ToolbarLayoutManager::elementReplaced( const ui::ConfigurationEvent& rEvent )
3875{
3876 UIElement aUIElement = implts_findToolbar( rEvent.ResourceURL );
3877
3878 uno::Reference< ui::XUIElementSettings > xElementSettings( aUIElement.m_xUIElement, uno::UNO_QUERY );
3879 if ( !xElementSettings.is() )
3880 return;
3881
3882 uno::Reference< uno::XInterface > xElementCfgMgr;
3883 uno::Reference< beans::XPropertySet > xPropSet( xElementSettings, uno::UNO_QUERY );
3884
3885 if ( xPropSet.is() )
3886 xPropSet->getPropertyValue( "ConfigurationSource" ) >>= xElementCfgMgr;
3887
3888 if ( !xElementCfgMgr.is() )
3889 return;
3890
3891 // Check if the same UI configuration manager has changed => update settings
3892 if ( rEvent.Source != xElementCfgMgr )
3893 return;
3894
3895 xElementSettings->updateSettings();
3896
3897 SolarMutexClearableGuard aWriteLock;
3898 bool bNotify = !aUIElement.m_bFloating;
3899 m_bLayoutDirty = bNotify;
3900 LayoutManager* pParentLayouter( m_pParentLayouter );
3901 aWriteLock.clear();
3902
3903 if ( bNotify && pParentLayouter )
3904 pParentLayouter->requestLayout();
3905}
3906
3908{
3910
3911 for (auto& elem : m_aUIElements)
3912 {
3913 uno::Reference< ui::XUIElementSettings > xElementSettings(elem.m_xUIElement, uno::UNO_QUERY);
3914 if (!xElementSettings.is())
3915 continue;
3916 xElementSettings->updateSettings();
3917 }
3918}
3919
3920
3921uno::Reference< ui::XUIElement > ToolbarLayoutManager::getToolbar( std::u16string_view aName )
3922{
3924}
3925
3926uno::Sequence< uno::Reference< ui::XUIElement > > ToolbarLayoutManager::getToolbars()
3927{
3928 uno::Sequence< uno::Reference< ui::XUIElement > > aSeq;
3929
3931 if ( !m_aUIElements.empty() )
3932 {
3933 sal_uInt32 nCount(0);
3934 for (auto const& elem : m_aUIElements)
3935 {
3936 if ( elem.m_xUIElement.is() )
3937 {
3938 ++nCount;
3939 aSeq.realloc( nCount );
3940 aSeq.getArray()[nCount-1] = elem.m_xUIElement;
3941 }
3942 }
3943 }
3944
3945 return aSeq;
3946}
3947
3948bool ToolbarLayoutManager::floatToolbar( std::u16string_view rResourceURL )
3949{
3950 UIElement aUIElement = implts_findToolbar( rResourceURL );
3951 if ( !aUIElement.m_xUIElement.is() )
3952 return false;
3953
3954 try
3955 {
3956 uno::Reference< awt::XDockableWindow > xDockWindow( aUIElement.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
3957 if ( xDockWindow.is() && !xDockWindow->isFloating() )
3958 {
3959 aUIElement.m_bFloating = true;
3960 implts_writeWindowStateData( aUIElement );
3961 xDockWindow->setFloatingMode( true );
3962
3964 implts_setToolbar( aUIElement );
3965 return true;
3966 }
3967 }
3968 catch (const lang::DisposedException&)
3969 {
3970 }
3971
3972 return false;
3973}
3974
3975bool ToolbarLayoutManager::lockToolbar( std::u16string_view rResourceURL )
3976{
3977 UIElement aUIElement = implts_findToolbar( rResourceURL );
3978 if ( !aUIElement.m_xUIElement.is() )
3979 return false;
3980
3981 try
3982 {
3983 uno::Reference< awt::XDockableWindow > xDockWindow( aUIElement.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
3984 if ( xDockWindow.is() && !xDockWindow->isFloating() && !xDockWindow->isLocked() )
3985 {
3986 aUIElement.m_aDockedData.m_bLocked = true;
3987 implts_writeWindowStateData( aUIElement );
3988 xDockWindow->lock();
3989
3991 implts_setToolbar( aUIElement );
3992 return true;
3993 }
3994 }
3995 catch (const lang::DisposedException&)
3996 {
3997 }
3998
3999 return false;
4000}
4001
4002bool ToolbarLayoutManager::unlockToolbar( std::u16string_view rResourceURL )
4003{
4004 UIElement aUIElement = implts_findToolbar( rResourceURL );
4005 if ( !aUIElement.m_xUIElement.is() )
4006 return false;
4007
4008 try
4009 {
4010 uno::Reference< awt::XDockableWindow > xDockWindow( aUIElement.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
4011 if ( xDockWindow.is() && !xDockWindow->isFloating() && xDockWindow->isLocked() )
4012 {
4013 aUIElement.m_aDockedData.m_bLocked = false;
4014 implts_writeWindowStateData( aUIElement );
4015 xDockWindow->unlock();
4016
4018 implts_setToolbar( aUIElement );
4019 return true;
4020 }
4021 }
4022 catch (const lang::DisposedException&)
4023 {
4024 }
4025
4026 return false;
4027}
4028
4029bool ToolbarLayoutManager::isToolbarVisible( std::u16string_view rResourceURL )
4030{
4031 uno::Reference< awt::XWindow2 > xWindow2( implts_getXWindow( rResourceURL ), uno::UNO_QUERY );
4032 return ( xWindow2.is() && xWindow2->isVisible() );
4033}
4034
4035bool ToolbarLayoutManager::isToolbarFloating( std::u16string_view rResourceURL )
4036{
4037 uno::Reference< awt::XDockableWindow > xDockWindow( implts_getXWindow( rResourceURL ), uno::UNO_QUERY );
4038 return ( xDockWindow.is() && xDockWindow->isFloating() );
4039}
4040
4041bool ToolbarLayoutManager::isToolbarDocked( std::u16string_view rResourceURL )
4042{
4043 return !isToolbarFloating( rResourceURL );
4044}
4045
4046bool ToolbarLayoutManager::isToolbarLocked( std::u16string_view rResourceURL )
4047{
4048 uno::Reference< awt::XDockableWindow > xDockWindow( implts_getXWindow( rResourceURL ), uno::UNO_QUERY );
4049 return ( xDockWindow.is() && xDockWindow->isLocked() );
4050}
4051
4052awt::Size ToolbarLayoutManager::getToolbarSize( std::u16string_view rResourceURL )
4053{
4054 vcl::Window* pWindow = implts_getWindow( rResourceURL );
4055
4056 SolarMutexGuard aGuard;
4057 if ( pWindow )
4058 {
4059 ::Size aSize = pWindow->GetSizePixel();
4060 awt::Size aWinSize;
4061 aWinSize.Width = aSize.Width();
4062 aWinSize.Height = aSize.Height();
4063 return aWinSize;
4064 }
4065
4066 return awt::Size();
4067}
4068
4069awt::Point ToolbarLayoutManager::getToolbarPos( std::u16string_view rResourceURL )
4070{
4071 awt::Point aPos;
4072 UIElement aUIElement = implts_findToolbar( rResourceURL );
4073
4074 uno::Reference< awt::XWindow > xWindow( implts_getXWindow( rResourceURL ));
4075 if ( xWindow.is() )
4076 {
4077 if ( aUIElement.m_bFloating )
4078 {
4079 awt::Rectangle aRect = xWindow->getPosSize();
4080 aPos.X = aRect.X;
4081 aPos.Y = aRect.Y;
4082 }
4083 else
4084 aPos = aUIElement.m_aDockedData.m_aPos;
4085 }
4086
4087 return aPos;
4088}
4089
4090void ToolbarLayoutManager::setToolbarSize( std::u16string_view rResourceURL, const awt::Size& aSize )
4091{
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 );
4095
4096 if ( xWindow.is() && xDockWindow.is() && xDockWindow->isFloating() )
4097 {
4098 xWindow->setOutputSize( aSize );
4099 aUIElement.m_aFloatingData.m_aSize = aSize;
4100 implts_setToolbar( aUIElement );
4101 implts_writeWindowStateData( aUIElement );
4103 }
4104}
4105
4106void ToolbarLayoutManager::setToolbarPos( std::u16string_view rResourceURL, const awt::Point& aPos )
4107{
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 );
4111
4112 if ( xWindow.is() && xDockWindow.is() && xDockWindow->isFloating() )
4113 {
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 );
4119 }
4120}
4121
4122void ToolbarLayoutManager::setToolbarPosSize( std::u16string_view rResourceURL, const awt::Point& aPos, const awt::Size& aSize )
4123{
4124 setToolbarPos( rResourceURL, aPos );
4125 setToolbarSize( rResourceURL, aSize );
4126}
4127
4128} // namespace framework
4129
4130/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
AnyEventRef aEvent
const vcl::I18nHelper & GetUILocaleI18nHelper() const
static const AllSettings & GetSettings()
SystemWindow * GetFloatingWindow(const vcl::Window *pWin)
void SetOutputSizePixel(const Size &rNewSize) override
Point GetPosPixel() const override
void SetFloatStyle(WinBits nWinStyle)
Size GetOutputSizePixel() const
WinBits GetFloatStyle() const
constexpr tools::Long Y() const
void setX(tools::Long nX)
void setY(tools::Long nY)
constexpr tools::Long X() const
bool IsEmpty() const
constexpr tools::Long Height() const
void setWidth(tools::Long nWidth)
void setHeight(tools::Long nHeight)
constexpr tools::Long Width() const
bool LookupDisabled(const OUString &aCommandURL) const
bool UpdatePositionData()
OUString GetItemCommand(ToolBoxItemId nItemId) const
ToolBoxMenuType GetMenuType() const
Size CalcWindowSizePixel()
ToolBoxItemId GetCurItemId() const
void SetLineCount(ImplToolItems::size_type nNewLines)
void SetButtonType(ButtonType eNewType)
Size CalcFloatingWindowSizePixel()
ImplToolItems::size_type GetFloatingLines() const
void SetMenuType(ToolBoxMenuType aType=ToolBoxMenuType::Customize)
void SetAlign(WindowAlign eNewAlign=WindowAlign::Top)
static vcl::Window * GetWindow(const css::uno::Reference< css::awt::XWindow > &rxWindow)
reference_type * get() const
VclEventId GetId() const
static bool readWindowStateData(const OUString &rName, UIElement &rElementData, const css::uno::Reference< css::container::XNameAccess > &rPersistentWindowState, std::unique_ptr< GlobalSettings > &rGlobalSettings, bool &bInGlobalSettings, const css::uno::Reference< css::uno::XComponentContext > &rComponentContext)
Reading of settings - shared with ToolbarLayoutManager.
virtual sal_Bool SAL_CALL prepareToggleFloatingMode(const css::lang::EventObject &e) override
void setFloatingToolbarsVisibility(bool bVisible)
css::uno::Reference< css::awt::XWindow > implts_getXWindow(std::u16string_view aName)
virtual void SAL_CALL elementRemoved(const css::ui::ConfigurationEvent &Event) override
css::uno::Reference< css::awt::XWindow2 > m_xContainerWindow
css::uno::Reference< css::ui::XUIConfigurationManager > m_xDocCfgMgr
virtual void SAL_CALL endDocking(const css::awt::EndDockingEvent &e) override
vcl::Window * implts_getWindow(std::u16string_view aName)
css::uno::Reference< css::uno::XComponentContext > m_xContext
ToolbarLayoutManager(css::uno::Reference< css::uno::XComponentContext > xContext, css::uno::Reference< css::ui::XUIElementFactory > xUIElementFactory, LayoutManager *pParentLayouter)
css::uno::Reference< css::ui::XUIElement > getToolbar(std::u16string_view aName)
::tools::Rectangle implts_calcHotZoneRect(const ::tools::Rectangle &rRect, sal_Int32 nHotZoneOffset)
virtual void SAL_CALL toggleFloatingMode(const css::lang::EventObject &e) override
virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type &rType) override
void setDockingAreaOffsets(const ::tools::Rectangle &rOffsets)
::tools::Rectangle implts_determineFrontDockingRect(css::ui::DockingArea eDockingArea, sal_Int32 nRowCol, const ::tools::Rectangle &rDockedElementRect, std::u16string_view rMovedElementName, const ::tools::Rectangle &rMovedElementRect)
void implts_setDockingAreaWindowSizes(const css::awt::Rectangle &rBorderSpace)
void setParentWindow(const css::uno::Reference< css::awt::XVclWindowPeer > &xParentWindow)
void implts_setToolbarCreation(bool bStart=true)
::tools::Rectangle implts_getWindowRectFromRowColumn(css::ui::DockingArea DockingArea, const SingleRowColumnWindowData &rRowColumnWindowData, const ::Point &rMousePos, std::u16string_view rExcludeElementName)
bool floatToolbar(std::u16string_view rResourceURL)
UIElement & impl_findToolbar(std::u16string_view aName)
UIElement implts_findToolbar(std::u16string_view aName)
css::uno::Reference< css::frame::XFrame > m_xFrame
css::uno::Reference< css::awt::XWindow > m_xDockAreaWindows[DOCKINGAREAS_COUNT]
virtual void SAL_CALL elementReplaced(const css::ui::ConfigurationEvent &Event) override
OUString implts_generateGenericAddonToolbarTitle(sal_Int32 nNumber) const
void implts_setTrackingRect(css::ui::DockingArea eDockingArea, const ::Point &rMousePos, ::tools::Rectangle &rTrackingRect)
virtual void SAL_CALL disposing(const css::lang::EventObject &aEvent) override
void childWindowEvent(VclSimpleEvent const *pEvent)
std::unique_ptr< AddonsOptions > m_pAddonOptions
std::unique_ptr< GlobalSettings > m_pGlobalSettings
void refreshToolbarsVisibility(bool bAutomaticToolbars)
::tools::Rectangle implts_calcTrackingAndElementRect(css::ui::DockingArea eDockingArea, sal_Int32 nRowCol, UIElement &rUIElement, const ::tools::Rectangle &rTrackingRect, const ::tools::Rectangle &rRowColumnRect, const ::Size &rContainerWinSize)
css::uno::Reference< css::ui::XUIElementFactory > m_xUIElementFactoryManager
bool showToolbar(std::u16string_view rResourceURL)
void setToolbarSize(std::u16string_view rResourceURL, const css::awt::Size &aSize)
void implts_renumberRowColumnData(css::ui::DockingArea eDockingArea, const UIElement &rUIElement)
virtual void SAL_CALL closed(const css::lang::EventObject &e) override
bool isToolbarVisible(std::u16string_view rResourceURL)
css::uno::Reference< css::ui::XUIConfigurationManager > m_xModuleCfgMgr
void setToolbarPos(std::u16string_view rResourceURL, const css::awt::Point &aPos)
virtual void SAL_CALL elementInserted(const css::ui::ConfigurationEvent &Event) override
bool isToolbarFloating(std::u16string_view rResourceURL)
bool lockToolbar(std::u16string_view rResourceURL)
void implts_setToolbar(const UIElement &rUIElement)
bool implts_insertToolbar(const UIElement &rUIElement)
void implts_writeWindowStateData(const UIElement &rElementData)
virtual void SAL_CALL endPopupMode(const css::awt::EndPopupModeEvent &e) override
void implts_calcDockingPosSize(UIElement &aUIElement, DockingOperation &eDockOperation, ::tools::Rectangle &rTrackingRect, const Point &rMousePos)
bool unlockToolbar(std::u16string_view rResourceURL)
void attach(const css::uno::Reference< css::frame::XFrame > &xFrame, const css::uno::Reference< css::ui::XUIConfigurationManager > &xModuleCfgMgr, const css::uno::Reference< css::ui::XUIConfigurationManager > &xDocCfgMgr, const css::uno::Reference< css::container::XNameAccess > &xPersistentWindowState)
void implts_setElementData(UIElement &rUIElement, const css::uno::Reference< css::awt::XDockableWindow > &rDockWindow)
virtual css::awt::DockingData SAL_CALL docking(const css::awt::DockingEvent &e) override
void implts_setLayoutInProgress(bool bInProgress=true)
css::awt::Size getToolbarSize(std::u16string_view rResourceURL)
void implts_getDockingAreaElementInfos(css::ui::DockingArea DockingArea, std::vector< SingleRowColumnWindowData > &rRowColumnsWindowData)
css::awt::Point getToolbarPos(std::u16string_view rResourceURL)
virtual void SAL_CALL windowShown(const css::lang::EventObject &aEvent) override
virtual void SAL_CALL windowMoved(const css::awt::WindowEvent &aEvent) override
std::vector< UIElement > UIElementVector
bool dockToolbar(std::u16string_view rResourceURL, css::ui::DockingArea eDockingArea, const css::awt::Point &aPos)
void setToolbarPosSize(std::u16string_view rResourceURL, const css::awt::Point &aPos, const css::awt::Size &aSize)
void doLayout(const ::Size &aContainerSize)
void implts_getUIElementVectorCopy(UIElementVector &rCopy)
bool hideToolbar(std::u16string_view rResourceURL)
virtual void SAL_CALL startDocking(const css::awt::DockingEvent &e) override
bool createToolbar(const OUString &rResourceURL)
bool isToolbarLocked(std::u16string_view rResourceURL)
void implts_findNextDockingPos(css::ui::DockingArea DockingArea, const ::Size &aUIElementSize, css::awt::Point &rVirtualPos, ::Point &rPixelPos)
bool requestToolbar(const OUString &rResourceURL)
virtual void SAL_CALL windowHidden(const css::lang::EventObject &aEvent) override
void implts_createCustomToolBar(const OUString &aTbxResName, const OUString &aTitle)
bool destroyToolbar(std::u16string_view rResourceURL)
bool implts_readWindowStateData(const OUString &aName, UIElement &rElementData)
css::uno::Reference< css::container::XNameAccess > m_xPersistentWindowState
void implts_calcWindowPosSizeOnSingleRowColumn(sal_Int32 nDockingArea, sal_Int32 nOffset, SingleRowColumnWindowData &rRowColumnWindowData, const ::Size &rContainerSize)
void implts_getDockingAreaElementInfoOnSingleRowCol(css::ui::DockingArea, sal_Int32 nRowCol, SingleRowColumnWindowData &rRowColumnWindowData)
void setDockingArea(const css::awt::Rectangle &rDockingArea)
css::uno::Sequence< css::uno::Reference< css::ui::XUIElement > > getToolbars()
DockingOperation implts_determineDockingOperation(css::ui::DockingArea DockingArea, const ::tools::Rectangle &rRowColRect, const Point &rMousePos)
virtual void SAL_CALL release() noexcept override
virtual void SAL_CALL windowResized(const css::awt::WindowEvent &aEvent) override
bool isToolbarDocked(std::u16string_view rResourceURL)
virtual void SAL_CALL acquire() noexcept override
bool Contains(const Point &rPOINT) const
constexpr void SetLeft(tools::Long v)
constexpr void SetTop(tools::Long v)
constexpr tools::Long Top() const
void SetSize(const Size &)
constexpr Point TopLeft() const
tools::Long getOpenHeight() const
void SetPos(const Point &rPoint)
void setWidth(tools::Long n)
constexpr void SetRight(tools::Long v)
constexpr Size GetSize() const
void Move(tools::Long nHorzMoveDelta, tools::Long nVertMoveDelta)
constexpr tools::Long Right() const
tools::Long AdjustTop(tools::Long nVertMoveDelta)
tools::Long AdjustRight(tools::Long nHorzMoveDelta)
constexpr void SetBottom(tools::Long v)
constexpr Point BottomRight() const
constexpr tools::Long GetHeight() const
tools::Long AdjustBottom(tools::Long nVertMoveDelta)
tools::Long AdjustLeft(tools::Long nHorzMoveDelta)
void setHeight(tools::Long n)
tools::Long getOpenWidth() const
constexpr tools::Long Left() const
constexpr tools::Long Bottom() const
constexpr bool IsEmpty() const
OUString GetNum(tools::Long nNumber, sal_uInt16 nDecimals, bool bUseThousandSep=true, bool bTrailingZeros=true) const
Point OutputToScreenPixel(const Point &rPos) const
void SetStyle(WinBits nStyle)
WindowType GetType() const
static DockingManager * GetDockingManager()
virtual Point GetPosPixel() const
WinBits GetStyle() const
void Show(bool bVisible=true, ShowFlags nFlags=ShowFlags::NONE)
virtual Size GetSizePixel() const
Size GetOutputSizePixel() const
virtual void SetText(const OUString &rStr)
virtual OUString GetText() const
Point ScreenToOutputPixel(const Point &rPos) const
css::awt::Size AWTSize(const Size &rVCLSize)
css::awt::Point AWTPoint(const ::Point &rVCLPoint)
inline ::Point VCLPoint(const css::awt::Point &rAWTPoint)
int nCount
float u
OUString FwkResId(TranslateId aId)
Definition: fwkresid.cxx:22
css::uno::Reference< css::uno::XComponentContext > m_xContext
constexpr OUStringLiteral UIRESOURCETYPE_TOOLBAR
Definition: helpers.hxx:34
sal_Int32 nIndex
OUString aName
uno_Any a
Sequence< sal_Int8 > aSeq
#define SAL_WARN(area, stream)
css::beans::PropertyValue makePropertyValue(const OUString &rName, T &&rValue)
css::awt::Rectangle putRectangleValueToAWT(const ::tools::Rectangle &rRect)
Definition: helpers.cxx:211
WindowAlign ImplConvertAlignment(ui::DockingArea aAlignment)
Definition: helpers.cxx:178
void parseResourceURL(std::u16string_view aResourceURL, OUString &aElementType, OUString &aElementName)
Definition: helpers.cxx:201
OUString retrieveToolbarNameFromHelpURL(vcl::Window *pWindow)
Definition: helpers.cxx:83
bool isHorizontalDockingArea(const ui::DockingArea &nDockingArea)
Definition: helpers.cxx:72
ToolBox * getToolboxPtr(vcl::Window *pWindow)
Definition: helpers.cxx:103
uno::Reference< awt::XVclWindowPeer > createToolkitWindow(const uno::Reference< uno::XComponentContext > &rxContext, const uno::Reference< awt::XVclWindowPeer > &rParent, const char *pService)
Definition: helpers.cxx:157
::tools::Rectangle putAWTToRectangle(const css::awt::Rectangle &rRect)
Definition: helpers.cxx:222
bool isToolboxHorizontalAligned(ToolBox const *pToolBox)
Definition: helpers.cxx:65
vcl::Window * getWindowFromXUIElement(const uno::Reference< ui::XUIElement > &xUIElement)
Definition: helpers.cxx:111
uno::Reference< frame::XModel > impl_getModelFromFrame(const uno::Reference< frame::XFrame > &rFrame)
Definition: helpers.cxx:242
bool implts_isPreviewModel(const uno::Reference< frame::XModel > &xModel)
Definition: helpers.cxx:256
bool hasEmptySize(const css::awt::Size &rSize)
Definition: helpers.cxx:43
bool isReverseOrderDockingArea(const sal_Int32 nDockArea)
Definition: helpers.cxx:58
bool lcl_checkUIElement(const uno::Reference< ui::XUIElement > &xUIElement, awt::Rectangle &_rPosSize, uno::Reference< awt::XWindow > &_xWindow)
Definition: helpers.cxx:137
bool isDefaultPos(const css::awt::Point &rPos)
Definition: helpers.cxx:53
bool hasDefaultPosValue(const css::awt::Point &rPos)
Definition: helpers.cxx:48
int i
constexpr bool starts_with(std::basic_string_view< charT, traits > sv, std::basic_string_view< charT, traits > x) noexcept
long Long
sal_Int16 nId
const wchar_t *typedef int(__stdcall *DllNativeUnregProc)(int
css::ui::DockingArea m_nDockedArea
Definition: uielement.hxx:41
css::awt::Point m_aPos
Definition: uielement.hxx:40
ToolBox::ImplToolItems::size_type m_nLines
Definition: uielement.hxx:53
css::awt::Size m_aSize
Definition: uielement.hxx:52
css::awt::Point m_aPos
Definition: uielement.hxx:51
std::vector< css::uno::Reference< css::awt::XWindow > > aRowColumnWindows
ButtonType m_nStyle
Definition: uielement.hxx:97
FloatingData m_aFloatingData
Definition: uielement.hxx:99
DockedData m_aDockedData
Definition: uielement.hxx:98
css::uno::Reference< css::ui::XUIElement > m_xUIElement
Definition: uielement.hxx:89
Reference< XFrame > xFrame
Reference< XModel > xModel
OUString aUIName
bool bVisible
OUString aCommand
ToolBoxMenuType
#define SAL_MAX_INT32
unsigned char sal_Bool
constexpr OUStringLiteral WINDOWSTATE_PROPERTY_VISIBLE
constexpr OUStringLiteral WINDOWSTATE_PROPERTY_DOCKINGAREA
constexpr OUStringLiteral WINDOWSTATE_PROPERTY_POS
constexpr OUStringLiteral WINDOWSTATE_PROPERTY_LOCKED
constexpr OUStringLiteral WINDOWSTATE_PROPERTY_STYLE
constexpr OUStringLiteral WINDOWSTATE_PROPERTY_DOCKPOS
constexpr OUStringLiteral WINDOWSTATE_PROPERTY_DOCKED
constexpr OUStringLiteral WINDOWSTATE_PROPERTY_SIZE
constexpr OUStringLiteral WINDOWSTATE_PROPERTY_UINAME
WinBits const WB_CLOSEABLE