Files
loongoffice/framework/source/layoutmanager/layoutmanager.cxx
Patrick Luby c0d4bed050 Related: tdf#161623 don't set the menubar to null on macOS
When a window enters LibreOffice's internal full screen mode,
the vcl code will hide the macOS menubar. However, if the
window is also in native full screen mode, macOS will force
the menubar to be visible.

While the vcl code already partially handles this case by
disabling all menu items when in LibreOffice's internal full
screen mode, the problem is that any submenus that were not
displayed before setting the menubar to null will show all
menu items with no title.

A simple way to reproduce this bug is to open a new Writer
or Calc document and do the following:
- Switch the window to LibreOffice's internal full screen
  mode by manually selecting the View > Full Screen menu
  item (the bug does not occur if its key shortcut is
  pressed)
- Switch the window to native full screen mode
- Click on the menubar and note that many of the submenus
  are displayed with menu items, but none of the menu items
  have a title

So, we need to keep the menubar visible and rely on the vcl
code to disable all menu items.

Change-Id: I97fc63a8cd028c029a71899090185bc09d4aa492
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/183508
Reviewed-by: Patrick Luby <guibomacdev@gmail.com>
Tested-by: Jenkins
(cherry picked from commit 159be5c95178088c02ad863a3ad6f0a01b3ecc7f)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/183509
Reviewed-by: Adolfo Jayme Barrientos <fitojb@ubuntu.com>
2025-03-31 20:02:24 +02:00

3101 lines
108 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 <memory>
#include <config_feature_desktop.h>
#include <properties.h>
#include <services/layoutmanager.hxx>
#include "helpers.hxx"
#include <framework/sfxhelperfunctions.hxx>
#include <uielement/menubarwrapper.hxx>
#include <uielement/progressbarwrapper.hxx>
#include <uiconfiguration/globalsettings.hxx>
#include <uiconfiguration/windowstateproperties.hxx>
#include "toolbarlayoutmanager.hxx"
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/beans/PropertyAttribute.hpp>
#include <com/sun/star/frame/ModuleManager.hpp>
#include <com/sun/star/frame/XModel.hpp>
#include <com/sun/star/frame/FrameAction.hpp>
#include <com/sun/star/awt/PosSize.hpp>
#include <com/sun/star/awt/XDevice.hpp>
#include <com/sun/star/ui/theModuleUIConfigurationManagerSupplier.hpp>
#include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp>
#include <com/sun/star/ui/theWindowStateConfiguration.hpp>
#include <com/sun/star/ui/theUIElementFactoryManager.hpp>
#include <com/sun/star/container/XNameReplace.hpp>
#include <com/sun/star/container/XNameContainer.hpp>
#include <com/sun/star/frame/LayoutManagerEvents.hpp>
#include <com/sun/star/frame/XDispatchProvider.hpp>
#include <com/sun/star/frame/DispatchHelper.hpp>
#include <com/sun/star/lang/DisposedException.hpp>
#include <com/sun/star/util/URLTransformer.hpp>
#include <comphelper/lok.hxx>
#include <comphelper/propertyvalue.hxx>
#include <vcl/status.hxx>
#include <vcl/settings.hxx>
#include <vcl/window.hxx>
#include <vcl/svapp.hxx>
#include <toolkit/helper/vclunohelper.hxx>
#include <toolkit/awt/vclxmenu.hxx>
#include <comphelper/uno3.hxx>
#include <officecfg/Office/Compatibility.hxx>
#include <rtl/ref.hxx>
#include <sal/log.hxx>
#include <o3tl/string_view.hxx>
#include <algorithm>
// using namespace
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::util;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::container;
using namespace ::com::sun::star::ui;
using namespace ::com::sun::star::frame;
constexpr OUString STATUS_BAR_ALIAS = u"private:resource/statusbar/statusbar"_ustr;
namespace framework
{
IMPLEMENT_FORWARD_XTYPEPROVIDER2( LayoutManager, LayoutManager_Base, LayoutManager_PBase )
IMPLEMENT_FORWARD_XINTERFACE2( LayoutManager, LayoutManager_Base, LayoutManager_PBase )
LayoutManager::LayoutManager( const Reference< XComponentContext >& xContext ) :
::cppu::OBroadcastHelperVar< ::cppu::OMultiTypeInterfaceContainerHelper, ::cppu::OMultiTypeInterfaceContainerHelper::keyType >(m_aMutex)
, LayoutManager_PBase( *static_cast< ::cppu::OBroadcastHelper* >(this) )
, m_xContext( xContext )
, m_xURLTransformer( URLTransformer::create(xContext) )
, m_nLockCount( 0 )
, m_bInplaceMenuSet( false )
, m_bMenuVisible( true )
, m_bVisible( true )
, m_bParentWindowVisible( false )
, m_bMustDoLayout( true )
#if HAVE_FEATURE_DESKTOP
, m_bAutomaticToolbars( true )
#else
, m_bAutomaticToolbars( false )
#endif
, m_bHideCurrentUI( false )
, m_bGlobalSettings( false )
, m_bPreserveContentSize( false )
, m_bMenuBarCloseButton( false )
, m_xModuleManager( ModuleManager::create( xContext ))
, m_xUIElementFactoryManager( ui::theUIElementFactoryManager::get(xContext) )
, m_xPersistentWindowStateSupplier( ui::theWindowStateConfiguration::get( xContext ) )
, m_aAsyncLayoutTimer( "framework::LayoutManager m_aAsyncLayoutTimer" )
, m_aListenerContainer( m_aMutex )
, m_bInSetCurrentUIVisibility( false )
{
// Initialize statusbar member
m_aStatusBarElement.m_aType = "statusbar";
m_aStatusBarElement.m_aName = STATUS_BAR_ALIAS;
if (!comphelper::LibreOfficeKit::isActive())
{
m_xToolbarManager = new ToolbarLayoutManager( xContext, Reference<XUIElementFactory>(m_xUIElementFactoryManager, UNO_QUERY_THROW), this );
}
m_aAsyncLayoutTimer.SetPriority( TaskPriority::HIGH_IDLE );
m_aAsyncLayoutTimer.SetTimeout( 50 );
m_aAsyncLayoutTimer.SetInvokeHandler( LINK( this, LayoutManager, AsyncLayoutHdl ) );
registerProperty( LAYOUTMANAGER_PROPNAME_ASCII_AUTOMATICTOOLBARS, LAYOUTMANAGER_PROPHANDLE_AUTOMATICTOOLBARS, css::beans::PropertyAttribute::TRANSIENT, &m_bAutomaticToolbars, cppu::UnoType<decltype(m_bAutomaticToolbars)>::get() );
registerProperty( LAYOUTMANAGER_PROPNAME_ASCII_HIDECURRENTUI, LAYOUTMANAGER_PROPHANDLE_HIDECURRENTUI, beans::PropertyAttribute::TRANSIENT, &m_bHideCurrentUI, cppu::UnoType<decltype(m_bHideCurrentUI)>::get() );
registerProperty( LAYOUTMANAGER_PROPNAME_ASCII_LOCKCOUNT, LAYOUTMANAGER_PROPHANDLE_LOCKCOUNT, beans::PropertyAttribute::TRANSIENT | beans::PropertyAttribute::READONLY, &m_nLockCount, cppu::UnoType<decltype(m_nLockCount)>::get() );
registerProperty( LAYOUTMANAGER_PROPNAME_MENUBARCLOSER, LAYOUTMANAGER_PROPHANDLE_MENUBARCLOSER, beans::PropertyAttribute::TRANSIENT, &m_bMenuBarCloseButton, cppu::UnoType<decltype(m_bMenuBarCloseButton)>::get() );
registerPropertyNoMember( LAYOUTMANAGER_PROPNAME_ASCII_REFRESHVISIBILITY, LAYOUTMANAGER_PROPHANDLE_REFRESHVISIBILITY, beans::PropertyAttribute::TRANSIENT, cppu::UnoType<bool>::get(), css::uno::Any(false) );
registerProperty( LAYOUTMANAGER_PROPNAME_ASCII_PRESERVE_CONTENT_SIZE, LAYOUTMANAGER_PROPHANDLE_PRESERVE_CONTENT_SIZE, beans::PropertyAttribute::TRANSIENT, &m_bPreserveContentSize, cppu::UnoType<decltype(m_bPreserveContentSize)>::get() );
registerPropertyNoMember( LAYOUTMANAGER_PROPNAME_ASCII_REFRESHTOOLTIP, LAYOUTMANAGER_PROPHANDLE_REFRESHTOOLTIP, beans::PropertyAttribute::TRANSIENT, cppu::UnoType<bool>::get(), css::uno::Any(false) );
}
LayoutManager::~LayoutManager()
{
m_aAsyncLayoutTimer.Stop();
setDockingAreaAcceptor(nullptr);
m_pGlobalSettings.reset();
}
void LayoutManager::implts_createMenuBar(const OUString& rMenuBarName)
{
SolarMutexGuard aWriteLock;
// Create a customized menu if compatibility mode is on
if (m_aModuleIdentifier == "com.sun.star.text.TextDocument" && officecfg::Office::Compatibility::View::MSCompatibleFormsMenu::get())
{
implts_createMSCompatibleMenuBar(rMenuBarName);
}
// Create the default menubar otherwise
if (m_bInplaceMenuSet || m_xMenuBar.is())
return;
m_xMenuBar.set( static_cast< MenuBarWrapper* >(implts_createElement( rMenuBarName ).get()) );
if ( !m_xMenuBar.is() )
return;
SystemWindow* pSysWindow = getTopSystemWindow( m_xContainerWindow );
if ( !pSysWindow )
return;
Reference< awt::XMenuBar > xMenuBar;
try
{
m_xMenuBar->getPropertyValue(u"XMenuBar"_ustr) >>= xMenuBar;
}
catch (const beans::UnknownPropertyException&)
{
}
catch (const lang::WrappedTargetException&)
{
}
if ( !xMenuBar.is() )
return;
VCLXMenu* pAwtMenuBar = dynamic_cast<VCLXMenu*>( xMenuBar.get() );
if ( pAwtMenuBar )
{
MenuBar* pMenuBar = static_cast<MenuBar*>(pAwtMenuBar->GetMenu());
if ( pMenuBar )
{
pSysWindow->SetMenuBar(pMenuBar);
pMenuBar->SetDisplayable( m_bMenuVisible );
implts_updateMenuBarClose();
}
}
}
// Internal helper function
void LayoutManager::impl_clearUpMenuBar()
{
implts_lock();
// Clear up VCL menu bar to prepare shutdown
if ( m_xContainerWindow.is() )
{
SolarMutexGuard aGuard;
SystemWindow* pSysWindow = getTopSystemWindow( m_xContainerWindow );
if ( pSysWindow )
{
MenuBar* pSetMenuBar = nullptr;
if ( m_xInplaceMenuBar.is() )
pSetMenuBar = static_cast<MenuBar *>(m_xInplaceMenuBar->GetMenuBar());
else
{
Reference< awt::XMenuBar > xMenuBar;
if ( m_xMenuBar.is() )
{
try
{
m_xMenuBar->getPropertyValue(u"XMenuBar"_ustr) >>= xMenuBar;
}
catch (const beans::UnknownPropertyException&)
{
}
catch (const lang::WrappedTargetException&)
{
}
}
VCLXMenu* pAwtMenuBar = dynamic_cast<VCLXMenu*>( xMenuBar.get() );
if ( pAwtMenuBar )
pSetMenuBar = static_cast<MenuBar*>(pAwtMenuBar->GetMenu());
}
MenuBar* pTopMenuBar = pSysWindow->GetMenuBar();
if ( pSetMenuBar == pTopMenuBar )
pSysWindow->SetMenuBar( nullptr );
}
}
// reset inplace menubar manager
VclPtr<Menu> pMenuBar;
if (m_xInplaceMenuBar.is())
{
pMenuBar = m_xInplaceMenuBar->GetMenuBar();
m_xInplaceMenuBar->dispose();
m_xInplaceMenuBar.clear();
}
pMenuBar.disposeAndClear();
m_bInplaceMenuSet = false;
if ( m_xMenuBar.is() )
{
m_xMenuBar->dispose();
m_xMenuBar.clear();
}
implts_unlock();
}
void LayoutManager::implts_lock()
{
SolarMutexGuard g;
++m_nLockCount;
}
bool LayoutManager::implts_unlock()
{
SolarMutexGuard g;
m_nLockCount = std::max( m_nLockCount-1, static_cast<sal_Int32>(0) );
return ( m_nLockCount == 0 );
}
void LayoutManager::implts_reset( bool bAttached )
{
/* SAFE AREA ----------------------------------------------------------------------------------------------- */
SolarMutexClearableGuard aReadLock;
Reference< XFrame > xFrame = m_xFrame;
Reference< awt::XWindow > xContainerWindow( m_xContainerWindow );
Reference< XUIConfiguration > xModuleCfgMgr( m_xModuleCfgMgr, UNO_QUERY );
Reference< XUIConfiguration > xDocCfgMgr( m_xDocCfgMgr, UNO_QUERY );
Reference< XNameAccess > xPersistentWindowState( m_xPersistentWindowState );
Reference< XComponentContext > xContext( m_xContext );
Reference< XNameAccess > xPersistentWindowStateSupplier( m_xPersistentWindowStateSupplier );
rtl::Reference<ToolbarLayoutManager> xToolbarManager( m_xToolbarManager );
OUString aModuleIdentifier( m_aModuleIdentifier );
bool bAutomaticToolbars( m_bAutomaticToolbars );
aReadLock.clear();
/* SAFE AREA ----------------------------------------------------------------------------------------------- */
implts_lock();
Reference< XModel > xModel;
if ( xFrame.is() )
{
if ( bAttached )
{
OUString aOldModuleIdentifier( aModuleIdentifier );
try
{
aModuleIdentifier = m_xModuleManager->identify( xFrame );
}
catch( const Exception& ) {}
if ( !aModuleIdentifier.isEmpty() && aOldModuleIdentifier != aModuleIdentifier )
{
Reference< XModuleUIConfigurationManagerSupplier > xModuleCfgSupplier;
if ( xContext.is() )
xModuleCfgSupplier = theModuleUIConfigurationManagerSupplier::get( xContext );
if ( xModuleCfgMgr.is() )
{
try
{
// Remove listener to old module ui configuration manager
xModuleCfgMgr->removeConfigurationListener( Reference< XUIConfigurationListener >(this) );
}
catch (const Exception&)
{
}
}
try
{
// Add listener to new module ui configuration manager
xModuleCfgMgr.set( xModuleCfgSupplier->getUIConfigurationManager( aModuleIdentifier ), UNO_QUERY );
if ( xModuleCfgMgr.is() )
xModuleCfgMgr->addConfigurationListener( Reference< XUIConfigurationListener >(this) );
}
catch (const Exception&)
{
}
try
{
// Retrieve persistent window state reference for our new module
if ( xPersistentWindowStateSupplier.is() )
xPersistentWindowStateSupplier->getByName( aModuleIdentifier ) >>= xPersistentWindowState;
}
catch (const NoSuchElementException&)
{
}
catch (const WrappedTargetException&)
{
}
}
xModel = impl_getModelFromFrame( xFrame );
if ( xModel.is() )
{
Reference< XUIConfigurationManagerSupplier > xUIConfigurationManagerSupplier( xModel, UNO_QUERY );
if ( xUIConfigurationManagerSupplier.is() )
{
if ( xDocCfgMgr.is() )
{
try
{
// Remove listener to old ui configuration manager
xDocCfgMgr->removeConfigurationListener( Reference< XUIConfigurationListener >(this) );
}
catch (const Exception&)
{
}
}
try
{
xDocCfgMgr.set( xUIConfigurationManagerSupplier->getUIConfigurationManager(), UNO_QUERY );
if ( xDocCfgMgr.is() )
xDocCfgMgr->addConfigurationListener( Reference< XUIConfigurationListener >(this) );
}
catch (const Exception&)
{
}
}
}
}
else
{
// Remove configuration listeners before we can release our references
if ( xModuleCfgMgr.is() )
{
try
{
xModuleCfgMgr->removeConfigurationListener(
Reference< XUIConfigurationListener >(this) );
}
catch (const Exception&)
{
}
}
if ( xDocCfgMgr.is() )
{
try
{
xDocCfgMgr->removeConfigurationListener(
Reference< XUIConfigurationListener >(this) );
}
catch (const Exception&)
{
}
}
// Release references to our configuration managers as we currently don't have
// an attached module.
xModuleCfgMgr.clear();
xDocCfgMgr.clear();
xPersistentWindowState.clear();
aModuleIdentifier.clear();
}
Reference< XUIConfigurationManager > xModCfgMgr( xModuleCfgMgr, UNO_QUERY );
Reference< XUIConfigurationManager > xDokCfgMgr( xDocCfgMgr, UNO_QUERY );
/* SAFE AREA ----------------------------------------------------------------------------------------------- */
SolarMutexClearableGuard aWriteLock;
m_aDockingArea = awt::Rectangle();
m_aModuleIdentifier = aModuleIdentifier;
m_xModuleCfgMgr = xModCfgMgr;
m_xDocCfgMgr = xDokCfgMgr;
m_xPersistentWindowState = xPersistentWindowState;
m_aStatusBarElement.m_bStateRead = false; // reset state to read data again!
aWriteLock.clear();
/* SAFE AREA ----------------------------------------------------------------------------------------------- */
// reset/notify toolbar layout manager
if ( xToolbarManager.is() )
{
if ( bAttached )
{
xToolbarManager->attach( xFrame, xModCfgMgr, xDokCfgMgr, xPersistentWindowState );
uno::Reference< awt::XVclWindowPeer > xParent( xContainerWindow, UNO_QUERY );
xToolbarManager->setParentWindow( xParent );
if ( bAutomaticToolbars )
xToolbarManager->createStaticToolbars();
}
else
{
xToolbarManager->reset();
implts_destroyElements();
}
}
}
implts_unlock();
}
bool LayoutManager::implts_isEmbeddedLayoutManager() const
{
SolarMutexClearableGuard aReadLock;
Reference< XFrame > xFrame = m_xFrame;
Reference< awt::XWindow > xContainerWindow( m_xContainerWindow );
aReadLock.clear();
Reference< awt::XWindow > xFrameContainerWindow = xFrame->getContainerWindow();
return xFrameContainerWindow != xContainerWindow;
}
void LayoutManager::implts_destroyElements()
{
SolarMutexResettableGuard aWriteLock;
ToolbarLayoutManager* pToolbarManager = m_xToolbarManager.get();
aWriteLock.clear();
if ( pToolbarManager )
pToolbarManager->destroyToolbars();
implts_destroyStatusBar();
aWriteLock.reset();
impl_clearUpMenuBar();
aWriteLock.clear();
}
void LayoutManager::implts_toggleFloatingUIElementsVisibility( bool bActive )
{
SolarMutexClearableGuard aReadLock;
ToolbarLayoutManager* pToolbarManager = m_xToolbarManager.get();
aReadLock.clear();
if ( pToolbarManager )
pToolbarManager->setFloatingToolbarsVisibility( bActive );
}
uno::Reference< ui::XUIElement > LayoutManager::implts_findElement( std::u16string_view aName )
{
OUString aElementType;
OUString aElementName;
parseResourceURL( aName, aElementType, aElementName );
if ( aElementType.equalsIgnoreAsciiCase("menubar") &&
aElementName.equalsIgnoreAsciiCase("menubar") )
return m_xMenuBar;
else if (( aElementType.equalsIgnoreAsciiCase("statusbar") &&
aElementName.equalsIgnoreAsciiCase("statusbar") ) ||
( m_aStatusBarElement.m_aName == aName ))
return m_aStatusBarElement.m_xUIElement;
else if ( aElementType.equalsIgnoreAsciiCase("progressbar") &&
aElementName.equalsIgnoreAsciiCase("progressbar") )
return m_aProgressBarElement.m_xUIElement;
return uno::Reference< ui::XUIElement >();
}
bool LayoutManager::implts_readWindowStateData( const OUString& aName, UIElement& rElementData )
{
return readWindowStateData( aName, rElementData, m_xPersistentWindowState,
m_pGlobalSettings, m_bGlobalSettings, m_xContext );
}
bool LayoutManager::readWindowStateData( const OUString& aName, UIElement& rElementData,
const Reference< XNameAccess > &rPersistentWindowState,
std::unique_ptr<GlobalSettings> &rGlobalSettings, bool &bInGlobalSettings,
const Reference< XComponentContext > &rComponentContext )
{
if ( !rPersistentWindowState.is() )
return false;
bool bGetSettingsState( false );
SolarMutexClearableGuard aWriteLock;
bool bGlobalSettings( bInGlobalSettings );
if ( rGlobalSettings == nullptr )
{
rGlobalSettings.reset( new GlobalSettings( rComponentContext ) );
bGetSettingsState = true;
}
GlobalSettings* pGlobalSettings = rGlobalSettings.get();
aWriteLock.clear();
try
{
Sequence< PropertyValue > aWindowState;
if ( rPersistentWindowState->hasByName( aName ) && (rPersistentWindowState->getByName( aName ) >>= aWindowState) )
{
bool bValue( false );
for (PropertyValue const& rProp : aWindowState)
{
if ( rProp.Name == WINDOWSTATE_PROPERTY_DOCKED )
{
if ( rProp.Value >>= bValue )
rElementData.m_bFloating = !bValue;
}
else if ( rProp.Name == WINDOWSTATE_PROPERTY_VISIBLE )
{
if ( rProp.Value >>= bValue )
rElementData.m_bVisible = bValue;
}
else if ( rProp.Name == WINDOWSTATE_PROPERTY_DOCKINGAREA )
{
ui::DockingArea eDockingArea;
if ( rProp.Value >>= eDockingArea )
rElementData.m_aDockedData.m_nDockedArea = eDockingArea;
}
else if ( rProp.Name == WINDOWSTATE_PROPERTY_DOCKPOS )
{
awt::Point aPoint;
if (rProp.Value >>= aPoint)
{
//tdf#90256 repair these broken Docking positions
if (aPoint.X < 0)
aPoint.X = SAL_MAX_INT32;
if (aPoint.Y < 0)
aPoint.Y = SAL_MAX_INT32;
rElementData.m_aDockedData.m_aPos = aPoint;
}
}
else if ( rProp.Name == WINDOWSTATE_PROPERTY_POS )
{
awt::Point aPoint;
if ( rProp.Value >>= aPoint )
rElementData.m_aFloatingData.m_aPos = aPoint;
}
else if ( rProp.Name == WINDOWSTATE_PROPERTY_SIZE )
{
awt::Size aSize;
if ( rProp.Value >>= aSize )
rElementData.m_aFloatingData.m_aSize = aSize;
}
else if ( rProp.Name == WINDOWSTATE_PROPERTY_UINAME )
rProp.Value >>= rElementData.m_aUIName;
else if ( rProp.Name == WINDOWSTATE_PROPERTY_STYLE )
{
sal_Int32 nStyle = 0;
if ( rProp.Value >>= nStyle )
rElementData.m_nStyle = static_cast<ButtonType>( nStyle );
}
else if ( rProp.Name == WINDOWSTATE_PROPERTY_LOCKED )
{
if ( rProp.Value >>= bValue )
rElementData.m_aDockedData.m_bLocked = bValue;
}
else if ( rProp.Name == WINDOWSTATE_PROPERTY_CONTEXT )
{
if ( rProp.Value >>= bValue )
rElementData.m_bContextSensitive = bValue;
}
else if ( rProp.Name == WINDOWSTATE_PROPERTY_NOCLOSE )
{
if ( rProp.Value >>= bValue )
rElementData.m_bNoClose = bValue;
}
}
}
// oversteer values with global settings
if (bGetSettingsState || bGlobalSettings)
{
if ( pGlobalSettings->HasToolbarStatesInfo())
{
{
SolarMutexGuard aWriteLock2;
bInGlobalSettings = true;
}
uno::Any aValue;
if ( pGlobalSettings->GetToolbarStateInfo(
GlobalSettings::STATEINFO_LOCKED,
aValue ))
aValue >>= rElementData.m_aDockedData.m_bLocked;
if ( pGlobalSettings->GetToolbarStateInfo(
GlobalSettings::STATEINFO_DOCKED,
aValue ))
{
bool bValue;
if ( aValue >>= bValue )
rElementData.m_bFloating = !bValue;
}
}
}
const bool bDockingSupportCrippled = !StyleSettings::GetDockingFloatsSupported();
if (bDockingSupportCrippled)
rElementData.m_bFloating = false;
return true;
}
catch (const NoSuchElementException&)
{
}
return false;
}
void LayoutManager::implts_writeWindowStateData( const OUString& aName, const UIElement& rElementData )
{
SolarMutexClearableGuard aWriteLock;
Reference< XNameAccess > xPersistentWindowState( m_xPersistentWindowState );
aWriteLock.clear();
bool bPersistent( false );
Reference< XPropertySet > xPropSet( rElementData.m_xUIElement, UNO_QUERY );
if ( xPropSet.is() )
{
try
{
// Check persistent flag of the user interface element
xPropSet->getPropertyValue(u"Persistent"_ustr) >>= bPersistent;
}
catch (const beans::UnknownPropertyException&)
{
// Non-configurable elements should at least store their dimension/position
bPersistent = true;
}
catch (const lang::WrappedTargetException&)
{
}
}
if ( !(bPersistent && xPersistentWindowState.is()) )
return;
try
{
Sequence< PropertyValue > aWindowState{
comphelper::makePropertyValue(WINDOWSTATE_PROPERTY_DOCKED, !rElementData.m_bFloating),
comphelper::makePropertyValue(WINDOWSTATE_PROPERTY_VISIBLE, rElementData.m_bVisible),
comphelper::makePropertyValue(WINDOWSTATE_PROPERTY_DOCKINGAREA,
rElementData.m_aDockedData.m_nDockedArea),
comphelper::makePropertyValue(WINDOWSTATE_PROPERTY_DOCKPOS,
rElementData.m_aDockedData.m_aPos),
comphelper::makePropertyValue(WINDOWSTATE_PROPERTY_POS,
rElementData.m_aFloatingData.m_aPos),
comphelper::makePropertyValue(WINDOWSTATE_PROPERTY_SIZE,
rElementData.m_aFloatingData.m_aSize),
comphelper::makePropertyValue(WINDOWSTATE_PROPERTY_UINAME, rElementData.m_aUIName),
comphelper::makePropertyValue(WINDOWSTATE_PROPERTY_LOCKED,
rElementData.m_aDockedData.m_bLocked)
};
if ( xPersistentWindowState->hasByName( aName ))
{
Reference< XNameReplace > xReplace( xPersistentWindowState, uno::UNO_QUERY );
xReplace->replaceByName( aName, Any( aWindowState ));
}
else
{
Reference< XNameContainer > xInsert( xPersistentWindowState, uno::UNO_QUERY );
xInsert->insertByName( aName, Any( aWindowState ));
}
}
catch (const Exception&)
{
}
}
::Size LayoutManager::implts_getContainerWindowOutputSize()
{
::Size aContainerWinSize;
vcl::Window* pContainerWindow( nullptr );
// Retrieve output size from container Window
SolarMutexGuard aGuard;
pContainerWindow = VCLUnoHelper::GetWindow( m_xContainerWindow );
if ( pContainerWindow )
aContainerWinSize = pContainerWindow->GetOutputSizePixel();
return aContainerWinSize;
}
Reference< XUIElement > LayoutManager::implts_createElement( const OUString& aName )
{
Reference< ui::XUIElement > xUIElement;
SolarMutexGuard g;
Sequence< PropertyValue > aPropSeq{ comphelper::makePropertyValue(u"Frame"_ustr, m_xFrame),
comphelper::makePropertyValue(u"Persistent"_ustr, true) };
try
{
xUIElement = m_xUIElementFactoryManager->createUIElement( aName, aPropSeq );
}
catch (const NoSuchElementException&)
{
}
catch (const IllegalArgumentException&)
{
}
return xUIElement;
}
void LayoutManager::implts_setVisibleState( bool bShow )
{
{
SolarMutexGuard aWriteLock;
m_aStatusBarElement.m_bMasterHide = !bShow;
}
implts_updateUIElementsVisibleState( bShow );
}
void LayoutManager::implts_updateUIElementsVisibleState( bool bSetVisible )
{
// notify listeners
uno::Any a;
if ( bSetVisible )
implts_notifyListeners( frame::LayoutManagerEvents::VISIBLE, a );
else
implts_notifyListeners( frame::LayoutManagerEvents::INVISIBLE, a );
SolarMutexResettableGuard aWriteLock;
rtl::Reference< MenuBarWrapper > xMenuBar = m_xMenuBar;
Reference< awt::XWindow > xContainerWindow( m_xContainerWindow );
rtl::Reference< MenuBarManager > xInplaceMenuBar( m_xInplaceMenuBar );
aWriteLock.clear();
if (( xMenuBar.is() || xInplaceMenuBar.is() ) && xContainerWindow.is() )
{
SolarMutexGuard aGuard;
MenuBar* pMenuBar( nullptr );
if ( xInplaceMenuBar.is() )
pMenuBar = static_cast<MenuBar *>(xInplaceMenuBar->GetMenuBar());
else
{
pMenuBar = static_cast<MenuBar *>(xMenuBar->GetMenuBarManager()->GetMenuBar());
}
SystemWindow* pSysWindow = getTopSystemWindow( xContainerWindow );
if ( pSysWindow )
{
if ( bSetVisible )
{
pSysWindow->SetMenuBar(pMenuBar);
}
#ifdef MACOSX
// Related: tdf#161623 don't set the menubar to null on macOS
// When a window enters LibreOffice's internal full screen mode,
// the vcl code will hide the macOS menubar. However, if the
// window is also in native full screen mode, macOS will force
// the menubar to be visible.
// While the vcl code already partially handles this case by
// disabling all menu items when in LibreOffice's internal full
// screen mode, the problem is that any submenus that were not
// displayed before setting the menubar to null will show all
// menu items with no title.
// A simple way to reproduce this bug is to open a new Writer
// or Calc document and do the following:
// - Switch the window to LibreOffice's internal full screen
// mode by manually selecting the View > Full Screen menu
// item (the bug does not occur if its key shortcut is
// pressed)
// - Switch the window to native full screen mode
// - Click on the menubar and note that many of the submenus
// are displayed with menu items, but none of the menu items
// have a title
// So, we need to keep the menubar visible and rely on the vcl
// code to disable all menu items.
else if ( m_bInSetCurrentUIVisibility )
pSysWindow->SetMenuBar(pMenuBar);
#endif
else
pSysWindow->SetMenuBar( nullptr );
}
}
bool bMustDoLayout;
// Hide/show the statusbar according to bSetVisible
if ( bSetVisible )
bMustDoLayout = !implts_showStatusBar();
else
bMustDoLayout = !implts_hideStatusBar();
aWriteLock.reset();
ToolbarLayoutManager* pToolbarManager( m_xToolbarManager.get() );
aWriteLock.clear();
if ( pToolbarManager )
{
pToolbarManager->setVisible( bSetVisible );
bMustDoLayout = pToolbarManager->isLayoutDirty();
}
if ( bMustDoLayout )
implts_doLayout_notify( false );
}
void LayoutManager::implts_setCurrentUIVisibility( bool bShow )
{
{
SolarMutexGuard aWriteLock;
if (!bShow && m_aStatusBarElement.m_bVisible && m_aStatusBarElement.m_xUIElement.is())
m_aStatusBarElement.m_bMasterHide = true;
else if (bShow && m_aStatusBarElement.m_bVisible)
m_aStatusBarElement.m_bMasterHide = false;
}
bool bOldInSetCurrentUIVisibility = m_bInSetCurrentUIVisibility;
m_bInSetCurrentUIVisibility = true;
implts_updateUIElementsVisibleState( bShow );
m_bInSetCurrentUIVisibility = bOldInSetCurrentUIVisibility;
}
void LayoutManager::implts_destroyStatusBar()
{
Reference< XComponent > xCompStatusBar;
SolarMutexClearableGuard aWriteLock;
m_aStatusBarElement.m_aName.clear();
xCompStatusBar.set( m_aStatusBarElement.m_xUIElement, UNO_QUERY );
m_aStatusBarElement.m_xUIElement.clear();
aWriteLock.clear();
if ( xCompStatusBar.is() )
xCompStatusBar->dispose();
implts_destroyProgressBar();
}
void LayoutManager::implts_createStatusBar( const OUString& aStatusBarName )
{
{
SolarMutexGuard aWriteLock;
if (!m_aStatusBarElement.m_xUIElement.is())
{
implts_readStatusBarState(aStatusBarName);
m_aStatusBarElement.m_aName = aStatusBarName;
m_aStatusBarElement.m_xUIElement = implts_createElement(aStatusBarName);
}
}
implts_createProgressBar();
}
void LayoutManager::implts_readStatusBarState( const OUString& rStatusBarName )
{
SolarMutexGuard g;
if ( !m_aStatusBarElement.m_bStateRead )
{
// Read persistent data for status bar if not yet read!
if ( implts_readWindowStateData( rStatusBarName, m_aStatusBarElement ))
m_aStatusBarElement.m_bStateRead = true;
}
}
void LayoutManager::implts_createProgressBar()
{
Reference< XUIElement > xStatusBar;
Reference< XUIElement > xProgressBar;
rtl::Reference< ProgressBarWrapper > xProgressBarBackup;
Reference< awt::XWindow > xContainerWindow;
SolarMutexResettableGuard aWriteLock;
xStatusBar = m_aStatusBarElement.m_xUIElement;
xProgressBar = m_aProgressBarElement.m_xUIElement;
xProgressBarBackup = m_xProgressBarBackup;
m_xProgressBarBackup.clear();
xContainerWindow = m_xContainerWindow;
aWriteLock.clear();
bool bRecycled = xProgressBarBackup.is();
rtl::Reference<ProgressBarWrapper> pWrapper;
if ( bRecycled )
pWrapper = xProgressBarBackup.get();
else if ( xProgressBar.is() )
pWrapper = static_cast<ProgressBarWrapper*>(xProgressBar.get());
else
pWrapper = new ProgressBarWrapper();
if ( xStatusBar.is() )
{
Reference< awt::XWindow > xWindow( xStatusBar->getRealInterface(), UNO_QUERY );
pWrapper->setStatusBar( xWindow );
}
else
{
Reference< awt::XWindow > xStatusBarWindow = pWrapper->getStatusBar();
SolarMutexGuard aGuard;
VclPtr<vcl::Window> pStatusBarWnd = VCLUnoHelper::GetWindow( xStatusBarWindow );
if ( !pStatusBarWnd )
{
VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xContainerWindow );
if ( pWindow )
{
VclPtrInstance<StatusBar> pStatusBar( pWindow, WinBits( WB_LEFT | WB_3DLOOK ) );
Reference< awt::XWindow > xStatusBarWindow2( VCLUnoHelper::GetInterface( pStatusBar ));
pWrapper->setStatusBar( xStatusBarWindow2, true );
}
}
}
/* SAFE AREA ----------------------------------------------------------------------------------------------- */
aWriteLock.reset();
m_aProgressBarElement.m_xUIElement = pWrapper;
aWriteLock.clear();
/* SAFE AREA ----------------------------------------------------------------------------------------------- */
if ( bRecycled )
implts_showProgressBar();
}
void LayoutManager::implts_backupProgressBarWrapper()
{
SolarMutexGuard g;
if (m_xProgressBarBackup.is())
return;
// safe a backup copy of the current progress!
// This copy will be used automatically inside createProgressBar() which is called
// implicitly from implts_doLayout() .-)
m_xProgressBarBackup = static_cast<ProgressBarWrapper*>(m_aProgressBarElement.m_xUIElement.get());
// remove the relation between this old progress bar and our old status bar.
// Otherwise we work on disposed items ...
// The internal used ProgressBarWrapper can handle a NULL reference.
if ( m_xProgressBarBackup.is() )
m_xProgressBarBackup->setStatusBar( Reference< awt::XWindow >() );
// prevent us from dispose() the m_aProgressBarElement.m_xUIElement inside implts_reset()
m_aProgressBarElement.m_xUIElement.clear();
}
void LayoutManager::implts_destroyProgressBar()
{
// don't remove the progressbar in general
// We must reuse it if a new status bar is created later.
// Of course there exists one backup only.
// And further this backup will be released inside our dtor.
implts_backupProgressBarWrapper();
}
void LayoutManager::implts_setStatusBarPosSize( const ::Point& rPos, const ::Size& rSize )
{
Reference< XUIElement > xStatusBar;
Reference< XUIElement > xProgressBar;
Reference< awt::XWindow > xContainerWindow;
/* SAFE AREA ----------------------------------------------------------------------------------------------- */
SolarMutexClearableGuard aReadLock;
xStatusBar = m_aStatusBarElement.m_xUIElement;
xProgressBar = m_aProgressBarElement.m_xUIElement;
xContainerWindow = m_xContainerWindow;
Reference< awt::XWindow > xWindow;
if ( xStatusBar.is() )
xWindow.set( xStatusBar->getRealInterface(), UNO_QUERY );
else if ( xProgressBar.is() )
{
ProgressBarWrapper* pWrapper = static_cast<ProgressBarWrapper*>(xProgressBar.get());
if ( pWrapper )
xWindow = pWrapper->getStatusBar();
}
aReadLock.clear();
/* SAFE AREA ----------------------------------------------------------------------------------------------- */
if ( !xWindow.is() )
return;
SolarMutexGuard aGuard;
VclPtr<vcl::Window> pParentWindow = VCLUnoHelper::GetWindow( xContainerWindow );
VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
if ( pParentWindow && ( pWindow && pWindow->GetType() == WindowType::STATUSBAR ))
{
vcl::Window* pOldParentWindow = pWindow->GetParent();
if ( pParentWindow != pOldParentWindow )
pWindow->SetParent( pParentWindow );
static_cast<StatusBar *>(pWindow.get())->SetPosSizePixel( rPos, rSize );
}
}
bool LayoutManager::implts_showProgressBar()
{
Reference< XUIElement > xStatusBar;
Reference< XUIElement > xProgressBar;
Reference< awt::XWindow > xWindow;
/* SAFE AREA ----------------------------------------------------------------------------------------------- */
SolarMutexGuard aWriteLock;
xStatusBar = m_aStatusBarElement.m_xUIElement;
xProgressBar = m_aProgressBarElement.m_xUIElement;
bool bVisible( m_bVisible );
m_aProgressBarElement.m_bVisible = true;
if ( bVisible )
{
if ( xStatusBar.is() && !m_aStatusBarElement.m_bMasterHide )
{
xWindow.set( xStatusBar->getRealInterface(), UNO_QUERY );
}
else if ( xProgressBar.is() )
{
ProgressBarWrapper* pWrapper = static_cast<ProgressBarWrapper*>(xProgressBar.get());
if ( pWrapper )
xWindow = pWrapper->getStatusBar();
}
}
VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
if ( pWindow )
{
if ( !pWindow->IsVisible() )
{
implts_setOffset( pWindow->GetSizePixel().Height() );
pWindow->Show();
implts_doLayout_notify( false );
}
return true;
}
return false;
}
bool LayoutManager::implts_hideProgressBar()
{
Reference< XUIElement > xProgressBar;
Reference< awt::XWindow > xWindow;
bool bHideStatusBar( false );
SolarMutexGuard g;
xProgressBar = m_aProgressBarElement.m_xUIElement;
bool bInternalStatusBar( false );
if ( xProgressBar.is() )
{
Reference< awt::XWindow > xStatusBar;
ProgressBarWrapper* pWrapper = static_cast<ProgressBarWrapper*>(xProgressBar.get());
if ( pWrapper )
xWindow = pWrapper->getStatusBar();
Reference< ui::XUIElement > xStatusBarElement = m_aStatusBarElement.m_xUIElement;
if ( xStatusBarElement.is() )
xStatusBar.set( xStatusBarElement->getRealInterface(), UNO_QUERY );
bInternalStatusBar = xStatusBar != xWindow;
}
m_aProgressBarElement.m_bVisible = false;
implts_readStatusBarState( STATUS_BAR_ALIAS );
bHideStatusBar = !m_aStatusBarElement.m_bVisible;
VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
if ( pWindow && pWindow->IsVisible() && ( bHideStatusBar || bInternalStatusBar ))
{
implts_setOffset( 0 );
pWindow->Hide();
implts_doLayout_notify( false );
return true;
}
return false;
}
bool LayoutManager::implts_showStatusBar( bool bStoreState )
{
SolarMutexClearableGuard aWriteLock;
Reference< ui::XUIElement > xStatusBar = m_aStatusBarElement.m_xUIElement;
if ( bStoreState )
m_aStatusBarElement.m_bVisible = true;
aWriteLock.clear();
if ( xStatusBar.is() )
{
Reference< awt::XWindow > xWindow( xStatusBar->getRealInterface(), UNO_QUERY );
SolarMutexGuard aGuard;
VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
if ( pWindow && !pWindow->IsVisible() )
{
implts_setOffset( pWindow->GetSizePixel().Height() );
pWindow->Show();
implts_doLayout_notify( false );
return true;
}
}
return false;
}
bool LayoutManager::implts_hideStatusBar( bool bStoreState )
{
SolarMutexClearableGuard aWriteLock;
Reference< ui::XUIElement > xStatusBar = m_aStatusBarElement.m_xUIElement;
if ( bStoreState )
m_aStatusBarElement.m_bVisible = false;
aWriteLock.clear();
if ( xStatusBar.is() )
{
Reference< awt::XWindow > xWindow( xStatusBar->getRealInterface(), UNO_QUERY );
SolarMutexGuard aGuard;
VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
if ( pWindow && pWindow->IsVisible() )
{
implts_setOffset( 0 );
pWindow->Hide();
implts_doLayout_notify( false );
return true;
}
}
return false;
}
void LayoutManager::implts_setOffset( const sal_Int32 nBottomOffset )
{
if ( m_xToolbarManager.is() )
m_xToolbarManager->setDockingAreaOffsets({ 0, 0, 0, nBottomOffset });
}
void LayoutManager::implts_setInplaceMenuBar( const Reference< XIndexAccess >& xMergedMenuBar )
{
/* SAFE AREA ----------------------------------------------------------------------------------------------- */
SolarMutexClearableGuard aWriteLock;
if ( m_bInplaceMenuSet )
return;
SolarMutexGuard aGuard;
// Reset old inplace menubar!
VclPtr<Menu> pOldMenuBar;
if (m_xInplaceMenuBar.is())
{
pOldMenuBar = m_xInplaceMenuBar->GetMenuBar();
m_xInplaceMenuBar->dispose();
m_xInplaceMenuBar.clear();
}
pOldMenuBar.disposeAndClear();
m_bInplaceMenuSet = false;
if ( m_xFrame.is() && m_xContainerWindow.is() )
{
Reference< XDispatchProvider > xDispatchProvider;
VclPtr<MenuBar> pMenuBar = VclPtr<MenuBar>::Create();
m_xInplaceMenuBar = new MenuBarManager( m_xContext, m_xFrame, m_xURLTransformer, xDispatchProvider, OUString(), pMenuBar, true );
m_xInplaceMenuBar->SetItemContainer( xMergedMenuBar );
SystemWindow* pSysWindow = getTopSystemWindow( m_xContainerWindow );
if ( pSysWindow )
pSysWindow->SetMenuBar(pMenuBar);
m_bInplaceMenuSet = true;
}
aWriteLock.clear();
/* SAFE AREA ----------------------------------------------------------------------------------------------- */
implts_updateMenuBarClose();
}
void LayoutManager::implts_resetInplaceMenuBar()
{
SolarMutexGuard g;
m_bInplaceMenuSet = false;
if ( m_xContainerWindow.is() )
{
SolarMutexGuard aGuard;
SystemWindow* pSysWindow = getTopSystemWindow( m_xContainerWindow );
if ( pSysWindow )
{
if ( m_xMenuBar )
pSysWindow->SetMenuBar(static_cast<MenuBar *>(m_xMenuBar->GetMenuBarManager()->GetMenuBar()));
else
pSysWindow->SetMenuBar(nullptr);
}
}
// Remove inplace menu bar
VclPtr<Menu> pMenuBar;
if (m_xInplaceMenuBar.is())
{
pMenuBar = m_xInplaceMenuBar->GetMenuBar();
m_xInplaceMenuBar->dispose();
m_xInplaceMenuBar.clear();
}
pMenuBar.disposeAndClear();
}
void SAL_CALL LayoutManager::attachFrame( const Reference< XFrame >& xFrame )
{
SolarMutexGuard g;
m_xFrame = xFrame;
}
void SAL_CALL LayoutManager::reset()
{
implts_reset( true );
}
// XMenuBarMergingAcceptor
sal_Bool SAL_CALL LayoutManager::setMergedMenuBar(
const Reference< XIndexAccess >& xMergedMenuBar )
{
implts_setInplaceMenuBar( xMergedMenuBar );
uno::Any a;
implts_notifyListeners( frame::LayoutManagerEvents::MERGEDMENUBAR, a );
return true;
}
void SAL_CALL LayoutManager::removeMergedMenuBar()
{
implts_resetInplaceMenuBar();
}
awt::Rectangle SAL_CALL LayoutManager::getCurrentDockingArea()
{
SolarMutexGuard g;
return m_aDockingArea;
}
Reference< XDockingAreaAcceptor > SAL_CALL LayoutManager::getDockingAreaAcceptor()
{
SolarMutexGuard g;
return m_xDockingAreaAcceptor;
}
void SAL_CALL LayoutManager::setDockingAreaAcceptor( const Reference< ui::XDockingAreaAcceptor >& xDockingAreaAcceptor )
{
/* SAFE AREA ----------------------------------------------------------------------------------------------- */
SolarMutexClearableGuard aWriteLock;
if (( m_xDockingAreaAcceptor == xDockingAreaAcceptor ) || !m_xFrame.is() )
return;
// IMPORTANT: Be sure to stop layout timer if don't have a docking area acceptor!
if ( !xDockingAreaAcceptor.is() )
m_aAsyncLayoutTimer.Stop();
bool bAutomaticToolbars( m_bAutomaticToolbars );
ToolbarLayoutManager* pToolbarManager = m_xToolbarManager.get();
if ( !xDockingAreaAcceptor.is() )
m_aAsyncLayoutTimer.Stop();
// Remove listener from old docking area acceptor
if ( m_xDockingAreaAcceptor.is() )
{
Reference< awt::XWindow > xWindow( m_xDockingAreaAcceptor->getContainerWindow() );
if ( xWindow.is() && ( m_xFrame->getContainerWindow() != m_xContainerWindow || !xDockingAreaAcceptor.is() ) )
xWindow->removeWindowListener( Reference< awt::XWindowListener >(this) );
m_aDockingArea = awt::Rectangle();
if ( pToolbarManager )
pToolbarManager->resetDockingArea();
VclPtr<vcl::Window> pContainerWindow = VCLUnoHelper::GetWindow( xWindow );
if ( pContainerWindow )
pContainerWindow->RemoveChildEventListener( LINK( this, LayoutManager, WindowEventListener ) );
}
m_xDockingAreaAcceptor = xDockingAreaAcceptor;
if ( m_xDockingAreaAcceptor.is() )
{
m_aDockingArea = awt::Rectangle();
m_xContainerWindow = m_xDockingAreaAcceptor->getContainerWindow();
m_xContainerTopWindow.set( m_xContainerWindow, UNO_QUERY );
m_xContainerWindow->addWindowListener( Reference< awt::XWindowListener >(this) );
// we always must keep a connection to the window of our frame for resize events
if ( m_xContainerWindow != m_xFrame->getContainerWindow() )
m_xFrame->getContainerWindow()->addWindowListener( Reference< awt::XWindowListener >(this) );
// #i37884# set initial visibility state - in the plugin case the container window is already shown
// and we get no notification anymore
{
VclPtr<vcl::Window> pContainerWindow = VCLUnoHelper::GetWindow( m_xContainerWindow );
if( pContainerWindow )
m_bParentWindowVisible = pContainerWindow->IsVisible();
}
}
aWriteLock.clear();
/* SAFE AREA ----------------------------------------------------------------------------------------------- */
if ( xDockingAreaAcceptor.is() )
{
SolarMutexGuard aGuard;
// Add layout manager as listener to get notifications about toolbar button activities
VclPtr<vcl::Window> pContainerWindow = VCLUnoHelper::GetWindow( m_xContainerWindow );
if ( pContainerWindow )
pContainerWindow->AddChildEventListener( LINK( this, LayoutManager, WindowEventListener ) );
// We have now a new container window, reparent all child windows!
implts_reparentChildWindows();
}
else
implts_destroyElements(); // remove all elements
if ( pToolbarManager && xDockingAreaAcceptor.is() )
{
if ( bAutomaticToolbars )
{
lock();
pToolbarManager->createStaticToolbars();
unlock();
}
implts_doLayout( true, false );
}
}
void LayoutManager::implts_reparentChildWindows()
{
SolarMutexResettableGuard aWriteLock;
UIElement aStatusBarElement = m_aStatusBarElement;
uno::Reference< awt::XWindow > xContainerWindow = m_xContainerWindow;
aWriteLock.clear();
uno::Reference< awt::XWindow > xStatusBarWindow;
if ( aStatusBarElement.m_xUIElement.is() )
{
try
{
xStatusBarWindow.set( aStatusBarElement.m_xUIElement->getRealInterface(), UNO_QUERY );
}
catch (const RuntimeException&)
{
throw;
}
catch (const Exception&)
{
}
}
if ( xStatusBarWindow.is() )
{
SolarMutexGuard aGuard;
VclPtr<vcl::Window> pContainerWindow = VCLUnoHelper::GetWindow( xContainerWindow );
VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xStatusBarWindow );
if ( pWindow && pContainerWindow )
pWindow->SetParent( pContainerWindow );
}
implts_resetMenuBar();
aWriteLock.reset();
ToolbarLayoutManager* pToolbarManager = m_xToolbarManager.get();
if ( pToolbarManager )
pToolbarManager->setParentWindow( uno::Reference< awt::XVclWindowPeer >( xContainerWindow, uno::UNO_QUERY ));
aWriteLock.clear();
}
uno::Reference< ui::XUIElement > LayoutManager::implts_createDockingWindow( const OUString& aElementName )
{
Reference< XUIElement > xUIElement = implts_createElement( aElementName );
return xUIElement;
}
IMPL_LINK( LayoutManager, WindowEventListener, VclWindowEvent&, rEvent, void )
{
vcl::Window* pWindow = rEvent.GetWindow();
if ( pWindow && pWindow->GetType() == WindowType::TOOLBOX )
{
SolarMutexClearableGuard aReadLock;
ToolbarLayoutManager* pToolbarManager( m_xToolbarManager.get() );
aReadLock.clear();
if ( pToolbarManager )
pToolbarManager->childWindowEvent( &rEvent );
}
}
void SAL_CALL LayoutManager::createElement( const OUString& aName )
{
SAL_INFO( "fwk", "LayoutManager::createElement " << aName );
SolarMutexClearableGuard aReadLock;
Reference< XFrame > xFrame = m_xFrame;
aReadLock.clear();
if ( !xFrame.is() )
return;
/* SAFE AREA ----------------------------------------------------------------------------------------------- */
SolarMutexClearableGuard aWriteLock;
bool bMustBeLayouted( false );
bool bNotify( false );
bool bPreviewFrame;
if (m_xToolbarManager.is())
// Assumes that we created the ToolbarLayoutManager with our frame, if
// not then we're somewhat fouled up ...
bPreviewFrame = m_xToolbarManager->isPreviewFrame();
else
{
Reference< XModel > xModel( impl_getModelFromFrame( xFrame ) );
bPreviewFrame = implts_isPreviewModel( xModel );
}
if ( m_xContainerWindow.is() && !bPreviewFrame ) // no UI elements on preview frames
{
OUString aElementType;
OUString aElementName;
parseResourceURL( aName, aElementType, aElementName );
if ( aElementType.equalsIgnoreAsciiCase( UIRESOURCETYPE_TOOLBAR ) && m_xToolbarManager.is() )
{
bNotify = m_xToolbarManager->createToolbar( aName );
bMustBeLayouted = m_xToolbarManager->isLayoutDirty();
}
else if ( aElementType.equalsIgnoreAsciiCase("menubar") &&
aElementName.equalsIgnoreAsciiCase("menubar") &&
implts_isFrameOrWindowTop(xFrame) )
{
implts_createMenuBar( aName );
if (m_bMenuVisible)
bNotify = true;
aWriteLock.clear();
}
else if ( aElementType.equalsIgnoreAsciiCase("statusbar") &&
( implts_isFrameOrWindowTop(xFrame) || implts_isEmbeddedLayoutManager() ))
{
implts_createStatusBar( aName );
bNotify = true;
}
else if ( aElementType.equalsIgnoreAsciiCase("progressbar") &&
aElementName.equalsIgnoreAsciiCase("progressbar") &&
implts_isFrameOrWindowTop(xFrame) )
{
implts_createProgressBar();
bNotify = true;
}
else if ( aElementType.equalsIgnoreAsciiCase("dockingwindow"))
{
// Add layout manager as listener for docking and other window events
uno::Reference< uno::XInterface > xThis( static_cast< OWeakObject* >(this), uno::UNO_QUERY );
uno::Reference< ui::XUIElement > xUIElement( implts_createDockingWindow( aName ));
if ( xUIElement.is() )
{
impl_addWindowListeners( xThis, xUIElement );
}
// The docking window is created by a factory method located in the sfx2 library.
// CreateDockingWindow( xFrame, aElementName );
}
}
if ( bMustBeLayouted )
implts_doLayout_notify( true );
if ( bNotify )
{
// UI element is invisible - provide information to listeners
implts_notifyListeners( frame::LayoutManagerEvents::UIELEMENT_VISIBLE, uno::Any( aName ) );
}
}
void SAL_CALL LayoutManager::destroyElement( const OUString& aName )
{
SAL_INFO( "fwk", "LayoutManager::destroyElement " << aName );
bool bMustBeLayouted(false);
bool bNotify(false);
/* SAFE AREA ----------------------------------------------------------------------------------------------- */
{
SolarMutexClearableGuard aWriteLock;
OUString aElementType;
OUString aElementName;
parseResourceURL(aName, aElementType, aElementName);
if (aElementType.equalsIgnoreAsciiCase("menubar")
&& aElementName.equalsIgnoreAsciiCase("menubar"))
{
if (!m_bInplaceMenuSet)
{
impl_clearUpMenuBar();
m_xMenuBar.clear();
bNotify = true;
}
}
else if ((aElementType.equalsIgnoreAsciiCase("statusbar")
&& aElementName.equalsIgnoreAsciiCase("statusbar"))
|| (m_aStatusBarElement.m_aName == aName))
{
aWriteLock.clear();
implts_destroyStatusBar();
bMustBeLayouted = true;
bNotify = true;
}
else if (aElementType.equalsIgnoreAsciiCase("progressbar")
&& aElementName.equalsIgnoreAsciiCase("progressbar"))
{
aWriteLock.clear();
implts_createProgressBar();
bMustBeLayouted = true;
bNotify = true;
}
else if (aElementType.equalsIgnoreAsciiCase(UIRESOURCETYPE_TOOLBAR)
&& m_xToolbarManager.is())
{
aWriteLock.clear();
bNotify = m_xToolbarManager->destroyToolbar(aName);
bMustBeLayouted = m_xToolbarManager->isLayoutDirty();
}
else if (aElementType.equalsIgnoreAsciiCase("dockingwindow"))
{
uno::Reference<frame::XFrame> xFrame(m_xFrame);
uno::Reference<XComponentContext> xContext(m_xContext);
aWriteLock.clear();
impl_setDockingWindowVisibility(xContext, xFrame, aElementName, false);
bMustBeLayouted = false;
bNotify = false;
}
}
/* SAFE AREA ----------------------------------------------------------------------------------------------- */
if ( bMustBeLayouted )
doLayout();
if ( bNotify )
implts_notifyListeners( frame::LayoutManagerEvents::UIELEMENT_INVISIBLE, uno::Any( aName ) );
}
sal_Bool SAL_CALL LayoutManager::requestElement( const OUString& rResourceURL )
{
bool bResult( false );
bool bNotify( false );
OUString aElementType;
OUString aElementName;
parseResourceURL( rResourceURL, aElementType, aElementName );
SolarMutexClearableGuard aWriteLock;
OString aResName = OUStringToOString( aElementName, RTL_TEXTENCODING_ASCII_US );
SAL_INFO( "fwk", "LayoutManager::requestElement " << aResName );
if (( aElementType.equalsIgnoreAsciiCase("statusbar") &&
aElementName.equalsIgnoreAsciiCase("statusbar") ) ||
( m_aStatusBarElement.m_aName == rResourceURL ))
{
implts_readStatusBarState( rResourceURL );
if ( m_aStatusBarElement.m_bVisible && !m_aStatusBarElement.m_bMasterHide )
{
aWriteLock.clear();
createElement( rResourceURL );
// There are some situation where we are not able to create an element.
// Therefore we have to check the reference before further action.
// See #i70019#
uno::Reference< ui::XUIElement > xUIElement( m_aStatusBarElement.m_xUIElement );
if ( xUIElement.is() )
{
// we need VCL here to pass special flags to Show()
SolarMutexGuard aGuard;
Reference< awt::XWindow > xWindow( xUIElement->getRealInterface(), UNO_QUERY );
VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
if ( pWindow )
{
pWindow->Show( true, ShowFlags::NoFocusChange | ShowFlags::NoActivate );
bResult = true;
bNotify = true;
}
}
}
}
else if ( aElementType.equalsIgnoreAsciiCase("progressbar") &&
aElementName.equalsIgnoreAsciiCase("progressbar") )
{
aWriteLock.clear();
implts_showProgressBar();
bResult = true;
bNotify = true;
}
else if ( aElementType.equalsIgnoreAsciiCase( UIRESOURCETYPE_TOOLBAR ) && m_bVisible )
{
bool bComponentAttached( !m_aModuleIdentifier.isEmpty() );
ToolbarLayoutManager* pToolbarManager = m_xToolbarManager.get();
aWriteLock.clear();
if ( pToolbarManager && bComponentAttached )
{
bNotify = pToolbarManager->requestToolbar( rResourceURL );
}
}
else if ( aElementType.equalsIgnoreAsciiCase("dockingwindow"))
{
uno::Reference< frame::XFrame > xFrame( m_xFrame );
aWriteLock.clear();
CreateDockingWindow( xFrame, aElementName );
}
if ( bNotify )
implts_notifyListeners( frame::LayoutManagerEvents::UIELEMENT_VISIBLE, uno::Any( rResourceURL ) );
return bResult;
}
Reference< XUIElement > SAL_CALL LayoutManager::getElement( const OUString& aName )
{
Reference< XUIElement > xUIElement = implts_findElement( aName );
if ( !xUIElement.is() )
{
SolarMutexClearableGuard aReadLock;
ToolbarLayoutManager* pToolbarManager( m_xToolbarManager.get() );
aReadLock.clear();
if ( pToolbarManager )
xUIElement = pToolbarManager->getToolbar( aName );
}
return xUIElement;
}
Sequence< Reference< ui::XUIElement > > SAL_CALL LayoutManager::getElements()
{
SolarMutexClearableGuard aReadLock;
rtl::Reference< MenuBarWrapper > xMenuBar( m_xMenuBar );
uno::Reference< ui::XUIElement > xStatusBar( m_aStatusBarElement.m_xUIElement );
ToolbarLayoutManager* pToolbarManager( m_xToolbarManager.get() );
aReadLock.clear();
Sequence< Reference< ui::XUIElement > > aSeq;
if ( pToolbarManager )
aSeq = pToolbarManager->getToolbars();
sal_Int32 nSize = aSeq.getLength();
sal_Int32 nMenuBarIndex(-1);
sal_Int32 nStatusBarIndex(-1);
if ( xMenuBar.is() )
{
nMenuBarIndex = nSize;
++nSize;
}
if ( xStatusBar.is() )
{
nStatusBarIndex = nSize;
++nSize;
}
aSeq.realloc(nSize);
auto pSeq = aSeq.getArray();
if ( nMenuBarIndex >= 0 )
pSeq[nMenuBarIndex] = xMenuBar;
if ( nStatusBarIndex >= 0 )
pSeq[nStatusBarIndex] = std::move(xStatusBar);
return aSeq;
}
sal_Bool SAL_CALL LayoutManager::showElement( const OUString& aName )
{
bool bResult( false );
bool bNotify( false );
bool bMustLayout( false );
OUString aElementType;
OUString aElementName;
parseResourceURL( aName, aElementType, aElementName );
OString aResName = OUStringToOString( aElementName, RTL_TEXTENCODING_ASCII_US );
SAL_INFO( "fwk", "LayoutManager::showElement " << aResName );
if ( aElementType.equalsIgnoreAsciiCase("menubar") &&
aElementName.equalsIgnoreAsciiCase("menubar") )
{
{
SolarMutexGuard aWriteLock;
m_bMenuVisible = true;
}
bResult = implts_resetMenuBar();
bNotify = bResult;
}
else if (( aElementType.equalsIgnoreAsciiCase("statusbar") &&
aElementName.equalsIgnoreAsciiCase("statusbar") ) ||
( m_aStatusBarElement.m_aName == aName ))
{
SolarMutexClearableGuard aWriteLock;
if ( m_aStatusBarElement.m_xUIElement.is() && !m_aStatusBarElement.m_bMasterHide &&
implts_showStatusBar( true ))
{
aWriteLock.clear();
implts_writeWindowStateData( STATUS_BAR_ALIAS, m_aStatusBarElement );
bMustLayout = true;
bResult = true;
bNotify = true;
}
}
else if ( aElementType.equalsIgnoreAsciiCase("progressbar") &&
aElementName.equalsIgnoreAsciiCase("progressbar") )
{
bNotify = bResult = implts_showProgressBar();
}
else if ( aElementType.equalsIgnoreAsciiCase( UIRESOURCETYPE_TOOLBAR ))
{
SolarMutexClearableGuard aReadLock;
ToolbarLayoutManager* pToolbarManager = m_xToolbarManager.get();
aReadLock.clear();
if ( pToolbarManager )
{
bNotify = pToolbarManager->showToolbar( aName );
bMustLayout = pToolbarManager->isLayoutDirty();
}
}
else if ( aElementType.equalsIgnoreAsciiCase("dockingwindow"))
{
SolarMutexClearableGuard aReadGuard;
uno::Reference< frame::XFrame > xFrame( m_xFrame );
uno::Reference< XComponentContext > xContext( m_xContext );
aReadGuard.clear();
impl_setDockingWindowVisibility( xContext, xFrame, aElementName, true );
}
if ( bMustLayout )
doLayout();
if ( bNotify )
implts_notifyListeners( frame::LayoutManagerEvents::UIELEMENT_VISIBLE, uno::Any( aName ) );
return bResult;
}
sal_Bool SAL_CALL LayoutManager::hideElement( const OUString& aName )
{
bool bNotify( false );
bool bMustLayout( false );
OUString aElementType;
OUString aElementName;
parseResourceURL( aName, aElementType, aElementName );
OString aResName = OUStringToOString( aElementName, RTL_TEXTENCODING_ASCII_US );
SAL_INFO( "fwk", "LayoutManager::hideElement " << aResName );
if ( aElementType.equalsIgnoreAsciiCase("menubar") &&
aElementName.equalsIgnoreAsciiCase("menubar") )
{
SolarMutexGuard g;
if ( m_xContainerWindow.is() )
{
m_bMenuVisible = false;
SolarMutexGuard aGuard;
SystemWindow* pSysWindow = getTopSystemWindow( m_xContainerWindow );
if ( pSysWindow )
{
MenuBar* pMenuBar = pSysWindow->GetMenuBar();
if ( pMenuBar )
{
pMenuBar->SetDisplayable( false );
bNotify = true;
}
}
}
}
else if (( aElementType.equalsIgnoreAsciiCase("statusbar") &&
aElementName.equalsIgnoreAsciiCase("statusbar") ) ||
( m_aStatusBarElement.m_aName == aName ))
{
SolarMutexGuard g;
if ( m_aStatusBarElement.m_xUIElement.is() && !m_aStatusBarElement.m_bMasterHide &&
implts_hideStatusBar( true ))
{
implts_writeWindowStateData( STATUS_BAR_ALIAS, m_aStatusBarElement );
bMustLayout = true;
bNotify = true;
}
}
else if ( aElementType.equalsIgnoreAsciiCase("progressbar") &&
aElementName.equalsIgnoreAsciiCase("progressbar") )
{
bNotify = implts_hideProgressBar();
}
else if ( aElementType.equalsIgnoreAsciiCase( UIRESOURCETYPE_TOOLBAR ))
{
SolarMutexClearableGuard aReadLock;
ToolbarLayoutManager* pToolbarManager = m_xToolbarManager.get();
aReadLock.clear();
if ( pToolbarManager )
{
bNotify = pToolbarManager->hideToolbar( aName );
bMustLayout = pToolbarManager->isLayoutDirty();
}
}
else if ( aElementType.equalsIgnoreAsciiCase("dockingwindow"))
{
SolarMutexClearableGuard aReadGuard;
uno::Reference< frame::XFrame > xFrame( m_xFrame );
uno::Reference< XComponentContext > xContext( m_xContext );
aReadGuard.clear();
impl_setDockingWindowVisibility( xContext, xFrame, aElementName, false );
}
if ( bMustLayout )
doLayout();
if ( bNotify )
implts_notifyListeners( frame::LayoutManagerEvents::UIELEMENT_INVISIBLE, uno::Any( aName ) );
return false;
}
sal_Bool SAL_CALL LayoutManager::dockWindow( const OUString& aName, DockingArea DockingArea, const awt::Point& Pos )
{
OUString aElementType;
OUString aElementName;
parseResourceURL( aName, aElementType, aElementName );
if ( aElementType.equalsIgnoreAsciiCase( UIRESOURCETYPE_TOOLBAR ))
{
SolarMutexClearableGuard aReadLock;
ToolbarLayoutManager* pToolbarManager = m_xToolbarManager.get();
aReadLock.clear();
if ( pToolbarManager )
{
pToolbarManager->dockToolbar( aName, DockingArea, Pos );
if ( pToolbarManager->isLayoutDirty() )
doLayout();
}
}
return false;
}
sal_Bool SAL_CALL LayoutManager::dockAllWindows( ::sal_Int16 /*nElementType*/ )
{
SolarMutexClearableGuard aReadLock;
bool bResult( false );
ToolbarLayoutManager* pToolbarManager = m_xToolbarManager.get();
aReadLock.clear();
if ( pToolbarManager )
{
bResult = pToolbarManager->dockAllToolbars();
if ( pToolbarManager->isLayoutDirty() )
doLayout();
}
return bResult;
}
sal_Bool SAL_CALL LayoutManager::floatWindow( const OUString& aName )
{
bool bResult( false );
if ( o3tl::equalsIgnoreAsciiCase(getElementTypeFromResourceURL( aName ), UIRESOURCETYPE_TOOLBAR ))
{
SolarMutexClearableGuard aReadLock;
ToolbarLayoutManager* pToolbarManager = m_xToolbarManager.get();
aReadLock.clear();
if ( pToolbarManager )
{
bResult = pToolbarManager->floatToolbar( aName );
if ( pToolbarManager->isLayoutDirty() )
doLayout();
}
}
return bResult;
}
sal_Bool SAL_CALL LayoutManager::lockWindow( const OUString& aName )
{
bool bResult( false );
if ( o3tl::equalsIgnoreAsciiCase(getElementTypeFromResourceURL( aName ), UIRESOURCETYPE_TOOLBAR ))
{
SolarMutexClearableGuard aReadLock;
ToolbarLayoutManager* pToolbarManager = m_xToolbarManager.get();
aReadLock.clear();
if ( pToolbarManager )
{
bResult = pToolbarManager->lockToolbar( aName );
if ( pToolbarManager->isLayoutDirty() )
doLayout();
}
}
return bResult;
}
sal_Bool SAL_CALL LayoutManager::unlockWindow( const OUString& aName )
{
bool bResult( false );
if ( o3tl::equalsIgnoreAsciiCase(getElementTypeFromResourceURL( aName ), UIRESOURCETYPE_TOOLBAR ))
{
SolarMutexClearableGuard aReadLock;
ToolbarLayoutManager* pToolbarManager = m_xToolbarManager.get();
aReadLock.clear();
if ( pToolbarManager )
{
bResult = pToolbarManager->unlockToolbar( aName );
if ( pToolbarManager->isLayoutDirty() )
doLayout();
}
}
return bResult;
}
void SAL_CALL LayoutManager::setElementSize( const OUString& aName, const awt::Size& aSize )
{
if ( !o3tl::equalsIgnoreAsciiCase(getElementTypeFromResourceURL( aName ), UIRESOURCETYPE_TOOLBAR ))
return;
SolarMutexClearableGuard aReadLock;
ToolbarLayoutManager* pToolbarManager = m_xToolbarManager.get();
aReadLock.clear();
if ( pToolbarManager )
{
pToolbarManager->setToolbarSize( aName, aSize );
if ( pToolbarManager->isLayoutDirty() )
doLayout();
}
}
void SAL_CALL LayoutManager::setElementPos( const OUString& aName, const awt::Point& aPos )
{
if ( !o3tl::equalsIgnoreAsciiCase(getElementTypeFromResourceURL( aName ), UIRESOURCETYPE_TOOLBAR ))
return;
SolarMutexClearableGuard aReadLock;
ToolbarLayoutManager* pToolbarManager( m_xToolbarManager.get() );
aReadLock.clear();
if ( pToolbarManager )
{
pToolbarManager->setToolbarPos( aName, aPos );
if ( pToolbarManager->isLayoutDirty() )
doLayout();
}
}
void SAL_CALL LayoutManager::setElementPosSize( const OUString& aName, const awt::Point& aPos, const awt::Size& aSize )
{
if ( !o3tl::equalsIgnoreAsciiCase(getElementTypeFromResourceURL( aName ), UIRESOURCETYPE_TOOLBAR ))
return;
SolarMutexClearableGuard aReadLock;
ToolbarLayoutManager* pToolbarManager( m_xToolbarManager.get() );
aReadLock.clear();
if ( pToolbarManager )
{
pToolbarManager->setToolbarPosSize( aName, aPos, aSize );
if ( pToolbarManager->isLayoutDirty() )
doLayout();
}
}
sal_Bool SAL_CALL LayoutManager::isElementVisible( const OUString& aName )
{
OUString aElementType;
OUString aElementName;
parseResourceURL( aName, aElementType, aElementName );
if ( aElementType.equalsIgnoreAsciiCase("menubar") &&
aElementName.equalsIgnoreAsciiCase("menubar") )
{
SolarMutexResettableGuard aReadLock;
if ( m_xContainerWindow.is() )
{
aReadLock.clear();
SolarMutexGuard aGuard;
SystemWindow* pSysWindow = getTopSystemWindow( m_xContainerWindow );
if ( pSysWindow )
{
MenuBar* pMenuBar = pSysWindow->GetMenuBar();
if ( pMenuBar && pMenuBar->IsDisplayable() )
return true;
}
else
{
aReadLock.reset();
return m_bMenuVisible;
}
}
}
else if (( aElementType.equalsIgnoreAsciiCase("statusbar") &&
aElementName.equalsIgnoreAsciiCase("statusbar") ) ||
( m_aStatusBarElement.m_aName == aName ))
{
if ( m_aStatusBarElement.m_xUIElement.is() )
{
Reference< awt::XWindow > xWindow( m_aStatusBarElement.m_xUIElement->getRealInterface(), UNO_QUERY );
if ( xWindow.is() )
{
SolarMutexGuard g;
VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
if ( pWindow && pWindow->IsVisible() )
return true;
else
return false;
}
}
}
else if ( aElementType.equalsIgnoreAsciiCase("progressbar") &&
aElementName.equalsIgnoreAsciiCase("progressbar") )
{
if ( m_aProgressBarElement.m_xUIElement.is() )
return m_aProgressBarElement.m_bVisible;
}
else if ( aElementType.equalsIgnoreAsciiCase( UIRESOURCETYPE_TOOLBAR ))
{
SolarMutexClearableGuard aReadLock;
ToolbarLayoutManager* pToolbarManager = m_xToolbarManager.get();
aReadLock.clear();
if ( pToolbarManager )
return pToolbarManager->isToolbarVisible( aName );
}
else if ( aElementType.equalsIgnoreAsciiCase("dockingwindow"))
{
SolarMutexClearableGuard aReadGuard;
uno::Reference< frame::XFrame > xFrame( m_xFrame );
aReadGuard.clear();
return IsDockingWindowVisible( xFrame, aElementName );
}
return false;
}
sal_Bool SAL_CALL LayoutManager::isElementFloating( const OUString& aName )
{
if ( o3tl::equalsIgnoreAsciiCase(getElementTypeFromResourceURL( aName ), UIRESOURCETYPE_TOOLBAR ))
{
SolarMutexClearableGuard aReadLock;
ToolbarLayoutManager* pToolbarManager = m_xToolbarManager.get();
aReadLock.clear();
if ( pToolbarManager )
return pToolbarManager->isToolbarFloating( aName );
}
return false;
}
sal_Bool SAL_CALL LayoutManager::isElementDocked( const OUString& aName )
{
if ( o3tl::equalsIgnoreAsciiCase(getElementTypeFromResourceURL( aName ), UIRESOURCETYPE_TOOLBAR ))
{
SolarMutexClearableGuard aReadLock;
ToolbarLayoutManager* pToolbarManager = m_xToolbarManager.get();
aReadLock.clear();
if ( pToolbarManager )
return pToolbarManager->isToolbarDocked( aName );
}
return false;
}
sal_Bool SAL_CALL LayoutManager::isElementLocked( const OUString& aName )
{
if ( o3tl::equalsIgnoreAsciiCase(getElementTypeFromResourceURL( aName ), UIRESOURCETYPE_TOOLBAR ))
{
SolarMutexClearableGuard aReadLock;
ToolbarLayoutManager* pToolbarManager = m_xToolbarManager.get();
aReadLock.clear();
if ( pToolbarManager )
return pToolbarManager->isToolbarLocked( aName );
}
return false;
}
awt::Size SAL_CALL LayoutManager::getElementSize( const OUString& aName )
{
if ( o3tl::equalsIgnoreAsciiCase(getElementTypeFromResourceURL( aName ), UIRESOURCETYPE_TOOLBAR ))
{
SolarMutexClearableGuard aReadLock;
ToolbarLayoutManager* pToolbarManager = m_xToolbarManager.get();
aReadLock.clear();
if ( pToolbarManager )
return pToolbarManager->getToolbarSize( aName );
}
return awt::Size();
}
awt::Point SAL_CALL LayoutManager::getElementPos( const OUString& aName )
{
if ( o3tl::equalsIgnoreAsciiCase(getElementTypeFromResourceURL( aName ), UIRESOURCETYPE_TOOLBAR ))
{
SolarMutexClearableGuard aReadLock;
ToolbarLayoutManager* pToolbarManager = m_xToolbarManager.get();
aReadLock.clear();
if ( pToolbarManager )
return pToolbarManager->getToolbarPos( aName );
}
return awt::Point();
}
void SAL_CALL LayoutManager::lock()
{
implts_lock();
SolarMutexClearableGuard aReadLock;
sal_Int32 nLockCount( m_nLockCount );
aReadLock.clear();
SAL_INFO( "fwk", "LayoutManager::lock " << reinterpret_cast<sal_Int64>(this) << " - " << nLockCount );
Any a( nLockCount );
implts_notifyListeners( frame::LayoutManagerEvents::LOCK, a );
}
void SAL_CALL LayoutManager::unlock()
{
bool bDoLayout( implts_unlock() );
SolarMutexClearableGuard aReadLock;
sal_Int32 nLockCount( m_nLockCount );
aReadLock.clear();
SAL_INFO( "fwk", "LayoutManager::unlock " << reinterpret_cast<sal_Int64>(this) << " - " << nLockCount);
// conform to documentation: unlock with lock count == 0 means force a layout
{
SolarMutexGuard aWriteLock;
if (bDoLayout)
m_aAsyncLayoutTimer.Stop();
}
Any a( nLockCount );
implts_notifyListeners( frame::LayoutManagerEvents::UNLOCK, a );
if ( bDoLayout )
implts_doLayout_notify( true );
}
void SAL_CALL LayoutManager::doLayout()
{
implts_doLayout_notify( true );
}
// ILayoutNotifications
void LayoutManager::requestLayout()
{
doLayout();
}
void LayoutManager::implts_doLayout_notify( bool bOuterResize )
{
bool bLayouted = implts_doLayout( false, bOuterResize );
if ( bLayouted )
implts_notifyListeners( frame::LayoutManagerEvents::LAYOUT, Any() );
}
bool LayoutManager::implts_doLayout( bool bForceRequestBorderSpace, bool bOuterResize )
{
SAL_INFO( "fwk", "LayoutManager::implts_doLayout" );
/* SAFE AREA ----------------------------------------------------------------------------------------------- */
SolarMutexClearableGuard aReadLock;
if ( !m_xFrame.is() || !m_bParentWindowVisible )
return false;
bool bPreserveContentSize( m_bPreserveContentSize );
bool bMustDoLayout( m_bMustDoLayout );
bool bNoLock = ( m_nLockCount == 0 );
awt::Rectangle aCurrBorderSpace( m_aDockingArea );
Reference< awt::XWindow > xContainerWindow( m_xContainerWindow );
Reference< awt::XTopWindow2 > xContainerTopWindow( m_xContainerTopWindow );
Reference< awt::XWindow > xComponentWindow;
try {
xComponentWindow = m_xFrame->getComponentWindow();
} catch (css::lang::DisposedException &) {
// There can be a race between one thread calling Frame::dispose
// (framework/source/services/frame.cxx) -> Frame::disableLayoutManager
// -> LayoutManager::attachFrame(null) setting m_xFrame to null, and
// the main thread firing the timer-triggered
// LayoutManager::AsyncLayoutHdl -> LayoutManager::implts_doLayout and
// calling into the in-dispose m_xFrame here, so silently ignore a
// DisposedException here:
return false;
}
Reference< XDockingAreaAcceptor > xDockingAreaAcceptor( m_xDockingAreaAcceptor );
aReadLock.clear();
/* SAFE AREA ----------------------------------------------------------------------------------------------- */
bool bLayouted( false );
if ( bNoLock && xDockingAreaAcceptor.is() && xContainerWindow.is() && xComponentWindow.is() )
{
bLayouted = true;
awt::Rectangle aDockSpace( implts_calcDockingAreaSizes() );
awt::Rectangle aBorderSpace( aDockSpace );
bool bGotRequestedBorderSpace( true );
// We have to add the height of a possible status bar
aBorderSpace.Height += implts_getStatusBarSize().Height();
if ( !equalRectangles( aBorderSpace, aCurrBorderSpace ) || bForceRequestBorderSpace || bMustDoLayout )
{
// we always resize the content window (instead of the complete container window) if we're not set up
// to (attempt to) preserve the content window's size
if ( bOuterResize && !bPreserveContentSize )
bOuterResize = false;
// maximized windows can resized their content window only, not their container window
if ( bOuterResize && xContainerTopWindow.is() && xContainerTopWindow->getIsMaximized() )
bOuterResize = false;
// if the component window does not have a size (yet), then we can't use it to calc the container
// window size
awt::Rectangle aComponentRect = xComponentWindow->getPosSize();
if ( bOuterResize && ( aComponentRect.Width == 0 ) && ( aComponentRect.Height == 0 ) )
bOuterResize = false;
bGotRequestedBorderSpace = false;
if ( bOuterResize )
{
Reference< awt::XDevice > xDevice( xContainerWindow, uno::UNO_QUERY );
awt::DeviceInfo aContainerInfo = xDevice->getInfo();
awt::Size aRequestedSize( aComponentRect.Width + aContainerInfo.LeftInset + aContainerInfo.RightInset + aBorderSpace.X + aBorderSpace.Width,
aComponentRect.Height + aContainerInfo.TopInset + aContainerInfo.BottomInset + aBorderSpace.Y + aBorderSpace.Height );
awt::Point aComponentPos( aBorderSpace.X, aBorderSpace.Y );
bGotRequestedBorderSpace = implts_resizeContainerWindow( aRequestedSize, aComponentPos );
}
// if we did not do a container window resize, or it failed, then use the DockingAcceptor as usual
if ( !bGotRequestedBorderSpace )
bGotRequestedBorderSpace = xDockingAreaAcceptor->requestDockingAreaSpace( aBorderSpace );
if ( bGotRequestedBorderSpace )
{
SolarMutexGuard aWriteGuard;
m_aDockingArea = aBorderSpace;
m_bMustDoLayout = false;
}
}
if ( bGotRequestedBorderSpace )
{
::Size aContainerSize;
::Size aStatusBarSize;
// Interim solution to let the layout method within the
// toolbar layout manager.
implts_setOffset( implts_getStatusBarSize().Height() );
if ( m_xToolbarManager.is() )
m_xToolbarManager->setDockingArea( aDockSpace );
// Subtract status bar size from our container output size. Docking area windows
// don't contain the status bar!
aStatusBarSize = implts_getStatusBarSize();
aContainerSize = implts_getContainerWindowOutputSize();
aContainerSize.AdjustHeight( -(aStatusBarSize.Height()) );
if ( m_xToolbarManager.is() )
m_xToolbarManager->doLayout(aContainerSize);
// Position the status bar
if ( aStatusBarSize.Height() > 0 )
{
implts_setStatusBarPosSize( ::Point( 0, std::max(( aContainerSize.Height() ), tools::Long( 0 ))),
::Size( aContainerSize.Width(),aStatusBarSize.Height() ));
}
xDockingAreaAcceptor->setDockingAreaSpace( aBorderSpace );
}
}
return bLayouted;
}
bool LayoutManager::implts_resizeContainerWindow( const awt::Size& rContainerSize,
const awt::Point& rComponentPos )
{
SolarMutexClearableGuard aReadLock;
Reference< awt::XWindow > xContainerWindow = m_xContainerWindow;
Reference< awt::XTopWindow2 > xContainerTopWindow = m_xContainerTopWindow;
Reference< awt::XWindow > xComponentWindow = m_xFrame->getComponentWindow();
aReadLock.clear();
// calculate the maximum size we have for the container window
sal_Int32 nDisplay = xContainerTopWindow->getDisplay();
AbsoluteScreenPixelRectangle aWorkArea = Application::GetScreenPosSizePixel( nDisplay );
if (!aWorkArea.IsEmpty())
{
if (( rContainerSize.Width > aWorkArea.GetWidth() ) || ( rContainerSize.Height > aWorkArea.GetHeight() ))
return false;
// Strictly, this is not correct. If we have a multi-screen display (css.awt.DisplayAccess.MultiDisplay == true),
// the "effective work area" would be much larger than the work area of a single display, since we could in theory
// position the container window across multiple screens.
// However, this should suffice as a heuristics here ... (nobody really wants to check whether the different screens are
// stacked horizontally or vertically, whether their work areas can really be combined, or are separated by non-work-areas,
// and the like ... right?)
}
// resize our container window
xContainerWindow->setPosSize( 0, 0, rContainerSize.Width, rContainerSize.Height, awt::PosSize::SIZE );
// position the component window
xComponentWindow->setPosSize( rComponentPos.X, rComponentPos.Y, 0, 0, awt::PosSize::POS );
return true;
}
void SAL_CALL LayoutManager::setVisible( sal_Bool bVisible )
{
SolarMutexClearableGuard aWriteLock;
bool bWasVisible( m_bVisible );
m_bVisible = bVisible;
aWriteLock.clear();
if ( bWasVisible != bool(bVisible) )
implts_setVisibleState( bVisible );
}
sal_Bool SAL_CALL LayoutManager::isVisible()
{
SolarMutexGuard g;
return m_bVisible;
}
::Size LayoutManager::implts_getStatusBarSize()
{
SolarMutexClearableGuard aReadLock;
bool bStatusBarVisible( isElementVisible( STATUS_BAR_ALIAS ));
bool bProgressBarVisible( isElementVisible( u"private:resource/progressbar/progressbar"_ustr ));
bool bVisible( m_bVisible );
Reference< XUIElement > xStatusBar( m_aStatusBarElement.m_xUIElement );
Reference< XUIElement > xProgressBar( m_aProgressBarElement.m_xUIElement );
Reference< awt::XWindow > xWindow;
if ( bStatusBarVisible && bVisible && xStatusBar.is() )
xWindow.set( xStatusBar->getRealInterface(), UNO_QUERY );
else if ( xProgressBar.is() && !xStatusBar.is() && bProgressBarVisible )
{
ProgressBarWrapper* pWrapper = static_cast<ProgressBarWrapper*>(xProgressBar.get());
if ( pWrapper )
xWindow = pWrapper->getStatusBar();
}
aReadLock.clear();
if ( xWindow.is() )
{
awt::Rectangle aPosSize = xWindow->getPosSize();
return ::Size( aPosSize.Width, aPosSize.Height );
}
else
return ::Size();
}
awt::Rectangle LayoutManager::implts_calcDockingAreaSizes()
{
SolarMutexClearableGuard aReadLock;
Reference< awt::XWindow > xContainerWindow( m_xContainerWindow );
Reference< XDockingAreaAcceptor > xDockingAreaAcceptor( m_xDockingAreaAcceptor );
aReadLock.clear();
awt::Rectangle aBorderSpace;
if ( m_xToolbarManager.is() && xDockingAreaAcceptor.is() && xContainerWindow.is() )
aBorderSpace = m_xToolbarManager->getDockingArea();
return aBorderSpace;
}
void LayoutManager::implts_setDockingAreaWindowSizes()
{
SolarMutexClearableGuard aReadLock;
Reference< awt::XWindow > xContainerWindow( m_xContainerWindow );
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 );
::Size aStatusBarSize = implts_getStatusBarSize();
// Position the status bar
if ( aStatusBarSize.Height() > 0 )
{
implts_setStatusBarPosSize( ::Point( 0, std::max(( aContainerClientSize.Height - aStatusBarSize.Height() ), tools::Long( 0 ))),
::Size( aContainerClientSize.Width, aStatusBarSize.Height() ));
}
}
void LayoutManager::implts_updateMenuBarClose()
{
SolarMutexClearableGuard aWriteLock;
bool bShowCloseButton( m_bMenuBarCloseButton );
Reference< awt::XWindow > xContainerWindow( m_xContainerWindow );
aWriteLock.clear();
if ( !xContainerWindow.is() )
return;
SolarMutexGuard aGuard;
SystemWindow* pSysWindow = getTopSystemWindow( xContainerWindow );
if ( pSysWindow )
{
MenuBar* pMenuBar = pSysWindow->GetMenuBar();
if ( pMenuBar )
{
// TODO remove link on sal_False ?!
pMenuBar->ShowCloseButton(bShowCloseButton);
pMenuBar->SetCloseButtonClickHdl(LINK(this, LayoutManager, MenuBarClose));
}
}
}
bool LayoutManager::implts_resetMenuBar()
{
/* SAFE AREA ----------------------------------------------------------------------------------------------- */
SolarMutexGuard aWriteLock;
bool bMenuVisible( m_bMenuVisible );
Reference< awt::XWindow > xContainerWindow( m_xContainerWindow );
MenuBar* pSetMenuBar = nullptr;
if ( m_xInplaceMenuBar.is() )
pSetMenuBar = static_cast<MenuBar *>(m_xInplaceMenuBar->GetMenuBar());
else if ( m_xMenuBar )
pSetMenuBar = static_cast<MenuBar*>(m_xMenuBar->GetMenuBarManager()->GetMenuBar());
SystemWindow* pSysWindow = getTopSystemWindow( xContainerWindow );
if ( pSysWindow && bMenuVisible && pSetMenuBar )
{
pSysWindow->SetMenuBar(pSetMenuBar);
pSetMenuBar->SetDisplayable( true );
return true;
}
return false;
}
void LayoutManager::implts_createMSCompatibleMenuBar( const OUString& aName )
{
SolarMutexGuard aWriteLock;
// Find Form menu in the original menubar
m_xMenuBar.set( static_cast< MenuBarWrapper* >(implts_createElement( aName ).get()) );
uno::Reference< container::XIndexReplace > xMenuIndex(m_xMenuBar->getSettings(true), UNO_QUERY);
sal_Int32 nFormsMenu = -1;
for (sal_Int32 nIndex = 0; nIndex < xMenuIndex->getCount(); ++nIndex)
{
uno::Sequence< beans::PropertyValue > aProps;
xMenuIndex->getByIndex( nIndex ) >>= aProps;
OUString aCommand;
for (beans::PropertyValue const& rProp : aProps)
{
if (rProp.Name == "CommandURL")
{
rProp.Value >>= aCommand;
break;
}
}
if (aCommand == ".uno:FormatFormMenu")
nFormsMenu = nIndex;
}
assert(nFormsMenu != -1);
// Create the MS compatible Form menu
css::uno::Reference< css::ui::XUIElement > xFormsMenu = implts_createElement( u"private:resource/menubar/mscompatibleformsmenu"_ustr );
if(!xFormsMenu.is())
return;
// Merge the MS compatible Form menu into the menubar
uno::Reference< XUIElementSettings > xFormsMenuSettings(xFormsMenu, UNO_QUERY);
uno::Reference< container::XIndexAccess > xFormsMenuIndex(xFormsMenuSettings->getSettings(true));
assert(xFormsMenuIndex->getCount() >= 1);
uno::Sequence< beans::PropertyValue > aNewFormsMenu;
xFormsMenuIndex->getByIndex( 0 ) >>= aNewFormsMenu;
xMenuIndex->replaceByIndex(nFormsMenu, uno::Any(aNewFormsMenu));
setMergedMenuBar( xMenuIndex );
// Clear up the temporal forms menubar
Reference< XComponent > xFormsMenuComp( xFormsMenu, UNO_QUERY );
if ( xFormsMenuComp.is() )
xFormsMenuComp->dispose();
xFormsMenu.clear();
}
IMPL_LINK_NOARG(LayoutManager, MenuBarClose, void*, void)
{
SolarMutexClearableGuard aReadLock;
uno::Reference< frame::XDispatchProvider > xProvider(m_xFrame, uno::UNO_QUERY);
uno::Reference< XComponentContext > xContext( m_xContext );
aReadLock.clear();
if ( !xProvider.is())
return;
uno::Reference< frame::XDispatchHelper > xDispatcher = frame::DispatchHelper::create( xContext );
xDispatcher->executeDispatch(
xProvider,
u".uno:CloseWin"_ustr,
u"_self"_ustr,
0,
uno::Sequence< beans::PropertyValue >());
}
// XLayoutManagerEventBroadcaster
void SAL_CALL LayoutManager::addLayoutManagerEventListener( const uno::Reference< frame::XLayoutManagerListener >& xListener )
{
m_aListenerContainer.addInterface( cppu::UnoType<frame::XLayoutManagerListener>::get(), xListener );
}
void SAL_CALL LayoutManager::removeLayoutManagerEventListener( const uno::Reference< frame::XLayoutManagerListener >& xListener )
{
m_aListenerContainer.removeInterface( cppu::UnoType<frame::XLayoutManagerListener>::get(), xListener );
}
void LayoutManager::implts_notifyListeners(short nEvent, const uno::Any& rInfoParam)
{
comphelper::OInterfaceContainerHelper2* pContainer = m_aListenerContainer.getContainer( cppu::UnoType<frame::XLayoutManagerListener>::get());
if (pContainer==nullptr)
return;
lang::EventObject aSource( static_cast< ::cppu::OWeakObject*>(this) );
comphelper::OInterfaceIteratorHelper2 pIterator(*pContainer);
while (pIterator.hasMoreElements())
{
try
{
static_cast<frame::XLayoutManagerListener*>(pIterator.next())->layoutEvent(aSource, nEvent, rInfoParam);
}
catch( const uno::RuntimeException& )
{
pIterator.remove();
}
}
}
// XWindowListener
void SAL_CALL LayoutManager::windowResized( const awt::WindowEvent& aEvent )
{
SolarMutexGuard g;
Reference< awt::XWindow > xContainerWindow( m_xContainerWindow );
Reference< XInterface > xIfac( xContainerWindow, UNO_QUERY );
if ( xIfac == aEvent.Source && m_bVisible )
{
// We have to call our resize handler at least once synchronously, as some
// application modules need this. So we have to check if this is the first
// call after the async layout time expired.
m_bMustDoLayout = true;
if ( !m_aAsyncLayoutTimer.IsActive() )
{
m_aAsyncLayoutTimer.Invoke();
if ( m_nLockCount == 0 )
m_aAsyncLayoutTimer.Start();
}
}
else if ( m_xFrame.is() && aEvent.Source == m_xFrame->getContainerWindow() )
{
// the container window of my DockingAreaAcceptor is not the same as of my frame
// I still have to resize my frames' window as nobody else will do it
Reference< awt::XWindow > xComponentWindow( m_xFrame->getComponentWindow() );
if( xComponentWindow.is() )
{
uno::Reference< awt::XDevice > xDevice( m_xFrame->getContainerWindow(), uno::UNO_QUERY );
// Convert relative size to output size.
awt::Rectangle aRectangle = m_xFrame->getContainerWindow()->getPosSize();
awt::DeviceInfo aInfo = xDevice->getInfo();
awt::Size aSize( aRectangle.Width - aInfo.LeftInset - aInfo.RightInset ,
aRectangle.Height - aInfo.TopInset - aInfo.BottomInset );
// Resize our component window.
xComponentWindow->setPosSize( 0, 0, aSize.Width, aSize.Height, awt::PosSize::POSSIZE );
}
}
}
void SAL_CALL LayoutManager::windowMoved( const awt::WindowEvent& )
{
}
void SAL_CALL LayoutManager::windowShown( const lang::EventObject& aEvent )
{
SolarMutexClearableGuard aReadLock;
Reference< awt::XWindow > xContainerWindow( m_xContainerWindow );
bool bParentWindowVisible( m_bParentWindowVisible );
aReadLock.clear();
Reference< XInterface > xIfac( xContainerWindow, UNO_QUERY );
if ( xIfac == aEvent.Source )
{
SolarMutexClearableGuard aWriteLock;
m_bParentWindowVisible = true;
bool bSetVisible = ( m_bParentWindowVisible != bParentWindowVisible );
aWriteLock.clear();
if ( bSetVisible )
implts_updateUIElementsVisibleState( true );
}
}
void SAL_CALL LayoutManager::windowHidden( const lang::EventObject& aEvent )
{
SolarMutexClearableGuard aReadLock;
Reference< awt::XWindow > xContainerWindow( m_xContainerWindow );
bool bParentWindowVisible( m_bParentWindowVisible );
aReadLock.clear();
Reference< XInterface > xIfac( xContainerWindow, UNO_QUERY );
if ( xIfac == aEvent.Source )
{
SolarMutexClearableGuard aWriteLock;
m_bParentWindowVisible = false;
bool bSetInvisible = ( m_bParentWindowVisible != bParentWindowVisible );
aWriteLock.clear();
if ( bSetInvisible )
implts_updateUIElementsVisibleState( false );
}
}
IMPL_LINK_NOARG(LayoutManager, AsyncLayoutHdl, Timer *, void)
{
{
SolarMutexGuard aReadLock;
if (!m_xContainerWindow.is())
return;
}
implts_setDockingAreaWindowSizes();
implts_doLayout( true, false );
}
// XFrameActionListener
void SAL_CALL LayoutManager::frameAction( const FrameActionEvent& aEvent )
{
if (( aEvent.Action == FrameAction_COMPONENT_ATTACHED ) || ( aEvent.Action == FrameAction_COMPONENT_REATTACHED ))
{
SAL_INFO( "fwk", "LayoutManager::frameAction (COMPONENT_ATTACHED|REATTACHED)" );
{
SolarMutexGuard aWriteLock;
m_bMustDoLayout = true;
}
implts_reset( true );
implts_doLayout( true, false );
implts_doLayout( true, true );
}
else if (( aEvent.Action == FrameAction_FRAME_UI_ACTIVATED ) || ( aEvent.Action == FrameAction_FRAME_UI_DEACTIVATING ))
{
SAL_INFO( "fwk", "LayoutManager::frameAction (FRAME_UI_ACTIVATED|DEACTIVATING)" );
implts_toggleFloatingUIElementsVisibility( aEvent.Action == FrameAction_FRAME_UI_ACTIVATED );
}
else if ( aEvent.Action == FrameAction_COMPONENT_DETACHING )
{
SAL_INFO( "fwk", "LayoutManager::frameAction (COMPONENT_DETACHING)" );
implts_reset( false );
}
}
void SAL_CALL LayoutManager::disposing( const lang::EventObject& rEvent )
{
bool bDisposeAndClear( false );
/* SAFE AREA ----------------------------------------------------------------------------------------------- */
{
SolarMutexGuard aWriteLock;
if (rEvent.Source == Reference<XInterface>(m_xFrame, UNO_QUERY))
{
// Our frame gets disposed, release all our references that depends on a working frame reference.
setDockingAreaAcceptor(Reference<ui::XDockingAreaAcceptor>());
// destroy all elements, it's possible that detaching is NOT called!
implts_destroyElements();
impl_clearUpMenuBar();
m_xMenuBar.clear();
VclPtr<Menu> pMenuBar;
if (m_xInplaceMenuBar.is())
{
pMenuBar = m_xInplaceMenuBar->GetMenuBar();
m_xInplaceMenuBar->dispose();
m_xInplaceMenuBar.clear();
}
pMenuBar.disposeAndClear();
m_xContainerWindow.clear();
m_xContainerTopWindow.clear();
// forward disposing call to toolbar manager
if (m_xToolbarManager.is())
m_xToolbarManager->disposing(rEvent);
if (m_xModuleCfgMgr.is())
{
try
{
Reference<XUIConfiguration> xModuleCfgMgr(m_xModuleCfgMgr, UNO_QUERY);
xModuleCfgMgr->removeConfigurationListener(Reference<XUIConfigurationListener>(this));
}
catch (const Exception&)
{
}
}
if (m_xDocCfgMgr.is())
{
try
{
Reference<XUIConfiguration> xDocCfgMgr(m_xDocCfgMgr, UNO_QUERY);
xDocCfgMgr->removeConfigurationListener(Reference<XUIConfigurationListener>(this));
}
catch (const Exception&)
{
}
}
m_xDocCfgMgr.clear();
m_xModuleCfgMgr.clear();
m_xFrame.clear();
m_pGlobalSettings.reset();
bDisposeAndClear = true;
}
else if (rEvent.Source == Reference<XInterface>(m_xContainerWindow, UNO_QUERY))
{
// Our container window gets disposed. Remove all user interface elements.
ToolbarLayoutManager* pToolbarManager = m_xToolbarManager.get();
if (pToolbarManager)
{
uno::Reference<awt::XVclWindowPeer> aEmptyWindowPeer;
pToolbarManager->setParentWindow(aEmptyWindowPeer);
}
impl_clearUpMenuBar();
m_xMenuBar.clear();
VclPtr<Menu> pMenuBar;
if (m_xInplaceMenuBar.is())
{
pMenuBar = m_xInplaceMenuBar->GetMenuBar();
m_xInplaceMenuBar->dispose();
m_xInplaceMenuBar.clear();
}
pMenuBar.disposeAndClear();
m_xContainerWindow.clear();
m_xContainerTopWindow.clear();
}
else if (rEvent.Source == Reference<XInterface>(m_xDocCfgMgr, UNO_QUERY))
m_xDocCfgMgr.clear();
else if (rEvent.Source == Reference<XInterface>(m_xModuleCfgMgr, UNO_QUERY))
m_xModuleCfgMgr.clear();
}
/* SAFE AREA ----------------------------------------------------------------------------------------------- */
// Send disposing to our listener when we have lost our frame.
if ( bDisposeAndClear )
{
// Send message to all listener and forget her references.
uno::Reference< frame::XLayoutManager > xThis(this);
lang::EventObject aEvent( xThis );
m_aListenerContainer.disposeAndClear( aEvent );
}
}
void SAL_CALL LayoutManager::elementInserted( const ui::ConfigurationEvent& Event )
{
SolarMutexClearableGuard aReadLock;
Reference< XFrame > xFrame( m_xFrame );
rtl::Reference< ToolbarLayoutManager > xToolbarManager( m_xToolbarManager );
aReadLock.clear();
if ( !xFrame.is() )
return;
OUString aElementType;
OUString aElementName;
bool bRefreshLayout(false);
parseResourceURL( Event.ResourceURL, aElementType, aElementName );
if ( aElementType.equalsIgnoreAsciiCase( UIRESOURCETYPE_TOOLBAR ))
{
if ( xToolbarManager.is() )
{
xToolbarManager->elementInserted( Event );
bRefreshLayout = xToolbarManager->isLayoutDirty();
}
}
else if ( aElementType.equalsIgnoreAsciiCase( UIRESOURCETYPE_MENUBAR ))
{
Reference< XUIElement > xUIElement = implts_findElement( Event.ResourceURL );
Reference< XUIElementSettings > xElementSettings( xUIElement, UNO_QUERY );
if ( xElementSettings.is() )
{
uno::Reference< XPropertySet > xPropSet( xElementSettings, uno::UNO_QUERY );
if ( xPropSet.is() )
{
if ( Event.Source == uno::Reference< uno::XInterface >( m_xDocCfgMgr, uno::UNO_QUERY ))
xPropSet->setPropertyValue( u"ConfigurationSource"_ustr, Any( m_xDocCfgMgr ));
}
xElementSettings->updateSettings();
}
}
if ( bRefreshLayout )
doLayout();
}
void SAL_CALL LayoutManager::elementRemoved( const ui::ConfigurationEvent& Event )
{
SolarMutexClearableGuard aReadLock;
Reference< frame::XFrame > xFrame( m_xFrame );
rtl::Reference< ToolbarLayoutManager > xToolbarManager( m_xToolbarManager );
Reference< awt::XWindow > xContainerWindow( m_xContainerWindow );
rtl::Reference< MenuBarWrapper > xMenuBar( m_xMenuBar );
Reference< ui::XUIConfigurationManager > xModuleCfgMgr( m_xModuleCfgMgr );
Reference< ui::XUIConfigurationManager > xDocCfgMgr( m_xDocCfgMgr );
aReadLock.clear();
if ( !xFrame.is() )
return;
OUString aElementType;
OUString aElementName;
bool bRefreshLayout(false);
parseResourceURL( Event.ResourceURL, aElementType, aElementName );
if ( aElementType.equalsIgnoreAsciiCase( UIRESOURCETYPE_TOOLBAR ))
{
if ( xToolbarManager.is() )
{
xToolbarManager->elementRemoved( Event );
bRefreshLayout = xToolbarManager->isLayoutDirty();
}
}
else
{
Reference< XUIElement > xUIElement = implts_findElement( Event.ResourceURL );
Reference< XUIElementSettings > xElementSettings( xUIElement, UNO_QUERY );
if ( xElementSettings.is() )
{
bool bNoSettings( false );
OUString aConfigSourcePropName( u"ConfigurationSource"_ustr );
Reference< XInterface > xElementCfgMgr;
Reference< XPropertySet > xPropSet( xElementSettings, 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 ( Event.Source == xElementCfgMgr )
{
// Same UI configuration manager where our element has its settings
if ( Event.Source == Reference< XInterface >( xDocCfgMgr, UNO_QUERY ))
{
// document settings removed
if ( xModuleCfgMgr->hasSettings( Event.ResourceURL ))
{
xPropSet->setPropertyValue( aConfigSourcePropName, Any( m_xModuleCfgMgr ));
xElementSettings->updateSettings();
return;
}
}
bNoSettings = true;
}
// No settings anymore, element must be destroyed
if ( xContainerWindow.is() && bNoSettings )
{
if ( aElementType.equalsIgnoreAsciiCase("menubar") &&
aElementName.equalsIgnoreAsciiCase("menubar") )
{
SystemWindow* pSysWindow = getTopSystemWindow( xContainerWindow );
if ( pSysWindow && !m_bInplaceMenuSet )
pSysWindow->SetMenuBar( nullptr );
if ( xMenuBar.is() )
xMenuBar->dispose();
SolarMutexGuard g;
m_xMenuBar.clear();
}
}
}
}
if ( bRefreshLayout )
doLayout();
}
void SAL_CALL LayoutManager::elementReplaced( const ui::ConfigurationEvent& Event )
{
SolarMutexClearableGuard aReadLock;
Reference< XFrame > xFrame( m_xFrame );
rtl::Reference< ToolbarLayoutManager > xToolbarManager( m_xToolbarManager );
aReadLock.clear();
if ( !xFrame.is() )
return;
OUString aElementType;
OUString aElementName;
bool bRefreshLayout(false);
parseResourceURL( Event.ResourceURL, aElementType, aElementName );
if ( aElementType.equalsIgnoreAsciiCase( UIRESOURCETYPE_TOOLBAR ))
{
if ( xToolbarManager.is() )
{
xToolbarManager->elementReplaced( Event );
bRefreshLayout = xToolbarManager->isLayoutDirty();
}
}
else
{
Reference< XUIElement > xUIElement = implts_findElement( Event.ResourceURL );
Reference< XUIElementSettings > xElementSettings( xUIElement, UNO_QUERY );
if ( xElementSettings.is() )
{
Reference< XInterface > xElementCfgMgr;
Reference< XPropertySet > xPropSet( xElementSettings, UNO_QUERY );
if ( xPropSet.is() )
xPropSet->getPropertyValue( u"ConfigurationSource"_ustr ) >>= xElementCfgMgr;
if ( !xElementCfgMgr.is() )
return;
// Check if the same UI configuration manager has changed => update settings
if ( Event.Source == xElementCfgMgr )
xElementSettings->updateSettings();
}
}
if ( bRefreshLayout )
doLayout();
}
void SAL_CALL LayoutManager::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle,
const uno::Any& aValue )
{
if ( (nHandle != LAYOUTMANAGER_PROPHANDLE_REFRESHVISIBILITY) && (nHandle != LAYOUTMANAGER_PROPHANDLE_REFRESHTOOLTIP) )
LayoutManager_PBase::setFastPropertyValue_NoBroadcast( nHandle, aValue );
switch( nHandle )
{
case LAYOUTMANAGER_PROPHANDLE_MENUBARCLOSER:
implts_updateMenuBarClose();
break;
case LAYOUTMANAGER_PROPHANDLE_REFRESHVISIBILITY:
{
bool bValue(false);
if (( aValue >>= bValue ) && bValue )
{
SolarMutexClearableGuard aReadLock;
ToolbarLayoutManager* pToolbarManager = m_xToolbarManager.get();
bool bAutomaticToolbars( m_bAutomaticToolbars );
aReadLock.clear();
if ( pToolbarManager )
pToolbarManager->refreshToolbarsVisibility( bAutomaticToolbars );
}
break;
}
case LAYOUTMANAGER_PROPHANDLE_HIDECURRENTUI:
implts_setCurrentUIVisibility( !m_bHideCurrentUI );
break;
case LAYOUTMANAGER_PROPHANDLE_REFRESHTOOLTIP:
if (m_xToolbarManager.is())
m_xToolbarManager->updateToolbarsTips();
break;
default: break;
}
}
namespace detail
{
class InfoHelperBuilder
{
private:
std::unique_ptr<::cppu::OPropertyArrayHelper> m_pInfoHelper;
public:
explicit InfoHelperBuilder(const LayoutManager &rManager)
{
uno::Sequence< beans::Property > aProperties;
rManager.describeProperties(aProperties);
m_pInfoHelper.reset( new ::cppu::OPropertyArrayHelper(aProperties, true) );
}
InfoHelperBuilder(const InfoHelperBuilder&) = delete;
InfoHelperBuilder& operator=(const InfoHelperBuilder&) = delete;
::cppu::OPropertyArrayHelper& getHelper() { return *m_pInfoHelper; }
};
}
::cppu::IPropertyArrayHelper& SAL_CALL LayoutManager::getInfoHelper()
{
static detail::InfoHelperBuilder INFO(*this);
return INFO.getHelper();
}
uno::Reference< beans::XPropertySetInfo > SAL_CALL LayoutManager::getPropertySetInfo()
{
static uno::Reference< beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
return xInfo;
}
} // namespace framework
extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
com_sun_star_comp_framework_LayoutManager_get_implementation(
css::uno::XComponentContext *context,
css::uno::Sequence<css::uno::Any> const &)
{
return cppu::acquire(new framework::LayoutManager(context));
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */