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