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