2bafc7384b
and cid#1545841 COPY_INSTEAD_OF_MOVE cid#1554682 COPY_INSTEAD_OF_MOVE cid#1554686 COPY_INSTEAD_OF_MOVE cid#1554715 COPY_INSTEAD_OF_MOVE cid#1554750 COPY_INSTEAD_OF_MOVE cid#1554759 COPY_INSTEAD_OF_MOVE cid#1554770 COPY_INSTEAD_OF_MOVE cid#1554779 COPY_INSTEAD_OF_MOVE cid#1554794 COPY_INSTEAD_OF_MOVE cid#1554800 COPY_INSTEAD_OF_MOVE cid#1554826 COPY_INSTEAD_OF_MOVE cid#1554836 COPY_INSTEAD_OF_MOVE cid#1554862 COPY_INSTEAD_OF_MOVE cid#1554865 COPY_INSTEAD_OF_MOVE cid#1554872 COPY_INSTEAD_OF_MOVE cid#1554883 COPY_INSTEAD_OF_MOVE cid#1554906 COPY_INSTEAD_OF_MOVE cid#1554921 COPY_INSTEAD_OF_MOVE cid#1554926 COPY_INSTEAD_OF_MOVE cid#1554946 COPY_INSTEAD_OF_MOVE cid#1554956 COPY_INSTEAD_OF_MOVE cid#1554970 COPY_INSTEAD_OF_MOVE cid#1554986 COPY_INSTEAD_OF_MOVE cid#1554991 COPY_INSTEAD_OF_MOVE cid#1555013 COPY_INSTEAD_OF_MOVE cid#1555037 COPY_INSTEAD_OF_MOVE cid#1555050 COPY_INSTEAD_OF_MOVE cid#1555057 COPY_INSTEAD_OF_MOVE cid#1555066 COPY_INSTEAD_OF_MOVE cid#1555067 COPY_INSTEAD_OF_MOVE cid#1555083 COPY_INSTEAD_OF_MOVE cid#1555097 COPY_INSTEAD_OF_MOVE cid#1555135 COPY_INSTEAD_OF_MOVE cid#1555140 COPY_INSTEAD_OF_MOVE cid#1555146 COPY_INSTEAD_OF_MOVE cid#1555148 COPY_INSTEAD_OF_MOVE cid#1555149 COPY_INSTEAD_OF_MOVE cid#1555155 COPY_INSTEAD_OF_MOVE cid#1555157 COPY_INSTEAD_OF_MOVE cid#1555168 COPY_INSTEAD_OF_MOVE cid#1555195 COPY_INSTEAD_OF_MOVE cid#1555196 COPY_INSTEAD_OF_MOVE cid#1555237 COPY_INSTEAD_OF_MOVE Change-Id: I90531c19c28dca77fe99c72efdfc0972c311da98 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/175377 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caolan.mcnamara@collabora.com>
4139 lines
161 KiB
C++
4139 lines
161 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice project.
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* This file incorporates work covered by the following license notice:
|
|
*
|
|
* 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 .
|
|
*/
|
|
|
|
#include "toolbarlayoutmanager.hxx"
|
|
#include <uiconfiguration/windowstateproperties.hxx>
|
|
#include <uielement/addonstoolbarwrapper.hxx>
|
|
#include "helpers.hxx"
|
|
#include <services/layoutmanager.hxx>
|
|
#include <strings.hrc>
|
|
#include <classes/fwkresid.hxx>
|
|
|
|
#include <com/sun/star/awt/PosSize.hpp>
|
|
#include <com/sun/star/beans/XPropertySet.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>
|
|
|
|
#include <comphelper/propertyvalue.hxx>
|
|
#include <cppuhelper/queryinterface.hxx>
|
|
#include <o3tl/string_view.hxx>
|
|
#include <unotools/cmdoptions.hxx>
|
|
#include <toolkit/helper/vclunohelper.hxx>
|
|
#include <utility>
|
|
#include <vcl/i18nhelp.hxx>
|
|
#include <vcl/dockingarea.hxx>
|
|
#include <vcl/settings.hxx>
|
|
#include <vcl/svapp.hxx>
|
|
#include <sal/log.hxx>
|
|
#include <tools/gen.hxx>
|
|
|
|
|
|
using namespace ::com::sun::star;
|
|
|
|
namespace framework
|
|
{
|
|
|
|
ToolbarLayoutManager::ToolbarLayoutManager(
|
|
uno::Reference< uno::XComponentContext > xContext,
|
|
uno::Reference< ui::XUIElementFactory > xUIElementFactory,
|
|
LayoutManager* pParentLayouter ):
|
|
m_xContext(std::move( xContext)),
|
|
m_xUIElementFactoryManager(std::move( xUIElementFactory )),
|
|
m_pParentLayouter( pParentLayouter ),
|
|
m_aDockingArea(0, 0, 0, 0),
|
|
m_aDockingAreaOffsets(0, 0, 0, 0),
|
|
m_eDockOperation( DOCKOP_ON_COLROW ),
|
|
m_ePreviewDetection( PREVIEWFRAME_UNKNOWN ),
|
|
m_bComponentAttached( false ),
|
|
m_bLayoutDirty( false ),
|
|
m_bGlobalSettings( false ),
|
|
m_bDockingInProgress( false ),
|
|
m_bLayoutInProgress( false ),
|
|
m_bToolbarCreation( false )
|
|
{
|
|
}
|
|
|
|
ToolbarLayoutManager::~ToolbarLayoutManager()
|
|
{
|
|
m_pGlobalSettings.reset();
|
|
m_pAddonOptions.reset();
|
|
}
|
|
|
|
// XInterface
|
|
|
|
void SAL_CALL ToolbarLayoutManager::acquire() noexcept
|
|
{
|
|
OWeakObject::acquire();
|
|
}
|
|
|
|
void SAL_CALL ToolbarLayoutManager::release() noexcept
|
|
{
|
|
OWeakObject::release();
|
|
}
|
|
|
|
uno::Any SAL_CALL ToolbarLayoutManager::queryInterface( const uno::Type & rType )
|
|
{
|
|
uno::Any a = ::cppu::queryInterface( rType,
|
|
static_cast< awt::XDockableWindowListener* >(this),
|
|
static_cast< ui::XUIConfigurationListener* >(this),
|
|
static_cast< awt::XWindowListener* >(this));
|
|
|
|
if ( a.hasValue() )
|
|
return a;
|
|
|
|
return OWeakObject::queryInterface( rType );
|
|
}
|
|
|
|
void SAL_CALL ToolbarLayoutManager::disposing( const lang::EventObject& aEvent )
|
|
{
|
|
if ( aEvent.Source == m_xFrame )
|
|
{
|
|
// Reset all internal references
|
|
reset();
|
|
implts_destroyDockingAreaWindows();
|
|
}
|
|
}
|
|
|
|
awt::Rectangle ToolbarLayoutManager::getDockingArea()
|
|
{
|
|
SolarMutexResettableGuard aWriteLock;
|
|
tools::Rectangle aNewDockingArea( m_aDockingArea );
|
|
aWriteLock.clear();
|
|
|
|
if ( isLayoutDirty() )
|
|
aNewDockingArea = implts_calcDockingArea();
|
|
|
|
aWriteLock.reset();
|
|
m_aDockingArea = aNewDockingArea;
|
|
aWriteLock.clear();
|
|
|
|
return putRectangleValueToAWT(aNewDockingArea);
|
|
}
|
|
|
|
void ToolbarLayoutManager::setDockingArea( const awt::Rectangle& rDockingArea )
|
|
{
|
|
SolarMutexGuard g;
|
|
m_aDockingArea = putAWTToRectangle( rDockingArea );
|
|
m_bLayoutDirty = true;
|
|
}
|
|
|
|
void ToolbarLayoutManager::implts_setDockingAreaWindowSizes( const awt::Rectangle& rBorderSpace )
|
|
{
|
|
SolarMutexClearableGuard aReadLock;
|
|
tools::Rectangle aDockOffsets = m_aDockingAreaOffsets;
|
|
uno::Reference< awt::XWindow2 > xContainerWindow( m_xContainerWindow );
|
|
uno::Reference< awt::XWindow > xTopDockAreaWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_TOP)] );
|
|
uno::Reference< awt::XWindow > xBottomDockAreaWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_BOTTOM)] );
|
|
uno::Reference< awt::XWindow > xLeftDockAreaWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_LEFT)] );
|
|
uno::Reference< awt::XWindow > xRightDockAreaWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_RIGHT)] );
|
|
aReadLock.clear();
|
|
|
|
uno::Reference< awt::XDevice > xDevice( xContainerWindow, uno::UNO_QUERY );
|
|
|
|
// Convert relative size to output size.
|
|
awt::Rectangle aRectangle = xContainerWindow->getPosSize();
|
|
awt::DeviceInfo aInfo = xDevice->getInfo();
|
|
awt::Size aContainerClientSize( aRectangle.Width - aInfo.LeftInset - aInfo.RightInset ,
|
|
aRectangle.Height - aInfo.TopInset - aInfo.BottomInset );
|
|
tools::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( true );
|
|
nLeftRightDockingAreaHeight -= rBorderSpace.Y;
|
|
}
|
|
|
|
if ( rBorderSpace.Height >= 0 )
|
|
{
|
|
// Bottom docking area window
|
|
sal_Int32 nBottomPos = std::max( sal_Int32( aContainerClientSize.Height - rBorderSpace.Height - aStatusBarHeight + 1 ), sal_Int32( 0 ));
|
|
sal_Int32 nHeight = ( nBottomPos == 0 ) ? 0 : rBorderSpace.Height;
|
|
|
|
xBottomDockAreaWindow->setPosSize( 0, nBottomPos, aContainerClientSize.Width, nHeight, awt::PosSize::POSSIZE );
|
|
xBottomDockAreaWindow->setVisible( true );
|
|
nLeftRightDockingAreaHeight -= nHeight - 1;
|
|
}
|
|
|
|
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, nLeftRightDockingAreaHeight );
|
|
|
|
xLeftDockAreaWindow->setPosSize( 0, rBorderSpace.Y, rBorderSpace.X, nHeight, awt::PosSize::POSSIZE );
|
|
xLeftDockAreaWindow->setVisible( 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, aContainerClientSize.Width - rBorderSpace.Width );
|
|
sal_Int32 nHeight = std::max<sal_Int32>( 0, nLeftRightDockingAreaHeight );
|
|
sal_Int32 nWidth = ( nLeftPos == 0 ) ? 0 : rBorderSpace.Width;
|
|
|
|
xRightDockAreaWindow->setPosSize( nLeftPos, rBorderSpace.Y, nWidth, nHeight, awt::PosSize::POSSIZE );
|
|
xRightDockAreaWindow->setVisible( true );
|
|
}
|
|
}
|
|
|
|
|
|
void ToolbarLayoutManager::doLayout(const ::Size& aContainerSize)
|
|
{
|
|
SolarMutexResettableGuard aWriteLock;
|
|
bool bLayoutInProgress( m_bLayoutInProgress );
|
|
m_bLayoutInProgress = true;
|
|
awt::Rectangle aDockingArea = putRectangleValueToAWT( m_aDockingArea );
|
|
aWriteLock.clear();
|
|
|
|
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( static_cast<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.reset();
|
|
m_bLayoutDirty = false;
|
|
m_bLayoutInProgress = false;
|
|
aWriteLock.clear();
|
|
}
|
|
|
|
bool ToolbarLayoutManager::implts_isParentWindowVisible() const
|
|
{
|
|
SolarMutexGuard g;
|
|
bool bVisible( false );
|
|
if ( m_xContainerWindow.is() )
|
|
bVisible = m_xContainerWindow->isVisible();
|
|
|
|
return bVisible;
|
|
}
|
|
|
|
tools::Rectangle ToolbarLayoutManager::implts_calcDockingArea()
|
|
{
|
|
SolarMutexClearableGuard aReadLock;
|
|
UIElementVector aWindowVector( m_aUIElements );
|
|
aReadLock.clear();
|
|
|
|
tools::Rectangle aBorderSpace;
|
|
sal_Int32 nCurrRowColumn( 0 );
|
|
sal_Int32 nCurrPos( 0 );
|
|
ui::DockingArea nCurrDockingArea( ui::DockingArea_DOCKINGAREA_TOP );
|
|
std::vector< sal_Int32 > aRowColumnSizes[DOCKINGAREAS_COUNT];
|
|
|
|
// initialize rectangle with zero values!
|
|
aBorderSpace.setWidth(0);
|
|
aBorderSpace.setHeight(0);
|
|
|
|
aRowColumnSizes[static_cast<int>(nCurrDockingArea)].clear();
|
|
aRowColumnSizes[static_cast<int>(nCurrDockingArea)].push_back( 0 );
|
|
|
|
for (auto const& window : aWindowVector)
|
|
{
|
|
if ( window.m_xUIElement.is() )
|
|
{
|
|
uno::Reference< awt::XWindow > xWindow( window.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
|
|
uno::Reference< awt::XDockableWindow > xDockWindow( xWindow, uno::UNO_QUERY );
|
|
if ( xWindow.is() && xDockWindow.is() )
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
|
|
VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
|
|
if ( pWindow && !xDockWindow->isFloating() && window.m_bVisible && !window.m_bMasterHide )
|
|
{
|
|
awt::Rectangle aPosSize = xWindow->getPosSize();
|
|
if ( window.m_aDockedData.m_nDockedArea != nCurrDockingArea )
|
|
{
|
|
nCurrDockingArea = window.m_aDockedData.m_nDockedArea;
|
|
nCurrRowColumn = 0;
|
|
nCurrPos = 0;
|
|
aRowColumnSizes[static_cast<int>(nCurrDockingArea)].clear();
|
|
aRowColumnSizes[static_cast<int>(nCurrDockingArea)].push_back( 0 );
|
|
}
|
|
|
|
if ( window.m_aDockedData.m_nDockedArea == nCurrDockingArea )
|
|
{
|
|
if ( isHorizontalDockingArea( window.m_aDockedData.m_nDockedArea ))
|
|
{
|
|
if ( window.m_aDockedData.m_aPos.Y > nCurrPos )
|
|
{
|
|
++nCurrRowColumn;
|
|
nCurrPos = window.m_aDockedData.m_aPos.Y;
|
|
aRowColumnSizes[static_cast<int>(nCurrDockingArea)].push_back( 0 );
|
|
}
|
|
|
|
if ( aPosSize.Height > aRowColumnSizes[static_cast<int>(nCurrDockingArea)][nCurrRowColumn] )
|
|
aRowColumnSizes[static_cast<int>(nCurrDockingArea)][nCurrRowColumn] = aPosSize.Height;
|
|
}
|
|
else
|
|
{
|
|
if ( window.m_aDockedData.m_aPos.X > nCurrPos )
|
|
{
|
|
++nCurrRowColumn;
|
|
nCurrPos = window.m_aDockedData.m_aPos.X;
|
|
aRowColumnSizes[static_cast<int>(nCurrDockingArea)].push_back( 0 );
|
|
}
|
|
|
|
if ( aPosSize.Width > aRowColumnSizes[static_cast<int>(nCurrDockingArea)][nCurrRowColumn] )
|
|
aRowColumnSizes[static_cast<int>(nCurrDockingArea)][nCurrRowColumn] = aPosSize.Width;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Sum up max heights from every row/column
|
|
if ( !aWindowVector.empty() )
|
|
{
|
|
for ( sal_Int32 i = 0; i <= sal_Int32(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 == sal_Int32(ui::DockingArea_DOCKINGAREA_TOP) )
|
|
aBorderSpace.SetTop( nSize );
|
|
else if ( i == sal_Int32(ui::DockingArea_DOCKINGAREA_BOTTOM) )
|
|
aBorderSpace.SetBottom( nSize );
|
|
else if ( i == sal_Int32(ui::DockingArea_DOCKINGAREA_LEFT) )
|
|
aBorderSpace.SetLeft( nSize );
|
|
else
|
|
aBorderSpace.SetRight( nSize );
|
|
}
|
|
}
|
|
|
|
return aBorderSpace;
|
|
}
|
|
|
|
void ToolbarLayoutManager::reset()
|
|
{
|
|
{
|
|
SolarMutexGuard aWriteLock;
|
|
m_xModuleCfgMgr.clear();
|
|
m_xDocCfgMgr.clear();
|
|
m_ePreviewDetection = PREVIEWFRAME_UNKNOWN;
|
|
m_bComponentAttached = false;
|
|
}
|
|
|
|
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();
|
|
|
|
SolarMutexGuard g;
|
|
m_xFrame = xFrame;
|
|
m_xModuleCfgMgr = xModuleCfgMgr;
|
|
m_xDocCfgMgr = xDocCfgMgr;
|
|
m_xPersistentWindowState = xPersistentWindowState;
|
|
m_bComponentAttached = true;
|
|
}
|
|
|
|
bool ToolbarLayoutManager::isPreviewFrame()
|
|
{
|
|
SolarMutexGuard g;
|
|
if (m_ePreviewDetection == PREVIEWFRAME_UNKNOWN)
|
|
{
|
|
uno::Reference< frame::XFrame > xFrame( m_xFrame );
|
|
|
|
uno::Reference< frame::XModel > xModel( impl_getModelFromFrame( xFrame ));
|
|
|
|
m_ePreviewDetection = (implts_isPreviewModel( xModel ) ? PREVIEWFRAME_YES : PREVIEWFRAME_NO);
|
|
}
|
|
return m_ePreviewDetection == PREVIEWFRAME_YES;
|
|
}
|
|
|
|
void ToolbarLayoutManager::createStaticToolbars()
|
|
{
|
|
resetDockingArea();
|
|
implts_createCustomToolBars();
|
|
implts_createAddonsToolBars();
|
|
implts_createNonContextSensitiveToolBars();
|
|
implts_sortUIElements();
|
|
}
|
|
|
|
bool ToolbarLayoutManager::requestToolbar( const OUString& rResourceURL )
|
|
{
|
|
if (isPreviewFrame())
|
|
return false; // no toolbars for preview frame!
|
|
|
|
bool bNotify( false );
|
|
bool bMustCallCreate( false );
|
|
uno::Reference< ui::XUIElement > xUIElement;
|
|
|
|
UIElement aRequestedToolbar = impl_findToolbar( rResourceURL );
|
|
if ( aRequestedToolbar.m_aName != rResourceURL )
|
|
{
|
|
bMustCallCreate = true;
|
|
aRequestedToolbar.m_aName = rResourceURL;
|
|
aRequestedToolbar.m_aType = UIRESOURCETYPE_TOOLBAR;
|
|
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 );
|
|
|
|
if ( bCreateOrShowToolbar )
|
|
bNotify = bMustCallCreate ? createToolbar( rResourceURL ) : showToolbar( rResourceURL );
|
|
|
|
return bNotify;
|
|
}
|
|
|
|
bool ToolbarLayoutManager::createToolbar( const OUString& rResourceURL )
|
|
{
|
|
bool bNotify( false );
|
|
|
|
uno::Reference<frame::XFrame> xFrame;
|
|
uno::Reference<awt::XWindow2> xContainerWindow;
|
|
{
|
|
SolarMutexGuard aReadLock;
|
|
xFrame.set(m_xFrame);
|
|
xContainerWindow.set(m_xContainerWindow);
|
|
}
|
|
|
|
if ( !xFrame.is() || !xContainerWindow.is() )
|
|
return false;
|
|
|
|
UIElement aToolbarElement = implts_findToolbar( rResourceURL );
|
|
if ( !aToolbarElement.m_xUIElement.is() )
|
|
{
|
|
uno::Reference< ui::XUIElement > xUIElement;
|
|
|
|
uno::Sequence< beans::PropertyValue > aPropSeq{
|
|
comphelper::makePropertyValue(u"Frame"_ustr, xFrame),
|
|
comphelper::makePropertyValue(u"Persistent"_ustr, true)
|
|
};
|
|
uno::Reference<ui::XUIElementFactory> xUIElementFactory;
|
|
{
|
|
SolarMutexGuard aReadLock;
|
|
xUIElementFactory.set(m_xUIElementFactoryManager);
|
|
}
|
|
|
|
implts_setToolbarCreation();
|
|
try
|
|
{
|
|
if ( xUIElementFactory.is() )
|
|
xUIElement = xUIElementFactory->createUIElement( rResourceURL, aPropSeq );
|
|
}
|
|
catch (const container::NoSuchElementException&)
|
|
{
|
|
}
|
|
catch (const lang::IllegalArgumentException&)
|
|
{
|
|
}
|
|
implts_setToolbarCreation( false );
|
|
|
|
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() && xWindow.is() )
|
|
{
|
|
try
|
|
{
|
|
xDockWindow->addDockableWindowListener( uno::Reference< awt::XDockableWindowListener >(this) );
|
|
xWindow->addWindowListener( uno::Reference< awt::XWindowListener >(this) );
|
|
xDockWindow->enableDocking( true );
|
|
}
|
|
catch (const uno::Exception&)
|
|
{
|
|
}
|
|
}
|
|
|
|
bool bVisible = false;
|
|
bool bFloating = false;
|
|
|
|
/* SAFE AREA ----------------------------------------------------------------------------------------------- */
|
|
{
|
|
SolarMutexClearableGuard aWriteLock;
|
|
|
|
UIElement& rElement = impl_findToolbar(rResourceURL);
|
|
if (rElement.m_xUIElement.is())
|
|
{
|
|
// somebody else must have created it while we released
|
|
// the SolarMutex - just dispose our new instance and
|
|
// do nothing. (We have to dispose either the new or the
|
|
// existing m_xUIElement.)
|
|
aWriteLock.clear();
|
|
uno::Reference<lang::XComponent> const xC(xUIElement, uno::UNO_QUERY);
|
|
xC->dispose();
|
|
return false;
|
|
}
|
|
if (!rElement.m_aName.isEmpty())
|
|
{
|
|
// Reuse a local entry so we are able to use the latest
|
|
// UI changes for this document.
|
|
implts_setElementData(rElement, xDockWindow);
|
|
rElement.m_xUIElement = std::move(xUIElement);
|
|
bVisible = rElement.m_bVisible;
|
|
bFloating = rElement.m_bFloating;
|
|
}
|
|
else
|
|
{
|
|
// Create new UI element and try to read its state data
|
|
UIElement aNewToolbar(rResourceURL, UIRESOURCETYPE_TOOLBAR, xUIElement);
|
|
implts_readWindowStateData(rResourceURL, aNewToolbar);
|
|
implts_setElementData(aNewToolbar, xDockWindow);
|
|
implts_insertToolbar(aNewToolbar);
|
|
bVisible = aNewToolbar.m_bVisible;
|
|
bFloating = rElement.m_bFloating;
|
|
}
|
|
}
|
|
/* SAFE AREA ----------------------------------------------------------------------------------------------- */
|
|
|
|
// set toolbar menu style according to customize command state
|
|
SvtCommandOptions aCmdOptions;
|
|
|
|
SolarMutexGuard aGuard;
|
|
VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
|
|
if ( pWindow && pWindow->GetType() == WindowType::TOOLBOX )
|
|
{
|
|
ToolBox* pToolbar = static_cast<ToolBox *>(pWindow.get());
|
|
ToolBoxMenuType nMenuType = pToolbar->GetMenuType();
|
|
if ( aCmdOptions.LookupDisabled( u"ConfigureDialog"_ustr ))
|
|
pToolbar->SetMenuType( nMenuType & ~ToolBoxMenuType::Customize );
|
|
else
|
|
pToolbar->SetMenuType( nMenuType | ToolBoxMenuType::Customize );
|
|
}
|
|
bNotify = true;
|
|
|
|
implts_sortUIElements();
|
|
|
|
if ( bVisible && !bFloating )
|
|
implts_setLayoutDirty();
|
|
}
|
|
}
|
|
|
|
return bNotify;
|
|
}
|
|
|
|
bool ToolbarLayoutManager::destroyToolbar( std::u16string_view rResourceURL )
|
|
{
|
|
uno::Reference< lang::XComponent > xComponent;
|
|
|
|
bool bNotify( false );
|
|
bool bMustBeSorted( false );
|
|
bool bMustLayouted( false );
|
|
bool bMustBeDestroyed( !o3tl::starts_with(rResourceURL, u"private:resource/toolbar/addon_") );
|
|
|
|
{
|
|
SolarMutexGuard aWriteLock;
|
|
for (auto & elem : m_aUIElements)
|
|
{
|
|
if (elem.m_aName == rResourceURL)
|
|
{
|
|
xComponent.set(elem.m_xUIElement, uno::UNO_QUERY);
|
|
if (bMustBeDestroyed)
|
|
elem.m_xUIElement.clear();
|
|
else
|
|
elem.m_bVisible = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
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 >(this) );
|
|
}
|
|
catch (const uno::Exception&)
|
|
{
|
|
}
|
|
|
|
try
|
|
{
|
|
if ( xDockWindow.is() )
|
|
xDockWindow->removeDockableWindowListener( uno::Reference< awt::XDockableWindowListener >(this) );
|
|
}
|
|
catch (const uno::Exception&)
|
|
{
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( xWindow.is() )
|
|
xWindow->setVisible( 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 );
|
|
|
|
{
|
|
SolarMutexGuard aWriteLock;
|
|
m_aUIElements.clear();
|
|
m_bLayoutDirty = true;
|
|
}
|
|
|
|
for (auto const& elem : aUIElementVector)
|
|
{
|
|
uno::Reference< lang::XComponent > xComponent( elem.m_xUIElement, uno::UNO_QUERY );
|
|
if ( xComponent.is() )
|
|
xComponent->dispose();
|
|
}
|
|
}
|
|
|
|
bool ToolbarLayoutManager::showToolbar( std::u16string_view rResourceURL )
|
|
{
|
|
UIElement aUIElement = implts_findToolbar( rResourceURL );
|
|
|
|
SolarMutexGuard aGuard;
|
|
vcl::Window* pWindow = getWindowFromXUIElement( aUIElement.m_xUIElement );
|
|
|
|
// Addons appear to need to be populated at start, but we don't
|
|
// want to populate them with (scaled) images until later.
|
|
AddonsToolBarWrapper *pAddOns;
|
|
pAddOns = dynamic_cast<AddonsToolBarWrapper *>( aUIElement.m_xUIElement.get());
|
|
if (pAddOns)
|
|
pAddOns->populateImages();
|
|
|
|
if ( pWindow )
|
|
{
|
|
if ( !aUIElement.m_bFloating )
|
|
implts_setLayoutDirty();
|
|
else
|
|
pWindow->Show( true, ShowFlags::NoFocusChange | ShowFlags::NoActivate );
|
|
|
|
aUIElement.m_bVisible = true;
|
|
implts_writeWindowStateData( aUIElement );
|
|
implts_setToolbar( aUIElement );
|
|
implts_sortUIElements();
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool ToolbarLayoutManager::hideToolbar( std::u16string_view rResourceURL )
|
|
{
|
|
UIElement aUIElement = implts_findToolbar( rResourceURL );
|
|
|
|
SolarMutexGuard aGuard;
|
|
vcl::Window* pWindow = getWindowFromXUIElement( aUIElement.m_xUIElement );
|
|
if ( pWindow )
|
|
{
|
|
pWindow->Show( 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;
|
|
|
|
if ( !bAutomaticToolbars )
|
|
return;
|
|
|
|
implts_getUIElementVectorCopy( aUIElementVector );
|
|
|
|
UIElement aUIElement;
|
|
SolarMutexGuard aGuard;
|
|
for (auto const& elem : aUIElementVector)
|
|
{
|
|
if ( implts_readWindowStateData( elem.m_aName, aUIElement ) &&
|
|
( elem.m_bVisible != aUIElement.m_bVisible ) && !elem.m_bMasterHide )
|
|
{
|
|
SolarMutexGuard g;
|
|
UIElement& rUIElement = impl_findToolbar( elem.m_aName );
|
|
if ( rUIElement.m_aName == elem.m_aName )
|
|
{
|
|
rUIElement.m_bVisible = aUIElement.m_bVisible;
|
|
implts_setLayoutDirty();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void ToolbarLayoutManager::setFloatingToolbarsVisibility( bool bVisible )
|
|
{
|
|
UIElementVector aUIElementVector;
|
|
implts_getUIElementVectorCopy( aUIElementVector );
|
|
|
|
SolarMutexGuard aGuard;
|
|
for (auto const& elem : aUIElementVector)
|
|
{
|
|
vcl::Window* pWindow = getWindowFromXUIElement( elem.m_xUIElement );
|
|
if ( pWindow && elem.m_bFloating )
|
|
{
|
|
if ( bVisible )
|
|
{
|
|
if ( elem.m_bVisible && !elem.m_bMasterHide )
|
|
pWindow->Show( true, ShowFlags::NoFocusChange | ShowFlags::NoActivate );
|
|
}
|
|
else
|
|
pWindow->Show( false );
|
|
}
|
|
}
|
|
}
|
|
|
|
void ToolbarLayoutManager::setVisible( bool bVisible )
|
|
{
|
|
UIElementVector aUIElementVector;
|
|
implts_getUIElementVectorCopy( aUIElementVector );
|
|
|
|
SolarMutexGuard aGuard;
|
|
for (auto & elem : aUIElementVector)
|
|
{
|
|
if (!elem.m_bFloating)
|
|
{
|
|
elem.m_bMasterHide = !bVisible;
|
|
implts_setToolbar(elem);
|
|
implts_setLayoutDirty();
|
|
}
|
|
|
|
vcl::Window* pWindow = getWindowFromXUIElement( elem.m_xUIElement );
|
|
if ( pWindow )
|
|
{
|
|
bool bSetVisible( elem.m_bVisible && bVisible );
|
|
if ( !bSetVisible )
|
|
pWindow->Hide();
|
|
else
|
|
{
|
|
if ( elem.m_bFloating )
|
|
pWindow->Show(true, ShowFlags::NoFocusChange | ShowFlags::NoActivate );
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( !bVisible )
|
|
resetDockingArea();
|
|
}
|
|
|
|
bool ToolbarLayoutManager::dockToolbar( std::u16string_view rResourceURL, ui::DockingArea eDockingArea, const awt::Point& aPos )
|
|
{
|
|
UIElement aUIElement = implts_findToolbar( rResourceURL );
|
|
|
|
if ( !aUIElement.m_xUIElement.is() )
|
|
return false;
|
|
|
|
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 = eDockingArea;
|
|
|
|
if ( !isDefaultPos( aPos ))
|
|
aUIElement.m_aDockedData.m_aPos = aPos;
|
|
|
|
if ( !xDockWindow->isFloating() )
|
|
{
|
|
vcl::Window* pWindow( nullptr );
|
|
ToolBox* pToolBox( nullptr );
|
|
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
pWindow = VCLUnoHelper::GetWindow( xWindow );
|
|
if ( pWindow && pWindow->GetType() == WindowType::TOOLBOX )
|
|
{
|
|
pToolBox = static_cast<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;
|
|
|
|
SolarMutexGuard aGuard;
|
|
{
|
|
if (pToolBox)
|
|
aSize = pToolBox->CalcWindowSizePixel( 1, ImplConvertAlignment( aUIElement.m_aDockedData.m_nDockedArea ) );
|
|
else if (pWindow)
|
|
aSize = pWindow->GetSizePixel();
|
|
}
|
|
|
|
::Point aPixelPos;
|
|
awt::Point aDockPos;
|
|
implts_findNextDockingPos(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( false );
|
|
}
|
|
else
|
|
{
|
|
implts_writeWindowStateData( aUIElement );
|
|
implts_sortUIElements();
|
|
|
|
if ( aUIElement.m_bVisible )
|
|
implts_setLayoutDirty();
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
catch (const lang::DisposedException&)
|
|
{
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool ToolbarLayoutManager::dockAllToolbars()
|
|
{
|
|
std::vector< OUString > aToolBarNameVector;
|
|
|
|
{
|
|
SolarMutexGuard aReadLock;
|
|
for (auto const& elem : m_aUIElements)
|
|
{
|
|
if (elem.m_aType == "toolbar" && elem.m_xUIElement.is() && elem.m_bFloating
|
|
&& elem.m_bVisible)
|
|
aToolBarNameVector.push_back(elem.m_aName);
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
void ToolbarLayoutManager::childWindowEvent( VclSimpleEvent const * 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!
|
|
auto pWindowEvent = dynamic_cast< const VclWindowEvent* >(pEvent);
|
|
if (!pWindowEvent)
|
|
return;
|
|
|
|
if ( pEvent->GetId() == VclEventId::ToolboxSelect )
|
|
{
|
|
OUString aToolbarName;
|
|
OUString aCommand;
|
|
ToolBox* pToolBox = getToolboxPtr( pWindowEvent->GetWindow() );
|
|
|
|
if ( pToolBox )
|
|
{
|
|
aToolbarName = retrieveToolbarNameFromHelpURL( pToolBox );
|
|
ToolBoxItemId nId = pToolBox->GetCurItemId();
|
|
if ( nId > ToolBoxItemId(0) )
|
|
aCommand = pToolBox->GetItemCommand( nId );
|
|
}
|
|
|
|
if ( !aToolbarName.isEmpty() && !aCommand.isEmpty() )
|
|
{
|
|
SolarMutexClearableGuard aReadLock;
|
|
::std::vector< uno::Reference< ui::XUIFunctionListener > > aListenerArray;
|
|
|
|
for (auto const& elem : m_aUIElements)
|
|
{
|
|
if ( elem.m_xUIElement.is() )
|
|
{
|
|
uno::Reference< ui::XUIFunctionListener > xListener( elem.m_xUIElement, uno::UNO_QUERY );
|
|
if ( xListener.is() )
|
|
aListenerArray.push_back( xListener );
|
|
}
|
|
}
|
|
aReadLock.clear();
|
|
|
|
const sal_uInt32 nCount = aListenerArray.size();
|
|
for ( sal_uInt32 i = 0; i < nCount; ++i )
|
|
{
|
|
try
|
|
{
|
|
aListenerArray[i]->functionExecute( aToolbarName, aCommand );
|
|
}
|
|
catch (const uno::RuntimeException&)
|
|
{
|
|
throw;
|
|
}
|
|
catch (const uno::Exception&)
|
|
{
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if ( pEvent->GetId() == VclEventId::ToolboxFormatChanged )
|
|
{
|
|
if ( !implts_isToolbarCreationActive() )
|
|
{
|
|
ToolBox* pToolBox = getToolboxPtr( pWindowEvent->GetWindow() );
|
|
if ( pToolBox )
|
|
{
|
|
OUString aToolbarName = retrieveToolbarNameFromHelpURL( pToolBox );
|
|
if ( !aToolbarName.isEmpty() )
|
|
{
|
|
OUString aToolbarUrl = "private:resource/toolbar/" + aToolbarName;
|
|
|
|
UIElement aToolbar = implts_findToolbar( aToolbarUrl );
|
|
if ( aToolbar.m_xUIElement.is() && !aToolbar.m_bFloating )
|
|
{
|
|
implts_setLayoutDirty();
|
|
m_pParentLayouter->requestLayout();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void ToolbarLayoutManager::resetDockingArea()
|
|
{
|
|
SolarMutexClearableGuard aReadLock;
|
|
uno::Reference< awt::XWindow > xTopDockingWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_TOP)] );
|
|
uno::Reference< awt::XWindow > xLeftDockingWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_LEFT)] );
|
|
uno::Reference< awt::XWindow > xRightDockingWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_RIGHT)] );
|
|
uno::Reference< awt::XWindow > xBottomDockingWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_BOTTOM)] );
|
|
aReadLock.clear();
|
|
|
|
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::XVclWindowPeer >& xParentWindow )
|
|
{
|
|
static constexpr OUString DOCKINGAREASTRING = u"dockingarea"_ustr;
|
|
|
|
uno::Reference< awt::XWindow > xTopDockWindow( createToolkitWindow( m_xContext, xParentWindow, DOCKINGAREASTRING ), uno::UNO_QUERY );
|
|
uno::Reference< awt::XWindow > xLeftDockWindow( createToolkitWindow( m_xContext, xParentWindow, DOCKINGAREASTRING ), uno::UNO_QUERY );
|
|
uno::Reference< awt::XWindow > xRightDockWindow( createToolkitWindow( m_xContext, xParentWindow, DOCKINGAREASTRING ), uno::UNO_QUERY );
|
|
uno::Reference< awt::XWindow > xBottomDockWindow( createToolkitWindow( m_xContext, xParentWindow, DOCKINGAREASTRING ), uno::UNO_QUERY );
|
|
|
|
{
|
|
SolarMutexGuard aWriteLock;
|
|
m_xContainerWindow.set(xParentWindow, uno::UNO_QUERY);
|
|
m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_TOP)] = xTopDockWindow;
|
|
m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_LEFT)] = xLeftDockWindow;
|
|
m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_RIGHT)] = xRightDockWindow;
|
|
m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_BOTTOM)] = xBottomDockWindow;
|
|
}
|
|
|
|
if ( xParentWindow.is() )
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
VclPtr< ::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 ::tools::Rectangle& rOffsets )
|
|
{
|
|
SolarMutexGuard g;
|
|
m_aDockingAreaOffsets = rOffsets;
|
|
m_bLayoutDirty = true;
|
|
}
|
|
|
|
// static
|
|
OUString ToolbarLayoutManager::implts_generateGenericAddonToolbarTitle( sal_Int32 nNumber )
|
|
{
|
|
OUString aAddonGenericTitle(FwkResId(STR_TOOLBAR_TITLE_ADDON));
|
|
const vcl::I18nHelper& rI18nHelper = Application::GetSettings().GetUILocaleI18nHelper();
|
|
|
|
OUString aNumStr = rI18nHelper.GetNum( nNumber, 0, false, false );
|
|
aAddonGenericTitle = aAddonGenericTitle.replaceFirst( "%num%", aNumStr );
|
|
|
|
return aAddonGenericTitle;
|
|
}
|
|
|
|
void ToolbarLayoutManager::implts_createAddonsToolBars()
|
|
{
|
|
SolarMutexClearableGuard aWriteLock;
|
|
if ( !m_pAddonOptions )
|
|
m_pAddonOptions.reset( new AddonsOptions );
|
|
|
|
uno::Reference< ui::XUIElementFactory > xUIElementFactory( m_xUIElementFactoryManager );
|
|
uno::Reference< frame::XFrame > xFrame( m_xFrame );
|
|
aWriteLock.clear();
|
|
|
|
if (isPreviewFrame())
|
|
return; // no addon toolbars for preview frame!
|
|
|
|
uno::Sequence< uno::Sequence< beans::PropertyValue > > aAddonToolBarData;
|
|
uno::Reference< ui::XUIElement > xUIElement;
|
|
|
|
sal_uInt32 nCount = m_pAddonOptions->GetAddonsToolBarCount();
|
|
|
|
uno::Sequence< beans::PropertyValue > aPropSeq( 2 );
|
|
auto pPropSeq = aPropSeq.getArray();
|
|
pPropSeq[0].Name = "Frame";
|
|
pPropSeq[0].Value <<= xFrame;
|
|
pPropSeq[1].Name = "ConfigurationData";
|
|
for ( sal_uInt32 i = 0; i < nCount; i++ )
|
|
{
|
|
OUString aAddonToolBarName( "private:resource/toolbar/addon_" +
|
|
m_pAddonOptions->GetAddonsToolbarResourceName(i) );
|
|
aAddonToolBarData = m_pAddonOptions->GetAddonsToolBarPart( i );
|
|
pPropSeq[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 >(this) );
|
|
xDockWindow->enableDocking( true );
|
|
uno::Reference< awt::XWindow > xWindow( xDockWindow, uno::UNO_QUERY );
|
|
if ( xWindow.is() )
|
|
xWindow->addWindowListener( uno::Reference< awt::XWindowListener >(this) );
|
|
}
|
|
catch (const uno::Exception&)
|
|
{
|
|
}
|
|
}
|
|
|
|
OUString aGenericAddonTitle = implts_generateGenericAddonToolbarTitle( i+1 );
|
|
|
|
if ( !aElement.m_aName.isEmpty() )
|
|
{
|
|
// 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.isEmpty() )
|
|
{
|
|
aElement.m_aUIName = aGenericAddonTitle;
|
|
implts_writeWindowStateData( aElement );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Create new UI element and try to read its state data
|
|
UIElement aNewToolbar( aAddonToolBarName, u"toolbar"_ustr, xUIElement );
|
|
aNewToolbar.m_bFloating = true;
|
|
implts_readWindowStateData( aAddonToolBarName, aNewToolbar );
|
|
implts_setElementData( aNewToolbar, xDockWindow );
|
|
if ( aNewToolbar.m_aUIName.isEmpty() )
|
|
{
|
|
aNewToolbar.m_aUIName = aGenericAddonTitle;
|
|
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
|
|
SolarMutexGuard aGuard;
|
|
VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
|
|
if ( pWindow->GetText().isEmpty() )
|
|
pWindow->SetText( aGenericAddonTitle );
|
|
if ( pWindow->GetType() == WindowType::TOOLBOX )
|
|
{
|
|
ToolBox* pToolbar = static_cast<ToolBox *>(pWindow.get());
|
|
pToolbar->SetMenuType();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (const container::NoSuchElementException&)
|
|
{
|
|
}
|
|
catch (const lang::IllegalArgumentException&)
|
|
{
|
|
}
|
|
}
|
|
}
|
|
|
|
void ToolbarLayoutManager::implts_createCustomToolBars()
|
|
{
|
|
SolarMutexClearableGuard aReadLock;
|
|
if ( !m_bComponentAttached )
|
|
return;
|
|
|
|
uno::Reference< frame::XFrame > xFrame( m_xFrame );
|
|
uno::Reference< ui::XUIConfigurationManager > xModuleCfgMgr = m_xModuleCfgMgr;
|
|
uno::Reference< ui::XUIConfigurationManager > xDocCfgMgr = m_xDocCfgMgr;
|
|
aReadLock.clear();
|
|
|
|
if ( !xFrame.is() )
|
|
return;
|
|
|
|
if (isPreviewFrame())
|
|
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()
|
|
{
|
|
SolarMutexClearableGuard aReadLock;
|
|
|
|
if ( !m_xPersistentWindowState.is() || !m_xFrame.is() || !m_bComponentAttached )
|
|
return;
|
|
|
|
uno::Reference< container::XNameAccess > xPersistentWindowState( m_xPersistentWindowState );
|
|
aReadLock.clear();
|
|
|
|
if (isPreviewFrame())
|
|
return;
|
|
|
|
std::vector< OUString > aMakeVisibleToolbars;
|
|
|
|
try
|
|
{
|
|
const uno::Sequence< OUString > aToolbarNames = xPersistentWindowState->getElementNames();
|
|
|
|
if ( aToolbarNames.hasElements() )
|
|
{
|
|
OUString aElementType;
|
|
OUString aElementName;
|
|
|
|
aMakeVisibleToolbars.reserve(aToolbarNames.getLength());
|
|
|
|
SolarMutexGuard g;
|
|
|
|
for ( OUString const & aName : aToolbarNames )
|
|
{
|
|
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.equalsIgnoreAsciiCase("toolbar") &&
|
|
aElementName.indexOf( "custom_" ) == -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 );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (const uno::RuntimeException&)
|
|
{
|
|
throw;
|
|
}
|
|
catch (const uno::Exception&)
|
|
{
|
|
}
|
|
|
|
for (auto const& rURL : aMakeVisibleToolbars)
|
|
{
|
|
requestToolbar(rURL);
|
|
}
|
|
}
|
|
|
|
void ToolbarLayoutManager::implts_createCustomToolBars( const uno::Sequence< uno::Sequence< beans::PropertyValue > >& aTbxSeqSeq )
|
|
{
|
|
for ( const uno::Sequence< beans::PropertyValue >& rTbxSeq : aTbxSeqSeq )
|
|
{
|
|
OUString aTbxResName;
|
|
OUString aTbxTitle;
|
|
for ( const beans::PropertyValue& rProp : rTbxSeq )
|
|
{
|
|
if ( rProp.Name == "ResourceURL" )
|
|
rProp.Value >>= aTbxResName;
|
|
else if ( rProp.Name == "UIName" )
|
|
rProp.Value >>= aTbxTitle;
|
|
}
|
|
|
|
// Only create custom toolbars. Their name have to start with "custom_"!
|
|
if ( !aTbxResName.isEmpty() && ( aTbxResName.indexOf( "custom_" ) != -1 ) )
|
|
implts_createCustomToolBar( aTbxResName, aTbxTitle );
|
|
}
|
|
}
|
|
|
|
void ToolbarLayoutManager::implts_createCustomToolBar( const OUString& aTbxResName, const OUString& aTitle )
|
|
{
|
|
if ( aTbxResName.isEmpty() )
|
|
return;
|
|
|
|
if ( !createToolbar( aTbxResName ) )
|
|
SAL_WARN("fwk.uielement", "ToolbarLayoutManager cannot create custom toolbar");
|
|
|
|
uno::Reference< ui::XUIElement > xUIElement = getToolbar( aTbxResName );
|
|
|
|
if ( !aTitle.isEmpty() && xUIElement.is() )
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
|
|
vcl::Window* pWindow = getWindowFromXUIElement( xUIElement );
|
|
if ( pWindow )
|
|
pWindow->SetText( aTitle );
|
|
}
|
|
}
|
|
|
|
void ToolbarLayoutManager::implts_reparentToolbars()
|
|
{
|
|
SolarMutexClearableGuard aWriteLock;
|
|
UIElementVector aUIElementVector = m_aUIElements;
|
|
VclPtr<vcl::Window> pContainerWindow = VCLUnoHelper::GetWindow( m_xContainerWindow );
|
|
VclPtr<vcl::Window> pTopDockWindow = VCLUnoHelper::GetWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_TOP)] );
|
|
VclPtr<vcl::Window> pBottomDockWindow = VCLUnoHelper::GetWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_BOTTOM)] );
|
|
VclPtr<vcl::Window> pLeftDockWindow = VCLUnoHelper::GetWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_LEFT)] );
|
|
VclPtr<vcl::Window> pRightDockWindow = VCLUnoHelper::GetWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_RIGHT)] );
|
|
aWriteLock.clear();
|
|
|
|
SolarMutexGuard aGuard;
|
|
if ( !pContainerWindow )
|
|
return;
|
|
|
|
for (auto const& elem : aUIElementVector)
|
|
{
|
|
uno::Reference< ui::XUIElement > xUIElement( elem.m_xUIElement );
|
|
if ( xUIElement.is() )
|
|
{
|
|
uno::Reference< awt::XWindow > xWindow;
|
|
try
|
|
{
|
|
// We have to retrieve the window reference with try/catch as it is
|
|
// possible that all elements have been disposed!
|
|
xWindow.set( xUIElement->getRealInterface(), uno::UNO_QUERY );
|
|
}
|
|
catch (const uno::RuntimeException&)
|
|
{
|
|
throw;
|
|
}
|
|
catch (const uno::Exception&)
|
|
{
|
|
}
|
|
|
|
VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
|
|
if ( pWindow )
|
|
{
|
|
// Reparent our child windows according to their current state.
|
|
if ( elem.m_bFloating )
|
|
pWindow->SetParent( pContainerWindow );
|
|
else
|
|
{
|
|
if ( elem.m_aDockedData.m_nDockedArea == ui::DockingArea_DOCKINGAREA_TOP )
|
|
pWindow->SetParent( pTopDockWindow );
|
|
else if ( elem.m_aDockedData.m_nDockedArea == ui::DockingArea_DOCKINGAREA_BOTTOM )
|
|
pWindow->SetParent( pBottomDockWindow );
|
|
else if ( elem.m_aDockedData.m_nDockedArea == ui::DockingArea_DOCKINGAREA_LEFT )
|
|
pWindow->SetParent( pLeftDockWindow );
|
|
else
|
|
pWindow->SetParent( pRightDockWindow );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void ToolbarLayoutManager::implts_setToolbarCreation( bool bStart )
|
|
{
|
|
SolarMutexGuard g;
|
|
m_bToolbarCreation = bStart;
|
|
}
|
|
|
|
bool ToolbarLayoutManager::implts_isToolbarCreationActive()
|
|
{
|
|
SolarMutexGuard g;
|
|
return m_bToolbarCreation;
|
|
}
|
|
|
|
void ToolbarLayoutManager::implts_setElementData( UIElement& rElement, const uno::Reference< awt::XDockableWindow >& rDockWindow )
|
|
{
|
|
SolarMutexClearableGuard aReadLock;
|
|
bool bShowElement( rElement.m_bVisible && !rElement.m_bMasterHide && implts_isParentWindowVisible() );
|
|
aReadLock.clear();
|
|
|
|
uno::Reference< awt::XWindow2 > xWindow( rDockWindow, uno::UNO_QUERY );
|
|
|
|
vcl::Window* pWindow( nullptr );
|
|
ToolBox* pToolBox( nullptr );
|
|
|
|
if ( !(rDockWindow.is() && xWindow.is()) )
|
|
return;
|
|
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
pWindow = VCLUnoHelper::GetWindow( xWindow );
|
|
if ( pWindow )
|
|
{
|
|
OUString aText = pWindow->GetText();
|
|
if ( aText.isEmpty() )
|
|
pWindow->SetText( rElement.m_aUIName );
|
|
if ( rElement.m_bNoClose )
|
|
pWindow->SetStyle( pWindow->GetStyle() & ~WB_CLOSEABLE );
|
|
if ( pWindow->GetType() == WindowType::TOOLBOX )
|
|
pToolBox = static_cast<ToolBox *>(pWindow);
|
|
}
|
|
if ( pToolBox )
|
|
{
|
|
pToolBox->SetButtonType( rElement.m_nStyle );
|
|
if ( rElement.m_bNoClose )
|
|
pToolBox->SetFloatStyle( pToolBox->GetFloatStyle() & ~WB_CLOSEABLE );
|
|
}
|
|
}
|
|
|
|
if ( rElement.m_bFloating )
|
|
{
|
|
if ( pWindow )
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
OUString aText = pWindow->GetText();
|
|
if ( aText.isEmpty() )
|
|
pWindow->SetText( rElement.m_aUIName );
|
|
}
|
|
|
|
awt::Point aPos(rElement.m_aFloatingData.m_aPos);
|
|
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 );
|
|
rDockWindow->setFloatingMode( true );
|
|
if ( bUndefPos )
|
|
{
|
|
aPos = implts_findNextCascadeFloatingPos();
|
|
rElement.m_aFloatingData.m_aPos = aPos; // set new cascaded position
|
|
bWriteData = true;
|
|
}
|
|
|
|
if( bSetSize )
|
|
xWindow->setOutputSize(rElement.m_aFloatingData.m_aSize);
|
|
else
|
|
{
|
|
if( pToolBox )
|
|
{
|
|
// set an optimal initial floating size
|
|
SolarMutexGuard aGuard;
|
|
::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 )
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
pWindow->Show( true, ShowFlags::NoFocusChange | ShowFlags::NoActivate );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bool bSetSize( false );
|
|
::Point aPixelPos;
|
|
::Size aSize;
|
|
|
|
if ( pToolBox )
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
pToolBox->SetAlign( ImplConvertAlignment(rElement.m_aDockedData.m_nDockedArea ) );
|
|
pToolBox->SetLineCount( 1 );
|
|
rDockWindow->setFloatingMode( false );
|
|
if ( rElement.m_aDockedData.m_bLocked )
|
|
rDockWindow->lock();
|
|
aSize = pToolBox->CalcWindowSizePixel();
|
|
bSetSize = true;
|
|
|
|
if ( isDefaultPos( rElement.m_aDockedData.m_aPos ))
|
|
{
|
|
awt::Point aDockPos;
|
|
implts_findNextDockingPos( 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(VCLUnoHelper::ConvertToAWTSize(aSize));
|
|
|
|
if ( pWindow )
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
if ( !bShowElement )
|
|
pWindow->Hide();
|
|
}
|
|
}
|
|
}
|
|
|
|
void ToolbarLayoutManager::implts_destroyDockingAreaWindows()
|
|
{
|
|
SolarMutexClearableGuard aWriteLock;
|
|
uno::Reference< awt::XWindow > xTopDockingWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_TOP)] );
|
|
uno::Reference< awt::XWindow > xLeftDockingWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_LEFT)] );
|
|
uno::Reference< awt::XWindow > xRightDockingWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_RIGHT)] );
|
|
uno::Reference< awt::XWindow > xBottomDockingWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_BOTTOM)] );
|
|
m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_TOP)].clear();
|
|
m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_LEFT)].clear();
|
|
m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_RIGHT)].clear();
|
|
m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_BOTTOM)].clear();
|
|
aWriteLock.clear();
|
|
|
|
// destroy windows
|
|
xTopDockingWindow->dispose();
|
|
xLeftDockingWindow->dispose();
|
|
xRightDockingWindow->dispose();
|
|
xBottomDockingWindow->dispose();
|
|
}
|
|
|
|
// persistence methods
|
|
|
|
bool ToolbarLayoutManager::implts_readWindowStateData( const OUString& aName, UIElement& rElementData )
|
|
{
|
|
return LayoutManager::readWindowStateData( aName, rElementData, m_xPersistentWindowState,
|
|
m_pGlobalSettings, m_bGlobalSettings, m_xContext );
|
|
}
|
|
|
|
void ToolbarLayoutManager::implts_writeWindowStateData( const UIElement& rElementData )
|
|
{
|
|
SolarMutexClearableGuard aWriteLock;
|
|
uno::Reference< container::XNameAccess > xPersistentWindowState( m_xPersistentWindowState );
|
|
aWriteLock.clear();
|
|
|
|
bool bPersistent( 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(u"Persistent"_ustr) >>= bPersistent;
|
|
}
|
|
catch (const beans::UnknownPropertyException&)
|
|
{
|
|
bPersistent = true; // Non-configurable elements should at least store their dimension/position
|
|
}
|
|
catch (const lang::WrappedTargetException&)
|
|
{
|
|
}
|
|
}
|
|
|
|
if ( !(bPersistent && xPersistentWindowState.is()) )
|
|
return;
|
|
|
|
try
|
|
{
|
|
uno::Sequence<beans::PropertyValue> aWindowState{
|
|
comphelper::makePropertyValue(WINDOWSTATE_PROPERTY_DOCKED, !rElementData.m_bFloating),
|
|
comphelper::makePropertyValue(WINDOWSTATE_PROPERTY_VISIBLE, rElementData.m_bVisible),
|
|
comphelper::makePropertyValue(WINDOWSTATE_PROPERTY_DOCKINGAREA,
|
|
rElementData.m_aDockedData.m_nDockedArea),
|
|
comphelper::makePropertyValue(WINDOWSTATE_PROPERTY_DOCKPOS,
|
|
rElementData.m_aDockedData.m_aPos),
|
|
comphelper::makePropertyValue(WINDOWSTATE_PROPERTY_POS,
|
|
rElementData.m_aFloatingData.m_aPos),
|
|
comphelper::makePropertyValue(WINDOWSTATE_PROPERTY_SIZE,
|
|
rElementData.m_aFloatingData.m_aSize),
|
|
comphelper::makePropertyValue(WINDOWSTATE_PROPERTY_UINAME, rElementData.m_aUIName),
|
|
comphelper::makePropertyValue(WINDOWSTATE_PROPERTY_LOCKED,
|
|
rElementData.m_aDockedData.m_bLocked),
|
|
comphelper::makePropertyValue(WINDOWSTATE_PROPERTY_STYLE,
|
|
static_cast<sal_uInt16>(rElementData.m_nStyle))
|
|
};
|
|
|
|
OUString aName = rElementData.m_aName;
|
|
if ( xPersistentWindowState->hasByName( aName ))
|
|
{
|
|
uno::Reference< container::XNameReplace > xReplace( xPersistentWindowState, uno::UNO_QUERY );
|
|
xReplace->replaceByName( aName, uno::Any( aWindowState ));
|
|
}
|
|
else
|
|
{
|
|
uno::Reference< container::XNameContainer > xInsert( xPersistentWindowState, uno::UNO_QUERY );
|
|
xInsert->insertByName( aName, uno::Any( aWindowState ));
|
|
}
|
|
}
|
|
catch (const uno::Exception&)
|
|
{
|
|
}
|
|
}
|
|
|
|
/******************************************************************************
|
|
LOOKUP PART FOR TOOLBARS
|
|
******************************************************************************/
|
|
|
|
UIElement& ToolbarLayoutManager::impl_findToolbar( std::u16string_view aName )
|
|
{
|
|
static UIElement aEmptyElement;
|
|
|
|
SolarMutexGuard g;
|
|
for (auto & elem : m_aUIElements)
|
|
{
|
|
if ( elem.m_aName == aName )
|
|
return elem;
|
|
}
|
|
|
|
return aEmptyElement;
|
|
}
|
|
|
|
UIElement ToolbarLayoutManager::implts_findToolbar( std::u16string_view aName )
|
|
{
|
|
SolarMutexGuard g;
|
|
return impl_findToolbar( aName );
|
|
}
|
|
|
|
UIElement ToolbarLayoutManager::implts_findToolbar( const uno::Reference< uno::XInterface >& xToolbar )
|
|
{
|
|
UIElement aToolbar;
|
|
|
|
SolarMutexGuard g;
|
|
for (auto const& elem : m_aUIElements)
|
|
{
|
|
if ( elem.m_xUIElement.is() )
|
|
{
|
|
uno::Reference< uno::XInterface > xIfac( elem.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
|
|
if ( xIfac == xToolbar )
|
|
{
|
|
aToolbar = elem;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return aToolbar;
|
|
}
|
|
|
|
uno::Reference< awt::XWindow > ToolbarLayoutManager::implts_getXWindow( std::u16string_view aName )
|
|
{
|
|
uno::Reference< awt::XWindow > xWindow;
|
|
|
|
SolarMutexGuard g;
|
|
for (auto const& elem : m_aUIElements)
|
|
{
|
|
if ( elem.m_aName == aName && elem.m_xUIElement.is() )
|
|
{
|
|
xWindow.set( elem.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
|
|
break;
|
|
}
|
|
}
|
|
|
|
return xWindow;
|
|
}
|
|
|
|
vcl::Window* ToolbarLayoutManager::implts_getWindow( std::u16string_view aName )
|
|
{
|
|
uno::Reference< awt::XWindow > xWindow = implts_getXWindow( aName );
|
|
VclPtr<vcl::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 )
|
|
{
|
|
SolarMutexGuard g;
|
|
m_aUIElements.push_back( rUIElement );
|
|
bResult = true;
|
|
}
|
|
|
|
return bResult;
|
|
}
|
|
|
|
void ToolbarLayoutManager::implts_setToolbar( const UIElement& rUIElement )
|
|
{
|
|
SolarMutexGuard g;
|
|
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
|
|
******************************************************************************/
|
|
|
|
awt::Point ToolbarLayoutManager::implts_findNextCascadeFloatingPos()
|
|
{
|
|
const sal_Int32 nHotZoneX = 50;
|
|
const sal_Int32 nHotZoneY = 50;
|
|
const sal_Int32 nCascadeIndentX = 15;
|
|
const sal_Int32 nCascadeIndentY = 15;
|
|
|
|
SolarMutexClearableGuard aReadLock;
|
|
uno::Reference< awt::XWindow2 > xContainerWindow( m_xContainerWindow );
|
|
uno::Reference< awt::XWindow > xTopDockingWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_TOP)] );
|
|
uno::Reference< awt::XWindow > xLeftDockingWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_LEFT)] );
|
|
aReadLock.clear();
|
|
|
|
awt::Point aStartPos( nCascadeIndentX, nCascadeIndentY );
|
|
awt::Point aCurrPos( aStartPos );
|
|
|
|
if ( xContainerWindow.is() )
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
VclPtr<vcl::Window> pContainerWindow = VCLUnoHelper::GetWindow( xContainerWindow );
|
|
if ( pContainerWindow )
|
|
aStartPos = VCLUnoHelper::ConvertToAWTPoint(
|
|
pContainerWindow->OutputToScreenPixel(VCLUnoHelper::ConvertToVCLPoint(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
|
|
for (auto const& elem : m_aUIElements)
|
|
{
|
|
if ( elem.m_xUIElement.is() )
|
|
{
|
|
uno::Reference< awt::XDockableWindow > xDockWindow( elem.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
|
|
uno::Reference< awt::XWindow > xWindow( xDockWindow, uno::UNO_QUERY );
|
|
if ( xDockWindow.is() && xDockWindow->isFloating() )
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
VclPtr<vcl::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()
|
|
{
|
|
SolarMutexGuard g;
|
|
|
|
std::stable_sort( m_aUIElements.begin(), m_aUIElements.end()); // first created element should first
|
|
|
|
// We have to reset our temporary flags.
|
|
for (auto & elem : m_aUIElements)
|
|
elem.m_bUserActive = false;
|
|
}
|
|
|
|
void ToolbarLayoutManager::implts_getUIElementVectorCopy( UIElementVector& rCopy )
|
|
{
|
|
SolarMutexGuard g;
|
|
rCopy = m_aUIElements;
|
|
}
|
|
|
|
::Size ToolbarLayoutManager::implts_getTopBottomDockingAreaSizes()
|
|
{
|
|
::Size aSize;
|
|
uno::Reference< awt::XWindow > xTopDockingAreaWindow;
|
|
uno::Reference< awt::XWindow > xBottomDockingAreaWindow;
|
|
|
|
{
|
|
SolarMutexGuard aReadLock;
|
|
xTopDockingAreaWindow = m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_TOP)];
|
|
xBottomDockingAreaWindow = m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_BOTTOM)];
|
|
}
|
|
|
|
if ( xTopDockingAreaWindow.is() )
|
|
aSize.setWidth( xTopDockingAreaWindow->getPosSize().Height );
|
|
if ( xBottomDockingAreaWindow.is() )
|
|
aSize.setHeight( 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 ----------------------------------------------------------------------------------------------- */
|
|
{
|
|
SolarMutexGuard aReadLock;
|
|
aWindowVector.reserve(m_aUIElements.size());
|
|
xDockAreaWindow = m_xDockAreaWindows[static_cast<int>(eDockingArea)];
|
|
for (auto const& elem : m_aUIElements)
|
|
{
|
|
if (elem.m_aDockedData.m_nDockedArea == eDockingArea && elem.m_bVisible)
|
|
{
|
|
uno::Reference<ui::XUIElement> xUIElement(elem.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())
|
|
{
|
|
if (!elem.m_bFloating)
|
|
{
|
|
// docked windows
|
|
aWindowVector.push_back(elem);
|
|
}
|
|
else
|
|
{
|
|
// floating windows
|
|
VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow(xWindow);
|
|
DockingManager* pDockMgr = vcl::Window::GetDockingManager();
|
|
if (pDockMgr != nullptr)
|
|
{
|
|
SystemWindow* pFloatingWindow = pDockMgr->GetFloatingWindow(pWindow);
|
|
if (pFloatingWindow)
|
|
{
|
|
// update the position data of the floating window
|
|
if (pFloatingWindow->UpdatePositionData())
|
|
{
|
|
awt::Rectangle aTmpRect = xWindow->getPosSize();
|
|
UIElement uiElem = elem;
|
|
uiElem.m_aFloatingData.m_aPos
|
|
= awt::Point(aTmpRect.X, aTmpRect.Y);
|
|
implts_setToolbar(uiElem);
|
|
implts_writeWindowStateData(uiElem);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/* 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.emplace_back(
|
|
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.emplace_back(
|
|
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 ----------------------------------------------------------------------------------------------- */
|
|
{
|
|
SolarMutexGuard aReadLock;
|
|
for (auto const& elem : m_aUIElements)
|
|
{
|
|
if (elem.m_aDockedData.m_nDockedArea == eDockingArea)
|
|
{
|
|
bool bSameRowCol = bHorzDockArea ? (elem.m_aDockedData.m_aPos.Y == nRowCol)
|
|
: (elem.m_aDockedData.m_aPos.X == nRowCol);
|
|
uno::Reference<ui::XUIElement> xUIElement(elem.m_xUIElement);
|
|
|
|
if (bSameRowCol && xUIElement.is())
|
|
{
|
|
uno::Reference<awt::XWindow> xWindow(xUIElement->getRealInterface(),
|
|
uno::UNO_QUERY);
|
|
if (xWindow.is())
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow(xWindow);
|
|
uno::Reference<awt::XDockableWindow> xDockWindow(xWindow, uno::UNO_QUERY);
|
|
if (pWindow && elem.m_bVisible && xDockWindow.is() && !elem.m_bFloating)
|
|
aWindowVector.push_back(elem); // docked windows
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/* 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.emplace_back(
|
|
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.emplace_back(
|
|
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;
|
|
}
|
|
}
|
|
|
|
::tools::Rectangle ToolbarLayoutManager::implts_getWindowRectFromRowColumn(
|
|
ui::DockingArea DockingArea,
|
|
const SingleRowColumnWindowData& rRowColumnWindowData,
|
|
const ::Point& rMousePos,
|
|
std::u16string_view rExcludeElementName )
|
|
{
|
|
::tools::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
|
|
{
|
|
SolarMutexClearableGuard aReadLock;
|
|
VclPtr<vcl::Window> pContainerWindow( VCLUnoHelper::GetWindow( m_xContainerWindow ));
|
|
VclPtr<vcl::Window> pDockingAreaWindow( VCLUnoHelper::GetWindow( m_xDockAreaWindows[static_cast<int>(DockingArea)] ));
|
|
aReadLock.clear();
|
|
|
|
// Calc correct position of the column/row rectangle to be able to compare it with mouse pos/tracking rect
|
|
SolarMutexGuard aGuard;
|
|
|
|
// 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();
|
|
::tools::Rectangle aRect( aWindowRect.X, aWindowRect.Y, aWindowRect.X+aWindowRect.Width, aWindowRect.Y+aWindowRect.Height );
|
|
aRect.SetPos( pContainerWindow->ScreenToOutputPixel( pDockingAreaWindow->OutputToScreenPixel( aRect.TopLeft() )));
|
|
if ( aRect.Contains( 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;
|
|
}
|
|
|
|
::tools::Rectangle ToolbarLayoutManager::implts_determineFrontDockingRect(
|
|
ui::DockingArea eDockingArea,
|
|
sal_Int32 nRowCol,
|
|
const ::tools::Rectangle& rDockedElementRect,
|
|
std::u16string_view rMovedElementName,
|
|
const ::tools::Rectangle& rMovedElementRect )
|
|
{
|
|
SingleRowColumnWindowData aRowColumnWindowData;
|
|
|
|
bool bHorzDockArea( isHorizontalDockingArea( eDockingArea ));
|
|
implts_getDockingAreaElementInfoOnSingleRowCol( eDockingArea, nRowCol, aRowColumnWindowData );
|
|
if ( aRowColumnWindowData.aRowColumnWindows.empty() )
|
|
return rMovedElementRect;
|
|
else
|
|
{
|
|
sal_Int32 nSpace( 0 );
|
|
::tools::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.getOpenWidth()) );
|
|
if ( bHorzDockArea )
|
|
aFrontDockingRect.Move( -nMove, 0 );
|
|
else
|
|
aFrontDockingRect.Move( 0, -nMove );
|
|
}
|
|
|
|
return aFrontDockingRect;
|
|
}
|
|
}
|
|
|
|
void ToolbarLayoutManager::implts_findNextDockingPos( ui::DockingArea DockingArea, const ::Size& aUIElementSize, awt::Point& rVirtualPos, ::Point& rPixelPos )
|
|
{
|
|
SolarMutexClearableGuard aReadLock;
|
|
if (( DockingArea < ui::DockingArea_DOCKINGAREA_TOP ) || ( DockingArea > ui::DockingArea_DOCKINGAREA_RIGHT ))
|
|
DockingArea = ui::DockingArea_DOCKINGAREA_TOP;
|
|
uno::Reference< awt::XWindow > xDockingWindow( m_xDockAreaWindows[static_cast<int>(DockingArea)] );
|
|
::Size aDockingWinSize;
|
|
|
|
// Retrieve output size from container Window
|
|
vcl::Window* pDockingWindow = VCLUnoHelper::GetWindow( xDockingWindow );
|
|
if ( pDockingWindow )
|
|
aDockingWinSize = pDockingWindow->GetOutputSizePixel();
|
|
aReadLock.clear();
|
|
|
|
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 = awt::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 = awt::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 = awt::Point( nCurrPos, rRowColumnWindowData.nRowColumn );
|
|
if ( DockingArea == ui::DockingArea_DOCKINGAREA_TOP )
|
|
rPixelPos = ::Point( nCurrPos, nPixelPos );
|
|
else
|
|
rPixelPos = ::Point( nCurrPos, aDockingWinSize.Height() - nPixelPos );
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
rVirtualPos = awt::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 = awt::Point( 0, nNextFreeRowCol );
|
|
if ( DockingArea == ui::DockingArea_DOCKINGAREA_TOP )
|
|
rPixelPos = ::Point( 0, nFreeRowColPixelPos );
|
|
else
|
|
rPixelPos = ::Point( 0, aDockingWinSize.Height() - nFreeRowColPixelPos );
|
|
}
|
|
else
|
|
{
|
|
rVirtualPos = awt::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 nContainerClientSize(0);
|
|
|
|
if ( rRowColumnWindowData.aRowColumnWindows.empty() )
|
|
return;
|
|
|
|
if ( isHorizontalDockingArea( nDockingArea ))
|
|
{
|
|
nContainerClientSize = rContainerSize.Width();
|
|
nDiff = nContainerClientSize - rRowColumnWindowData.nVarSize;
|
|
}
|
|
else
|
|
{
|
|
sal_Int32 nTopDockingAreaSize = implts_getTopBottomDockingAreaSizes().Width();
|
|
sal_Int32 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;
|
|
|
|
SolarMutexGuard aGuard;
|
|
{
|
|
uno::Reference< awt::XWindow > xWindow = rRowColumnWindowData.aRowColumnWindows[i];
|
|
VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
|
|
if ( pWindow && pWindow->GetType() == WindowType::TOOLBOX )
|
|
aMinSize = static_cast<ToolBox *>(pWindow.get())->CalcMinimumWindowSizePixel();
|
|
}
|
|
|
|
if ( !aMinSize.IsEmpty() )
|
|
{
|
|
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;
|
|
}
|
|
}
|
|
|
|
SolarMutexClearableGuard aReadLock;
|
|
VclPtr<vcl::Window> pDockAreaWindow = VCLUnoHelper::GetWindow( m_xDockAreaWindows[nDockingArea] );
|
|
aReadLock.clear();
|
|
|
|
sal_Int32 nCurrPos( 0 );
|
|
|
|
SolarMutexGuard aGuard;
|
|
for ( sal_uInt32 i = 0; i < nCount; i++ )
|
|
{
|
|
uno::Reference< awt::XWindow > xWindow = rRowColumnWindowData.aRowColumnWindows[i];
|
|
VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
|
|
vcl::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( true, ShowFlags::NoFocusChange | ShowFlags::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( true, ShowFlags::NoFocusChange | ShowFlags::NoActivate );
|
|
nCurrPos += ( aWinRect.Y - nCurrPos ) + aWinRect.Height;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ToolbarLayoutManager::implts_setLayoutDirty()
|
|
{
|
|
SolarMutexGuard g;
|
|
m_bLayoutDirty = true;
|
|
}
|
|
|
|
void ToolbarLayoutManager::implts_setLayoutInProgress( bool bInProgress )
|
|
{
|
|
SolarMutexGuard g;
|
|
m_bLayoutInProgress = bInProgress;
|
|
}
|
|
|
|
// static
|
|
::tools::Rectangle ToolbarLayoutManager::implts_calcHotZoneRect( const ::tools::Rectangle& rRect, sal_Int32 nHotZoneOffset )
|
|
{
|
|
::tools::Rectangle aRect( rRect );
|
|
|
|
aRect.AdjustLeft( -nHotZoneOffset );
|
|
aRect.AdjustTop( -nHotZoneOffset );
|
|
aRect.AdjustRight(nHotZoneOffset );
|
|
aRect.AdjustBottom(nHotZoneOffset );
|
|
|
|
return aRect;
|
|
}
|
|
|
|
void ToolbarLayoutManager::implts_calcDockingPosSize(
|
|
UIElement& rUIElement,
|
|
DockingOperation& rDockingOperation,
|
|
::tools::Rectangle& rTrackingRect,
|
|
const Point& rMousePos )
|
|
{
|
|
SolarMutexResettableGuard aReadLock;
|
|
uno::Reference< awt::XWindow2 > xContainerWindow( m_xContainerWindow );
|
|
::Size aContainerWinSize;
|
|
vcl::Window* pContainerWindow( nullptr );
|
|
::tools::Rectangle aDockingAreaOffsets( m_aDockingAreaOffsets );
|
|
aReadLock.clear();
|
|
|
|
if ( !rUIElement.m_xUIElement.is() )
|
|
{
|
|
rTrackingRect = ::tools::Rectangle();
|
|
return;
|
|
}
|
|
|
|
{
|
|
// Retrieve output size from container Window
|
|
SolarMutexGuard aGuard;
|
|
pContainerWindow = VCLUnoHelper::GetWindow( xContainerWindow );
|
|
aContainerWinSize = pContainerWindow->GetOutputSizePixel();
|
|
}
|
|
|
|
vcl::Window* pDockingAreaWindow( nullptr );
|
|
uno::Reference< awt::XWindow > xWindow( rUIElement.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
|
|
uno::Reference< awt::XWindow > xDockingAreaWindow;
|
|
::tools::Rectangle aTrackingRect( rTrackingRect );
|
|
ui::DockingArea eDockedArea( 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();
|
|
::tools::Rectangle aDockingAreaRect;
|
|
|
|
aReadLock.reset();
|
|
xDockingAreaWindow = m_xDockAreaWindows[static_cast<int>(eDockedArea)];
|
|
aReadLock.clear();
|
|
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
pDockingAreaWindow = VCLUnoHelper::GetWindow( xDockingAreaWindow );
|
|
VclPtr<vcl::Window> pDockWindow = VCLUnoHelper::GetWindow( xWindow );
|
|
ToolBox* pToolBox( nullptr );
|
|
if ( pDockWindow && pDockWindow->GetType() == WindowType::TOOLBOX )
|
|
pToolBox = static_cast<ToolBox *>(pDockWindow.get());
|
|
|
|
aDockingAreaRect = ::tools::Rectangle( pDockingAreaWindow->GetPosPixel(), pDockingAreaWindow->GetSizePixel() );
|
|
if ( pToolBox )
|
|
{
|
|
// docked toolbars always have one line
|
|
::Size aSize = pToolBox->CalcWindowSizePixel( 1, ImplConvertAlignment( eDockedArea ) );
|
|
aTrackingRect.SetSize( ::Size( aSize.Width(), aSize.Height() ));
|
|
}
|
|
}
|
|
|
|
// default docking operation, dock on the given row/column
|
|
bool bOpOutsideOfDockingArea( !aDockingAreaRect.Contains( 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 );
|
|
::tools::Rectangle aWindowRect;
|
|
::tools::Rectangle aRowColumnRect;
|
|
|
|
const sal_uInt32 nWindowDataCount = aRowColumnsWindowData.size();
|
|
for ( sal_uInt32 i = 0; i < nWindowDataCount; i++ )
|
|
{
|
|
::tools::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
|
|
SolarMutexGuard aGuard;
|
|
aRect.SetPos( pContainerWindow->ScreenToOutputPixel( pDockingAreaWindow->OutputToScreenPixel( aRect.TopLeft() )));
|
|
}
|
|
|
|
bool bIsInsideRowCol( aRect.Contains( 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.
|
|
|
|
::tools::Rectangle aUIElementRect( aWindowRect );
|
|
sal_Int32 nMiddle( bHorizontalDockArea ? ( aWindowRect.Left() + aWindowRect.getOpenWidth() / 2 ) :
|
|
( aWindowRect.Top() + aWindowRect.getOpenHeight() / 2 ));
|
|
bool bInsertBefore( bHorizontalDockArea ? ( rMousePos.X() < nMiddle ) : ( rMousePos.Y() < nMiddle ));
|
|
if ( bInsertBefore )
|
|
{
|
|
if ( bHorizontalDockArea )
|
|
{
|
|
sal_Int32 nSize = std::clamp( sal_Int32(aContainerWinSize.Width() - aWindowRect.Left()),
|
|
sal_Int32(0), sal_Int32(aTrackingRect.getOpenWidth()) );
|
|
if ( nSize == 0 )
|
|
nSize = aWindowRect.getOpenWidth();
|
|
|
|
aUIElementRect.SetSize( ::Size( nSize, aWindowRect.getOpenHeight() ));
|
|
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::clamp( sal_Int32(nTopDockingAreaSize + nMaxLeftRightDockAreaSize - aWindowRect.Top()),
|
|
sal_Int32(0), sal_Int32(aTrackingRect.getOpenHeight()) );
|
|
if ( nSize == 0 )
|
|
nSize = aWindowRect.getOpenHeight();
|
|
|
|
aUIElementRect.SetSize( ::Size( aWindowRect.getOpenWidth(), 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::clamp( sal_Int32(aContainerWinSize.Width() - aWindowRect.Right()),
|
|
sal_Int32(0), sal_Int32(aTrackingRect.getOpenWidth()) );
|
|
if ( nSize == 0 )
|
|
{
|
|
aUIElementRect.SetPos( ::Point( aContainerWinSize.Width() - aTrackingRect.getOpenWidth(), aWindowRect.Top() ));
|
|
aUIElementRect.SetSize( ::Size( aTrackingRect.getOpenWidth(), aWindowRect.getOpenHeight() ));
|
|
rUIElement.m_aDockedData.m_aPos.X = aUIElementRect.Left();
|
|
|
|
}
|
|
else
|
|
{
|
|
aUIElementRect.SetPos( ::Point( aWindowRect.Right(), aWindowRect.Top() ));
|
|
aUIElementRect.SetSize( ::Size( nSize, aWindowRect.getOpenHeight() ));
|
|
rUIElement.m_aDockedData.m_aPos.X = aWindowRect.Right();
|
|
}
|
|
|
|
// Set virtual position
|
|
rUIElement.m_aDockedData.m_aPos.Y = nRowCol;
|
|
}
|
|
else
|
|
{
|
|
sal_Int32 nSize = std::clamp( sal_Int32(nTopDockingAreaSize + nMaxLeftRightDockAreaSize - aWindowRect.Bottom()),
|
|
sal_Int32(0), sal_Int32(aTrackingRect.getOpenHeight()) );
|
|
aUIElementRect.SetPos( ::Point( aWindowRect.Left(), aWindowRect.Bottom() ));
|
|
aUIElementRect.SetSize( ::Size( aWindowRect.getOpenWidth(), nSize ));
|
|
|
|
// Set virtual position
|
|
sal_Int32 nPosY( 0 );
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
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.getOpenHeight() / 2.0 + 0.5 ));
|
|
else
|
|
nOffsetX = sal_Int32( floor( aRowColumnRect.getOpenWidth() / 2.0 + 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 )
|
|
return;
|
|
|
|
// 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.getOpenWidth()) > aContainerWinSize.Width() )
|
|
nPosX = std::min( nPosX,
|
|
std::max( sal_Int32( aContainerWinSize.Width() - rTrackingRect.getOpenWidth() ),
|
|
sal_Int32( 0 )));
|
|
|
|
sal_Int32 nSize = std::min( aContainerWinSize.Width(), rTrackingRect.getOpenWidth() );
|
|
sal_Int32 nDockHeight = std::max( static_cast<sal_Int32>(aDockingAreaRect.getOpenHeight()), sal_Int32( 0 ));
|
|
if ( nDockHeight == 0 )
|
|
{
|
|
sal_Int32 nPosY( std::max( aDockingAreaRect.Top(), aDockingAreaRect.Bottom() ));
|
|
if ( eDockedArea == ui::DockingArea_DOCKINGAREA_BOTTOM )
|
|
nPosY -= rTrackingRect.getOpenHeight();
|
|
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.getOpenHeight() ));
|
|
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 );
|
|
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
nPosX = pDockingAreaWindow->ScreenToOutputPixel(
|
|
pContainerWindow->OutputToScreenPixel( rTrackingRect.TopLeft() )).X();
|
|
}
|
|
rUIElement.m_aDockedData.m_aPos.X = nPosX;
|
|
}
|
|
else
|
|
{
|
|
sal_Int32 nMaxDockingAreaHeight = std::max<sal_Int32>( 0, nMaxLeftRightDockAreaSize );
|
|
sal_Int32 nPosY( std::max<sal_Int32>( aTrackingRect.Top(), nTopDockingAreaSize ));
|
|
if (( nPosY + aTrackingRect.getOpenHeight()) > ( nTopDockingAreaSize + nMaxDockingAreaHeight ))
|
|
nPosY = std::min( nPosY,
|
|
std::max<sal_Int32>( nTopDockingAreaSize + ( nMaxDockingAreaHeight - aTrackingRect.getOpenHeight() ),
|
|
nTopDockingAreaSize ));
|
|
|
|
sal_Int32 nSize = std::min( nMaxDockingAreaHeight, static_cast<sal_Int32>(aTrackingRect.getOpenHeight()) );
|
|
sal_Int32 nDockWidth = std::max( static_cast<sal_Int32>(aDockingAreaRect.getOpenWidth()), sal_Int32( 0 ));
|
|
if ( nDockWidth == 0 )
|
|
{
|
|
sal_Int32 nPosX( std::max( aDockingAreaRect.Left(), aDockingAreaRect.Right() ));
|
|
if ( eDockedArea == ui::DockingArea_DOCKINGAREA_RIGHT )
|
|
nPosX -= rTrackingRect.getOpenWidth();
|
|
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.getOpenWidth(), 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 );
|
|
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
nPosY = pDockingAreaWindow->ScreenToOutputPixel(
|
|
pContainerWindow->OutputToScreenPixel( rTrackingRect.TopLeft() )).Y();
|
|
}
|
|
rUIElement.m_aDockedData.m_aPos.Y = nPosY;
|
|
}
|
|
}
|
|
|
|
// static
|
|
framework::ToolbarLayoutManager::DockingOperation ToolbarLayoutManager::implts_determineDockingOperation(
|
|
ui::DockingArea DockingArea,
|
|
const ::tools::Rectangle& rRowColRect,
|
|
const Point& rMousePos )
|
|
{
|
|
constexpr sal_Int32 nHorzVerticalRegionSize = 6;
|
|
constexpr sal_Int32 nHorzVerticalMoveRegion = 4;
|
|
|
|
if ( rRowColRect.Contains( rMousePos ))
|
|
{
|
|
if ( isHorizontalDockingArea( DockingArea ))
|
|
{
|
|
sal_Int32 nRegion = rRowColRect.getOpenHeight() / 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.getOpenWidth() / 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;
|
|
}
|
|
|
|
::tools::Rectangle ToolbarLayoutManager::implts_calcTrackingAndElementRect(
|
|
ui::DockingArea eDockingArea,
|
|
sal_Int32 nRowCol,
|
|
UIElement& rUIElement,
|
|
const ::tools::Rectangle& rTrackingRect,
|
|
const ::tools::Rectangle& rRowColumnRect,
|
|
const ::Size& rContainerWinSize )
|
|
{
|
|
SolarMutexResettableGuard aReadGuard;
|
|
::tools::Rectangle aDockingAreaOffsets( m_aDockingAreaOffsets );
|
|
aReadGuard.clear();
|
|
|
|
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();
|
|
|
|
::tools::Rectangle aTrackingRect( rTrackingRect );
|
|
if ( bHorizontalDockArea )
|
|
{
|
|
sal_Int32 nPosX( std::max( sal_Int32( rTrackingRect.Left()), sal_Int32( 0 )));
|
|
if (( nPosX + rTrackingRect.getOpenWidth()) > rContainerWinSize.Width() )
|
|
nPosX = std::min( nPosX,
|
|
std::max( sal_Int32( rContainerWinSize.Width() - rTrackingRect.getOpenWidth() ),
|
|
sal_Int32( 0 )));
|
|
|
|
sal_Int32 nSize = std::min( rContainerWinSize.Width(), rTrackingRect.getOpenWidth() );
|
|
|
|
aTrackingRect.SetPos( ::Point( nPosX, rRowColumnRect.Top() ));
|
|
aTrackingRect.setWidth( nSize );
|
|
aTrackingRect.setHeight( rRowColumnRect.getOpenHeight() );
|
|
|
|
// 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, nMaxLeftRightDockAreaSize );
|
|
|
|
sal_Int32 nPosY( std::max<sal_Int32>( aTrackingRect.Top(), nTopDockingAreaSize ));
|
|
if (( nPosY + aTrackingRect.getOpenHeight()) > ( nTopDockingAreaSize + nMaxDockingAreaHeight ))
|
|
nPosY = std::min( nPosY,
|
|
std::max<sal_Int32>( nTopDockingAreaSize + ( nMaxDockingAreaHeight - aTrackingRect.getOpenHeight() ),
|
|
nTopDockingAreaSize ));
|
|
|
|
sal_Int32 nSize = std::min( nMaxDockingAreaHeight, static_cast<sal_Int32>(aTrackingRect.getOpenHeight()) );
|
|
|
|
aTrackingRect.SetPos( ::Point( rRowColumnRect.Left(), nPosY ));
|
|
aTrackingRect.setWidth( rRowColumnRect.getOpenWidth() );
|
|
aTrackingRect.setHeight( nSize );
|
|
|
|
aReadGuard.reset();
|
|
uno::Reference< awt::XWindow > xDockingAreaWindow( m_xDockAreaWindows[static_cast<int>(eDockingArea)] );
|
|
uno::Reference< awt::XWindow2 > xContainerWindow( m_xContainerWindow );
|
|
aReadGuard.clear();
|
|
|
|
sal_Int32 nDockPosY( 0 );
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
vcl::Window* pDockingAreaWindow = VCLUnoHelper::GetWindow( xDockingAreaWindow );
|
|
VclPtr<vcl::Window> 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;
|
|
}
|
|
|
|
// static
|
|
void ToolbarLayoutManager::implts_setTrackingRect( ui::DockingArea eDockingArea, const ::Point& rMousePos, ::tools::Rectangle& rTrackingRect )
|
|
{
|
|
::Point aPoint( rTrackingRect.TopLeft());
|
|
if ( isHorizontalDockingArea( eDockingArea ))
|
|
aPoint.setX( rMousePos.X() );
|
|
else
|
|
aPoint.setY( rMousePos.Y() );
|
|
rTrackingRect.SetPos( aPoint );
|
|
}
|
|
|
|
void ToolbarLayoutManager::implts_renumberRowColumnData(
|
|
ui::DockingArea eDockingArea,
|
|
const UIElement& rUIElement )
|
|
{
|
|
SolarMutexClearableGuard aReadLock;
|
|
uno::Reference< container::XNameAccess > xPersistentWindowState( m_xPersistentWindowState );
|
|
aReadLock.clear();
|
|
|
|
bool bHorzDockingArea( isHorizontalDockingArea( eDockingArea ));
|
|
sal_Int32 nRowCol( bHorzDockingArea ? rUIElement.m_aDockedData.m_aPos.Y : rUIElement.m_aDockedData.m_aPos.X );
|
|
|
|
/* SAFE AREA ----------------------------------------------------------------------------------------------- */
|
|
{
|
|
SolarMutexGuard aWriteLock;
|
|
for (auto& elem : m_aUIElements)
|
|
{
|
|
if ((elem.m_aDockedData.m_nDockedArea == eDockingArea)
|
|
&& (elem.m_aName != rUIElement.m_aName))
|
|
{
|
|
// Don't change toolbars without a valid docking position!
|
|
if (isDefaultPos(elem.m_aDockedData.m_aPos))
|
|
continue;
|
|
|
|
sal_Int32 nWindowRowCol
|
|
= bHorzDockingArea ? elem.m_aDockedData.m_aPos.Y : elem.m_aDockedData.m_aPos.X;
|
|
if (nWindowRowCol >= nRowCol)
|
|
{
|
|
if (bHorzDockingArea)
|
|
elem.m_aDockedData.m_aPos.Y += 1;
|
|
else
|
|
elem.m_aDockedData.m_aPos.X += 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/* SAFE AREA ----------------------------------------------------------------------------------------------- */
|
|
|
|
// We have to change the persistent window state part
|
|
if ( !xPersistentWindowState.is() )
|
|
return;
|
|
|
|
try
|
|
{
|
|
const uno::Sequence< OUString > aWindowElements = xPersistentWindowState->getElementNames();
|
|
for ( OUString const & rWindowElementName : aWindowElements )
|
|
{
|
|
if ( rUIElement.m_aName != rWindowElementName )
|
|
{
|
|
try
|
|
{
|
|
uno::Sequence< beans::PropertyValue > aPropValueSeq;
|
|
awt::Point aDockedPos;
|
|
ui::DockingArea nDockedArea( ui::DockingArea_DOCKINGAREA_DEFAULT );
|
|
|
|
xPersistentWindowState->getByName( rWindowElementName ) >>= aPropValueSeq;
|
|
for (beans::PropertyValue const& rProp : aPropValueSeq)
|
|
{
|
|
if ( rProp.Name == WINDOWSTATE_PROPERTY_DOCKINGAREA )
|
|
rProp.Value >>= nDockedArea;
|
|
else if ( rProp.Name == WINDOWSTATE_PROPERTY_DOCKPOS )
|
|
rProp.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( rWindowElementName, css::uno::Any( aPropValueSeq ));
|
|
}
|
|
}
|
|
catch (const uno::Exception&)
|
|
{
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (const uno::Exception&)
|
|
{
|
|
}
|
|
}
|
|
|
|
// XWindowListener
|
|
|
|
void SAL_CALL ToolbarLayoutManager::windowResized( const awt::WindowEvent& aEvent )
|
|
{
|
|
SolarMutexClearableGuard aWriteLock;
|
|
bool bLocked( m_bDockingInProgress );
|
|
bool bLayoutInProgress( m_bLayoutInProgress );
|
|
aWriteLock.clear();
|
|
|
|
// 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 )
|
|
return;
|
|
|
|
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 = awt::Point(aPos.X, aPos.Y);
|
|
aUIElement.m_aFloatingData.m_aSize = aSize;
|
|
aUIElement.m_bVisible = bVisible;
|
|
}
|
|
|
|
implts_writeWindowStateData( aUIElement );
|
|
}
|
|
else
|
|
{
|
|
implts_setLayoutDirty();
|
|
bNotify = true;
|
|
}
|
|
}
|
|
|
|
if ( bNotify )
|
|
m_pParentLayouter->requestLayout();
|
|
}
|
|
|
|
void SAL_CALL ToolbarLayoutManager::windowMoved( const awt::WindowEvent& /*aEvent*/ )
|
|
{
|
|
}
|
|
|
|
void SAL_CALL ToolbarLayoutManager::windowShown( const lang::EventObject& /*aEvent*/ )
|
|
{
|
|
}
|
|
|
|
void SAL_CALL ToolbarLayoutManager::windowHidden( const lang::EventObject& /*aEvent*/ )
|
|
{
|
|
}
|
|
|
|
// XDockableWindowListener
|
|
|
|
void SAL_CALL ToolbarLayoutManager::startDocking( const awt::DockingEvent& e )
|
|
{
|
|
bool bWinFound( false );
|
|
|
|
SolarMutexClearableGuard aReadGuard;
|
|
uno::Reference< awt::XWindow2 > xWindow( e.Source, uno::UNO_QUERY );
|
|
aReadGuard.clear();
|
|
|
|
UIElement aUIElement = implts_findToolbar( e.Source );
|
|
|
|
if ( aUIElement.m_xUIElement.is() && xWindow.is() )
|
|
{
|
|
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 = awt::Point(aPos.X, aPos.Y);
|
|
aUIElement.m_aFloatingData.m_aSize = aSize;
|
|
|
|
SolarMutexGuard aGuard;
|
|
|
|
VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
|
|
if ( pWindow && pWindow->GetType() == WindowType::TOOLBOX )
|
|
{
|
|
ToolBox* pToolBox = static_cast<ToolBox *>(pWindow.get());
|
|
aUIElement.m_aFloatingData.m_nLines = pToolBox->GetFloatingLines();
|
|
aUIElement.m_aFloatingData.m_bIsHorizontal = isToolboxHorizontalAligned( pToolBox );
|
|
}
|
|
}
|
|
}
|
|
|
|
SolarMutexGuard g;
|
|
m_bDockingInProgress = bWinFound;
|
|
m_aDockUIElement = std::move(aUIElement);
|
|
m_aDockUIElement.m_bUserActive = true;
|
|
}
|
|
|
|
awt::DockingData SAL_CALL ToolbarLayoutManager::docking( const awt::DockingEvent& e )
|
|
{
|
|
constexpr sal_Int32 MAGNETIC_DISTANCE_UNDOCK = 25;
|
|
constexpr sal_Int32 MAGNETIC_DISTANCE_DOCK = 20;
|
|
|
|
SolarMutexClearableGuard aReadLock;
|
|
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[int(ui::DockingArea_DOCKINGAREA_TOP)] );
|
|
uno::Reference< awt::XWindow > xLeftDockingWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_LEFT)] );
|
|
uno::Reference< awt::XWindow > xRightDockingWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_RIGHT)] );
|
|
uno::Reference< awt::XWindow > xBottomDockingWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_BOTTOM)] );
|
|
uno::Reference< awt::XWindow2 > xContainerWindow( m_xContainerWindow );
|
|
UIElement aUIDockingElement( m_aDockUIElement );
|
|
|
|
bool bDockingInProgress( m_bDockingInProgress );
|
|
aReadLock.clear();
|
|
|
|
if ( bDockingInProgress )
|
|
aDockingData.TrackingRectangle = e.TrackingRectangle;
|
|
|
|
if ( bDockingInProgress && xDockWindow.is() && xWindow.is() )
|
|
{
|
|
try
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
|
|
DockingOperation eDockingOperation( DOCKOP_ON_COLROW );
|
|
ui::DockingArea eDockingArea( ui::DockingArea(-1) ); // none
|
|
sal_Int32 nMagneticZone( aUIDockingElement.m_bFloating ? MAGNETIC_DISTANCE_DOCK : MAGNETIC_DISTANCE_UNDOCK );
|
|
::tools::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();
|
|
::tools::Rectangle aTopDockRect( aTmpRect.X, aTmpRect.Y, aTmpRect.Width, aTmpRect.Height );
|
|
::tools::Rectangle aHotZoneTopDockRect( implts_calcHotZoneRect( aTopDockRect, nMagneticZone ));
|
|
|
|
aTmpRect = xBottomDockingWindow->getPosSize();
|
|
::tools::Rectangle aBottomDockRect( aTmpRect.X, aTmpRect.Y, ( aTmpRect.X + aTmpRect.Width), ( aTmpRect.Y + aTmpRect.Height ));
|
|
::tools::Rectangle aHotZoneBottomDockRect( implts_calcHotZoneRect( aBottomDockRect, nMagneticZone ));
|
|
|
|
aTmpRect = xLeftDockingWindow->getPosSize();
|
|
::tools::Rectangle aLeftDockRect( aTmpRect.X, aTmpRect.Y, ( aTmpRect.X + aTmpRect.Width ), ( aTmpRect.Y + aTmpRect.Height ));
|
|
::tools::Rectangle aHotZoneLeftDockRect( implts_calcHotZoneRect( aLeftDockRect, nMagneticZone ));
|
|
|
|
aTmpRect = xRightDockingWindow->getPosSize();
|
|
::tools::Rectangle aRightDockRect( aTmpRect.X, aTmpRect.Y, ( aTmpRect.X + aTmpRect.Width ), ( aTmpRect.Y + aTmpRect.Height ));
|
|
::tools::Rectangle aHotZoneRightDockRect( implts_calcHotZoneRect( aRightDockRect, nMagneticZone ));
|
|
|
|
VclPtr<vcl::Window> pContainerWindow( VCLUnoHelper::GetWindow( xContainerWindow ) );
|
|
::Point aMousePos( pContainerWindow->ScreenToOutputPixel( ::Point( e.MousePos.X, e.MousePos.Y )));
|
|
|
|
if ( aHotZoneTopDockRect.Contains( aMousePos ))
|
|
eDockingArea = ui::DockingArea_DOCKINGAREA_TOP;
|
|
else if ( aHotZoneBottomDockRect.Contains( aMousePos ))
|
|
eDockingArea = ui::DockingArea_DOCKINGAREA_BOTTOM;
|
|
else if ( aHotZoneLeftDockRect.Contains( aMousePos ))
|
|
eDockingArea = ui::DockingArea_DOCKINGAREA_LEFT;
|
|
else if ( aHotZoneRightDockRect.Contains( aMousePos ))
|
|
eDockingArea = ui::DockingArea_DOCKINGAREA_RIGHT;
|
|
|
|
// Higher priority for movements inside the real docking area
|
|
if ( aTopDockRect.Contains( aMousePos ))
|
|
eDockingArea = ui::DockingArea_DOCKINGAREA_TOP;
|
|
else if ( aBottomDockRect.Contains( aMousePos ))
|
|
eDockingArea = ui::DockingArea_DOCKINGAREA_BOTTOM;
|
|
else if ( aLeftDockRect.Contains( aMousePos ))
|
|
eDockingArea = ui::DockingArea_DOCKINGAREA_LEFT;
|
|
else if ( aRightDockRect.Contains( aMousePos ))
|
|
eDockingArea = ui::DockingArea_DOCKINGAREA_RIGHT;
|
|
|
|
// Determine if we have a toolbar and set alignment according to the docking area!
|
|
VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
|
|
ToolBox* pToolBox = nullptr;
|
|
if ( pWindow && pWindow->GetType() == WindowType::TOOLBOX )
|
|
pToolBox = static_cast<ToolBox *>(pWindow.get());
|
|
|
|
if ( eDockingArea != ui::DockingArea(-1) )
|
|
{
|
|
if ( eDockingArea == ui::DockingArea_DOCKINGAREA_TOP )
|
|
{
|
|
aUIDockingElement.m_aDockedData.m_nDockedArea = ui::DockingArea_DOCKINGAREA_TOP;
|
|
aUIDockingElement.m_bFloating = false;
|
|
}
|
|
else if ( eDockingArea == ui::DockingArea_DOCKINGAREA_BOTTOM )
|
|
{
|
|
aUIDockingElement.m_aDockedData.m_nDockedArea = ui::DockingArea_DOCKINGAREA_BOTTOM;
|
|
aUIDockingElement.m_bFloating = false;
|
|
}
|
|
else if ( eDockingArea == ui::DockingArea_DOCKINGAREA_LEFT )
|
|
{
|
|
aUIDockingElement.m_aDockedData.m_nDockedArea = ui::DockingArea_DOCKINGAREA_LEFT;
|
|
aUIDockingElement.m_bFloating = false;
|
|
}
|
|
else if ( eDockingArea == ui::DockingArea_DOCKINGAREA_RIGHT )
|
|
{
|
|
aUIDockingElement.m_aDockedData.m_nDockedArea = ui::DockingArea_DOCKINGAREA_RIGHT;
|
|
aUIDockingElement.m_bFloating = false;
|
|
}
|
|
|
|
::Point aOutputPos = pContainerWindow->ScreenToOutputPixel( aTrackingRect.TopLeft() );
|
|
aTrackingRect.SetPos( aOutputPos );
|
|
|
|
::tools::Rectangle aNewDockingRect( aTrackingRect );
|
|
|
|
implts_calcDockingPosSize( aUIDockingElement, eDockingOperation, aNewDockingRect, aMousePos );
|
|
|
|
::Point aScreenPos = pContainerWindow->OutputToScreenPixel( aNewDockingRect.TopLeft() );
|
|
aDockingData.TrackingRectangle = awt::Rectangle( aScreenPos.X(), aScreenPos.Y(),
|
|
aNewDockingRect.getOpenWidth(), aNewDockingRect.getOpenHeight() );
|
|
}
|
|
else if (pToolBox)
|
|
{
|
|
bool bIsHorizontal = isToolboxHorizontalAligned( pToolBox );
|
|
awt::Size aFloatSize = aUIDockingElement.m_aFloatingData.m_aSize;
|
|
if ( aFloatSize.Width > 0 && aFloatSize.Height > 0 )
|
|
{
|
|
aUIDockingElement.m_aFloatingData.m_aPos
|
|
= VCLUnoHelper::ConvertToAWTPoint(pContainerWindow->ScreenToOutputPixel(
|
|
VCLUnoHelper::ConvertToVCLPoint(e.MousePos)));
|
|
aDockingData.TrackingRectangle.Height = aFloatSize.Height;
|
|
aDockingData.TrackingRectangle.Width = aFloatSize.Width;
|
|
}
|
|
else
|
|
{
|
|
aFloatSize = VCLUnoHelper::ConvertToAWTSize(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
|
|
= VCLUnoHelper::ConvertToAWTPoint(pContainerWindow->ScreenToOutputPixel(
|
|
VCLUnoHelper::ConvertToVCLPoint(e.MousePos)));
|
|
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 == ui::DockingArea(-1) );
|
|
|
|
// Write current data to the member docking progress data
|
|
SolarMutexGuard g;
|
|
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;
|
|
}
|
|
catch (const uno::Exception&)
|
|
{
|
|
}
|
|
}
|
|
|
|
return aDockingData;
|
|
}
|
|
|
|
void SAL_CALL ToolbarLayoutManager::endDocking( const awt::EndDockingEvent& e )
|
|
{
|
|
if (e.bCancelled)
|
|
return;
|
|
|
|
bool bDockingInProgress( false );
|
|
bool bStartDockFloated( false );
|
|
bool bFloating( false );
|
|
UIElement aUIDockingElement;
|
|
|
|
/* SAFE AREA ----------------------------------------------------------------------------------------------- */
|
|
SolarMutexResettableGuard aWriteLock;
|
|
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 = awt::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(aUIDockingElement.m_aDockedData.m_nDockedArea, 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.clear();
|
|
/* SAFE AREA ----------------------------------------------------------------------------------------------- */
|
|
|
|
implts_writeWindowStateData( aUIDockingElement );
|
|
|
|
if ( bDockingInProgress )
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( uno::Reference< awt::XWindow >( e.Source, uno::UNO_QUERY ));
|
|
ToolBox* pToolBox = nullptr;
|
|
if ( pWindow && pWindow->GetType() == WindowType::TOOLBOX )
|
|
pToolBox = static_cast<ToolBox *>(pWindow.get());
|
|
|
|
if ( pToolBox )
|
|
{
|
|
if( e.bFloating )
|
|
{
|
|
if ( aUIDockingElement.m_aFloatingData.m_bIsHorizontal )
|
|
pToolBox->SetAlign();
|
|
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.reset();
|
|
m_bDockingInProgress = false;
|
|
m_bLayoutDirty = !bStartDockFloated || !bFloating;
|
|
bool bNotify = m_bLayoutDirty;
|
|
aWriteLock.clear();
|
|
|
|
if ( bNotify )
|
|
m_pParentLayouter->requestLayout();
|
|
}
|
|
|
|
sal_Bool SAL_CALL ToolbarLayoutManager::prepareToggleFloatingMode( const lang::EventObject& e )
|
|
{
|
|
SolarMutexClearableGuard aReadLock;
|
|
bool bDockingInProgress = m_bDockingInProgress;
|
|
aReadLock.clear();
|
|
|
|
UIElement aUIDockingElement = implts_findToolbar( e.Source );
|
|
bool bWinFound( !aUIDockingElement.m_aName.isEmpty() );
|
|
uno::Reference< awt::XWindow > xWindow( e.Source, uno::UNO_QUERY );
|
|
|
|
if ( !bWinFound || !xWindow.is() )
|
|
return true;
|
|
|
|
if ( bDockingInProgress )
|
|
return true;
|
|
|
|
uno::Reference< awt::XDockableWindow > xDockWindow( xWindow, uno::UNO_QUERY );
|
|
if ( !xDockWindow->isFloating() )
|
|
return true;
|
|
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
|
|
if ( pWindow && pWindow->GetType() == WindowType::TOOLBOX )
|
|
{
|
|
ToolBox* pToolBox = static_cast< ToolBox *>( pWindow.get() );
|
|
aUIDockingElement.m_aFloatingData.m_aPos
|
|
= VCLUnoHelper::ConvertToAWTPoint(pToolBox->GetPosPixel());
|
|
aUIDockingElement.m_aFloatingData.m_aSize = VCLUnoHelper::ConvertToAWTSize(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 true;
|
|
}
|
|
|
|
void SAL_CALL ToolbarLayoutManager::toggleFloatingMode( const lang::EventObject& e )
|
|
{
|
|
UIElement aUIDockingElement;
|
|
|
|
SolarMutexResettableGuard aReadLock;
|
|
bool bDockingInProgress( m_bDockingInProgress );
|
|
if ( bDockingInProgress )
|
|
aUIDockingElement = m_aDockUIElement;
|
|
aReadLock.clear();
|
|
|
|
vcl::Window* pWindow( nullptr );
|
|
ToolBox* pToolBox( nullptr );
|
|
uno::Reference< awt::XWindow2 > xWindow;
|
|
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
xWindow.set( e.Source, uno::UNO_QUERY );
|
|
pWindow = VCLUnoHelper::GetWindow( xWindow );
|
|
|
|
if ( pWindow && pWindow->GetType() == WindowType::TOOLBOX )
|
|
pToolBox = static_cast<ToolBox *>(pWindow);
|
|
}
|
|
|
|
if ( !bDockingInProgress )
|
|
{
|
|
aUIDockingElement = implts_findToolbar( e.Source );
|
|
bool bWinFound = !aUIDockingElement.m_aName.isEmpty();
|
|
|
|
if ( bWinFound && xWindow.is() )
|
|
{
|
|
aUIDockingElement.m_bFloating = !aUIDockingElement.m_bFloating;
|
|
aUIDockingElement.m_bUserActive = true;
|
|
|
|
implts_setLayoutInProgress();
|
|
if ( aUIDockingElement.m_bFloating )
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
if ( pToolBox )
|
|
{
|
|
pToolBox->SetLineCount( aUIDockingElement.m_aFloatingData.m_nLines );
|
|
if ( aUIDockingElement.m_aFloatingData.m_bIsHorizontal )
|
|
pToolBox->SetAlign();
|
|
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 = VCLUnoHelper::ConvertToAWTSize(pToolBox->CalcFloatingWindowSizePixel());
|
|
else if ( pWindow )
|
|
aUIDockingElement.m_aFloatingData.m_aSize = VCLUnoHelper::ConvertToAWTSize(pWindow->GetOutputSizePixel());
|
|
}
|
|
|
|
xWindow->setPosSize( aUIDockingElement.m_aFloatingData.m_aPos.X,
|
|
aUIDockingElement.m_aFloatingData.m_aPos.Y,
|
|
0, 0, awt::PosSize::POS );
|
|
xWindow->setOutputSize(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;
|
|
awt::Point aDockPos;
|
|
::Size aSize;
|
|
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
if ( pToolBox )
|
|
aSize = pToolBox->CalcWindowSizePixel( 1, ImplConvertAlignment( aUIDockingElement.m_aDockedData.m_nDockedArea ) );
|
|
else if ( pWindow )
|
|
aSize = pWindow->GetSizePixel();
|
|
}
|
|
|
|
implts_findNextDockingPos(aUIDockingElement.m_aDockedData.m_nDockedArea, aSize, aDockPos, aPixelPos );
|
|
aUIDockingElement.m_aDockedData.m_aPos = aDockPos;
|
|
}
|
|
|
|
SolarMutexGuard aGuard;
|
|
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(VCLUnoHelper::ConvertToAWTSize(aSize));
|
|
}
|
|
}
|
|
|
|
implts_setLayoutInProgress( false );
|
|
implts_setToolbar( aUIDockingElement );
|
|
implts_writeWindowStateData( aUIDockingElement );
|
|
implts_sortUIElements();
|
|
implts_setLayoutDirty();
|
|
|
|
aReadLock.reset();
|
|
LayoutManager* pParentLayouter( m_pParentLayouter );
|
|
aReadLock.clear();
|
|
|
|
if ( pParentLayouter )
|
|
pParentLayouter->requestLayout();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
if ( pToolBox )
|
|
{
|
|
if ( aUIDockingElement.m_bFloating )
|
|
{
|
|
if ( aUIDockingElement.m_aFloatingData.m_bIsHorizontal )
|
|
pToolBox->SetAlign();
|
|
else
|
|
pToolBox->SetAlign( WindowAlign::Left );
|
|
}
|
|
else
|
|
pToolBox->SetAlign( ImplConvertAlignment( aUIDockingElement.m_aDockedData.m_nDockedArea) );
|
|
}
|
|
}
|
|
}
|
|
|
|
void SAL_CALL ToolbarLayoutManager::closed( const lang::EventObject& e )
|
|
{
|
|
OUString aName;
|
|
UIElement aUIElement;
|
|
|
|
{
|
|
SolarMutexGuard aWriteLock;
|
|
for (auto& elem : m_aUIElements)
|
|
{
|
|
uno::Reference<ui::XUIElement> xUIElement(elem.m_xUIElement);
|
|
if (xUIElement.is())
|
|
{
|
|
uno::Reference<uno::XInterface> xIfac(xUIElement->getRealInterface(),
|
|
uno::UNO_QUERY);
|
|
if (xIfac == e.Source)
|
|
{
|
|
aName = elem.m_aName;
|
|
|
|
// user closes a toolbar =>
|
|
// context sensitive toolbar: only destroy toolbar and store state.
|
|
// non context sensitive toolbar: make it invisible, store state and destroy it.
|
|
if (!elem.m_bContextSensitive)
|
|
elem.m_bVisible = false;
|
|
|
|
aUIElement = elem;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// destroy element
|
|
if ( aName.isEmpty() )
|
|
return;
|
|
|
|
implts_writeWindowStateData( aUIElement );
|
|
destroyToolbar( aName );
|
|
|
|
SolarMutexClearableGuard aReadLock;
|
|
bool bLayoutDirty = m_bLayoutDirty;
|
|
LayoutManager* pParentLayouter( m_pParentLayouter );
|
|
aReadLock.clear();
|
|
|
|
if ( bLayoutDirty && pParentLayouter )
|
|
pParentLayouter->requestLayout();
|
|
}
|
|
|
|
void SAL_CALL ToolbarLayoutManager::endPopupMode( const awt::EndPopupModeEvent& /*e*/ )
|
|
{
|
|
}
|
|
|
|
// XUIConfigurationListener
|
|
|
|
void SAL_CALL ToolbarLayoutManager::elementInserted( const ui::ConfigurationEvent& rEvent )
|
|
{
|
|
UIElement aUIElement = implts_findToolbar( rEvent.ResourceURL );
|
|
|
|
uno::Reference< ui::XUIElementSettings > xElementSettings( aUIElement.m_xUIElement, uno::UNO_QUERY );
|
|
if ( xElementSettings.is() )
|
|
{
|
|
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( u"ConfigurationSource"_ustr, css::uno::Any( m_xDocCfgMgr ));
|
|
}
|
|
xElementSettings->updateSettings();
|
|
}
|
|
else
|
|
{
|
|
OUString aElementType;
|
|
OUString aElementName;
|
|
parseResourceURL( rEvent.ResourceURL, aElementType, aElementName );
|
|
if ( aElementName.indexOf( "custom_" ) != -1 )
|
|
{
|
|
// custom toolbar must be directly created, shown and layouted!
|
|
createToolbar( rEvent.ResourceURL );
|
|
uno::Reference< ui::XUIElement > xUIElement = getToolbar( rEvent.ResourceURL );
|
|
if ( xUIElement.is() )
|
|
{
|
|
OUString aUIName;
|
|
uno::Reference< ui::XUIConfigurationManager > xCfgMgr;
|
|
uno::Reference< beans::XPropertySet > xPropSet;
|
|
|
|
try
|
|
{
|
|
xCfgMgr.set( rEvent.Source, uno::UNO_QUERY );
|
|
xPropSet.set( xCfgMgr->getSettings( rEvent.ResourceURL, false ), uno::UNO_QUERY );
|
|
|
|
if ( xPropSet.is() )
|
|
xPropSet->getPropertyValue(u"UIName"_ustr) >>= aUIName;
|
|
}
|
|
catch (const container::NoSuchElementException&)
|
|
{
|
|
}
|
|
catch (const beans::UnknownPropertyException&)
|
|
{
|
|
}
|
|
catch (const lang::WrappedTargetException&)
|
|
{
|
|
}
|
|
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
vcl::Window* pWindow = getWindowFromXUIElement( xUIElement );
|
|
if ( pWindow )
|
|
pWindow->SetText( aUIName );
|
|
}
|
|
|
|
showToolbar( rEvent.ResourceURL );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void SAL_CALL ToolbarLayoutManager::elementRemoved( const ui::ConfigurationEvent& rEvent )
|
|
{
|
|
SolarMutexClearableGuard aReadLock;
|
|
uno::Reference< awt::XWindow > xContainerWindow = m_xContainerWindow;
|
|
uno::Reference< ui::XUIConfigurationManager > xModuleCfgMgr( m_xModuleCfgMgr );
|
|
uno::Reference< ui::XUIConfigurationManager > xDocCfgMgr( m_xDocCfgMgr );
|
|
aReadLock.clear();
|
|
|
|
UIElement aUIElement = implts_findToolbar( rEvent.ResourceURL );
|
|
uno::Reference< ui::XUIElementSettings > xElementSettings( aUIElement.m_xUIElement, uno::UNO_QUERY );
|
|
if ( !xElementSettings.is() )
|
|
return;
|
|
|
|
bool bNoSettings( false );
|
|
OUString aConfigSourcePropName( u"ConfigurationSource"_ustr );
|
|
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, css::uno::Any( 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 )
|
|
{
|
|
UIElement aUIElement = implts_findToolbar( rEvent.ResourceURL );
|
|
|
|
uno::Reference< ui::XUIElementSettings > xElementSettings( aUIElement.m_xUIElement, uno::UNO_QUERY );
|
|
if ( !xElementSettings.is() )
|
|
return;
|
|
|
|
uno::Reference< uno::XInterface > xElementCfgMgr;
|
|
uno::Reference< beans::XPropertySet > xPropSet( xElementSettings, uno::UNO_QUERY );
|
|
|
|
if ( xPropSet.is() )
|
|
xPropSet->getPropertyValue( u"ConfigurationSource"_ustr ) >>= xElementCfgMgr;
|
|
|
|
if ( !xElementCfgMgr.is() )
|
|
return;
|
|
|
|
// Check if the same UI configuration manager has changed => update settings
|
|
if ( rEvent.Source != xElementCfgMgr )
|
|
return;
|
|
|
|
xElementSettings->updateSettings();
|
|
|
|
SolarMutexClearableGuard aWriteLock;
|
|
bool bNotify = !aUIElement.m_bFloating;
|
|
m_bLayoutDirty = bNotify;
|
|
LayoutManager* pParentLayouter( m_pParentLayouter );
|
|
aWriteLock.clear();
|
|
|
|
if ( bNotify && pParentLayouter )
|
|
pParentLayouter->requestLayout();
|
|
}
|
|
|
|
void ToolbarLayoutManager::updateToolbarsTips()
|
|
{
|
|
SolarMutexGuard g;
|
|
|
|
for (auto& elem : m_aUIElements)
|
|
{
|
|
uno::Reference< ui::XUIElementSettings > xElementSettings(elem.m_xUIElement, uno::UNO_QUERY);
|
|
if (!xElementSettings.is())
|
|
continue;
|
|
xElementSettings->updateSettings();
|
|
}
|
|
}
|
|
|
|
|
|
uno::Reference< ui::XUIElement > ToolbarLayoutManager::getToolbar( std::u16string_view aName )
|
|
{
|
|
return implts_findToolbar( aName ).m_xUIElement;
|
|
}
|
|
|
|
uno::Sequence< uno::Reference< ui::XUIElement > > ToolbarLayoutManager::getToolbars()
|
|
{
|
|
uno::Sequence< uno::Reference< ui::XUIElement > > aSeq;
|
|
|
|
SolarMutexGuard g;
|
|
if ( !m_aUIElements.empty() )
|
|
{
|
|
sal_uInt32 nCount(0);
|
|
for (auto const& elem : m_aUIElements)
|
|
{
|
|
if ( elem.m_xUIElement.is() )
|
|
{
|
|
++nCount;
|
|
aSeq.realloc( nCount );
|
|
aSeq.getArray()[nCount-1] = elem.m_xUIElement;
|
|
}
|
|
}
|
|
}
|
|
|
|
return aSeq;
|
|
}
|
|
|
|
bool ToolbarLayoutManager::floatToolbar( std::u16string_view rResourceURL )
|
|
{
|
|
UIElement aUIElement = implts_findToolbar( rResourceURL );
|
|
if ( !aUIElement.m_xUIElement.is() )
|
|
return false;
|
|
|
|
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 (const lang::DisposedException&)
|
|
{
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool ToolbarLayoutManager::lockToolbar( std::u16string_view rResourceURL )
|
|
{
|
|
UIElement aUIElement = implts_findToolbar( rResourceURL );
|
|
if ( !aUIElement.m_xUIElement.is() )
|
|
return false;
|
|
|
|
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 (const lang::DisposedException&)
|
|
{
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool ToolbarLayoutManager::unlockToolbar( std::u16string_view rResourceURL )
|
|
{
|
|
UIElement aUIElement = implts_findToolbar( rResourceURL );
|
|
if ( !aUIElement.m_xUIElement.is() )
|
|
return false;
|
|
|
|
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 (const lang::DisposedException&)
|
|
{
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool ToolbarLayoutManager::isToolbarVisible( std::u16string_view rResourceURL )
|
|
{
|
|
uno::Reference< awt::XWindow2 > xWindow2( implts_getXWindow( rResourceURL ), uno::UNO_QUERY );
|
|
return ( xWindow2.is() && xWindow2->isVisible() );
|
|
}
|
|
|
|
bool ToolbarLayoutManager::isToolbarFloating( std::u16string_view rResourceURL )
|
|
{
|
|
uno::Reference< awt::XDockableWindow > xDockWindow( implts_getXWindow( rResourceURL ), uno::UNO_QUERY );
|
|
return ( xDockWindow.is() && xDockWindow->isFloating() );
|
|
}
|
|
|
|
bool ToolbarLayoutManager::isToolbarDocked( std::u16string_view rResourceURL )
|
|
{
|
|
return !isToolbarFloating( rResourceURL );
|
|
}
|
|
|
|
bool ToolbarLayoutManager::isToolbarLocked( std::u16string_view rResourceURL )
|
|
{
|
|
uno::Reference< awt::XDockableWindow > xDockWindow( implts_getXWindow( rResourceURL ), uno::UNO_QUERY );
|
|
return ( xDockWindow.is() && xDockWindow->isLocked() );
|
|
}
|
|
|
|
awt::Size ToolbarLayoutManager::getToolbarSize( std::u16string_view rResourceURL )
|
|
{
|
|
vcl::Window* pWindow = implts_getWindow( rResourceURL );
|
|
|
|
SolarMutexGuard aGuard;
|
|
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( std::u16string_view 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
|
|
aPos = aUIElement.m_aDockedData.m_aPos;
|
|
}
|
|
|
|
return aPos;
|
|
}
|
|
|
|
void ToolbarLayoutManager::setToolbarSize( std::u16string_view 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 = aSize;
|
|
implts_setToolbar( aUIElement );
|
|
implts_writeWindowStateData( aUIElement );
|
|
implts_sortUIElements();
|
|
}
|
|
}
|
|
|
|
void ToolbarLayoutManager::setToolbarPos( std::u16string_view 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 = aPos;
|
|
implts_setToolbar( aUIElement );
|
|
implts_writeWindowStateData( aUIElement );
|
|
implts_sortUIElements();
|
|
}
|
|
}
|
|
|
|
void ToolbarLayoutManager::setToolbarPosSize( std::u16string_view rResourceURL, const awt::Point& aPos, const awt::Size& aSize )
|
|
{
|
|
setToolbarPos( rResourceURL, aPos );
|
|
setToolbarSize( rResourceURL, aSize );
|
|
}
|
|
|
|
} // namespace framework
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|