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