blob: b8ddc52f11fbf56e5a6373eabbfd56db35983b90 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_framework.hxx"
// my own includes
#include <toolbarlayoutmanager.hxx>
#include <helpers.hxx>
#include <services.h>
#include <classes/resource.hrc>
#include <classes/fwkresid.hxx>
#include <uiconfiguration/windowstateconfiguration.hxx>
// interface includes
#include <com/sun/star/awt/PosSize.hpp>
#include <com/sun/star/ui/UIElementType.hpp>
#include <com/sun/star/container/XNameReplace.hpp>
#include <com/sun/star/container/XNameContainer.hpp>
#include <com/sun/star/ui/XUIElementSettings.hpp>
#include <com/sun/star/ui/XUIFunctionListener.hpp>
// other includes
#include <unotools/cmdoptions.hxx>
#include <toolkit/unohlp.hxx>
#include <toolkit/helper/convert.hxx>
#include <toolkit/awt/vclxwindow.hxx>
#include <vcl/i18nhelp.hxx>
#include <vcl/dockingarea.hxx>
#include <boost/bind.hpp>
using namespace ::com::sun::star;
namespace framework
{
ToolbarLayoutManager::ToolbarLayoutManager(
const uno::Reference< lang::XMultiServiceFactory >& xSMGR,
const uno::Reference< ui::XUIElementFactory >& xUIElementFactory,
ILayoutNotifications* pParentLayouter )
: ThreadHelpBase( &Application::GetSolarMutex() ),
m_xSMGR( xSMGR ),
m_xUIElementFactoryManager( xUIElementFactory ),
m_pParentLayouter( pParentLayouter ),
m_eDockOperation( DOCKOP_ON_COLROW ),
m_pAddonOptions( 0 ),
m_pGlobalSettings( 0 ),
m_bComponentAttached( false ),
m_bMustLayout( false ),
m_bLayoutDirty( false ),
m_bStoreWindowState( false ),
m_bGlobalSettings( false ),
m_bDockingInProgress( false ),
m_bVisible( true ),
m_bLayoutInProgress( false ),
m_bToolbarCreation( false ),
m_aFullAddonTbxPrefix( RTL_CONSTASCII_USTRINGPARAM( "private:resource/toolbar/addon_" )),
m_aCustomTbxPrefix( RTL_CONSTASCII_USTRINGPARAM( "custom_" )),
m_aCustomizeCmd( RTL_CONSTASCII_USTRINGPARAM( "ConfigureDialog" )),
m_aToolbarTypeString( RTL_CONSTASCII_USTRINGPARAM( UIRESOURCETYPE_TOOLBAR ))
{
// initialize rectangles to zero values
setZeroRectangle( m_aDockingAreaOffsets );
setZeroRectangle( m_aDockingArea );
// create toolkit object
m_xToolkit = uno::Reference< awt::XToolkit >( m_xSMGR->createInstance( SERVICENAME_VCLTOOLKIT ), uno::UNO_QUERY );
}
ToolbarLayoutManager::~ToolbarLayoutManager()
{
}
//---------------------------------------------------------------------------------------------------------
// XInterface
//---------------------------------------------------------------------------------------------------------
void SAL_CALL ToolbarLayoutManager::acquire() throw()
{
OWeakObject::acquire();
}
void SAL_CALL ToolbarLayoutManager::release() throw()
{
OWeakObject::release();
}
uno::Any SAL_CALL ToolbarLayoutManager::queryInterface( const uno::Type & rType ) throw( uno::RuntimeException )
{
uno::Any a = ::cppu::queryInterface( rType,
SAL_STATIC_CAST( awt::XDockableWindowListener*, this ),
SAL_STATIC_CAST( ui::XUIConfigurationListener*, this ),
SAL_STATIC_CAST( awt::XWindowListener*, this ));
if ( a.hasValue() )
return a;
return OWeakObject::queryInterface( rType );
}
void SAL_CALL ToolbarLayoutManager::disposing( const lang::EventObject& aEvent ) throw( uno::RuntimeException )
{
if ( aEvent.Source == m_xFrame )
{
// Reset all internal references
reset();
implts_destroyDockingAreaWindows();
}
}
awt::Rectangle ToolbarLayoutManager::getDockingArea()
{
WriteGuard aWriteLock( m_aLock );
Rectangle aNewDockingArea( m_aDockingArea );
aWriteLock.unlock();
if ( isLayoutDirty() )
aNewDockingArea = implts_calcDockingArea();
aWriteLock.lock();
m_aDockingArea = aNewDockingArea;
aWriteLock.unlock();
return putRectangleValueToAWT(aNewDockingArea);
}
void ToolbarLayoutManager::setDockingArea( const awt::Rectangle& rDockingArea )
{
WriteGuard aWriteLock( m_aLock );
m_aDockingArea = putAWTToRectangle( rDockingArea );
m_bLayoutDirty = true;
aWriteLock.unlock();
}
void ToolbarLayoutManager::implts_setDockingAreaWindowSizes( const awt::Rectangle& rBorderSpace )
{
ReadGuard aReadLock( m_aLock );
Rectangle aDockOffsets = m_aDockingAreaOffsets;
uno::Reference< awt::XWindow2 > xContainerWindow( m_xContainerWindow );
uno::Reference< awt::XWindow > xTopDockAreaWindow( m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_TOP] );
uno::Reference< awt::XWindow > xBottomDockAreaWindow( m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_BOTTOM] );
uno::Reference< awt::XWindow > xLeftDockAreaWindow( m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_LEFT] );
uno::Reference< awt::XWindow > xRightDockAreaWindow( m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_RIGHT] );
aReadLock.unlock();
uno::Reference< awt::XDevice > xDevice( xContainerWindow, uno::UNO_QUERY );
// Convert relativ size to output size.
awt::Rectangle aRectangle = xContainerWindow->getPosSize();
awt::DeviceInfo aInfo = xDevice->getInfo();
awt::Size aContainerClientSize = awt::Size( aRectangle.Width - aInfo.LeftInset - aInfo.RightInset ,
aRectangle.Height - aInfo.TopInset - aInfo.BottomInset );
long aStatusBarHeight = aDockOffsets.GetHeight();
sal_Int32 nLeftRightDockingAreaHeight( aContainerClientSize.Height );
if ( rBorderSpace.Y >= 0 )
{
// Top docking area window
xTopDockAreaWindow->setPosSize( 0, 0, aContainerClientSize.Width, rBorderSpace.Y, awt::PosSize::POSSIZE );
xTopDockAreaWindow->setVisible( sal_True );
nLeftRightDockingAreaHeight -= rBorderSpace.Y;
}
if ( rBorderSpace.Height >= 0 )
{
// Bottom docking area window
sal_Int32 nBottomPos = std::max( sal_Int32( aContainerClientSize.Height - rBorderSpace.Height - aStatusBarHeight ), sal_Int32( 0 ));
sal_Int32 nHeight = ( nBottomPos == 0 ) ? 0 : rBorderSpace.Height;
xBottomDockAreaWindow->setPosSize( 0, nBottomPos, aContainerClientSize.Width, nHeight, awt::PosSize::POSSIZE );
xBottomDockAreaWindow->setVisible( sal_True );
nLeftRightDockingAreaHeight -= nHeight;
}
nLeftRightDockingAreaHeight -= aStatusBarHeight;
if ( rBorderSpace.X >= 0 || nLeftRightDockingAreaHeight > 0 )
{
// Left docking area window
// We also have to change our right docking area window if the top or bottom area has changed. They have a higher priority!
sal_Int32 nHeight = std::max( sal_Int32( 0 ), sal_Int32( nLeftRightDockingAreaHeight ));
xLeftDockAreaWindow->setPosSize( 0, rBorderSpace.Y, rBorderSpace.X, nHeight, awt::PosSize::POSSIZE );
xLeftDockAreaWindow->setVisible( sal_True );
}
if ( rBorderSpace.Width >= 0 || nLeftRightDockingAreaHeight > 0 )
{
// Right docking area window
// We also have to change our right docking area window if the top or bottom area has changed. They have a higher priority!
sal_Int32 nLeftPos = std::max( sal_Int32( 0 ), sal_Int32( aContainerClientSize.Width - rBorderSpace.Width ));
sal_Int32 nHeight = std::max( sal_Int32( 0 ), sal_Int32( nLeftRightDockingAreaHeight ));
sal_Int32 nWidth = ( nLeftPos == 0 ) ? 0 : rBorderSpace.Width;
xRightDockAreaWindow->setPosSize( nLeftPos, rBorderSpace.Y, nWidth, nHeight, awt::PosSize::POSSIZE );
xRightDockAreaWindow->setVisible( sal_True );
}
}
bool ToolbarLayoutManager::isLayoutDirty()
{
return m_bLayoutDirty;
}
void ToolbarLayoutManager::doLayout(const ::Size& aContainerSize)
{
WriteGuard aWriteLock( m_aLock );
bool bLayoutInProgress( m_bLayoutInProgress );
m_bLayoutInProgress = true;
awt::Rectangle aDockingArea = putRectangleValueToAWT( m_aDockingArea );
aWriteLock.unlock();
if ( bLayoutInProgress )
return;
// Retrieve row/column dependent data from all docked user-interface elements
for ( sal_Int32 i = 0; i < DOCKINGAREAS_COUNT; i++ )
{
bool bReverse( isReverseOrderDockingArea( i ));
std::vector< SingleRowColumnWindowData > aRowColumnsWindowData;
implts_getDockingAreaElementInfos( (ui::DockingArea)i, aRowColumnsWindowData );
sal_Int32 nOffset( 0 );
const sal_uInt32 nCount = aRowColumnsWindowData.size();
for ( sal_uInt32 j = 0; j < nCount; ++j )
{
sal_uInt32 nIndex = bReverse ? nCount-j-1 : j;
implts_calcWindowPosSizeOnSingleRowColumn( i, nOffset, aRowColumnsWindowData[nIndex], aContainerSize );
nOffset += aRowColumnsWindowData[j].nStaticSize;
}
}
implts_setDockingAreaWindowSizes( aDockingArea );
aWriteLock.lock();
m_bLayoutDirty = false;
m_bLayoutInProgress = false;
aWriteLock.unlock();
}
bool ToolbarLayoutManager::implts_isParentWindowVisible() const
{
ReadGuard aReadLock( m_aLock );
bool bVisible( false );
if ( m_xContainerWindow.is() )
bVisible = m_xContainerWindow->isVisible();
return bVisible;
}
Rectangle ToolbarLayoutManager::implts_calcDockingArea()
{
ReadGuard aReadLock( m_aLock );
UIElementVector aWindowVector( m_aUIElements );
aReadLock.unlock();
Rectangle aBorderSpace;
sal_Int32 nCurrRowColumn( 0 );
sal_Int32 nCurrPos( 0 );
sal_Int32 nCurrDockingArea( ui::DockingArea_DOCKINGAREA_TOP );
std::vector< sal_Int32 > aRowColumnSizes[DOCKINGAREAS_COUNT];
UIElementVector::const_iterator pConstIter;
// initialize rectangle with zero values!
aBorderSpace.setWidth(0);
aBorderSpace.setHeight(0);
aRowColumnSizes[nCurrDockingArea].clear();
aRowColumnSizes[nCurrDockingArea].push_back( 0 );
for ( pConstIter = aWindowVector.begin(); pConstIter != aWindowVector.end(); pConstIter++ )
{
uno::Reference< ui::XUIElement > xUIElement( pConstIter->m_xUIElement, uno::UNO_QUERY );
if ( xUIElement.is() )
{
uno::Reference< awt::XWindow > xWindow( xUIElement->getRealInterface(), uno::UNO_QUERY );
uno::Reference< awt::XDockableWindow > xDockWindow( xWindow, uno::UNO_QUERY );
if ( xWindow.is() && xDockWindow.is() )
{
vos::OGuard aGuard( Application::GetSolarMutex() );
Window* pWindow = VCLUnoHelper::GetWindow( xWindow );
if ( pWindow && !xDockWindow->isFloating() && pConstIter->m_bVisible )
{
awt::Rectangle aPosSize = xWindow->getPosSize();
if ( pConstIter->m_aDockedData.m_nDockedArea != nCurrDockingArea )
{
nCurrDockingArea = pConstIter->m_aDockedData.m_nDockedArea;
nCurrRowColumn = 0;
nCurrPos = 0;
aRowColumnSizes[nCurrDockingArea].clear();
aRowColumnSizes[nCurrDockingArea].push_back( 0 );
}
if ( pConstIter->m_aDockedData.m_nDockedArea == nCurrDockingArea )
{
if ( isHorizontalDockingArea( pConstIter->m_aDockedData.m_nDockedArea ))
{
if ( pConstIter->m_aDockedData.m_aPos.Y() > nCurrPos )
{
++nCurrRowColumn;
nCurrPos = pConstIter->m_aDockedData.m_aPos.Y();
aRowColumnSizes[nCurrDockingArea].push_back( 0 );
}
if ( aPosSize.Height > aRowColumnSizes[nCurrDockingArea][nCurrRowColumn] )
aRowColumnSizes[nCurrDockingArea][nCurrRowColumn] = aPosSize.Height;
}
else
{
if ( pConstIter->m_aDockedData.m_aPos.X() > nCurrPos )
{
++nCurrRowColumn;
nCurrPos = pConstIter->m_aDockedData.m_aPos.X();
aRowColumnSizes[nCurrDockingArea].push_back( 0 );
}
if ( aPosSize.Width > aRowColumnSizes[nCurrDockingArea][nCurrRowColumn] )
aRowColumnSizes[nCurrDockingArea][nCurrRowColumn] = aPosSize.Width;
}
}
}
}
}
}
// Sum up max heights from every row/column
if ( !aWindowVector.empty() )
{
for ( sal_Int32 i = 0; i <= ui::DockingArea_DOCKINGAREA_RIGHT; i++ )
{
sal_Int32 nSize( 0 );
const sal_uInt32 nCount = aRowColumnSizes[i].size();
for ( sal_uInt32 j = 0; j < nCount; j++ )
nSize += aRowColumnSizes[i][j];
if ( i == ui::DockingArea_DOCKINGAREA_TOP )
aBorderSpace.Top() = nSize;
else if ( i == ui::DockingArea_DOCKINGAREA_BOTTOM )
aBorderSpace.Bottom() = nSize;
else if ( i == ui::DockingArea_DOCKINGAREA_LEFT )
aBorderSpace.Left() = nSize;
else
aBorderSpace.Right() = nSize;
}
}
return aBorderSpace;
}
void ToolbarLayoutManager::reset()
{
WriteGuard aWriteLock( m_aLock );
uno::Reference< ui::XUIConfigurationManager > xModuleCfgMgr( m_xModuleCfgMgr );
uno::Reference< ui::XUIConfigurationManager > xDocCfgMgr( m_xDocCfgMgr );
m_xModuleCfgMgr.clear();
m_xDocCfgMgr.clear();
m_bComponentAttached = false;
aWriteLock.unlock();
destroyToolbars();
resetDockingArea();
}
void ToolbarLayoutManager::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 )
{
// reset toolbar manager if we lose our current frame
if ( m_xFrame.is() && m_xFrame != xFrame )
reset();
WriteGuard aWriteLock( m_aLock );
m_xFrame = xFrame;
m_xModuleCfgMgr = xModuleCfgMgr;
m_xDocCfgMgr = xDocCfgMgr;
m_xPersistentWindowState = xPersistentWindowState;
m_bComponentAttached = true;
}
void ToolbarLayoutManager::createStaticToolbars()
{
resetDockingArea();
implts_createCustomToolBars();
implts_createAddonsToolBars();
implts_createNonContextSensitiveToolBars();
implts_sortUIElements();
}
bool ToolbarLayoutManager::requestToolbar( const ::rtl::OUString& rResourceURL )
{
bool bNotify( false );
bool bMustCallCreate( false );
uno::Reference< ui::XUIElement > xUIElement;
ReadGuard aReadLock( m_aLock );
uno::Reference< frame::XFrame > xFrame( m_xFrame );
aReadLock.unlock();
uno::Reference< frame::XModel > xModel( impl_getModelFromFrame( xFrame ));
if ( implts_isPreviewModel( xModel ))
return false; // no toolbars for preview frame!
UIElement aRequestedToolbar = impl_findToolbar( rResourceURL );
if ( aRequestedToolbar.m_aName != rResourceURL )
{
bMustCallCreate = true;
aRequestedToolbar.m_aName = rResourceURL;
aRequestedToolbar.m_aType = m_aToolbarTypeString;
aRequestedToolbar.m_xUIElement = xUIElement;
implts_readWindowStateData( rResourceURL, aRequestedToolbar );
}
xUIElement = aRequestedToolbar.m_xUIElement;
if ( !xUIElement.is() )
bMustCallCreate = true;
bool bCreateOrShowToolbar( aRequestedToolbar.m_bVisible & !aRequestedToolbar.m_bMasterHide );
uno::Reference< awt::XWindow2 > xContainerWindow( m_xContainerWindow, uno::UNO_QUERY );
if ( xContainerWindow.is() && aRequestedToolbar.m_bFloating )
bCreateOrShowToolbar &= bool( xContainerWindow->isActive());
if ( bCreateOrShowToolbar )
bNotify = ( bMustCallCreate ) ? createToolbar( rResourceURL ) : showToolbar( rResourceURL );
return bNotify;
}
bool ToolbarLayoutManager::createToolbar( const ::rtl::OUString& rResourceURL )
{
bool bNotify( false );
uno::Reference< ui::XUIElement > xUITempElement;
implts_createToolBar( rResourceURL, bNotify, xUITempElement );
return bNotify;
}
bool ToolbarLayoutManager::destroyToolbar( const ::rtl::OUString& rResourceURL )
{
const rtl::OUString aAddonTbResourceName( RTL_CONSTASCII_USTRINGPARAM( "private:resource/toolbar/addon_" ));
UIElementVector::iterator pIter;
uno::Reference< lang::XComponent > xComponent;
bool bNotify( false );
bool bMustBeSorted( false );
bool bMustLayouted( false );
bool bMustBeDestroyed( rResourceURL.indexOf( aAddonTbResourceName ) != 0 );
WriteGuard aWriteLock( m_aLock );
for ( pIter = m_aUIElements.begin(); pIter != m_aUIElements.end(); pIter++ )
{
if ( pIter->m_aName == rResourceURL )
{
xComponent.set( pIter->m_xUIElement, uno::UNO_QUERY );
if ( bMustBeDestroyed )
pIter->m_xUIElement.clear();
else
pIter->m_bVisible = false;
break;
}
}
aWriteLock.unlock();
uno::Reference< ui::XUIElement > xUIElement( xComponent, uno::UNO_QUERY );
if ( xUIElement.is() )
{
uno::Reference< awt::XWindow > xWindow( xUIElement->getRealInterface(), uno::UNO_QUERY );
uno::Reference< awt::XDockableWindow > xDockWindow( xWindow, uno::UNO_QUERY );
if ( bMustBeDestroyed )
{
try
{
if ( xWindow.is() )
xWindow->removeWindowListener( uno::Reference< awt::XWindowListener >(
static_cast< OWeakObject * >( this ), uno::UNO_QUERY ));
}
catch( uno::Exception& ) {}
try
{
if ( xDockWindow.is() )
xDockWindow->removeDockableWindowListener( uno::Reference< awt::XDockableWindowListener >(
static_cast< OWeakObject * >( this ), uno::UNO_QUERY ));
}
catch ( uno::Exception& ) {}
}
else
{
if ( xWindow.is() )
xWindow->setVisible( sal_False );
bNotify = true;
}
if ( !xDockWindow->isFloating() )
bMustLayouted = true;
bMustBeSorted = true;
}
if ( bMustBeDestroyed )
{
if ( xComponent.is() )
xComponent->dispose();
bNotify = true;
}
if ( bMustLayouted )
implts_setLayoutDirty();
if ( bMustBeSorted )
implts_sortUIElements();
return bNotify;
}
void ToolbarLayoutManager::destroyToolbars()
{
UIElementVector aUIElementVector;
implts_getUIElementVectorCopy( aUIElementVector );
WriteGuard aWriteLock( m_aLock );
m_aUIElements.clear();
m_bLayoutDirty = true;
aWriteLock.unlock();
UIElementVector::iterator pIter;
for ( pIter = aUIElementVector.begin(); pIter != aUIElementVector.end(); pIter++ )
{
uno::Reference< lang::XComponent > xComponent( pIter->m_xUIElement, uno::UNO_QUERY );
if ( xComponent.is() )
xComponent->dispose();
}
}
bool ToolbarLayoutManager::showToolbar( const ::rtl::OUString& rResourceURL )
{
UIElement aUIElement = implts_findToolbar( rResourceURL );
vos::OGuard aGuard( Application::GetSolarMutex() );
Window* pWindow = getWindowFromXUIElement( aUIElement.m_xUIElement );
if ( pWindow )
{
if ( !aUIElement.m_bFloating )
implts_setLayoutDirty();
else
pWindow->Show( sal_True, SHOW_NOFOCUSCHANGE | SHOW_NOACTIVATE );
aUIElement.m_bVisible = true;
implts_writeWindowStateData( aUIElement );
implts_setToolbar( aUIElement );
return true;
}
return false;
}
bool ToolbarLayoutManager::hideToolbar( const ::rtl::OUString& rResourceURL )
{
UIElement aUIElement = implts_findToolbar( rResourceURL );
vos::OGuard aGuard( Application::GetSolarMutex() );
Window* pWindow = getWindowFromXUIElement( aUIElement.m_xUIElement );
if ( pWindow )
{
pWindow->Show( sal_False );
if ( !aUIElement.m_bFloating )
implts_setLayoutDirty();
aUIElement.m_bVisible = false;
implts_writeWindowStateData( aUIElement );
implts_setToolbar( aUIElement );
return true;
}
return false;
}
void ToolbarLayoutManager::refreshToolbarsVisibility( bool bAutomaticToolbars )
{
UIElementVector aUIElementVector;
ReadGuard aReadLock( m_aLock );
bool bVisible( m_bVisible );
aReadLock.unlock();
if ( !bVisible || !bAutomaticToolbars )
return;
implts_getUIElementVectorCopy( aUIElementVector );
UIElement aUIElement;
vos::OGuard aGuard( Application::GetSolarMutex() );
UIElementVector::iterator pIter;
for ( pIter = aUIElementVector.begin(); pIter != aUIElementVector.end(); pIter++ )
{
if ( implts_readWindowStateData( pIter->m_aName, aUIElement ) &&
( pIter->m_bVisible != aUIElement.m_bVisible ) && !pIter->m_bMasterHide )
{
WriteGuard aWriteLock( m_aLock );
UIElement& rUIElement = impl_findToolbar( pIter->m_aName );
if ( rUIElement.m_aName == pIter->m_aName )
{
rUIElement.m_bVisible = aUIElement.m_bVisible;
implts_setLayoutDirty();
}
}
}
}
void ToolbarLayoutManager::setFloatingToolbarsVisibility( bool bVisible )
{
UIElementVector aUIElementVector;
implts_getUIElementVectorCopy( aUIElementVector );
vos::OGuard aGuard( Application::GetSolarMutex() );
UIElementVector::iterator pIter;
for ( pIter = aUIElementVector.begin(); pIter != aUIElementVector.end(); pIter++ )
{
Window* pWindow = getWindowFromXUIElement( pIter->m_xUIElement );
if ( pWindow && pIter->m_bFloating )
{
if ( bVisible )
{
if ( pIter->m_bVisible && !pIter->m_bMasterHide )
pWindow->Show( sal_True, SHOW_NOFOCUSCHANGE | SHOW_NOACTIVATE );
}
else
pWindow->Show( sal_False );
}
}
}
void ToolbarLayoutManager::setVisible( bool bVisible )
{
UIElementVector aUIElementVector;
implts_getUIElementVectorCopy( aUIElementVector );
vos::OGuard aGuard( Application::GetSolarMutex() );
UIElementVector::iterator pIter;
for ( pIter = aUIElementVector.begin(); pIter != aUIElementVector.end(); pIter++ )
{
pIter->m_bMasterHide = !bVisible;
Window* pWindow = getWindowFromXUIElement( pIter->m_xUIElement );
if ( pWindow )
{
bool bSetVisible( pIter->m_bVisible & bVisible );
if ( !bSetVisible )
pWindow->Hide();
else
{
if ( pIter->m_bFloating )
pWindow->Show(true, SHOW_NOFOCUSCHANGE | SHOW_NOACTIVATE );
else
implts_setLayoutDirty();
}
}
}
if ( !bVisible )
resetDockingArea();
}
bool ToolbarLayoutManager::dockToolbar( const ::rtl::OUString& rResourceURL, ui::DockingArea eDockingArea, const awt::Point& aPos )
{
UIElement aUIElement = implts_findToolbar( rResourceURL );
if ( aUIElement.m_xUIElement.is() )
{
try
{
uno::Reference< awt::XWindow > xWindow( aUIElement.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
uno::Reference< awt::XDockableWindow > xDockWindow( xWindow, uno::UNO_QUERY );
if ( xDockWindow.is() )
{
if ( eDockingArea != ui::DockingArea_DOCKINGAREA_DEFAULT )
aUIElement.m_aDockedData.m_nDockedArea = sal_Int16( eDockingArea );
if ( !isDefaultPos( aPos ))
aUIElement.m_aDockedData.m_aPos = ::Point( aPos.X, aPos.Y );
if ( !xDockWindow->isFloating() )
{
Window* pWindow( 0 );
ToolBox* pToolBox( 0 );
{
vos::OGuard aGuard( Application::GetSolarMutex() );
pWindow = VCLUnoHelper::GetWindow( xWindow );
if ( pWindow && pWindow->GetType() == WINDOW_TOOLBOX )
{
pToolBox = (ToolBox *)pWindow;
// We have to set the alignment of the toolbox. It's possible that the toolbox is moved from a
// horizontal to a vertical docking area!
pToolBox->SetAlign( ImplConvertAlignment( aUIElement.m_aDockedData.m_nDockedArea ));
}
}
if ( hasDefaultPosValue( aUIElement.m_aDockedData.m_aPos ))
{
// Docking on its default position without a preset position -
// we have to find a good place for it.
::Size aSize;
vos::OGuard aGuard( Application::GetSolarMutex() );
{
if ( pToolBox )
aSize = pToolBox->CalcWindowSizePixel( 1, ImplConvertAlignment( aUIElement.m_aDockedData.m_nDockedArea ) );
else
aSize = pWindow->GetSizePixel();
}
::Point aPixelPos;
::Point aDockPos;
implts_findNextDockingPos((ui::DockingArea)aUIElement.m_aDockedData.m_nDockedArea, aSize, aDockPos, aPixelPos );
aUIElement.m_aDockedData.m_aPos = aDockPos;
}
}
implts_setToolbar( aUIElement );
if ( xDockWindow->isFloating() )
{
// ATTENTION: This will call toggleFloatingMode() via notifications which
// sets the floating member of the UIElement correctly!
xDockWindow->setFloatingMode( sal_False );
}
else
{
implts_writeWindowStateData( aUIElement );
implts_sortUIElements();
if ( aUIElement.m_bVisible )
implts_setLayoutDirty();
}
return true;
}
}
catch ( lang::DisposedException& ) {}
}
return false;
}
bool ToolbarLayoutManager::dockAllToolbars()
{
std::vector< ::rtl::OUString > aToolBarNameVector;
::rtl::OUString aElementType;
::rtl::OUString aElementName;
ReadGuard aReadLock( m_aLock );
UIElementVector::iterator pIter;
for ( pIter = m_aUIElements.begin(); pIter != m_aUIElements.end(); pIter++ )
{
if ( pIter->m_aType.equalsAscii( "toolbar" ) && pIter->m_xUIElement.is() &&
pIter->m_bFloating && pIter->m_bVisible )
aToolBarNameVector.push_back( pIter->m_aName );
}
aReadLock.unlock();
bool bResult(true);
const sal_uInt32 nCount = aToolBarNameVector.size();
for ( sal_uInt32 i = 0; i < nCount; ++i )
{
awt::Point aPoint;
aPoint.X = aPoint.Y = SAL_MAX_INT32;
bResult &= dockToolbar( aToolBarNameVector[i], ui::DockingArea_DOCKINGAREA_DEFAULT, aPoint );
}
return bResult;
}
long ToolbarLayoutManager::childWindowEvent( VclSimpleEvent* pEvent )
{
// To enable toolbar controllers to change their image when a sub-toolbar function
// is activated, we need this mechanism. We have NO connection between these toolbars
// anymore!
if ( pEvent && pEvent->ISA( VclWindowEvent ))
{
if ( pEvent->GetId() == VCLEVENT_TOOLBOX_SELECT )
{
::rtl::OUString aToolbarName;
::rtl::OUString aCommand;
ToolBox* pToolBox = getToolboxPtr( ((VclWindowEvent*)pEvent)->GetWindow() );
if ( pToolBox )
{
aToolbarName = retrieveToolbarNameFromHelpURL( pToolBox );
sal_uInt16 nId = pToolBox->GetCurItemId();
if ( nId > 0 )
aCommand = pToolBox->GetItemCommand( nId );
}
if (( aToolbarName.getLength() > 0 ) && ( aCommand.getLength() > 0 ))
{
ReadGuard aReadLock( m_aLock );
::std::vector< uno::Reference< ui::XUIFunctionListener > > aListenerArray;
UIElementVector::iterator pIter;
for ( pIter = m_aUIElements.begin(); pIter != m_aUIElements.end(); pIter++ )
{
if ( pIter->m_xUIElement.is() )
{
uno::Reference< ui::XUIFunctionListener > xListener( pIter->m_xUIElement, uno::UNO_QUERY );
if ( xListener.is() )
aListenerArray.push_back( xListener );
}
}
aReadLock.unlock();
const sal_uInt32 nCount = aListenerArray.size();
for ( sal_uInt32 i = 0; i < nCount; ++i )
{
try { aListenerArray[i]->functionExecute( aToolbarName, aCommand ); }
catch ( uno::RuntimeException& ) { throw; }
catch ( uno::Exception& ) {}
}
}
}
else if ( pEvent->GetId() == VCLEVENT_TOOLBOX_FORMATCHANGED )
{
if ( !implts_isToolbarCreationActive() )
{
ToolBox* pToolBox = getToolboxPtr( ((VclWindowEvent*)pEvent)->GetWindow() );
if ( pToolBox )
{
::rtl::OUString aToolbarName = retrieveToolbarNameFromHelpURL( pToolBox );
if ( aToolbarName.getLength() > 0 )
{
::rtl::OUStringBuffer aBuf(100);
aBuf.appendAscii( "private:resource/toolbar/" );
aBuf.append( aToolbarName );
UIElement aToolbar = implts_findToolbar( aBuf.makeStringAndClear() );
if ( aToolbar.m_xUIElement.is() && !aToolbar.m_bFloating )
{
implts_setLayoutDirty();
m_pParentLayouter->requestLayout( ILayoutNotifications::HINT_TOOLBARSPACE_HAS_CHANGED );
}
}
}
}
}
}
return 1;
}
void ToolbarLayoutManager::resetDockingArea()
{
ReadGuard aReadLock( m_aLock );
uno::Reference< awt::XWindow > xTopDockingWindow( m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_TOP] );
uno::Reference< awt::XWindow > xLeftDockingWindow( m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_LEFT] );
uno::Reference< awt::XWindow > xRightDockingWindow( m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_RIGHT] );
uno::Reference< awt::XWindow > xBottomDockingWindow( m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_BOTTOM] );
aReadLock.unlock();
if ( xTopDockingWindow.is() )
xTopDockingWindow->setPosSize( 0, 0, 0, 0, awt::PosSize::POSSIZE );
if ( xLeftDockingWindow.is() )
xLeftDockingWindow->setPosSize( 0, 0, 0, 0, awt::PosSize::POSSIZE );
if ( xRightDockingWindow.is() )
xRightDockingWindow->setPosSize( 0, 0, 0, 0, awt::PosSize::POSSIZE );
if ( xBottomDockingWindow.is() )
xBottomDockingWindow->setPosSize( 0, 0, 0, 0, awt::PosSize::POSSIZE );
}
void ToolbarLayoutManager::setParentWindow(
const uno::Reference< awt::XWindowPeer >& xParentWindow )
{
static const char DOCKINGAREASTRING[] = "dockingarea";
uno::Reference< awt::XWindow > xTopDockWindow = uno::Reference< awt::XWindow >( createToolkitWindow( m_xSMGR, xParentWindow, DOCKINGAREASTRING ), uno::UNO_QUERY );
uno::Reference< awt::XWindow > xLeftDockWindow = uno::Reference< awt::XWindow >( createToolkitWindow( m_xSMGR, xParentWindow, DOCKINGAREASTRING ), uno::UNO_QUERY );
uno::Reference< awt::XWindow > xRightDockWindow = uno::Reference< awt::XWindow >( createToolkitWindow( m_xSMGR, xParentWindow, DOCKINGAREASTRING ), uno::UNO_QUERY );
uno::Reference< awt::XWindow > xBottomDockWindow = uno::Reference< awt::XWindow >( createToolkitWindow( m_xSMGR, xParentWindow, DOCKINGAREASTRING ), uno::UNO_QUERY );
WriteGuard aWriteLock( m_aLock );
m_xContainerWindow = uno::Reference< awt::XWindow2 >( xParentWindow, uno::UNO_QUERY );
m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_TOP] = xTopDockWindow;
m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_LEFT] = xLeftDockWindow;
m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_RIGHT] = xRightDockWindow;
m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_BOTTOM] = xBottomDockWindow;
aWriteLock.unlock();
if ( xParentWindow.is() )
{
vos::OGuard aGuard( Application::GetSolarMutex() );
::DockingAreaWindow* pWindow = dynamic_cast< ::DockingAreaWindow* >(VCLUnoHelper::GetWindow( xTopDockWindow ) );
if( pWindow ) pWindow->SetAlign( WINDOWALIGN_TOP );
pWindow = dynamic_cast< ::DockingAreaWindow* >(VCLUnoHelper::GetWindow( xBottomDockWindow ) );
if( pWindow ) pWindow->SetAlign( WINDOWALIGN_BOTTOM );
pWindow = dynamic_cast< ::DockingAreaWindow* >(VCLUnoHelper::GetWindow( xLeftDockWindow ) );
if( pWindow ) pWindow->SetAlign( WINDOWALIGN_LEFT );
pWindow = dynamic_cast< ::DockingAreaWindow* >(VCLUnoHelper::GetWindow( xRightDockWindow ) );
if( pWindow ) pWindow->SetAlign( WINDOWALIGN_RIGHT );
implts_reparentToolbars();
}
else
{
destroyToolbars();
resetDockingArea();
}
}
void ToolbarLayoutManager::setDockingAreaOffsets( const ::Rectangle aOffsets )
{
WriteGuard aWriteLock( m_aLock );
m_aDockingAreaOffsets = aOffsets;
m_bLayoutDirty = true;
}
rtl::OUString ToolbarLayoutManager::implts_generateGenericAddonToolbarTitle( sal_Int32 nNumber ) const
{
String aAddonGenericTitle;
aAddonGenericTitle = String( FwkResId( STR_TOOLBAR_TITLE_ADDON ));
const vcl::I18nHelper& rI18nHelper = Application::GetSettings().GetUILocaleI18nHelper();
String aNumStr = rI18nHelper.GetNum( nNumber, 0, sal_False, sal_False );
aAddonGenericTitle.SearchAndReplaceAscii( "%num%", aNumStr );
return rtl::OUString( aAddonGenericTitle );
}
void ToolbarLayoutManager::implts_createAddonsToolBars()
{
WriteGuard aWriteLock( m_aLock );
if ( !m_pAddonOptions )
m_pAddonOptions = new AddonsOptions;
uno::Reference< ui::XUIElementFactory > xUIElementFactory( m_xUIElementFactoryManager );
uno::Reference< frame::XFrame > xFrame( m_xFrame );
aWriteLock.unlock();
uno::Reference< frame::XModel > xModel( impl_getModelFromFrame( xFrame ));
if ( implts_isPreviewModel( xModel ))
return; // no addon toolbars for preview frame!
UIElementVector aUIElementVector;
uno::Sequence< uno::Sequence< beans::PropertyValue > > aAddonToolBarData;
uno::Reference< ui::XUIElement > xUIElement;
sal_uInt32 nCount = m_pAddonOptions->GetAddonsToolBarCount();
::rtl::OUString aAddonsToolBarStaticName( m_aFullAddonTbxPrefix );
::rtl::OUString aElementType( RTL_CONSTASCII_USTRINGPARAM( "toolbar" ));
uno::Sequence< beans::PropertyValue > aPropSeq( 2 );
aPropSeq[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Frame" ));
aPropSeq[0].Value <<= xFrame;
aPropSeq[1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ConfigurationData" ));
for ( sal_uInt32 i = 0; i < nCount; i++ )
{
::rtl::OUString aAddonToolBarName( aAddonsToolBarStaticName + m_pAddonOptions->GetAddonsToolbarResourceName(i) );
aAddonToolBarData = m_pAddonOptions->GetAddonsToolBarPart( i );
aPropSeq[1].Value <<= aAddonToolBarData;
UIElement aElement = implts_findToolbar( aAddonToolBarName );
// #i79828
// It's now possible that we are called more than once. Be sure to not create
// add-on toolbars more than once!
if ( aElement.m_xUIElement.is() )
continue;
try
{
xUIElement = xUIElementFactory->createUIElement( aAddonToolBarName, aPropSeq );
if ( xUIElement.is() )
{
uno::Reference< awt::XDockableWindow > xDockWindow( xUIElement->getRealInterface(), uno::UNO_QUERY );
if ( xDockWindow.is() )
{
try
{
xDockWindow->addDockableWindowListener( uno::Reference< awt::XDockableWindowListener >( static_cast< OWeakObject * >( this ), uno::UNO_QUERY ));
xDockWindow->enableDocking( sal_True );
uno::Reference< awt::XWindow > xWindow( xDockWindow, uno::UNO_QUERY );
if ( xWindow.is() )
xWindow->addWindowListener( uno::Reference< awt::XWindowListener >( static_cast< OWeakObject * >( this ), uno::UNO_QUERY ));
}
catch ( uno::Exception& ) {}
}
::rtl::OUString aAddonUIName = m_pAddonOptions->GetAddonsToolbarUIName( i );
const bool bAddonUIName = aAddonUIName.getLength();
::rtl::OUString aAddonTitle = bAddonUIName ?
aAddonUIName : implts_generateGenericAddonToolbarTitle( i+1 );
if ( aElement.m_aName.getLength() > 0 )
{
// Reuse a local entry so we are able to use the latest
// UI changes for this document.
implts_setElementData( aElement, xDockWindow );
aElement.m_xUIElement = xUIElement;
if ( aElement.m_aUIName.getLength() == 0 && !bAddonUIName)
{
aElement.m_aUIName = aAddonTitle;
implts_writeWindowStateData( aElement );
}
}
else
{
// Create new UI element and try to read its state data
UIElement aNewToolbar( aAddonToolBarName, aElementType, xUIElement );
aNewToolbar.m_bFloating = true;
implts_readWindowStateData( aAddonToolBarName, aNewToolbar );
implts_setElementData( aNewToolbar, xDockWindow );
if ( aNewToolbar.m_aUIName.getLength() == 0 && !bAddonUIName)
{
aNewToolbar.m_aUIName = aAddonTitle;
implts_writeWindowStateData( aNewToolbar );
}
implts_insertToolbar( aNewToolbar );
}
uno::Reference< awt::XWindow > xWindow( xDockWindow, uno::UNO_QUERY );
if ( xWindow.is() )
{
// Set generic title for add-on toolbar
vos::OGuard aGuard( Application::GetSolarMutex() );
Window* pWindow = VCLUnoHelper::GetWindow( xWindow );
if ( pWindow->GetText().Len() == 0 )
pWindow->SetText( aAddonTitle );
if ( pWindow->GetType() == WINDOW_TOOLBOX )
{
ToolBox* pToolbar = (ToolBox *)pWindow;
pToolbar->SetMenuType();
}
}
}
}
catch ( container::NoSuchElementException& ) {}
catch ( lang::IllegalArgumentException& ) {}
}
}
void ToolbarLayoutManager::implts_createCustomToolBars()
{
ReadGuard aReadLock( m_aLock );
if ( !m_bComponentAttached )
return;
uno::Reference< ui::XUIElementFactory > xUIElementFactory( m_xUIElementFactoryManager );
uno::Reference< frame::XFrame > xFrame( m_xFrame );
uno::Reference< frame::XModel > xModel;
uno::Reference< ui::XUIConfigurationManager > xModuleCfgMgr( m_xModuleCfgMgr, uno::UNO_QUERY );
uno::Reference< ui::XUIConfigurationManager > xDocCfgMgr( m_xDocCfgMgr, uno::UNO_QUERY );
aReadLock.unlock();
if ( xFrame.is() )
{
xModel = impl_getModelFromFrame( xFrame );
if ( implts_isPreviewModel( xModel ))
return; // no custom toolbars for preview frame!
uno::Sequence< uno::Sequence< beans::PropertyValue > > aTbxSeq;
if ( xDocCfgMgr.is() )
{
aTbxSeq = xDocCfgMgr->getUIElementsInfo( ui::UIElementType::TOOLBAR );
implts_createCustomToolBars( aTbxSeq ); // first create all document based toolbars
}
if ( xModuleCfgMgr.is() )
{
aTbxSeq = xModuleCfgMgr->getUIElementsInfo( ui::UIElementType::TOOLBAR );
implts_createCustomToolBars( aTbxSeq ); // second create module based toolbars
}
}
}
void ToolbarLayoutManager::implts_createNonContextSensitiveToolBars()
{
ReadGuard aReadLock( m_aLock );
if ( !m_xPersistentWindowState.is() || !m_xFrame.is() || !m_bComponentAttached )
return;
uno::Reference< frame::XFrame > xFrame( m_xFrame );
uno::Reference< ui::XUIElementFactory > xUIElementFactory( m_xUIElementFactoryManager );
uno::Reference< container::XNameAccess > xPersistentWindowState( m_xPersistentWindowState );
aReadLock.unlock();
if ( implts_isPreviewModel( impl_getModelFromFrame( xFrame )))
return;
std::vector< rtl::OUString > aMakeVisibleToolbars;
try
{
uno::Sequence< ::rtl::OUString > aToolbarNames = xPersistentWindowState->getElementNames();
if ( aToolbarNames.getLength() > 0 )
{
::rtl::OUString aElementType;
::rtl::OUString aElementName;
::rtl::OUString aName;
uno::Reference< ui::XUIElement > xUIElement;
aMakeVisibleToolbars.reserve(aToolbarNames.getLength());
/* SAFE AREA ----------------------------------------------------------------------------------------------- */
WriteGuard aWriteLock( m_aLock );
const rtl::OUString* pTbNames = aToolbarNames.getConstArray();
for ( sal_Int32 i = 0; i < aToolbarNames.getLength(); i++ )
{
aName = pTbNames[i];
parseResourceURL( aName, aElementType, aElementName );
// Check that we only create:
// - Toolbars (the statusbar is also member of the persistent window state)
// - Not custom toolbars, there are created with their own method (implts_createCustomToolbars)
if ( aElementType.equalsIgnoreAsciiCaseAscii( "toolbar" ) && aElementName.indexOf( m_aCustomTbxPrefix ) == -1 )
{
UIElement aNewToolbar = implts_findToolbar( aName );
bool bFound = ( aNewToolbar.m_aName == aName );
if ( !bFound )
implts_readWindowStateData( aName, aNewToolbar );
if ( aNewToolbar.m_bVisible && !aNewToolbar.m_bContextSensitive )
{
if ( !bFound )
implts_insertToolbar( aNewToolbar );
aMakeVisibleToolbars.push_back( aName );
}
}
}
/* SAFE AREA ----------------------------------------------------------------------------------------------- */
}
}
catch ( uno::RuntimeException& ) { throw; }
catch ( uno::Exception& ) {}
if ( !aMakeVisibleToolbars.empty() )
::std::for_each( aMakeVisibleToolbars.begin(), aMakeVisibleToolbars.end(),::boost::bind( &ToolbarLayoutManager::requestToolbar, this,_1 ));
}
void ToolbarLayoutManager::implts_createCustomToolBars( const uno::Sequence< uno::Sequence< beans::PropertyValue > >& aTbxSeqSeq )
{
const uno::Sequence< beans::PropertyValue >* pTbxSeq = aTbxSeqSeq.getConstArray();
for ( sal_Int32 i = 0; i < aTbxSeqSeq.getLength(); i++ )
{
const uno::Sequence< beans::PropertyValue >& rTbxSeq = pTbxSeq[i];
::rtl::OUString aTbxResName;
::rtl::OUString aTbxTitle;
for ( sal_Int32 j = 0; j < rTbxSeq.getLength(); j++ )
{
if ( rTbxSeq[j].Name.equalsAscii( "ResourceURL" ))
rTbxSeq[j].Value >>= aTbxResName;
else if ( rTbxSeq[j].Name.equalsAscii( "UIName" ))
rTbxSeq[j].Value >>= aTbxTitle;
}
// Only create custom toolbars. Their name have to start with "custom_"!
if ( aTbxResName.getLength() > 0 && aTbxResName.indexOf( m_aCustomTbxPrefix ) != -1 )
implts_createCustomToolBar( aTbxResName, aTbxTitle );
}
}
void ToolbarLayoutManager::implts_createCustomToolBar( const rtl::OUString& aTbxResName, const rtl::OUString& aTitle )
{
if ( aTbxResName.getLength() > 0 )
{
bool bNotify( false );
uno::Reference< ui::XUIElement > xUIElement;
implts_createToolBar( aTbxResName, bNotify, xUIElement );
if ( !aTitle.isEmpty() && xUIElement.is() )
{
vos::OGuard aGuard( Application::GetSolarMutex() );
Window* pWindow = getWindowFromXUIElement( xUIElement );
if ( pWindow )
pWindow->SetText( aTitle );
}
}
}
void ToolbarLayoutManager::implts_reparentToolbars()
{
WriteGuard aWriteLock( m_aLock );
UIElementVector aUIElementVector = m_aUIElements;
Window* pContainerWindow = VCLUnoHelper::GetWindow( m_xContainerWindow );
Window* pTopDockWindow = VCLUnoHelper::GetWindow( m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_TOP] );
Window* pBottomDockWindow = VCLUnoHelper::GetWindow( m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_BOTTOM] );
Window* pLeftDockWindow = VCLUnoHelper::GetWindow( m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_LEFT] );
Window* pRightDockWindow = VCLUnoHelper::GetWindow( m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_RIGHT] );
aWriteLock.unlock();
vos::OGuard aGuard( Application::GetSolarMutex() );
if ( pContainerWindow )
{
UIElementVector::iterator pIter;
for ( pIter = aUIElementVector.begin(); pIter != aUIElementVector.end(); pIter++ )
{
uno::Reference< ui::XUIElement > xUIElement( pIter->m_xUIElement );
if ( xUIElement.is() )
{
uno::Reference< awt::XWindow > xWindow;
try
{
// We have to retreive the window reference with try/catch as it is
// possible that all elements have been disposed!
xWindow = uno::Reference< awt::XWindow >( xUIElement->getRealInterface(), uno::UNO_QUERY );
}
catch ( uno::RuntimeException& ) { throw; }
catch ( uno::Exception& ) {}
Window* pWindow = VCLUnoHelper::GetWindow( xWindow );
if ( pWindow )
{
// Reparent our child windows acording to their current state.
if ( pIter->m_bFloating )
pWindow->SetParent( pContainerWindow );
else
{
if ( pIter->m_aDockedData.m_nDockedArea == ui::DockingArea_DOCKINGAREA_TOP )
pWindow->SetParent( pTopDockWindow );
else if ( pIter->m_aDockedData.m_nDockedArea == ui::DockingArea_DOCKINGAREA_BOTTOM )
pWindow->SetParent( pBottomDockWindow );
else if ( pIter->m_aDockedData.m_nDockedArea == ui::DockingArea_DOCKINGAREA_LEFT )
pWindow->SetParent( pLeftDockWindow );
else
pWindow->SetParent( pRightDockWindow );
}
}
}
}
}
}
void ToolbarLayoutManager::implts_setToolbarCreation( bool bStart )
{
WriteGuard aWriteLock( m_aLock );
m_bToolbarCreation = bStart;
}
bool ToolbarLayoutManager::implts_isToolbarCreationActive()
{
ReadGuard aReadLock( m_aLock );
return m_bToolbarCreation;
}
void ToolbarLayoutManager::implts_createToolBar( const ::rtl::OUString& aName, bool& bNotify, uno::Reference< ui::XUIElement >& rUIElement )
{
ReadGuard aReadLock( m_aLock );
uno::Reference< frame::XFrame > xFrame( m_xFrame );
uno::Reference< awt::XWindow2 > xContainerWindow( m_xContainerWindow );
aReadLock.unlock();
bNotify = false;
if ( !xFrame.is() || !xContainerWindow.is() )
return;
UIElement aToolbarElement = implts_findToolbar( aName );
if ( !aToolbarElement.m_xUIElement.is() )
{
uno::Reference< ui::XUIElement > xUIElement = implts_createElement( aName );
bool bVisible( false );
bool bFloating( false );
if ( xUIElement.is() )
{
rUIElement = xUIElement;
uno::Reference< awt::XWindow > xWindow( xUIElement->getRealInterface(), uno::UNO_QUERY );
uno::Reference< awt::XDockableWindow > xDockWindow( xWindow, uno::UNO_QUERY );
if ( xDockWindow.is() && xWindow.is() )
{
try
{
xDockWindow->addDockableWindowListener( uno::Reference< awt::XDockableWindowListener >(
static_cast< OWeakObject * >( this ), uno::UNO_QUERY ));
xWindow->addWindowListener( uno::Reference< awt::XWindowListener >(
static_cast< OWeakObject * >( this ), uno::UNO_QUERY ));
xDockWindow->enableDocking( sal_True );
}
catch ( uno::Exception& ) {}
}
/* SAFE AREA ----------------------------------------------------------------------------------------------- */
WriteGuard aWriteLock( m_aLock );
UIElement& rElement = impl_findToolbar( aName );
if ( rElement.m_aName.getLength() > 0 )
{
// Reuse a local entry so we are able to use the latest
// UI changes for this document.
implts_setElementData( rElement, xDockWindow );
rElement.m_xUIElement = xUIElement;
bVisible = rElement.m_bVisible;
bFloating = rElement.m_bFloating;
}
else
{
// Create new UI element and try to read its state data
UIElement aNewToolbar( aName, m_aToolbarTypeString, xUIElement );
implts_readWindowStateData( aName, aNewToolbar );
implts_setElementData( aNewToolbar, xDockWindow );
implts_insertToolbar( aNewToolbar );
bVisible = aNewToolbar.m_bVisible;
bFloating = rElement.m_bFloating;
}
aWriteLock.unlock();
/* SAFE AREA ----------------------------------------------------------------------------------------------- */
// set toolbar menu style according to customize command state
SvtCommandOptions aCmdOptions;
vos::OGuard aGuard( Application::GetSolarMutex() );
Window* pWindow = VCLUnoHelper::GetWindow( xWindow );
if ( pWindow && pWindow->GetType() == WINDOW_TOOLBOX )
{
ToolBox* pToolbar = (ToolBox *)pWindow;
sal_uInt16 nMenuType = pToolbar->GetMenuType();
if ( aCmdOptions.Lookup( SvtCommandOptions::CMDOPTION_DISABLED, m_aCustomizeCmd ))
pToolbar->SetMenuType( nMenuType & ~TOOLBOX_MENUTYPE_CUSTOMIZE );
else
pToolbar->SetMenuType( nMenuType | TOOLBOX_MENUTYPE_CUSTOMIZE );
}
bNotify = true;
implts_sortUIElements();
if ( bVisible && !bFloating )
implts_setLayoutDirty();
}
}
}
uno::Reference< ui::XUIElement > ToolbarLayoutManager::implts_createElement( const ::rtl::OUString& aName )
{
uno::Reference< ui::XUIElement > xUIElement;
ReadGuard aReadLock( m_aLock );
uno::Sequence< beans::PropertyValue > aPropSeq( 2 );
aPropSeq[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Frame" ));
aPropSeq[0].Value <<= m_xFrame;
aPropSeq[1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Persistent" ));
aPropSeq[1].Value <<= true;
uno::Reference< ui::XUIElementFactory > xUIElementFactory( m_xUIElementFactoryManager );
aReadLock.unlock();
implts_setToolbarCreation( true );
try
{
if ( xUIElementFactory.is() )
xUIElement = xUIElementFactory->createUIElement( aName, aPropSeq );
}
catch ( container::NoSuchElementException& ) {}
catch ( lang::IllegalArgumentException& ) {}
implts_setToolbarCreation( false );
return xUIElement;
}
void ToolbarLayoutManager::implts_setElementData( UIElement& rElement, const uno::Reference< awt::XDockableWindow >& rDockWindow )
{
ReadGuard aReadLock( m_aLock );
bool bShowElement( rElement.m_bVisible && !rElement.m_bMasterHide && implts_isParentWindowVisible() );
aReadLock.unlock();
uno::Reference< awt::XDockableWindow > xDockWindow( rDockWindow );
uno::Reference< awt::XWindow2 > xWindow( xDockWindow, uno::UNO_QUERY );
Window* pWindow( 0 );
ToolBox* pToolBox( 0 );
if ( xDockWindow.is() && xWindow.is() )
{
{
vos::OGuard aGuard( Application::GetSolarMutex() );
pWindow = VCLUnoHelper::GetWindow( xWindow );
if ( pWindow )
{
String aText = pWindow->GetText();
if ( aText.Len() == 0 )
pWindow->SetText( rElement.m_aUIName );
if ( rElement.m_bNoClose )
pWindow->SetStyle( pWindow->GetStyle() & ~WB_CLOSEABLE );
if ( pWindow->GetType() == WINDOW_TOOLBOX )
pToolBox = (ToolBox *)pWindow;
}
if ( pToolBox )
{
if (( rElement.m_nStyle < 0 ) || ( rElement.m_nStyle > BUTTON_SYMBOLTEXT ))
rElement.m_nStyle = BUTTON_SYMBOL;
pToolBox->SetButtonType( (ButtonType)rElement.m_nStyle );
if ( rElement.m_bNoClose )
pToolBox->SetFloatStyle( pToolBox->GetFloatStyle() & ~WB_CLOSEABLE );
}
}
if ( rElement.m_bFloating )
{
if ( pWindow )
{
vos::OGuard aGuard( Application::GetSolarMutex() );
String aText = pWindow->GetText();
if ( aText.Len() == 0 )
pWindow->SetText( rElement.m_aUIName );
}
::Point aPos( rElement.m_aFloatingData.m_aPos.X(),
rElement.m_aFloatingData.m_aPos.Y() );
bool bWriteData( false );
bool bUndefPos = hasDefaultPosValue( rElement.m_aFloatingData.m_aPos );
bool bSetSize = ( rElement.m_aFloatingData.m_aSize.Width() != 0 &&
rElement.m_aFloatingData.m_aSize.Height() != 0 );
xDockWindow->setFloatingMode( sal_True );
if ( bUndefPos )
{
aPos = implts_findNextCascadeFloatingPos();
rElement.m_aFloatingData.m_aPos = aPos; // set new cascaded position
bWriteData = true;
}
if( bSetSize )
xWindow->setOutputSize( AWTSize( rElement.m_aFloatingData.m_aSize ) );
else
{
if( pToolBox )
{
// set an optimal initial floating size
vos::OGuard aGuard( Application::GetSolarMutex() );
::Size aSize( pToolBox->CalcFloatingWindowSizePixel() );
pToolBox->SetOutputSizePixel( aSize );
}
}
// #i60882# IMPORTANT: Set position after size as it is
// possible that we position some part of the toolbar
// outside of the desktop. A default constructed toolbar
// always has one line. Now VCL automatically
// position the toolbar back into the desktop. Therefore
// we resize the toolbar with the new (wrong) position.
// To fix this problem we have to set the size BEFORE the
// position.
xWindow->setPosSize( aPos.X(), aPos.Y(), 0, 0, awt::PosSize::POS );
if ( bWriteData )
implts_writeWindowStateData( rElement );
if ( bShowElement && pWindow )
{
vos::OGuard aGuard( Application::GetSolarMutex() );
pWindow->Show( sal_True, SHOW_NOFOCUSCHANGE | SHOW_NOACTIVATE );
}
}
else
{
bool bSetSize( false );
::Point aDockPos;
::Point aPixelPos;
::Size aSize;
if ( pToolBox )
{
vos::OGuard aGuard( Application::GetSolarMutex() );
pToolBox->SetAlign( ImplConvertAlignment(rElement.m_aDockedData.m_nDockedArea ) );
pToolBox->SetLineCount( 1 );
xDockWindow->setFloatingMode( sal_False );
if ( rElement.m_aDockedData.m_bLocked )
xDockWindow->lock();
aSize = pToolBox->CalcWindowSizePixel();
bSetSize = true;
if ( isDefaultPos( rElement.m_aDockedData.m_aPos ))
{
implts_findNextDockingPos( (ui::DockingArea)rElement.m_aDockedData.m_nDockedArea, aSize, aDockPos, aPixelPos );
rElement.m_aDockedData.m_aPos = aDockPos;
}
}
xWindow->setPosSize( aPixelPos.X(), aPixelPos.Y(), 0, 0, awt::PosSize::POS );
if( bSetSize )
xWindow->setOutputSize( AWTSize( aSize) );
if ( pWindow )
{
vos::OGuard aGuard( Application::GetSolarMutex() );
if ( !bShowElement )
pWindow->Hide();
}
}
}
}
void ToolbarLayoutManager::implts_destroyDockingAreaWindows()
{
WriteGuard aWriteLock( m_aLock );
uno::Reference< awt::XWindow > xTopDockingWindow( m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_TOP] );
uno::Reference< awt::XWindow > xLeftDockingWindow( m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_LEFT] );
uno::Reference< awt::XWindow > xRightDockingWindow( m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_RIGHT] );
uno::Reference< awt::XWindow > xBottomDockingWindow( m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_BOTTOM] );
m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_TOP].clear();
m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_LEFT].clear();
m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_RIGHT].clear();
m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_BOTTOM].clear();
aWriteLock.unlock();
// destroy windows
xTopDockingWindow->dispose();
xLeftDockingWindow->dispose();
xRightDockingWindow->dispose();
xBottomDockingWindow->dispose();
}
//---------------------------------------------------------------------------------------------------------
// persistence methods
//---------------------------------------------------------------------------------------------------------
sal_Bool ToolbarLayoutManager::implts_readWindowStateData( const rtl::OUString& aName, UIElement& rElementData )
{
WriteGuard aWriteLock( m_aLock );
uno::Reference< container::XNameAccess > xPersistentWindowState( m_xPersistentWindowState );
bool bGetSettingsState( false );
aWriteLock.unlock();
if ( xPersistentWindowState.is() )
{
aWriteLock.lock();
bool bGlobalSettings( m_bGlobalSettings );
GlobalSettings* pGlobalSettings( 0 );
if ( m_pGlobalSettings == 0 )
{
m_pGlobalSettings = new GlobalSettings( m_xSMGR );
bGetSettingsState = true;
}
pGlobalSettings = m_pGlobalSettings;
aWriteLock.unlock();
try
{
uno::Sequence< beans::PropertyValue > aWindowState;
if ( xPersistentWindowState->getByName( aName ) >>= aWindowState )
{
sal_Bool bValue( sal_False );
for ( sal_Int32 n = 0; n < aWindowState.getLength(); n++ )
{
if ( aWindowState[n].Name.equalsAscii( WINDOWSTATE_PROPERTY_DOCKED ))
{
if ( aWindowState[n].Value >>= bValue )
rElementData.m_bFloating = !bValue;
}
else if ( aWindowState[n].Name.equalsAscii( WINDOWSTATE_PROPERTY_VISIBLE ))
{
if ( aWindowState[n].Value >>= bValue )
rElementData.m_bVisible = bValue;
}
else if ( aWindowState[n].Name.equalsAscii( WINDOWSTATE_PROPERTY_DOCKINGAREA ))
{
ui::DockingArea eDockingArea;
if ( aWindowState[n].Value >>= eDockingArea )
rElementData.m_aDockedData.m_nDockedArea = sal_Int16( eDockingArea );
}
else if ( aWindowState[n].Name.equalsAscii( WINDOWSTATE_PROPERTY_DOCKPOS ))
{
awt::Point aPoint;
if ( aWindowState[n].Value >>= aPoint )
{
rElementData.m_aDockedData.m_aPos.X() = aPoint.X;
rElementData.m_aDockedData.m_aPos.Y() = aPoint.Y;
}
}
else if ( aWindowState[n].Name.equalsAscii( WINDOWSTATE_PROPERTY_POS ))
{
awt::Point aPoint;
if ( aWindowState[n].Value >>= aPoint )
{
rElementData.m_aFloatingData.m_aPos.X() = aPoint.X;
rElementData.m_aFloatingData.m_aPos.Y() = aPoint.Y;
}
}
else if ( aWindowState[n].Name.equalsAscii( WINDOWSTATE_PROPERTY_SIZE ))
{
awt::Size aSize;
if ( aWindowState[n].Value >>= aSize )
{
rElementData.m_aFloatingData.m_aSize.Width() = aSize.Width;
rElementData.m_aFloatingData.m_aSize.Height() = aSize.Height;
}
}
else if ( aWindowState[n].Name.equalsAscii( WINDOWSTATE_PROPERTY_UINAME ))
aWindowState[n].Value >>= rElementData.m_aUIName;
else if ( aWindowState[n].Name.equalsAscii( WINDOWSTATE_PROPERTY_STYLE ))
{
sal_Int32 nStyle = 0;
if ( aWindowState[n].Value >>= nStyle )
rElementData.m_nStyle = sal_Int16( nStyle );
}
else if ( aWindowState[n].Name.equalsAscii( WINDOWSTATE_PROPERTY_LOCKED ))
{
if ( aWindowState[n].Value >>= bValue )
rElementData.m_aDockedData.m_bLocked = bValue;
}
else if ( aWindowState[n].Name.equalsAscii( WINDOWSTATE_PROPERTY_CONTEXT ))
{
if ( aWindowState[n].Value >>= bValue )
rElementData.m_bContextSensitive = bValue;
}
else if ( aWindowState[n].Name.equalsAscii( WINDOWSTATE_PROPERTY_NOCLOSE ))
{
if ( aWindowState[n].Value >>= bValue )
rElementData.m_bNoClose = bValue;
}
else if ( aWindowState[n].Name.equalsAscii( WINDOWSTATE_PROPERTY_CONTEXTACTIVE ))
{
if ( aWindowState[n].Value >>= bValue )
rElementData.m_bContextActive = bValue;
}
else if ( aWindowState[n].Name.equalsAscii( WINDOWSTATE_PROPERTY_SOFTCLOSE ))
{
if ( aWindowState[n].Value >>= bValue )
rElementData.m_bSoftClose = bValue;
}
}
}
// oversteer values with global settings
if ( pGlobalSettings && ( bGetSettingsState || bGlobalSettings ))
{
if ( pGlobalSettings->HasStatesInfo( GlobalSettings::UIELEMENT_TYPE_TOOLBAR ))
{
WriteGuard aWriteLock2( m_aLock );
m_bGlobalSettings = true;
aWriteLock2.unlock();
uno::Any aValue;
sal_Bool bValue = sal_Bool();
if ( pGlobalSettings->GetStateInfo( GlobalSettings::UIELEMENT_TYPE_TOOLBAR,
GlobalSettings::STATEINFO_LOCKED,
aValue ))
aValue >>= rElementData.m_aDockedData.m_bLocked;
if ( pGlobalSettings->GetStateInfo( GlobalSettings::UIELEMENT_TYPE_TOOLBAR,
GlobalSettings::STATEINFO_DOCKED,
aValue ))
{
if ( aValue >>= bValue )
rElementData.m_bFloating = !bValue;
}
}
}
return sal_True;
}
catch ( container::NoSuchElementException& ) {}
}
return sal_False;
}
void ToolbarLayoutManager::implts_writeWindowStateData( const UIElement& rElementData )
{
WriteGuard aWriteLock( m_aLock );
uno::Reference< container::XNameAccess > xPersistentWindowState( m_xPersistentWindowState );
m_bStoreWindowState = true; // set flag to determine that we triggered the notification
aWriteLock.unlock();
bool bPersistent( sal_False );
uno::Reference< beans::XPropertySet > xPropSet( rElementData.m_xUIElement, uno::UNO_QUERY );
if ( xPropSet.is() )
{
try
{
// Check persistent flag of the user interface element
xPropSet->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Persistent" ))) >>= bPersistent;
}
catch ( beans::UnknownPropertyException )
{
bPersistent = true; // Non-configurable elements should at least store their dimension/position
}
catch ( lang::WrappedTargetException ) {}
}
if ( bPersistent && xPersistentWindowState.is() )
{
try
{
uno::Sequence< beans::PropertyValue > aWindowState( 9 );
aWindowState[0].Name = ::rtl::OUString::createFromAscii( WINDOWSTATE_PROPERTY_DOCKED );
aWindowState[0].Value = ::uno::makeAny( sal_Bool( !rElementData.m_bFloating ));
aWindowState[1].Name = ::rtl::OUString::createFromAscii( WINDOWSTATE_PROPERTY_VISIBLE );
aWindowState[1].Value = uno::makeAny( sal_Bool( rElementData.m_bVisible ));
aWindowState[2].Name = ::rtl::OUString::createFromAscii( WINDOWSTATE_PROPERTY_DOCKINGAREA );
aWindowState[2].Value = uno::makeAny( static_cast< ui::DockingArea >( rElementData.m_aDockedData.m_nDockedArea ) );
awt::Point aPos;
aPos.X = rElementData.m_aDockedData.m_aPos.X();
aPos.Y = rElementData.m_aDockedData.m_aPos.Y();
aWindowState[3].Name = ::rtl::OUString::createFromAscii( WINDOWSTATE_PROPERTY_DOCKPOS );
aWindowState[3].Value <<= aPos;
aPos.X = rElementData.m_aFloatingData.m_aPos.X();
aPos.Y = rElementData.m_aFloatingData.m_aPos.Y();
aWindowState[4].Name = ::rtl::OUString::createFromAscii( WINDOWSTATE_PROPERTY_POS );
aWindowState[4].Value <<= aPos;
awt::Size aSize;
aSize.Width = rElementData.m_aFloatingData.m_aSize.Width();
aSize.Height = rElementData.m_aFloatingData.m_aSize.Height();
aWindowState[5].Name = ::rtl::OUString::createFromAscii( WINDOWSTATE_PROPERTY_SIZE );
aWindowState[5].Value <<= aSize;
aWindowState[6].Name = ::rtl::OUString::createFromAscii( WINDOWSTATE_PROPERTY_UINAME );
aWindowState[6].Value = uno::makeAny( rElementData.m_aUIName );
aWindowState[7].Name = ::rtl::OUString::createFromAscii( WINDOWSTATE_PROPERTY_LOCKED );
aWindowState[7].Value = uno::makeAny( rElementData.m_aDockedData.m_bLocked );
aWindowState[8].Name = ::rtl::OUString::createFromAscii( WINDOWSTATE_PROPERTY_STYLE );
aWindowState[8].Value = uno::makeAny( rElementData.m_nStyle );
::rtl::OUString aName = rElementData.m_aName;
if ( xPersistentWindowState->hasByName( aName ))
{
uno::Reference< container::XNameReplace > xReplace( xPersistentWindowState, uno::UNO_QUERY );
xReplace->replaceByName( aName, uno::makeAny( aWindowState ));
}
else
{
uno::Reference< container::XNameContainer > xInsert( xPersistentWindowState, uno::UNO_QUERY );
xInsert->insertByName( aName, uno::makeAny( aWindowState ));
}
}
catch ( uno::Exception& ) {}
}
// Reset flag
aWriteLock.lock();
m_bStoreWindowState = false;
aWriteLock.unlock();
}
void ToolbarLayoutManager::implts_writeNewWindowStateData( const rtl::OUString aName, const uno::Reference< awt::XWindow >& xWindow )
{
bool bVisible( false );
bool bFloating( true );
awt::Rectangle aPos;
awt::Size aSize;
if ( xWindow.is() )
{
uno::Reference< awt::XDockableWindow > xDockWindow( xWindow, uno::UNO_QUERY );
if ( xDockWindow.is() )
bFloating = xDockWindow->isFloating();
uno::Reference< awt::XWindow2 > xWindow2( xWindow, uno::UNO_QUERY );
if( xWindow2.is() )
{
aPos = xWindow2->getPosSize();
aSize = xWindow2->getOutputSize(); // always use output size for consistency
bVisible = xWindow2->isVisible();
}
WriteGuard aWriteLock( m_aLock );
UIElement& rUIElement = impl_findToolbar( aName );
if ( rUIElement.m_xUIElement.is() )
{
rUIElement.m_bVisible = bVisible;
rUIElement.m_bFloating = bFloating;
if ( bFloating )
{
rUIElement.m_aFloatingData.m_aPos = ::Point( aPos.X, aPos.Y );
rUIElement.m_aFloatingData.m_aSize = ::Size( aSize.Width, aSize.Height );
}
}
implts_writeWindowStateData( rUIElement );
aWriteLock.unlock();
}
}
/******************************************************************************
LOOKUP PART FOR TOOLBARS
******************************************************************************/
UIElement& ToolbarLayoutManager::impl_findToolbar( const rtl::OUString& aName )
{
static UIElement aEmptyElement;
UIElementVector::iterator pIter;
ReadGuard aReadLock( m_aLock );
for ( pIter = m_aUIElements.begin(); pIter != m_aUIElements.end(); pIter++ )
{
if ( pIter->m_aName == aName )
return *pIter;
}
return aEmptyElement;
}
UIElement ToolbarLayoutManager::implts_findToolbar( const rtl::OUString& aName )
{
ReadGuard aReadLock( m_aLock );
UIElement aElement = impl_findToolbar( aName );
aReadLock.unlock();
return aElement;
}
UIElement ToolbarLayoutManager::implts_findToolbar( const uno::Reference< uno::XInterface >& xToolbar )
{
UIElement aToolbar;
UIElementVector::const_iterator pIter;
ReadGuard aReadLock( m_aLock );
for ( pIter = m_aUIElements.begin(); pIter != m_aUIElements.end(); pIter++ )
{
if ( pIter->m_xUIElement.is() )
{
uno::Reference< uno::XInterface > xIfac( pIter->m_xUIElement->getRealInterface(), uno::UNO_QUERY );
if ( xIfac == xToolbar )
{
aToolbar = *pIter;
break;
}
}
}
return aToolbar;
}
uno::Reference< awt::XWindow > ToolbarLayoutManager::implts_getXWindow( const ::rtl::OUString& aName )
{
UIElementVector::iterator pIter;
uno::Reference< awt::XWindow > xWindow;
ReadGuard aReadLock( m_aLock );
for ( pIter = m_aUIElements.begin(); pIter != m_aUIElements.end(); pIter++ )
{
if ( pIter->m_aName == aName && pIter->m_xUIElement.is() )
{
xWindow = uno::Reference< awt::XWindow >( pIter->m_xUIElement->getRealInterface(), uno::UNO_QUERY );
break;
}
}
return xWindow;
}
Window* ToolbarLayoutManager::implts_getWindow( const ::rtl::OUString& aName )
{
uno::Reference< awt::XWindow > xWindow = implts_getXWindow( aName );
Window* pWindow = VCLUnoHelper::GetWindow( xWindow );
return pWindow;
}
bool ToolbarLayoutManager::implts_insertToolbar( const UIElement& rUIElement )
{
UIElement aTempData;
bool bFound( false );
bool bResult( false );
aTempData = implts_findToolbar( rUIElement.m_aName );
if ( aTempData.m_aName == rUIElement.m_aName )
bFound = true;
if ( !bFound )
{
WriteGuard aWriteLock( m_aLock );
m_aUIElements.push_back( rUIElement );
bResult = true;
}
return bResult;
}
void ToolbarLayoutManager::implts_setToolbar( const UIElement& rUIElement )
{
WriteGuard aWriteLock( m_aLock );
UIElement& rData = impl_findToolbar( rUIElement.m_aName );
if ( rData.m_aName == rUIElement.m_aName )
rData = rUIElement;
else
m_aUIElements.push_back( rUIElement );
}
/******************************************************************************
LAYOUT CODE PART FOR TOOLBARS
******************************************************************************/
::Point ToolbarLayoutManager::implts_findNextCascadeFloatingPos()
{
const sal_Int32 nHotZoneX = 50;
const sal_Int32 nHotZoneY = 50;
const sal_Int32 nCascadeIndentX = 15;
const sal_Int32 nCascadeIndentY = 15;
ReadGuard aReadLock( m_aLock );
uno::Reference< awt::XWindow2 > xContainerWindow( m_xContainerWindow );
uno::Reference< awt::XWindow > xTopDockingWindow( m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_TOP] );
uno::Reference< awt::XWindow > xLeftDockingWindow( m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_LEFT] );
aReadLock.unlock();
::Point aStartPos( nCascadeIndentX, nCascadeIndentY );
::Point aCurrPos( aStartPos );
awt::Rectangle aRect;
Window* pContainerWindow( 0 );
if ( xContainerWindow.is() )
{
vos::OGuard aGuard( Application::GetSolarMutex() );
pContainerWindow = VCLUnoHelper::GetWindow( xContainerWindow );
if ( pContainerWindow )
aStartPos = pContainerWindow->OutputToScreenPixel( aStartPos );
}
// Determine size of top and left docking area
awt::Rectangle aTopRect( xTopDockingWindow->getPosSize() );
awt::Rectangle aLeftRect( xLeftDockingWindow->getPosSize() );
aStartPos.X() += aLeftRect.Width + nCascadeIndentX;
aStartPos.Y() += aTopRect.Height + nCascadeIndentY;
aCurrPos = aStartPos;
// Try to find a cascaded position for the new floating window
UIElementVector::const_iterator pIter;
for ( pIter = m_aUIElements.begin(); pIter != m_aUIElements.end(); pIter++ )
{
if ( pIter->m_xUIElement.is() )
{
uno::Reference< awt::XDockableWindow > xDockWindow( pIter->m_xUIElement->getRealInterface(), uno::UNO_QUERY );
uno::Reference< awt::XWindow > xWindow( xDockWindow, uno::UNO_QUERY );
if ( xDockWindow.is() && xDockWindow->isFloating() )
{
vos::OGuard aGuard( Application::GetSolarMutex() );
Window* pWindow = VCLUnoHelper::GetWindow( xWindow );
if ( pWindow && pWindow->IsVisible() )
{
awt::Rectangle aFloatRect = xWindow->getPosSize();
if ((( aFloatRect.X - nHotZoneX ) <= aCurrPos.X() ) &&
( aFloatRect.X >= aCurrPos.X() ) &&
(( aFloatRect.Y - nHotZoneY ) <= aCurrPos.Y() ) &&
( aFloatRect.Y >= aCurrPos.Y() ))
{
aCurrPos.X() = aFloatRect.X + nCascadeIndentX;
aCurrPos.Y() = aFloatRect.Y + nCascadeIndentY;
}
}
}
}
}
return aCurrPos;
}
void ToolbarLayoutManager::implts_sortUIElements()
{
WriteGuard aWriteLock( m_aLock );
UIElementVector::iterator pIterStart = m_aUIElements.begin();
UIElementVector::iterator pIterEnd = m_aUIElements.end();
std::stable_sort( pIterStart, pIterEnd ); // first created element should first
// We have to reset our temporary flags.
UIElementVector::iterator pIter;
for ( pIter = m_aUIElements.begin(); pIter != m_aUIElements.end(); pIter++ )
pIter->m_bUserActive = sal_False;
aWriteLock.unlock();
}
void ToolbarLayoutManager::implts_getUIElementVectorCopy( UIElementVector& rCopy )
{
ReadGuard aReadLock( m_aLock );
rCopy = m_aUIElements;
}
::Size ToolbarLayoutManager::implts_getTopBottomDockingAreaSizes()
{
::Size aSize;
uno::Reference< awt::XWindow > xTopDockingAreaWindow;
uno::Reference< awt::XWindow > xBottomDockingAreaWindow;
ReadGuard aReadLock( m_aLock );
xTopDockingAreaWindow = m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_TOP];
xBottomDockingAreaWindow = m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_BOTTOM];
aReadLock.unlock();
if ( xTopDockingAreaWindow.is() )
aSize.Width() = xTopDockingAreaWindow->getPosSize().Height;
if ( xBottomDockingAreaWindow.is() )
aSize.Height() = xBottomDockingAreaWindow->getPosSize().Height;
return aSize;
}
void ToolbarLayoutManager::implts_getDockingAreaElementInfos( ui::DockingArea eDockingArea, std::vector< SingleRowColumnWindowData >& rRowColumnsWindowData )
{
std::vector< UIElement > aWindowVector;
if (( eDockingArea < ui::DockingArea_DOCKINGAREA_TOP ) || ( eDockingArea > ui::DockingArea_DOCKINGAREA_RIGHT ))
eDockingArea = ui::DockingArea_DOCKINGAREA_TOP;
uno::Reference< awt::XWindow > xDockAreaWindow;
/* SAFE AREA ----------------------------------------------------------------------------------------------- */
ReadGuard aReadLock( m_aLock );
aWindowVector.reserve(m_aUIElements.size());
xDockAreaWindow = m_xDockAreaWindows[eDockingArea];
UIElementVector::iterator pIter;
for ( pIter = m_aUIElements.begin(); pIter != m_aUIElements.end(); pIter++ )
{
if ( pIter->m_aDockedData.m_nDockedArea == eDockingArea && pIter->m_bVisible && !pIter->m_bFloating )
{
uno::Reference< ui::XUIElement > xUIElement( pIter->m_xUIElement );
if ( xUIElement.is() )
{
uno::Reference< awt::XWindow > xWindow( xUIElement->getRealInterface(), uno::UNO_QUERY );
uno::Reference< awt::XDockableWindow > xDockWindow( xWindow, uno::UNO_QUERY );
if ( xDockWindow.is() )
{
// docked windows
aWindowVector.push_back( *pIter );
}
}
}
}
aReadLock.unlock();
/* SAFE AREA ----------------------------------------------------------------------------------------------- */
rRowColumnsWindowData.clear();
// Collect data from windows that are on the same row/column
sal_Int32 j;
sal_Int32 nIndex( 0 );
sal_Int32 nLastPos( 0 );
sal_Int32 nCurrPos( -1 );
sal_Int32 nLastRowColPixelPos( 0 );
awt::Rectangle aDockAreaRect;
if ( xDockAreaWindow.is() )
aDockAreaRect = xDockAreaWindow->getPosSize();
if ( eDockingArea == ui::DockingArea_DOCKINGAREA_TOP )
nLastRowColPixelPos = 0;
else if ( eDockingArea == ui::DockingArea_DOCKINGAREA_BOTTOM )
nLastRowColPixelPos = aDockAreaRect.Height;
else if ( eDockingArea == ui::DockingArea_DOCKINGAREA_LEFT )
nLastRowColPixelPos = 0;
else
nLastRowColPixelPos = aDockAreaRect.Width;
const sal_uInt32 nCount = aWindowVector.size();
for ( j = 0; j < sal_Int32( nCount); j++ )
{
const UIElement& rElement = aWindowVector[j];
uno::Reference< awt::XWindow > xWindow;
uno::Reference< ui::XUIElement > xUIElement( rElement.m_xUIElement );
awt::Rectangle aPosSize;
if ( !lcl_checkUIElement(xUIElement,aPosSize,xWindow) )
continue;
if ( isHorizontalDockingArea( eDockingArea ))
{
if ( nCurrPos == -1 )
{
nCurrPos = rElement.m_aDockedData.m_aPos.Y();
nLastPos = 0;
SingleRowColumnWindowData aRowColumnWindowData;
aRowColumnWindowData.nRowColumn = nCurrPos;
rRowColumnsWindowData.push_back( aRowColumnWindowData );
}
sal_Int32 nSpace( 0 );
if ( rElement.m_aDockedData.m_aPos.Y() != nCurrPos )
{
if ( eDockingArea == ui::DockingArea_DOCKINGAREA_TOP )
nLastRowColPixelPos += rRowColumnsWindowData[nIndex].nStaticSize;
else
nLastRowColPixelPos -= rRowColumnsWindowData[nIndex].nStaticSize;
++nIndex;
nLastPos = 0;
nCurrPos = rElement.m_aDockedData.m_aPos.Y();
SingleRowColumnWindowData aRowColumnWindowData;
aRowColumnWindowData.nRowColumn = nCurrPos;
rRowColumnsWindowData.push_back( aRowColumnWindowData );
}
// Calc space before an element and store it
nSpace = ( rElement.m_aDockedData.m_aPos.X() - nLastPos );
if ( rElement.m_aDockedData.m_aPos.X() >= nLastPos )
{
rRowColumnsWindowData[nIndex].nSpace += nSpace;
nLastPos = rElement.m_aDockedData.m_aPos.X() + aPosSize.Width;
}
else
{
nSpace = 0;
nLastPos += aPosSize.Width;
}
rRowColumnsWindowData[nIndex].aRowColumnSpace.push_back( nSpace );
rRowColumnsWindowData[nIndex].aRowColumnWindows.push_back( xWindow );
rRowColumnsWindowData[nIndex].aUIElementNames.push_back( rElement.m_aName );
rRowColumnsWindowData[nIndex].aRowColumnWindowSizes.push_back(
awt::Rectangle( rElement.m_aDockedData.m_aPos.X(),
rElement.m_aDockedData.m_aPos.Y(),
aPosSize.Width,
aPosSize.Height ));
if ( rRowColumnsWindowData[nIndex].nStaticSize < aPosSize.Height )
rRowColumnsWindowData[nIndex].nStaticSize = aPosSize.Height;
if ( eDockingArea == ui::DockingArea_DOCKINGAREA_TOP )
rRowColumnsWindowData[nIndex].aRowColumnRect = awt::Rectangle( 0, nLastRowColPixelPos,
aDockAreaRect.Width, aPosSize.Height );
else
rRowColumnsWindowData[nIndex].aRowColumnRect = awt::Rectangle( 0, ( nLastRowColPixelPos - aPosSize.Height ),
aDockAreaRect.Width, aPosSize.Height );
rRowColumnsWindowData[nIndex].nVarSize += aPosSize.Width + nSpace;
}
else
{
if ( nCurrPos == -1 )
{
nCurrPos = rElement.m_aDockedData.m_aPos.X();
nLastPos = 0;
SingleRowColumnWindowData aRowColumnWindowData;
aRowColumnWindowData.nRowColumn = nCurrPos;
rRowColumnsWindowData.push_back( aRowColumnWindowData );
}
sal_Int32 nSpace( 0 );
if ( rElement.m_aDockedData.m_aPos.X() != nCurrPos )
{
if ( eDockingArea == ui::DockingArea_DOCKINGAREA_LEFT )
nLastRowColPixelPos += rRowColumnsWindowData[nIndex].nStaticSize;
else
nLastRowColPixelPos -= rRowColumnsWindowData[nIndex].nStaticSize;
++nIndex;
nLastPos = 0;
nCurrPos = rElement.m_aDockedData.m_aPos.X();
SingleRowColumnWindowData aRowColumnWindowData;
aRowColumnWindowData.nRowColumn = nCurrPos;
rRowColumnsWindowData.push_back( aRowColumnWindowData );
}
// Calc space before an element and store it
nSpace = ( rElement.m_aDockedData.m_aPos.Y() - nLastPos );
if ( rElement.m_aDockedData.m_aPos.Y() > nLastPos )
{
rRowColumnsWindowData[nIndex].nSpace += nSpace;
nLastPos = rElement.m_aDockedData.m_aPos.Y() + aPosSize.Height;
}
else
{
nSpace = 0;
nLastPos += aPosSize.Height;
}
rRowColumnsWindowData[nIndex].aRowColumnSpace.push_back( nSpace );
rRowColumnsWindowData[nIndex].aRowColumnWindows.push_back( xWindow );
rRowColumnsWindowData[nIndex].aUIElementNames.push_back( rElement.m_aName );
rRowColumnsWindowData[nIndex].aRowColumnWindowSizes.push_back(
awt::Rectangle( rElement.m_aDockedData.m_aPos.X(),
rElement.m_aDockedData.m_aPos.Y(),
aPosSize.Width,
aPosSize.Height ));
if ( rRowColumnsWindowData[nIndex].nStaticSize < aPosSize.Width )
rRowColumnsWindowData[nIndex].nStaticSize = aPosSize.Width;
if ( eDockingArea == ui::DockingArea_DOCKINGAREA_LEFT )
rRowColumnsWindowData[nIndex].aRowColumnRect = awt::Rectangle( nLastRowColPixelPos, 0,
aPosSize.Width, aDockAreaRect.Height );
else
rRowColumnsWindowData[nIndex].aRowColumnRect = awt::Rectangle( ( nLastRowColPixelPos - aPosSize.Width ), 0,
aPosSize.Width, aDockAreaRect.Height );
rRowColumnsWindowData[nIndex].nVarSize += aPosSize.Height + nSpace;
}
}
}
void ToolbarLayoutManager::implts_getDockingAreaElementInfoOnSingleRowCol( ui::DockingArea eDockingArea, sal_Int32 nRowCol, SingleRowColumnWindowData& rRowColumnWindowData )
{
std::vector< UIElement > aWindowVector;
if (( eDockingArea < ui::DockingArea_DOCKINGAREA_TOP ) || ( eDockingArea > ui::DockingArea_DOCKINGAREA_RIGHT ))
eDockingArea = ui::DockingArea_DOCKINGAREA_TOP;
bool bHorzDockArea = isHorizontalDockingArea( eDockingArea );
/* SAFE AREA ----------------------------------------------------------------------------------------------- */
ReadGuard aReadLock( m_aLock );
UIElementVector::iterator pIter;
UIElementVector::iterator pEnd = m_aUIElements.end();
for ( pIter = m_aUIElements.begin(); pIter != pEnd; pIter++ )
{
if ( pIter->m_aDockedData.m_nDockedArea == eDockingArea )
{
bool bSameRowCol = bHorzDockArea ? ( pIter->m_aDockedData.m_aPos.Y() == nRowCol ) : ( pIter->m_aDockedData.m_aPos.X() == nRowCol );
uno::Reference< ui::XUIElement > xUIElement( pIter->m_xUIElement );
if ( bSameRowCol && xUIElement.is() )
{
uno::Reference< awt::XWindow > xWindow( xUIElement->getRealInterface(), uno::UNO_QUERY );
if ( xWindow.is() )
{
vos::OGuard aGuard( Application::GetSolarMutex() );
Window* pWindow = VCLUnoHelper::GetWindow( xWindow );
uno::Reference< awt::XDockableWindow > xDockWindow( xWindow, uno::UNO_QUERY );
if ( pWindow && pIter->m_bVisible && xDockWindow.is() && !pIter->m_bFloating )
aWindowVector.push_back( *pIter ); // docked windows
}
}
}
}
aReadLock.unlock();
/* SAFE AREA ----------------------------------------------------------------------------------------------- */
// Initialize structure
rRowColumnWindowData.aUIElementNames.clear();
rRowColumnWindowData.aRowColumnWindows.clear();
rRowColumnWindowData.aRowColumnWindowSizes.clear();
rRowColumnWindowData.aRowColumnSpace.clear();
rRowColumnWindowData.nVarSize = 0;
rRowColumnWindowData.nStaticSize = 0;
rRowColumnWindowData.nSpace = 0;
rRowColumnWindowData.nRowColumn = nRowCol;
// Collect data from windows that are on the same row/column
sal_Int32 j;
sal_Int32 nLastPos( 0 );
const sal_uInt32 nCount = aWindowVector.size();
for ( j = 0; j < sal_Int32( nCount); j++ )
{
const UIElement& rElement = aWindowVector[j];
uno::Reference< awt::XWindow > xWindow;
uno::Reference< ui::XUIElement > xUIElement( rElement.m_xUIElement );
awt::Rectangle aPosSize;
if ( !lcl_checkUIElement(xUIElement,aPosSize,xWindow) )
continue;
sal_Int32 nSpace;
if ( isHorizontalDockingArea( eDockingArea ))
{
nSpace = ( rElement.m_aDockedData.m_aPos.X() - nLastPos );
// Calc space before an element and store it
if ( rElement.m_aDockedData.m_aPos.X() > nLastPos )
rRowColumnWindowData.nSpace += nSpace;
else
nSpace = 0;
nLastPos = rElement.m_aDockedData.m_aPos.X() + aPosSize.Width;
rRowColumnWindowData.aRowColumnWindowSizes.push_back(
awt::Rectangle( rElement.m_aDockedData.m_aPos.X(), rElement.m_aDockedData.m_aPos.Y(),
aPosSize.Width, aPosSize.Height ));
if ( rRowColumnWindowData.nStaticSize < aPosSize.Height )
rRowColumnWindowData.nStaticSize = aPosSize.Height;
rRowColumnWindowData.nVarSize += aPosSize.Width;
}
else
{
// Calc space before an element and store it
nSpace = ( rElement.m_aDockedData.m_aPos.Y() - nLastPos );
if ( rElement.m_aDockedData.m_aPos.Y() > nLastPos )
rRowColumnWindowData.nSpace += nSpace;
else
nSpace = 0;
nLastPos = rElement.m_aDockedData.m_aPos.Y() + aPosSize.Height;
rRowColumnWindowData.aRowColumnWindowSizes.push_back(
awt::Rectangle( rElement.m_aDockedData.m_aPos.X(), rElement.m_aDockedData.m_aPos.Y(),
aPosSize.Width, aPosSize.Height ));
if ( rRowColumnWindowData.nStaticSize < aPosSize.Width )
rRowColumnWindowData.nStaticSize = aPosSize.Width;
rRowColumnWindowData.nVarSize += aPosSize.Height;
}
rRowColumnWindowData.aUIElementNames.push_back( rElement.m_aName );
rRowColumnWindowData.aRowColumnWindows.push_back( xWindow );
rRowColumnWindowData.aRowColumnSpace.push_back( nSpace );
rRowColumnWindowData.nVarSize += nSpace;
}
}
::Rectangle ToolbarLayoutManager::implts_getWindowRectFromRowColumn(
ui::DockingArea DockingArea,
const SingleRowColumnWindowData& rRowColumnWindowData,
const ::Point& rMousePos,
const rtl::OUString& rExcludeElementName )
{
::Rectangle aWinRect;
if (( DockingArea < ui::DockingArea_DOCKINGAREA_TOP ) || ( DockingArea > ui::DockingArea_DOCKINGAREA_RIGHT ))
DockingArea = ui::DockingArea_DOCKINGAREA_TOP;
if ( rRowColumnWindowData.aRowColumnWindows.empty() )
return aWinRect;
else
{
ReadGuard aReadLock( m_aLock );
Window* pContainerWindow( VCLUnoHelper::GetWindow( m_xContainerWindow ));
Window* pDockingAreaWindow( VCLUnoHelper::GetWindow( m_xDockAreaWindows[DockingArea] ));
aReadLock.unlock();
// Calc correct position of the column/row rectangle to be able to compare it with mouse pos/tracking rect
vos::OGuard aGuard( Application::GetSolarMutex() );
// Retrieve output size from container Window
if ( pDockingAreaWindow && pContainerWindow )
{
const sal_uInt32 nCount = rRowColumnWindowData.aRowColumnWindows.size();
for ( sal_uInt32 i = 0; i < nCount; i++ )
{
awt::Rectangle aWindowRect = rRowColumnWindowData.aRowColumnWindows[i]->getPosSize();
::Rectangle aRect( aWindowRect.X, aWindowRect.Y, aWindowRect.X+aWindowRect.Width, aWindowRect.Y+aWindowRect.Height );
aRect.SetPos( pContainerWindow->ScreenToOutputPixel( pDockingAreaWindow->OutputToScreenPixel( aRect.TopLeft() )));
if ( aRect.IsInside( rMousePos ))
{
// Check if we have found the excluded element. If yes, we have to provide an empty rectangle.
// We prevent that a toolbar cannot be moved when the mouse pointer is inside its own rectangle!
if ( rExcludeElementName != rRowColumnWindowData.aUIElementNames[i] )
return aRect;
else
break;
}
}
}
}
return aWinRect;
}
::Rectangle ToolbarLayoutManager::implts_determineFrontDockingRect(
ui::DockingArea eDockingArea,
sal_Int32 nRowCol,
const ::Rectangle& rDockedElementRect,
const ::rtl::OUString& rMovedElementName,
const ::Rectangle& rMovedElementRect )
{
SingleRowColumnWindowData aRowColumnWindowData;
sal_Bool bHorzDockArea( isHorizontalDockingArea( eDockingArea ));
implts_getDockingAreaElementInfoOnSingleRowCol( eDockingArea, nRowCol, aRowColumnWindowData );
if ( aRowColumnWindowData.aRowColumnWindows.empty() )
return rMovedElementRect;
else
{
sal_Int32 nSpace( 0 );
::Rectangle aFrontDockingRect( rMovedElementRect );
const sal_uInt32 nCount = aRowColumnWindowData.aRowColumnWindows.size();
for ( sal_uInt32 i = 0; i < nCount; i++ )
{
if ( bHorzDockArea )
{
if ( aRowColumnWindowData.aRowColumnWindowSizes[i].X >= rDockedElementRect.Left() )
{
nSpace += aRowColumnWindowData.aRowColumnSpace[i];
break;
}
else if ( aRowColumnWindowData.aUIElementNames[i] == rMovedElementName )
nSpace += aRowColumnWindowData.aRowColumnWindowSizes[i].Width +
aRowColumnWindowData.aRowColumnSpace[i];
else
nSpace = 0;
}
else
{
if ( aRowColumnWindowData.aRowColumnWindowSizes[i].Y >= rDockedElementRect.Top() )
{
nSpace += aRowColumnWindowData.aRowColumnSpace[i];
break;
}
else if ( aRowColumnWindowData.aUIElementNames[i] == rMovedElementName )
nSpace += aRowColumnWindowData.aRowColumnWindowSizes[i].Height +
aRowColumnWindowData.aRowColumnSpace[i];
else
nSpace = 0;
}
}
if ( nSpace > 0 )
{
sal_Int32 nMove = std::min( nSpace, static_cast<sal_Int32>(aFrontDockingRect.getWidth()) );
if ( bHorzDockArea )
aFrontDockingRect.Move( -nMove, 0 );
else
aFrontDockingRect.Move( 0, -nMove );
}
return aFrontDockingRect;
}
}
void ToolbarLayoutManager::implts_findNextDockingPos( ui::DockingArea DockingArea, const ::Size& aUIElementSize, ::Point& rVirtualPos, ::Point& rPixelPos )
{
ReadGuard aReadLock( m_aLock );
uno::Reference< awt::XWindow > xDockingWindow( m_xDockAreaWindows[DockingArea] );
::Size aDockingWinSize;
Window* pDockingWindow( 0 );
aReadLock.unlock();
if (( DockingArea < ui::DockingArea_DOCKINGAREA_TOP ) || ( DockingArea > ui::DockingArea_DOCKINGAREA_RIGHT ))
DockingArea = ui::DockingArea_DOCKINGAREA_TOP;
{
// Retrieve output size from container Window
vos::OGuard aGuard( Application::GetSolarMutex() );
pDockingWindow = VCLUnoHelper::GetWindow( xDockingWindow );
if ( pDockingWindow )
aDockingWinSize = pDockingWindow->GetOutputSizePixel();
}
sal_Int32 nFreeRowColPixelPos( 0 );
sal_Int32 nMaxSpace( 0 );
sal_Int32 nNeededSpace( 0 );
sal_Int32 nTopDockingAreaSize( 0 );
if ( isHorizontalDockingArea( DockingArea ))
{
nMaxSpace = aDockingWinSize.Width();
nNeededSpace = aUIElementSize.Width();
}
else
{
nMaxSpace = aDockingWinSize.Height();
nNeededSpace = aUIElementSize.Height();
nTopDockingAreaSize = implts_getTopBottomDockingAreaSizes().Width();
}
std::vector< SingleRowColumnWindowData > aRowColumnsWindowData;
implts_getDockingAreaElementInfos( DockingArea, aRowColumnsWindowData );
sal_Int32 nPixelPos( 0 );
const sal_uInt32 nCount = aRowColumnsWindowData.size();
for ( sal_uInt32 i = 0; i < nCount; i++ )
{
SingleRowColumnWindowData& rRowColumnWindowData = aRowColumnsWindowData[i];
if (( DockingArea == ui::DockingArea_DOCKINGAREA_BOTTOM ) ||
( DockingArea == ui::DockingArea_DOCKINGAREA_RIGHT ))
nPixelPos += rRowColumnWindowData.nStaticSize;
if ((( nMaxSpace - rRowColumnWindowData.nVarSize ) >= nNeededSpace ) ||
( rRowColumnWindowData.nSpace >= nNeededSpace ))
{
// Check current row where we can find the needed space
sal_Int32 nCurrPos( 0 );
const sal_uInt32 nWindowSizesCount = rRowColumnWindowData.aRowColumnWindowSizes.size();
for ( sal_uInt32 j = 0; j < nWindowSizesCount; j++ )
{
awt::Rectangle rRect = rRowColumnWindowData.aRowColumnWindowSizes[j];
sal_Int32& rSpace = rRowColumnWindowData.aRowColumnSpace[j];
if ( isHorizontalDockingArea( DockingArea ))
{
if ( rSpace >= nNeededSpace )
{
rVirtualPos = ::Point( nCurrPos, rRowColumnWindowData.nRowColumn );
if ( DockingArea == ui::DockingArea_DOCKINGAREA_TOP )
rPixelPos = ::Point( nCurrPos, nPixelPos );
else
rPixelPos = ::Point( nCurrPos, aDockingWinSize.Height() - nPixelPos );
return;
}
nCurrPos = rRect.X + rRect.Width;
}
else
{
if ( rSpace >= nNeededSpace )
{
rVirtualPos = ::Point( rRowColumnWindowData.nRowColumn, nCurrPos );
if ( DockingArea == ui::DockingArea_DOCKINGAREA_LEFT )
rPixelPos = ::Point( nPixelPos, nTopDockingAreaSize + nCurrPos );
else
rPixelPos = ::Point( aDockingWinSize.Width() - nPixelPos , nTopDockingAreaSize + nCurrPos );
return;
}
nCurrPos = rRect.Y + rRect.Height;
}
}
if (( nCurrPos + nNeededSpace ) <= nMaxSpace )
{
if ( isHorizontalDockingArea( DockingArea ))
{
rVirtualPos = ::Point( nCurrPos, rRowColumnWindowData.nRowColumn );
if ( DockingArea == ui::DockingArea_DOCKINGAREA_TOP )
rPixelPos = ::Point( nCurrPos, nPixelPos );
else
rPixelPos = ::Point( nCurrPos, aDockingWinSize.Height() - nPixelPos );
return;
}
else
{
rVirtualPos = ::Point( rRowColumnWindowData.nRowColumn, nCurrPos );
if ( DockingArea == ui::DockingArea_DOCKINGAREA_LEFT )
rPixelPos = ::Point( nPixelPos, nTopDockingAreaSize + nCurrPos );
else
rPixelPos = ::Point( aDockingWinSize.Width() - nPixelPos , nTopDockingAreaSize + nCurrPos );
return;
}
}
}
if (( DockingArea == ui::DockingArea_DOCKINGAREA_TOP ) || ( DockingArea == ui::DockingArea_DOCKINGAREA_LEFT ))
nPixelPos += rRowColumnWindowData.nStaticSize;
}
sal_Int32 nNextFreeRowCol( 0 );
sal_Int32 nRowColumnsCount = aRowColumnsWindowData.size();
if ( nRowColumnsCount > 0 )
nNextFreeRowCol = aRowColumnsWindowData[nRowColumnsCount-1].nRowColumn+1;
else
nNextFreeRowCol = 0;
if ( nNextFreeRowCol == 0 )
{
if ( DockingArea == ui::DockingArea_DOCKINGAREA_BOTTOM )
nFreeRowColPixelPos = aDockingWinSize.Height() - aUIElementSize.Height();
else if ( DockingArea == ui::DockingArea_DOCKINGAREA_RIGHT )
nFreeRowColPixelPos = aDockingWinSize.Width() - aUIElementSize.Width();
}
if ( isHorizontalDockingArea( DockingArea ))
{
rVirtualPos = ::Point( 0, nNextFreeRowCol );
if ( DockingArea == ui::DockingArea_DOCKINGAREA_TOP )
rPixelPos = ::Point( 0, nFreeRowColPixelPos );
else
rPixelPos = ::Point( 0, aDockingWinSize.Height() - nFreeRowColPixelPos );
}
else
{
rVirtualPos = ::Point( nNextFreeRowCol, 0 );
rPixelPos = ::Point( aDockingWinSize.Width() - nFreeRowColPixelPos, 0 );
}
}
void ToolbarLayoutManager::implts_calcWindowPosSizeOnSingleRowColumn(
sal_Int32 nDockingArea,
sal_Int32 nOffset,
SingleRowColumnWindowData& rRowColumnWindowData,
const ::Size& rContainerSize )
{
sal_Int32 nDiff(0);
sal_Int32 nRCSpace( rRowColumnWindowData.nSpace );
sal_Int32 nTopDockingAreaSize(0);
sal_Int32 nBottomDockingAreaSize(0);
sal_Int32 nContainerClientSize(0);
if ( rRowColumnWindowData.aRowColumnWindows.empty() )
return;
if ( isHorizontalDockingArea( nDockingArea ))
{
nContainerClientSize = rContainerSize.Width();
nDiff = nContainerClientSize - rRowColumnWindowData.nVarSize;
}
else
{
nTopDockingAreaSize = implts_getTopBottomDockingAreaSizes().Width();
nBottomDockingAreaSize = implts_getTopBottomDockingAreaSizes().Height();
nContainerClientSize = ( rContainerSize.Height() - nTopDockingAreaSize - nBottomDockingAreaSize );
nDiff = nContainerClientSize - rRowColumnWindowData.nVarSize;
}
const sal_uInt32 nCount = rRowColumnWindowData.aRowColumnWindowSizes.size();
if (( nDiff < 0 ) && ( nRCSpace > 0 ))
{
// First we try to reduce the size of blank space before/behind docked windows
sal_Int32 i = nCount - 1;
while ( i >= 0 )
{
sal_Int32 nSpace = rRowColumnWindowData.aRowColumnSpace[i];
if ( nSpace >= -nDiff )
{
if ( isHorizontalDockingArea( nDockingArea ))
{
// Try to move this and all user elements behind with the calculated difference
for ( sal_uInt32 j = i; j < nCount ; j++ )
rRowColumnWindowData.aRowColumnWindowSizes[j].X += nDiff;
}
else
{
// Try to move this and all user elements behind with the calculated difference
for ( sal_uInt32 j = i; j < nCount ; j++ )
rRowColumnWindowData.aRowColumnWindowSizes[j].Y += nDiff;
}
nDiff = 0;
break;
}
else if ( nSpace > 0 )
{
if ( isHorizontalDockingArea( nDockingArea ))
{
// Try to move this and all user elements behind with the calculated difference
for ( sal_uInt32 j = i; j < nCount; j++ )
rRowColumnWindowData.aRowColumnWindowSizes[j].X -= nSpace;
}
else
{
// Try to move this and all user elements behind with the calculated difference
for ( sal_uInt32 j = i; j < nCount; j++ )
rRowColumnWindowData.aRowColumnWindowSizes[j].Y -= nSpace;
}
nDiff += nSpace;
}
--i;
}
}
// Check if we have to reduce further
if ( nDiff < 0 )
{
// Now we have to reduce the size of certain docked windows
sal_Int32 i = sal_Int32( nCount - 1 );
while ( i >= 0 )
{
awt::Rectangle& rWinRect = rRowColumnWindowData.aRowColumnWindowSizes[i];
::Size aMinSize;
vos::OGuard aGuard( Application::GetSolarMutex() );
{
uno::Reference< awt::XWindow > xWindow = rRowColumnWindowData.aRowColumnWindows[i];
Window* pWindow = VCLUnoHelper::GetWindow( xWindow );
if ( pWindow && pWindow->GetType() == WINDOW_TOOLBOX )
aMinSize = ((ToolBox *)pWindow)->CalcMinimumWindowSizePixel();
}
if (( aMinSize.Width() > 0 ) && ( aMinSize.Height() > 0 ))
{
if ( isHorizontalDockingArea( nDockingArea ))
{
sal_Int32 nMaxReducation = ( rWinRect.Width - aMinSize.Width() );
if ( nMaxReducation >= -nDiff )
{
rWinRect.Width = rWinRect.Width + nDiff;
nDiff = 0;
}
else
{
rWinRect.Width = aMinSize.Width();
nDiff += nMaxReducation;
}
// Try to move this and all user elements behind with the calculated difference
for ( sal_uInt32 j = i; j < nCount; j++ )
rRowColumnWindowData.aRowColumnWindowSizes[j].X += nDiff;
}
else
{
sal_Int32 nMaxReducation = ( rWinRect.Height - aMinSize.Height() );
if ( nMaxReducation >= -nDiff )
{
rWinRect.Height = rWinRect.Height + nDiff;
nDiff = 0;
}
else
{
rWinRect.Height = aMinSize.Height();
nDiff += nMaxReducation;
}
// Try to move this and all user elements behind with the calculated difference
for ( sal_uInt32 j = i; j < nCount; j++ )
rRowColumnWindowData.aRowColumnWindowSizes[j].Y += nDiff;
}
}
if ( nDiff >= 0 )
break;
--i;
}
}
ReadGuard aReadLock( m_aLock );
Window* pDockAreaWindow = VCLUnoHelper::GetWindow( m_xDockAreaWindows[nDockingArea] );
aReadLock.unlock();
sal_Int32 nCurrPos( 0 );
vos::OGuard aGuard( Application::GetSolarMutex() );
for ( sal_uInt32 i = 0; i < nCount; i++ )
{
uno::Reference< awt::XWindow > xWindow = rRowColumnWindowData.aRowColumnWindows[i];
Window* pWindow = VCLUnoHelper::GetWindow( xWindow );
Window* pOldParentWindow = pWindow->GetParent();
if ( pDockAreaWindow != pOldParentWindow )
pWindow->SetParent( pDockAreaWindow );
awt::Rectangle aWinRect = rRowColumnWindowData.aRowColumnWindowSizes[i];
if ( isHorizontalDockingArea( nDockingArea ))
{
if ( aWinRect.X < nCurrPos )
aWinRect.X = nCurrPos;
pWindow->SetPosSizePixel( ::Point( aWinRect.X, nOffset ), ::Size( aWinRect.Width, rRowColumnWindowData.nStaticSize ));
pWindow->Show( sal_True, SHOW_NOFOCUSCHANGE | SHOW_NOACTIVATE );
nCurrPos += ( aWinRect.X - nCurrPos ) + aWinRect.Width;
}
else
{
if ( aWinRect.Y < nCurrPos )
aWinRect.Y = nCurrPos;
pWindow->SetPosSizePixel( ::Point( nOffset, aWinRect.Y ), ::Size( rRowColumnWindowData.nStaticSize, aWinRect.Height ));
pWindow->Show( sal_True, SHOW_NOFOCUSCHANGE | SHOW_NOACTIVATE );
nCurrPos += ( aWinRect.Y - nCurrPos ) + aWinRect.Height;
}
}
}
void ToolbarLayoutManager::implts_setLayoutDirty()
{
WriteGuard aWriteLock( m_aLock );
m_bLayoutDirty = true;
}
void ToolbarLayoutManager::implts_setLayoutInProgress( bool bInProgress )
{
WriteGuard aWriteLock( m_aLock );
m_bLayoutInProgress = bInProgress;
}
::Rectangle ToolbarLayoutManager::implts_calcHotZoneRect( const ::Rectangle& rRect, sal_Int32 nHotZoneOffset )
{
::Rectangle aRect( rRect );
aRect.Left() -= nHotZoneOffset;
aRect.Top() -= nHotZoneOffset;
aRect.Right() += nHotZoneOffset;
aRect.Bottom() += nHotZoneOffset;
return aRect;
}
void ToolbarLayoutManager::implts_calcDockingPosSize(
UIElement& rUIElement,
DockingOperation& rDockingOperation,
::Rectangle& rTrackingRect,
const Point& rMousePos )
{
ReadGuard aReadLock( m_aLock );
uno::Reference< awt::XWindow2 > xContainerWindow( m_xContainerWindow );
::Size aContainerWinSize;
Window* pContainerWindow( 0 );
::Rectangle aDockingAreaOffsets( m_aDockingAreaOffsets );
aReadLock.unlock();
if ( !rUIElement.m_xUIElement.is() )
{
rTrackingRect = ::Rectangle();
return;
}
{
// Retrieve output size from container Window
vos::OGuard aGuard( Application::GetSolarMutex() );
pContainerWindow = VCLUnoHelper::GetWindow( xContainerWindow );
aContainerWinSize = pContainerWindow->GetOutputSizePixel();
}
Window* pDockWindow( 0 );
Window* pDockingAreaWindow( 0 );
ToolBox* pToolBox( 0 );
uno::Reference< awt::XWindow > xWindow( rUIElement.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
uno::Reference< awt::XWindow > xDockingAreaWindow;
::Rectangle aTrackingRect( rTrackingRect );
ui::DockingArea eDockedArea( (ui::DockingArea)rUIElement.m_aDockedData.m_nDockedArea );
sal_Int32 nTopDockingAreaSize( implts_getTopBottomDockingAreaSizes().Width() );
sal_Int32 nBottomDockingAreaSize( implts_getTopBottomDockingAreaSizes().Height() );
bool bHorizontalDockArea(( eDockedArea == ui::DockingArea_DOCKINGAREA_TOP ) ||
( eDockedArea == ui::DockingArea_DOCKINGAREA_BOTTOM ));
sal_Int32 nMaxLeftRightDockAreaSize = aContainerWinSize.Height() -
nTopDockingAreaSize -
nBottomDockingAreaSize -
aDockingAreaOffsets.Top() -
aDockingAreaOffsets.Bottom();
::Rectangle aDockingAreaRect;
aReadLock.lock();
xDockingAreaWindow = m_xDockAreaWindows[eDockedArea];
aReadLock.unlock();
{
vos::OGuard aGuard( Application::GetSolarMutex() );
pDockingAreaWindow = VCLUnoHelper::GetWindow( xDockingAreaWindow );
pDockWindow = VCLUnoHelper::GetWindow( xWindow );
if ( pDockWindow && pDockWindow->GetType() == WINDOW_TOOLBOX )
pToolBox = (ToolBox *)pDockWindow;
aDockingAreaRect = ::Rectangle( pDockingAreaWindow->GetPosPixel(), pDockingAreaWindow->GetSizePixel() );
if ( pToolBox )
{
// docked toolbars always have one line
::Size aSize = pToolBox->CalcWindowSizePixel( 1, ImplConvertAlignment( sal_Int16( eDockedArea )) );
aTrackingRect.SetSize( ::Size( aSize.Width(), aSize.Height() ));
}
}
// default docking operation, dock on the given row/column
bool bOpOutsideOfDockingArea( !aDockingAreaRect.IsInside( rMousePos ));
std::vector< SingleRowColumnWindowData > aRowColumnsWindowData;
rDockingOperation = DOCKOP_ON_COLROW;
implts_getDockingAreaElementInfos( eDockedArea, aRowColumnsWindowData );
// determine current first row/column and last row/column
sal_Int32 nMaxRowCol( -1 );
sal_Int32 nMinRowCol( SAL_MAX_INT32 );
const sal_uInt32 nCount = aRowColumnsWindowData.size();
for ( sal_uInt32 i = 0; i < nCount; i++ )
{
if ( aRowColumnsWindowData[i].nRowColumn > nMaxRowCol )
nMaxRowCol = aRowColumnsWindowData[i].nRowColumn;
if ( aRowColumnsWindowData[i].nRowColumn < nMinRowCol )
nMinRowCol = aRowColumnsWindowData[i].nRowColumn;
}
if ( !bOpOutsideOfDockingArea )
{
// docking inside our docking area
sal_Int32 nIndex( -1 );
sal_Int32 nRowCol( -1 );
::Rectangle aWindowRect;
::Rectangle aRowColumnRect;
const sal_uInt32 nWindowDataCount = aRowColumnsWindowData.size();
for ( sal_uInt32 i = 0; i < nWindowDataCount; i++ )
{
::Rectangle aRect( aRowColumnsWindowData[i].aRowColumnRect.X,
aRowColumnsWindowData[i].aRowColumnRect.Y,
aRowColumnsWindowData[i].aRowColumnRect.X + aRowColumnsWindowData[i].aRowColumnRect.Width,
aRowColumnsWindowData[i].aRowColumnRect.Y + aRowColumnsWindowData[i].aRowColumnRect.Height );
{
// Calc correct position of the column/row rectangle to be able to compare it with mouse pos/tracking rect
vos::OGuard aGuard( Application::GetSolarMutex() );
aRect.SetPos( pContainerWindow->ScreenToOutputPixel( pDockingAreaWindow->OutputToScreenPixel( aRect.TopLeft() )));
}
bool bIsInsideRowCol( aRect.IsInside( rMousePos ) );
if ( bIsInsideRowCol )
{
nIndex = i;
nRowCol = aRowColumnsWindowData[i].nRowColumn;
rDockingOperation = implts_determineDockingOperation( eDockedArea, aRect, rMousePos );
aWindowRect = implts_getWindowRectFromRowColumn( eDockedArea, aRowColumnsWindowData[i], rMousePos, rUIElement.m_aName );
aRowColumnRect = aRect;
break;
}
}
OSL_ENSURE( ( nIndex >= 0 ) && ( nRowCol >= 0 ), "Impossible case - no row/column found but mouse pointer is inside our docking area" );
if (( nIndex >= 0 ) && ( nRowCol >= 0 ))
{
if ( rDockingOperation == DOCKOP_ON_COLROW )
{
if ( !aWindowRect.IsEmpty())
{
// Tracking rect is on a row/column and mouse is over a docked toolbar.
// Determine if the tracking rect must be located before/after the docked toolbar.
::Rectangle aUIElementRect( aWindowRect );
sal_Int32 nMiddle( bHorizontalDockArea ? ( aWindowRect.Left() + aWindowRect.getWidth() / 2 ) :
( aWindowRect.Top() + aWindowRect.getHeight() / 2 ));
sal_Bool bInsertBefore( bHorizontalDockArea ? ( rMousePos.X() < nMiddle ) : ( rMousePos.Y() < nMiddle ));
if ( bInsertBefore )
{
if ( bHorizontalDockArea )
{
sal_Int32 nSize = ::std::max( sal_Int32( 0 ), std::min( sal_Int32( aContainerWinSize.Width() - aWindowRect.Left() ),
sal_Int32( aTrackingRect.getWidth() )));
if ( nSize == 0 )
nSize = aWindowRect.getWidth();
aUIElementRect.SetSize( ::Size( nSize, aWindowRect.getHeight() ));
aWindowRect = implts_determineFrontDockingRect( eDockedArea, nRowCol, aWindowRect,rUIElement.m_aName, aUIElementRect );
// Set virtual position
rUIElement.m_aDockedData.m_aPos.X() = aWindowRect.Left();
rUIElement.m_aDockedData.m_aPos.Y() = nRowCol;
}
else
{
sal_Int32 nSize = ::std::max( sal_Int32( 0 ), std::min( sal_Int32(
nTopDockingAreaSize + nMaxLeftRightDockAreaSize - aWindowRect.Top() ),
sal_Int32( aTrackingRect.getHeight() )));
if ( nSize == 0 )
nSize = aWindowRect.getHeight();
aUIElementRect.SetSize( ::Size( aWindowRect.getWidth(), nSize ));
aWindowRect = implts_determineFrontDockingRect( eDockedArea, nRowCol, aWindowRect, rUIElement.m_aName, aUIElementRect );
// Set virtual position
sal_Int32 nPosY = pDockingAreaWindow->ScreenToOutputPixel(
pContainerWindow->OutputToScreenPixel( aWindowRect.TopLeft() )).Y();
rUIElement.m_aDockedData.m_aPos.X() = nRowCol;
rUIElement.m_aDockedData.m_aPos.Y() = nPosY;
}
rTrackingRect = aWindowRect;
return;
}
else
{
if ( bHorizontalDockArea )
{
sal_Int32 nSize = ::std::max( sal_Int32( 0 ), std::min( sal_Int32(( aContainerWinSize.Width() ) - aWindowRect.Right() ),
sal_Int32( aTrackingRect.getWidth() )));
if ( nSize == 0 )
{
aUIElementRect.SetPos( ::Point( aContainerWinSize.Width() - aTrackingRect.getWidth(), aWindowRect.Top() ));
aUIElementRect.SetSize( ::Size( aTrackingRect.getWidth(), aWindowRect.getHeight() ));
rUIElement.m_aDockedData.m_aPos.X() = aUIElementRect.Left();
}
else
{
aUIElementRect.SetPos( ::Point( aWindowRect.Right(), aWindowRect.Top() ));
aUIElementRect.SetSize( ::Size( nSize, aWindowRect.getHeight() ));
rUIElement.m_aDockedData.m_aPos.X() = aWindowRect.Right();
}
// Set virtual position
rUIElement.m_aDockedData.m_aPos.Y() = nRowCol;
}
else
{
sal_Int32 nSize = ::std::max( sal_Int32( 0 ), std::min( sal_Int32( nTopDockingAreaSize + nMaxLeftRightDockAreaSize - aWindowRect.Bottom() ),
sal_Int32( aTrackingRect.getHeight() )));
aUIElementRect.SetPos( ::Point( aWindowRect.Left(), aWindowRect.Bottom() ));
aUIElementRect.SetSize( ::Size( aWindowRect.getWidth(), nSize ));
// Set virtual position
sal_Int32 nPosY( 0 );
{
vos::OGuard aGuard( Application::GetSolarMutex() );
nPosY = pDockingAreaWindow->ScreenToOutputPixel(
pContainerWindow->OutputToScreenPixel( aWindowRect.BottomRight() )).Y();
}
rUIElement.m_aDockedData.m_aPos.X() = nRowCol;
rUIElement.m_aDockedData.m_aPos.Y() = nPosY;
}
rTrackingRect = aUIElementRect;
return;
}
}
else
{
implts_setTrackingRect( eDockedArea, rMousePos, aTrackingRect );
rTrackingRect = implts_calcTrackingAndElementRect(
eDockedArea, nRowCol, rUIElement,
aTrackingRect, aRowColumnRect, aContainerWinSize );
return;
}
}
else
{
if ((( nRowCol == nMinRowCol ) && ( rDockingOperation == DOCKOP_BEFORE_COLROW )) ||
(( nRowCol == nMaxRowCol ) && ( rDockingOperation == DOCKOP_AFTER_COLROW )))
bOpOutsideOfDockingArea = true;
else
{
// handle docking before/after a row
implts_setTrackingRect( eDockedArea, rMousePos, aTrackingRect );
rTrackingRect = implts_calcTrackingAndElementRect(
eDockedArea, nRowCol, rUIElement,
aTrackingRect, aRowColumnRect, aContainerWinSize );
sal_Int32 nOffsetX( 0 );
sal_Int32 nOffsetY( 0 );
if ( bHorizontalDockArea )
nOffsetY = sal_Int32( floor( aRowColumnRect.getHeight() / 2 + 0.5 ));
else
nOffsetX = sal_Int32( floor( aRowColumnRect.getWidth() / 2 + 0.5 ));
if ( rDockingOperation == DOCKOP_BEFORE_COLROW )
{
if (( eDockedArea == ui::DockingArea_DOCKINGAREA_TOP ) || ( eDockedArea == ui::DockingArea_DOCKINGAREA_LEFT ))
{
// Docking before/after means move track rectangle half column/row.
// As left and top are ordered 0...n instead of right and bottom
// which uses n...0, we have to use negative values for top/left.
nOffsetX *= -1;
nOffsetY *= -1;
}
}
else
{
if (( eDockedArea == ui::DockingArea_DOCKINGAREA_BOTTOM ) || ( eDockedArea == ui::DockingArea_DOCKINGAREA_RIGHT ))
{
// Docking before/after means move track rectangle half column/row.
// As left and top are ordered 0...n instead of right and bottom
// which uses n...0, we have to use negative values for top/left.
nOffsetX *= -1;
nOffsetY *= -1;
}
nRowCol++;
}
if ( bHorizontalDockArea )
rUIElement.m_aDockedData.m_aPos.Y() = nRowCol;
else
rUIElement.m_aDockedData.m_aPos.X() = nRowCol;
rTrackingRect.Move( nOffsetX, nOffsetY );
rTrackingRect.SetSize( aTrackingRect.GetSize() );
}
}
}
}
// Docking outside of our docking window area =>
// Users want to dock before/after first/last docked element or to an empty docking area
if ( bOpOutsideOfDockingArea )
{
// set correct size for docking
implts_setTrackingRect( eDockedArea, rMousePos, aTrackingRect );
rTrackingRect = aTrackingRect;
if ( bHorizontalDockArea )
{
sal_Int32 nPosX( std::max( sal_Int32( rTrackingRect.Left()), sal_Int32( 0 )));
if (( nPosX + rTrackingRect.getWidth()) > aContainerWinSize.Width() )
nPosX = std::min( nPosX,
std::max( sal_Int32( aContainerWinSize.Width() - rTrackingRect.getWidth() ),
sal_Int32( 0 )));
sal_Int32 nSize = std::min( aContainerWinSize.Width(), rTrackingRect.getWidth() );
sal_Int32 nDockHeight = std::max( static_cast<sal_Int32>(aDockingAreaRect.getHeight()), sal_Int32( 0 ));
if ( nDockHeight == 0 )
{
sal_Int32 nPosY( std::max( aDockingAreaRect.Top(), aDockingAreaRect.Bottom() ));
if ( eDockedArea == ui::DockingArea_DOCKINGAREA_BOTTOM )
nPosY -= rTrackingRect.getHeight();
rTrackingRect.SetPos( Point( nPosX, nPosY ));
rUIElement.m_aDockedData.m_aPos.Y() = 0;
}
else if ( rMousePos.Y() < ( aDockingAreaRect.Top() + ( nDockHeight / 2 )))
{
rTrackingRect.SetPos( Point( nPosX, aDockingAreaRect.Top() - rTrackingRect.getHeight() ));
if ( eDockedArea == ui::DockingArea_DOCKINGAREA_TOP )
rUIElement.m_aDockedData.m_aPos.Y() = 0;
else
rUIElement.m_aDockedData.m_aPos.Y() = ( nMaxRowCol >= 0 ) ? nMaxRowCol+1 : 0;
rDockingOperation = DOCKOP_BEFORE_COLROW;
}
else
{
rTrackingRect.SetPos( Point( nPosX, aDockingAreaRect.Bottom() ));
if ( eDockedArea == ui::DockingArea_DOCKINGAREA_TOP )
rUIElement.m_aDockedData.m_aPos.Y() = ( nMaxRowCol >= 0 ) ? nMaxRowCol+1 : 0;
else
rUIElement.m_aDockedData.m_aPos.Y() = 0;
rDockingOperation = DOCKOP_AFTER_COLROW;
}
rTrackingRect.setWidth( nSize );
{
vos::OGuard aGuard( Application::GetSolarMutex() );
nPosX = pDockingAreaWindow->ScreenToOutputPixel(
pContainerWindow->OutputToScreenPixel( rTrackingRect.TopLeft() )).X();
}
rUIElement.m_aDockedData.m_aPos.X() = nPosX;
}
else
{
sal_Int32 nMaxDockingAreaHeight = std::max( sal_Int32( 0 ), sal_Int32( nMaxLeftRightDockAreaSize ));
sal_Int32 nPosY( std::max( sal_Int32( aTrackingRect.Top()), sal_Int32( nTopDockingAreaSize )));
if (( nPosY + aTrackingRect.getHeight()) > ( nTopDockingAreaSize + nMaxDockingAreaHeight ))
nPosY = std::min( nPosY,
std::max( sal_Int32( nTopDockingAreaSize + ( nMaxDockingAreaHeight - aTrackingRect.getHeight() )),
sal_Int32( nTopDockingAreaSize )));
sal_Int32 nSize = std::min( nMaxDockingAreaHeight, static_cast<sal_Int32>(aTrackingRect.getHeight()) );
sal_Int32 nDockWidth = std::max( static_cast<sal_Int32>(aDockingAreaRect.getWidth()), sal_Int32( 0 ));
if ( nDockWidth == 0 )
{
sal_Int32 nPosX( std::max( aDockingAreaRect.Left(), aDockingAreaRect.Right() ));
if ( eDockedArea == ui::DockingArea_DOCKINGAREA_RIGHT )
nPosX -= rTrackingRect.getWidth();
rTrackingRect.SetPos( Point( nPosX, nPosY ));
rUIElement.m_aDockedData.m_aPos.X() = 0;
}
else if ( rMousePos.X() < ( aDockingAreaRect.Left() + ( nDockWidth / 2 )))
{
rTrackingRect.SetPos( Point( aDockingAreaRect.Left() - rTrackingRect.getWidth(), nPosY ));
if ( eDockedArea == ui::DockingArea_DOCKINGAREA_LEFT )
rUIElement.m_aDockedData.m_aPos.X() = 0;
else
rUIElement.m_aDockedData.m_aPos.X() = ( nMaxRowCol >= 0 ) ? nMaxRowCol+1 : 0;
rDockingOperation = DOCKOP_BEFORE_COLROW;
}
else
{
rTrackingRect.SetPos( Point( aDockingAreaRect.Right(), nPosY ));
if ( eDockedArea == ui::DockingArea_DOCKINGAREA_LEFT )
rUIElement.m_aDockedData.m_aPos.X() = ( nMaxRowCol >= 0 ) ? nMaxRowCol+1 : 0;
else
rUIElement.m_aDockedData.m_aPos.X() = 0;
rDockingOperation = DOCKOP_AFTER_COLROW;
}
rTrackingRect.setHeight( nSize );
{
vos::OGuard aGuard( Application::GetSolarMutex() );
nPosY = pDockingAreaWindow->ScreenToOutputPixel(
pContainerWindow->OutputToScreenPixel( rTrackingRect.TopLeft() )).Y();
}
rUIElement.m_aDockedData.m_aPos.Y() = nPosY;
}
}
}
framework::ToolbarLayoutManager::DockingOperation ToolbarLayoutManager::implts_determineDockingOperation(
ui::DockingArea DockingArea,
const ::Rectangle& rRowColRect,
const Point& rMousePos )
{
const sal_Int32 nHorzVerticalRegionSize = 6;
const sal_Int32 nHorzVerticalMoveRegion = 4;
if ( rRowColRect.IsInside( rMousePos ))
{
if ( isHorizontalDockingArea( DockingArea ))
{
sal_Int32 nRegion = rRowColRect.getHeight() / nHorzVerticalRegionSize;
sal_Int32 nPosY = rRowColRect.Top() + nRegion;
if ( rMousePos.Y() < nPosY )
return ( DockingArea == ui::DockingArea_DOCKINGAREA_TOP ) ? DOCKOP_BEFORE_COLROW : DOCKOP_AFTER_COLROW;
else if ( rMousePos.Y() < ( nPosY + nRegion*nHorzVerticalMoveRegion ))
return DOCKOP_ON_COLROW;
else
return ( DockingArea == ui::DockingArea_DOCKINGAREA_TOP ) ? DOCKOP_AFTER_COLROW : DOCKOP_BEFORE_COLROW;
}
else
{
sal_Int32 nRegion = rRowColRect.getWidth() / nHorzVerticalRegionSize;
sal_Int32 nPosX = rRowColRect.Left() + nRegion;
if ( rMousePos.X() < nPosX )
return ( DockingArea == ui::DockingArea_DOCKINGAREA_LEFT ) ? DOCKOP_BEFORE_COLROW : DOCKOP_AFTER_COLROW;
else if ( rMousePos.X() < ( nPosX + nRegion*nHorzVerticalMoveRegion ))
return DOCKOP_ON_COLROW;
else
return ( DockingArea == ui::DockingArea_DOCKINGAREA_LEFT ) ? DOCKOP_AFTER_COLROW : DOCKOP_BEFORE_COLROW;
}
}
else
return DOCKOP_ON_COLROW;
}
::Rectangle ToolbarLayoutManager::implts_calcTrackingAndElementRect(
ui::DockingArea eDockingArea,
sal_Int32 nRowCol,
UIElement& rUIElement,
const ::Rectangle& rTrackingRect,
const ::Rectangle& rRowColumnRect,
const ::Size& rContainerWinSize )
{
ReadGuard aReadGuard( m_aLock );
::Rectangle aDockingAreaOffsets( m_aDockingAreaOffsets );
aReadGuard.unlock();
bool bHorizontalDockArea( isHorizontalDockingArea( eDockingArea ));
sal_Int32 nTopDockingAreaSize( implts_getTopBottomDockingAreaSizes().Width() );
sal_Int32 nBottomDockingAreaSize( implts_getTopBottomDockingAreaSizes().Height() );
sal_Int32 nMaxLeftRightDockAreaSize = rContainerWinSize.Height() -
nTopDockingAreaSize -
nBottomDockingAreaSize -
aDockingAreaOffsets.Top() -
aDockingAreaOffsets.Bottom();
::Rectangle aTrackingRect( rTrackingRect );
if ( bHorizontalDockArea )
{
sal_Int32 nPosX( std::max( sal_Int32( rTrackingRect.Left()), sal_Int32( 0 )));
if (( nPosX + rTrackingRect.getWidth()) > rContainerWinSize.Width() )
nPosX = std::min( nPosX,
std::max( sal_Int32( rContainerWinSize.Width() - rTrackingRect.getWidth() ),
sal_Int32( 0 )));
sal_Int32 nSize = std::min( rContainerWinSize.Width(), rTrackingRect.getWidth() );
aTrackingRect.SetPos( ::Point( nPosX, rRowColumnRect.Top() ));
aTrackingRect.setWidth( nSize );
aTrackingRect.setHeight( rRowColumnRect.getHeight() );
// Set virtual position
rUIElement.m_aDockedData.m_aPos.X() = nPosX;
rUIElement.m_aDockedData.m_aPos.Y() = nRowCol;
}
else
{
sal_Int32 nMaxDockingAreaHeight = std::max( sal_Int32( 0 ),
sal_Int32( nMaxLeftRightDockAreaSize ));
sal_Int32 nPosY( std::max( sal_Int32( aTrackingRect.Top()), sal_Int32( nTopDockingAreaSize )));
if (( nPosY + aTrackingRect.getHeight()) > ( nTopDockingAreaSize + nMaxDockingAreaHeight ))
nPosY = std::min( nPosY,
std::max( sal_Int32( nTopDockingAreaSize + ( nMaxDockingAreaHeight - aTrackingRect.getHeight() )),
sal_Int32( nTopDockingAreaSize )));
sal_Int32 nSize = std::min( nMaxDockingAreaHeight, static_cast<sal_Int32>(aTrackingRect.getHeight()) );
aTrackingRect.SetPos( ::Point( rRowColumnRect.Left(), nPosY ));
aTrackingRect.setWidth( rRowColumnRect.getWidth() );
aTrackingRect.setHeight( nSize );
aReadGuard.lock();
uno::Reference< awt::XWindow > xDockingAreaWindow( m_xDockAreaWindows[eDockingArea] );
uno::Reference< awt::XWindow2 > xContainerWindow( m_xContainerWindow );
aReadGuard.unlock();
sal_Int32 nDockPosY( 0 );
Window* pDockingAreaWindow( 0 );
Window* pContainerWindow( 0 );
{
vos::OGuard aGuard( Application::GetSolarMutex() );
pDockingAreaWindow = VCLUnoHelper::GetWindow( xDockingAreaWindow );
pContainerWindow = VCLUnoHelper::GetWindow( xContainerWindow );
nDockPosY = pDockingAreaWindow->ScreenToOutputPixel( pContainerWindow->OutputToScreenPixel( ::Point( 0, nPosY ))).Y();
}
// Set virtual position
rUIElement.m_aDockedData.m_aPos.X() = nRowCol;
rUIElement.m_aDockedData.m_aPos.Y() = nDockPosY;
}
return aTrackingRect;
}
void ToolbarLayoutManager::implts_setTrackingRect( ui::DockingArea eDockingArea, const ::Point& rMousePos, ::Rectangle& rTrackingRect )
{
::Point aPoint( rTrackingRect.TopLeft());
if ( isHorizontalDockingArea( eDockingArea ))
aPoint.X() = rMousePos.X();
else
aPoint.Y() = rMousePos.Y();
rTrackingRect.SetPos( aPoint );
}
void ToolbarLayoutManager::implts_renumberRowColumnData(
ui::DockingArea eDockingArea,
DockingOperation /*eDockingOperation*/,
const UIElement& rUIElement )
{
ReadGuard aReadLock( m_aLock );
uno::Reference< container::XNameAccess > xPersistentWindowState( m_xPersistentWindowState );
aReadLock.unlock();
bool bHorzDockingArea( isHorizontalDockingArea( eDockingArea ));
sal_Int32 nRowCol( bHorzDockingArea ? rUIElement.m_aDockedData.m_aPos.Y() : rUIElement.m_aDockedData.m_aPos.X() );
/* SAFE AREA ----------------------------------------------------------------------------------------------- */
WriteGuard aWriteLock( m_aLock );
UIElementVector::iterator pIter;
for ( pIter = m_aUIElements.begin(); pIter != m_aUIElements.end(); pIter++ )
{
if (( pIter->m_aDockedData.m_nDockedArea == sal_Int16( eDockingArea )) && ( pIter->m_aName != rUIElement.m_aName ))
{
// Don't change toolbars without a valid docking position!
if ( isDefaultPos( pIter->m_aDockedData.m_aPos ))
continue;
sal_Int32 nWindowRowCol = ( bHorzDockingArea ) ? pIter->m_aDockedData.m_aPos.Y() : pIter->m_aDockedData.m_aPos.X();
if ( nWindowRowCol >= nRowCol )
{
if ( bHorzDockingArea )
pIter->m_aDockedData.m_aPos.Y() += 1;
else
pIter->m_aDockedData.m_aPos.X() += 1;
}
}
}
aWriteLock.unlock();
/* SAFE AREA ----------------------------------------------------------------------------------------------- */
// We have to change the persistent window state part
if ( xPersistentWindowState.is() )
{
try
{
uno::Sequence< ::rtl::OUString > aWindowElements = xPersistentWindowState->getElementNames();
for ( sal_Int32 i = 0; i < aWindowElements.getLength(); i++ )
{
if ( rUIElement.m_aName != aWindowElements[i] )
{
try
{
uno::Sequence< beans::PropertyValue > aPropValueSeq;
awt::Point aDockedPos;
ui::DockingArea nDockedArea( ui::DockingArea_DOCKINGAREA_DEFAULT );
xPersistentWindowState->getByName( aWindowElements[i] ) >>= aPropValueSeq;
for ( sal_Int32 j = 0; j < aPropValueSeq.getLength(); j++ )
{
if ( aPropValueSeq[j].Name.equalsAscii( WINDOWSTATE_PROPERTY_DOCKINGAREA ))
aPropValueSeq[j].Value >>= nDockedArea;
else if ( aPropValueSeq[j].Name.equalsAscii( WINDOWSTATE_PROPERTY_DOCKPOS ))
aPropValueSeq[j].Value >>= aDockedPos;
}
// Don't change toolbars without a valid docking position!
if ( isDefaultPos( aDockedPos ))
continue;
sal_Int32 nWindowRowCol = ( bHorzDockingArea ) ? aDockedPos.Y : aDockedPos.X;
if (( nDockedArea == eDockingArea ) && ( nWindowRowCol >= nRowCol ))
{
if ( bHorzDockingArea )
aDockedPos.Y += 1;
else
aDockedPos.X += 1;
uno::Reference< container::XNameReplace > xReplace( xPersistentWindowState, uno::UNO_QUERY );
xReplace->replaceByName( aWindowElements[i], makeAny( aPropValueSeq ));
}
}
catch ( uno::Exception& ) {}
}
}
}
catch ( uno::Exception& ) {}
}
}
//---------------------------------------------------------------------------------------------------------
// XWindowListener
//---------------------------------------------------------------------------------------------------------
void SAL_CALL ToolbarLayoutManager::windowResized( const awt::WindowEvent& aEvent )
throw( uno::RuntimeException )
{
WriteGuard aWriteLock( m_aLock );
bool bLocked( m_bDockingInProgress );
bool bLayoutInProgress( m_bLayoutInProgress );
aWriteLock.unlock();
// Do not do anything if we are in the middle of a docking process. This would interfere all other
// operations. We will store the new position and size in the docking handlers.
// Do not do anything if we are in the middle of our layouting process. We will adapt the position
// and size of the user interface elements.
if ( !bLocked && !bLayoutInProgress )
{
bool bNotify( false );
uno::Reference< awt::XWindow > xWindow( aEvent.Source, uno::UNO_QUERY );
UIElement aUIElement = implts_findToolbar( aEvent.Source );
if ( aUIElement.m_xUIElement.is() )
{
if ( aUIElement.m_bFloating )
{
uno::Reference< awt::XWindow2 > xWindow2( xWindow, uno::UNO_QUERY );
if( xWindow2.is() )
{
awt::Rectangle aPos = xWindow2->getPosSize();
awt::Size aSize = xWindow2->getOutputSize(); // always use output size for consistency
bool bVisible = xWindow2->isVisible();
// update element data
aUIElement.m_aFloatingData.m_aPos = ::Point( aPos.X, aPos.Y );
aUIElement.m_aFloatingData.m_aSize = ::Size( aSize.Width, aSize.Height );
aUIElement.m_bVisible = bVisible;
}
implts_writeWindowStateData( aUIElement );
}
else
{
implts_setLayoutDirty();
bNotify = true;
}
}
if ( bNotify )
m_pParentLayouter->requestLayout( ILayoutNotifications::HINT_TOOLBARSPACE_HAS_CHANGED );
}
}
void SAL_CALL ToolbarLayoutManager::windowMoved( const awt::WindowEvent& /*aEvent*/ )
throw( uno::RuntimeException )
{
}
void SAL_CALL ToolbarLayoutManager::windowShown( const lang::EventObject& /*aEvent*/ )
throw( uno::RuntimeException )
{
}
void SAL_CALL ToolbarLayoutManager::windowHidden( const lang::EventObject& /*aEvent*/ )
throw( uno::RuntimeException )
{
}
//---------------------------------------------------------------------------------------------------------
// XDockableWindowListener
//---------------------------------------------------------------------------------------------------------
void SAL_CALL ToolbarLayoutManager::startDocking( const awt::DockingEvent& e )
throw (uno::RuntimeException)
{
bool bWinFound( false );
ReadGuard aReadGuard( m_aLock );
uno::Reference< awt::XWindow2 > xContainerWindow( m_xContainerWindow );
uno::Reference< awt::XWindow2 > xWindow( e.Source, uno::UNO_QUERY );
aReadGuard.unlock();
Window* pContainerWindow( 0 );
Window* pWindow( 0 );
::Point aMousePos;
{
vos::OGuard aGuard( Application::GetSolarMutex() );
pContainerWindow = VCLUnoHelper::GetWindow( xContainerWindow );
aMousePos = pContainerWindow->ScreenToOutputPixel( ::Point( e.MousePos.X, e.MousePos.Y ));
}
UIElement aUIElement = implts_findToolbar( e.Source );
if ( aUIElement.m_xUIElement.is() && xWindow.is() )
{
awt::Rectangle aRect;
bWinFound = true;
uno::Reference< awt::XDockableWindow > xDockWindow( xWindow, uno::UNO_QUERY );
if ( xDockWindow->isFloating() )
{
awt::Rectangle aPos = xWindow->getPosSize();
awt::Size aSize = xWindow->getOutputSize();
aUIElement.m_aFloatingData.m_aPos = ::Point( aPos.X, aPos.Y );
aUIElement.m_aFloatingData.m_aSize = ::Size( aSize.Width, aSize.Height );
vos::OGuard aGuard( Application::GetSolarMutex() );
pWindow = VCLUnoHelper::GetWindow( xWindow );
if ( pWindow && pWindow->GetType() == WINDOW_TOOLBOX )
{
ToolBox* pToolBox = (ToolBox *)pWindow;
aUIElement.m_aFloatingData.m_nLines = pToolBox->GetFloatingLines();
aUIElement.m_aFloatingData.m_bIsHorizontal = isToolboxHorizontalAligned( pToolBox );
}
}
}
WriteGuard aWriteLock( m_aLock );
m_bDockingInProgress = bWinFound;
m_aDockUIElement = aUIElement;
m_aDockUIElement.m_bUserActive = true;
m_aStartDockMousePos = aMousePos;
aWriteLock.unlock();
}
awt::DockingData SAL_CALL ToolbarLayoutManager::docking( const awt::DockingEvent& e )
throw (uno::RuntimeException)
{
const sal_Int32 MAGNETIC_DISTANCE_UNDOCK = 25;
const sal_Int32 MAGNETIC_DISTANCE_DOCK = 20;
ReadGuard aReadLock( m_aLock );
awt::DockingData aDockingData;
uno::Reference< awt::XDockableWindow > xDockWindow( e.Source, uno::UNO_QUERY );
uno::Reference< awt::XWindow > xWindow( e.Source, uno::UNO_QUERY );
uno::Reference< awt::XWindow > xTopDockingWindow( m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_TOP] );
uno::Reference< awt::XWindow > xLeftDockingWindow( m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_LEFT] );
uno::Reference< awt::XWindow > xRightDockingWindow( m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_RIGHT] );
uno::Reference< awt::XWindow > xBottomDockingWindow( m_xDockAreaWindows[ui::DockingArea_DOCKINGAREA_BOTTOM] );
uno::Reference< awt::XWindow2 > xContainerWindow( m_xContainerWindow );
UIElement aUIDockingElement( m_aDockUIElement );
DockingOperation eDockingOperation( DOCKOP_ON_COLROW );
bool bDockingInProgress( m_bDockingInProgress );
aReadLock.unlock();
if ( bDockingInProgress )
aDockingData.TrackingRectangle = e.TrackingRectangle;
if ( bDockingInProgress && xDockWindow.is() && xWindow.is() )
{
try
{
vos::OGuard aGuard( Application::GetSolarMutex() );
sal_Int16 eDockingArea( -1 ); // none
sal_Int32 nMagneticZone( aUIDockingElement.m_bFloating ? MAGNETIC_DISTANCE_DOCK : MAGNETIC_DISTANCE_UNDOCK );
awt::Rectangle aNewTrackingRect;
::Rectangle aTrackingRect( e.TrackingRectangle.X, e.TrackingRectangle.Y,
( e.TrackingRectangle.X + e.TrackingRectangle.Width ),
( e.TrackingRectangle.Y + e.TrackingRectangle.Height ));
awt::Rectangle aTmpRect = xTopDockingWindow->getPosSize();
::Rectangle aTopDockRect( aTmpRect.X, aTmpRect.Y, aTmpRect.Width, aTmpRect.Height );
::Rectangle aHotZoneTopDockRect( implts_calcHotZoneRect( aTopDockRect, nMagneticZone ));
aTmpRect = xBottomDockingWindow->getPosSize();
::Rectangle aBottomDockRect( aTmpRect.X, aTmpRect.Y, ( aTmpRect.X + aTmpRect.Width), ( aTmpRect.Y + aTmpRect.Height ));
::Rectangle aHotZoneBottomDockRect( implts_calcHotZoneRect( aBottomDockRect, nMagneticZone ));
aTmpRect = xLeftDockingWindow->getPosSize();
::Rectangle aLeftDockRect( aTmpRect.X, aTmpRect.Y, ( aTmpRect.X + aTmpRect.Width ), ( aTmpRect.Y + aTmpRect.Height ));
::Rectangle aHotZoneLeftDockRect( implts_calcHotZoneRect( aLeftDockRect, nMagneticZone ));
aTmpRect = xRightDockingWindow->getPosSize();
::Rectangle aRightDockRect( aTmpRect.X, aTmpRect.Y, ( aTmpRect.X + aTmpRect.Width ), ( aTmpRect.Y + aTmpRect.Height ));
::Rectangle aHotZoneRightDockRect( implts_calcHotZoneRect( aRightDockRect, nMagneticZone ));
Window* pContainerWindow( VCLUnoHelper::GetWindow( xContainerWindow ) );
Window* pDockingAreaWindow( 0 );
::Point aMousePos( pContainerWindow->ScreenToOutputPixel( ::Point( e.MousePos.X, e.MousePos.Y )));
if ( aHotZoneTopDockRect.IsInside( aMousePos ))
eDockingArea = ui::DockingArea_DOCKINGAREA_TOP;
else if ( aHotZoneBottomDockRect.IsInside( aMousePos ))
eDockingArea = ui::DockingArea_DOCKINGAREA_BOTTOM;
else if ( aHotZoneLeftDockRect.IsInside( aMousePos ))
eDockingArea = ui::DockingArea_DOCKINGAREA_LEFT;
else if ( aHotZoneRightDockRect.IsInside( aMousePos ))
eDockingArea = ui::DockingArea_DOCKINGAREA_RIGHT;
// Higher priority for movements inside the real docking area
if ( aTopDockRect.IsInside( aMousePos ))
eDockingArea = ui::DockingArea_DOCKINGAREA_TOP;
else if ( aBottomDockRect.IsInside( aMousePos ))
eDockingArea = ui::DockingArea_DOCKINGAREA_BOTTOM;
else if ( aLeftDockRect.IsInside( aMousePos ))
eDockingArea = ui::DockingArea_DOCKINGAREA_LEFT;
else if ( aRightDockRect.IsInside( aMousePos ))
eDockingArea = ui::DockingArea_DOCKINGAREA_RIGHT;
// Determine if we have a toolbar and set alignment according to the docking area!
Window* pWindow = VCLUnoHelper::GetWindow( xWindow );
ToolBox* pToolBox = 0;
if ( pWindow && pWindow->GetType() == WINDOW_TOOLBOX )
pToolBox = (ToolBox *)pWindow;
if ( eDockingArea != -1 )
{
if ( eDockingArea == ui::DockingArea_DOCKINGAREA_TOP )
{
aUIDockingElement.m_aDockedData.m_nDockedArea = ui::DockingArea_DOCKINGAREA_TOP;
aUIDockingElement.m_bFloating = false;
pDockingAreaWindow = VCLUnoHelper::GetWindow( xTopDockingWindow );
}
else if ( eDockingArea == ui::DockingArea_DOCKINGAREA_BOTTOM )
{
aUIDockingElement.m_aDockedData.m_nDockedArea = ui::DockingArea_DOCKINGAREA_BOTTOM;
aUIDockingElement.m_bFloating = false;
pDockingAreaWindow = VCLUnoHelper::GetWindow( xBottomDockingWindow );
}
else if ( eDockingArea == ui::DockingArea_DOCKINGAREA_LEFT )
{
aUIDockingElement.m_aDockedData.m_nDockedArea = ui::DockingArea_DOCKINGAREA_LEFT;
aUIDockingElement.m_bFloating = false;
pDockingAreaWindow = VCLUnoHelper::GetWindow( xLeftDockingWindow );
}
else if ( eDockingArea == ui::DockingArea_DOCKINGAREA_RIGHT )
{
aUIDockingElement.m_aDockedData.m_nDockedArea = ui::DockingArea_DOCKINGAREA_RIGHT;
aUIDockingElement.m_bFloating = false;
pDockingAreaWindow = VCLUnoHelper::GetWindow( xRightDockingWindow );
}
::Point aOutputPos = pContainerWindow->ScreenToOutputPixel( aTrackingRect.TopLeft() );
aTrackingRect.SetPos( aOutputPos );
::Rectangle aNewDockingRect( aTrackingRect );
implts_calcDockingPosSize( aUIDockingElement, eDockingOperation, aNewDockingRect, aMousePos );
::Point aScreenPos = pContainerWindow->OutputToScreenPixel( aNewDockingRect.TopLeft() );
aNewTrackingRect = awt::Rectangle( aScreenPos.X(), aScreenPos.Y(),
aNewDockingRect.getWidth(), aNewDockingRect.getHeight() );
aDockingData.TrackingRectangle = aNewTrackingRect;
}
else if ( pToolBox && bDockingInProgress )
{
bool bIsHorizontal = isToolboxHorizontalAligned( pToolBox );
::Size aFloatSize = aUIDockingElement.m_aFloatingData.m_aSize;
if ( aFloatSize.Width() > 0 && aFloatSize.Height() > 0 )
{
aUIDockingElement.m_aFloatingData.m_aPos = pContainerWindow->ScreenToOutputPixel(
::Point( e.MousePos.X, e.MousePos.Y ));
aDockingData.TrackingRectangle.Height = aFloatSize.Height();
aDockingData.TrackingRectangle.Width = aFloatSize.Width();
}
else
{
aFloatSize = pToolBox->CalcWindowSizePixel();
if ( !bIsHorizontal )
{
// Floating toolbars are always horizontal aligned! We have to swap
// width/height if we have a vertical aligned toolbar.
sal_Int32 nTemp = aFloatSize.Height();
aFloatSize.Height() = aFloatSize.Width();
aFloatSize.Width() = nTemp;
}
aDockingData.TrackingRectangle.Height = aFloatSize.Height();
aDockingData.TrackingRectangle.Width = aFloatSize.Width();
// For the first time we don't have any data about the floating size of a toolbar.
// We calculate it and store it for later use.
aUIDockingElement.m_aFloatingData.m_aPos = pContainerWindow->ScreenToOutputPixel(::Point( e.MousePos.X, e.MousePos.Y ));
aUIDockingElement.m_aFloatingData.m_aSize = aFloatSize;
aUIDockingElement.m_aFloatingData.m_nLines = pToolBox->GetFloatingLines();
aUIDockingElement.m_aFloatingData.m_bIsHorizontal = isToolboxHorizontalAligned( pToolBox );
}
aDockingData.TrackingRectangle.X = e.MousePos.X;
aDockingData.TrackingRectangle.Y = e.MousePos.Y;
}
aDockingData.bFloating = ( eDockingArea == -1 );
// Write current data to the member docking progress data
WriteGuard aWriteLock( m_aLock );
m_aDockUIElement.m_bFloating = aDockingData.bFloating;
if ( !aDockingData.bFloating )
{
m_aDockUIElement.m_aDockedData = aUIDockingElement.m_aDockedData;
m_eDockOperation = eDockingOperation;
}
else
m_aDockUIElement.m_aFloatingData = aUIDockingElement.m_aFloatingData;
aWriteLock.unlock();
}
catch ( uno::Exception& ) {}
}
return aDockingData;
}
void SAL_CALL ToolbarLayoutManager::endDocking( const awt::EndDockingEvent& e )
throw (uno::RuntimeException)
{
bool bDockingInProgress( false );
bool bStartDockFloated( false );
bool bFloating( false );
UIElement aUIDockingElement;
/* SAFE AREA ----------------------------------------------------------------------------------------------- */
WriteGuard aWriteLock( m_aLock );
bDockingInProgress = m_bDockingInProgress;
aUIDockingElement = m_aDockUIElement;
bFloating = aUIDockingElement.m_bFloating;
UIElement& rUIElement = impl_findToolbar( aUIDockingElement.m_aName );
if ( rUIElement.m_aName == aUIDockingElement.m_aName )
{
if ( aUIDockingElement.m_bFloating )
{
// Write last position into position data
uno::Reference< awt::XWindow > xWindow( aUIDockingElement.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
rUIElement.m_aFloatingData = aUIDockingElement.m_aFloatingData;
awt::Rectangle aTmpRect = xWindow->getPosSize();
rUIElement.m_aFloatingData.m_aPos = ::Point( aTmpRect.X, aTmpRect.Y );
// make changes also for our local data as we use it to make data persistent
aUIDockingElement.m_aFloatingData = rUIElement.m_aFloatingData;
}
else
{
rUIElement.m_aDockedData = aUIDockingElement.m_aDockedData;
rUIElement.m_aFloatingData.m_aSize = aUIDockingElement.m_aFloatingData.m_aSize;
if ( m_eDockOperation != DOCKOP_ON_COLROW )
{
// we have to renumber our row/column data to insert a new row/column
implts_renumberRowColumnData((ui::DockingArea)aUIDockingElement.m_aDockedData.m_nDockedArea, m_eDockOperation, aUIDockingElement );
}
}
bStartDockFloated = rUIElement.m_bFloating;
rUIElement.m_bFloating = m_aDockUIElement.m_bFloating;
rUIElement.m_bUserActive = true;
}
// reset member for next docking operation
m_aDockUIElement.m_xUIElement.clear();
m_eDockOperation = DOCKOP_ON_COLROW;
aWriteLock.unlock();
/* SAFE AREA ----------------------------------------------------------------------------------------------- */
implts_writeWindowStateData( aUIDockingElement );
if ( bDockingInProgress )
{
vos::OGuard aGuard( Application::GetSolarMutex() );
Window* pWindow = VCLUnoHelper::GetWindow( uno::Reference< awt::XWindow >( e.Source, uno::UNO_QUERY ));
ToolBox* pToolBox = 0;
if ( pWindow && pWindow->GetType() == WINDOW_TOOLBOX )
pToolBox = (ToolBox *)pWindow;
if ( pToolBox )
{
if( e.bFloating )
{
if ( aUIDockingElement.m_aFloatingData.m_bIsHorizontal )
pToolBox->SetAlign( WINDOWALIGN_TOP );
else
pToolBox->SetAlign( WINDOWALIGN_LEFT );
}
else
{
::Size aSize;
pToolBox->SetAlign( ImplConvertAlignment( aUIDockingElement.m_aDockedData.m_nDockedArea) );
// Docked toolbars have always one line
aSize = pToolBox->CalcWindowSizePixel( 1 );
// Lock layouting updates as our listener would be called due to SetSizePixel
pToolBox->SetOutputSizePixel( aSize );
}
}
}
implts_sortUIElements();
aWriteLock.lock();
m_bDockingInProgress = sal_False;
m_bLayoutDirty = !bStartDockFloated || !bFloating;
bool bNotify = m_bLayoutDirty;
aWriteLock.unlock();
if ( bNotify )
m_pParentLayouter->requestLayout( ILayoutNotifications::HINT_TOOLBARSPACE_HAS_CHANGED );
}
sal_Bool SAL_CALL ToolbarLayoutManager::prepareToggleFloatingMode( const lang::EventObject& e )
throw (uno::RuntimeException)
{
ReadGuard aReadLock( m_aLock );
bool bDockingInProgress = m_bDockingInProgress;
aReadLock.unlock();
UIElement aUIDockingElement = implts_findToolbar( e.Source );
bool bWinFound( aUIDockingElement.m_aName.getLength() > 0 );
uno::Reference< awt::XWindow > xWindow( e.Source, uno::UNO_QUERY );
if ( bWinFound && xWindow.is() )
{
if ( !bDockingInProgress )
{
awt::Rectangle aRect;
uno::Reference< awt::XDockableWindow > xDockWindow( xWindow, uno::UNO_QUERY );
if ( xDockWindow->isFloating() )
{
{
vos::OGuard aGuard( Application::GetSolarMutex() );
Window* pWindow = VCLUnoHelper::GetWindow( xWindow );
if ( pWindow && pWindow->GetType() == WINDOW_TOOLBOX )
{
ToolBox* pToolBox = static_cast< ToolBox *>( pWindow );
aUIDockingElement.m_aFloatingData.m_aPos = pToolBox->GetPosPixel();
aUIDockingElement.m_aFloatingData.m_aSize = pToolBox->GetOutputSizePixel();
aUIDockingElement.m_aFloatingData.m_nLines = pToolBox->GetFloatingLines();
aUIDockingElement.m_aFloatingData.m_bIsHorizontal = isToolboxHorizontalAligned( pToolBox );
}
}
UIElement aUIElement = implts_findToolbar( aUIDockingElement.m_aName );
if ( aUIElement.m_aName == aUIDockingElement.m_aName )
implts_setToolbar( aUIDockingElement );
}
}
}
return sal_True;
}
void SAL_CALL ToolbarLayoutManager::toggleFloatingMode( const lang::EventObject& e )
throw (uno::RuntimeException)
{
UIElement aUIDockingElement;
ReadGuard aReadLock( m_aLock );
bool bDockingInProgress( m_bDockingInProgress );
if ( bDockingInProgress )
aUIDockingElement = m_aDockUIElement;
aReadLock.unlock();
Window* pWindow( 0 );
ToolBox* pToolBox( 0 );
uno::Reference< awt::XWindow2 > xWindow;
{
vos::OGuard aGuard( Application::GetSolarMutex() );
xWindow = uno::Reference< awt::XWindow2 >( e.Source, uno::UNO_QUERY );
pWindow = VCLUnoHelper::GetWindow( xWindow );
if ( pWindow && pWindow->GetType() == WINDOW_TOOLBOX )
pToolBox = (ToolBox *)pWindow;
}
if ( !bDockingInProgress )
{
aUIDockingElement = implts_findToolbar( e.Source );
bool bWinFound = ( aUIDockingElement.m_aName.getLength() > 0 );
if ( bWinFound && xWindow.is() )
{
aUIDockingElement.m_bFloating = !aUIDockingElement.m_bFloating;
aUIDockingElement.m_bUserActive = true;
implts_setLayoutInProgress( true );
if ( aUIDockingElement.m_bFloating )
{
vos::OGuard aGuard( Application::GetSolarMutex() );
if ( pToolBox )
{
pToolBox->SetLineCount( aUIDockingElement.m_aFloatingData.m_nLines );
if ( aUIDockingElement.m_aFloatingData.m_bIsHorizontal )
pToolBox->SetAlign( WINDOWALIGN_TOP );
else
pToolBox->SetAlign( WINDOWALIGN_LEFT );
}
bool bUndefPos = hasDefaultPosValue( aUIDockingElement.m_aFloatingData.m_aPos );
bool bSetSize = !hasEmptySize( aUIDockingElement.m_aFloatingData.m_aSize );
if ( bUndefPos )
aUIDockingElement.m_aFloatingData.m_aPos = implts_findNextCascadeFloatingPos();
if ( !bSetSize )
{
if ( pToolBox )
aUIDockingElement.m_aFloatingData.m_aSize = pToolBox->CalcFloatingWindowSizePixel();
else
aUIDockingElement.m_aFloatingData.m_aSize = pWindow->GetOutputSizePixel();
}
xWindow->setPosSize( aUIDockingElement.m_aFloatingData.m_aPos.X(),
aUIDockingElement.m_aFloatingData.m_aPos.Y(),
0, 0, awt::PosSize::POS );
xWindow->setOutputSize( AWTSize( aUIDockingElement.m_aFloatingData.m_aSize ) );
}
else
{
if ( isDefaultPos( aUIDockingElement.m_aDockedData.m_aPos ))
{
// Docking on its default position without a preset position -
// we have to find a good place for it.
::Point aPixelPos;
::Point aDockPos;
::Size aSize;
{
vos::OGuard aGuard( Application::GetSolarMutex() );
if ( pToolBox )
aSize = pToolBox->CalcWindowSizePixel( 1, ImplConvertAlignment( aUIDockingElement.m_aDockedData.m_nDockedArea ) );
else
aSize = pWindow->GetSizePixel();
}
implts_findNextDockingPos((ui::DockingArea)aUIDockingElement.m_aDockedData.m_nDockedArea, aSize, aDockPos, aPixelPos );
aUIDockingElement.m_aDockedData.m_aPos = aDockPos;
}
vos::OGuard aGuard( Application::GetSolarMutex() );
if ( pToolBox )
{
pToolBox->SetAlign( ImplConvertAlignment( aUIDockingElement.m_aDockedData.m_nDockedArea) );
::Size aSize = pToolBox->CalcWindowSizePixel( 1 );
awt::Rectangle aRect = xWindow->getPosSize();
xWindow->setPosSize( aRect.X, aRect.Y, 0, 0, awt::PosSize::POS );
xWindow->setOutputSize( AWTSize( aSize ) );
}
}
implts_setLayoutInProgress( false );
implts_setToolbar( aUIDockingElement );
implts_writeWindowStateData( aUIDockingElement );
implts_sortUIElements();
implts_setLayoutDirty();
aReadLock.lock();
ILayoutNotifications* pParentLayouter( m_pParentLayouter );
aReadLock.unlock();
if ( pParentLayouter )
pParentLayouter->requestLayout( ILayoutNotifications::HINT_TOOLBARSPACE_HAS_CHANGED );
}
}
else
{
vos::OGuard aGuard( Application::GetSolarMutex() );
if ( pToolBox )
{
if ( aUIDockingElement.m_bFloating )
{
if ( aUIDockingElement.m_aFloatingData.m_bIsHorizontal )
pToolBox->SetAlign( WINDOWALIGN_TOP );
else
pToolBox->SetAlign( WINDOWALIGN_LEFT );
}
else
pToolBox->SetAlign( ImplConvertAlignment( aUIDockingElement.m_aDockedData.m_nDockedArea) );
}
}
}
void SAL_CALL ToolbarLayoutManager::closed( const lang::EventObject& e )
throw (uno::RuntimeException)
{
rtl::OUString aName;
UIElement aUIElement;
UIElementVector::iterator pIter;
WriteGuard aWriteLock( m_aLock );
for ( pIter = m_aUIElements.begin(); pIter != m_aUIElements.end(); pIter++ )
{
uno::Reference< ui::XUIElement > xUIElement( pIter->m_xUIElement );
if ( xUIElement.is() )
{
uno::Reference< uno::XInterface > xIfac( xUIElement->getRealInterface(), uno::UNO_QUERY );
if ( xIfac == e.Source )
{
aName = pIter->m_aName;
// user closes a toolbar =>
// context sensitive toolbar: only destroy toolbar and store state.
// context sensitive toolbar: make it invisible, store state and destroy it.
if ( !pIter->m_bContextSensitive )
pIter->m_bVisible = sal_False;
aUIElement = *pIter;
break;
}
}
}
aWriteLock.unlock();
// destroy element
if ( aName.getLength() > 0 )
{
implts_writeWindowStateData( aUIElement );
destroyToolbar( aName );
}
}
void SAL_CALL ToolbarLayoutManager::endPopupMode( const awt::EndPopupModeEvent& /*e*/ )
throw (uno::RuntimeException)
{
}
//---------------------------------------------------------------------------------------------------------
// XUIConfigurationListener
//---------------------------------------------------------------------------------------------------------
void SAL_CALL ToolbarLayoutManager::elementInserted( const ui::ConfigurationEvent& rEvent )
throw (uno::RuntimeException)
{
UIElement aUIElement = implts_findToolbar( rEvent.ResourceURL );
uno::Reference< ui::XUIElementSettings > xElementSettings( aUIElement.m_xUIElement, uno::UNO_QUERY );
if ( xElementSettings.is() )
{
::rtl::OUString aConfigSourcePropName( RTL_CONSTASCII_USTRINGPARAM( "ConfigurationSource" ));
uno::Reference< beans::XPropertySet > xPropSet( xElementSettings, uno::UNO_QUERY );
if ( xPropSet.is() )
{
if ( rEvent.Source == uno::Reference< uno::XInterface >( m_xDocCfgMgr, uno::UNO_QUERY ))
xPropSet->setPropertyValue( aConfigSourcePropName, makeAny( m_xDocCfgMgr ));
}
xElementSettings->updateSettings();
}
else
{
::rtl::OUString aElementType;
::rtl::OUString aElementName;
parseResourceURL( rEvent.ResourceURL, aElementType, aElementName );
if ( aElementName.indexOf( m_aCustomTbxPrefix ) != -1 )
{
// custom toolbar must be directly created, shown and layouted!
createToolbar( rEvent.ResourceURL );
uno::Reference< ui::XUIElement > xUIElement = getToolbar( rEvent.ResourceURL );
if ( xUIElement.is() )
{
::rtl::OUString aUIName;
uno::Reference< ui::XUIConfigurationManager > xCfgMgr;
uno::Reference< beans::XPropertySet > xPropSet;
try
{
xCfgMgr = uno::Reference< ui::XUIConfigurationManager >( rEvent.Source, uno::UNO_QUERY );
xPropSet = uno::Reference< beans::XPropertySet >( xCfgMgr->getSettings( rEvent.ResourceURL, sal_False ), uno::UNO_QUERY );
if ( xPropSet.is() )
xPropSet->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UIName" ))) >>= aUIName;
}
catch ( container::NoSuchElementException& ) {}
catch ( beans::UnknownPropertyException& ) {}
catch ( lang::WrappedTargetException& ) {}
{
vos::OGuard aGuard( Application::GetSolarMutex() );
Window* pWindow = getWindowFromXUIElement( xUIElement );
if ( pWindow )
pWindow->SetText( aUIName );
}
showToolbar( rEvent.ResourceURL );
}
}
}
}
void SAL_CALL ToolbarLayoutManager::elementRemoved( const ui::ConfigurationEvent& rEvent )
throw (uno::RuntimeException)
{
ReadGuard aReadLock( m_aLock );
uno::Reference< awt::XWindow > xContainerWindow( m_xContainerWindow, uno::UNO_QUERY );
uno::Reference< ui::XUIConfigurationManager > xModuleCfgMgr( m_xModuleCfgMgr );
uno::Reference< ui::XUIConfigurationManager > xDocCfgMgr( m_xDocCfgMgr );
aReadLock.unlock();
UIElement aUIElement = implts_findToolbar( rEvent.ResourceURL );
uno::Reference< ui::XUIElementSettings > xElementSettings( aUIElement.m_xUIElement, uno::UNO_QUERY );
if ( xElementSettings.is() )
{
bool bNoSettings( false );
::rtl::OUString aConfigSourcePropName( RTL_CONSTASCII_USTRINGPARAM( "ConfigurationSource" ));
uno::Reference< uno::XInterface > xElementCfgMgr;
uno::Reference< beans::XPropertySet > xPropSet( xElementSettings, uno::UNO_QUERY );
if ( xPropSet.is() )
xPropSet->getPropertyValue( aConfigSourcePropName ) >>= xElementCfgMgr;
if ( !xElementCfgMgr.is() )
return;
// Check if the same UI configuration manager has changed => check further
if ( rEvent.Source == xElementCfgMgr )
{
// Same UI configuration manager where our element has its settings
if ( rEvent.Source == uno::Reference< uno::XInterface >( xDocCfgMgr, uno::UNO_QUERY ))
{
// document settings removed
if ( xModuleCfgMgr->hasSettings( rEvent.ResourceURL ))
{
xPropSet->setPropertyValue( aConfigSourcePropName, makeAny( xModuleCfgMgr ));
xElementSettings->updateSettings();
return;
}
}
bNoSettings = true;
}
// No settings anymore, element must be destroyed
if ( xContainerWindow.is() && bNoSettings )
destroyToolbar( rEvent.ResourceURL );
}
}
void SAL_CALL ToolbarLayoutManager::elementReplaced( const ui::ConfigurationEvent& rEvent )
throw (uno::RuntimeException)
{
UIElement aUIElement = implts_findToolbar( rEvent.ResourceURL );
uno::Reference< ui::XUIElementSettings > xElementSettings( aUIElement.m_xUIElement, uno::UNO_QUERY );
if ( xElementSettings.is() )
{
::rtl::OUString aConfigSourcePropName( RTL_CONSTASCII_USTRINGPARAM( "ConfigurationSource" ));
uno::Reference< uno::XInterface > xElementCfgMgr;
uno::Reference< beans::XPropertySet > xPropSet( xElementSettings, uno::UNO_QUERY );
if ( xPropSet.is() )
xPropSet->getPropertyValue( aConfigSourcePropName ) >>= xElementCfgMgr;
if ( !xElementCfgMgr.is() )
return;
// Check if the same UI configuration manager has changed => update settings
if ( rEvent.Source == xElementCfgMgr )
{
xElementSettings->updateSettings();
WriteGuard aWriteLock( m_aLock );
bool bNotify = !aUIElement.m_bFloating;
m_bLayoutDirty = bNotify;
ILayoutNotifications* pParentLayouter( m_pParentLayouter );
aWriteLock.unlock();
if ( bNotify && pParentLayouter )
pParentLayouter->requestLayout( ILayoutNotifications::HINT_TOOLBARSPACE_HAS_CHANGED );
}
}
}
uno::Reference< ui::XUIElement > ToolbarLayoutManager::getToolbar( const ::rtl::OUString& aName )
{
return implts_findToolbar( aName ).m_xUIElement;
}
uno::Sequence< uno::Reference< ui::XUIElement > > ToolbarLayoutManager::getToolbars()
{
uno::Sequence< uno::Reference< ui::XUIElement > > aSeq;
ReadGuard aReadLock( m_aLock );
if ( m_aUIElements.size() > 0 )
{
sal_uInt32 nCount(0);
UIElementVector::iterator pIter;
for ( pIter = m_aUIElements.begin(); pIter != m_aUIElements.end(); pIter++ )
{
if ( pIter->m_xUIElement.is() )
{
++nCount;
aSeq.realloc( nCount );
aSeq[nCount-1] = pIter->m_xUIElement;
}
}
}
return aSeq;
}
bool ToolbarLayoutManager::floatToolbar( const ::rtl::OUString& rResourceURL )
{
UIElement aUIElement = implts_findToolbar( rResourceURL );
if ( aUIElement.m_xUIElement.is() )
{
try
{
uno::Reference< awt::XDockableWindow > xDockWindow( aUIElement.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
if ( xDockWindow.is() && !xDockWindow->isFloating() )
{
aUIElement.m_bFloating = true;
implts_writeWindowStateData( aUIElement );
xDockWindow->setFloatingMode( true );
implts_setLayoutDirty();
implts_setToolbar( aUIElement );
return true;
}
}
catch ( lang::DisposedException& ) {}
}
return false;
}
bool ToolbarLayoutManager::lockToolbar( const ::rtl::OUString& rResourceURL )
{
UIElement aUIElement = implts_findToolbar( rResourceURL );
if ( aUIElement.m_xUIElement.is() )
{
try
{
uno::Reference< awt::XDockableWindow > xDockWindow( aUIElement.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
if ( xDockWindow.is() && !xDockWindow->isFloating() && !xDockWindow->isLocked() )
{
aUIElement.m_aDockedData.m_bLocked = true;
implts_writeWindowStateData( aUIElement );
xDockWindow->lock();
implts_setLayoutDirty();
implts_setToolbar( aUIElement );
return true;
}
}
catch ( lang::DisposedException& ) {}
}
return false;
}
bool ToolbarLayoutManager::unlockToolbar( const ::rtl::OUString& rResourceURL )
{
UIElement aUIElement = implts_findToolbar( rResourceURL );
if ( aUIElement.m_xUIElement.is() )
{
try
{
uno::Reference< awt::XDockableWindow > xDockWindow( aUIElement.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
if ( xDockWindow.is() && !xDockWindow->isFloating() && xDockWindow->isLocked() )
{
aUIElement.m_aDockedData.m_bLocked = false;
implts_writeWindowStateData( aUIElement );
xDockWindow->unlock();
implts_setLayoutDirty();
implts_setToolbar( aUIElement );
return true;
}
}
catch ( lang::DisposedException& ) {}
}
return false;
}
bool ToolbarLayoutManager::isToolbarVisible( const ::rtl::OUString& rResourceURL )
{
uno::Reference< awt::XWindow2 > xWindow2( implts_getXWindow( rResourceURL ), uno::UNO_QUERY );
return ( xWindow2.is() && xWindow2->isVisible() );
}
bool ToolbarLayoutManager::isToolbarFloating( const ::rtl::OUString& rResourceURL )
{
uno::Reference< awt::XDockableWindow > xDockWindow( implts_getXWindow( rResourceURL ), uno::UNO_QUERY );
return ( xDockWindow.is() && xDockWindow->isFloating() );
}
bool ToolbarLayoutManager::isToolbarDocked( const ::rtl::OUString& rResourceURL )
{
return !isToolbarFloating( rResourceURL );
}
bool ToolbarLayoutManager::isToolbarLocked( const ::rtl::OUString& rResourceURL )
{
uno::Reference< awt::XDockableWindow > xDockWindow( implts_getXWindow( rResourceURL ), uno::UNO_QUERY );
return ( xDockWindow.is() && xDockWindow->isLocked() );
}
awt::Size ToolbarLayoutManager::getToolbarSize( const ::rtl::OUString& rResourceURL )
{
Window* pWindow = implts_getWindow( rResourceURL );
vos::OGuard aGuard( Application::GetSolarMutex() );
if ( pWindow )
{
::Size aSize = pWindow->GetSizePixel();
awt::Size aWinSize;
aWinSize.Width = aSize.Width();
aWinSize.Height = aSize.Height();
return aWinSize;
}
return awt::Size();
}
awt::Point ToolbarLayoutManager::getToolbarPos( const ::rtl::OUString& rResourceURL )
{
awt::Point aPos;
UIElement aUIElement = implts_findToolbar( rResourceURL );
uno::Reference< awt::XWindow > xWindow( implts_getXWindow( rResourceURL ));
if ( xWindow.is() )
{
if ( aUIElement.m_bFloating )
{
awt::Rectangle aRect = xWindow->getPosSize();
aPos.X = aRect.X;
aPos.Y = aRect.Y;
}
else
{
::Point aVirtualPos = aUIElement.m_aDockedData.m_aPos;
aPos.X = aVirtualPos.X();
aPos.Y = aVirtualPos.Y();
}
}
return aPos;
}
void ToolbarLayoutManager::setToolbarSize( const ::rtl::OUString& rResourceURL, const awt::Size& aSize )
{
uno::Reference< awt::XWindow2 > xWindow( implts_getXWindow( rResourceURL ), uno::UNO_QUERY );
uno::Reference< awt::XDockableWindow > xDockWindow( xWindow, uno::UNO_QUERY );
UIElement aUIElement = implts_findToolbar( rResourceURL );
if ( xWindow.is() && xDockWindow.is() && xDockWindow->isFloating() )
{
xWindow->setOutputSize( aSize );
aUIElement.m_aFloatingData.m_aSize = ::Size( aSize.Width, aSize.Height );
implts_setToolbar( aUIElement );
implts_writeWindowStateData( aUIElement );
implts_sortUIElements();
}
}
void ToolbarLayoutManager::setToolbarPos( const ::rtl::OUString& rResourceURL, const awt::Point& aPos )
{
uno::Reference< awt::XWindow > xWindow( implts_getXWindow( rResourceURL ));
uno::Reference< awt::XDockableWindow > xDockWindow( xWindow, uno::UNO_QUERY );
UIElement aUIElement = implts_findToolbar( rResourceURL );
if ( xWindow.is() && xDockWindow.is() && xDockWindow->isFloating() )
{
xWindow->setPosSize( aPos.X, aPos.Y, 0, 0, awt::PosSize::POS );
aUIElement.m_aFloatingData.m_aPos = ::Point( aPos.X, aPos.Y );
implts_setToolbar( aUIElement );
implts_writeWindowStateData( aUIElement );
implts_sortUIElements();
}
}
void ToolbarLayoutManager::setToolbarPosSize( const ::rtl::OUString& rResourceURL, const awt::Point& aPos, const awt::Size& aSize )
{
setToolbarPos( rResourceURL, aPos );
setToolbarSize( rResourceURL, aSize );
}
} // namespace framework