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