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