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