forked from amazingfate/loongoffice
The change allowed to simplify many places where previously this API was used, to avoid inefficient calculations (e.g., moving rectangle keeping its size, and then immediately changing the size). Change-Id: Ica2dc594d91cae83e2c2740c1f4fb23f44998916 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/120461 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
4127 lines
161 KiB
C++
4127 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 <cppuhelper/queryinterface.hxx>
|
|
#include <unotools/cmdoptions.hxx>
|
|
#include <toolkit/helper/vclunohelper.hxx>
|
|
#include <toolkit/helper/convert.hxx>
|
|
#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(
|
|
const uno::Reference< uno::XComponentContext >& rxContext,
|
|
const uno::Reference< ui::XUIElementFactory >& xUIElementFactory,
|
|
LayoutManager* pParentLayouter ):
|
|
m_xContext( rxContext),
|
|
m_xUIElementFactoryManager( 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( 2 );
|
|
aPropSeq[0].Name = "Frame";
|
|
aPropSeq[0].Value <<= xFrame;
|
|
aPropSeq[1].Name = "Persistent";
|
|
aPropSeq[1].Value <<= 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 >(
|
|
static_cast< OWeakObject * >( this ), uno::UNO_QUERY ));
|
|
xWindow->addWindowListener( uno::Reference< awt::XWindowListener >(
|
|
static_cast< OWeakObject * >( this ), uno::UNO_QUERY ));
|
|
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 = 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.Lookup( SvtCommandOptions::CMDOPTION_DISABLED, "ConfigureDialog" ))
|
|
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( const OUString& rResourceURL )
|
|
{
|
|
uno::Reference< lang::XComponent > xComponent;
|
|
|
|
bool bNotify( false );
|
|
bool bMustBeSorted( false );
|
|
bool bMustLayouted( false );
|
|
bool bMustBeDestroyed( !rResourceURL.startsWith("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 >(
|
|
static_cast< OWeakObject * >( this ), uno::UNO_QUERY ));
|
|
}
|
|
catch (const uno::Exception&)
|
|
{
|
|
}
|
|
|
|
try
|
|
{
|
|
if ( xDockWindow.is() )
|
|
xDockWindow->removeDockableWindowListener( uno::Reference< awt::XDockableWindowListener >(
|
|
static_cast< OWeakObject * >( this ), uno::UNO_QUERY ));
|
|
}
|
|
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() )
|
|
{
|
|
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::XWindowPeer >& xParentWindow )
|
|
{
|
|
static const char DOCKINGAREASTRING[] = "dockingarea";
|
|
|
|
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;
|
|
}
|
|
|
|
OUString ToolbarLayoutManager::implts_generateGenericAddonToolbarTitle( sal_Int32 nNumber ) const
|
|
{
|
|
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 );
|
|
aPropSeq[0].Name = "Frame";
|
|
aPropSeq[0].Value <<= xFrame;
|
|
aPropSeq[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 );
|
|
aPropSeq[1].Value <<= aAddonToolBarData;
|
|
|
|
UIElement aElement = implts_findToolbar( aAddonToolBarName );
|
|
|
|
// #i79828
|
|
// It's now possible that we are called more than once. Be sure to not create
|
|
// add-on toolbars more than once!
|
|
if ( aElement.m_xUIElement.is() )
|
|
continue;
|
|
|
|
try
|
|
{
|
|
xUIElement = xUIElementFactory->createUIElement( aAddonToolBarName, aPropSeq );
|
|
if ( xUIElement.is() )
|
|
{
|
|
uno::Reference< awt::XDockableWindow > xDockWindow( xUIElement->getRealInterface(), uno::UNO_QUERY );
|
|
if ( xDockWindow.is() )
|
|
{
|
|
try
|
|
{
|
|
xDockWindow->addDockableWindowListener( uno::Reference< awt::XDockableWindowListener >( static_cast< OWeakObject * >( this ), uno::UNO_QUERY ));
|
|
xDockWindow->enableDocking( true );
|
|
uno::Reference< awt::XWindow > xWindow( xDockWindow, uno::UNO_QUERY );
|
|
if ( xWindow.is() )
|
|
xWindow->addWindowListener( uno::Reference< awt::XWindowListener >( static_cast< OWeakObject * >( this ), uno::UNO_QUERY ));
|
|
}
|
|
catch (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, "toolbar", 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( AWTSize( 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("Persistent") >>= 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( 9 );
|
|
|
|
aWindowState[0].Name = WINDOWSTATE_PROPERTY_DOCKED;
|
|
aWindowState[0].Value <<= !rElementData.m_bFloating;
|
|
aWindowState[1].Name = WINDOWSTATE_PROPERTY_VISIBLE;
|
|
aWindowState[1].Value <<= rElementData.m_bVisible;
|
|
aWindowState[2].Name = WINDOWSTATE_PROPERTY_DOCKINGAREA;
|
|
aWindowState[2].Value <<= rElementData.m_aDockedData.m_nDockedArea;
|
|
|
|
awt::Point aPos = rElementData.m_aDockedData.m_aPos;
|
|
aWindowState[3].Name = WINDOWSTATE_PROPERTY_DOCKPOS;
|
|
aWindowState[3].Value <<= aPos;
|
|
|
|
aPos = rElementData.m_aFloatingData.m_aPos;
|
|
aWindowState[4].Name = WINDOWSTATE_PROPERTY_POS;
|
|
aWindowState[4].Value <<= aPos;
|
|
|
|
aWindowState[5].Name = WINDOWSTATE_PROPERTY_SIZE;
|
|
aWindowState[5].Value <<= rElementData.m_aFloatingData.m_aSize;
|
|
aWindowState[6].Name = WINDOWSTATE_PROPERTY_UINAME;
|
|
aWindowState[6].Value <<= rElementData.m_aUIName;
|
|
aWindowState[7].Name = WINDOWSTATE_PROPERTY_LOCKED;
|
|
aWindowState[7].Value <<= rElementData.m_aDockedData.m_bLocked;
|
|
aWindowState[8].Name = WINDOWSTATE_PROPERTY_STYLE;
|
|
aWindowState[8].Value <<= 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::makeAny( aWindowState ));
|
|
}
|
|
else
|
|
{
|
|
uno::Reference< container::XNameContainer > xInsert( xPersistentWindowState, uno::UNO_QUERY );
|
|
xInsert->insertByName( aName, uno::makeAny( 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 = AWTPoint(pContainerWindow->OutputToScreenPixel(VCLPoint(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.IsInside( rMousePos ))
|
|
{
|
|
// Check if we have found the excluded element. If yes, we have to provide an empty rectangle.
|
|
// We prevent that a toolbar cannot be moved when the mouse pointer is inside its own rectangle!
|
|
if ( rExcludeElementName != rRowColumnWindowData.aUIElementNames[i] )
|
|
return aRect;
|
|
else
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return aWinRect;
|
|
}
|
|
|
|
::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.getWidth()) );
|
|
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;
|
|
}
|
|
|
|
::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.IsInside( rMousePos ));
|
|
|
|
std::vector< SingleRowColumnWindowData > aRowColumnsWindowData;
|
|
|
|
rDockingOperation = DOCKOP_ON_COLROW;
|
|
implts_getDockingAreaElementInfos( eDockedArea, aRowColumnsWindowData );
|
|
|
|
// determine current first row/column and last row/column
|
|
sal_Int32 nMaxRowCol( -1 );
|
|
sal_Int32 nMinRowCol( SAL_MAX_INT32 );
|
|
const sal_uInt32 nCount = aRowColumnsWindowData.size();
|
|
for ( sal_uInt32 i = 0; i < nCount; i++ )
|
|
{
|
|
if ( aRowColumnsWindowData[i].nRowColumn > nMaxRowCol )
|
|
nMaxRowCol = aRowColumnsWindowData[i].nRowColumn;
|
|
if ( aRowColumnsWindowData[i].nRowColumn < nMinRowCol )
|
|
nMinRowCol = aRowColumnsWindowData[i].nRowColumn;
|
|
}
|
|
|
|
if ( !bOpOutsideOfDockingArea )
|
|
{
|
|
// docking inside our docking area
|
|
sal_Int32 nIndex( -1 );
|
|
sal_Int32 nRowCol( -1 );
|
|
::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.IsInside( rMousePos ) );
|
|
if ( bIsInsideRowCol )
|
|
{
|
|
nIndex = i;
|
|
nRowCol = aRowColumnsWindowData[i].nRowColumn;
|
|
rDockingOperation = implts_determineDockingOperation( eDockedArea, aRect, rMousePos );
|
|
aWindowRect = implts_getWindowRectFromRowColumn( eDockedArea, aRowColumnsWindowData[i], rMousePos, rUIElement.m_aName );
|
|
aRowColumnRect = aRect;
|
|
break;
|
|
}
|
|
}
|
|
|
|
OSL_ENSURE( ( nIndex >= 0 ) && ( nRowCol >= 0 ), "Impossible case - no row/column found but mouse pointer is inside our docking area" );
|
|
if (( nIndex >= 0 ) && ( nRowCol >= 0 ))
|
|
{
|
|
if ( rDockingOperation == DOCKOP_ON_COLROW )
|
|
{
|
|
if ( !aWindowRect.IsEmpty())
|
|
{
|
|
// Tracking rect is on a row/column and mouse is over a docked toolbar.
|
|
// Determine if the tracking rect must be located before/after the docked toolbar.
|
|
|
|
::tools::Rectangle aUIElementRect( aWindowRect );
|
|
sal_Int32 nMiddle( bHorizontalDockArea ? ( aWindowRect.Left() + aWindowRect.getWidth() / 2 ) :
|
|
( aWindowRect.Top() + aWindowRect.getHeight() / 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.getWidth()) );
|
|
if ( nSize == 0 )
|
|
nSize = aWindowRect.getWidth();
|
|
|
|
aUIElementRect.SetSize( ::Size( nSize, aWindowRect.getHeight() ));
|
|
aWindowRect = implts_determineFrontDockingRect( eDockedArea, nRowCol, aWindowRect,rUIElement.m_aName, aUIElementRect );
|
|
|
|
// Set virtual position
|
|
rUIElement.m_aDockedData.m_aPos.X = aWindowRect.Left();
|
|
rUIElement.m_aDockedData.m_aPos.Y = nRowCol;
|
|
}
|
|
else
|
|
{
|
|
sal_Int32 nSize = std::clamp( sal_Int32(nTopDockingAreaSize + nMaxLeftRightDockAreaSize - aWindowRect.Top()),
|
|
sal_Int32(0), sal_Int32(aTrackingRect.getHeight()) );
|
|
if ( nSize == 0 )
|
|
nSize = aWindowRect.getHeight();
|
|
|
|
aUIElementRect.SetSize( ::Size( aWindowRect.getWidth(), nSize ));
|
|
aWindowRect = implts_determineFrontDockingRect( eDockedArea, nRowCol, aWindowRect, rUIElement.m_aName, aUIElementRect );
|
|
|
|
// Set virtual position
|
|
sal_Int32 nPosY = pDockingAreaWindow->ScreenToOutputPixel(
|
|
pContainerWindow->OutputToScreenPixel( aWindowRect.TopLeft() )).Y();
|
|
rUIElement.m_aDockedData.m_aPos.X = nRowCol;
|
|
rUIElement.m_aDockedData.m_aPos.Y = nPosY;
|
|
}
|
|
|
|
rTrackingRect = aWindowRect;
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
if ( bHorizontalDockArea )
|
|
{
|
|
sal_Int32 nSize = ::std::clamp( sal_Int32(aContainerWinSize.Width() - aWindowRect.Right()),
|
|
sal_Int32(0), sal_Int32(aTrackingRect.getWidth()) );
|
|
if ( nSize == 0 )
|
|
{
|
|
aUIElementRect.SetPos( ::Point( aContainerWinSize.Width() - aTrackingRect.getWidth(), aWindowRect.Top() ));
|
|
aUIElementRect.SetSize( ::Size( aTrackingRect.getWidth(), aWindowRect.getHeight() ));
|
|
rUIElement.m_aDockedData.m_aPos.X = aUIElementRect.Left();
|
|
|
|
}
|
|
else
|
|
{
|
|
aUIElementRect.SetPos( ::Point( aWindowRect.Right(), aWindowRect.Top() ));
|
|
aUIElementRect.SetSize( ::Size( nSize, aWindowRect.getHeight() ));
|
|
rUIElement.m_aDockedData.m_aPos.X = aWindowRect.Right();
|
|
}
|
|
|
|
// Set virtual position
|
|
rUIElement.m_aDockedData.m_aPos.Y = nRowCol;
|
|
}
|
|
else
|
|
{
|
|
sal_Int32 nSize = std::clamp( sal_Int32(nTopDockingAreaSize + nMaxLeftRightDockAreaSize - aWindowRect.Bottom()),
|
|
sal_Int32(0), sal_Int32(aTrackingRect.getHeight()) );
|
|
aUIElementRect.SetPos( ::Point( aWindowRect.Left(), aWindowRect.Bottom() ));
|
|
aUIElementRect.SetSize( ::Size( aWindowRect.getWidth(), 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.getHeight() / 2.0 + 0.5 ));
|
|
else
|
|
nOffsetX = sal_Int32( floor( aRowColumnRect.getWidth() / 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.getWidth()) > aContainerWinSize.Width() )
|
|
nPosX = std::min( nPosX,
|
|
std::max( sal_Int32( aContainerWinSize.Width() - rTrackingRect.getWidth() ),
|
|
sal_Int32( 0 )));
|
|
|
|
sal_Int32 nSize = std::min( aContainerWinSize.Width(), rTrackingRect.getWidth() );
|
|
sal_Int32 nDockHeight = std::max( static_cast<sal_Int32>(aDockingAreaRect.getHeight()), sal_Int32( 0 ));
|
|
if ( nDockHeight == 0 )
|
|
{
|
|
sal_Int32 nPosY( std::max( aDockingAreaRect.Top(), aDockingAreaRect.Bottom() ));
|
|
if ( eDockedArea == ui::DockingArea_DOCKINGAREA_BOTTOM )
|
|
nPosY -= rTrackingRect.getHeight();
|
|
rTrackingRect.SetPos( Point( nPosX, nPosY ));
|
|
rUIElement.m_aDockedData.m_aPos.Y = 0;
|
|
}
|
|
else if ( rMousePos.Y() < ( aDockingAreaRect.Top() + ( nDockHeight / 2 )))
|
|
{
|
|
rTrackingRect.SetPos( Point( nPosX, aDockingAreaRect.Top() - rTrackingRect.getHeight() ));
|
|
if ( eDockedArea == ui::DockingArea_DOCKINGAREA_TOP )
|
|
rUIElement.m_aDockedData.m_aPos.Y = 0;
|
|
else
|
|
rUIElement.m_aDockedData.m_aPos.Y = ( nMaxRowCol >= 0 ) ? nMaxRowCol+1 : 0;
|
|
rDockingOperation = DOCKOP_BEFORE_COLROW;
|
|
}
|
|
else
|
|
{
|
|
rTrackingRect.SetPos( Point( nPosX, aDockingAreaRect.Bottom() ));
|
|
if ( eDockedArea == ui::DockingArea_DOCKINGAREA_TOP )
|
|
rUIElement.m_aDockedData.m_aPos.Y = ( nMaxRowCol >= 0 ) ? nMaxRowCol+1 : 0;
|
|
else
|
|
rUIElement.m_aDockedData.m_aPos.Y = 0;
|
|
rDockingOperation = DOCKOP_AFTER_COLROW;
|
|
}
|
|
rTrackingRect.setWidth( nSize );
|
|
|
|
{
|
|
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.getHeight()) > ( nTopDockingAreaSize + nMaxDockingAreaHeight ))
|
|
nPosY = std::min( nPosY,
|
|
std::max<sal_Int32>( nTopDockingAreaSize + ( nMaxDockingAreaHeight - aTrackingRect.getHeight() ),
|
|
nTopDockingAreaSize ));
|
|
|
|
sal_Int32 nSize = std::min( nMaxDockingAreaHeight, static_cast<sal_Int32>(aTrackingRect.getHeight()) );
|
|
sal_Int32 nDockWidth = std::max( static_cast<sal_Int32>(aDockingAreaRect.getWidth()), sal_Int32( 0 ));
|
|
if ( nDockWidth == 0 )
|
|
{
|
|
sal_Int32 nPosX( std::max( aDockingAreaRect.Left(), aDockingAreaRect.Right() ));
|
|
if ( eDockedArea == ui::DockingArea_DOCKINGAREA_RIGHT )
|
|
nPosX -= rTrackingRect.getWidth();
|
|
rTrackingRect.SetPos( Point( nPosX, nPosY ));
|
|
rUIElement.m_aDockedData.m_aPos.X = 0;
|
|
}
|
|
else if ( rMousePos.X() < ( aDockingAreaRect.Left() + ( nDockWidth / 2 )))
|
|
{
|
|
rTrackingRect.SetPos( Point( aDockingAreaRect.Left() - rTrackingRect.getWidth(), nPosY ));
|
|
if ( eDockedArea == ui::DockingArea_DOCKINGAREA_LEFT )
|
|
rUIElement.m_aDockedData.m_aPos.X = 0;
|
|
else
|
|
rUIElement.m_aDockedData.m_aPos.X = ( nMaxRowCol >= 0 ) ? nMaxRowCol+1 : 0;
|
|
rDockingOperation = DOCKOP_BEFORE_COLROW;
|
|
}
|
|
else
|
|
{
|
|
rTrackingRect.SetPos( Point( aDockingAreaRect.Right(), nPosY ));
|
|
if ( eDockedArea == ui::DockingArea_DOCKINGAREA_LEFT )
|
|
rUIElement.m_aDockedData.m_aPos.X = ( nMaxRowCol >= 0 ) ? nMaxRowCol+1 : 0;
|
|
else
|
|
rUIElement.m_aDockedData.m_aPos.X = 0;
|
|
rDockingOperation = DOCKOP_AFTER_COLROW;
|
|
}
|
|
rTrackingRect.setHeight( nSize );
|
|
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
nPosY = pDockingAreaWindow->ScreenToOutputPixel(
|
|
pContainerWindow->OutputToScreenPixel( rTrackingRect.TopLeft() )).Y();
|
|
}
|
|
rUIElement.m_aDockedData.m_aPos.Y = nPosY;
|
|
}
|
|
}
|
|
|
|
framework::ToolbarLayoutManager::DockingOperation ToolbarLayoutManager::implts_determineDockingOperation(
|
|
ui::DockingArea DockingArea,
|
|
const ::tools::Rectangle& rRowColRect,
|
|
const Point& rMousePos )
|
|
{
|
|
constexpr sal_Int32 nHorzVerticalRegionSize = 6;
|
|
constexpr sal_Int32 nHorzVerticalMoveRegion = 4;
|
|
|
|
if ( rRowColRect.IsInside( rMousePos ))
|
|
{
|
|
if ( isHorizontalDockingArea( DockingArea ))
|
|
{
|
|
sal_Int32 nRegion = rRowColRect.getHeight() / nHorzVerticalRegionSize;
|
|
sal_Int32 nPosY = rRowColRect.Top() + nRegion;
|
|
|
|
if ( rMousePos.Y() < nPosY )
|
|
return ( DockingArea == ui::DockingArea_DOCKINGAREA_TOP ) ? DOCKOP_BEFORE_COLROW : DOCKOP_AFTER_COLROW;
|
|
else if ( rMousePos.Y() < ( nPosY + nRegion*nHorzVerticalMoveRegion ))
|
|
return DOCKOP_ON_COLROW;
|
|
else
|
|
return ( DockingArea == ui::DockingArea_DOCKINGAREA_TOP ) ? DOCKOP_AFTER_COLROW : DOCKOP_BEFORE_COLROW;
|
|
}
|
|
else
|
|
{
|
|
sal_Int32 nRegion = rRowColRect.getWidth() / nHorzVerticalRegionSize;
|
|
sal_Int32 nPosX = rRowColRect.Left() + nRegion;
|
|
|
|
if ( rMousePos.X() < nPosX )
|
|
return ( DockingArea == ui::DockingArea_DOCKINGAREA_LEFT ) ? DOCKOP_BEFORE_COLROW : DOCKOP_AFTER_COLROW;
|
|
else if ( rMousePos.X() < ( nPosX + nRegion*nHorzVerticalMoveRegion ))
|
|
return DOCKOP_ON_COLROW;
|
|
else
|
|
return ( DockingArea == ui::DockingArea_DOCKINGAREA_LEFT ) ? DOCKOP_AFTER_COLROW : DOCKOP_BEFORE_COLROW;
|
|
}
|
|
}
|
|
else
|
|
return DOCKOP_ON_COLROW;
|
|
}
|
|
|
|
::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.getWidth()) > rContainerWinSize.Width() )
|
|
nPosX = std::min( nPosX,
|
|
std::max( sal_Int32( rContainerWinSize.Width() - rTrackingRect.getWidth() ),
|
|
sal_Int32( 0 )));
|
|
|
|
sal_Int32 nSize = std::min( rContainerWinSize.Width(), rTrackingRect.getWidth() );
|
|
|
|
aTrackingRect.SetPos( ::Point( nPosX, rRowColumnRect.Top() ));
|
|
aTrackingRect.setWidth( nSize );
|
|
aTrackingRect.setHeight( rRowColumnRect.getHeight() );
|
|
|
|
// Set virtual position
|
|
rUIElement.m_aDockedData.m_aPos.X = nPosX;
|
|
rUIElement.m_aDockedData.m_aPos.Y = nRowCol;
|
|
}
|
|
else
|
|
{
|
|
sal_Int32 nMaxDockingAreaHeight = std::max<sal_Int32>( 0, nMaxLeftRightDockAreaSize );
|
|
|
|
sal_Int32 nPosY( std::max<sal_Int32>( aTrackingRect.Top(), nTopDockingAreaSize ));
|
|
if (( nPosY + aTrackingRect.getHeight()) > ( nTopDockingAreaSize + nMaxDockingAreaHeight ))
|
|
nPosY = std::min( nPosY,
|
|
std::max<sal_Int32>( nTopDockingAreaSize + ( nMaxDockingAreaHeight - aTrackingRect.getHeight() ),
|
|
nTopDockingAreaSize ));
|
|
|
|
sal_Int32 nSize = std::min( nMaxDockingAreaHeight, static_cast<sal_Int32>(aTrackingRect.getHeight()) );
|
|
|
|
aTrackingRect.SetPos( ::Point( rRowColumnRect.Left(), nPosY ));
|
|
aTrackingRect.setWidth( rRowColumnRect.getWidth() );
|
|
aTrackingRect.setHeight( nSize );
|
|
|
|
aReadGuard.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;
|
|
}
|
|
|
|
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 : std::as_const(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, makeAny( 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 > xContainerWindow( m_xContainerWindow );
|
|
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 = 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.IsInside( aMousePos ))
|
|
eDockingArea = ui::DockingArea_DOCKINGAREA_TOP;
|
|
else if ( aHotZoneBottomDockRect.IsInside( aMousePos ))
|
|
eDockingArea = ui::DockingArea_DOCKINGAREA_BOTTOM;
|
|
else if ( aHotZoneLeftDockRect.IsInside( aMousePos ))
|
|
eDockingArea = ui::DockingArea_DOCKINGAREA_LEFT;
|
|
else if ( aHotZoneRightDockRect.IsInside( aMousePos ))
|
|
eDockingArea = ui::DockingArea_DOCKINGAREA_RIGHT;
|
|
|
|
// Higher priority for movements inside the real docking area
|
|
if ( aTopDockRect.IsInside( aMousePos ))
|
|
eDockingArea = ui::DockingArea_DOCKINGAREA_TOP;
|
|
else if ( aBottomDockRect.IsInside( aMousePos ))
|
|
eDockingArea = ui::DockingArea_DOCKINGAREA_BOTTOM;
|
|
else if ( aLeftDockRect.IsInside( aMousePos ))
|
|
eDockingArea = ui::DockingArea_DOCKINGAREA_LEFT;
|
|
else if ( aRightDockRect.IsInside( aMousePos ))
|
|
eDockingArea = ui::DockingArea_DOCKINGAREA_RIGHT;
|
|
|
|
// Determine if we have a toolbar and set alignment according to the docking area!
|
|
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.getWidth(), aNewDockingRect.getHeight() );
|
|
}
|
|
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 = AWTPoint(pContainerWindow->ScreenToOutputPixel(VCLPoint(e.MousePos)));
|
|
aDockingData.TrackingRectangle.Height = aFloatSize.Height;
|
|
aDockingData.TrackingRectangle.Width = aFloatSize.Width;
|
|
}
|
|
else
|
|
{
|
|
aFloatSize = AWTSize(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 = AWTPoint(pContainerWindow->ScreenToOutputPixel(VCLPoint(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() )
|
|
{
|
|
if ( !bDockingInProgress )
|
|
{
|
|
uno::Reference< awt::XDockableWindow > xDockWindow( xWindow, uno::UNO_QUERY );
|
|
if ( xDockWindow->isFloating() )
|
|
{
|
|
{
|
|
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 = AWTPoint(pToolBox->GetPosPixel());
|
|
aUIDockingElement.m_aFloatingData.m_aSize = AWTSize(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 = AWTSize(pToolBox->CalcFloatingWindowSizePixel());
|
|
else if ( pWindow )
|
|
aUIDockingElement.m_aFloatingData.m_aSize = AWTSize(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( AWTSize( 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( "ConfigurationSource", makeAny( 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("UIName") >>= 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( "ConfigurationSource" );
|
|
uno::Reference< uno::XInterface > xElementCfgMgr;
|
|
uno::Reference< beans::XPropertySet > xPropSet( xElementSettings, uno::UNO_QUERY );
|
|
|
|
if ( xPropSet.is() )
|
|
xPropSet->getPropertyValue( aConfigSourcePropName ) >>= xElementCfgMgr;
|
|
|
|
if ( !xElementCfgMgr.is() )
|
|
return;
|
|
|
|
// Check if the same UI configuration manager has changed => check further
|
|
if ( rEvent.Source == xElementCfgMgr )
|
|
{
|
|
// Same UI configuration manager where our element has its settings
|
|
if ( rEvent.Source == uno::Reference< uno::XInterface >( xDocCfgMgr, uno::UNO_QUERY ))
|
|
{
|
|
// document settings removed
|
|
if ( xModuleCfgMgr->hasSettings( rEvent.ResourceURL ))
|
|
{
|
|
xPropSet->setPropertyValue( aConfigSourcePropName, makeAny( xModuleCfgMgr ));
|
|
xElementSettings->updateSettings();
|
|
return;
|
|
}
|
|
}
|
|
|
|
bNoSettings = true;
|
|
}
|
|
|
|
// No settings anymore, element must be destroyed
|
|
if ( xContainerWindow.is() && bNoSettings )
|
|
destroyToolbar( rEvent.ResourceURL );
|
|
}
|
|
|
|
void SAL_CALL ToolbarLayoutManager::elementReplaced( const ui::ConfigurationEvent& rEvent )
|
|
{
|
|
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( "ConfigurationSource" ) >>= 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();
|
|
}
|
|
|
|
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[nCount-1] = elem.m_xUIElement;
|
|
}
|
|
}
|
|
}
|
|
|
|
return aSeq;
|
|
}
|
|
|
|
bool ToolbarLayoutManager::floatToolbar( std::u16string_view rResourceURL )
|
|
{
|
|
UIElement aUIElement = implts_findToolbar( rResourceURL );
|
|
if ( aUIElement.m_xUIElement.is() )
|
|
{
|
|
try
|
|
{
|
|
uno::Reference< awt::XDockableWindow > xDockWindow( aUIElement.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
|
|
if ( xDockWindow.is() && !xDockWindow->isFloating() )
|
|
{
|
|
aUIElement.m_bFloating = true;
|
|
implts_writeWindowStateData( aUIElement );
|
|
xDockWindow->setFloatingMode( true );
|
|
|
|
implts_setLayoutDirty();
|
|
implts_setToolbar( aUIElement );
|
|
return true;
|
|
}
|
|
}
|
|
catch (const lang::DisposedException&)
|
|
{
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool ToolbarLayoutManager::lockToolbar( std::u16string_view rResourceURL )
|
|
{
|
|
UIElement aUIElement = implts_findToolbar( rResourceURL );
|
|
if ( aUIElement.m_xUIElement.is() )
|
|
{
|
|
try
|
|
{
|
|
uno::Reference< awt::XDockableWindow > xDockWindow( aUIElement.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
|
|
if ( xDockWindow.is() && !xDockWindow->isFloating() && !xDockWindow->isLocked() )
|
|
{
|
|
aUIElement.m_aDockedData.m_bLocked = true;
|
|
implts_writeWindowStateData( aUIElement );
|
|
xDockWindow->lock();
|
|
|
|
implts_setLayoutDirty();
|
|
implts_setToolbar( aUIElement );
|
|
return true;
|
|
}
|
|
}
|
|
catch (const lang::DisposedException&)
|
|
{
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool ToolbarLayoutManager::unlockToolbar( std::u16string_view rResourceURL )
|
|
{
|
|
UIElement aUIElement = implts_findToolbar( rResourceURL );
|
|
if ( aUIElement.m_xUIElement.is() )
|
|
{
|
|
try
|
|
{
|
|
uno::Reference< awt::XDockableWindow > xDockWindow( aUIElement.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
|
|
if ( xDockWindow.is() && !xDockWindow->isFloating() && xDockWindow->isLocked() )
|
|
{
|
|
aUIElement.m_aDockedData.m_bLocked = false;
|
|
implts_writeWindowStateData( aUIElement );
|
|
xDockWindow->unlock();
|
|
|
|
implts_setLayoutDirty();
|
|
implts_setToolbar( aUIElement );
|
|
return true;
|
|
}
|
|
}
|
|
catch (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: */
|