diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
commit | 940b4d1848e8c70ab7642901a68594e8016caffc (patch) | |
tree | eb72f344ee6c3d9b80a7ecc079ea79e9fba8676d /framework/source/uifactory | |
parent | Initial commit. (diff) | |
download | libreoffice-940b4d1848e8c70ab7642901a68594e8016caffc.tar.xz libreoffice-940b4d1848e8c70ab7642901a68594e8016caffc.zip |
Adding upstream version 1:7.0.4.upstream/1%7.0.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'framework/source/uifactory')
-rw-r--r-- | framework/source/uifactory/addonstoolbarfactory.cxx | 212 | ||||
-rw-r--r-- | framework/source/uifactory/factoryconfiguration.cxx | 285 | ||||
-rw-r--r-- | framework/source/uifactory/menubarfactory.cxx | 171 | ||||
-rw-r--r-- | framework/source/uifactory/statusbarfactory.cxx | 85 | ||||
-rw-r--r-- | framework/source/uifactory/toolbarfactory.cxx | 85 | ||||
-rw-r--r-- | framework/source/uifactory/uicontrollerfactory.cxx | 397 | ||||
-rw-r--r-- | framework/source/uifactory/uielementfactorymanager.cxx | 569 | ||||
-rw-r--r-- | framework/source/uifactory/windowcontentfactorymanager.cxx | 223 |
8 files changed, 2027 insertions, 0 deletions
diff --git a/framework/source/uifactory/addonstoolbarfactory.cxx b/framework/source/uifactory/addonstoolbarfactory.cxx new file mode 100644 index 000000000..021d3dc02 --- /dev/null +++ b/framework/source/uifactory/addonstoolbarfactory.cxx @@ -0,0 +1,212 @@ +/* -*- 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 <uielement/addonstoolbarwrapper.hxx> + +#include <com/sun/star/frame/ModuleManager.hpp> +#include <com/sun/star/frame/XModuleManager2.hpp> +#include <com/sun/star/frame/XFrame.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/ui/XUIElementFactory.hpp> + +#include <cppuhelper/implbase.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <o3tl/safeint.hxx> +#include <vcl/svapp.hxx> + +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::frame; +using namespace com::sun::star::beans; +using namespace com::sun::star::util; +using namespace ::com::sun::star::ui; +using namespace framework; + +namespace { + +class AddonsToolBarFactory : public ::cppu::WeakImplHelper< css::lang::XServiceInfo , + css::ui::XUIElementFactory > +{ +public: + explicit AddonsToolBarFactory( const css::uno::Reference< css::uno::XComponentContext >& xContext ); + + virtual OUString SAL_CALL getImplementationName() override + { + return "com.sun.star.comp.framework.AddonsToolBarFactory"; + } + + virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override + { + return cppu::supportsService(this, ServiceName); + } + + virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override + { + return {"com.sun.star.ui.ToolBarFactory"}; + } + + // XUIElementFactory + virtual css::uno::Reference< css::ui::XUIElement > SAL_CALL createUIElement( const OUString& ResourceURL, const css::uno::Sequence< css::beans::PropertyValue >& Args ) override; + + bool hasButtonsInContext( const css::uno::Sequence< css::uno::Sequence< css::beans::PropertyValue > >& rPropSeq, + const css::uno::Reference< css::frame::XFrame >& rFrame ); + +private: + css::uno::Reference< css::uno::XComponentContext > m_xContext; + css::uno::Reference< css::frame::XModuleManager2 > m_xModuleManager; +}; + +AddonsToolBarFactory::AddonsToolBarFactory( + const css::uno::Reference< css::uno::XComponentContext >& xContext ) : + m_xContext( xContext ) + , m_xModuleManager( ModuleManager::create( xContext ) ) +{ +} + +bool IsCorrectContext( const OUString& rModuleIdentifier, const OUString& aContextList ) +{ + if ( aContextList.isEmpty() ) + return true; + + if ( !rModuleIdentifier.isEmpty() ) + { + sal_Int32 nIndex = aContextList.indexOf( rModuleIdentifier ); + return ( nIndex >= 0 ); + } + + return false; +} + +bool AddonsToolBarFactory::hasButtonsInContext( + const Sequence< Sequence< PropertyValue > >& rPropSeqSeq, + const Reference< XFrame >& rFrame ) +{ + OUString aModuleIdentifier; + try + { + aModuleIdentifier = m_xModuleManager->identify( rFrame ); + } + catch ( const RuntimeException& ) + { + throw; + } + catch ( const Exception& ) + { + } + + // Check before we create a toolbar that we have at least one button in + // the current frame context. + for ( Sequence<PropertyValue> const & props : rPropSeqSeq ) + { + bool bIsButton( true ); + bool bIsCorrectContext( false ); + sal_uInt32 nPropChecked( 0 ); + + for ( PropertyValue const & prop : props ) + { + if ( prop.Name == "Context" ) + { + OUString aContextList; + if ( prop.Value >>= aContextList ) + bIsCorrectContext = IsCorrectContext( aModuleIdentifier, aContextList ); + nPropChecked++; + } + else if ( prop.Name == "URL" ) + { + OUString aURL; + prop.Value >>= aURL; + bIsButton = aURL != "private:separator"; + nPropChecked++; + } + + if ( nPropChecked == 2 ) + break; + } + + if ( bIsButton && bIsCorrectContext ) + return true; + } + + return false; +} + +// XUIElementFactory +Reference< XUIElement > SAL_CALL AddonsToolBarFactory::createUIElement( + const OUString& ResourceURL, + const Sequence< PropertyValue >& Args ) +{ + SolarMutexGuard g; + + Sequence< Sequence< PropertyValue > > aConfigData; + Reference< XFrame > xFrame; + OUString aResourceURL( ResourceURL ); + + for ( PropertyValue const & arg : Args ) + { + if ( arg.Name == "ConfigurationData" ) + arg.Value >>= aConfigData; + else if ( arg.Name == "Frame" ) + arg.Value >>= xFrame; + else if ( arg.Name == "ResourceURL" ) + arg.Value >>= aResourceURL; + } + + if ( !aResourceURL.startsWith("private:resource/toolbar/addon_") ) + throw IllegalArgumentException(); + + // Identify frame and determine module identifier to look for context based buttons + Reference< css::ui::XUIElement > xToolBar; + if ( xFrame.is() && + aConfigData.hasElements() && + hasButtonsInContext( aConfigData, xFrame )) + { + PropertyValue aPropValue; + Sequence< Any > aPropSeq( 3 ); + aPropValue.Name = "Frame"; + aPropValue.Value <<= xFrame; + aPropSeq[0] <<= aPropValue; + aPropValue.Name = "ConfigurationData"; + aPropValue.Value <<= aConfigData; + aPropSeq[1] <<= aPropValue; + aPropValue.Name = "ResourceURL"; + aPropValue.Value <<= aResourceURL; + aPropSeq[2] <<= aPropValue; + + SolarMutexGuard aGuard; + AddonsToolBarWrapper* pToolBarWrapper = new AddonsToolBarWrapper( m_xContext ); + xToolBar.set( static_cast<OWeakObject *>(pToolBarWrapper), UNO_QUERY ); + Reference< XInitialization > xInit( xToolBar, UNO_QUERY ); + xInit->initialize( aPropSeq ); + } + + return xToolBar; +} + +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_framework_AddonsToolBarFactory_get_implementation( + css::uno::XComponentContext *context, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new AddonsToolBarFactory(context)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/framework/source/uifactory/factoryconfiguration.cxx b/framework/source/uifactory/factoryconfiguration.cxx new file mode 100644 index 000000000..485b5a0a9 --- /dev/null +++ b/framework/source/uifactory/factoryconfiguration.cxx @@ -0,0 +1,285 @@ +/* -*- 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 <uifactory/factoryconfiguration.hxx> +#include <services.h> + +#include <helper/mischelper.hxx> + +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/configuration/theDefaultProvider.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/container/XContainer.hpp> + +#include <comphelper/propertysequence.hxx> + +// Defines + +using namespace com::sun::star; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::beans; +using namespace com::sun::star::container; + +// Namespace + +namespace framework +{ +static OUString getHashKeyFromStrings( const OUString& aCommandURL, const OUString& aModuleName ) +{ + return aCommandURL + "-" + aModuleName; +} + +// XInterface, XTypeProvider + +ConfigurationAccess_ControllerFactory::ConfigurationAccess_ControllerFactory( const Reference< XComponentContext >& rxContext, const OUString& _sRoot ) : + m_aPropCommand( "Command" ), + m_aPropModule( "Module" ), + m_aPropController( "Controller" ), + m_aPropValue( "Value" ), + m_sRoot(_sRoot), + m_bConfigAccessInitialized( false ) +{ + m_xConfigProvider = configuration::theDefaultProvider::get( rxContext ); +} + +ConfigurationAccess_ControllerFactory::~ConfigurationAccess_ControllerFactory() +{ + osl::MutexGuard g(m_mutex); + + Reference< XContainer > xContainer( m_xConfigAccess, UNO_QUERY ); + if ( xContainer.is() ) + xContainer->removeContainerListener(m_xConfigAccessListener); +} + +OUString ConfigurationAccess_ControllerFactory::getServiceFromCommandModule( const OUString& rCommandURL, const OUString& rModule ) const +{ + osl::MutexGuard g(m_mutex); + MenuControllerMap::const_iterator pIter = m_aMenuControllerMap.find( getHashKeyFromStrings( rCommandURL, rModule )); + + if ( pIter != m_aMenuControllerMap.end() ) + return pIter->second.m_aImplementationName; + else if ( !rModule.isEmpty() ) + { + // Try to detect if we have a generic popup menu controller + pIter = m_aMenuControllerMap.find( getHashKeyFromStrings( rCommandURL, OUString() )); + + if ( pIter != m_aMenuControllerMap.end() ) + return pIter->second.m_aImplementationName; + } + + return OUString(); +} +OUString ConfigurationAccess_ControllerFactory::getValueFromCommandModule( const OUString& rCommandURL, const OUString& rModule ) const +{ + osl::MutexGuard g(m_mutex); + + MenuControllerMap::const_iterator pIter = m_aMenuControllerMap.find( getHashKeyFromStrings( rCommandURL, rModule )); + + if ( pIter != m_aMenuControllerMap.end() ) + return pIter->second.m_aValue; + else if ( !rModule.isEmpty() ) + { + // Try to detect if we have a generic popup menu controller + pIter = m_aMenuControllerMap.find( getHashKeyFromStrings( rCommandURL, OUString() )); + + if ( pIter != m_aMenuControllerMap.end() ) + return pIter->second.m_aValue; + } + + return OUString(); +} + +void ConfigurationAccess_ControllerFactory::addServiceToCommandModule( + const OUString& rCommandURL, + const OUString& rModule, + const OUString& rServiceSpecifier ) +{ + osl::MutexGuard g(m_mutex); + + OUString aHashKey = getHashKeyFromStrings( rCommandURL, rModule ); + m_aMenuControllerMap.emplace( aHashKey,ControllerInfo(rServiceSpecifier,OUString()) ); +} + +void ConfigurationAccess_ControllerFactory::removeServiceFromCommandModule( + const OUString& rCommandURL, + const OUString& rModule ) +{ + osl::MutexGuard g(m_mutex); + + OUString aHashKey = getHashKeyFromStrings( rCommandURL, rModule ); + m_aMenuControllerMap.erase( aHashKey ); +} + +// container.XContainerListener +void SAL_CALL ConfigurationAccess_ControllerFactory::elementInserted( const ContainerEvent& aEvent ) +{ + OUString aCommand; + OUString aModule; + OUString aService; + OUString aValue; + + osl::MutexGuard g(m_mutex); + + if ( impl_getElementProps( aEvent.Element, aCommand, aModule, aService, aValue )) + { + // Create hash key from command and module as they are together a primary key to + // the UNO service that implements the popup menu controller. + OUString aHashKey( getHashKeyFromStrings( aCommand, aModule )); + ControllerInfo& rControllerInfo = m_aMenuControllerMap[ aHashKey ]; + rControllerInfo.m_aImplementationName = aService; + rControllerInfo.m_aValue = aValue; + } +} + +void SAL_CALL ConfigurationAccess_ControllerFactory::elementRemoved ( const ContainerEvent& aEvent ) +{ + OUString aCommand; + OUString aModule; + OUString aService; + OUString aValue; + + osl::MutexGuard g(m_mutex); + + if ( impl_getElementProps( aEvent.Element, aCommand, aModule, aService, aValue )) + { + // Create hash key from command and module as they are together a primary key to + // the UNO service that implements the popup menu controller. + OUString aHashKey( getHashKeyFromStrings( aCommand, aModule )); + m_aMenuControllerMap.erase( aHashKey ); + } +} + +void SAL_CALL ConfigurationAccess_ControllerFactory::elementReplaced( const ContainerEvent& aEvent ) +{ + elementInserted(aEvent); +} + +// lang.XEventListener +void SAL_CALL ConfigurationAccess_ControllerFactory::disposing( const EventObject& ) +{ + // remove our reference to the config access + osl::MutexGuard g(m_mutex); + m_xConfigAccess.clear(); +} + +void ConfigurationAccess_ControllerFactory::readConfigurationData() +{ + // SAFE + osl::ClearableMutexGuard aLock( m_mutex ); + + if ( !m_bConfigAccessInitialized ) + { + uno::Sequence<uno::Any> aArgs(comphelper::InitAnyPropertySequence( + { + {"nodepath", uno::Any(m_sRoot)} + })); + try + { + m_xConfigAccess.set( m_xConfigProvider->createInstanceWithArguments(SERVICENAME_CFGREADACCESS,aArgs ), UNO_QUERY ); + } + catch ( const WrappedTargetException& ) + { + } + + m_bConfigAccessInitialized = true; + } + + if ( !m_xConfigAccess.is() ) + return; + + // Read and update configuration data + updateConfigurationData(); + + uno::Reference< container::XContainer > xContainer( m_xConfigAccess, uno::UNO_QUERY ); + // UNSAFE + aLock.clear(); + + if ( xContainer.is() ) + { + m_xConfigAccessListener = new WeakContainerListener(this); + xContainer->addContainerListener(m_xConfigAccessListener); + } +} + +void ConfigurationAccess_ControllerFactory::updateConfigurationData() +{ + osl::MutexGuard g(m_mutex); + if ( !m_xConfigAccess.is() ) + return; + + const Sequence< OUString > aPopupMenuControllers = m_xConfigAccess->getElementNames(); + + OUString aCommand; + OUString aModule; + OUString aService; + OUString aHashKey; + OUString aValue; + + m_aMenuControllerMap.clear(); + for ( OUString const & name : aPopupMenuControllers ) + { + try + { + if ( impl_getElementProps( m_xConfigAccess->getByName( name ), aCommand, aModule, aService,aValue )) + { + // Create hash key from command and module as they are together a primary key to + // the UNO service that implements the popup menu controller. + aHashKey = getHashKeyFromStrings( aCommand, aModule ); + m_aMenuControllerMap.emplace( aHashKey, ControllerInfo(aService,aValue) ); + } + } + catch ( const NoSuchElementException& ) + { + } + catch ( const WrappedTargetException& ) + { + } + } +} + +bool ConfigurationAccess_ControllerFactory::impl_getElementProps( const Any& aElement, OUString& aCommand, OUString& aModule, OUString& aServiceSpecifier,OUString& aValue ) const +{ + Reference< XPropertySet > xPropertySet; + aElement >>= xPropertySet; + + if ( xPropertySet.is() ) + { + try + { + xPropertySet->getPropertyValue( m_aPropCommand ) >>= aCommand; + xPropertySet->getPropertyValue( m_aPropModule ) >>= aModule; + xPropertySet->getPropertyValue( m_aPropController ) >>= aServiceSpecifier; + xPropertySet->getPropertyValue( m_aPropValue ) >>= aValue; + } + catch ( const css::beans::UnknownPropertyException& ) + { + return false; + } + catch ( const css::lang::WrappedTargetException& ) + { + return false; + } + } + + return true; +} +} // namespace framework + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/framework/source/uifactory/menubarfactory.cxx b/framework/source/uifactory/menubarfactory.cxx new file mode 100644 index 000000000..2899b6428 --- /dev/null +++ b/framework/source/uifactory/menubarfactory.cxx @@ -0,0 +1,171 @@ +/* -*- 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 <uifactory/menubarfactory.hxx> + +#include <uielement/menubarwrapper.hxx> + +#include <com/sun/star/frame/ModuleManager.hpp> +#include <com/sun/star/frame/XFrame.hpp> +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/ui/theModuleUIConfigurationManagerSupplier.hpp> +#include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> + +#include <vcl/svapp.hxx> + +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::frame; +using namespace com::sun::star::beans; +using namespace com::sun::star::util; +using namespace ::com::sun::star::ui; + +namespace framework +{ + +MenuBarFactory::MenuBarFactory( const css::uno::Reference< css::uno::XComponentContext >& xContext ) + : m_xContext( xContext ) +{ +} + +MenuBarFactory::~MenuBarFactory() +{ +} + +// XUIElementFactory +Reference< XUIElement > SAL_CALL MenuBarFactory::createUIElement( + const OUString& ResourceURL, + const Sequence< PropertyValue >& Args ) +{ + Reference< css::ui::XUIElement > xMenuBar( + static_cast<OWeakObject *>(new MenuBarWrapper(m_xContext)), UNO_QUERY); + CreateUIElement(ResourceURL, Args, "private:resource/menubar/", xMenuBar, m_xContext); + return xMenuBar; +} + +void MenuBarFactory::CreateUIElement(const OUString& ResourceURL + ,const Sequence< PropertyValue >& Args + ,const OUString& ResourceType + ,const Reference< css::ui::XUIElement >& _xMenuBar + ,const css::uno::Reference< css::uno::XComponentContext >& _rxContext) +{ + sal_Int32 nConfigPropertyIndex( Args.getLength() ); + sal_Int32 nURLPropertyIndex( Args.getLength() ); + Reference< XUIConfigurationManager > xCfgMgr; + Reference< XFrame > xFrame; + OUString aResourceURL( ResourceURL ); + + for ( sal_Int32 n = 0; n < Args.getLength(); n++ ) + { + if ( Args[n].Name == "ConfigurationSource" ) + { + nConfigPropertyIndex = n; + Args[n].Value >>= xCfgMgr; + } + else if ( Args[n].Name == "ResourceURL" ) + { + nURLPropertyIndex = n; + Args[n].Value >>= aResourceURL; + } + else if ( Args[n].Name == "Frame" ) + Args[n].Value >>= xFrame; + } + if (!aResourceURL.startsWith(ResourceType)) + throw IllegalArgumentException(); + + // Identify frame and determine document based ui configuration manager/module ui configuration manager + if ( xFrame.is() && !xCfgMgr.is() ) + { + bool bHasSettings( false ); + Reference< XModel > xModel; + + Reference< XController > xController = xFrame->getController(); + if ( xController.is() ) + xModel = xController->getModel(); + + if ( xModel.is() ) + { + Reference< XUIConfigurationManagerSupplier > xUIConfigurationManagerSupplier( xModel, UNO_QUERY ); + if ( xUIConfigurationManagerSupplier.is() ) + { + xCfgMgr = xUIConfigurationManagerSupplier->getUIConfigurationManager(); + bHasSettings = xCfgMgr->hasSettings( aResourceURL ); + } + } + + if ( !bHasSettings ) + { + Reference< css::frame::XModuleManager2 > xModuleManager = + ModuleManager::create( _rxContext ); + OUString aModuleIdentifier = xModuleManager->identify( Reference<XInterface>( xFrame, UNO_QUERY ) ); + if ( !aModuleIdentifier.isEmpty() ) + { + Reference< XModuleUIConfigurationManagerSupplier > xModuleCfgSupplier = + theModuleUIConfigurationManagerSupplier::get( _rxContext ); + xCfgMgr = xModuleCfgSupplier->getUIConfigurationManager( aModuleIdentifier ); + } + } + } + + sal_Int32 nSeqLength( Args.getLength() ); + if ( Args.getLength() == nConfigPropertyIndex ) + nSeqLength++; + if ( Args.getLength() == nURLPropertyIndex ) + nSeqLength++; + if ( nConfigPropertyIndex == nURLPropertyIndex ) + nURLPropertyIndex++; + + Sequence< Any > aPropSeq( nSeqLength ); + for ( sal_Int32 n = 0; n < aPropSeq.getLength(); n++ ) + { + PropertyValue aPropValue; + if ( n == nURLPropertyIndex ) + { + aPropValue.Name = "ResourceURL"; + aPropValue.Value <<= aResourceURL; + } + else if ( n == nConfigPropertyIndex ) + { + aPropValue.Name = "ConfigurationSource"; + aPropValue.Value <<= xCfgMgr; + } + else + aPropValue = Args[n]; + + aPropSeq[n] <<= aPropValue; + } + + SolarMutexGuard aGuard; + Reference< XInitialization > xInit( _xMenuBar, UNO_QUERY ); + xInit->initialize( aPropSeq ); +} + +} // namespace framework + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_framework_MenuBarFactory_get_implementation( + css::uno::XComponentContext *context, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new framework::MenuBarFactory(context)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/framework/source/uifactory/statusbarfactory.cxx b/framework/source/uifactory/statusbarfactory.cxx new file mode 100644 index 000000000..6791db896 --- /dev/null +++ b/framework/source/uifactory/statusbarfactory.cxx @@ -0,0 +1,85 @@ +/* -*- 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 <uifactory/menubarfactory.hxx> +#include <uielement/statusbarwrapper.hxx> + +#include <cppuhelper/supportsservice.hxx> + +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::beans; +using namespace com::sun::star::util; +using namespace ::com::sun::star::ui; + +using namespace framework; + +namespace { + +class StatusBarFactory : public MenuBarFactory +{ +public: + explicit StatusBarFactory( const css::uno::Reference< css::uno::XComponentContext >& xContext ); + + virtual OUString SAL_CALL getImplementationName() override + { + return "com.sun.star.comp.framework.StatusBarFactory"; + } + + virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override + { + return cppu::supportsService(this, ServiceName); + } + + virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override + { + return {"com.sun.star.ui.StatusBarFactory"}; + } + + // XUIElementFactory + virtual css::uno::Reference< css::ui::XUIElement > SAL_CALL createUIElement( const OUString& ResourceURL, const css::uno::Sequence< css::beans::PropertyValue >& Args ) override; +}; + +StatusBarFactory::StatusBarFactory( const css::uno::Reference< css::uno::XComponentContext >& xContext ) : + MenuBarFactory( xContext ) +{ +} + +// XUIElementFactory +Reference< XUIElement > SAL_CALL StatusBarFactory::createUIElement( + const OUString& ResourceURL, + const Sequence< PropertyValue >& Args ) +{ + Reference< css::ui::XUIElement > xStatusBar( + static_cast<OWeakObject *>(new StatusBarWrapper(m_xContext)), UNO_QUERY); + MenuBarFactory::CreateUIElement(ResourceURL, Args, "private:resource/statusbar/", xStatusBar, m_xContext); + return xStatusBar; +} + +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_framework_StatusBarFactory_get_implementation( + css::uno::XComponentContext *context, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new StatusBarFactory(context)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/framework/source/uifactory/toolbarfactory.cxx b/framework/source/uifactory/toolbarfactory.cxx new file mode 100644 index 000000000..f797ab2e6 --- /dev/null +++ b/framework/source/uifactory/toolbarfactory.cxx @@ -0,0 +1,85 @@ +/* -*- 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 <cppuhelper/supportsservice.hxx> +#include <vcl/svapp.hxx> +#include <uielement/toolbarwrapper.hxx> +#include <uifactory/menubarfactory.hxx> + +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::beans; +using namespace com::sun::star::util; +using namespace ::com::sun::star::ui; +using namespace framework; + +namespace { + +class ToolBarFactory : public MenuBarFactory +{ +public: + explicit ToolBarFactory( const css::uno::Reference< css::uno::XComponentContext >& xContext ); + + virtual OUString SAL_CALL getImplementationName() override + { + return "com.sun.star.comp.framework.ToolBarFactory"; + } + + virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override + { + return cppu::supportsService(this, ServiceName); + } + + virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override + { + return {"com.sun.star.ui.ToolBarFactory"}; + } + + // XUIElementFactory + virtual css::uno::Reference< css::ui::XUIElement > SAL_CALL createUIElement( + const OUString& ResourceURL, const css::uno::Sequence< css::beans::PropertyValue >& Args ) override; +}; + +ToolBarFactory::ToolBarFactory( const css::uno::Reference< css::uno::XComponentContext >& xContext ) : + MenuBarFactory( xContext ) +{ +} + +// XUIElementFactory +Reference< XUIElement > SAL_CALL ToolBarFactory::createUIElement( + const OUString& ResourceURL, + const Sequence< PropertyValue >& Args ) +{ + Reference< css::ui::XUIElement > xToolBar( + static_cast<OWeakObject *>(new ToolBarWrapper(m_xContext)), UNO_QUERY); + CreateUIElement(ResourceURL, Args, "private:resource/toolbar/", xToolBar, m_xContext); + return xToolBar; +} + +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_framework_ToolBarFactory_get_implementation( + css::uno::XComponentContext *context, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new ToolBarFactory(context)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/framework/source/uifactory/uicontrollerfactory.cxx b/framework/source/uifactory/uicontrollerfactory.cxx new file mode 100644 index 000000000..35d883a4c --- /dev/null +++ b/framework/source/uifactory/uicontrollerfactory.cxx @@ -0,0 +1,397 @@ +/* -*- 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 <uifactory/factoryconfiguration.hxx> + +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/frame/XUIControllerFactory.hpp> + +#include <rtl/ref.hxx> +#include <cppuhelper/basemutex.hxx> +#include <cppuhelper/compbase.hxx> +#include <cppuhelper/supportsservice.hxx> + +using namespace css::uno; +using namespace css::lang; +using namespace css::beans; +using namespace css::container; +using namespace css::frame; +using namespace framework; + +namespace { + +typedef ::cppu::WeakComponentImplHelper< + css::lang::XServiceInfo, + css::frame::XUIControllerFactory > UIControllerFactory_BASE; + +class UIControllerFactory : private cppu::BaseMutex, + public UIControllerFactory_BASE +{ +public: + virtual ~UIControllerFactory() override; + + // XMultiComponentFactory + virtual css::uno::Reference< css::uno::XInterface > SAL_CALL createInstanceWithContext( const OUString& aServiceSpecifier, const css::uno::Reference< css::uno::XComponentContext >& Context ) override; + virtual css::uno::Reference< css::uno::XInterface > SAL_CALL createInstanceWithArgumentsAndContext( const OUString& ServiceSpecifier, const css::uno::Sequence< css::uno::Any >& Arguments, const css::uno::Reference< css::uno::XComponentContext >& Context ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getAvailableServiceNames() override; + + // XUIControllerRegistration + virtual sal_Bool SAL_CALL hasController( const OUString& aCommandURL, const OUString& aModuleName ) override; + virtual void SAL_CALL registerController( const OUString& aCommandURL, const OUString& aModuleName, const OUString& aControllerImplementationName ) override; + virtual void SAL_CALL deregisterController( const OUString& aCommandURL, const OUString& aModuleName ) override; + +protected: + UIControllerFactory( const css::uno::Reference< css::uno::XComponentContext >& xContext, const OUString &rUINode ); + bool m_bConfigRead; + css::uno::Reference< css::uno::XComponentContext > m_xContext; + rtl::Reference<ConfigurationAccess_ControllerFactory> m_pConfigAccess; + +private: + virtual void SAL_CALL disposing() final override; +}; + +UIControllerFactory::UIControllerFactory( + const Reference< XComponentContext >& xContext, + const OUString &rConfigurationNode ) + : UIControllerFactory_BASE(m_aMutex) + , m_bConfigRead( false ) + , m_xContext( xContext ) + , m_pConfigAccess() +{ + m_pConfigAccess = new ConfigurationAccess_ControllerFactory(m_xContext, + "/org.openoffice.Office.UI.Controller/Registered/" + rConfigurationNode); +} + +UIControllerFactory::~UIControllerFactory() +{ + disposing(); +} + +void SAL_CALL UIControllerFactory::disposing() +{ + osl::MutexGuard g(rBHelper.rMutex); + m_pConfigAccess.clear(); +} + +// XMultiComponentFactory +Reference< XInterface > SAL_CALL UIControllerFactory::createInstanceWithContext( + const OUString& aServiceSpecifier, + const Reference< XComponentContext >& ) +{ + // SAFE + osl::MutexGuard g(rBHelper.rMutex); + + if ( !m_bConfigRead ) + { + m_bConfigRead = true; + m_pConfigAccess->readConfigurationData(); + } + + OUString aServiceName = m_pConfigAccess->getServiceFromCommandModule( aServiceSpecifier, OUString() ); + if ( !aServiceName.isEmpty() ) + return m_xContext->getServiceManager()->createInstanceWithContext( aServiceName, m_xContext ); + else + return Reference< XInterface >(); + // SAFE +} + +Reference< XInterface > SAL_CALL UIControllerFactory::createInstanceWithArgumentsAndContext( + const OUString& ServiceSpecifier, + const Sequence< Any >& Arguments, + const Reference< XComponentContext >& ) +{ + const OUString aPropModuleName( "ModuleIdentifier" ); + const OUString aPropValueName( "Value" ); + + OUString aPropName; + PropertyValue aPropValue; + + // Retrieve the optional module name from the Arguments sequence. It is used as a part of + // the hash map key to support different controller implementation for the same URL but different + // module!! + for ( Any const & arg : Arguments ) + { + if (( arg >>= aPropValue ) && ( aPropValue.Name == aPropModuleName )) + { + aPropValue.Value >>= aPropName; + break; + } + } + + Sequence< Any > aNewArgs( Arguments ); + + sal_Int32 nAppendIndex = aNewArgs.getLength(); + aNewArgs.realloc( aNewArgs.getLength() + 2 ); + + // Append the command URL to the Arguments sequence so that one controller can be + // used for more than one command URL. + aPropValue.Name = "CommandURL"; + aPropValue.Value <<= ServiceSpecifier; + aNewArgs[nAppendIndex] <<= aPropValue; + + // Append the optional value argument. It's an empty string if no additional info + // is provided to the controller. + OUString aValue = m_pConfigAccess->getValueFromCommandModule( ServiceSpecifier, aPropName ); + aPropValue.Name = aPropValueName; + aPropValue.Value <<= aValue; + aNewArgs[nAppendIndex+1] <<= aPropValue; + + { + OUString aServiceName; + { // SAFE + osl::MutexGuard g(rBHelper.rMutex); + + if ( !m_bConfigRead ) + { + m_bConfigRead = true; + m_pConfigAccess->readConfigurationData(); + } + + aServiceName = m_pConfigAccess->getServiceFromCommandModule( ServiceSpecifier, aPropName ); + } // SAFE + + if ( !aServiceName.isEmpty() ) + return m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext( aServiceName, aNewArgs, m_xContext ); + else + return Reference< XInterface >(); + } +} + +Sequence< OUString > SAL_CALL UIControllerFactory::getAvailableServiceNames() +{ + return Sequence< OUString >(); +} + +// XUIControllerRegistration +sal_Bool SAL_CALL UIControllerFactory::hasController( + const OUString& aCommandURL, + const OUString& aModuleName ) +{ + osl::MutexGuard g(rBHelper.rMutex); + + if ( !m_bConfigRead ) + { + m_bConfigRead = true; + m_pConfigAccess->readConfigurationData(); + } + + return ( !m_pConfigAccess->getServiceFromCommandModule( aCommandURL, aModuleName ).isEmpty() ); +} + +void SAL_CALL UIControllerFactory::registerController( + const OUString& aCommandURL, + const OUString& aModuleName, + const OUString& aControllerImplementationName ) +{ + // SAFE + osl::MutexGuard g(rBHelper.rMutex); + + if ( !m_bConfigRead ) + { + m_bConfigRead = true; + m_pConfigAccess->readConfigurationData(); + } + + m_pConfigAccess->addServiceToCommandModule( aCommandURL, aModuleName, aControllerImplementationName ); + // SAFE +} + +void SAL_CALL UIControllerFactory::deregisterController( + const OUString& aCommandURL, + const OUString& aModuleName ) +{ + // SAFE + osl::MutexGuard g(rBHelper.rMutex); + + if ( !m_bConfigRead ) + { + m_bConfigRead = true; + m_pConfigAccess->readConfigurationData(); + } + + m_pConfigAccess->removeServiceFromCommandModule( aCommandURL, aModuleName ); + // SAFE +} + +class PopupMenuControllerFactory : public UIControllerFactory +{ +public: + explicit PopupMenuControllerFactory( const css::uno::Reference< css::uno::XComponentContext >& xContext ); + + virtual OUString SAL_CALL getImplementationName() override + { + return "com.sun.star.comp.framework.PopupMenuControllerFactory"; + } + + virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override + { + return cppu::supportsService(this, ServiceName); + } + + virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override + { + return {"com.sun.star.frame.PopupMenuControllerFactory"}; + } + +}; + +PopupMenuControllerFactory::PopupMenuControllerFactory( const Reference< XComponentContext >& xContext ) : + UIControllerFactory( xContext, "PopupMenu" ) +{ +} + +struct PopupMenuControllerFactoryInstance { + explicit PopupMenuControllerFactoryInstance( + css::uno::Reference<css::uno::XComponentContext> const & context): + instance(static_cast<cppu::OWeakObject *>( + new PopupMenuControllerFactory(context))) + { + } + + css::uno::Reference<css::uno::XInterface> instance; +}; + +struct PopupMenuControllerFactorySingleton: + public rtl::StaticWithArg< + PopupMenuControllerFactoryInstance, + css::uno::Reference<css::uno::XComponentContext>, + PopupMenuControllerFactorySingleton> +{}; + +class ToolbarControllerFactory : public UIControllerFactory +{ +public: + explicit ToolbarControllerFactory( const css::uno::Reference< css::uno::XComponentContext >& xContext ); + + virtual OUString SAL_CALL getImplementationName() override + { + return "com.sun.star.comp.framework.ToolBarControllerFactory"; + } + + virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override + { + return cppu::supportsService(this, ServiceName); + } + + virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override + { + return {"com.sun.star.frame.ToolbarControllerFactory"}; + } + +}; + +ToolbarControllerFactory::ToolbarControllerFactory( const Reference< XComponentContext >& xContext ) : + UIControllerFactory( xContext, "ToolBar" ) +{ +} + +struct ToolbarControllerFactoryInstance { + explicit ToolbarControllerFactoryInstance( + css::uno::Reference<css::uno::XComponentContext> const & context): + instance(static_cast<cppu::OWeakObject *>( + new ToolbarControllerFactory(context))) + { + } + + css::uno::Reference<css::uno::XInterface> instance; +}; + +struct ToolbarControllerFactorySingleton: + public rtl::StaticWithArg< + ToolbarControllerFactoryInstance, + css::uno::Reference<css::uno::XComponentContext>, + ToolbarControllerFactorySingleton> +{}; + +class StatusbarControllerFactory : public UIControllerFactory +{ +public: + explicit StatusbarControllerFactory( const css::uno::Reference< css::uno::XComponentContext >& xContext ); + + virtual OUString SAL_CALL getImplementationName() override + { + return "com.sun.star.comp.framework.StatusBarControllerFactory"; + } + + virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override + { + return cppu::supportsService(this, ServiceName); + } + + virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override + { + return {"com.sun.star.frame.StatusbarControllerFactory"}; + } + +}; + +StatusbarControllerFactory::StatusbarControllerFactory( const Reference< XComponentContext >& xContext ) : + UIControllerFactory( xContext, "StatusBar" ) +{ +} + +struct StatusbarControllerFactoryInstance { + explicit StatusbarControllerFactoryInstance( + css::uno::Reference<css::uno::XComponentContext> const & context): + instance(static_cast<cppu::OWeakObject *>( + new StatusbarControllerFactory(context))) + { + } + + css::uno::Reference<css::uno::XInterface> instance; +}; + +struct StatusbarControllerFactorySingleton: + public rtl::StaticWithArg< + StatusbarControllerFactoryInstance, + css::uno::Reference<css::uno::XComponentContext>, + StatusbarControllerFactorySingleton> +{}; + +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_framework_PopupMenuControllerFactory_get_implementation( + css::uno::XComponentContext *context, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(static_cast<cppu::OWeakObject *>( + PopupMenuControllerFactorySingleton::get(context).instance.get())); +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_framework_ToolBarControllerFactory_get_implementation( + css::uno::XComponentContext *context, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(static_cast<cppu::OWeakObject *>( + ToolbarControllerFactorySingleton::get(context).instance.get())); +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_framework_StatusBarControllerFactory_get_implementation( + css::uno::XComponentContext *context, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(static_cast<cppu::OWeakObject *>( + StatusbarControllerFactorySingleton::get(context).instance.get())); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/framework/source/uifactory/uielementfactorymanager.cxx b/framework/source/uifactory/uielementfactorymanager.cxx new file mode 100644 index 000000000..68e228683 --- /dev/null +++ b/framework/source/uifactory/uielementfactorymanager.cxx @@ -0,0 +1,569 @@ +/* -*- 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 <sal/config.h> + +#include <uifactory/configurationaccessfactorymanager.hxx> +#include <helper/mischelper.hxx> + +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/configuration/theDefaultProvider.hpp> +#include <com/sun/star/container/ElementExistException.hpp> +#include <com/sun/star/container/XContainer.hpp> +#include <com/sun/star/container/XContainerListener.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/loader/CannotActivateFactoryException.hpp> +#include <com/sun/star/frame/ModuleManager.hpp> +#include <com/sun/star/frame/UnknownModuleException.hpp> +#include <com/sun/star/frame/XFrame.hpp> +#include <com/sun/star/frame/XModuleManager2.hpp> +#include <com/sun/star/ui/XUIElementFactoryManager.hpp> + +#include <rtl/ref.hxx> +#include <sal/log.hxx> +#include <comphelper/propertysequence.hxx> +#include <cppuhelper/basemutex.hxx> +#include <cppuhelper/compbase.hxx> +#include <cppuhelper/supportsservice.hxx> + +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::beans; +using namespace com::sun::star::frame; +using namespace com::sun::star::configuration; +using namespace com::sun::star::container; +using namespace ::com::sun::star::ui; +using namespace framework; + +namespace framework +{ + +// global function needed by both implementations +static OUString getHashKeyFromStrings( const OUString& aType, const OUString& aName, const OUString& aModuleName ) +{ + return aType + "^" + aName + "^" + aModuleName; +} + +ConfigurationAccess_FactoryManager::ConfigurationAccess_FactoryManager( const Reference< XComponentContext >& rxContext, const OUString& _sRoot ) : + m_aPropType( "Type" ), + m_aPropName( "Name" ), + m_aPropModule( "Module" ), + m_aPropFactory( "FactoryImplementation" ), + m_sRoot(_sRoot), + m_bConfigAccessInitialized( false ) +{ + m_xConfigProvider = theDefaultProvider::get( rxContext ); +} + +ConfigurationAccess_FactoryManager::~ConfigurationAccess_FactoryManager() +{ + // SAFE + osl::MutexGuard g(m_aMutex); + + Reference< XContainer > xContainer( m_xConfigAccess, UNO_QUERY ); + if ( xContainer.is() ) + xContainer->removeContainerListener(m_xConfigListener); +} + +OUString ConfigurationAccess_FactoryManager::getFactorySpecifierFromTypeNameModule( const OUString& rType, const OUString& rName, const OUString& rModule ) const +{ + // SAFE + osl::MutexGuard g(m_aMutex); + + FactoryManagerMap::const_iterator pIter = + m_aFactoryManagerMap.find( getHashKeyFromStrings( rType, rName, rModule )); + if ( pIter != m_aFactoryManagerMap.end() ) + return pIter->second; + else + { + pIter = m_aFactoryManagerMap.find( getHashKeyFromStrings( rType, rName, OUString() )); + if ( pIter != m_aFactoryManagerMap.end() ) + return pIter->second; + else + { + // Support factories which uses a defined prefix before the ui name. + sal_Int32 nIndex = rName.indexOf( '_' ); + if ( nIndex > 0 ) + { + OUString aName = rName.copy( 0, nIndex+1 ); + pIter = m_aFactoryManagerMap.find( getHashKeyFromStrings( rType, aName, OUString() )); + if ( pIter != m_aFactoryManagerMap.end() ) + return pIter->second; + } + + pIter = m_aFactoryManagerMap.find( getHashKeyFromStrings( rType, OUString(), OUString() )); + if ( pIter != m_aFactoryManagerMap.end() ) + return pIter->second; + } + } + + return OUString(); +} + +void ConfigurationAccess_FactoryManager::addFactorySpecifierToTypeNameModule( const OUString& rType, const OUString& rName, const OUString& rModule, const OUString& rServiceSpecifier ) +{ + // SAFE + osl::MutexGuard g(m_aMutex); + + OUString aHashKey = getHashKeyFromStrings( rType, rName, rModule ); + + FactoryManagerMap::const_iterator pIter = m_aFactoryManagerMap.find( aHashKey ); + + if ( pIter != m_aFactoryManagerMap.end() ) + throw ElementExistException(); + m_aFactoryManagerMap.emplace( aHashKey, rServiceSpecifier ); +} + +void ConfigurationAccess_FactoryManager::removeFactorySpecifierFromTypeNameModule( const OUString& rType, const OUString& rName, const OUString& rModule ) +{ + // SAFE + osl::MutexGuard g(m_aMutex); + + OUString aHashKey = getHashKeyFromStrings( rType, rName, rModule ); + + FactoryManagerMap::const_iterator pIter = m_aFactoryManagerMap.find( aHashKey ); + + if ( pIter == m_aFactoryManagerMap.end() ) + throw NoSuchElementException(); + m_aFactoryManagerMap.erase( aHashKey ); +} + +Sequence< Sequence< PropertyValue > > ConfigurationAccess_FactoryManager::getFactoriesDescription() const +{ + // SAFE + osl::MutexGuard g(m_aMutex); + + Sequence< Sequence< PropertyValue > > aSeqSeq; + + sal_Int32 nIndex( 0 ); + for ( const auto& rEntry : m_aFactoryManagerMap ) + { + OUString aFactory = rEntry.first; + if ( !aFactory.isEmpty() ) + { + sal_Int32 nToken = 0; + Sequence< PropertyValue > aSeq( 1 ); + + aSeqSeq.realloc( aSeqSeq.getLength() + 1 ); + aSeq[0].Name = m_aPropType; + aSeq[0].Value <<= aFactory.getToken( 0, '^', nToken ); + if ( nToken > 0 ) + { + aSeq.realloc( 2 ); + aSeq[1].Name = m_aPropName; + aSeq[1].Value <<= aFactory.getToken( 0, '^', nToken ); + if ( nToken > 0 ) + { + aSeq.realloc( 3 ); + aSeq[2].Name = m_aPropModule; + aSeq[2].Value <<= aFactory.getToken( 0, '^', nToken ); + } + } + + aSeqSeq[nIndex++] = aSeq; + } + } + + return aSeqSeq; +} + +// container.XContainerListener +void SAL_CALL ConfigurationAccess_FactoryManager::elementInserted( const ContainerEvent& aEvent ) +{ + OUString aType; + OUString aName; + OUString aModule; + OUString aService; + + // SAFE + osl::MutexGuard g(m_aMutex); + + if ( impl_getElementProps( aEvent.Element, aType, aName, aModule, aService )) + { + // Create hash key from type, name and module as they are together a primary key to + // the UNO service that implements a user interface factory. + OUString aHashKey( getHashKeyFromStrings( aType, aName, aModule )); + m_aFactoryManagerMap.emplace( aHashKey, aService ); + } +} + +void SAL_CALL ConfigurationAccess_FactoryManager::elementRemoved ( const ContainerEvent& aEvent ) +{ + OUString aType; + OUString aName; + OUString aModule; + OUString aService; + + // SAFE + osl::MutexGuard g(m_aMutex); + + if ( impl_getElementProps( aEvent.Element, aType, aName, aModule, aService )) + { + // Create hash key from command and model as they are together a primary key to + // the UNO service that implements the popup menu controller. + OUString aHashKey( getHashKeyFromStrings( aType, aName, aModule )); + m_aFactoryManagerMap.erase( aHashKey ); + } +} + +void SAL_CALL ConfigurationAccess_FactoryManager::elementReplaced( const ContainerEvent& aEvent ) +{ + OUString aType; + OUString aName; + OUString aModule; + OUString aService; + + // SAFE + osl::MutexGuard g(m_aMutex); + + if ( impl_getElementProps( aEvent.Element, aType, aName, aModule, aService )) + { + // Create hash key from command and model as they are together a primary key to + // the UNO service that implements the popup menu controller. + OUString aHashKey( getHashKeyFromStrings( aType, aName, aModule )); + m_aFactoryManagerMap.erase( aHashKey ); + m_aFactoryManagerMap.emplace( aHashKey, aService ); + } +} + +// lang.XEventListener +void SAL_CALL ConfigurationAccess_FactoryManager::disposing( const EventObject& ) +{ + // SAFE + // remove our reference to the config access + osl::MutexGuard g(m_aMutex); + m_xConfigAccess.clear(); +} + +void ConfigurationAccess_FactoryManager::readConfigurationData() +{ + // SAFE + osl::MutexGuard g(m_aMutex); + + if ( !m_bConfigAccessInitialized ) + { + Sequence<Any> aArgs(comphelper::InitAnyPropertySequence( + { + {"nodepath", Any(m_sRoot)} + })); + + try + { + m_xConfigAccess.set( m_xConfigProvider->createInstanceWithArguments( + "com.sun.star.configuration.ConfigurationAccess", aArgs ), UNO_QUERY ); + } + catch ( const WrappedTargetException& ) + { + } + + m_bConfigAccessInitialized = true; + } + + if ( !m_xConfigAccess.is() ) + return; + + const Sequence< OUString > aUIElementFactories = m_xConfigAccess->getElementNames(); + + OUString aType; + OUString aName; + OUString aModule; + OUString aService; + OUString aHashKey; + for ( OUString const & factoryName : aUIElementFactories ) + { + if ( impl_getElementProps( m_xConfigAccess->getByName( factoryName ), aType, aName, aModule, aService )) + { + // Create hash key from type, name and module as they are together a primary key to + // the UNO service that implements the user interface element factory. + aHashKey = getHashKeyFromStrings( aType, aName, aModule ); + m_aFactoryManagerMap.emplace( aHashKey, aService ); + } + } + + Reference< XContainer > xContainer( m_xConfigAccess, UNO_QUERY ); + if ( xContainer.is() ) + { + m_xConfigListener = new WeakContainerListener(this); + xContainer->addContainerListener(m_xConfigListener); + } +} + +bool ConfigurationAccess_FactoryManager::impl_getElementProps( const Any& aElement, OUString& rType, OUString& rName, OUString& rModule, OUString& rServiceSpecifier ) const +{ + Reference< XPropertySet > xPropertySet; + aElement >>= xPropertySet; + + if ( xPropertySet.is() ) + { + try + { + xPropertySet->getPropertyValue( m_aPropType ) >>= rType; + xPropertySet->getPropertyValue( m_aPropName ) >>= rName; + xPropertySet->getPropertyValue( m_aPropModule ) >>= rModule; + xPropertySet->getPropertyValue( m_aPropFactory ) >>= rServiceSpecifier; + } + catch ( const css::beans::UnknownPropertyException& ) + { + return false; + } + catch ( const css::lang::WrappedTargetException& ) + { + return false; + } + } + + return true; +} + +} // framework + +namespace { + +typedef ::cppu::WeakComponentImplHelper< + css::lang::XServiceInfo, + css::ui::XUIElementFactoryManager> UIElementFactoryManager_BASE; + +class UIElementFactoryManager : private cppu::BaseMutex, + public UIElementFactoryManager_BASE +{ + virtual void SAL_CALL disposing() override; +public: + explicit UIElementFactoryManager( const css::uno::Reference< css::uno::XComponentContext >& rxContext ); + + virtual OUString SAL_CALL getImplementationName() override + { + return "com.sun.star.comp.framework.UIElementFactoryManager"; + } + + virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override + { + return cppu::supportsService(this, ServiceName); + } + + virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override + { + return {"com.sun.star.ui.UIElementFactoryManager"}; + } + + // XUIElementFactory + virtual css::uno::Reference< css::ui::XUIElement > SAL_CALL createUIElement( const OUString& ResourceURL, const css::uno::Sequence< css::beans::PropertyValue >& Args ) override; + + // XUIElementFactoryRegistration + virtual css::uno::Sequence< css::uno::Sequence< css::beans::PropertyValue > > SAL_CALL getRegisteredFactories( ) override; + virtual css::uno::Reference< css::ui::XUIElementFactory > SAL_CALL getFactory( const OUString& ResourceURL, const OUString& ModuleIdentifier ) override; + virtual void SAL_CALL registerFactory( const OUString& aType, const OUString& aName, const OUString& aModuleIdentifier, const OUString& aFactoryImplementationName ) override; + virtual void SAL_CALL deregisterFactory( const OUString& aType, const OUString& aName, const OUString& aModuleIdentifier ) override; + +private: + bool m_bConfigRead; + css::uno::Reference< css::uno::XComponentContext > m_xContext; + rtl::Reference<ConfigurationAccess_FactoryManager> m_pConfigAccess; +}; + +UIElementFactoryManager::UIElementFactoryManager( const Reference< XComponentContext >& rxContext ) : + UIElementFactoryManager_BASE(m_aMutex), + m_bConfigRead( false ), + m_xContext(rxContext), + m_pConfigAccess( + new ConfigurationAccess_FactoryManager( + rxContext, + "/org.openoffice.Office.UI.Factories/Registered/UIElementFactories")) +{} + +void SAL_CALL UIElementFactoryManager::disposing() +{ + m_pConfigAccess.clear(); +} + +// XUIElementFactory +Reference< XUIElement > SAL_CALL UIElementFactoryManager::createUIElement( + const OUString& ResourceURL, + const Sequence< PropertyValue >& Args ) +{ + Reference< XFrame > xFrame; + OUString aModuleId; + { // SAFE + osl::MutexGuard g(rBHelper.rMutex); + if (rBHelper.bDisposed) { + throw css::lang::DisposedException( + "disposed", static_cast<OWeakObject *>(this)); + } + + if ( !m_bConfigRead ) + { + m_bConfigRead = true; + m_pConfigAccess->readConfigurationData(); + } + + // Retrieve the frame instance from the arguments to determine the module identifier. This must be provided + // to the search function. An empty module identifier is provided if the frame is missing or the module id cannot + // retrieve from it. + for ( auto const & arg : Args ) + { + if ( arg.Name == "Frame") + arg.Value >>= xFrame; + if (arg.Name == "Module") + arg.Value >>= aModuleId; + } + } // SAFE + + Reference< XModuleManager2 > xManager = ModuleManager::create( m_xContext ); + + // Determine the module identifier + try + { + if ( aModuleId.isEmpty() && xFrame.is() && xManager.is() ) + aModuleId = xManager->identify( Reference<XInterface>( xFrame, UNO_QUERY ) ); + + Reference< XUIElementFactory > xUIElementFactory = getFactory( ResourceURL, aModuleId ); + if ( xUIElementFactory.is() ) + return xUIElementFactory->createUIElement( ResourceURL, Args ); + } + catch ( const UnknownModuleException& ) + { + } + + throw NoSuchElementException(); +} + +// XUIElementFactoryRegistration +Sequence< Sequence< PropertyValue > > SAL_CALL UIElementFactoryManager::getRegisteredFactories() +{ + // SAFE + osl::MutexGuard g(rBHelper.rMutex); + if (rBHelper.bDisposed) { + throw css::lang::DisposedException( + "disposed", static_cast<OWeakObject *>(this)); + } + + if ( !m_bConfigRead ) + { + m_bConfigRead = true; + m_pConfigAccess->readConfigurationData(); + } + + return m_pConfigAccess->getFactoriesDescription(); +} + +Reference< XUIElementFactory > SAL_CALL UIElementFactoryManager::getFactory( const OUString& aResourceURL, const OUString& aModuleId ) +{ + OUString aServiceSpecifier; + { // SAFE + osl::MutexGuard g(rBHelper.rMutex); + if (rBHelper.bDisposed) { + throw css::lang::DisposedException( + "disposed", static_cast<OWeakObject *>(this)); + } + + if ( !m_bConfigRead ) + { + m_bConfigRead = true; + m_pConfigAccess->readConfigurationData(); + } + + OUString aType; + OUString aName; + + RetrieveTypeNameFromResourceURL( aResourceURL, aType, aName ); + + aServiceSpecifier = m_pConfigAccess->getFactorySpecifierFromTypeNameModule( aType, aName, aModuleId ); + } // SAFE + + if ( !aServiceSpecifier.isEmpty() ) try + { + Reference< XUIElementFactory > xFactory(m_xContext->getServiceManager()-> + createInstanceWithContext(aServiceSpecifier, m_xContext), UNO_QUERY); + SAL_WARN_IF(!xFactory.is(), "fwk.uielement", "could not create factory: " << aServiceSpecifier); + return xFactory; + } + catch ( const css::loader::CannotActivateFactoryException& ) + { + SAL_WARN("fwk.uielement", aServiceSpecifier << + " not available. This should happen only on mobile platforms."); + } + return Reference< XUIElementFactory >(); +} + +void SAL_CALL UIElementFactoryManager::registerFactory( const OUString& aType, const OUString& aName, const OUString& aModuleId, const OUString& aFactoryImplementationName ) +{ + // SAFE + osl::MutexGuard g(rBHelper.rMutex); + if (rBHelper.bDisposed) { + throw css::lang::DisposedException( + "disposed", static_cast<OWeakObject *>(this)); + } + + if ( !m_bConfigRead ) + { + m_bConfigRead = true; + m_pConfigAccess->readConfigurationData(); + } + + m_pConfigAccess->addFactorySpecifierToTypeNameModule( aType, aName, aModuleId, aFactoryImplementationName ); + // SAFE +} + +void SAL_CALL UIElementFactoryManager::deregisterFactory( const OUString& aType, const OUString& aName, const OUString& aModuleId ) +{ + // SAFE + osl::MutexGuard g(rBHelper.rMutex); + if (rBHelper.bDisposed) { + throw css::lang::DisposedException( + "disposed", static_cast<OWeakObject *>(this)); + } + + if ( !m_bConfigRead ) + { + m_bConfigRead = true; + m_pConfigAccess->readConfigurationData(); + } + + m_pConfigAccess->removeFactorySpecifierFromTypeNameModule( aType, aName, aModuleId ); + // SAFE +} + +struct Instance { + explicit Instance( + css::uno::Reference<css::uno::XComponentContext> const & context): + instance(static_cast<cppu::OWeakObject *>( + new UIElementFactoryManager(context))) + { + } + + css::uno::Reference<css::uno::XInterface> instance; +}; + +struct Singleton: + public rtl::StaticWithArg< + Instance, css::uno::Reference<css::uno::XComponentContext>, Singleton> +{}; + +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_framework_UIElementFactoryManager_get_implementation( + css::uno::XComponentContext *context, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(static_cast<cppu::OWeakObject *>( + Singleton::get(context).instance.get())); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/framework/source/uifactory/windowcontentfactorymanager.cxx b/framework/source/uifactory/windowcontentfactorymanager.cxx new file mode 100644 index 000000000..996fae5f4 --- /dev/null +++ b/framework/source/uifactory/windowcontentfactorymanager.cxx @@ -0,0 +1,223 @@ +/* -*- 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 <sal/config.h> + +#include <uifactory/configurationaccessfactorymanager.hxx> +#include <helper/mischelper.hxx> + +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/frame/ModuleManager.hpp> +#include <com/sun/star/frame/UnknownModuleException.hpp> +#include <com/sun/star/frame/XModuleManager2.hpp> +#include <com/sun/star/frame/XFrame.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XSingleComponentFactory.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> + +#include <cppuhelper/basemutex.hxx> +#include <cppuhelper/compbase.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <rtl/ref.hxx> +#include <tools/diagnose_ex.h> + +using namespace ::com::sun::star; +using namespace framework; + +namespace { + +typedef ::cppu::WeakComponentImplHelper< + css::lang::XServiceInfo, + css::lang::XSingleComponentFactory > WindowContentFactoryManager_BASE; + +class WindowContentFactoryManager : private cppu::BaseMutex, + public WindowContentFactoryManager_BASE +{ +public: + explicit WindowContentFactoryManager( const css::uno::Reference< css::uno::XComponentContext>& rxContext ); + + virtual OUString SAL_CALL getImplementationName() override + { + return "com.sun.star.comp.framework.WindowContentFactoryManager"; + } + + virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override + { + return cppu::supportsService(this, ServiceName); + } + + virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override + { + return {"com.sun.star.ui.WindowContentFactoryManager"}; + } + + // XSingleComponentFactory + virtual css::uno::Reference< css::uno::XInterface > SAL_CALL createInstanceWithContext( const css::uno::Reference< css::uno::XComponentContext >& Context ) override; + virtual css::uno::Reference< css::uno::XInterface > SAL_CALL createInstanceWithArgumentsAndContext( const css::uno::Sequence< css::uno::Any >& Arguments, const css::uno::Reference< css::uno::XComponentContext >& Context ) override; + +private: + virtual void SAL_CALL disposing() override; + + css::uno::Reference< css::uno::XComponentContext > m_xContext; + bool m_bConfigRead; + rtl::Reference<ConfigurationAccess_FactoryManager> m_pConfigAccess; +}; + +WindowContentFactoryManager::WindowContentFactoryManager( const uno::Reference< uno::XComponentContext >& rxContext ) : + WindowContentFactoryManager_BASE(m_aMutex), + m_xContext( rxContext ), + m_bConfigRead( false ), + m_pConfigAccess( + new ConfigurationAccess_FactoryManager( + m_xContext, + "/org.openoffice.Office.UI.WindowContentFactories/Registered/ContentFactories")) +{} + +void SAL_CALL WindowContentFactoryManager::disposing() +{ + m_pConfigAccess.clear(); +} + +// XSingleComponentFactory +uno::Reference< uno::XInterface > SAL_CALL WindowContentFactoryManager::createInstanceWithContext( + const uno::Reference< uno::XComponentContext >& /*xContext*/ ) +{ + uno::Reference< uno::XInterface > xWindow; + return xWindow; +} + +uno::Reference< uno::XInterface > SAL_CALL WindowContentFactoryManager::createInstanceWithArgumentsAndContext( + const uno::Sequence< uno::Any >& Arguments, const uno::Reference< uno::XComponentContext >& Context ) +{ + uno::Reference< uno::XInterface > xWindow; + uno::Reference< frame::XFrame > xFrame; + OUString aResourceURL; + + for (auto const & arg : Arguments ) + { + beans::PropertyValue aPropValue; + if ( arg >>= aPropValue ) + { + if ( aPropValue.Name == "Frame" ) + aPropValue.Value >>= xFrame; + else if ( aPropValue.Name == "ResourceURL" ) + aPropValue.Value >>= aResourceURL; + } + } + + // Determine the module identifier + OUString aType; + OUString aName; + OUString aModuleId; + uno::Reference< frame::XModuleManager2 > xModuleManager = + frame::ModuleManager::create( m_xContext ); + try + { + if ( xFrame.is() && xModuleManager.is() ) + aModuleId = xModuleManager->identify( uno::Reference< uno::XInterface >( xFrame, uno::UNO_QUERY ) ); + } + catch ( const frame::UnknownModuleException& ) + { + } + + RetrieveTypeNameFromResourceURL( aResourceURL, aType, aName ); + if ( !aType.isEmpty() && + !aName.isEmpty() && + !aModuleId.isEmpty() ) + { + OUString aImplementationName; + uno::Reference< uno::XInterface > xHolder( static_cast<cppu::OWeakObject*>(this), uno::UNO_QUERY ); + + // Determine the implementation name of the window content factory dependent on the + // module identifier, user interface element type and name + { // SAFE + osl::MutexGuard g(rBHelper.rMutex); + if (rBHelper.bDisposed) { + throw css::lang::DisposedException( + "disposed", static_cast<OWeakObject *>(this)); + } + if ( !m_bConfigRead ) + { + m_bConfigRead = true; + m_pConfigAccess->readConfigurationData(); + } + aImplementationName = m_pConfigAccess->getFactorySpecifierFromTypeNameModule( aType, aName, aModuleId ); + } // SAFE + + if ( !aImplementationName.isEmpty() ) + { + uno::Reference< lang::XMultiServiceFactory > xServiceManager( Context->getServiceManager(), uno::UNO_QUERY ); + if ( xServiceManager.is() ) + { + uno::Reference< lang::XSingleComponentFactory > xFactory( + xServiceManager->createInstance( aImplementationName ), uno::UNO_QUERY ); + if ( xFactory.is() ) + { + // Be careful: We call external code. Therefore here we have to catch all exceptions + try + { + xWindow = xFactory->createInstanceWithArgumentsAndContext( Arguments, Context ); + } + catch ( uno::Exception& ) + { + DBG_UNHANDLED_EXCEPTION("fwk"); + } + } + } + } + } + + // UNSAFE + if ( !xWindow.is()) + { + // Fallback: Use internal factory code to create a toolkit dialog as a content window + xWindow = createInstanceWithContext(Context); + } + + return xWindow; +} + +struct Instance { + explicit Instance( + css::uno::Reference<css::uno::XComponentContext> const & context): + instance(static_cast<cppu::OWeakObject *>( + new WindowContentFactoryManager(context))) + { + } + + css::uno::Reference<css::uno::XInterface> instance; +}; + +struct Singleton: + public rtl::StaticWithArg< + Instance, css::uno::Reference<css::uno::XComponentContext>, Singleton> +{}; + +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_framework_WindowContentFactoryManager_get_implementation( + css::uno::XComponentContext *context, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(static_cast<cppu::OWeakObject *>( + Singleton::get(context).instance.get())); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |