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