bump product version to 4.1.6.2
[LibreOffice.git] / framework / source / layoutmanager / toolbarlayoutmanager.cxx
blob1bb03d116fc505bfc140c126d9080d405e6235eb
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <toolbarlayoutmanager.hxx>
21 #include <uielement/addonstoolbarwrapper.hxx>
22 #include <helpers.hxx>
23 #include <services.h>
24 #include <services/layoutmanager.hxx>
25 #include <classes/resource.hrc>
26 #include <classes/fwkresid.hxx>
27 #include <uiconfiguration/windowstateconfiguration.hxx>
29 #include <com/sun/star/awt/PosSize.hpp>
30 #include <com/sun/star/awt/Toolkit.hpp>
31 #include <com/sun/star/beans/XPropertySet.hpp>
32 #include <com/sun/star/ui/UIElementType.hpp>
33 #include <com/sun/star/container/XNameReplace.hpp>
34 #include <com/sun/star/container/XNameContainer.hpp>
35 #include <com/sun/star/ui/XUIElementSettings.hpp>
36 #include <com/sun/star/ui/XUIFunctionListener.hpp>
38 #include <unotools/cmdoptions.hxx>
39 #include <toolkit/unohlp.hxx>
40 #include <toolkit/helper/convert.hxx>
41 #include <toolkit/awt/vclxwindow.hxx>
42 #include <vcl/i18nhelp.hxx>
43 #include <vcl/dockingarea.hxx>
44 #include <boost/bind.hpp>
46 using namespace ::com::sun::star;
48 namespace framework
51 ToolbarLayoutManager::ToolbarLayoutManager(
52 const uno::Reference< uno::XComponentContext >& rxContext,
53 const uno::Reference< ui::XUIElementFactory >& xUIElementFactory,
54 ILayoutNotifications* pParentLayouter )
55 : ThreadHelpBase( &Application::GetSolarMutex() ),
56 m_xContext( rxContext),
57 m_xUIElementFactoryManager( xUIElementFactory ),
58 m_pParentLayouter( pParentLayouter ),
59 m_eDockOperation( DOCKOP_ON_COLROW ),
60 m_ePreviewDetection( PREVIEWFRAME_UNKNOWN ),
61 m_pAddonOptions( 0 ),
62 m_pGlobalSettings( 0 ),
63 m_bComponentAttached( false ),
64 m_bLayoutDirty( false ),
65 m_bStoreWindowState( false ),
66 m_bGlobalSettings( false ),
67 m_bDockingInProgress( false ),
68 m_bVisible( true ),
69 m_bLayoutInProgress( false ),
70 m_bToolbarCreation( false ),
71 m_aFullAddonTbxPrefix( "private:resource/toolbar/addon_" ),
72 m_aCustomTbxPrefix( "custom_" ),
73 m_aCustomizeCmd( "ConfigureDialog" ),
74 m_aToolbarTypeString( UIRESOURCETYPE_TOOLBAR )
76 // initialize rectangles to zero values
77 setZeroRectangle( m_aDockingAreaOffsets );
78 setZeroRectangle( m_aDockingArea );
80 // create toolkit object
81 m_xToolkit = awt::Toolkit::create( m_xContext );
84 ToolbarLayoutManager::~ToolbarLayoutManager()
86 delete m_pGlobalSettings;
87 delete m_pAddonOptions;
90 //---------------------------------------------------------------------------------------------------------
91 // XInterface
92 //---------------------------------------------------------------------------------------------------------
93 void SAL_CALL ToolbarLayoutManager::acquire() throw()
95 OWeakObject::acquire();
98 void SAL_CALL ToolbarLayoutManager::release() throw()
100 OWeakObject::release();
103 uno::Any SAL_CALL ToolbarLayoutManager::queryInterface( const uno::Type & rType ) throw( uno::RuntimeException )
105 uno::Any a = ::cppu::queryInterface( rType,
106 (static_cast< awt::XDockableWindowListener* >(this)),
107 (static_cast< ui::XUIConfigurationListener* >(this)),
108 (static_cast< awt::XWindowListener* >(this)));
110 if ( a.hasValue() )
111 return a;
113 return OWeakObject::queryInterface( rType );
116 void SAL_CALL ToolbarLayoutManager::disposing( const lang::EventObject& aEvent ) throw( uno::RuntimeException )
118 if ( aEvent.Source == m_xFrame )
120 // Reset all internal references
121 reset();
122 implts_destroyDockingAreaWindows();
126 awt::Rectangle ToolbarLayoutManager::getDockingArea()
128 WriteGuard aWriteLock( m_aLock );
129 Rectangle aNewDockingArea( m_aDockingArea );
130 aWriteLock.unlock();
132 if ( isLayoutDirty() )
133 aNewDockingArea = implts_calcDockingArea();
135 aWriteLock.lock();
136 m_aDockingArea = aNewDockingArea;
137 aWriteLock.unlock();
139 return putRectangleValueToAWT(aNewDockingArea);
142 void ToolbarLayoutManager::setDockingArea( const awt::Rectangle& rDockingArea )
144 WriteGuard aWriteLock( m_aLock );
145 m_aDockingArea = putAWTToRectangle( rDockingArea );
146 m_bLayoutDirty = true;
147 aWriteLock.unlock();
150 void ToolbarLayoutManager::implts_setDockingAreaWindowSizes( const awt::Rectangle& rBorderSpace )
152 ReadGuard aReadLock( m_aLock );
153 Rectangle aDockOffsets = m_aDockingAreaOffsets;
154 uno::Reference< awt::XWindow2 > xContainerWindow( m_xContainerWindow );
155 uno::Reference< awt::XWindow > xTopDockAreaWindow( m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_TOP] );
156 uno::Reference< awt::XWindow > xBottomDockAreaWindow( m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_BOTTOM] );
157 uno::Reference< awt::XWindow > xLeftDockAreaWindow( m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_LEFT] );
158 uno::Reference< awt::XWindow > xRightDockAreaWindow( m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_RIGHT] );
159 aReadLock.unlock();
161 uno::Reference< awt::XDevice > xDevice( xContainerWindow, uno::UNO_QUERY );
163 // Convert relativ size to output size.
164 awt::Rectangle aRectangle = xContainerWindow->getPosSize();
165 awt::DeviceInfo aInfo = xDevice->getInfo();
166 awt::Size aContainerClientSize = awt::Size( aRectangle.Width - aInfo.LeftInset - aInfo.RightInset ,
167 aRectangle.Height - aInfo.TopInset - aInfo.BottomInset );
168 long aStatusBarHeight = aDockOffsets.GetHeight();
170 sal_Int32 nLeftRightDockingAreaHeight( aContainerClientSize.Height );
171 if ( rBorderSpace.Y >= 0 )
173 // Top docking area window
174 xTopDockAreaWindow->setPosSize( 0, 0, aContainerClientSize.Width, rBorderSpace.Y, awt::PosSize::POSSIZE );
175 xTopDockAreaWindow->setVisible( sal_True );
176 nLeftRightDockingAreaHeight -= rBorderSpace.Y;
179 if ( rBorderSpace.Height >= 0 )
181 // Bottom docking area window
182 sal_Int32 nBottomPos = std::max( sal_Int32( aContainerClientSize.Height - rBorderSpace.Height - aStatusBarHeight + 1 ), sal_Int32( 0 ));
183 sal_Int32 nHeight = ( nBottomPos == 0 ) ? 0 : rBorderSpace.Height;
185 xBottomDockAreaWindow->setPosSize( 0, nBottomPos, aContainerClientSize.Width, nHeight, awt::PosSize::POSSIZE );
186 xBottomDockAreaWindow->setVisible( sal_True );
187 nLeftRightDockingAreaHeight -= nHeight - 1;
190 nLeftRightDockingAreaHeight -= aStatusBarHeight;
191 if ( rBorderSpace.X >= 0 || nLeftRightDockingAreaHeight > 0 )
193 // Left docking area window
194 // We also have to change our right docking area window if the top or bottom area has changed. They have a higher priority!
195 sal_Int32 nHeight = std::max( sal_Int32( 0 ), sal_Int32( nLeftRightDockingAreaHeight ));
197 xLeftDockAreaWindow->setPosSize( 0, rBorderSpace.Y, rBorderSpace.X, nHeight, awt::PosSize::POSSIZE );
198 xLeftDockAreaWindow->setVisible( sal_True );
200 if ( rBorderSpace.Width >= 0 || nLeftRightDockingAreaHeight > 0 )
202 // Right docking area window
203 // We also have to change our right docking area window if the top or bottom area has changed. They have a higher priority!
204 sal_Int32 nLeftPos = std::max( sal_Int32( 0 ), sal_Int32( aContainerClientSize.Width - rBorderSpace.Width ));
205 sal_Int32 nHeight = std::max( sal_Int32( 0 ), sal_Int32( nLeftRightDockingAreaHeight ));
206 sal_Int32 nWidth = ( nLeftPos == 0 ) ? 0 : rBorderSpace.Width;
208 xRightDockAreaWindow->setPosSize( nLeftPos, rBorderSpace.Y, nWidth, nHeight, awt::PosSize::POSSIZE );
209 xRightDockAreaWindow->setVisible( sal_True );
213 bool ToolbarLayoutManager::isLayoutDirty()
215 return m_bLayoutDirty;
218 void ToolbarLayoutManager::doLayout(const ::Size& aContainerSize)
220 WriteGuard aWriteLock( m_aLock );
221 bool bLayoutInProgress( m_bLayoutInProgress );
222 m_bLayoutInProgress = true;
223 awt::Rectangle aDockingArea = putRectangleValueToAWT( m_aDockingArea );
224 aWriteLock.unlock();
226 if ( bLayoutInProgress )
227 return;
229 // Retrieve row/column dependent data from all docked user-interface elements
230 for ( sal_Int32 i = 0; i < DOCKINGAREAS_COUNT; i++ )
232 bool bReverse( isReverseOrderDockingArea( i ));
233 std::vector< SingleRowColumnWindowData > aRowColumnsWindowData;
235 implts_getDockingAreaElementInfos( (ui::DockingArea)i, aRowColumnsWindowData );
237 sal_Int32 nOffset( 0 );
238 const sal_uInt32 nCount = aRowColumnsWindowData.size();
239 for ( sal_uInt32 j = 0; j < nCount; ++j )
241 sal_uInt32 nIndex = bReverse ? nCount-j-1 : j;
242 implts_calcWindowPosSizeOnSingleRowColumn( i, nOffset, aRowColumnsWindowData[nIndex], aContainerSize );
243 nOffset += aRowColumnsWindowData[j].nStaticSize;
247 implts_setDockingAreaWindowSizes( aDockingArea );
249 aWriteLock.lock();
250 m_bLayoutDirty = false;
251 m_bLayoutInProgress = false;
252 aWriteLock.unlock();
255 bool ToolbarLayoutManager::implts_isParentWindowVisible() const
257 ReadGuard aReadLock( m_aLock );
258 bool bVisible( false );
259 if ( m_xContainerWindow.is() )
260 bVisible = m_xContainerWindow->isVisible();
262 return bVisible;
265 Rectangle ToolbarLayoutManager::implts_calcDockingArea()
267 ReadGuard aReadLock( m_aLock );
268 UIElementVector aWindowVector( m_aUIElements );
269 aReadLock.unlock();
271 Rectangle aBorderSpace;
272 sal_Int32 nCurrRowColumn( 0 );
273 sal_Int32 nCurrPos( 0 );
274 sal_Int32 nCurrDockingArea( ui::DockingArea_DOCKINGAREA_TOP );
275 std::vector< sal_Int32 > aRowColumnSizes[DOCKINGAREAS_COUNT];
276 UIElementVector::const_iterator pConstIter;
278 // initialize rectangle with zero values!
279 aBorderSpace.setWidth(0);
280 aBorderSpace.setHeight(0);
282 aRowColumnSizes[nCurrDockingArea].clear();
283 aRowColumnSizes[nCurrDockingArea].push_back( 0 );
285 for ( pConstIter = aWindowVector.begin(); pConstIter != aWindowVector.end(); ++pConstIter )
287 uno::Reference< ui::XUIElement > xUIElement( pConstIter->m_xUIElement, uno::UNO_QUERY );
288 if ( xUIElement.is() )
290 uno::Reference< awt::XWindow > xWindow( xUIElement->getRealInterface(), uno::UNO_QUERY );
291 uno::Reference< awt::XDockableWindow > xDockWindow( xWindow, uno::UNO_QUERY );
292 if ( xWindow.is() && xDockWindow.is() )
294 SolarMutexGuard aGuard;
296 Window* pWindow = VCLUnoHelper::GetWindow( xWindow );
297 if ( pWindow && !xDockWindow->isFloating() && pConstIter->m_bVisible && !pConstIter->m_bMasterHide )
299 awt::Rectangle aPosSize = xWindow->getPosSize();
300 if ( pConstIter->m_aDockedData.m_nDockedArea != nCurrDockingArea )
302 nCurrDockingArea = pConstIter->m_aDockedData.m_nDockedArea;
303 nCurrRowColumn = 0;
304 nCurrPos = 0;
305 aRowColumnSizes[nCurrDockingArea].clear();
306 aRowColumnSizes[nCurrDockingArea].push_back( 0 );
309 if ( pConstIter->m_aDockedData.m_nDockedArea == nCurrDockingArea )
311 if ( isHorizontalDockingArea( pConstIter->m_aDockedData.m_nDockedArea ))
313 if ( pConstIter->m_aDockedData.m_aPos.Y > nCurrPos )
315 ++nCurrRowColumn;
316 nCurrPos = pConstIter->m_aDockedData.m_aPos.Y;
317 aRowColumnSizes[nCurrDockingArea].push_back( 0 );
320 if ( aPosSize.Height > aRowColumnSizes[nCurrDockingArea][nCurrRowColumn] )
321 aRowColumnSizes[nCurrDockingArea][nCurrRowColumn] = aPosSize.Height;
323 else
325 if ( pConstIter->m_aDockedData.m_aPos.X > nCurrPos )
327 ++nCurrRowColumn;
328 nCurrPos = pConstIter->m_aDockedData.m_aPos.X;
329 aRowColumnSizes[nCurrDockingArea].push_back( 0 );
332 if ( aPosSize.Width > aRowColumnSizes[nCurrDockingArea][nCurrRowColumn] )
333 aRowColumnSizes[nCurrDockingArea][nCurrRowColumn] = aPosSize.Width;
341 // Sum up max heights from every row/column
342 if ( !aWindowVector.empty() )
344 for ( sal_Int32 i = 0; i <= ui::DockingArea_DOCKINGAREA_RIGHT; i++ )
346 sal_Int32 nSize( 0 );
347 const sal_uInt32 nCount = aRowColumnSizes[i].size();
348 for ( sal_uInt32 j = 0; j < nCount; j++ )
349 nSize += aRowColumnSizes[i][j];
351 if ( i == ui::DockingArea_DOCKINGAREA_TOP )
352 aBorderSpace.Top() = nSize;
353 else if ( i == ui::DockingArea_DOCKINGAREA_BOTTOM )
354 aBorderSpace.Bottom() = nSize;
355 else if ( i == ui::DockingArea_DOCKINGAREA_LEFT )
356 aBorderSpace.Left() = nSize;
357 else
358 aBorderSpace.Right() = nSize;
362 return aBorderSpace;
365 void ToolbarLayoutManager::reset()
367 WriteGuard aWriteLock( m_aLock );
368 uno::Reference< ui::XUIConfigurationManager > xModuleCfgMgr( m_xModuleCfgMgr );
369 uno::Reference< ui::XUIConfigurationManager > xDocCfgMgr( m_xDocCfgMgr );
370 m_xModuleCfgMgr.clear();
371 m_xDocCfgMgr.clear();
372 m_ePreviewDetection = PREVIEWFRAME_UNKNOWN;
373 m_bComponentAttached = false;
374 aWriteLock.unlock();
376 destroyToolbars();
377 resetDockingArea();
380 void ToolbarLayoutManager::attach(
381 const uno::Reference< frame::XFrame >& xFrame,
382 const uno::Reference< ui::XUIConfigurationManager >& xModuleCfgMgr,
383 const uno::Reference< ui::XUIConfigurationManager >& xDocCfgMgr,
384 const uno::Reference< container::XNameAccess >& xPersistentWindowState )
386 // reset toolbar manager if we lose our current frame
387 if ( m_xFrame.is() && m_xFrame != xFrame )
388 reset();
390 WriteGuard aWriteLock( m_aLock );
391 m_xFrame = xFrame;
392 m_xModuleCfgMgr = xModuleCfgMgr;
393 m_xDocCfgMgr = xDocCfgMgr;
394 m_xPersistentWindowState = xPersistentWindowState;
395 m_bComponentAttached = true;
398 bool ToolbarLayoutManager::isPreviewFrame()
400 ReadGuard aReadLock( m_aLock );
401 if (m_ePreviewDetection == PREVIEWFRAME_UNKNOWN)
403 uno::Reference< frame::XFrame > xFrame( m_xFrame );
405 uno::Reference< frame::XModel > xModel( impl_getModelFromFrame( xFrame ));
407 WriteGuard aWriteLock( m_aLock );
408 m_ePreviewDetection = (implts_isPreviewModel( xModel ) ? PREVIEWFRAME_YES : PREVIEWFRAME_NO);
410 return m_ePreviewDetection == PREVIEWFRAME_YES;
413 void ToolbarLayoutManager::createStaticToolbars()
415 resetDockingArea();
416 implts_createCustomToolBars();
417 implts_createAddonsToolBars();
418 implts_createNonContextSensitiveToolBars();
419 implts_sortUIElements();
422 bool ToolbarLayoutManager::requestToolbar( const OUString& rResourceURL )
424 if (isPreviewFrame())
425 return false; // no toolbars for preview frame!
427 bool bNotify( false );
428 bool bMustCallCreate( false );
429 uno::Reference< ui::XUIElement > xUIElement;
431 UIElement aRequestedToolbar = impl_findToolbar( rResourceURL );
432 if ( aRequestedToolbar.m_aName != rResourceURL )
434 bMustCallCreate = true;
435 aRequestedToolbar.m_aName = rResourceURL;
436 aRequestedToolbar.m_aType = m_aToolbarTypeString;
437 aRequestedToolbar.m_xUIElement = xUIElement;
438 implts_readWindowStateData( rResourceURL, aRequestedToolbar );
441 xUIElement = aRequestedToolbar.m_xUIElement;
442 if ( !xUIElement.is() )
443 bMustCallCreate = true;
445 bool bCreateOrShowToolbar( aRequestedToolbar.m_bVisible && !aRequestedToolbar.m_bMasterHide );
447 uno::Reference< awt::XWindow2 > xContainerWindow( m_xContainerWindow, uno::UNO_QUERY );
448 if ( xContainerWindow.is() && aRequestedToolbar.m_bFloating )
449 bCreateOrShowToolbar &= bool( xContainerWindow->isActive());
451 if ( bCreateOrShowToolbar )
452 bNotify = ( bMustCallCreate ) ? createToolbar( rResourceURL ) : showToolbar( rResourceURL );
454 return bNotify;
457 bool ToolbarLayoutManager::createToolbar( const OUString& rResourceURL )
459 bool bNotify( false );
460 uno::Reference< ui::XUIElement > xUITempElement;
462 implts_createToolBar( rResourceURL, bNotify, xUITempElement );
463 return bNotify;
466 bool ToolbarLayoutManager::destroyToolbar( const OUString& rResourceURL )
468 const OUString aAddonTbResourceName( "private:resource/toolbar/addon_" );
470 UIElementVector::iterator pIter;
471 uno::Reference< lang::XComponent > xComponent;
473 bool bNotify( false );
474 bool bMustBeSorted( false );
475 bool bMustLayouted( false );
476 bool bMustBeDestroyed( rResourceURL.indexOf( aAddonTbResourceName ) != 0 );
478 WriteGuard aWriteLock( m_aLock );
479 for ( pIter = m_aUIElements.begin(); pIter != m_aUIElements.end(); ++pIter )
481 if ( pIter->m_aName == rResourceURL )
483 xComponent.set( pIter->m_xUIElement, uno::UNO_QUERY );
484 if ( bMustBeDestroyed )
485 pIter->m_xUIElement.clear();
486 else
487 pIter->m_bVisible = false;
488 break;
491 aWriteLock.unlock();
493 uno::Reference< ui::XUIElement > xUIElement( xComponent, uno::UNO_QUERY );
494 if ( xUIElement.is() )
496 uno::Reference< awt::XWindow > xWindow( xUIElement->getRealInterface(), uno::UNO_QUERY );
497 uno::Reference< awt::XDockableWindow > xDockWindow( xWindow, uno::UNO_QUERY );
499 if ( bMustBeDestroyed )
503 if ( xWindow.is() )
504 xWindow->removeWindowListener( uno::Reference< awt::XWindowListener >(
505 static_cast< OWeakObject * >( this ), uno::UNO_QUERY ));
507 catch (const uno::Exception&)
513 if ( xDockWindow.is() )
514 xDockWindow->removeDockableWindowListener( uno::Reference< awt::XDockableWindowListener >(
515 static_cast< OWeakObject * >( this ), uno::UNO_QUERY ));
517 catch (const uno::Exception&)
521 else
523 if ( xWindow.is() )
524 xWindow->setVisible( sal_False );
525 bNotify = true;
528 if ( !xDockWindow->isFloating() )
529 bMustLayouted = true;
530 bMustBeSorted = true;
533 if ( bMustBeDestroyed )
535 if ( xComponent.is() )
536 xComponent->dispose();
537 bNotify = true;
540 if ( bMustLayouted )
541 implts_setLayoutDirty();
543 if ( bMustBeSorted )
544 implts_sortUIElements();
546 return bNotify;
549 void ToolbarLayoutManager::destroyToolbars()
551 UIElementVector aUIElementVector;
552 implts_getUIElementVectorCopy( aUIElementVector );
554 WriteGuard aWriteLock( m_aLock );
555 m_aUIElements.clear();
556 m_bLayoutDirty = true;
557 aWriteLock.unlock();
559 UIElementVector::iterator pIter;
560 for ( pIter = aUIElementVector.begin(); pIter != aUIElementVector.end(); ++pIter )
562 uno::Reference< lang::XComponent > xComponent( pIter->m_xUIElement, uno::UNO_QUERY );
563 if ( xComponent.is() )
564 xComponent->dispose();
568 bool ToolbarLayoutManager::showToolbar( const OUString& rResourceURL )
570 UIElement aUIElement = implts_findToolbar( rResourceURL );
572 SolarMutexGuard aGuard;
573 Window* pWindow = getWindowFromXUIElement( aUIElement.m_xUIElement );
575 // Addons appear to need to be populated at start, but we don't
576 // want to populate them with (scaled) images until later.
577 AddonsToolBarWrapper *pAddOns;
578 pAddOns = dynamic_cast<AddonsToolBarWrapper *>( aUIElement.m_xUIElement.get());
579 if (pAddOns)
580 pAddOns->populateImages();
582 if ( pWindow )
584 if ( !aUIElement.m_bFloating )
585 implts_setLayoutDirty();
586 else
587 pWindow->Show( sal_True, SHOW_NOFOCUSCHANGE | SHOW_NOACTIVATE );
589 aUIElement.m_bVisible = true;
590 implts_writeWindowStateData( aUIElement );
591 implts_setToolbar( aUIElement );
592 implts_sortUIElements();
593 return true;
596 return false;
599 bool ToolbarLayoutManager::hideToolbar( const OUString& rResourceURL )
601 UIElement aUIElement = implts_findToolbar( rResourceURL );
603 SolarMutexGuard aGuard;
604 Window* pWindow = getWindowFromXUIElement( aUIElement.m_xUIElement );
605 if ( pWindow )
607 pWindow->Show( sal_False );
608 if ( !aUIElement.m_bFloating )
609 implts_setLayoutDirty();
611 aUIElement.m_bVisible = false;
612 implts_writeWindowStateData( aUIElement );
613 implts_setToolbar( aUIElement );
614 return true;
617 return false;
620 void ToolbarLayoutManager::refreshToolbarsVisibility( bool bAutomaticToolbars )
622 UIElementVector aUIElementVector;
624 ReadGuard aReadLock( m_aLock );
625 bool bVisible( m_bVisible );
626 aReadLock.unlock();
628 if ( !bVisible || !bAutomaticToolbars )
629 return;
631 implts_getUIElementVectorCopy( aUIElementVector );
633 UIElement aUIElement;
634 SolarMutexGuard aGuard;
635 UIElementVector::iterator pIter;
636 for ( pIter = aUIElementVector.begin(); pIter != aUIElementVector.end(); ++pIter )
638 if ( implts_readWindowStateData( pIter->m_aName, aUIElement ) &&
639 ( pIter->m_bVisible != aUIElement.m_bVisible ) && !pIter->m_bMasterHide )
641 WriteGuard aWriteLock( m_aLock );
642 UIElement& rUIElement = impl_findToolbar( pIter->m_aName );
643 if ( rUIElement.m_aName == pIter->m_aName )
645 rUIElement.m_bVisible = aUIElement.m_bVisible;
646 implts_setLayoutDirty();
652 void ToolbarLayoutManager::setFloatingToolbarsVisibility( bool bVisible )
654 UIElementVector aUIElementVector;
655 implts_getUIElementVectorCopy( aUIElementVector );
657 SolarMutexGuard aGuard;
658 UIElementVector::iterator pIter;
659 for ( pIter = aUIElementVector.begin(); pIter != aUIElementVector.end(); ++pIter )
661 Window* pWindow = getWindowFromXUIElement( pIter->m_xUIElement );
662 if ( pWindow && pIter->m_bFloating )
664 if ( bVisible )
666 if ( pIter->m_bVisible && !pIter->m_bMasterHide )
667 pWindow->Show( sal_True, SHOW_NOFOCUSCHANGE | SHOW_NOACTIVATE );
669 else
670 pWindow->Show( sal_False );
675 void ToolbarLayoutManager::setVisible( bool bVisible )
677 UIElementVector aUIElementVector;
678 implts_getUIElementVectorCopy( aUIElementVector );
680 SolarMutexGuard aGuard;
681 UIElementVector::iterator pIter;
682 for ( pIter = aUIElementVector.begin(); pIter != aUIElementVector.end(); ++pIter )
684 if (!pIter->m_bFloating)
686 UIElement aUIElement(*pIter);
687 aUIElement.m_bMasterHide = !bVisible;
688 implts_setToolbar(aUIElement);
689 implts_setLayoutDirty();
692 Window* pWindow = getWindowFromXUIElement( pIter->m_xUIElement );
693 if ( pWindow )
695 bool bSetVisible( pIter->m_bVisible && bVisible );
696 if ( !bSetVisible )
697 pWindow->Hide();
698 else
700 if ( pIter->m_bFloating )
701 pWindow->Show(true, SHOW_NOFOCUSCHANGE | SHOW_NOACTIVATE );
706 if ( !bVisible )
707 resetDockingArea();
710 bool ToolbarLayoutManager::dockToolbar( const OUString& rResourceURL, ui::DockingArea eDockingArea, const awt::Point& aPos )
712 UIElement aUIElement = implts_findToolbar( rResourceURL );
714 if ( aUIElement.m_xUIElement.is() )
718 uno::Reference< awt::XWindow > xWindow( aUIElement.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
719 uno::Reference< awt::XDockableWindow > xDockWindow( xWindow, uno::UNO_QUERY );
720 if ( xDockWindow.is() )
722 if ( eDockingArea != ui::DockingArea_DOCKINGAREA_DEFAULT )
723 aUIElement.m_aDockedData.m_nDockedArea = sal_Int16( eDockingArea );
725 if ( !isDefaultPos( aPos ))
726 aUIElement.m_aDockedData.m_aPos = aPos;
728 if ( !xDockWindow->isFloating() )
730 Window* pWindow( 0 );
731 ToolBox* pToolBox( 0 );
734 SolarMutexGuard aGuard;
735 pWindow = VCLUnoHelper::GetWindow( xWindow );
736 if ( pWindow && pWindow->GetType() == WINDOW_TOOLBOX )
738 pToolBox = (ToolBox *)pWindow;
740 // We have to set the alignment of the toolbox. It's possible that the toolbox is moved from a
741 // horizontal to a vertical docking area!
742 pToolBox->SetAlign( ImplConvertAlignment( aUIElement.m_aDockedData.m_nDockedArea ));
746 if ( hasDefaultPosValue( aUIElement.m_aDockedData.m_aPos ))
748 // Docking on its default position without a preset position -
749 // we have to find a good place for it.
750 ::Size aSize;
752 SolarMutexGuard aGuard;
754 if ( pToolBox )
755 aSize = pToolBox->CalcWindowSizePixel( 1, ImplConvertAlignment( aUIElement.m_aDockedData.m_nDockedArea ) );
756 else
757 aSize = pWindow->GetSizePixel();
760 ::Point aPixelPos;
761 awt::Point aDockPos;
762 implts_findNextDockingPos((ui::DockingArea)aUIElement.m_aDockedData.m_nDockedArea, aSize, aDockPos, aPixelPos );
763 aUIElement.m_aDockedData.m_aPos = aDockPos;
767 implts_setToolbar( aUIElement );
769 if ( xDockWindow->isFloating() )
771 // ATTENTION: This will call toggleFloatingMode() via notifications which
772 // sets the floating member of the UIElement correctly!
773 xDockWindow->setFloatingMode( sal_False );
775 else
777 implts_writeWindowStateData( aUIElement );
778 implts_sortUIElements();
780 if ( aUIElement.m_bVisible )
781 implts_setLayoutDirty();
783 return true;
786 catch (const lang::DisposedException&)
791 return false;
794 bool ToolbarLayoutManager::dockAllToolbars()
796 std::vector< OUString > aToolBarNameVector;
798 ReadGuard aReadLock( m_aLock );
799 UIElementVector::iterator pIter;
800 for ( pIter = m_aUIElements.begin(); pIter != m_aUIElements.end(); ++pIter )
802 if ( pIter->m_aType == "toolbar" && pIter->m_xUIElement.is() && pIter->m_bFloating && pIter->m_bVisible )
803 aToolBarNameVector.push_back( pIter->m_aName );
805 aReadLock.unlock();
807 bool bResult(true);
808 const sal_uInt32 nCount = aToolBarNameVector.size();
809 for ( sal_uInt32 i = 0; i < nCount; ++i )
811 awt::Point aPoint;
812 aPoint.X = aPoint.Y = SAL_MAX_INT32;
813 bResult &= dockToolbar( aToolBarNameVector[i], ui::DockingArea_DOCKINGAREA_DEFAULT, aPoint );
816 return bResult;
819 long ToolbarLayoutManager::childWindowEvent( VclSimpleEvent* pEvent )
821 // To enable toolbar controllers to change their image when a sub-toolbar function
822 // is activated, we need this mechanism. We have NO connection between these toolbars
823 // anymore!
824 if ( pEvent && pEvent->ISA( VclWindowEvent ))
826 if ( pEvent->GetId() == VCLEVENT_TOOLBOX_SELECT )
828 OUString aToolbarName;
829 OUString aCommand;
830 ToolBox* pToolBox = getToolboxPtr( ((VclWindowEvent*)pEvent)->GetWindow() );
832 if ( pToolBox )
834 aToolbarName = retrieveToolbarNameFromHelpURL( pToolBox );
835 sal_uInt16 nId = pToolBox->GetCurItemId();
836 if ( nId > 0 )
837 aCommand = pToolBox->GetItemCommand( nId );
840 if ( !aToolbarName.isEmpty() && !aCommand.isEmpty() )
842 ReadGuard aReadLock( m_aLock );
843 ::std::vector< uno::Reference< ui::XUIFunctionListener > > aListenerArray;
844 UIElementVector::iterator pIter;
846 for ( pIter = m_aUIElements.begin(); pIter != m_aUIElements.end(); ++pIter )
848 if ( pIter->m_xUIElement.is() )
850 uno::Reference< ui::XUIFunctionListener > xListener( pIter->m_xUIElement, uno::UNO_QUERY );
851 if ( xListener.is() )
852 aListenerArray.push_back( xListener );
855 aReadLock.unlock();
857 const sal_uInt32 nCount = aListenerArray.size();
858 for ( sal_uInt32 i = 0; i < nCount; ++i )
862 aListenerArray[i]->functionExecute( aToolbarName, aCommand );
864 catch (const uno::RuntimeException&)
866 throw;
868 catch (const uno::Exception&)
874 else if ( pEvent->GetId() == VCLEVENT_TOOLBOX_FORMATCHANGED )
876 if ( !implts_isToolbarCreationActive() )
878 ToolBox* pToolBox = getToolboxPtr( ((VclWindowEvent*)pEvent)->GetWindow() );
879 if ( pToolBox )
881 OUString aToolbarName = retrieveToolbarNameFromHelpURL( pToolBox );
882 if ( !aToolbarName.isEmpty() )
884 OUStringBuffer aBuf(100);
885 aBuf.appendAscii( "private:resource/toolbar/" );
886 aBuf.append( aToolbarName );
888 UIElement aToolbar = implts_findToolbar( aBuf.makeStringAndClear() );
889 if ( aToolbar.m_xUIElement.is() && !aToolbar.m_bFloating )
891 implts_setLayoutDirty();
892 m_pParentLayouter->requestLayout( ILayoutNotifications::HINT_TOOLBARSPACE_HAS_CHANGED );
900 return 1;
903 void ToolbarLayoutManager::resetDockingArea()
905 ReadGuard aReadLock( m_aLock );
906 uno::Reference< awt::XWindow > xTopDockingWindow( m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_TOP] );
907 uno::Reference< awt::XWindow > xLeftDockingWindow( m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_LEFT] );
908 uno::Reference< awt::XWindow > xRightDockingWindow( m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_RIGHT] );
909 uno::Reference< awt::XWindow > xBottomDockingWindow( m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_BOTTOM] );
910 aReadLock.unlock();
912 if ( xTopDockingWindow.is() )
913 xTopDockingWindow->setPosSize( 0, 0, 0, 0, awt::PosSize::POSSIZE );
914 if ( xLeftDockingWindow.is() )
915 xLeftDockingWindow->setPosSize( 0, 0, 0, 0, awt::PosSize::POSSIZE );
916 if ( xRightDockingWindow.is() )
917 xRightDockingWindow->setPosSize( 0, 0, 0, 0, awt::PosSize::POSSIZE );
918 if ( xBottomDockingWindow.is() )
919 xBottomDockingWindow->setPosSize( 0, 0, 0, 0, awt::PosSize::POSSIZE );
922 void ToolbarLayoutManager::setParentWindow(
923 const uno::Reference< awt::XWindowPeer >& xParentWindow )
925 static const char DOCKINGAREASTRING[] = "dockingarea";
927 uno::Reference< awt::XWindow > xTopDockWindow = uno::Reference< awt::XWindow >( createToolkitWindow( m_xContext, xParentWindow, DOCKINGAREASTRING ), uno::UNO_QUERY );
928 uno::Reference< awt::XWindow > xLeftDockWindow = uno::Reference< awt::XWindow >( createToolkitWindow( m_xContext, xParentWindow, DOCKINGAREASTRING ), uno::UNO_QUERY );
929 uno::Reference< awt::XWindow > xRightDockWindow = uno::Reference< awt::XWindow >( createToolkitWindow( m_xContext, xParentWindow, DOCKINGAREASTRING ), uno::UNO_QUERY );
930 uno::Reference< awt::XWindow > xBottomDockWindow = uno::Reference< awt::XWindow >( createToolkitWindow( m_xContext, xParentWindow, DOCKINGAREASTRING ), uno::UNO_QUERY );
932 WriteGuard aWriteLock( m_aLock );
933 m_xContainerWindow = uno::Reference< awt::XWindow2 >( xParentWindow, uno::UNO_QUERY );
934 m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_TOP] = xTopDockWindow;
935 m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_LEFT] = xLeftDockWindow;
936 m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_RIGHT] = xRightDockWindow;
937 m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_BOTTOM] = xBottomDockWindow;
938 aWriteLock.unlock();
940 if ( xParentWindow.is() )
942 SolarMutexGuard aGuard;
943 ::DockingAreaWindow* pWindow = dynamic_cast< ::DockingAreaWindow* >(VCLUnoHelper::GetWindow( xTopDockWindow ) );
944 if( pWindow ) pWindow->SetAlign( WINDOWALIGN_TOP );
945 pWindow = dynamic_cast< ::DockingAreaWindow* >(VCLUnoHelper::GetWindow( xBottomDockWindow ) );
946 if( pWindow ) pWindow->SetAlign( WINDOWALIGN_BOTTOM );
947 pWindow = dynamic_cast< ::DockingAreaWindow* >(VCLUnoHelper::GetWindow( xLeftDockWindow ) );
948 if( pWindow ) pWindow->SetAlign( WINDOWALIGN_LEFT );
949 pWindow = dynamic_cast< ::DockingAreaWindow* >(VCLUnoHelper::GetWindow( xRightDockWindow ) );
950 if( pWindow ) pWindow->SetAlign( WINDOWALIGN_RIGHT );
951 implts_reparentToolbars();
953 else
955 destroyToolbars();
956 resetDockingArea();
960 void ToolbarLayoutManager::setDockingAreaOffsets( const ::Rectangle aOffsets )
962 WriteGuard aWriteLock( m_aLock );
963 m_aDockingAreaOffsets = aOffsets;
964 m_bLayoutDirty = true;
967 OUString ToolbarLayoutManager::implts_generateGenericAddonToolbarTitle( sal_Int32 nNumber ) const
969 String aAddonGenericTitle;
971 aAddonGenericTitle = String( FwkResId( STR_TOOLBAR_TITLE_ADDON ));
972 const vcl::I18nHelper& rI18nHelper = Application::GetSettings().GetUILocaleI18nHelper();
974 String aNumStr = rI18nHelper.GetNum( nNumber, 0, sal_False, sal_False );
975 aAddonGenericTitle.SearchAndReplaceAscii( "%num%", aNumStr );
977 return OUString( aAddonGenericTitle );
980 void ToolbarLayoutManager::implts_createAddonsToolBars()
982 WriteGuard aWriteLock( m_aLock );
983 if ( !m_pAddonOptions )
984 m_pAddonOptions = new AddonsOptions;
986 uno::Reference< ui::XUIElementFactory > xUIElementFactory( m_xUIElementFactoryManager );
987 uno::Reference< frame::XFrame > xFrame( m_xFrame );
988 aWriteLock.unlock();
990 if (isPreviewFrame())
991 return; // no addon toolbars for preview frame!
993 uno::Sequence< uno::Sequence< beans::PropertyValue > > aAddonToolBarData;
994 uno::Reference< ui::XUIElement > xUIElement;
996 sal_uInt32 nCount = m_pAddonOptions->GetAddonsToolBarCount();
997 OUString aAddonsToolBarStaticName( m_aFullAddonTbxPrefix );
998 OUString aElementType( "toolbar" );
1000 uno::Sequence< beans::PropertyValue > aPropSeq( 2 );
1001 aPropSeq[0].Name = OUString( "Frame" );
1002 aPropSeq[0].Value <<= xFrame;
1003 aPropSeq[1].Name = OUString( "ConfigurationData" );
1004 for ( sal_uInt32 i = 0; i < nCount; i++ )
1006 OUString aAddonToolBarName( aAddonsToolBarStaticName + m_pAddonOptions->GetAddonsToolbarResourceName(i) );
1007 aAddonToolBarData = m_pAddonOptions->GetAddonsToolBarPart( i );
1008 aPropSeq[1].Value <<= aAddonToolBarData;
1010 UIElement aElement = implts_findToolbar( aAddonToolBarName );
1012 // #i79828
1013 // It's now possible that we are called more than once. Be sure to not create
1014 // add-on toolbars more than once!
1015 if ( aElement.m_xUIElement.is() )
1016 continue;
1020 xUIElement = xUIElementFactory->createUIElement( aAddonToolBarName, aPropSeq );
1021 if ( xUIElement.is() )
1023 uno::Reference< awt::XDockableWindow > xDockWindow( xUIElement->getRealInterface(), uno::UNO_QUERY );
1024 if ( xDockWindow.is() )
1028 xDockWindow->addDockableWindowListener( uno::Reference< awt::XDockableWindowListener >( static_cast< OWeakObject * >( this ), uno::UNO_QUERY ));
1029 xDockWindow->enableDocking( sal_True );
1030 uno::Reference< awt::XWindow > xWindow( xDockWindow, uno::UNO_QUERY );
1031 if ( xWindow.is() )
1032 xWindow->addWindowListener( uno::Reference< awt::XWindowListener >( static_cast< OWeakObject * >( this ), uno::UNO_QUERY ));
1034 catch (const uno::Exception&)
1039 OUString aGenericAddonTitle = implts_generateGenericAddonToolbarTitle( i+1 );
1041 if ( !aElement.m_aName.isEmpty() )
1043 // Reuse a local entry so we are able to use the latest
1044 // UI changes for this document.
1045 implts_setElementData( aElement, xDockWindow );
1046 aElement.m_xUIElement = xUIElement;
1047 if ( aElement.m_aUIName.isEmpty() )
1049 aElement.m_aUIName = aGenericAddonTitle;
1050 implts_writeWindowStateData( aElement );
1053 else
1055 // Create new UI element and try to read its state data
1056 UIElement aNewToolbar( aAddonToolBarName, aElementType, xUIElement );
1057 aNewToolbar.m_bFloating = true;
1058 implts_readWindowStateData( aAddonToolBarName, aNewToolbar );
1059 implts_setElementData( aNewToolbar, xDockWindow );
1060 if ( aNewToolbar.m_aUIName.isEmpty() )
1062 aNewToolbar.m_aUIName = aGenericAddonTitle;
1063 implts_writeWindowStateData( aNewToolbar );
1065 implts_insertToolbar( aNewToolbar );
1068 uno::Reference< awt::XWindow > xWindow( xDockWindow, uno::UNO_QUERY );
1069 if ( xWindow.is() )
1071 // Set generic title for add-on toolbar
1072 SolarMutexGuard aGuard;
1073 Window* pWindow = VCLUnoHelper::GetWindow( xWindow );
1074 if ( pWindow->GetText().isEmpty() )
1075 pWindow->SetText( aGenericAddonTitle );
1076 if ( pWindow->GetType() == WINDOW_TOOLBOX )
1078 ToolBox* pToolbar = (ToolBox *)pWindow;
1079 pToolbar->SetMenuType();
1084 catch (const container::NoSuchElementException&)
1087 catch (const lang::IllegalArgumentException&)
1093 void ToolbarLayoutManager::implts_createCustomToolBars()
1095 ReadGuard aReadLock( m_aLock );
1096 if ( !m_bComponentAttached )
1097 return;
1099 uno::Reference< ui::XUIElementFactory > xUIElementFactory( m_xUIElementFactoryManager );
1100 uno::Reference< frame::XFrame > xFrame( m_xFrame );
1101 uno::Reference< ui::XUIConfigurationManager > xModuleCfgMgr( m_xModuleCfgMgr, uno::UNO_QUERY );
1102 uno::Reference< ui::XUIConfigurationManager > xDocCfgMgr( m_xDocCfgMgr, uno::UNO_QUERY );
1103 aReadLock.unlock();
1105 if ( xFrame.is() )
1107 if (isPreviewFrame())
1108 return; // no custom toolbars for preview frame!
1110 uno::Sequence< uno::Sequence< beans::PropertyValue > > aTbxSeq;
1111 if ( xDocCfgMgr.is() )
1113 aTbxSeq = xDocCfgMgr->getUIElementsInfo( ui::UIElementType::TOOLBAR );
1114 implts_createCustomToolBars( aTbxSeq ); // first create all document based toolbars
1116 if ( xModuleCfgMgr.is() )
1118 aTbxSeq = xModuleCfgMgr->getUIElementsInfo( ui::UIElementType::TOOLBAR );
1119 implts_createCustomToolBars( aTbxSeq ); // second create module based toolbars
1124 void ToolbarLayoutManager::implts_createNonContextSensitiveToolBars()
1126 ReadGuard aReadLock( m_aLock );
1128 if ( !m_xPersistentWindowState.is() || !m_xFrame.is() || !m_bComponentAttached )
1129 return;
1131 uno::Reference< ui::XUIElementFactory > xUIElementFactory( m_xUIElementFactoryManager );
1132 uno::Reference< container::XNameAccess > xPersistentWindowState( m_xPersistentWindowState );
1133 aReadLock.unlock();
1135 if (isPreviewFrame())
1136 return;
1138 std::vector< OUString > aMakeVisibleToolbars;
1142 uno::Sequence< OUString > aToolbarNames = xPersistentWindowState->getElementNames();
1144 if ( aToolbarNames.getLength() > 0 )
1146 OUString aElementType;
1147 OUString aElementName;
1148 OUString aName;
1150 uno::Reference< ui::XUIElement > xUIElement;
1151 aMakeVisibleToolbars.reserve(aToolbarNames.getLength());
1153 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
1154 WriteGuard aWriteLock( m_aLock );
1156 const OUString* pTbNames = aToolbarNames.getConstArray();
1157 for ( sal_Int32 i = 0; i < aToolbarNames.getLength(); i++ )
1159 aName = pTbNames[i];
1160 parseResourceURL( aName, aElementType, aElementName );
1162 // Check that we only create:
1163 // - Toolbars (the statusbar is also member of the persistent window state)
1164 // - Not custom toolbars, there are created with their own method (implts_createCustomToolbars)
1165 if ( aElementType.equalsIgnoreAsciiCase("toolbar") &&
1166 aElementName.indexOf( m_aCustomTbxPrefix ) == -1 )
1168 UIElement aNewToolbar = implts_findToolbar( aName );
1169 bool bFound = ( aNewToolbar.m_aName == aName );
1170 if ( !bFound )
1171 implts_readWindowStateData( aName, aNewToolbar );
1173 if ( aNewToolbar.m_bVisible && !aNewToolbar.m_bContextSensitive )
1175 if ( !bFound )
1176 implts_insertToolbar( aNewToolbar );
1177 aMakeVisibleToolbars.push_back( aName );
1181 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
1184 catch (const uno::RuntimeException&)
1186 throw;
1188 catch (const uno::Exception&)
1192 if ( !aMakeVisibleToolbars.empty() )
1193 ::std::for_each( aMakeVisibleToolbars.begin(), aMakeVisibleToolbars.end(),
1194 ::boost::bind( &ToolbarLayoutManager::requestToolbar, this, _1));
1197 void ToolbarLayoutManager::implts_createCustomToolBars( const uno::Sequence< uno::Sequence< beans::PropertyValue > >& aTbxSeqSeq )
1199 const uno::Sequence< beans::PropertyValue >* pTbxSeq = aTbxSeqSeq.getConstArray();
1200 for ( sal_Int32 i = 0; i < aTbxSeqSeq.getLength(); i++ )
1202 const uno::Sequence< beans::PropertyValue >& rTbxSeq = pTbxSeq[i];
1203 OUString aTbxResName;
1204 OUString aTbxTitle;
1205 for ( sal_Int32 j = 0; j < rTbxSeq.getLength(); j++ )
1207 if ( rTbxSeq[j].Name == "ResourceURL" )
1208 rTbxSeq[j].Value >>= aTbxResName;
1209 else if ( rTbxSeq[j].Name == "UIName" )
1210 rTbxSeq[j].Value >>= aTbxTitle;
1213 // Only create custom toolbars. Their name have to start with "custom_"!
1214 if ( !aTbxResName.isEmpty() && ( aTbxResName.indexOf( m_aCustomTbxPrefix ) != -1 ) )
1215 implts_createCustomToolBar( aTbxResName, aTbxTitle );
1219 void ToolbarLayoutManager::implts_createCustomToolBar( const OUString& aTbxResName, const OUString& aTitle )
1221 if ( !aTbxResName.isEmpty() )
1223 bool bNotify( false );
1224 uno::Reference< ui::XUIElement > xUIElement;
1225 implts_createToolBar( aTbxResName, bNotify, xUIElement );
1227 if ( !aTitle.isEmpty() && xUIElement.is() )
1229 SolarMutexGuard aGuard;
1231 Window* pWindow = getWindowFromXUIElement( xUIElement );
1232 if ( pWindow )
1233 pWindow->SetText( aTitle );
1238 void ToolbarLayoutManager::implts_reparentToolbars()
1240 WriteGuard aWriteLock( m_aLock );
1241 UIElementVector aUIElementVector = m_aUIElements;
1242 Window* pContainerWindow = VCLUnoHelper::GetWindow( m_xContainerWindow );
1243 Window* pTopDockWindow = VCLUnoHelper::GetWindow( m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_TOP] );
1244 Window* pBottomDockWindow = VCLUnoHelper::GetWindow( m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_BOTTOM] );
1245 Window* pLeftDockWindow = VCLUnoHelper::GetWindow( m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_LEFT] );
1246 Window* pRightDockWindow = VCLUnoHelper::GetWindow( m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_RIGHT] );
1247 aWriteLock.unlock();
1249 SolarMutexGuard aGuard;
1250 if ( pContainerWindow )
1252 UIElementVector::iterator pIter;
1253 for ( pIter = aUIElementVector.begin(); pIter != aUIElementVector.end(); ++pIter )
1255 uno::Reference< ui::XUIElement > xUIElement( pIter->m_xUIElement );
1256 if ( xUIElement.is() )
1258 uno::Reference< awt::XWindow > xWindow;
1261 // We have to retrieve the window reference with try/catch as it is
1262 // possible that all elements have been disposed!
1263 xWindow = uno::Reference< awt::XWindow >( xUIElement->getRealInterface(), uno::UNO_QUERY );
1265 catch (const uno::RuntimeException&)
1267 throw;
1269 catch (const uno::Exception&)
1273 Window* pWindow = VCLUnoHelper::GetWindow( xWindow );
1274 if ( pWindow )
1276 // Reparent our child windows acording to their current state.
1277 if ( pIter->m_bFloating )
1278 pWindow->SetParent( pContainerWindow );
1279 else
1281 if ( pIter->m_aDockedData.m_nDockedArea == ui::DockingArea_DOCKINGAREA_TOP )
1282 pWindow->SetParent( pTopDockWindow );
1283 else if ( pIter->m_aDockedData.m_nDockedArea == ui::DockingArea_DOCKINGAREA_BOTTOM )
1284 pWindow->SetParent( pBottomDockWindow );
1285 else if ( pIter->m_aDockedData.m_nDockedArea == ui::DockingArea_DOCKINGAREA_LEFT )
1286 pWindow->SetParent( pLeftDockWindow );
1287 else
1288 pWindow->SetParent( pRightDockWindow );
1296 void ToolbarLayoutManager::implts_setToolbarCreation( bool bStart )
1298 WriteGuard aWriteLock( m_aLock );
1299 m_bToolbarCreation = bStart;
1302 bool ToolbarLayoutManager::implts_isToolbarCreationActive()
1304 ReadGuard aReadLock( m_aLock );
1305 return m_bToolbarCreation;
1308 void ToolbarLayoutManager::implts_createToolBar( const OUString& aName, bool& bNotify, uno::Reference< ui::XUIElement >& rUIElement )
1310 ReadGuard aReadLock( m_aLock );
1311 uno::Reference< frame::XFrame > xFrame( m_xFrame );
1312 uno::Reference< awt::XWindow2 > xContainerWindow( m_xContainerWindow );
1313 aReadLock.unlock();
1315 bNotify = false;
1317 if ( !xFrame.is() || !xContainerWindow.is() )
1318 return;
1320 UIElement aToolbarElement = implts_findToolbar( aName );
1321 if ( !aToolbarElement.m_xUIElement.is() )
1323 uno::Reference< ui::XUIElement > xUIElement = implts_createElement( aName );
1325 bool bVisible( false );
1326 bool bFloating( false );
1327 if ( xUIElement.is() )
1329 rUIElement = xUIElement;
1331 uno::Reference< awt::XWindow > xWindow( xUIElement->getRealInterface(), uno::UNO_QUERY );
1332 uno::Reference< awt::XDockableWindow > xDockWindow( xWindow, uno::UNO_QUERY );
1333 if ( xDockWindow.is() && xWindow.is() )
1337 xDockWindow->addDockableWindowListener( uno::Reference< awt::XDockableWindowListener >(
1338 static_cast< OWeakObject * >( this ), uno::UNO_QUERY ));
1339 xWindow->addWindowListener( uno::Reference< awt::XWindowListener >(
1340 static_cast< OWeakObject * >( this ), uno::UNO_QUERY ));
1341 xDockWindow->enableDocking( sal_True );
1343 catch (const uno::Exception&)
1348 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
1349 WriteGuard aWriteLock( m_aLock );
1351 UIElement& rElement = impl_findToolbar( aName );
1352 if ( !rElement.m_aName.isEmpty() )
1354 // Reuse a local entry so we are able to use the latest
1355 // UI changes for this document.
1356 implts_setElementData( rElement, xDockWindow );
1357 rElement.m_xUIElement = xUIElement;
1358 bVisible = rElement.m_bVisible;
1359 bFloating = rElement.m_bFloating;
1361 else
1363 // Create new UI element and try to read its state data
1364 UIElement aNewToolbar( aName, m_aToolbarTypeString, xUIElement );
1365 implts_readWindowStateData( aName, aNewToolbar );
1366 implts_setElementData( aNewToolbar, xDockWindow );
1367 implts_insertToolbar( aNewToolbar );
1368 bVisible = aNewToolbar.m_bVisible;
1369 bFloating = rElement.m_bFloating;
1371 aWriteLock.unlock();
1372 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
1374 // set toolbar menu style according to customize command state
1375 SvtCommandOptions aCmdOptions;
1377 SolarMutexGuard aGuard;
1378 Window* pWindow = VCLUnoHelper::GetWindow( xWindow );
1379 if ( pWindow && pWindow->GetType() == WINDOW_TOOLBOX )
1381 ToolBox* pToolbar = (ToolBox *)pWindow;
1382 sal_uInt16 nMenuType = pToolbar->GetMenuType();
1383 if ( aCmdOptions.Lookup( SvtCommandOptions::CMDOPTION_DISABLED, m_aCustomizeCmd ))
1384 pToolbar->SetMenuType( nMenuType & ~TOOLBOX_MENUTYPE_CUSTOMIZE );
1385 else
1386 pToolbar->SetMenuType( nMenuType | TOOLBOX_MENUTYPE_CUSTOMIZE );
1388 bNotify = true;
1390 implts_sortUIElements();
1392 if ( bVisible && !bFloating )
1393 implts_setLayoutDirty();
1398 uno::Reference< ui::XUIElement > ToolbarLayoutManager::implts_createElement( const OUString& aName )
1400 uno::Reference< ui::XUIElement > xUIElement;
1402 ReadGuard aReadLock( m_aLock );
1403 uno::Sequence< beans::PropertyValue > aPropSeq( 2 );
1404 aPropSeq[0].Name = OUString( "Frame" );
1405 aPropSeq[0].Value <<= m_xFrame;
1406 aPropSeq[1].Name = OUString( "Persistent" );
1407 aPropSeq[1].Value <<= true;
1408 uno::Reference< ui::XUIElementFactory > xUIElementFactory( m_xUIElementFactoryManager );
1409 aReadLock.unlock();
1411 implts_setToolbarCreation( true );
1414 if ( xUIElementFactory.is() )
1415 xUIElement = xUIElementFactory->createUIElement( aName, aPropSeq );
1417 catch (const container::NoSuchElementException&)
1420 catch (const lang::IllegalArgumentException&)
1423 implts_setToolbarCreation( false );
1425 return xUIElement;
1428 void ToolbarLayoutManager::implts_setElementData( UIElement& rElement, const uno::Reference< awt::XDockableWindow >& rDockWindow )
1430 ReadGuard aReadLock( m_aLock );
1431 bool bShowElement( rElement.m_bVisible && !rElement.m_bMasterHide && implts_isParentWindowVisible() );
1432 aReadLock.unlock();
1434 uno::Reference< awt::XDockableWindow > xDockWindow( rDockWindow );
1435 uno::Reference< awt::XWindow2 > xWindow( xDockWindow, uno::UNO_QUERY );
1437 Window* pWindow( 0 );
1438 ToolBox* pToolBox( 0 );
1440 if ( xDockWindow.is() && xWindow.is() )
1443 SolarMutexGuard aGuard;
1444 pWindow = VCLUnoHelper::GetWindow( xWindow );
1445 if ( pWindow )
1447 String aText = pWindow->GetText();
1448 if ( aText.Len() == 0 )
1449 pWindow->SetText( rElement.m_aUIName );
1450 if ( rElement.m_bNoClose )
1451 pWindow->SetStyle( pWindow->GetStyle() & ~WB_CLOSEABLE );
1452 if ( pWindow->GetType() == WINDOW_TOOLBOX )
1453 pToolBox = (ToolBox *)pWindow;
1455 if ( pToolBox )
1457 if (( rElement.m_nStyle < 0 ) || ( rElement.m_nStyle > BUTTON_SYMBOLTEXT ))
1458 rElement.m_nStyle = BUTTON_SYMBOL;
1459 pToolBox->SetButtonType( (ButtonType)rElement.m_nStyle );
1460 if ( rElement.m_bNoClose )
1461 pToolBox->SetFloatStyle( pToolBox->GetFloatStyle() & ~WB_CLOSEABLE );
1465 if ( rElement.m_bFloating )
1467 if ( pWindow )
1469 SolarMutexGuard aGuard;
1470 String aText = pWindow->GetText();
1471 if ( aText.Len() == 0 )
1472 pWindow->SetText( rElement.m_aUIName );
1475 awt::Point aPos(rElement.m_aFloatingData.m_aPos);
1476 bool bWriteData( false );
1477 bool bUndefPos = hasDefaultPosValue( rElement.m_aFloatingData.m_aPos );
1478 bool bSetSize = ( rElement.m_aFloatingData.m_aSize.Width != 0 &&
1479 rElement.m_aFloatingData.m_aSize.Height != 0 );
1480 xDockWindow->setFloatingMode( sal_True );
1481 if ( bUndefPos )
1483 aPos = implts_findNextCascadeFloatingPos();
1484 rElement.m_aFloatingData.m_aPos = aPos; // set new cascaded position
1485 bWriteData = true;
1488 if( bSetSize )
1489 xWindow->setOutputSize(rElement.m_aFloatingData.m_aSize);
1490 else
1492 if( pToolBox )
1494 // set an optimal initial floating size
1495 SolarMutexGuard aGuard;
1496 ::Size aSize( pToolBox->CalcFloatingWindowSizePixel() );
1497 pToolBox->SetOutputSizePixel( aSize );
1501 // #i60882# IMPORTANT: Set position after size as it is
1502 // possible that we position some part of the toolbar
1503 // outside of the desktop. A default constructed toolbar
1504 // always has one line. Now VCL automatically
1505 // position the toolbar back into the desktop. Therefore
1506 // we resize the toolbar with the new (wrong) position.
1507 // To fix this problem we have to set the size BEFORE the
1508 // position.
1509 xWindow->setPosSize( aPos.X, aPos.Y, 0, 0, awt::PosSize::POS );
1511 if ( bWriteData )
1512 implts_writeWindowStateData( rElement );
1513 if ( bShowElement && pWindow )
1515 SolarMutexGuard aGuard;
1516 pWindow->Show( sal_True, SHOW_NOFOCUSCHANGE | SHOW_NOACTIVATE );
1519 else
1521 bool bSetSize( false );
1522 awt::Point aDockPos;
1523 ::Point aPixelPos;
1524 ::Size aSize;
1526 if ( pToolBox )
1528 SolarMutexGuard aGuard;
1529 pToolBox->SetAlign( ImplConvertAlignment(rElement.m_aDockedData.m_nDockedArea ) );
1530 pToolBox->SetLineCount( 1 );
1531 xDockWindow->setFloatingMode( sal_False );
1532 if ( rElement.m_aDockedData.m_bLocked )
1533 xDockWindow->lock();
1534 aSize = pToolBox->CalcWindowSizePixel();
1535 bSetSize = true;
1537 if ( isDefaultPos( rElement.m_aDockedData.m_aPos ))
1539 implts_findNextDockingPos( (ui::DockingArea)rElement.m_aDockedData.m_nDockedArea, aSize, aDockPos, aPixelPos );
1540 rElement.m_aDockedData.m_aPos = aDockPos;
1544 xWindow->setPosSize( aPixelPos.X(), aPixelPos.Y(), 0, 0, awt::PosSize::POS );
1545 if( bSetSize )
1546 xWindow->setOutputSize( AWTSize( aSize) );
1548 if ( pWindow )
1550 SolarMutexGuard aGuard;
1551 if ( !bShowElement )
1552 pWindow->Hide();
1558 void ToolbarLayoutManager::implts_destroyDockingAreaWindows()
1560 WriteGuard aWriteLock( m_aLock );
1561 uno::Reference< awt::XWindow > xTopDockingWindow( m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_TOP] );
1562 uno::Reference< awt::XWindow > xLeftDockingWindow( m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_LEFT] );
1563 uno::Reference< awt::XWindow > xRightDockingWindow( m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_RIGHT] );
1564 uno::Reference< awt::XWindow > xBottomDockingWindow( m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_BOTTOM] );
1565 m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_TOP].clear();
1566 m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_LEFT].clear();
1567 m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_RIGHT].clear();
1568 m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_BOTTOM].clear();
1569 aWriteLock.unlock();
1571 // destroy windows
1572 xTopDockingWindow->dispose();
1573 xLeftDockingWindow->dispose();
1574 xRightDockingWindow->dispose();
1575 xBottomDockingWindow->dispose();
1578 //---------------------------------------------------------------------------------------------------------
1579 // persistence methods
1580 //---------------------------------------------------------------------------------------------------------
1582 sal_Bool ToolbarLayoutManager::implts_readWindowStateData( const OUString& aName, UIElement& rElementData )
1584 return LayoutManager::readWindowStateData( aName, rElementData, m_aLock, m_xPersistentWindowState,
1585 m_pGlobalSettings, m_bGlobalSettings, m_xContext );
1588 void ToolbarLayoutManager::implts_writeWindowStateData( const UIElement& rElementData )
1590 WriteGuard aWriteLock( m_aLock );
1591 uno::Reference< container::XNameAccess > xPersistentWindowState( m_xPersistentWindowState );
1592 m_bStoreWindowState = true; // set flag to determine that we triggered the notification
1593 aWriteLock.unlock();
1595 bool bPersistent( sal_False );
1596 uno::Reference< beans::XPropertySet > xPropSet( rElementData.m_xUIElement, uno::UNO_QUERY );
1597 if ( xPropSet.is() )
1601 // Check persistent flag of the user interface element
1602 xPropSet->getPropertyValue( OUString( "Persistent" )) >>= bPersistent;
1604 catch (const beans::UnknownPropertyException&)
1606 bPersistent = true; // Non-configurable elements should at least store their dimension/position
1608 catch (const lang::WrappedTargetException&)
1613 if ( bPersistent && xPersistentWindowState.is() )
1617 uno::Sequence< beans::PropertyValue > aWindowState( 8 );
1619 aWindowState[0].Name = OUString::createFromAscii( WINDOWSTATE_PROPERTY_DOCKED );
1620 aWindowState[0].Value = ::uno::makeAny( sal_Bool( !rElementData.m_bFloating ));
1621 aWindowState[1].Name = OUString::createFromAscii( WINDOWSTATE_PROPERTY_VISIBLE );
1622 aWindowState[1].Value = uno::makeAny( sal_Bool( rElementData.m_bVisible ));
1623 aWindowState[2].Name = OUString::createFromAscii( WINDOWSTATE_PROPERTY_DOCKINGAREA );
1624 aWindowState[2].Value = uno::makeAny( static_cast< ui::DockingArea >( rElementData.m_aDockedData.m_nDockedArea ) );
1626 awt::Point aPos = rElementData.m_aDockedData.m_aPos;
1627 aWindowState[3].Name = OUString::createFromAscii( WINDOWSTATE_PROPERTY_DOCKPOS );
1628 aWindowState[3].Value <<= aPos;
1630 aPos = rElementData.m_aFloatingData.m_aPos;
1631 aWindowState[4].Name = OUString::createFromAscii( WINDOWSTATE_PROPERTY_POS );
1632 aWindowState[4].Value <<= aPos;
1634 aWindowState[5].Name = OUString::createFromAscii( WINDOWSTATE_PROPERTY_SIZE );
1635 aWindowState[5].Value <<= rElementData.m_aFloatingData.m_aSize;
1636 aWindowState[6].Name = OUString::createFromAscii( WINDOWSTATE_PROPERTY_UINAME );
1637 aWindowState[6].Value = uno::makeAny( rElementData.m_aUIName );
1638 aWindowState[7].Name = OUString::createFromAscii( WINDOWSTATE_PROPERTY_LOCKED );
1639 aWindowState[7].Value = uno::makeAny( rElementData.m_aDockedData.m_bLocked );
1641 OUString aName = rElementData.m_aName;
1642 if ( xPersistentWindowState->hasByName( aName ))
1644 uno::Reference< container::XNameReplace > xReplace( xPersistentWindowState, uno::UNO_QUERY );
1645 xReplace->replaceByName( aName, uno::makeAny( aWindowState ));
1647 else
1649 uno::Reference< container::XNameContainer > xInsert( xPersistentWindowState, uno::UNO_QUERY );
1650 xInsert->insertByName( aName, uno::makeAny( aWindowState ));
1653 catch (const uno::Exception&)
1658 // Reset flag
1659 aWriteLock.lock();
1660 m_bStoreWindowState = false;
1661 aWriteLock.unlock();
1664 /******************************************************************************
1665 LOOKUP PART FOR TOOLBARS
1666 ******************************************************************************/
1668 UIElement& ToolbarLayoutManager::impl_findToolbar( const OUString& aName )
1670 static UIElement aEmptyElement;
1671 UIElementVector::iterator pIter;
1673 ReadGuard aReadLock( m_aLock );
1674 for ( pIter = m_aUIElements.begin(); pIter != m_aUIElements.end(); ++pIter )
1676 if ( pIter->m_aName == aName )
1677 return *pIter;
1680 return aEmptyElement;
1683 UIElement ToolbarLayoutManager::implts_findToolbar( const OUString& aName )
1685 ReadGuard aReadLock( m_aLock );
1686 UIElement aElement = impl_findToolbar( aName );
1687 aReadLock.unlock();
1689 return aElement;
1692 UIElement ToolbarLayoutManager::implts_findToolbar( const uno::Reference< uno::XInterface >& xToolbar )
1694 UIElement aToolbar;
1695 UIElementVector::const_iterator pIter;
1697 ReadGuard aReadLock( m_aLock );
1698 for ( pIter = m_aUIElements.begin(); pIter != m_aUIElements.end(); ++pIter )
1700 if ( pIter->m_xUIElement.is() )
1702 uno::Reference< uno::XInterface > xIfac( pIter->m_xUIElement->getRealInterface(), uno::UNO_QUERY );
1703 if ( xIfac == xToolbar )
1705 aToolbar = *pIter;
1706 break;
1711 return aToolbar;
1714 uno::Reference< awt::XWindow > ToolbarLayoutManager::implts_getXWindow( const OUString& aName )
1716 UIElementVector::iterator pIter;
1717 uno::Reference< awt::XWindow > xWindow;
1719 ReadGuard aReadLock( m_aLock );
1720 for ( pIter = m_aUIElements.begin(); pIter != m_aUIElements.end(); ++pIter )
1722 if ( pIter->m_aName == aName && pIter->m_xUIElement.is() )
1724 xWindow = uno::Reference< awt::XWindow >( pIter->m_xUIElement->getRealInterface(), uno::UNO_QUERY );
1725 break;
1729 return xWindow;
1732 Window* ToolbarLayoutManager::implts_getWindow( const OUString& aName )
1734 uno::Reference< awt::XWindow > xWindow = implts_getXWindow( aName );
1735 Window* pWindow = VCLUnoHelper::GetWindow( xWindow );
1737 return pWindow;
1740 bool ToolbarLayoutManager::implts_insertToolbar( const UIElement& rUIElement )
1742 UIElement aTempData;
1743 bool bFound( false );
1744 bool bResult( false );
1746 aTempData = implts_findToolbar( rUIElement.m_aName );
1747 if ( aTempData.m_aName == rUIElement.m_aName )
1748 bFound = true;
1750 if ( !bFound )
1752 WriteGuard aWriteLock( m_aLock );
1753 m_aUIElements.push_back( rUIElement );
1754 bResult = true;
1757 return bResult;
1760 void ToolbarLayoutManager::implts_setToolbar( const UIElement& rUIElement )
1762 WriteGuard aWriteLock( m_aLock );
1763 UIElement& rData = impl_findToolbar( rUIElement.m_aName );
1764 if ( rData.m_aName == rUIElement.m_aName )
1765 rData = rUIElement;
1766 else
1767 m_aUIElements.push_back( rUIElement );
1770 /******************************************************************************
1771 LAYOUT CODE PART FOR TOOLBARS
1772 ******************************************************************************/
1774 awt::Point ToolbarLayoutManager::implts_findNextCascadeFloatingPos()
1776 const sal_Int32 nHotZoneX = 50;
1777 const sal_Int32 nHotZoneY = 50;
1778 const sal_Int32 nCascadeIndentX = 15;
1779 const sal_Int32 nCascadeIndentY = 15;
1781 ReadGuard aReadLock( m_aLock );
1782 uno::Reference< awt::XWindow2 > xContainerWindow( m_xContainerWindow );
1783 uno::Reference< awt::XWindow > xTopDockingWindow( m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_TOP] );
1784 uno::Reference< awt::XWindow > xLeftDockingWindow( m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_LEFT] );
1785 aReadLock.unlock();
1787 awt::Point aStartPos( nCascadeIndentX, nCascadeIndentY );
1788 awt::Point aCurrPos( aStartPos );
1789 awt::Rectangle aRect;
1791 Window* pContainerWindow( 0 );
1792 if ( xContainerWindow.is() )
1794 SolarMutexGuard aGuard;
1795 pContainerWindow = VCLUnoHelper::GetWindow( xContainerWindow );
1796 if ( pContainerWindow )
1797 aStartPos = AWTPoint(pContainerWindow->OutputToScreenPixel(VCLPoint(aStartPos)));
1800 // Determine size of top and left docking area
1801 awt::Rectangle aTopRect( xTopDockingWindow->getPosSize() );
1802 awt::Rectangle aLeftRect( xLeftDockingWindow->getPosSize() );
1804 aStartPos.X += aLeftRect.Width + nCascadeIndentX;
1805 aStartPos.Y += aTopRect.Height + nCascadeIndentY;
1806 aCurrPos = aStartPos;
1808 // Try to find a cascaded position for the new floating window
1809 UIElementVector::const_iterator pIter;
1810 for ( pIter = m_aUIElements.begin(); pIter != m_aUIElements.end(); ++pIter )
1812 if ( pIter->m_xUIElement.is() )
1814 uno::Reference< awt::XDockableWindow > xDockWindow( pIter->m_xUIElement->getRealInterface(), uno::UNO_QUERY );
1815 uno::Reference< awt::XWindow > xWindow( xDockWindow, uno::UNO_QUERY );
1816 if ( xDockWindow.is() && xDockWindow->isFloating() )
1818 SolarMutexGuard aGuard;
1819 Window* pWindow = VCLUnoHelper::GetWindow( xWindow );
1820 if ( pWindow && pWindow->IsVisible() )
1822 awt::Rectangle aFloatRect = xWindow->getPosSize();
1823 if ((( aFloatRect.X - nHotZoneX ) <= aCurrPos.X ) &&
1824 ( aFloatRect.X >= aCurrPos.X ) &&
1825 (( aFloatRect.Y - nHotZoneY ) <= aCurrPos.Y ) &&
1826 ( aFloatRect.Y >= aCurrPos.Y ))
1828 aCurrPos.X = aFloatRect.X + nCascadeIndentX;
1829 aCurrPos.Y = aFloatRect.Y + nCascadeIndentY;
1836 return aCurrPos;
1839 void ToolbarLayoutManager::implts_sortUIElements()
1841 WriteGuard aWriteLock( m_aLock );
1842 UIElementVector::iterator pIterStart = m_aUIElements.begin();
1843 UIElementVector::iterator pIterEnd = m_aUIElements.end();
1845 std::stable_sort( pIterStart, pIterEnd ); // first created element should first
1847 // We have to reset our temporary flags.
1848 UIElementVector::iterator pIter;
1849 for ( pIter = m_aUIElements.begin(); pIter != m_aUIElements.end(); ++pIter )
1850 pIter->m_bUserActive = sal_False;
1851 aWriteLock.unlock();
1854 void ToolbarLayoutManager::implts_getUIElementVectorCopy( UIElementVector& rCopy )
1856 ReadGuard aReadLock( m_aLock );
1857 rCopy = m_aUIElements;
1860 ::Size ToolbarLayoutManager::implts_getTopBottomDockingAreaSizes()
1862 ::Size aSize;
1863 uno::Reference< awt::XWindow > xTopDockingAreaWindow;
1864 uno::Reference< awt::XWindow > xBottomDockingAreaWindow;
1866 ReadGuard aReadLock( m_aLock );
1867 xTopDockingAreaWindow = m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_TOP];
1868 xBottomDockingAreaWindow = m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_BOTTOM];
1869 aReadLock.unlock();
1871 if ( xTopDockingAreaWindow.is() )
1872 aSize.Width() = xTopDockingAreaWindow->getPosSize().Height;
1873 if ( xBottomDockingAreaWindow.is() )
1874 aSize.Height() = xBottomDockingAreaWindow->getPosSize().Height;
1876 return aSize;
1879 void ToolbarLayoutManager::implts_getDockingAreaElementInfos( ui::DockingArea eDockingArea, std::vector< SingleRowColumnWindowData >& rRowColumnsWindowData )
1881 std::vector< UIElement > aWindowVector;
1883 if (( eDockingArea < ui::DockingArea_DOCKINGAREA_TOP ) || ( eDockingArea > ui::DockingArea_DOCKINGAREA_RIGHT ))
1884 eDockingArea = ui::DockingArea_DOCKINGAREA_TOP;
1886 uno::Reference< awt::XWindow > xDockAreaWindow;
1888 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
1889 ReadGuard aReadLock( m_aLock );
1890 aWindowVector.reserve(m_aUIElements.size());
1891 xDockAreaWindow = m_xDockAreaWindows[eDockingArea];
1892 UIElementVector::iterator pIter;
1893 for ( pIter = m_aUIElements.begin(); pIter != m_aUIElements.end(); ++pIter )
1895 if ( pIter->m_aDockedData.m_nDockedArea == eDockingArea && pIter->m_bVisible && !pIter->m_bFloating )
1897 uno::Reference< ui::XUIElement > xUIElement( pIter->m_xUIElement );
1898 if ( xUIElement.is() )
1900 uno::Reference< awt::XWindow > xWindow( xUIElement->getRealInterface(), uno::UNO_QUERY );
1901 uno::Reference< awt::XDockableWindow > xDockWindow( xWindow, uno::UNO_QUERY );
1902 if ( xDockWindow.is() )
1904 // docked windows
1905 aWindowVector.push_back( *pIter );
1910 aReadLock.unlock();
1911 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
1913 rRowColumnsWindowData.clear();
1915 // Collect data from windows that are on the same row/column
1916 sal_Int32 j;
1917 sal_Int32 nIndex( 0 );
1918 sal_Int32 nLastPos( 0 );
1919 sal_Int32 nCurrPos( -1 );
1920 sal_Int32 nLastRowColPixelPos( 0 );
1921 awt::Rectangle aDockAreaRect;
1923 if ( xDockAreaWindow.is() )
1924 aDockAreaRect = xDockAreaWindow->getPosSize();
1926 if ( eDockingArea == ui::DockingArea_DOCKINGAREA_TOP )
1927 nLastRowColPixelPos = 0;
1928 else if ( eDockingArea == ui::DockingArea_DOCKINGAREA_BOTTOM )
1929 nLastRowColPixelPos = aDockAreaRect.Height;
1930 else if ( eDockingArea == ui::DockingArea_DOCKINGAREA_LEFT )
1931 nLastRowColPixelPos = 0;
1932 else
1933 nLastRowColPixelPos = aDockAreaRect.Width;
1935 const sal_uInt32 nCount = aWindowVector.size();
1936 for ( j = 0; j < sal_Int32( nCount); j++ )
1938 const UIElement& rElement = aWindowVector[j];
1939 uno::Reference< awt::XWindow > xWindow;
1940 uno::Reference< ui::XUIElement > xUIElement( rElement.m_xUIElement );
1941 awt::Rectangle aPosSize;
1943 if ( !lcl_checkUIElement(xUIElement,aPosSize,xWindow) )
1944 continue;
1945 if ( isHorizontalDockingArea( eDockingArea ))
1947 if ( nCurrPos == -1 )
1949 nCurrPos = rElement.m_aDockedData.m_aPos.Y;
1950 nLastPos = 0;
1952 SingleRowColumnWindowData aRowColumnWindowData;
1953 aRowColumnWindowData.nRowColumn = nCurrPos;
1954 rRowColumnsWindowData.push_back( aRowColumnWindowData );
1957 sal_Int32 nSpace( 0 );
1958 if ( rElement.m_aDockedData.m_aPos.Y != nCurrPos )
1960 if ( eDockingArea == ui::DockingArea_DOCKINGAREA_TOP )
1961 nLastRowColPixelPos += rRowColumnsWindowData[nIndex].nStaticSize;
1962 else
1963 nLastRowColPixelPos -= rRowColumnsWindowData[nIndex].nStaticSize;
1964 ++nIndex;
1965 nLastPos = 0;
1966 nCurrPos = rElement.m_aDockedData.m_aPos.Y;
1967 SingleRowColumnWindowData aRowColumnWindowData;
1968 aRowColumnWindowData.nRowColumn = nCurrPos;
1969 rRowColumnsWindowData.push_back( aRowColumnWindowData );
1972 // Calc space before an element and store it
1973 nSpace = ( rElement.m_aDockedData.m_aPos.X - nLastPos );
1974 if ( rElement.m_aDockedData.m_aPos.X >= nLastPos )
1976 rRowColumnsWindowData[nIndex].nSpace += nSpace;
1977 nLastPos = rElement.m_aDockedData.m_aPos.X + aPosSize.Width;
1979 else
1981 nSpace = 0;
1982 nLastPos += aPosSize.Width;
1984 rRowColumnsWindowData[nIndex].aRowColumnSpace.push_back( nSpace );
1986 rRowColumnsWindowData[nIndex].aRowColumnWindows.push_back( xWindow );
1987 rRowColumnsWindowData[nIndex].aUIElementNames.push_back( rElement.m_aName );
1988 rRowColumnsWindowData[nIndex].aRowColumnWindowSizes.push_back(
1989 awt::Rectangle( rElement.m_aDockedData.m_aPos.X,
1990 rElement.m_aDockedData.m_aPos.Y,
1991 aPosSize.Width,
1992 aPosSize.Height ));
1993 if ( rRowColumnsWindowData[nIndex].nStaticSize < aPosSize.Height )
1994 rRowColumnsWindowData[nIndex].nStaticSize = aPosSize.Height;
1995 if ( eDockingArea == ui::DockingArea_DOCKINGAREA_TOP )
1996 rRowColumnsWindowData[nIndex].aRowColumnRect = awt::Rectangle( 0, nLastRowColPixelPos,
1997 aDockAreaRect.Width, aPosSize.Height );
1998 else
1999 rRowColumnsWindowData[nIndex].aRowColumnRect = awt::Rectangle( 0, ( nLastRowColPixelPos - aPosSize.Height ),
2000 aDockAreaRect.Width, aPosSize.Height );
2001 rRowColumnsWindowData[nIndex].nVarSize += aPosSize.Width + nSpace;
2003 else
2005 if ( nCurrPos == -1 )
2007 nCurrPos = rElement.m_aDockedData.m_aPos.X;
2008 nLastPos = 0;
2010 SingleRowColumnWindowData aRowColumnWindowData;
2011 aRowColumnWindowData.nRowColumn = nCurrPos;
2012 rRowColumnsWindowData.push_back( aRowColumnWindowData );
2015 sal_Int32 nSpace( 0 );
2016 if ( rElement.m_aDockedData.m_aPos.X != nCurrPos )
2018 if ( eDockingArea == ui::DockingArea_DOCKINGAREA_LEFT )
2019 nLastRowColPixelPos += rRowColumnsWindowData[nIndex].nStaticSize;
2020 else
2021 nLastRowColPixelPos -= rRowColumnsWindowData[nIndex].nStaticSize;
2022 ++nIndex;
2023 nLastPos = 0;
2024 nCurrPos = rElement.m_aDockedData.m_aPos.X;
2025 SingleRowColumnWindowData aRowColumnWindowData;
2026 aRowColumnWindowData.nRowColumn = nCurrPos;
2027 rRowColumnsWindowData.push_back( aRowColumnWindowData );
2030 // Calc space before an element and store it
2031 nSpace = ( rElement.m_aDockedData.m_aPos.Y - nLastPos );
2032 if ( rElement.m_aDockedData.m_aPos.Y > nLastPos )
2034 rRowColumnsWindowData[nIndex].nSpace += nSpace;
2035 nLastPos = rElement.m_aDockedData.m_aPos.Y + aPosSize.Height;
2037 else
2039 nSpace = 0;
2040 nLastPos += aPosSize.Height;
2042 rRowColumnsWindowData[nIndex].aRowColumnSpace.push_back( nSpace );
2044 rRowColumnsWindowData[nIndex].aRowColumnWindows.push_back( xWindow );
2045 rRowColumnsWindowData[nIndex].aUIElementNames.push_back( rElement.m_aName );
2046 rRowColumnsWindowData[nIndex].aRowColumnWindowSizes.push_back(
2047 awt::Rectangle( rElement.m_aDockedData.m_aPos.X,
2048 rElement.m_aDockedData.m_aPos.Y,
2049 aPosSize.Width,
2050 aPosSize.Height ));
2051 if ( rRowColumnsWindowData[nIndex].nStaticSize < aPosSize.Width )
2052 rRowColumnsWindowData[nIndex].nStaticSize = aPosSize.Width;
2053 if ( eDockingArea == ui::DockingArea_DOCKINGAREA_LEFT )
2054 rRowColumnsWindowData[nIndex].aRowColumnRect = awt::Rectangle( nLastRowColPixelPos, 0,
2055 aPosSize.Width, aDockAreaRect.Height );
2056 else
2057 rRowColumnsWindowData[nIndex].aRowColumnRect = awt::Rectangle( ( nLastRowColPixelPos - aPosSize.Width ), 0,
2058 aPosSize.Width, aDockAreaRect.Height );
2059 rRowColumnsWindowData[nIndex].nVarSize += aPosSize.Height + nSpace;
2064 void ToolbarLayoutManager::implts_getDockingAreaElementInfoOnSingleRowCol( ui::DockingArea eDockingArea, sal_Int32 nRowCol, SingleRowColumnWindowData& rRowColumnWindowData )
2066 std::vector< UIElement > aWindowVector;
2068 if (( eDockingArea < ui::DockingArea_DOCKINGAREA_TOP ) || ( eDockingArea > ui::DockingArea_DOCKINGAREA_RIGHT ))
2069 eDockingArea = ui::DockingArea_DOCKINGAREA_TOP;
2071 bool bHorzDockArea = isHorizontalDockingArea( eDockingArea );
2073 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
2074 ReadGuard aReadLock( m_aLock );
2075 UIElementVector::iterator pIter;
2076 UIElementVector::iterator pEnd = m_aUIElements.end();
2077 for ( pIter = m_aUIElements.begin(); pIter != pEnd; ++pIter )
2079 if ( pIter->m_aDockedData.m_nDockedArea == eDockingArea )
2081 bool bSameRowCol = bHorzDockArea ? ( pIter->m_aDockedData.m_aPos.Y == nRowCol ) : ( pIter->m_aDockedData.m_aPos.X == nRowCol );
2082 uno::Reference< ui::XUIElement > xUIElement( pIter->m_xUIElement );
2084 if ( bSameRowCol && xUIElement.is() )
2086 uno::Reference< awt::XWindow > xWindow( xUIElement->getRealInterface(), uno::UNO_QUERY );
2087 if ( xWindow.is() )
2089 SolarMutexGuard aGuard;
2090 Window* pWindow = VCLUnoHelper::GetWindow( xWindow );
2091 uno::Reference< awt::XDockableWindow > xDockWindow( xWindow, uno::UNO_QUERY );
2092 if ( pWindow && pIter->m_bVisible && xDockWindow.is() && !pIter->m_bFloating )
2093 aWindowVector.push_back( *pIter ); // docked windows
2098 aReadLock.unlock();
2099 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
2101 // Initialize structure
2102 rRowColumnWindowData.aUIElementNames.clear();
2103 rRowColumnWindowData.aRowColumnWindows.clear();
2104 rRowColumnWindowData.aRowColumnWindowSizes.clear();
2105 rRowColumnWindowData.aRowColumnSpace.clear();
2106 rRowColumnWindowData.nVarSize = 0;
2107 rRowColumnWindowData.nStaticSize = 0;
2108 rRowColumnWindowData.nSpace = 0;
2109 rRowColumnWindowData.nRowColumn = nRowCol;
2111 // Collect data from windows that are on the same row/column
2112 sal_Int32 j;
2113 sal_Int32 nLastPos( 0 );
2115 const sal_uInt32 nCount = aWindowVector.size();
2116 for ( j = 0; j < sal_Int32( nCount); j++ )
2118 const UIElement& rElement = aWindowVector[j];
2119 uno::Reference< awt::XWindow > xWindow;
2120 uno::Reference< ui::XUIElement > xUIElement( rElement.m_xUIElement );
2121 awt::Rectangle aPosSize;
2122 if ( !lcl_checkUIElement(xUIElement,aPosSize,xWindow) )
2123 continue;
2125 sal_Int32 nSpace;
2126 if ( isHorizontalDockingArea( eDockingArea ))
2128 nSpace = ( rElement.m_aDockedData.m_aPos.X - nLastPos );
2130 // Calc space before an element and store it
2131 if ( rElement.m_aDockedData.m_aPos.X > nLastPos )
2132 rRowColumnWindowData.nSpace += nSpace;
2133 else
2134 nSpace = 0;
2136 nLastPos = rElement.m_aDockedData.m_aPos.X + aPosSize.Width;
2139 rRowColumnWindowData.aRowColumnWindowSizes.push_back(
2140 awt::Rectangle( rElement.m_aDockedData.m_aPos.X, rElement.m_aDockedData.m_aPos.Y,
2141 aPosSize.Width, aPosSize.Height ));
2142 if ( rRowColumnWindowData.nStaticSize < aPosSize.Height )
2143 rRowColumnWindowData.nStaticSize = aPosSize.Height;
2144 rRowColumnWindowData.nVarSize += aPosSize.Width;
2146 else
2148 // Calc space before an element and store it
2149 nSpace = ( rElement.m_aDockedData.m_aPos.Y - nLastPos );
2150 if ( rElement.m_aDockedData.m_aPos.Y > nLastPos )
2151 rRowColumnWindowData.nSpace += nSpace;
2152 else
2153 nSpace = 0;
2155 nLastPos = rElement.m_aDockedData.m_aPos.Y + aPosSize.Height;
2157 rRowColumnWindowData.aRowColumnWindowSizes.push_back(
2158 awt::Rectangle( rElement.m_aDockedData.m_aPos.X, rElement.m_aDockedData.m_aPos.Y,
2159 aPosSize.Width, aPosSize.Height ));
2160 if ( rRowColumnWindowData.nStaticSize < aPosSize.Width )
2161 rRowColumnWindowData.nStaticSize = aPosSize.Width;
2162 rRowColumnWindowData.nVarSize += aPosSize.Height;
2165 rRowColumnWindowData.aUIElementNames.push_back( rElement.m_aName );
2166 rRowColumnWindowData.aRowColumnWindows.push_back( xWindow );
2167 rRowColumnWindowData.aRowColumnSpace.push_back( nSpace );
2168 rRowColumnWindowData.nVarSize += nSpace;
2172 ::Rectangle ToolbarLayoutManager::implts_getWindowRectFromRowColumn(
2173 ui::DockingArea DockingArea,
2174 const SingleRowColumnWindowData& rRowColumnWindowData,
2175 const ::Point& rMousePos,
2176 const OUString& rExcludeElementName )
2178 ::Rectangle aWinRect;
2180 if (( DockingArea < ui::DockingArea_DOCKINGAREA_TOP ) || ( DockingArea > ui::DockingArea_DOCKINGAREA_RIGHT ))
2181 DockingArea = ui::DockingArea_DOCKINGAREA_TOP;
2183 if ( rRowColumnWindowData.aRowColumnWindows.empty() )
2184 return aWinRect;
2185 else
2187 ReadGuard aReadLock( m_aLock );
2188 Window* pContainerWindow( VCLUnoHelper::GetWindow( m_xContainerWindow ));
2189 Window* pDockingAreaWindow( VCLUnoHelper::GetWindow( m_xDockAreaWindows[DockingArea] ));
2190 aReadLock.unlock();
2192 // Calc correct position of the column/row rectangle to be able to compare it with mouse pos/tracking rect
2193 SolarMutexGuard aGuard;
2195 // Retrieve output size from container Window
2196 if ( pDockingAreaWindow && pContainerWindow )
2198 const sal_uInt32 nCount = rRowColumnWindowData.aRowColumnWindows.size();
2199 for ( sal_uInt32 i = 0; i < nCount; i++ )
2201 awt::Rectangle aWindowRect = rRowColumnWindowData.aRowColumnWindows[i]->getPosSize();
2202 ::Rectangle aRect( aWindowRect.X, aWindowRect.Y, aWindowRect.X+aWindowRect.Width, aWindowRect.Y+aWindowRect.Height );
2203 aRect.SetPos( pContainerWindow->ScreenToOutputPixel( pDockingAreaWindow->OutputToScreenPixel( aRect.TopLeft() )));
2204 if ( aRect.IsInside( rMousePos ))
2206 // Check if we have found the excluded element. If yes, we have to provide an empty rectangle.
2207 // We prevent that a toolbar cannot be moved when the mouse pointer is inside its own rectangle!
2208 if ( rExcludeElementName != rRowColumnWindowData.aUIElementNames[i] )
2209 return aRect;
2210 else
2211 break;
2217 return aWinRect;
2220 ::Rectangle ToolbarLayoutManager::implts_determineFrontDockingRect(
2221 ui::DockingArea eDockingArea,
2222 sal_Int32 nRowCol,
2223 const ::Rectangle& rDockedElementRect,
2224 const OUString& rMovedElementName,
2225 const ::Rectangle& rMovedElementRect )
2227 SingleRowColumnWindowData aRowColumnWindowData;
2229 sal_Bool bHorzDockArea( isHorizontalDockingArea( eDockingArea ));
2230 implts_getDockingAreaElementInfoOnSingleRowCol( eDockingArea, nRowCol, aRowColumnWindowData );
2231 if ( aRowColumnWindowData.aRowColumnWindows.empty() )
2232 return rMovedElementRect;
2233 else
2235 sal_Int32 nSpace( 0 );
2236 ::Rectangle aFrontDockingRect( rMovedElementRect );
2237 const sal_uInt32 nCount = aRowColumnWindowData.aRowColumnWindows.size();
2238 for ( sal_uInt32 i = 0; i < nCount; i++ )
2240 if ( bHorzDockArea )
2242 if ( aRowColumnWindowData.aRowColumnWindowSizes[i].X >= rDockedElementRect.Left() )
2244 nSpace += aRowColumnWindowData.aRowColumnSpace[i];
2245 break;
2247 else if ( aRowColumnWindowData.aUIElementNames[i] == rMovedElementName )
2248 nSpace += aRowColumnWindowData.aRowColumnWindowSizes[i].Width +
2249 aRowColumnWindowData.aRowColumnSpace[i];
2250 else
2251 nSpace = 0;
2253 else
2255 if ( aRowColumnWindowData.aRowColumnWindowSizes[i].Y >= rDockedElementRect.Top() )
2257 nSpace += aRowColumnWindowData.aRowColumnSpace[i];
2258 break;
2260 else if ( aRowColumnWindowData.aUIElementNames[i] == rMovedElementName )
2261 nSpace += aRowColumnWindowData.aRowColumnWindowSizes[i].Height +
2262 aRowColumnWindowData.aRowColumnSpace[i];
2263 else
2264 nSpace = 0;
2268 if ( nSpace > 0 )
2270 sal_Int32 nMove = std::min( nSpace, static_cast<sal_Int32>(aFrontDockingRect.getWidth()) );
2271 if ( bHorzDockArea )
2272 aFrontDockingRect.Move( -nMove, 0 );
2273 else
2274 aFrontDockingRect.Move( 0, -nMove );
2277 return aFrontDockingRect;
2281 void ToolbarLayoutManager::implts_findNextDockingPos( ui::DockingArea DockingArea, const ::Size& aUIElementSize, awt::Point& rVirtualPos, ::Point& rPixelPos )
2283 ReadGuard aReadLock( m_aLock );
2284 uno::Reference< awt::XWindow > xDockingWindow( m_xDockAreaWindows[DockingArea] );
2285 ::Size aDockingWinSize;
2286 Window* pDockingWindow( 0 );
2287 aReadLock.unlock();
2289 if (( DockingArea < ui::DockingArea_DOCKINGAREA_TOP ) || ( DockingArea > ui::DockingArea_DOCKINGAREA_RIGHT ))
2290 DockingArea = ui::DockingArea_DOCKINGAREA_TOP;
2293 // Retrieve output size from container Window
2294 SolarMutexGuard aGuard;
2295 pDockingWindow = VCLUnoHelper::GetWindow( xDockingWindow );
2296 if ( pDockingWindow )
2297 aDockingWinSize = pDockingWindow->GetOutputSizePixel();
2300 sal_Int32 nFreeRowColPixelPos( 0 );
2301 sal_Int32 nMaxSpace( 0 );
2302 sal_Int32 nNeededSpace( 0 );
2303 sal_Int32 nTopDockingAreaSize( 0 );
2305 if ( isHorizontalDockingArea( DockingArea ))
2307 nMaxSpace = aDockingWinSize.Width();
2308 nNeededSpace = aUIElementSize.Width();
2310 else
2312 nMaxSpace = aDockingWinSize.Height();
2313 nNeededSpace = aUIElementSize.Height();
2314 nTopDockingAreaSize = implts_getTopBottomDockingAreaSizes().Width();
2317 std::vector< SingleRowColumnWindowData > aRowColumnsWindowData;
2319 implts_getDockingAreaElementInfos( DockingArea, aRowColumnsWindowData );
2320 sal_Int32 nPixelPos( 0 );
2321 const sal_uInt32 nCount = aRowColumnsWindowData.size();
2322 for ( sal_uInt32 i = 0; i < nCount; i++ )
2324 SingleRowColumnWindowData& rRowColumnWindowData = aRowColumnsWindowData[i];
2326 if (( DockingArea == ui::DockingArea_DOCKINGAREA_BOTTOM ) ||
2327 ( DockingArea == ui::DockingArea_DOCKINGAREA_RIGHT ))
2328 nPixelPos += rRowColumnWindowData.nStaticSize;
2330 if ((( nMaxSpace - rRowColumnWindowData.nVarSize ) >= nNeededSpace ) ||
2331 ( rRowColumnWindowData.nSpace >= nNeededSpace ))
2333 // Check current row where we can find the needed space
2334 sal_Int32 nCurrPos( 0 );
2335 const sal_uInt32 nWindowSizesCount = rRowColumnWindowData.aRowColumnWindowSizes.size();
2336 for ( sal_uInt32 j = 0; j < nWindowSizesCount; j++ )
2338 awt::Rectangle rRect = rRowColumnWindowData.aRowColumnWindowSizes[j];
2339 sal_Int32& rSpace = rRowColumnWindowData.aRowColumnSpace[j];
2340 if ( isHorizontalDockingArea( DockingArea ))
2342 if ( rSpace >= nNeededSpace )
2344 rVirtualPos = awt::Point( nCurrPos, rRowColumnWindowData.nRowColumn );
2345 if ( DockingArea == ui::DockingArea_DOCKINGAREA_TOP )
2346 rPixelPos = ::Point( nCurrPos, nPixelPos );
2347 else
2348 rPixelPos = ::Point( nCurrPos, aDockingWinSize.Height() - nPixelPos );
2349 return;
2351 nCurrPos = rRect.X + rRect.Width;
2353 else
2355 if ( rSpace >= nNeededSpace )
2357 rVirtualPos = awt::Point( rRowColumnWindowData.nRowColumn, nCurrPos );
2358 if ( DockingArea == ui::DockingArea_DOCKINGAREA_LEFT )
2359 rPixelPos = ::Point( nPixelPos, nTopDockingAreaSize + nCurrPos );
2360 else
2361 rPixelPos = ::Point( aDockingWinSize.Width() - nPixelPos , nTopDockingAreaSize + nCurrPos );
2362 return;
2364 nCurrPos = rRect.Y + rRect.Height;
2368 if (( nCurrPos + nNeededSpace ) <= nMaxSpace )
2370 if ( isHorizontalDockingArea( DockingArea ))
2372 rVirtualPos = awt::Point( nCurrPos, rRowColumnWindowData.nRowColumn );
2373 if ( DockingArea == ui::DockingArea_DOCKINGAREA_TOP )
2374 rPixelPos = ::Point( nCurrPos, nPixelPos );
2375 else
2376 rPixelPos = ::Point( nCurrPos, aDockingWinSize.Height() - nPixelPos );
2377 return;
2379 else
2381 rVirtualPos = awt::Point( rRowColumnWindowData.nRowColumn, nCurrPos );
2382 if ( DockingArea == ui::DockingArea_DOCKINGAREA_LEFT )
2383 rPixelPos = ::Point( nPixelPos, nTopDockingAreaSize + nCurrPos );
2384 else
2385 rPixelPos = ::Point( aDockingWinSize.Width() - nPixelPos , nTopDockingAreaSize + nCurrPos );
2386 return;
2391 if (( DockingArea == ui::DockingArea_DOCKINGAREA_TOP ) || ( DockingArea == ui::DockingArea_DOCKINGAREA_LEFT ))
2392 nPixelPos += rRowColumnWindowData.nStaticSize;
2395 sal_Int32 nNextFreeRowCol( 0 );
2396 sal_Int32 nRowColumnsCount = aRowColumnsWindowData.size();
2397 if ( nRowColumnsCount > 0 )
2398 nNextFreeRowCol = aRowColumnsWindowData[nRowColumnsCount-1].nRowColumn+1;
2399 else
2400 nNextFreeRowCol = 0;
2402 if ( nNextFreeRowCol == 0 )
2404 if ( DockingArea == ui::DockingArea_DOCKINGAREA_BOTTOM )
2405 nFreeRowColPixelPos = aDockingWinSize.Height() - aUIElementSize.Height();
2406 else if ( DockingArea == ui::DockingArea_DOCKINGAREA_RIGHT )
2407 nFreeRowColPixelPos = aDockingWinSize.Width() - aUIElementSize.Width();
2410 if ( isHorizontalDockingArea( DockingArea ))
2412 rVirtualPos = awt::Point( 0, nNextFreeRowCol );
2413 if ( DockingArea == ui::DockingArea_DOCKINGAREA_TOP )
2414 rPixelPos = ::Point( 0, nFreeRowColPixelPos );
2415 else
2416 rPixelPos = ::Point( 0, aDockingWinSize.Height() - nFreeRowColPixelPos );
2418 else
2420 rVirtualPos = awt::Point( nNextFreeRowCol, 0 );
2421 rPixelPos = ::Point( aDockingWinSize.Width() - nFreeRowColPixelPos, 0 );
2425 void ToolbarLayoutManager::implts_calcWindowPosSizeOnSingleRowColumn(
2426 sal_Int32 nDockingArea,
2427 sal_Int32 nOffset,
2428 SingleRowColumnWindowData& rRowColumnWindowData,
2429 const ::Size& rContainerSize )
2431 sal_Int32 nDiff(0);
2432 sal_Int32 nRCSpace( rRowColumnWindowData.nSpace );
2433 sal_Int32 nTopDockingAreaSize(0);
2434 sal_Int32 nBottomDockingAreaSize(0);
2435 sal_Int32 nContainerClientSize(0);
2437 if ( rRowColumnWindowData.aRowColumnWindows.empty() )
2438 return;
2440 if ( isHorizontalDockingArea( nDockingArea ))
2442 nContainerClientSize = rContainerSize.Width();
2443 nDiff = nContainerClientSize - rRowColumnWindowData.nVarSize;
2445 else
2447 nTopDockingAreaSize = implts_getTopBottomDockingAreaSizes().Width();
2448 nBottomDockingAreaSize = implts_getTopBottomDockingAreaSizes().Height();
2449 nContainerClientSize = ( rContainerSize.Height() - nTopDockingAreaSize - nBottomDockingAreaSize );
2450 nDiff = nContainerClientSize - rRowColumnWindowData.nVarSize;
2453 const sal_uInt32 nCount = rRowColumnWindowData.aRowColumnWindowSizes.size();
2454 if (( nDiff < 0 ) && ( nRCSpace > 0 ))
2456 // First we try to reduce the size of blank space before/behind docked windows
2457 sal_Int32 i = nCount - 1;
2458 while ( i >= 0 )
2460 sal_Int32 nSpace = rRowColumnWindowData.aRowColumnSpace[i];
2461 if ( nSpace >= -nDiff )
2463 if ( isHorizontalDockingArea( nDockingArea ))
2465 // Try to move this and all user elements behind with the calculated difference
2466 for ( sal_uInt32 j = i; j < nCount ; j++ )
2467 rRowColumnWindowData.aRowColumnWindowSizes[j].X += nDiff;
2469 else
2471 // Try to move this and all user elements behind with the calculated difference
2472 for ( sal_uInt32 j = i; j < nCount ; j++ )
2473 rRowColumnWindowData.aRowColumnWindowSizes[j].Y += nDiff;
2475 nDiff = 0;
2477 break;
2479 else if ( nSpace > 0 )
2481 if ( isHorizontalDockingArea( nDockingArea ))
2483 // Try to move this and all user elements behind with the calculated difference
2484 for ( sal_uInt32 j = i; j < nCount; j++ )
2485 rRowColumnWindowData.aRowColumnWindowSizes[j].X -= nSpace;
2487 else
2489 // Try to move this and all user elements behind with the calculated difference
2490 for ( sal_uInt32 j = i; j < nCount; j++ )
2491 rRowColumnWindowData.aRowColumnWindowSizes[j].Y -= nSpace;
2493 nDiff += nSpace;
2495 --i;
2499 // Check if we have to reduce further
2500 if ( nDiff < 0 )
2502 // Now we have to reduce the size of certain docked windows
2503 sal_Int32 i = sal_Int32( nCount - 1 );
2504 while ( i >= 0 )
2506 awt::Rectangle& rWinRect = rRowColumnWindowData.aRowColumnWindowSizes[i];
2507 ::Size aMinSize;
2509 SolarMutexGuard aGuard;
2511 uno::Reference< awt::XWindow > xWindow = rRowColumnWindowData.aRowColumnWindows[i];
2512 Window* pWindow = VCLUnoHelper::GetWindow( xWindow );
2513 if ( pWindow && pWindow->GetType() == WINDOW_TOOLBOX )
2514 aMinSize = ((ToolBox *)pWindow)->CalcMinimumWindowSizePixel();
2517 if (( aMinSize.Width() > 0 ) && ( aMinSize.Height() > 0 ))
2519 if ( isHorizontalDockingArea( nDockingArea ))
2521 sal_Int32 nMaxReducation = ( rWinRect.Width - aMinSize.Width() );
2522 if ( nMaxReducation >= -nDiff )
2524 rWinRect.Width = rWinRect.Width + nDiff;
2525 nDiff = 0;
2527 else
2529 rWinRect.Width = aMinSize.Width();
2530 nDiff += nMaxReducation;
2533 // Try to move this and all user elements behind with the calculated difference
2534 for ( sal_uInt32 j = i; j < nCount; j++ )
2535 rRowColumnWindowData.aRowColumnWindowSizes[j].X += nDiff;
2537 else
2539 sal_Int32 nMaxReducation = ( rWinRect.Height - aMinSize.Height() );
2540 if ( nMaxReducation >= -nDiff )
2542 rWinRect.Height = rWinRect.Height + nDiff;
2543 nDiff = 0;
2545 else
2547 rWinRect.Height = aMinSize.Height();
2548 nDiff += nMaxReducation;
2551 // Try to move this and all user elements behind with the calculated difference
2552 for ( sal_uInt32 j = i; j < nCount; j++ )
2553 rRowColumnWindowData.aRowColumnWindowSizes[j].Y += nDiff;
2557 if ( nDiff >= 0 )
2558 break;
2560 --i;
2564 ReadGuard aReadLock( m_aLock );
2565 Window* pDockAreaWindow = VCLUnoHelper::GetWindow( m_xDockAreaWindows[nDockingArea] );
2566 aReadLock.unlock();
2568 sal_Int32 nCurrPos( 0 );
2570 SolarMutexGuard aGuard;
2571 for ( sal_uInt32 i = 0; i < nCount; i++ )
2573 uno::Reference< awt::XWindow > xWindow = rRowColumnWindowData.aRowColumnWindows[i];
2574 Window* pWindow = VCLUnoHelper::GetWindow( xWindow );
2575 Window* pOldParentWindow = pWindow->GetParent();
2577 if ( pDockAreaWindow != pOldParentWindow )
2578 pWindow->SetParent( pDockAreaWindow );
2580 awt::Rectangle aWinRect = rRowColumnWindowData.aRowColumnWindowSizes[i];
2581 if ( isHorizontalDockingArea( nDockingArea ))
2583 if ( aWinRect.X < nCurrPos )
2584 aWinRect.X = nCurrPos;
2585 pWindow->SetPosSizePixel( ::Point( aWinRect.X, nOffset ), ::Size( aWinRect.Width, rRowColumnWindowData.nStaticSize ));
2586 pWindow->Show( sal_True, SHOW_NOFOCUSCHANGE | SHOW_NOACTIVATE );
2587 nCurrPos += ( aWinRect.X - nCurrPos ) + aWinRect.Width;
2589 else
2591 if ( aWinRect.Y < nCurrPos )
2592 aWinRect.Y = nCurrPos;
2593 pWindow->SetPosSizePixel( ::Point( nOffset, aWinRect.Y ), ::Size( rRowColumnWindowData.nStaticSize, aWinRect.Height ));
2594 pWindow->Show( sal_True, SHOW_NOFOCUSCHANGE | SHOW_NOACTIVATE );
2595 nCurrPos += ( aWinRect.Y - nCurrPos ) + aWinRect.Height;
2600 void ToolbarLayoutManager::implts_setLayoutDirty()
2602 WriteGuard aWriteLock( m_aLock );
2603 m_bLayoutDirty = true;
2606 void ToolbarLayoutManager::implts_setLayoutInProgress( bool bInProgress )
2608 WriteGuard aWriteLock( m_aLock );
2609 m_bLayoutInProgress = bInProgress;
2612 ::Rectangle ToolbarLayoutManager::implts_calcHotZoneRect( const ::Rectangle& rRect, sal_Int32 nHotZoneOffset )
2614 ::Rectangle aRect( rRect );
2616 aRect.Left() -= nHotZoneOffset;
2617 aRect.Top() -= nHotZoneOffset;
2618 aRect.Right() += nHotZoneOffset;
2619 aRect.Bottom() += nHotZoneOffset;
2621 return aRect;
2624 void ToolbarLayoutManager::implts_calcDockingPosSize(
2625 UIElement& rUIElement,
2626 DockingOperation& rDockingOperation,
2627 ::Rectangle& rTrackingRect,
2628 const Point& rMousePos )
2630 ReadGuard aReadLock( m_aLock );
2631 uno::Reference< awt::XWindow2 > xContainerWindow( m_xContainerWindow );
2632 ::Size aContainerWinSize;
2633 Window* pContainerWindow( 0 );
2634 ::Rectangle aDockingAreaOffsets( m_aDockingAreaOffsets );
2635 aReadLock.unlock();
2637 if ( !rUIElement.m_xUIElement.is() )
2639 rTrackingRect = ::Rectangle();
2640 return;
2644 // Retrieve output size from container Window
2645 SolarMutexGuard aGuard;
2646 pContainerWindow = VCLUnoHelper::GetWindow( xContainerWindow );
2647 aContainerWinSize = pContainerWindow->GetOutputSizePixel();
2650 Window* pDockWindow( 0 );
2651 Window* pDockingAreaWindow( 0 );
2652 ToolBox* pToolBox( 0 );
2653 uno::Reference< awt::XWindow > xWindow( rUIElement.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
2654 uno::Reference< awt::XWindow > xDockingAreaWindow;
2655 ::Rectangle aTrackingRect( rTrackingRect );
2656 ui::DockingArea eDockedArea( (ui::DockingArea)rUIElement.m_aDockedData.m_nDockedArea );
2657 sal_Int32 nTopDockingAreaSize( implts_getTopBottomDockingAreaSizes().Width() );
2658 sal_Int32 nBottomDockingAreaSize( implts_getTopBottomDockingAreaSizes().Height() );
2659 bool bHorizontalDockArea(( eDockedArea == ui::DockingArea_DOCKINGAREA_TOP ) ||
2660 ( eDockedArea == ui::DockingArea_DOCKINGAREA_BOTTOM ));
2661 sal_Int32 nMaxLeftRightDockAreaSize = aContainerWinSize.Height() -
2662 nTopDockingAreaSize -
2663 nBottomDockingAreaSize -
2664 aDockingAreaOffsets.Top() -
2665 aDockingAreaOffsets.Bottom();
2666 ::Rectangle aDockingAreaRect;
2668 aReadLock.lock();
2669 xDockingAreaWindow = m_xDockAreaWindows[eDockedArea];
2670 aReadLock.unlock();
2673 SolarMutexGuard aGuard;
2674 pDockingAreaWindow = VCLUnoHelper::GetWindow( xDockingAreaWindow );
2675 pDockWindow = VCLUnoHelper::GetWindow( xWindow );
2676 if ( pDockWindow && pDockWindow->GetType() == WINDOW_TOOLBOX )
2677 pToolBox = (ToolBox *)pDockWindow;
2679 aDockingAreaRect = ::Rectangle( pDockingAreaWindow->GetPosPixel(), pDockingAreaWindow->GetSizePixel() );
2680 if ( pToolBox )
2682 // docked toolbars always have one line
2683 ::Size aSize = pToolBox->CalcWindowSizePixel( 1, ImplConvertAlignment( sal_Int16( eDockedArea )) );
2684 aTrackingRect.SetSize( ::Size( aSize.Width(), aSize.Height() ));
2688 // default docking operation, dock on the given row/column
2689 bool bOpOutsideOfDockingArea( !aDockingAreaRect.IsInside( rMousePos ));
2691 std::vector< SingleRowColumnWindowData > aRowColumnsWindowData;
2693 rDockingOperation = DOCKOP_ON_COLROW;
2694 implts_getDockingAreaElementInfos( eDockedArea, aRowColumnsWindowData );
2696 // determine current first row/column and last row/column
2697 sal_Int32 nMaxRowCol( -1 );
2698 sal_Int32 nMinRowCol( SAL_MAX_INT32 );
2699 const sal_uInt32 nCount = aRowColumnsWindowData.size();
2700 for ( sal_uInt32 i = 0; i < nCount; i++ )
2702 if ( aRowColumnsWindowData[i].nRowColumn > nMaxRowCol )
2703 nMaxRowCol = aRowColumnsWindowData[i].nRowColumn;
2704 if ( aRowColumnsWindowData[i].nRowColumn < nMinRowCol )
2705 nMinRowCol = aRowColumnsWindowData[i].nRowColumn;
2708 if ( !bOpOutsideOfDockingArea )
2710 // docking inside our docking area
2711 sal_Int32 nIndex( -1 );
2712 sal_Int32 nRowCol( -1 );
2713 ::Rectangle aWindowRect;
2714 ::Rectangle aRowColumnRect;
2716 const sal_uInt32 nWindowDataCount = aRowColumnsWindowData.size();
2717 for ( sal_uInt32 i = 0; i < nWindowDataCount; i++ )
2719 ::Rectangle aRect( aRowColumnsWindowData[i].aRowColumnRect.X,
2720 aRowColumnsWindowData[i].aRowColumnRect.Y,
2721 aRowColumnsWindowData[i].aRowColumnRect.X + aRowColumnsWindowData[i].aRowColumnRect.Width,
2722 aRowColumnsWindowData[i].aRowColumnRect.Y + aRowColumnsWindowData[i].aRowColumnRect.Height );
2725 // Calc correct position of the column/row rectangle to be able to compare it with mouse pos/tracking rect
2726 SolarMutexGuard aGuard;
2727 aRect.SetPos( pContainerWindow->ScreenToOutputPixel( pDockingAreaWindow->OutputToScreenPixel( aRect.TopLeft() )));
2730 bool bIsInsideRowCol( aRect.IsInside( rMousePos ) );
2731 if ( bIsInsideRowCol )
2733 nIndex = i;
2734 nRowCol = aRowColumnsWindowData[i].nRowColumn;
2735 rDockingOperation = implts_determineDockingOperation( eDockedArea, aRect, rMousePos );
2736 aWindowRect = implts_getWindowRectFromRowColumn( eDockedArea, aRowColumnsWindowData[i], rMousePos, rUIElement.m_aName );
2737 aRowColumnRect = aRect;
2738 break;
2742 OSL_ENSURE( ( nIndex >= 0 ) && ( nRowCol >= 0 ), "Impossible case - no row/column found but mouse pointer is inside our docking area" );
2743 if (( nIndex >= 0 ) && ( nRowCol >= 0 ))
2745 if ( rDockingOperation == DOCKOP_ON_COLROW )
2747 if ( !aWindowRect.IsEmpty())
2749 // Tracking rect is on a row/column and mouse is over a docked toolbar.
2750 // Determine if the tracking rect must be located before/after the docked toolbar.
2752 ::Rectangle aUIElementRect( aWindowRect );
2753 sal_Int32 nMiddle( bHorizontalDockArea ? ( aWindowRect.Left() + aWindowRect.getWidth() / 2 ) :
2754 ( aWindowRect.Top() + aWindowRect.getHeight() / 2 ));
2755 sal_Bool bInsertBefore( bHorizontalDockArea ? ( rMousePos.X() < nMiddle ) : ( rMousePos.Y() < nMiddle ));
2756 if ( bInsertBefore )
2758 if ( bHorizontalDockArea )
2760 sal_Int32 nSize = ::std::max( sal_Int32( 0 ), std::min( sal_Int32( aContainerWinSize.Width() - aWindowRect.Left() ),
2761 sal_Int32( aTrackingRect.getWidth() )));
2762 if ( nSize == 0 )
2763 nSize = aWindowRect.getWidth();
2765 aUIElementRect.SetSize( ::Size( nSize, aWindowRect.getHeight() ));
2766 aWindowRect = implts_determineFrontDockingRect( eDockedArea, nRowCol, aWindowRect,rUIElement.m_aName, aUIElementRect );
2768 // Set virtual position
2769 rUIElement.m_aDockedData.m_aPos.X = aWindowRect.Left();
2770 rUIElement.m_aDockedData.m_aPos.Y = nRowCol;
2772 else
2774 sal_Int32 nSize = ::std::max( sal_Int32( 0 ), std::min( sal_Int32(
2775 nTopDockingAreaSize + nMaxLeftRightDockAreaSize - aWindowRect.Top() ),
2776 sal_Int32( aTrackingRect.getHeight() )));
2777 if ( nSize == 0 )
2778 nSize = aWindowRect.getHeight();
2780 aUIElementRect.SetSize( ::Size( aWindowRect.getWidth(), nSize ));
2781 aWindowRect = implts_determineFrontDockingRect( eDockedArea, nRowCol, aWindowRect, rUIElement.m_aName, aUIElementRect );
2783 // Set virtual position
2784 sal_Int32 nPosY = pDockingAreaWindow->ScreenToOutputPixel(
2785 pContainerWindow->OutputToScreenPixel( aWindowRect.TopLeft() )).Y();
2786 rUIElement.m_aDockedData.m_aPos.X = nRowCol;
2787 rUIElement.m_aDockedData.m_aPos.Y = nPosY;
2790 rTrackingRect = aWindowRect;
2791 return;
2793 else
2795 if ( bHorizontalDockArea )
2797 sal_Int32 nSize = ::std::max( sal_Int32( 0 ), std::min( sal_Int32(( aContainerWinSize.Width() ) - aWindowRect.Right() ),
2798 sal_Int32( aTrackingRect.getWidth() )));
2799 if ( nSize == 0 )
2801 aUIElementRect.SetPos( ::Point( aContainerWinSize.Width() - aTrackingRect.getWidth(), aWindowRect.Top() ));
2802 aUIElementRect.SetSize( ::Size( aTrackingRect.getWidth(), aWindowRect.getHeight() ));
2803 rUIElement.m_aDockedData.m_aPos.X = aUIElementRect.Left();
2806 else
2808 aUIElementRect.SetPos( ::Point( aWindowRect.Right(), aWindowRect.Top() ));
2809 aUIElementRect.SetSize( ::Size( nSize, aWindowRect.getHeight() ));
2810 rUIElement.m_aDockedData.m_aPos.X = aWindowRect.Right();
2813 // Set virtual position
2814 rUIElement.m_aDockedData.m_aPos.Y = nRowCol;
2816 else
2818 sal_Int32 nSize = ::std::max( sal_Int32( 0 ), std::min( sal_Int32( nTopDockingAreaSize + nMaxLeftRightDockAreaSize - aWindowRect.Bottom() ),
2819 sal_Int32( aTrackingRect.getHeight() )));
2820 aUIElementRect.SetPos( ::Point( aWindowRect.Left(), aWindowRect.Bottom() ));
2821 aUIElementRect.SetSize( ::Size( aWindowRect.getWidth(), nSize ));
2823 // Set virtual position
2824 sal_Int32 nPosY( 0 );
2826 SolarMutexGuard aGuard;
2827 nPosY = pDockingAreaWindow->ScreenToOutputPixel(
2828 pContainerWindow->OutputToScreenPixel( aWindowRect.BottomRight() )).Y();
2830 rUIElement.m_aDockedData.m_aPos.X = nRowCol;
2831 rUIElement.m_aDockedData.m_aPos.Y = nPosY;
2834 rTrackingRect = aUIElementRect;
2835 return;
2838 else
2840 implts_setTrackingRect( eDockedArea, rMousePos, aTrackingRect );
2841 rTrackingRect = implts_calcTrackingAndElementRect(
2842 eDockedArea, nRowCol, rUIElement,
2843 aTrackingRect, aRowColumnRect, aContainerWinSize );
2844 return;
2847 else
2849 if ((( nRowCol == nMinRowCol ) && ( rDockingOperation == DOCKOP_BEFORE_COLROW )) ||
2850 (( nRowCol == nMaxRowCol ) && ( rDockingOperation == DOCKOP_AFTER_COLROW )))
2851 bOpOutsideOfDockingArea = true;
2852 else
2854 // handle docking before/after a row
2855 implts_setTrackingRect( eDockedArea, rMousePos, aTrackingRect );
2856 rTrackingRect = implts_calcTrackingAndElementRect(
2857 eDockedArea, nRowCol, rUIElement,
2858 aTrackingRect, aRowColumnRect, aContainerWinSize );
2860 sal_Int32 nOffsetX( 0 );
2861 sal_Int32 nOffsetY( 0 );
2862 if ( bHorizontalDockArea )
2863 nOffsetY = sal_Int32( floor( aRowColumnRect.getHeight() / 2 + 0.5 ));
2864 else
2865 nOffsetX = sal_Int32( floor( aRowColumnRect.getWidth() / 2 + 0.5 ));
2867 if ( rDockingOperation == DOCKOP_BEFORE_COLROW )
2869 if (( eDockedArea == ui::DockingArea_DOCKINGAREA_TOP ) || ( eDockedArea == ui::DockingArea_DOCKINGAREA_LEFT ))
2871 // Docking before/after means move track rectangle half column/row.
2872 // As left and top are ordered 0...n instead of right and bottom
2873 // which uses n...0, we have to use negative values for top/left.
2874 nOffsetX *= -1;
2875 nOffsetY *= -1;
2878 else
2880 if (( eDockedArea == ui::DockingArea_DOCKINGAREA_BOTTOM ) || ( eDockedArea == ui::DockingArea_DOCKINGAREA_RIGHT ))
2882 // Docking before/after means move track rectangle half column/row.
2883 // As left and top are ordered 0...n instead of right and bottom
2884 // which uses n...0, we have to use negative values for top/left.
2885 nOffsetX *= -1;
2886 nOffsetY *= -1;
2888 nRowCol++;
2891 if ( bHorizontalDockArea )
2892 rUIElement.m_aDockedData.m_aPos.Y = nRowCol;
2893 else
2894 rUIElement.m_aDockedData.m_aPos.X = nRowCol;
2896 rTrackingRect.Move( nOffsetX, nOffsetY );
2897 rTrackingRect.SetSize( aTrackingRect.GetSize() );
2903 // Docking outside of our docking window area =>
2904 // Users want to dock before/after first/last docked element or to an empty docking area
2905 if ( bOpOutsideOfDockingArea )
2907 // set correct size for docking
2908 implts_setTrackingRect( eDockedArea, rMousePos, aTrackingRect );
2909 rTrackingRect = aTrackingRect;
2911 if ( bHorizontalDockArea )
2913 sal_Int32 nPosX( std::max( sal_Int32( rTrackingRect.Left()), sal_Int32( 0 )));
2914 if (( nPosX + rTrackingRect.getWidth()) > aContainerWinSize.Width() )
2915 nPosX = std::min( nPosX,
2916 std::max( sal_Int32( aContainerWinSize.Width() - rTrackingRect.getWidth() ),
2917 sal_Int32( 0 )));
2919 sal_Int32 nSize = std::min( aContainerWinSize.Width(), rTrackingRect.getWidth() );
2920 sal_Int32 nDockHeight = std::max( static_cast<sal_Int32>(aDockingAreaRect.getHeight()), sal_Int32( 0 ));
2921 if ( nDockHeight == 0 )
2923 sal_Int32 nPosY( std::max( aDockingAreaRect.Top(), aDockingAreaRect.Bottom() ));
2924 if ( eDockedArea == ui::DockingArea_DOCKINGAREA_BOTTOM )
2925 nPosY -= rTrackingRect.getHeight();
2926 rTrackingRect.SetPos( Point( nPosX, nPosY ));
2927 rUIElement.m_aDockedData.m_aPos.Y = 0;
2929 else if ( rMousePos.Y() < ( aDockingAreaRect.Top() + ( nDockHeight / 2 )))
2931 rTrackingRect.SetPos( Point( nPosX, aDockingAreaRect.Top() - rTrackingRect.getHeight() ));
2932 if ( eDockedArea == ui::DockingArea_DOCKINGAREA_TOP )
2933 rUIElement.m_aDockedData.m_aPos.Y = 0;
2934 else
2935 rUIElement.m_aDockedData.m_aPos.Y = ( nMaxRowCol >= 0 ) ? nMaxRowCol+1 : 0;
2936 rDockingOperation = DOCKOP_BEFORE_COLROW;
2938 else
2940 rTrackingRect.SetPos( Point( nPosX, aDockingAreaRect.Bottom() ));
2941 if ( eDockedArea == ui::DockingArea_DOCKINGAREA_TOP )
2942 rUIElement.m_aDockedData.m_aPos.Y = ( nMaxRowCol >= 0 ) ? nMaxRowCol+1 : 0;
2943 else
2944 rUIElement.m_aDockedData.m_aPos.Y = 0;
2945 rDockingOperation = DOCKOP_AFTER_COLROW;
2947 rTrackingRect.setWidth( nSize );
2950 SolarMutexGuard aGuard;
2951 nPosX = pDockingAreaWindow->ScreenToOutputPixel(
2952 pContainerWindow->OutputToScreenPixel( rTrackingRect.TopLeft() )).X();
2954 rUIElement.m_aDockedData.m_aPos.X = nPosX;
2956 else
2958 sal_Int32 nMaxDockingAreaHeight = std::max( sal_Int32( 0 ), sal_Int32( nMaxLeftRightDockAreaSize ));
2959 sal_Int32 nPosY( std::max( sal_Int32( aTrackingRect.Top()), sal_Int32( nTopDockingAreaSize )));
2960 if (( nPosY + aTrackingRect.getHeight()) > ( nTopDockingAreaSize + nMaxDockingAreaHeight ))
2961 nPosY = std::min( nPosY,
2962 std::max( sal_Int32( nTopDockingAreaSize + ( nMaxDockingAreaHeight - aTrackingRect.getHeight() )),
2963 sal_Int32( nTopDockingAreaSize )));
2965 sal_Int32 nSize = std::min( nMaxDockingAreaHeight, static_cast<sal_Int32>(aTrackingRect.getHeight()) );
2966 sal_Int32 nDockWidth = std::max( static_cast<sal_Int32>(aDockingAreaRect.getWidth()), sal_Int32( 0 ));
2967 if ( nDockWidth == 0 )
2969 sal_Int32 nPosX( std::max( aDockingAreaRect.Left(), aDockingAreaRect.Right() ));
2970 if ( eDockedArea == ui::DockingArea_DOCKINGAREA_RIGHT )
2971 nPosX -= rTrackingRect.getWidth();
2972 rTrackingRect.SetPos( Point( nPosX, nPosY ));
2973 rUIElement.m_aDockedData.m_aPos.X = 0;
2975 else if ( rMousePos.X() < ( aDockingAreaRect.Left() + ( nDockWidth / 2 )))
2977 rTrackingRect.SetPos( Point( aDockingAreaRect.Left() - rTrackingRect.getWidth(), nPosY ));
2978 if ( eDockedArea == ui::DockingArea_DOCKINGAREA_LEFT )
2979 rUIElement.m_aDockedData.m_aPos.X = 0;
2980 else
2981 rUIElement.m_aDockedData.m_aPos.X = ( nMaxRowCol >= 0 ) ? nMaxRowCol+1 : 0;
2982 rDockingOperation = DOCKOP_BEFORE_COLROW;
2984 else
2986 rTrackingRect.SetPos( Point( aDockingAreaRect.Right(), nPosY ));
2987 if ( eDockedArea == ui::DockingArea_DOCKINGAREA_LEFT )
2988 rUIElement.m_aDockedData.m_aPos.X = ( nMaxRowCol >= 0 ) ? nMaxRowCol+1 : 0;
2989 else
2990 rUIElement.m_aDockedData.m_aPos.X = 0;
2991 rDockingOperation = DOCKOP_AFTER_COLROW;
2993 rTrackingRect.setHeight( nSize );
2996 SolarMutexGuard aGuard;
2997 nPosY = pDockingAreaWindow->ScreenToOutputPixel(
2998 pContainerWindow->OutputToScreenPixel( rTrackingRect.TopLeft() )).Y();
3000 rUIElement.m_aDockedData.m_aPos.Y = nPosY;
3005 framework::ToolbarLayoutManager::DockingOperation ToolbarLayoutManager::implts_determineDockingOperation(
3006 ui::DockingArea DockingArea,
3007 const ::Rectangle& rRowColRect,
3008 const Point& rMousePos )
3010 const sal_Int32 nHorzVerticalRegionSize = 6;
3011 const sal_Int32 nHorzVerticalMoveRegion = 4;
3013 if ( rRowColRect.IsInside( rMousePos ))
3015 if ( isHorizontalDockingArea( DockingArea ))
3017 sal_Int32 nRegion = rRowColRect.getHeight() / nHorzVerticalRegionSize;
3018 sal_Int32 nPosY = rRowColRect.Top() + nRegion;
3020 if ( rMousePos.Y() < nPosY )
3021 return ( DockingArea == ui::DockingArea_DOCKINGAREA_TOP ) ? DOCKOP_BEFORE_COLROW : DOCKOP_AFTER_COLROW;
3022 else if ( rMousePos.Y() < ( nPosY + nRegion*nHorzVerticalMoveRegion ))
3023 return DOCKOP_ON_COLROW;
3024 else
3025 return ( DockingArea == ui::DockingArea_DOCKINGAREA_TOP ) ? DOCKOP_AFTER_COLROW : DOCKOP_BEFORE_COLROW;
3027 else
3029 sal_Int32 nRegion = rRowColRect.getWidth() / nHorzVerticalRegionSize;
3030 sal_Int32 nPosX = rRowColRect.Left() + nRegion;
3032 if ( rMousePos.X() < nPosX )
3033 return ( DockingArea == ui::DockingArea_DOCKINGAREA_LEFT ) ? DOCKOP_BEFORE_COLROW : DOCKOP_AFTER_COLROW;
3034 else if ( rMousePos.X() < ( nPosX + nRegion*nHorzVerticalMoveRegion ))
3035 return DOCKOP_ON_COLROW;
3036 else
3037 return ( DockingArea == ui::DockingArea_DOCKINGAREA_LEFT ) ? DOCKOP_AFTER_COLROW : DOCKOP_BEFORE_COLROW;
3040 else
3041 return DOCKOP_ON_COLROW;
3044 ::Rectangle ToolbarLayoutManager::implts_calcTrackingAndElementRect(
3045 ui::DockingArea eDockingArea,
3046 sal_Int32 nRowCol,
3047 UIElement& rUIElement,
3048 const ::Rectangle& rTrackingRect,
3049 const ::Rectangle& rRowColumnRect,
3050 const ::Size& rContainerWinSize )
3052 ReadGuard aReadGuard( m_aLock );
3053 ::Rectangle aDockingAreaOffsets( m_aDockingAreaOffsets );
3054 aReadGuard.unlock();
3056 bool bHorizontalDockArea( isHorizontalDockingArea( eDockingArea ));
3058 sal_Int32 nTopDockingAreaSize( implts_getTopBottomDockingAreaSizes().Width() );
3059 sal_Int32 nBottomDockingAreaSize( implts_getTopBottomDockingAreaSizes().Height() );
3061 sal_Int32 nMaxLeftRightDockAreaSize = rContainerWinSize.Height() -
3062 nTopDockingAreaSize -
3063 nBottomDockingAreaSize -
3064 aDockingAreaOffsets.Top() -
3065 aDockingAreaOffsets.Bottom();
3067 ::Rectangle aTrackingRect( rTrackingRect );
3068 if ( bHorizontalDockArea )
3070 sal_Int32 nPosX( std::max( sal_Int32( rTrackingRect.Left()), sal_Int32( 0 )));
3071 if (( nPosX + rTrackingRect.getWidth()) > rContainerWinSize.Width() )
3072 nPosX = std::min( nPosX,
3073 std::max( sal_Int32( rContainerWinSize.Width() - rTrackingRect.getWidth() ),
3074 sal_Int32( 0 )));
3076 sal_Int32 nSize = std::min( rContainerWinSize.Width(), rTrackingRect.getWidth() );
3078 aTrackingRect.SetPos( ::Point( nPosX, rRowColumnRect.Top() ));
3079 aTrackingRect.setWidth( nSize );
3080 aTrackingRect.setHeight( rRowColumnRect.getHeight() );
3082 // Set virtual position
3083 rUIElement.m_aDockedData.m_aPos.X = nPosX;
3084 rUIElement.m_aDockedData.m_aPos.Y = nRowCol;
3086 else
3088 sal_Int32 nMaxDockingAreaHeight = std::max( sal_Int32( 0 ),
3089 sal_Int32( nMaxLeftRightDockAreaSize ));
3091 sal_Int32 nPosY( std::max( sal_Int32( aTrackingRect.Top()), sal_Int32( nTopDockingAreaSize )));
3092 if (( nPosY + aTrackingRect.getHeight()) > ( nTopDockingAreaSize + nMaxDockingAreaHeight ))
3093 nPosY = std::min( nPosY,
3094 std::max( sal_Int32( nTopDockingAreaSize + ( nMaxDockingAreaHeight - aTrackingRect.getHeight() )),
3095 sal_Int32( nTopDockingAreaSize )));
3097 sal_Int32 nSize = std::min( nMaxDockingAreaHeight, static_cast<sal_Int32>(aTrackingRect.getHeight()) );
3099 aTrackingRect.SetPos( ::Point( rRowColumnRect.Left(), nPosY ));
3100 aTrackingRect.setWidth( rRowColumnRect.getWidth() );
3101 aTrackingRect.setHeight( nSize );
3103 aReadGuard.lock();
3104 uno::Reference< awt::XWindow > xDockingAreaWindow( m_xDockAreaWindows[eDockingArea] );
3105 uno::Reference< awt::XWindow2 > xContainerWindow( m_xContainerWindow );
3106 aReadGuard.unlock();
3108 sal_Int32 nDockPosY( 0 );
3109 Window* pDockingAreaWindow( 0 );
3110 Window* pContainerWindow( 0 );
3112 SolarMutexGuard aGuard;
3113 pDockingAreaWindow = VCLUnoHelper::GetWindow( xDockingAreaWindow );
3114 pContainerWindow = VCLUnoHelper::GetWindow( xContainerWindow );
3115 nDockPosY = pDockingAreaWindow->ScreenToOutputPixel( pContainerWindow->OutputToScreenPixel( ::Point( 0, nPosY ))).Y();
3118 // Set virtual position
3119 rUIElement.m_aDockedData.m_aPos.X = nRowCol;
3120 rUIElement.m_aDockedData.m_aPos.Y = nDockPosY;
3123 return aTrackingRect;
3126 void ToolbarLayoutManager::implts_setTrackingRect( ui::DockingArea eDockingArea, const ::Point& rMousePos, ::Rectangle& rTrackingRect )
3128 ::Point aPoint( rTrackingRect.TopLeft());
3129 if ( isHorizontalDockingArea( eDockingArea ))
3130 aPoint.X() = rMousePos.X();
3131 else
3132 aPoint.Y() = rMousePos.Y();
3133 rTrackingRect.SetPos( aPoint );
3136 void ToolbarLayoutManager::implts_renumberRowColumnData(
3137 ui::DockingArea eDockingArea,
3138 DockingOperation /*eDockingOperation*/,
3139 const UIElement& rUIElement )
3141 ReadGuard aReadLock( m_aLock );
3142 uno::Reference< container::XNameAccess > xPersistentWindowState( m_xPersistentWindowState );
3143 aReadLock.unlock();
3145 bool bHorzDockingArea( isHorizontalDockingArea( eDockingArea ));
3146 sal_Int32 nRowCol( bHorzDockingArea ? rUIElement.m_aDockedData.m_aPos.Y : rUIElement.m_aDockedData.m_aPos.X );
3148 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
3149 WriteGuard aWriteLock( m_aLock );
3150 UIElementVector::iterator pIter;
3151 for ( pIter = m_aUIElements.begin(); pIter != m_aUIElements.end(); ++pIter )
3153 if (( pIter->m_aDockedData.m_nDockedArea == sal_Int16( eDockingArea )) && ( pIter->m_aName != rUIElement.m_aName ))
3155 // Don't change toolbars without a valid docking position!
3156 if ( isDefaultPos( pIter->m_aDockedData.m_aPos ))
3157 continue;
3159 sal_Int32 nWindowRowCol = ( bHorzDockingArea ) ? pIter->m_aDockedData.m_aPos.Y : pIter->m_aDockedData.m_aPos.X;
3160 if ( nWindowRowCol >= nRowCol )
3162 if ( bHorzDockingArea )
3163 pIter->m_aDockedData.m_aPos.Y += 1;
3164 else
3165 pIter->m_aDockedData.m_aPos.X += 1;
3169 aWriteLock.unlock();
3170 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
3172 // We have to change the persistent window state part
3173 if ( xPersistentWindowState.is() )
3177 uno::Sequence< OUString > aWindowElements = xPersistentWindowState->getElementNames();
3178 for ( sal_Int32 i = 0; i < aWindowElements.getLength(); i++ )
3180 if ( rUIElement.m_aName != aWindowElements[i] )
3184 uno::Sequence< beans::PropertyValue > aPropValueSeq;
3185 awt::Point aDockedPos;
3186 ui::DockingArea nDockedArea( ui::DockingArea_DOCKINGAREA_DEFAULT );
3188 xPersistentWindowState->getByName( aWindowElements[i] ) >>= aPropValueSeq;
3189 for ( sal_Int32 j = 0; j < aPropValueSeq.getLength(); j++ )
3191 if ( aPropValueSeq[j].Name == WINDOWSTATE_PROPERTY_DOCKINGAREA )
3192 aPropValueSeq[j].Value >>= nDockedArea;
3193 else if ( aPropValueSeq[j].Name == WINDOWSTATE_PROPERTY_DOCKPOS )
3194 aPropValueSeq[j].Value >>= aDockedPos;
3197 // Don't change toolbars without a valid docking position!
3198 if ( isDefaultPos( aDockedPos ))
3199 continue;
3201 sal_Int32 nWindowRowCol = ( bHorzDockingArea ) ? aDockedPos.Y : aDockedPos.X;
3202 if (( nDockedArea == eDockingArea ) && ( nWindowRowCol >= nRowCol ))
3204 if ( bHorzDockingArea )
3205 aDockedPos.Y += 1;
3206 else
3207 aDockedPos.X += 1;
3209 uno::Reference< container::XNameReplace > xReplace( xPersistentWindowState, uno::UNO_QUERY );
3210 xReplace->replaceByName( aWindowElements[i], makeAny( aPropValueSeq ));
3213 catch (const uno::Exception&)
3219 catch (const uno::Exception&)
3225 //---------------------------------------------------------------------------------------------------------
3226 // XWindowListener
3227 //---------------------------------------------------------------------------------------------------------
3228 void SAL_CALL ToolbarLayoutManager::windowResized( const awt::WindowEvent& aEvent )
3229 throw( uno::RuntimeException )
3231 WriteGuard aWriteLock( m_aLock );
3232 bool bLocked( m_bDockingInProgress );
3233 bool bLayoutInProgress( m_bLayoutInProgress );
3234 aWriteLock.unlock();
3236 // Do not do anything if we are in the middle of a docking process. This would interfere all other
3237 // operations. We will store the new position and size in the docking handlers.
3238 // Do not do anything if we are in the middle of our layouting process. We will adapt the position
3239 // and size of the user interface elements.
3240 if ( !bLocked && !bLayoutInProgress )
3242 bool bNotify( false );
3243 uno::Reference< awt::XWindow > xWindow( aEvent.Source, uno::UNO_QUERY );
3245 UIElement aUIElement = implts_findToolbar( aEvent.Source );
3246 if ( aUIElement.m_xUIElement.is() )
3248 if ( aUIElement.m_bFloating )
3250 uno::Reference< awt::XWindow2 > xWindow2( xWindow, uno::UNO_QUERY );
3252 if( xWindow2.is() )
3254 awt::Rectangle aPos = xWindow2->getPosSize();
3255 awt::Size aSize = xWindow2->getOutputSize(); // always use output size for consistency
3256 bool bVisible = xWindow2->isVisible();
3258 // update element data
3259 aUIElement.m_aFloatingData.m_aPos = awt::Point(aPos.X, aPos.Y);
3260 aUIElement.m_aFloatingData.m_aSize = aSize;
3261 aUIElement.m_bVisible = bVisible;
3264 implts_writeWindowStateData( aUIElement );
3266 else
3268 implts_setLayoutDirty();
3269 bNotify = true;
3273 if ( bNotify )
3274 m_pParentLayouter->requestLayout( ILayoutNotifications::HINT_TOOLBARSPACE_HAS_CHANGED );
3278 void SAL_CALL ToolbarLayoutManager::windowMoved( const awt::WindowEvent& /*aEvent*/ )
3279 throw( uno::RuntimeException )
3283 void SAL_CALL ToolbarLayoutManager::windowShown( const lang::EventObject& /*aEvent*/ )
3284 throw( uno::RuntimeException )
3288 void SAL_CALL ToolbarLayoutManager::windowHidden( const lang::EventObject& /*aEvent*/ )
3289 throw( uno::RuntimeException )
3293 //---------------------------------------------------------------------------------------------------------
3294 // XDockableWindowListener
3295 //---------------------------------------------------------------------------------------------------------
3296 void SAL_CALL ToolbarLayoutManager::startDocking( const awt::DockingEvent& e )
3297 throw (uno::RuntimeException)
3299 bool bWinFound( false );
3301 ReadGuard aReadGuard( m_aLock );
3302 uno::Reference< awt::XWindow2 > xContainerWindow( m_xContainerWindow );
3303 uno::Reference< awt::XWindow2 > xWindow( e.Source, uno::UNO_QUERY );
3304 aReadGuard.unlock();
3306 Window* pContainerWindow( 0 );
3307 Window* pWindow( 0 );
3308 ::Point aMousePos;
3310 SolarMutexGuard aGuard;
3311 pContainerWindow = VCLUnoHelper::GetWindow( xContainerWindow );
3312 aMousePos = pContainerWindow->ScreenToOutputPixel( ::Point( e.MousePos.X, e.MousePos.Y ));
3315 UIElement aUIElement = implts_findToolbar( e.Source );
3317 if ( aUIElement.m_xUIElement.is() && xWindow.is() )
3319 awt::Rectangle aRect;
3321 bWinFound = true;
3322 uno::Reference< awt::XDockableWindow > xDockWindow( xWindow, uno::UNO_QUERY );
3323 if ( xDockWindow->isFloating() )
3325 awt::Rectangle aPos = xWindow->getPosSize();
3326 awt::Size aSize = xWindow->getOutputSize();
3328 aUIElement.m_aFloatingData.m_aPos = awt::Point(aPos.X, aPos.Y);
3329 aUIElement.m_aFloatingData.m_aSize = aSize;
3331 SolarMutexGuard aGuard;
3333 pWindow = VCLUnoHelper::GetWindow( xWindow );
3334 if ( pWindow && pWindow->GetType() == WINDOW_TOOLBOX )
3336 ToolBox* pToolBox = (ToolBox *)pWindow;
3337 aUIElement.m_aFloatingData.m_nLines = pToolBox->GetFloatingLines();
3338 aUIElement.m_aFloatingData.m_bIsHorizontal = isToolboxHorizontalAligned( pToolBox );
3343 WriteGuard aWriteLock( m_aLock );
3344 m_bDockingInProgress = bWinFound;
3345 m_aDockUIElement = aUIElement;
3346 m_aDockUIElement.m_bUserActive = true;
3347 m_aStartDockMousePos = aMousePos;
3348 aWriteLock.unlock();
3351 awt::DockingData SAL_CALL ToolbarLayoutManager::docking( const awt::DockingEvent& e )
3352 throw (uno::RuntimeException)
3354 const sal_Int32 MAGNETIC_DISTANCE_UNDOCK = 25;
3355 const sal_Int32 MAGNETIC_DISTANCE_DOCK = 20;
3357 ReadGuard aReadLock( m_aLock );
3358 awt::DockingData aDockingData;
3359 uno::Reference< awt::XDockableWindow > xDockWindow( e.Source, uno::UNO_QUERY );
3360 uno::Reference< awt::XWindow > xWindow( e.Source, uno::UNO_QUERY );
3361 uno::Reference< awt::XWindow > xTopDockingWindow( m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_TOP] );
3362 uno::Reference< awt::XWindow > xLeftDockingWindow( m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_LEFT] );
3363 uno::Reference< awt::XWindow > xRightDockingWindow( m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_RIGHT] );
3364 uno::Reference< awt::XWindow > xBottomDockingWindow( m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_BOTTOM] );
3365 uno::Reference< awt::XWindow2 > xContainerWindow( m_xContainerWindow );
3366 UIElement aUIDockingElement( m_aDockUIElement );
3369 DockingOperation eDockingOperation( DOCKOP_ON_COLROW );
3370 bool bDockingInProgress( m_bDockingInProgress );
3371 aReadLock.unlock();
3373 if ( bDockingInProgress )
3374 aDockingData.TrackingRectangle = e.TrackingRectangle;
3376 if ( bDockingInProgress && xDockWindow.is() && xWindow.is() )
3380 SolarMutexGuard aGuard;
3382 sal_Int16 eDockingArea( -1 ); // none
3383 sal_Int32 nMagneticZone( aUIDockingElement.m_bFloating ? MAGNETIC_DISTANCE_DOCK : MAGNETIC_DISTANCE_UNDOCK );
3384 awt::Rectangle aNewTrackingRect;
3385 ::Rectangle aTrackingRect( e.TrackingRectangle.X, e.TrackingRectangle.Y,
3386 ( e.TrackingRectangle.X + e.TrackingRectangle.Width ),
3387 ( e.TrackingRectangle.Y + e.TrackingRectangle.Height ));
3389 awt::Rectangle aTmpRect = xTopDockingWindow->getPosSize();
3390 ::Rectangle aTopDockRect( aTmpRect.X, aTmpRect.Y, aTmpRect.Width, aTmpRect.Height );
3391 ::Rectangle aHotZoneTopDockRect( implts_calcHotZoneRect( aTopDockRect, nMagneticZone ));
3393 aTmpRect = xBottomDockingWindow->getPosSize();
3394 ::Rectangle aBottomDockRect( aTmpRect.X, aTmpRect.Y, ( aTmpRect.X + aTmpRect.Width), ( aTmpRect.Y + aTmpRect.Height ));
3395 ::Rectangle aHotZoneBottomDockRect( implts_calcHotZoneRect( aBottomDockRect, nMagneticZone ));
3397 aTmpRect = xLeftDockingWindow->getPosSize();
3398 ::Rectangle aLeftDockRect( aTmpRect.X, aTmpRect.Y, ( aTmpRect.X + aTmpRect.Width ), ( aTmpRect.Y + aTmpRect.Height ));
3399 ::Rectangle aHotZoneLeftDockRect( implts_calcHotZoneRect( aLeftDockRect, nMagneticZone ));
3401 aTmpRect = xRightDockingWindow->getPosSize();
3402 ::Rectangle aRightDockRect( aTmpRect.X, aTmpRect.Y, ( aTmpRect.X + aTmpRect.Width ), ( aTmpRect.Y + aTmpRect.Height ));
3403 ::Rectangle aHotZoneRightDockRect( implts_calcHotZoneRect( aRightDockRect, nMagneticZone ));
3405 Window* pContainerWindow( VCLUnoHelper::GetWindow( xContainerWindow ) );
3406 ::Point aMousePos( pContainerWindow->ScreenToOutputPixel( ::Point( e.MousePos.X, e.MousePos.Y )));
3408 if ( aHotZoneTopDockRect.IsInside( aMousePos ))
3409 eDockingArea = ui::DockingArea_DOCKINGAREA_TOP;
3410 else if ( aHotZoneBottomDockRect.IsInside( aMousePos ))
3411 eDockingArea = ui::DockingArea_DOCKINGAREA_BOTTOM;
3412 else if ( aHotZoneLeftDockRect.IsInside( aMousePos ))
3413 eDockingArea = ui::DockingArea_DOCKINGAREA_LEFT;
3414 else if ( aHotZoneRightDockRect.IsInside( aMousePos ))
3415 eDockingArea = ui::DockingArea_DOCKINGAREA_RIGHT;
3417 // Higher priority for movements inside the real docking area
3418 if ( aTopDockRect.IsInside( aMousePos ))
3419 eDockingArea = ui::DockingArea_DOCKINGAREA_TOP;
3420 else if ( aBottomDockRect.IsInside( aMousePos ))
3421 eDockingArea = ui::DockingArea_DOCKINGAREA_BOTTOM;
3422 else if ( aLeftDockRect.IsInside( aMousePos ))
3423 eDockingArea = ui::DockingArea_DOCKINGAREA_LEFT;
3424 else if ( aRightDockRect.IsInside( aMousePos ))
3425 eDockingArea = ui::DockingArea_DOCKINGAREA_RIGHT;
3427 // Determine if we have a toolbar and set alignment according to the docking area!
3428 Window* pWindow = VCLUnoHelper::GetWindow( xWindow );
3429 ToolBox* pToolBox = 0;
3430 if ( pWindow && pWindow->GetType() == WINDOW_TOOLBOX )
3431 pToolBox = (ToolBox *)pWindow;
3433 if ( eDockingArea != -1 )
3435 if ( eDockingArea == ui::DockingArea_DOCKINGAREA_TOP )
3437 aUIDockingElement.m_aDockedData.m_nDockedArea = ui::DockingArea_DOCKINGAREA_TOP;
3438 aUIDockingElement.m_bFloating = false;
3440 else if ( eDockingArea == ui::DockingArea_DOCKINGAREA_BOTTOM )
3442 aUIDockingElement.m_aDockedData.m_nDockedArea = ui::DockingArea_DOCKINGAREA_BOTTOM;
3443 aUIDockingElement.m_bFloating = false;
3445 else if ( eDockingArea == ui::DockingArea_DOCKINGAREA_LEFT )
3447 aUIDockingElement.m_aDockedData.m_nDockedArea = ui::DockingArea_DOCKINGAREA_LEFT;
3448 aUIDockingElement.m_bFloating = false;
3450 else if ( eDockingArea == ui::DockingArea_DOCKINGAREA_RIGHT )
3452 aUIDockingElement.m_aDockedData.m_nDockedArea = ui::DockingArea_DOCKINGAREA_RIGHT;
3453 aUIDockingElement.m_bFloating = false;
3456 ::Point aOutputPos = pContainerWindow->ScreenToOutputPixel( aTrackingRect.TopLeft() );
3457 aTrackingRect.SetPos( aOutputPos );
3459 ::Rectangle aNewDockingRect( aTrackingRect );
3462 implts_calcDockingPosSize( aUIDockingElement, eDockingOperation, aNewDockingRect, aMousePos );
3464 ::Point aScreenPos = pContainerWindow->OutputToScreenPixel( aNewDockingRect.TopLeft() );
3465 aNewTrackingRect = awt::Rectangle( aScreenPos.X(), aScreenPos.Y(),
3466 aNewDockingRect.getWidth(), aNewDockingRect.getHeight() );
3467 aDockingData.TrackingRectangle = aNewTrackingRect;
3469 else if ( pToolBox && bDockingInProgress )
3471 bool bIsHorizontal = isToolboxHorizontalAligned( pToolBox );
3472 awt::Size aFloatSize = aUIDockingElement.m_aFloatingData.m_aSize;
3473 if ( aFloatSize.Width > 0 && aFloatSize.Height > 0 )
3475 aUIDockingElement.m_aFloatingData.m_aPos = AWTPoint(pContainerWindow->ScreenToOutputPixel(VCLPoint(e.MousePos)));
3476 aDockingData.TrackingRectangle.Height = aFloatSize.Height;
3477 aDockingData.TrackingRectangle.Width = aFloatSize.Width;
3479 else
3481 aFloatSize = AWTSize(pToolBox->CalcWindowSizePixel());
3482 if ( !bIsHorizontal )
3484 // Floating toolbars are always horizontal aligned! We have to swap
3485 // width/height if we have a vertical aligned toolbar.
3486 sal_Int32 nTemp = aFloatSize.Height;
3487 aFloatSize.Height = aFloatSize.Width;
3488 aFloatSize.Width = nTemp;
3491 aDockingData.TrackingRectangle.Height = aFloatSize.Height;
3492 aDockingData.TrackingRectangle.Width = aFloatSize.Width;
3494 // For the first time we don't have any data about the floating size of a toolbar.
3495 // We calculate it and store it for later use.
3496 aUIDockingElement.m_aFloatingData.m_aPos = AWTPoint(pContainerWindow->ScreenToOutputPixel(VCLPoint(e.MousePos)));
3497 aUIDockingElement.m_aFloatingData.m_aSize = aFloatSize;
3498 aUIDockingElement.m_aFloatingData.m_nLines = pToolBox->GetFloatingLines();
3499 aUIDockingElement.m_aFloatingData.m_bIsHorizontal = isToolboxHorizontalAligned( pToolBox );
3501 aDockingData.TrackingRectangle.X = e.MousePos.X;
3502 aDockingData.TrackingRectangle.Y = e.MousePos.Y;
3505 aDockingData.bFloating = ( eDockingArea == -1 );
3507 // Write current data to the member docking progress data
3508 WriteGuard aWriteLock( m_aLock );
3509 m_aDockUIElement.m_bFloating = aDockingData.bFloating;
3510 if ( !aDockingData.bFloating )
3512 m_aDockUIElement.m_aDockedData = aUIDockingElement.m_aDockedData;
3515 m_eDockOperation = eDockingOperation;
3517 else
3518 m_aDockUIElement.m_aFloatingData = aUIDockingElement.m_aFloatingData;
3519 aWriteLock.unlock();
3521 catch (const uno::Exception&)
3526 return aDockingData;
3529 void SAL_CALL ToolbarLayoutManager::endDocking( const awt::EndDockingEvent& e )
3530 throw (uno::RuntimeException)
3532 bool bDockingInProgress( false );
3533 bool bStartDockFloated( false );
3534 bool bFloating( false );
3535 UIElement aUIDockingElement;
3537 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
3538 WriteGuard aWriteLock( m_aLock );
3539 bDockingInProgress = m_bDockingInProgress;
3540 aUIDockingElement = m_aDockUIElement;
3541 bFloating = aUIDockingElement.m_bFloating;
3543 UIElement& rUIElement = impl_findToolbar( aUIDockingElement.m_aName );
3544 if ( rUIElement.m_aName == aUIDockingElement.m_aName )
3546 if ( aUIDockingElement.m_bFloating )
3548 // Write last position into position data
3549 uno::Reference< awt::XWindow > xWindow( aUIDockingElement.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
3550 rUIElement.m_aFloatingData = aUIDockingElement.m_aFloatingData;
3551 awt::Rectangle aTmpRect = xWindow->getPosSize();
3552 rUIElement.m_aFloatingData.m_aPos = awt::Point(aTmpRect.X, aTmpRect.Y);
3553 // make changes also for our local data as we use it to make data persistent
3554 aUIDockingElement.m_aFloatingData = rUIElement.m_aFloatingData;
3556 else
3558 rUIElement.m_aDockedData = aUIDockingElement.m_aDockedData;
3559 rUIElement.m_aFloatingData.m_aSize = aUIDockingElement.m_aFloatingData.m_aSize;
3561 if ( m_eDockOperation != DOCKOP_ON_COLROW )
3563 // we have to renumber our row/column data to insert a new row/column
3564 implts_renumberRowColumnData((ui::DockingArea)aUIDockingElement.m_aDockedData.m_nDockedArea, m_eDockOperation, aUIDockingElement );
3568 bStartDockFloated = rUIElement.m_bFloating;
3569 rUIElement.m_bFloating = m_aDockUIElement.m_bFloating;
3570 rUIElement.m_bUserActive = true;
3573 // reset member for next docking operation
3574 m_aDockUIElement.m_xUIElement.clear();
3575 m_eDockOperation = DOCKOP_ON_COLROW;
3576 aWriteLock.unlock();
3577 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
3579 implts_writeWindowStateData( aUIDockingElement );
3581 if ( bDockingInProgress )
3583 SolarMutexGuard aGuard;
3584 Window* pWindow = VCLUnoHelper::GetWindow( uno::Reference< awt::XWindow >( e.Source, uno::UNO_QUERY ));
3585 ToolBox* pToolBox = 0;
3586 if ( pWindow && pWindow->GetType() == WINDOW_TOOLBOX )
3587 pToolBox = (ToolBox *)pWindow;
3589 if ( pToolBox )
3591 if( e.bFloating )
3593 if ( aUIDockingElement.m_aFloatingData.m_bIsHorizontal )
3594 pToolBox->SetAlign( WINDOWALIGN_TOP );
3595 else
3596 pToolBox->SetAlign( WINDOWALIGN_LEFT );
3598 else
3600 ::Size aSize;
3602 pToolBox->SetAlign( ImplConvertAlignment( aUIDockingElement.m_aDockedData.m_nDockedArea) );
3604 // Docked toolbars have always one line
3605 aSize = pToolBox->CalcWindowSizePixel( 1 );
3607 // Lock layouting updates as our listener would be called due to SetSizePixel
3608 pToolBox->SetOutputSizePixel( aSize );
3613 implts_sortUIElements();
3615 aWriteLock.lock();
3616 m_bDockingInProgress = sal_False;
3617 m_bLayoutDirty = !bStartDockFloated || !bFloating;
3618 bool bNotify = m_bLayoutDirty;
3619 aWriteLock.unlock();
3621 if ( bNotify )
3622 m_pParentLayouter->requestLayout( ILayoutNotifications::HINT_TOOLBARSPACE_HAS_CHANGED );
3625 sal_Bool SAL_CALL ToolbarLayoutManager::prepareToggleFloatingMode( const lang::EventObject& e )
3626 throw (uno::RuntimeException)
3628 ReadGuard aReadLock( m_aLock );
3629 bool bDockingInProgress = m_bDockingInProgress;
3630 aReadLock.unlock();
3632 UIElement aUIDockingElement = implts_findToolbar( e.Source );
3633 bool bWinFound( !aUIDockingElement.m_aName.isEmpty() );
3634 uno::Reference< awt::XWindow > xWindow( e.Source, uno::UNO_QUERY );
3636 if ( bWinFound && xWindow.is() )
3638 if ( !bDockingInProgress )
3640 awt::Rectangle aRect;
3641 uno::Reference< awt::XDockableWindow > xDockWindow( xWindow, uno::UNO_QUERY );
3642 if ( xDockWindow->isFloating() )
3645 SolarMutexGuard aGuard;
3646 Window* pWindow = VCLUnoHelper::GetWindow( xWindow );
3647 if ( pWindow && pWindow->GetType() == WINDOW_TOOLBOX )
3649 ToolBox* pToolBox = static_cast< ToolBox *>( pWindow );
3650 aUIDockingElement.m_aFloatingData.m_aPos = AWTPoint(pToolBox->GetPosPixel());
3651 aUIDockingElement.m_aFloatingData.m_aSize = AWTSize(pToolBox->GetOutputSizePixel());
3652 aUIDockingElement.m_aFloatingData.m_nLines = pToolBox->GetFloatingLines();
3653 aUIDockingElement.m_aFloatingData.m_bIsHorizontal = isToolboxHorizontalAligned( pToolBox );
3657 UIElement aUIElement = implts_findToolbar( aUIDockingElement.m_aName );
3658 if ( aUIElement.m_aName == aUIDockingElement.m_aName )
3659 implts_setToolbar( aUIDockingElement );
3664 return sal_True;
3667 void SAL_CALL ToolbarLayoutManager::toggleFloatingMode( const lang::EventObject& e )
3668 throw (uno::RuntimeException)
3670 UIElement aUIDockingElement;
3672 ReadGuard aReadLock( m_aLock );
3673 bool bDockingInProgress( m_bDockingInProgress );
3674 if ( bDockingInProgress )
3675 aUIDockingElement = m_aDockUIElement;
3676 aReadLock.unlock();
3678 Window* pWindow( 0 );
3679 ToolBox* pToolBox( 0 );
3680 uno::Reference< awt::XWindow2 > xWindow;
3683 SolarMutexGuard aGuard;
3684 xWindow = uno::Reference< awt::XWindow2 >( e.Source, uno::UNO_QUERY );
3685 pWindow = VCLUnoHelper::GetWindow( xWindow );
3687 if ( pWindow && pWindow->GetType() == WINDOW_TOOLBOX )
3688 pToolBox = (ToolBox *)pWindow;
3691 if ( !bDockingInProgress )
3693 aUIDockingElement = implts_findToolbar( e.Source );
3694 bool bWinFound = ( !aUIDockingElement.m_aName.isEmpty() );
3696 if ( bWinFound && xWindow.is() )
3698 aUIDockingElement.m_bFloating = !aUIDockingElement.m_bFloating;
3699 aUIDockingElement.m_bUserActive = true;
3701 implts_setLayoutInProgress( true );
3702 if ( aUIDockingElement.m_bFloating )
3704 SolarMutexGuard aGuard;
3705 if ( pToolBox )
3707 pToolBox->SetLineCount( aUIDockingElement.m_aFloatingData.m_nLines );
3708 if ( aUIDockingElement.m_aFloatingData.m_bIsHorizontal )
3709 pToolBox->SetAlign( WINDOWALIGN_TOP );
3710 else
3711 pToolBox->SetAlign( WINDOWALIGN_LEFT );
3714 bool bUndefPos = hasDefaultPosValue( aUIDockingElement.m_aFloatingData.m_aPos );
3715 bool bSetSize = !hasEmptySize( aUIDockingElement.m_aFloatingData.m_aSize );
3717 if ( bUndefPos )
3718 aUIDockingElement.m_aFloatingData.m_aPos = implts_findNextCascadeFloatingPos();
3720 if ( !bSetSize )
3722 if ( pToolBox )
3723 aUIDockingElement.m_aFloatingData.m_aSize = AWTSize(pToolBox->CalcFloatingWindowSizePixel());
3724 else
3725 aUIDockingElement.m_aFloatingData.m_aSize = AWTSize(pWindow->GetOutputSizePixel());
3728 xWindow->setPosSize( aUIDockingElement.m_aFloatingData.m_aPos.X,
3729 aUIDockingElement.m_aFloatingData.m_aPos.Y,
3730 0, 0, awt::PosSize::POS );
3731 xWindow->setOutputSize(aUIDockingElement.m_aFloatingData.m_aSize);
3733 else
3735 if ( isDefaultPos( aUIDockingElement.m_aDockedData.m_aPos ))
3737 // Docking on its default position without a preset position -
3738 // we have to find a good place for it.
3739 ::Point aPixelPos;
3740 awt::Point aDockPos;
3741 ::Size aSize;
3744 SolarMutexGuard aGuard;
3745 if ( pToolBox )
3746 aSize = pToolBox->CalcWindowSizePixel( 1, ImplConvertAlignment( aUIDockingElement.m_aDockedData.m_nDockedArea ) );
3747 else
3748 aSize = pWindow->GetSizePixel();
3751 implts_findNextDockingPos((ui::DockingArea)aUIDockingElement.m_aDockedData.m_nDockedArea, aSize, aDockPos, aPixelPos );
3752 aUIDockingElement.m_aDockedData.m_aPos = aDockPos;
3755 SolarMutexGuard aGuard;
3756 if ( pToolBox )
3758 pToolBox->SetAlign( ImplConvertAlignment( aUIDockingElement.m_aDockedData.m_nDockedArea) );
3759 ::Size aSize = pToolBox->CalcWindowSizePixel( 1 );
3760 awt::Rectangle aRect = xWindow->getPosSize();
3761 xWindow->setPosSize( aRect.X, aRect.Y, 0, 0, awt::PosSize::POS );
3762 xWindow->setOutputSize( AWTSize( aSize ) );
3766 implts_setLayoutInProgress( false );
3767 implts_setToolbar( aUIDockingElement );
3768 implts_writeWindowStateData( aUIDockingElement );
3769 implts_sortUIElements();
3770 implts_setLayoutDirty();
3772 aReadLock.lock();
3773 ILayoutNotifications* pParentLayouter( m_pParentLayouter );
3774 aReadLock.unlock();
3776 if ( pParentLayouter )
3777 pParentLayouter->requestLayout( ILayoutNotifications::HINT_TOOLBARSPACE_HAS_CHANGED );
3780 else
3782 SolarMutexGuard aGuard;
3783 if ( pToolBox )
3785 if ( aUIDockingElement.m_bFloating )
3787 if ( aUIDockingElement.m_aFloatingData.m_bIsHorizontal )
3788 pToolBox->SetAlign( WINDOWALIGN_TOP );
3789 else
3790 pToolBox->SetAlign( WINDOWALIGN_LEFT );
3792 else
3793 pToolBox->SetAlign( ImplConvertAlignment( aUIDockingElement.m_aDockedData.m_nDockedArea) );
3798 void SAL_CALL ToolbarLayoutManager::closed( const lang::EventObject& e )
3799 throw (uno::RuntimeException)
3801 OUString aName;
3802 UIElement aUIElement;
3803 UIElementVector::iterator pIter;
3805 WriteGuard aWriteLock( m_aLock );
3806 for ( pIter = m_aUIElements.begin(); pIter != m_aUIElements.end(); ++pIter )
3808 uno::Reference< ui::XUIElement > xUIElement( pIter->m_xUIElement );
3809 if ( xUIElement.is() )
3811 uno::Reference< uno::XInterface > xIfac( xUIElement->getRealInterface(), uno::UNO_QUERY );
3812 if ( xIfac == e.Source )
3814 aName = pIter->m_aName;
3816 // user closes a toolbar =>
3817 // context sensitive toolbar: only destroy toolbar and store state.
3818 // non context sensitive toolbar: make it invisible, store state and destroy it.
3819 if ( !pIter->m_bContextSensitive )
3820 pIter->m_bVisible = sal_False;
3822 aUIElement = *pIter;
3823 break;
3827 aWriteLock.unlock();
3829 // destroy element
3830 if ( !aName.isEmpty() )
3832 implts_writeWindowStateData( aUIElement );
3833 destroyToolbar( aName );
3835 ReadGuard aReadLock( m_aLock );
3836 bool bLayoutDirty = m_bLayoutDirty;
3837 ILayoutNotifications* pParentLayouter( m_pParentLayouter );
3838 aWriteLock.unlock();
3840 if ( bLayoutDirty && pParentLayouter )
3841 pParentLayouter->requestLayout( ILayoutNotifications::HINT_TOOLBARSPACE_HAS_CHANGED );
3845 void SAL_CALL ToolbarLayoutManager::endPopupMode( const awt::EndPopupModeEvent& /*e*/ )
3846 throw (uno::RuntimeException)
3850 //---------------------------------------------------------------------------------------------------------
3851 // XUIConfigurationListener
3852 //---------------------------------------------------------------------------------------------------------
3853 void SAL_CALL ToolbarLayoutManager::elementInserted( const ui::ConfigurationEvent& rEvent )
3854 throw (uno::RuntimeException)
3856 UIElement aUIElement = implts_findToolbar( rEvent.ResourceURL );
3858 uno::Reference< ui::XUIElementSettings > xElementSettings( aUIElement.m_xUIElement, uno::UNO_QUERY );
3859 if ( xElementSettings.is() )
3861 OUString aConfigSourcePropName( "ConfigurationSource" );
3862 uno::Reference< beans::XPropertySet > xPropSet( xElementSettings, uno::UNO_QUERY );
3863 if ( xPropSet.is() )
3865 if ( rEvent.Source == uno::Reference< uno::XInterface >( m_xDocCfgMgr, uno::UNO_QUERY ))
3866 xPropSet->setPropertyValue( aConfigSourcePropName, makeAny( m_xDocCfgMgr ));
3868 xElementSettings->updateSettings();
3870 else
3872 OUString aElementType;
3873 OUString aElementName;
3874 parseResourceURL( rEvent.ResourceURL, aElementType, aElementName );
3875 if ( aElementName.indexOf( m_aCustomTbxPrefix ) != -1 )
3877 // custom toolbar must be directly created, shown and layouted!
3878 createToolbar( rEvent.ResourceURL );
3879 uno::Reference< ui::XUIElement > xUIElement = getToolbar( rEvent.ResourceURL );
3880 if ( xUIElement.is() )
3882 OUString aUIName;
3883 uno::Reference< ui::XUIConfigurationManager > xCfgMgr;
3884 uno::Reference< beans::XPropertySet > xPropSet;
3888 xCfgMgr = uno::Reference< ui::XUIConfigurationManager >( rEvent.Source, uno::UNO_QUERY );
3889 xPropSet = uno::Reference< beans::XPropertySet >( xCfgMgr->getSettings( rEvent.ResourceURL, sal_False ), uno::UNO_QUERY );
3891 if ( xPropSet.is() )
3892 xPropSet->getPropertyValue( OUString( "UIName" )) >>= aUIName;
3894 catch (const container::NoSuchElementException&)
3897 catch (const beans::UnknownPropertyException&)
3900 catch (const lang::WrappedTargetException&)
3905 SolarMutexGuard aGuard;
3906 Window* pWindow = getWindowFromXUIElement( xUIElement );
3907 if ( pWindow )
3908 pWindow->SetText( aUIName );
3911 showToolbar( rEvent.ResourceURL );
3917 void SAL_CALL ToolbarLayoutManager::elementRemoved( const ui::ConfigurationEvent& rEvent )
3918 throw (uno::RuntimeException)
3920 ReadGuard aReadLock( m_aLock );
3921 uno::Reference< awt::XWindow > xContainerWindow( m_xContainerWindow, uno::UNO_QUERY );
3922 uno::Reference< ui::XUIConfigurationManager > xModuleCfgMgr( m_xModuleCfgMgr );
3923 uno::Reference< ui::XUIConfigurationManager > xDocCfgMgr( m_xDocCfgMgr );
3924 aReadLock.unlock();
3926 UIElement aUIElement = implts_findToolbar( rEvent.ResourceURL );
3927 uno::Reference< ui::XUIElementSettings > xElementSettings( aUIElement.m_xUIElement, uno::UNO_QUERY );
3928 if ( xElementSettings.is() )
3930 bool bNoSettings( false );
3931 OUString aConfigSourcePropName( "ConfigurationSource" );
3932 uno::Reference< uno::XInterface > xElementCfgMgr;
3933 uno::Reference< beans::XPropertySet > xPropSet( xElementSettings, uno::UNO_QUERY );
3935 if ( xPropSet.is() )
3936 xPropSet->getPropertyValue( aConfigSourcePropName ) >>= xElementCfgMgr;
3938 if ( !xElementCfgMgr.is() )
3939 return;
3941 // Check if the same UI configuration manager has changed => check further
3942 if ( rEvent.Source == xElementCfgMgr )
3944 // Same UI configuration manager where our element has its settings
3945 if ( rEvent.Source == uno::Reference< uno::XInterface >( xDocCfgMgr, uno::UNO_QUERY ))
3947 // document settings removed
3948 if ( xModuleCfgMgr->hasSettings( rEvent.ResourceURL ))
3950 xPropSet->setPropertyValue( aConfigSourcePropName, makeAny( xModuleCfgMgr ));
3951 xElementSettings->updateSettings();
3952 return;
3956 bNoSettings = true;
3959 // No settings anymore, element must be destroyed
3960 if ( xContainerWindow.is() && bNoSettings )
3961 destroyToolbar( rEvent.ResourceURL );
3965 void SAL_CALL ToolbarLayoutManager::elementReplaced( const ui::ConfigurationEvent& rEvent )
3966 throw (uno::RuntimeException)
3968 UIElement aUIElement = implts_findToolbar( rEvent.ResourceURL );
3970 uno::Reference< ui::XUIElementSettings > xElementSettings( aUIElement.m_xUIElement, uno::UNO_QUERY );
3971 if ( xElementSettings.is() )
3973 OUString aConfigSourcePropName( "ConfigurationSource" );
3974 uno::Reference< uno::XInterface > xElementCfgMgr;
3975 uno::Reference< beans::XPropertySet > xPropSet( xElementSettings, uno::UNO_QUERY );
3977 if ( xPropSet.is() )
3978 xPropSet->getPropertyValue( aConfigSourcePropName ) >>= xElementCfgMgr;
3980 if ( !xElementCfgMgr.is() )
3981 return;
3983 // Check if the same UI configuration manager has changed => update settings
3984 if ( rEvent.Source == xElementCfgMgr )
3986 xElementSettings->updateSettings();
3988 WriteGuard aWriteLock( m_aLock );
3989 bool bNotify = !aUIElement.m_bFloating;
3990 m_bLayoutDirty = bNotify;
3991 ILayoutNotifications* pParentLayouter( m_pParentLayouter );
3992 aWriteLock.unlock();
3994 if ( bNotify && pParentLayouter )
3995 pParentLayouter->requestLayout( ILayoutNotifications::HINT_TOOLBARSPACE_HAS_CHANGED );
4000 uno::Reference< ui::XUIElement > ToolbarLayoutManager::getToolbar( const OUString& aName )
4002 return implts_findToolbar( aName ).m_xUIElement;
4005 uno::Sequence< uno::Reference< ui::XUIElement > > ToolbarLayoutManager::getToolbars()
4007 uno::Sequence< uno::Reference< ui::XUIElement > > aSeq;
4009 ReadGuard aReadLock( m_aLock );
4010 if ( m_aUIElements.size() > 0 )
4012 sal_uInt32 nCount(0);
4013 UIElementVector::iterator pIter;
4014 for ( pIter = m_aUIElements.begin(); pIter != m_aUIElements.end(); ++pIter )
4016 if ( pIter->m_xUIElement.is() )
4018 ++nCount;
4019 aSeq.realloc( nCount );
4020 aSeq[nCount-1] = pIter->m_xUIElement;
4025 return aSeq;
4028 bool ToolbarLayoutManager::floatToolbar( const OUString& rResourceURL )
4030 UIElement aUIElement = implts_findToolbar( rResourceURL );
4031 if ( aUIElement.m_xUIElement.is() )
4035 uno::Reference< awt::XDockableWindow > xDockWindow( aUIElement.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
4036 if ( xDockWindow.is() && !xDockWindow->isFloating() )
4038 aUIElement.m_bFloating = true;
4039 implts_writeWindowStateData( aUIElement );
4040 xDockWindow->setFloatingMode( true );
4042 implts_setLayoutDirty();
4043 implts_setToolbar( aUIElement );
4044 return true;
4047 catch (const lang::DisposedException&)
4052 return false;
4055 bool ToolbarLayoutManager::lockToolbar( const OUString& rResourceURL )
4057 UIElement aUIElement = implts_findToolbar( rResourceURL );
4058 if ( aUIElement.m_xUIElement.is() )
4062 uno::Reference< awt::XDockableWindow > xDockWindow( aUIElement.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
4063 if ( xDockWindow.is() && !xDockWindow->isFloating() && !xDockWindow->isLocked() )
4065 aUIElement.m_aDockedData.m_bLocked = true;
4066 implts_writeWindowStateData( aUIElement );
4067 xDockWindow->lock();
4069 implts_setLayoutDirty();
4070 implts_setToolbar( aUIElement );
4071 return true;
4074 catch (const lang::DisposedException&)
4079 return false;
4082 bool ToolbarLayoutManager::unlockToolbar( const OUString& rResourceURL )
4084 UIElement aUIElement = implts_findToolbar( rResourceURL );
4085 if ( aUIElement.m_xUIElement.is() )
4089 uno::Reference< awt::XDockableWindow > xDockWindow( aUIElement.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
4090 if ( xDockWindow.is() && !xDockWindow->isFloating() && xDockWindow->isLocked() )
4092 aUIElement.m_aDockedData.m_bLocked = false;
4093 implts_writeWindowStateData( aUIElement );
4094 xDockWindow->unlock();
4096 implts_setLayoutDirty();
4097 implts_setToolbar( aUIElement );
4098 return true;
4101 catch (const lang::DisposedException&)
4106 return false;
4109 bool ToolbarLayoutManager::isToolbarVisible( const OUString& rResourceURL )
4111 uno::Reference< awt::XWindow2 > xWindow2( implts_getXWindow( rResourceURL ), uno::UNO_QUERY );
4112 return ( xWindow2.is() && xWindow2->isVisible() );
4115 bool ToolbarLayoutManager::isToolbarFloating( const OUString& rResourceURL )
4117 uno::Reference< awt::XDockableWindow > xDockWindow( implts_getXWindow( rResourceURL ), uno::UNO_QUERY );
4118 return ( xDockWindow.is() && xDockWindow->isFloating() );
4121 bool ToolbarLayoutManager::isToolbarDocked( const OUString& rResourceURL )
4123 return !isToolbarFloating( rResourceURL );
4126 bool ToolbarLayoutManager::isToolbarLocked( const OUString& rResourceURL )
4128 uno::Reference< awt::XDockableWindow > xDockWindow( implts_getXWindow( rResourceURL ), uno::UNO_QUERY );
4129 return ( xDockWindow.is() && xDockWindow->isLocked() );
4132 awt::Size ToolbarLayoutManager::getToolbarSize( const OUString& rResourceURL )
4134 Window* pWindow = implts_getWindow( rResourceURL );
4136 SolarMutexGuard aGuard;
4137 if ( pWindow )
4139 ::Size aSize = pWindow->GetSizePixel();
4140 awt::Size aWinSize;
4141 aWinSize.Width = aSize.Width();
4142 aWinSize.Height = aSize.Height();
4143 return aWinSize;
4146 return awt::Size();
4149 awt::Point ToolbarLayoutManager::getToolbarPos( const OUString& rResourceURL )
4151 awt::Point aPos;
4152 UIElement aUIElement = implts_findToolbar( rResourceURL );
4154 uno::Reference< awt::XWindow > xWindow( implts_getXWindow( rResourceURL ));
4155 if ( xWindow.is() )
4157 if ( aUIElement.m_bFloating )
4159 awt::Rectangle aRect = xWindow->getPosSize();
4160 aPos.X = aRect.X;
4161 aPos.Y = aRect.Y;
4163 else
4164 aPos = aUIElement.m_aDockedData.m_aPos;
4167 return aPos;
4170 void ToolbarLayoutManager::setToolbarSize( const OUString& rResourceURL, const awt::Size& aSize )
4172 uno::Reference< awt::XWindow2 > xWindow( implts_getXWindow( rResourceURL ), uno::UNO_QUERY );
4173 uno::Reference< awt::XDockableWindow > xDockWindow( xWindow, uno::UNO_QUERY );
4174 UIElement aUIElement = implts_findToolbar( rResourceURL );
4176 if ( xWindow.is() && xDockWindow.is() && xDockWindow->isFloating() )
4178 xWindow->setOutputSize( aSize );
4179 aUIElement.m_aFloatingData.m_aSize = aSize;
4180 implts_setToolbar( aUIElement );
4181 implts_writeWindowStateData( aUIElement );
4182 implts_sortUIElements();
4186 void ToolbarLayoutManager::setToolbarPos( const OUString& rResourceURL, const awt::Point& aPos )
4188 uno::Reference< awt::XWindow > xWindow( implts_getXWindow( rResourceURL ));
4189 uno::Reference< awt::XDockableWindow > xDockWindow( xWindow, uno::UNO_QUERY );
4190 UIElement aUIElement = implts_findToolbar( rResourceURL );
4192 if ( xWindow.is() && xDockWindow.is() && xDockWindow->isFloating() )
4194 xWindow->setPosSize( aPos.X, aPos.Y, 0, 0, awt::PosSize::POS );
4195 aUIElement.m_aFloatingData.m_aPos = aPos;
4196 implts_setToolbar( aUIElement );
4197 implts_writeWindowStateData( aUIElement );
4198 implts_sortUIElements();
4202 void ToolbarLayoutManager::setToolbarPosSize( const OUString& rResourceURL, const awt::Point& aPos, const awt::Size& aSize )
4204 setToolbarPos( rResourceURL, aPos );
4205 setToolbarSize( rResourceURL, aSize );
4208 } // namespace framework
4210 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */