From ed5640d8b587fbcfed7dd7967f3de04b37a76f26 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 11:06:44 +0200 Subject: Adding upstream version 4:7.4.7. Signed-off-by: Daniel Baumann --- scripting/source/dlgprov/DialogModelProvider.cxx | 166 ++++++ scripting/source/dlgprov/DialogModelProvider.hxx | 87 +++ scripting/source/dlgprov/dlgevtatt.cxx | 658 +++++++++++++++++++++ scripting/source/dlgprov/dlgevtatt.hxx | 130 +++++ scripting/source/dlgprov/dlgprov.component | 32 ++ scripting/source/dlgprov/dlgprov.cxx | 702 +++++++++++++++++++++++ scripting/source/dlgprov/dlgprov.hxx | 148 +++++ 7 files changed, 1923 insertions(+) create mode 100644 scripting/source/dlgprov/DialogModelProvider.cxx create mode 100644 scripting/source/dlgprov/DialogModelProvider.hxx create mode 100644 scripting/source/dlgprov/dlgevtatt.cxx create mode 100644 scripting/source/dlgprov/dlgevtatt.hxx create mode 100644 scripting/source/dlgprov/dlgprov.component create mode 100644 scripting/source/dlgprov/dlgprov.cxx create mode 100644 scripting/source/dlgprov/dlgprov.hxx (limited to 'scripting/source/dlgprov') diff --git a/scripting/source/dlgprov/DialogModelProvider.cxx b/scripting/source/dlgprov/DialogModelProvider.cxx new file mode 100644 index 000000000..e49ed058d --- /dev/null +++ b/scripting/source/dlgprov/DialogModelProvider.cxx @@ -0,0 +1,166 @@ +/* -*- 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 "DialogModelProvider.hxx" +#include "dlgprov.hxx" +#include +#include + +#include + +/// anonymous implementation namespace +namespace dlgprov { + +using namespace ::com::sun::star; +using namespace awt; +using namespace lang; +using namespace uno; +using namespace script; +using namespace beans; + + +DialogModelProvider::DialogModelProvider(Reference< XComponentContext > const & context) : + m_xContext(context) +{} + +// lang::XInitialization: +void SAL_CALL DialogModelProvider::initialize(const css::uno::Sequence< uno::Any > & aArguments) +{ + if ( aArguments.getLength() != 1 ) + return; + + OUString sURL; + if ( !( aArguments[ 0 ] >>= sURL )) + throw css::lang::IllegalArgumentException(); + // Try any other URL with SimpleFileAccess + Reference< ucb::XSimpleFileAccess3 > xSFI = ucb::SimpleFileAccess::create(m_xContext); + + try + { + Reference< io::XInputStream > xInput = xSFI->openFileRead( sURL ); + Reference< resource::XStringResourceManager > xStringResourceManager; + if ( xInput.is() ) + { + xStringResourceManager = dlgprov::lcl_getStringResourceManager(m_xContext,sURL); + Any aDialogSourceURLAny; + aDialogSourceURLAny <<= sURL; + + Reference< frame::XModel > xModel; + m_xDialogModel.set( dlgprov::lcl_createDialogModel( m_xContext, xInput , xModel, xStringResourceManager, aDialogSourceURLAny ), UNO_SET_THROW); + m_xDialogModelProp.set(m_xDialogModel, UNO_QUERY_THROW); + } + } + catch( Exception& ) + {} + //m_sURL = sURL; +} + +// container::XElementAccess: +uno::Type SAL_CALL DialogModelProvider::getElementType() +{ + return m_xDialogModel->getElementType(); +} + +sal_Bool SAL_CALL DialogModelProvider::hasElements() +{ + return m_xDialogModel->hasElements(); +} + +// container::XNameAccess: +uno::Any SAL_CALL DialogModelProvider::getByName(const OUString & aName) +{ + return m_xDialogModel->getByName(aName); +} + +css::uno::Sequence< OUString > SAL_CALL DialogModelProvider::getElementNames() +{ + return m_xDialogModel->getElementNames(); +} + +sal_Bool SAL_CALL DialogModelProvider::hasByName(const OUString & aName) +{ + return m_xDialogModel->hasByName(aName); +} + +// container::XNameReplace: +void SAL_CALL DialogModelProvider::replaceByName(const OUString & aName, const uno::Any & aElement) +{ + m_xDialogModel->replaceByName(aName,aElement); +} + +// container::XNameContainer: +void SAL_CALL DialogModelProvider::insertByName(const OUString & aName, const uno::Any & aElement) +{ + m_xDialogModel->insertByName(aName,aElement); +} + +void SAL_CALL DialogModelProvider::removeByName(const OUString & aName) +{ + m_xDialogModel->removeByName(aName); +} +uno::Reference< beans::XPropertySetInfo > SAL_CALL DialogModelProvider::getPropertySetInfo( ) +{ + return m_xDialogModelProp->getPropertySetInfo(); +} +void SAL_CALL DialogModelProvider::setPropertyValue( const OUString&, const uno::Any& ) +{ +} +uno::Any SAL_CALL DialogModelProvider::getPropertyValue( const OUString& PropertyName ) +{ + return m_xDialogModelProp->getPropertyValue(PropertyName); +} +void SAL_CALL DialogModelProvider::addPropertyChangeListener( const OUString& , const uno::Reference< beans::XPropertyChangeListener >& ) +{ +} +void SAL_CALL DialogModelProvider::removePropertyChangeListener( const OUString& , const uno::Reference< beans::XPropertyChangeListener >& ) +{ +} +void SAL_CALL DialogModelProvider::addVetoableChangeListener( const OUString& , const uno::Reference< beans::XVetoableChangeListener >& ) +{ +} +void SAL_CALL DialogModelProvider::removeVetoableChangeListener( const OUString& ,const uno::Reference< beans::XVetoableChangeListener >& ) +{ +} + +// com.sun.star.uno.XServiceInfo: +OUString SAL_CALL DialogModelProvider::getImplementationName() +{ + return "com.sun.star.comp.scripting.DialogModelProvider"; +} + +sal_Bool SAL_CALL DialogModelProvider::supportsService(OUString const & serviceName) +{ + return cppu::supportsService(this, serviceName); +} + +css::uno::Sequence< OUString > SAL_CALL DialogModelProvider::getSupportedServiceNames() +{ + return { "com.sun.star.awt.UnoControlDialogModelProvider" }; +} + +} // closing anonymous implementation namespace + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +scripting_DialogModelProvider_get_implementation( + css::uno::XComponentContext* context, css::uno::Sequence const&) +{ + return cppu::acquire(new dlgprov::DialogModelProvider(context)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/scripting/source/dlgprov/DialogModelProvider.hxx b/scripting/source/dlgprov/DialogModelProvider.hxx new file mode 100644 index 000000000..d9a41ef64 --- /dev/null +++ b/scripting/source/dlgprov/DialogModelProvider.hxx @@ -0,0 +1,87 @@ +/* -*- 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 . + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +/// anonymous implementation namespace +namespace dlgprov{ + +class DialogModelProvider: + public ::cppu::WeakImplHelper< + css::lang::XInitialization, + css::container::XNameContainer, + css::beans::XPropertySet, + css::lang::XServiceInfo> +{ +public: + explicit DialogModelProvider(css::uno::Reference< css::uno::XComponentContext > const & context); +private: + // css::lang::XInitialization: + virtual void SAL_CALL initialize(const css::uno::Sequence< css::uno::Any > & aArguments) override; + + // css::container::XElementAccess: + virtual css::uno::Type SAL_CALL getElementType() override; + virtual sal_Bool SAL_CALL hasElements() override; + + // css::container::XNameAccess: + virtual css::uno::Any SAL_CALL getByName(const OUString & aName) override; + virtual css::uno::Sequence< OUString > SAL_CALL getElementNames() override; + virtual sal_Bool SAL_CALL hasByName(const OUString & aName) override; + + // css::container::XNameReplace: + virtual void SAL_CALL replaceByName(const OUString & aName, const css::uno::Any & aElement) override; + + // css::container::XNameContainer: + virtual void SAL_CALL insertByName(const OUString & aName, const css::uno::Any & aElement) override; + virtual void SAL_CALL removeByName(const OUString & Name) override; + + // css::lang::XServiceInfo: + virtual OUString SAL_CALL getImplementationName() override; + virtual sal_Bool SAL_CALL supportsService(const OUString & ServiceName) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; + + virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) override; + virtual void SAL_CALL setPropertyValue( const OUString& aPropertyName, const css::uno::Any& aValue ) override; + virtual css::uno::Any SAL_CALL getPropertyValue( const OUString& PropertyName ) override; + virtual void SAL_CALL addPropertyChangeListener( const OUString& aPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener >& xListener ) override; + virtual void SAL_CALL removePropertyChangeListener( const OUString& aPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener >& aListener ) override; + virtual void SAL_CALL addVetoableChangeListener( const OUString& PropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener >& aListener ) override; + virtual void SAL_CALL removeVetoableChangeListener( const OUString& PropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener >& aListener ) override; + +private: + DialogModelProvider(const DialogModelProvider &) = delete; + DialogModelProvider& operator=(const DialogModelProvider &) = delete; + + // destructor is private and will be called indirectly by the release call virtual ~DialogModelProvider() {} + + css::uno::Reference< css::uno::XComponentContext > m_xContext; + css::uno::Reference< css::container::XNameContainer> m_xDialogModel; + css::uno::Reference< css::beans::XPropertySet> m_xDialogModelProp; +}; +} // closing anonymous implementation namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/scripting/source/dlgprov/dlgevtatt.cxx b/scripting/source/dlgprov/dlgevtatt.cxx new file mode 100644 index 000000000..704518e07 --- /dev/null +++ b/scripting/source/dlgprov/dlgevtatt.cxx @@ -0,0 +1,658 @@ +/* -*- 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 "dlgevtatt.hxx" + +#include "dlgprov.hxx" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace ::com::sun::star; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::script; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::reflection; + + +namespace dlgprov +{ + namespace { + + class DialogSFScriptListenerImpl : public DialogScriptListenerImpl + { + protected: + Reference< frame::XModel > m_xModel; + virtual void firing_impl( const script::ScriptEvent& aScriptEvent, uno::Any* pRet ) override; + public: + DialogSFScriptListenerImpl( const Reference< XComponentContext >& rxContext, const Reference< frame::XModel >& rxModel ) : DialogScriptListenerImpl( rxContext ), m_xModel( rxModel ) {} + }; + + class DialogLegacyScriptListenerImpl : public DialogSFScriptListenerImpl + { + protected: + virtual void firing_impl( const script::ScriptEvent& aScriptEvent, uno::Any* pRet ) override; + public: + DialogLegacyScriptListenerImpl( const Reference< XComponentContext >& rxContext, const Reference< frame::XModel >& rxModel ) : DialogSFScriptListenerImpl( rxContext, rxModel ){} + }; + + class DialogUnoScriptListenerImpl : public DialogSFScriptListenerImpl + { + Reference< awt::XControl > m_xControl; + Reference< XInterface > m_xHandler; + Reference< beans::XIntrospectionAccess > m_xIntrospectionAccess; + bool m_bDialogProviderMode; + + virtual void firing_impl( const script::ScriptEvent& aScriptEvent, uno::Any* pRet ) override; + + public: + DialogUnoScriptListenerImpl( const Reference< XComponentContext >& rxContext, + const Reference< frame::XModel >& rxModel, + const Reference< awt::XControl >& rxControl, + const Reference< XInterface >& rxHandler, + const Reference< beans::XIntrospectionAccess >& rxIntrospectionAccess, + bool bDialogProviderMode ); // false: ContainerWindowProvider mode + + }; + + class DialogVBAScriptListenerImpl : public DialogScriptListenerImpl + { + protected: + OUString msDialogCodeName; + OUString msDialogLibName; + Reference< script::XScriptListener > mxListener; + virtual void firing_impl( const script::ScriptEvent& aScriptEvent, uno::Any* pRet ) override; + public: + DialogVBAScriptListenerImpl( const Reference< XComponentContext >& rxContext, const Reference< awt::XControl >& rxControl, const Reference< frame::XModel >& xModel, const OUString& sDialogLibName ); + }; + + } + + DialogVBAScriptListenerImpl::DialogVBAScriptListenerImpl( const Reference< XComponentContext >& rxContext, const Reference< awt::XControl >& rxControl, const Reference< frame::XModel >& xModel, const OUString& sDialogLibName ) : DialogScriptListenerImpl( rxContext ), msDialogLibName( sDialogLibName ) + { + Reference< XMultiComponentFactory > xSMgr( m_xContext->getServiceManager() ); + Sequence< Any > args(1); + if ( xSMgr.is() ) + { + args.getArray()[0] <<= xModel; + mxListener.set( xSMgr->createInstanceWithArgumentsAndContext( "ooo.vba.EventListener", args, m_xContext ), UNO_QUERY ); + } + if ( !rxControl.is() ) + return; + + try + { + Reference< XPropertySet > xProps( rxControl->getModel(), UNO_QUERY_THROW ); + xProps->getPropertyValue("Name") >>= msDialogCodeName; + xProps.set( mxListener, UNO_QUERY_THROW ); + xProps->setPropertyValue("Model", args[ 0 ] ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("scripting"); + } + + } + + void DialogVBAScriptListenerImpl::firing_impl( const script::ScriptEvent& aScriptEvent, uno::Any* ) + { + if ( !(aScriptEvent.ScriptType == "VBAInterop" && mxListener.is()) ) + return; + + ScriptEvent aScriptEventCopy( aScriptEvent ); + aScriptEventCopy.ScriptCode = msDialogLibName + "." + msDialogCodeName; + try + { + mxListener->firing( aScriptEventCopy ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("scripting"); + } + } + + + // DialogEventsAttacherImpl + + + DialogEventsAttacherImpl::DialogEventsAttacherImpl( const Reference< XComponentContext >& rxContext, const Reference< frame::XModel >& rxModel, const Reference< awt::XControl >& rxControl, const Reference< XInterface >& rxHandler, const Reference< beans::XIntrospectionAccess >& rxIntrospect, bool bProviderMode, const Reference< script::XScriptListener >& rxRTLListener, const OUString& sDialogLibName ) + :mbUseFakeVBAEvents( false ), m_xContext( rxContext ) + { + // key listeners by protocol when ScriptType = 'Script' + // otherwise key is the ScriptType e.g. StarBasic + if ( rxRTLListener.is() ) // set up handler for RTL_BASIC + listenersForTypes[ OUString("StarBasic") ] = rxRTLListener; + else + listenersForTypes[ OUString("StarBasic") ] = new DialogLegacyScriptListenerImpl( rxContext, rxModel ); + // handler for Script & OUString("vnd.sun.star.UNO:") + listenersForTypes[ OUString("vnd.sun.star.UNO") ] = new DialogUnoScriptListenerImpl( rxContext, rxModel, rxControl, rxHandler, rxIntrospect, bProviderMode ); + listenersForTypes[ OUString("vnd.sun.star.script") ] = new DialogSFScriptListenerImpl( rxContext, rxModel ); + + // determine the VBA compatibility mode from the Basic library container + try + { + uno::Reference< beans::XPropertySet > xModelProps( rxModel, uno::UNO_QUERY_THROW ); + uno::Reference< script::vba::XVBACompatibility > xVBACompat( + xModelProps->getPropertyValue("BasicLibraries"), uno::UNO_QUERY_THROW ); + mbUseFakeVBAEvents = xVBACompat->getVBACompatibilityMode(); + } + catch( uno::Exception& ) + { + } + if ( mbUseFakeVBAEvents ) + listenersForTypes[ OUString("VBAInterop") ] = new DialogVBAScriptListenerImpl( rxContext, rxControl, rxModel, sDialogLibName ); + } + + + DialogEventsAttacherImpl::~DialogEventsAttacherImpl() + { + } + + + Reference< script::XScriptListener > const & + DialogEventsAttacherImpl::getScriptListenerForKey( const OUString& sKey ) + { + ListenerHash::iterator it = listenersForTypes.find( sKey ); + if ( it == listenersForTypes.end() ) + throw RuntimeException(); // more text info here please + return it->second; + } + Reference< XScriptEventsSupplier > DialogEventsAttacherImpl::getFakeVbaEventsSupplier( const Reference< XControl >& xControl, OUString const & sControlName ) + { + Reference< XScriptEventsSupplier > xEventsSupplier; + Reference< XMultiComponentFactory > xSMgr( m_xContext->getServiceManager() ); + if ( xSMgr.is() ) + { + Reference< ooo::vba::XVBAToOOEventDescGen > xVBAToOOEvtDesc( xSMgr->createInstanceWithContext("ooo.vba.VBAToOOEventDesc", m_xContext ), UNO_QUERY ); + if ( xVBAToOOEvtDesc.is() ) + xEventsSupplier = xVBAToOOEvtDesc->getEventSupplier( xControl, sControlName ); + + } + return xEventsSupplier; + } + + + void DialogEventsAttacherImpl::attachEventsToControl( const Reference< XControl>& xControl, const Reference< XScriptEventsSupplier >& xEventsSupplier, const Any& Helper ) + { + if ( !xEventsSupplier.is() ) + return; + + Reference< container::XNameContainer > xEventCont = xEventsSupplier->getEvents(); + + Reference< XControlModel > xControlModel = xControl->getModel(); + if ( !xEventCont.is() ) + return; + + const Sequence< OUString > aNames = xEventCont->getElementNames(); + + for ( const OUString& rName : aNames ) + { + ScriptEventDescriptor aDesc; + + Any aElement = xEventCont->getByName( rName ); + aElement >>= aDesc; + OUString sKey = aDesc.ScriptType; + if ( aDesc.ScriptType == "Script" || aDesc.ScriptType == "UNO" ) + { + sal_Int32 nIndex = aDesc.ScriptCode.indexOf( ':' ); + sKey = aDesc.ScriptCode.copy( 0, nIndex ); + } + Reference< XAllListener > xAllListener = + new DialogAllListenerImpl( getScriptListenerForKey( sKey ), aDesc.ScriptType, aDesc.ScriptCode ); + + // try first to attach event to the ControlModel + bool bSuccess = false; + try + { + Reference< XEventListener > xListener_ = m_xEventAttacher->attachSingleEventListener( + xControlModel, xAllListener, Helper, aDesc.ListenerType, + aDesc.AddListenerParam, aDesc.EventMethod ); + + if ( xListener_.is() ) + bSuccess = true; + } + catch ( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("scripting"); + } + + try + { + // if we had no success, try to attach to the control + if ( !bSuccess ) + { + m_xEventAttacher->attachSingleEventListener( + xControl, xAllListener, Helper, aDesc.ListenerType, + aDesc.AddListenerParam, aDesc.EventMethod ); + } + } + catch ( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("scripting"); + } + } + } + + + void DialogEventsAttacherImpl::nestedAttachEvents( const Sequence< Reference< XInterface > >& Objects, const Any& Helper, OUString& sDialogCodeName ) + { + for ( const Reference< XInterface >& rObject : Objects ) + { + // We know that we have to do with instances of XControl. + // Otherwise this is not the right implementation for + // XScriptEventsAttacher and we have to give up. + Reference< XControl > xControl( rObject, UNO_QUERY ); + Reference< XControlContainer > xControlContainer( xControl, UNO_QUERY ); + Reference< XDialog > xDialog( xControl, UNO_QUERY ); + if ( !xControl.is() ) + throw IllegalArgumentException(); + + // get XEventsSupplier from control model + Reference< XControlModel > xControlModel = xControl->getModel(); + Reference< XScriptEventsSupplier > xEventsSupplier( xControlModel, UNO_QUERY ); + attachEventsToControl( xControl, xEventsSupplier, Helper ); + if ( mbUseFakeVBAEvents ) + { + xEventsSupplier.set( getFakeVbaEventsSupplier( xControl, sDialogCodeName ) ); + Any newHelper(xControl ); + attachEventsToControl( xControl, xEventsSupplier, newHelper ); + } + if ( xControlContainer.is() && !xDialog.is() ) + { + Sequence< Reference< XControl > > aControls = xControlContainer->getControls(); + sal_Int32 nControlCount = aControls.getLength(); + + Sequence< Reference< XInterface > > aObjects( nControlCount ); + Reference< XInterface >* pObjects2 = aObjects.getArray(); + const Reference< XControl >* pControls = aControls.getConstArray(); + + for ( sal_Int32 i2 = 0; i2 < nControlCount; ++i2 ) + { + pObjects2[i2].set( pControls[i2], UNO_QUERY ); + } + nestedAttachEvents( aObjects, Helper, sDialogCodeName ); + } + } + } + + + // XScriptEventsAttacher + + + void SAL_CALL DialogEventsAttacherImpl::attachEvents( const Sequence< Reference< XInterface > >& Objects, + const css::uno::Reference&, + const Any& Helper ) + { + // get EventAttacher + { + ::osl::MutexGuard aGuard( getMutex() ); + + if ( !m_xEventAttacher.is() ) + { + Reference< XMultiComponentFactory > xSMgr( m_xContext->getServiceManager() ); + if ( !xSMgr.is() ) + throw RuntimeException(); + + m_xEventAttacher.set( xSMgr->createInstanceWithContext( + "com.sun.star.script.EventAttacher", m_xContext ), UNO_QUERY ); + + if ( !m_xEventAttacher.is() ) + throw ServiceNotRegisteredException(); + } + } + OUString sDialogCodeName; + sal_Int32 nObjCount = Objects.getLength(); + Reference< awt::XControl > xDlgControl( Objects[ nObjCount - 1 ], uno::UNO_QUERY ); // last object is the dialog + if ( xDlgControl.is() ) + { + Reference< XPropertySet > xProps( xDlgControl->getModel(), UNO_QUERY ); + try + { + xProps->getPropertyValue("Name") >>= sDialogCodeName; + } + catch( Exception& ){} + } + // go over all objects + nestedAttachEvents( Objects, Helper, sDialogCodeName ); + } + + + // DialogAllListenerImpl + + + DialogAllListenerImpl::DialogAllListenerImpl( const Reference< XScriptListener >& rxListener, + const OUString& rScriptType, const OUString& rScriptCode ) + :m_xScriptListener( rxListener ) + ,m_sScriptType( rScriptType ) + ,m_sScriptCode( rScriptCode ) + { + } + + + DialogAllListenerImpl::~DialogAllListenerImpl() + { + } + + + void DialogAllListenerImpl::firing_impl( const AllEventObject& Event, Any* pRet ) + { + ScriptEvent aScriptEvent; + aScriptEvent.Source = static_cast(this); // get correct XInterface + aScriptEvent.ListenerType = Event.ListenerType; + aScriptEvent.MethodName = Event.MethodName; + aScriptEvent.Arguments = Event.Arguments; + aScriptEvent.Helper = Event.Helper; + aScriptEvent.ScriptType = m_sScriptType; + aScriptEvent.ScriptCode = m_sScriptCode; + + if ( m_xScriptListener.is() ) + { + if ( pRet ) + *pRet = m_xScriptListener->approveFiring( aScriptEvent ); + else + m_xScriptListener->firing( aScriptEvent ); + } + } + + + // XEventListener + + + void DialogAllListenerImpl::disposing(const EventObject& ) + { + } + + + // XAllListener + + + void DialogAllListenerImpl::firing( const AllEventObject& Event ) + { + //::osl::MutexGuard aGuard( getMutex() ); + + firing_impl( Event, nullptr ); + } + + + Any DialogAllListenerImpl::approveFiring( const AllEventObject& Event ) + { + //::osl::MutexGuard aGuard( getMutex() ); + + Any aReturn; + firing_impl( Event, &aReturn ); + return aReturn; + } + + + // DialogScriptListenerImpl + + + DialogUnoScriptListenerImpl::DialogUnoScriptListenerImpl( const Reference< XComponentContext >& rxContext, + const Reference< css::frame::XModel >& rxModel, + const Reference< css::awt::XControl >& rxControl, + const Reference< css::uno::XInterface >& rxHandler, + const Reference< css::beans::XIntrospectionAccess >& rxIntrospectionAccess, + bool bDialogProviderMode ) + : DialogSFScriptListenerImpl( rxContext, rxModel ) + ,m_xControl( rxControl ) + ,m_xHandler( rxHandler ) + ,m_xIntrospectionAccess( rxIntrospectionAccess ) + ,m_bDialogProviderMode( bDialogProviderMode ) + { + } + + + DialogScriptListenerImpl::~DialogScriptListenerImpl() + { + } + + + void DialogSFScriptListenerImpl::firing_impl( const ScriptEvent& aScriptEvent, Any* pRet ) + { + try + { + Reference< provider::XScriptProvider > xScriptProvider; + if ( m_xModel.is() ) + { + Reference< provider::XScriptProviderSupplier > xSupplier( m_xModel, UNO_QUERY ); + OSL_ENSURE( xSupplier.is(), "DialogScriptListenerImpl::firing_impl: failed to get script provider supplier" ); + if ( xSupplier.is() ) + xScriptProvider.set( xSupplier->getScriptProvider() ); + } + else + { + OSL_ASSERT( m_xContext.is() ); + if ( m_xContext.is() ) + { + Reference< provider::XScriptProviderFactory > xFactory = + provider::theMasterScriptProviderFactory::get( m_xContext ); + + Any aCtx; + aCtx <<= OUString("user"); + xScriptProvider = xFactory->createScriptProvider( aCtx ); + } + } + + OSL_ENSURE( xScriptProvider.is(), "DialogScriptListenerImpl::firing_impl: failed to get script provider" ); + + if ( xScriptProvider.is() ) + { + Reference< provider::XScript > xScript = xScriptProvider->getScript( aScriptEvent.ScriptCode ); + OSL_ENSURE( xScript.is(), "DialogScriptListenerImpl::firing_impl: failed to get script" ); + + if ( xScript.is() ) + { + Sequence< Any > aInParams; + Sequence< sal_Int16 > aOutParamsIndex; + Sequence< Any > aOutParams; + + // get arguments for script + aInParams = aScriptEvent.Arguments; + + Any aResult = xScript->invoke( aInParams, aOutParamsIndex, aOutParams ); + if ( pRet ) + *pRet = aResult; + } + } + } + catch ( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("scripting"); + } + } + + void DialogLegacyScriptListenerImpl::firing_impl( const ScriptEvent& aScriptEvent, Any* pRet ) + { + OUString sScriptURL; + OUString sScriptCode( aScriptEvent.ScriptCode ); + + if ( aScriptEvent.ScriptType != "StarBasic" ) + return; + + // StarBasic script: convert ScriptCode to scriptURL + sal_Int32 nIndex = sScriptCode.indexOf( ':' ); + if ( nIndex >= 0 && nIndex < sScriptCode.getLength() ) + { + sScriptURL = OUString::Concat("vnd.sun.star.script:") + + sScriptCode.subView( nIndex + 1 ) + + "?language=Basic&location=" + + sScriptCode.subView( 0, nIndex ); + } + ScriptEvent aSFScriptEvent( aScriptEvent ); + aSFScriptEvent.ScriptCode = sScriptURL; + DialogSFScriptListenerImpl::firing_impl( aSFScriptEvent, pRet ); + } + + void DialogUnoScriptListenerImpl::firing_impl( const ScriptEvent& aScriptEvent, Any* pRet ) + { + OUString aMethodName = aScriptEvent.ScriptCode.copy( strlen("vnd.sun.star.UNO:") ); + + const Any* pArguments = aScriptEvent.Arguments.getConstArray(); + Any aEventObject = pArguments[0]; + + bool bHandled = false; + if( m_xHandler.is() ) + { + if( m_bDialogProviderMode ) + { + Reference< XDialogEventHandler > xDialogEventHandler( m_xHandler, UNO_QUERY ); + if( xDialogEventHandler.is() ) + { + Reference< XDialog > xDialog( m_xControl, UNO_QUERY ); + bHandled = xDialogEventHandler->callHandlerMethod( xDialog, aEventObject, aMethodName ); + } + } + else + { + Reference< XContainerWindowEventHandler > xContainerWindowEventHandler( m_xHandler, UNO_QUERY ); + if( xContainerWindowEventHandler.is() ) + { + Reference< XWindow > xWindow( m_xControl, UNO_QUERY ); + bHandled = xContainerWindowEventHandler->callHandlerMethod( xWindow, aEventObject, aMethodName ); + } + } + } + + Any aRet; + if( !bHandled && m_xIntrospectionAccess.is() ) + { + try + { + // call method + const Reference< XIdlMethod >& rxMethod = m_xIntrospectionAccess-> + getMethod( aMethodName, MethodConcept::ALL - MethodConcept::DANGEROUS ); + + Reference< XMaterialHolder > xMaterialHolder = + Reference< XMaterialHolder >::query( m_xIntrospectionAccess ); + Any aHandlerObject = xMaterialHolder->getMaterial(); + + Sequence< Reference< XIdlClass > > aParamTypeSeq = rxMethod->getParameterTypes(); + sal_Int32 nParamCount = aParamTypeSeq.getLength(); + if( nParamCount == 0 ) + { + Sequence args; + rxMethod->invoke( aHandlerObject, args ); + bHandled = true; + } + else if( nParamCount == 2 ) + { + // Signature check automatically done by reflection + Sequence Args(2); + Any* pArgs = Args.getArray(); + if( m_bDialogProviderMode ) + { + Reference< XDialog > xDialog( m_xControl, UNO_QUERY ); + pArgs[0] <<= xDialog; + } + else + { + Reference< XWindow > xWindow( m_xControl, UNO_QUERY ); + pArgs[0] <<= xWindow; + } + pArgs[1] = aEventObject; + aRet = rxMethod->invoke( aHandlerObject, Args ); + bHandled = true; + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("scripting"); + } + } + + if( bHandled ) + { + if( pRet ) + *pRet = aRet; + } + else + { + OUString aRes(SfxResId(STR_ERRUNOEVENTBINDUNG)); + OUString aQuoteChar( "\"" ); + + sal_Int32 nIndex = aRes.indexOf( '%' ); + + OUString aOUFinal = + aRes.subView( 0, nIndex ) + + aQuoteChar + aMethodName + aQuoteChar + + aRes.subView( nIndex + 2 ); + + std::unique_ptr xBox(Application::CreateMessageDialog(nullptr, + VclMessageType::Warning, VclButtonsType::Ok, aOUFinal)); + xBox->run(); + } + } + + + // XEventListener + + + void DialogScriptListenerImpl::disposing(const EventObject& ) + { + } + + + // XScriptListener + + + void DialogScriptListenerImpl::firing( const ScriptEvent& aScriptEvent ) + { + //::osl::MutexGuard aGuard( getMutex() ); + + firing_impl( aScriptEvent, nullptr ); + } + + + Any DialogScriptListenerImpl::approveFiring( const ScriptEvent& aScriptEvent ) + { + //::osl::MutexGuard aGuard( getMutex() ); + + Any aReturn; + firing_impl( aScriptEvent, &aReturn ); + return aReturn; + } + + +} // namespace dlgprov + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/scripting/source/dlgprov/dlgevtatt.hxx b/scripting/source/dlgprov/dlgevtatt.hxx new file mode 100644 index 000000000..239cb6530 --- /dev/null +++ b/scripting/source/dlgprov/dlgevtatt.hxx @@ -0,0 +1,130 @@ +/* -*- 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 . + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +namespace dlgprov +{ + typedef std::unordered_map< OUString, + css::uno::Reference< css::script::XScriptListener > > ListenerHash; + + typedef ::cppu::WeakImplHelper< + css::script::XScriptEventsAttacher > DialogEventsAttacherImpl_BASE; + + + class DialogEventsAttacherImpl : public DialogEventsAttacherImpl_BASE + { + private: + bool mbUseFakeVBAEvents; + ListenerHash listenersForTypes; + css::uno::Reference< css::uno::XComponentContext > m_xContext; + css::uno::Reference< css::script::XEventAttacher > m_xEventAttacher; + /// @throws css::uno::RuntimeException + css::uno::Reference< css::script::XScriptListener > const & getScriptListenerForKey( const OUString& sScriptName ); + css::uno::Reference< css::script::XScriptEventsSupplier > getFakeVbaEventsSupplier( const css::uno::Reference< css::awt::XControl>& xControl, OUString const & sCodeName ); + void nestedAttachEvents( const css::uno::Sequence< css::uno::Reference< css::uno::XInterface > >& Objects, const css::uno::Any& Helper, OUString& sDialogCodeName ); + void attachEventsToControl( const css::uno::Reference< css::awt::XControl>& xControl, const css::uno::Reference< css::script::XScriptEventsSupplier >& events, const css::uno::Any& Helper ); + public: + DialogEventsAttacherImpl( const css::uno::Reference< css::uno::XComponentContext >& rxContext, + const css::uno::Reference< css::frame::XModel >& xModel, + const css::uno::Reference< css::awt::XControl >& xControl, + const css::uno::Reference< css::uno::XInterface >& xHandler, + const css::uno::Reference< css::beans::XIntrospectionAccess >& xIntrospect, + bool bProviderMode, + const css::uno::Reference< css::script::XScriptListener >& xRTLListener ,const OUString& sDialogLibName ); + virtual ~DialogEventsAttacherImpl() override; + + // XScriptEventsAttacher + virtual void SAL_CALL attachEvents( const css::uno::Sequence< + css::uno::Reference< css::uno::XInterface > >& Objects, + const css::uno::Reference&, + const css::uno::Any& Helper ) override; + }; + + + + + typedef ::cppu::WeakImplHelper< + css::script::XAllListener > DialogAllListenerImpl_BASE; + + + class DialogAllListenerImpl : public DialogAllListenerImpl_BASE + { + private: + css::uno::Reference< css::script::XScriptListener > m_xScriptListener; + OUString m_sScriptType; + OUString m_sScriptCode; + + void firing_impl( const css::script::AllEventObject& Event, css::uno::Any* pRet ); + + public: + DialogAllListenerImpl( const css::uno::Reference< css::script::XScriptListener >& rxListener, + const OUString& rScriptType, const OUString& rScriptCode ); + virtual ~DialogAllListenerImpl() override; + + // XEventListener + virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override; + + // XAllListener + virtual void SAL_CALL firing( const css::script::AllEventObject& Event ) override; + virtual css::uno::Any SAL_CALL approveFiring( const css::script::AllEventObject& Event ) override; + }; + + + + + typedef ::cppu::WeakImplHelper< + css::script::XScriptListener > DialogScriptListenerImpl_BASE; + + + class DialogScriptListenerImpl : public DialogScriptListenerImpl_BASE + { + protected: + css::uno::Reference< css::uno::XComponentContext > m_xContext; + virtual void firing_impl( const css::script::ScriptEvent& aScriptEvent, css::uno::Any* pRet ) = 0; + public: + explicit DialogScriptListenerImpl( const css::uno::Reference< css::uno::XComponentContext >& rxContext ) : m_xContext( rxContext ) {} + virtual ~DialogScriptListenerImpl() override; + + // XEventListener + virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override; + + // XScriptListener + virtual void SAL_CALL firing( const css::script::ScriptEvent& aScriptEvent ) override; + virtual css::uno::Any SAL_CALL approveFiring( const css::script::ScriptEvent& aScriptEvent ) override; + }; + + +} // namespace dlgprov + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/scripting/source/dlgprov/dlgprov.component b/scripting/source/dlgprov/dlgprov.component new file mode 100644 index 000000000..35203afb8 --- /dev/null +++ b/scripting/source/dlgprov/dlgprov.component @@ -0,0 +1,32 @@ + + + + + + + + + + + + + diff --git a/scripting/source/dlgprov/dlgprov.cxx b/scripting/source/dlgprov/dlgprov.cxx new file mode 100644 index 000000000..18815f499 --- /dev/null +++ b/scripting/source/dlgprov/dlgprov.cxx @@ -0,0 +1,702 @@ +/* -*- 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 "dlgprov.hxx" +#include "dlgevtatt.hxx" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace ::com::sun::star; +using namespace awt; +using namespace lang; +using namespace uno; +using namespace script; +using namespace beans; +using namespace document; +using namespace ::sf_misc; + +namespace dlgprov +{ + + Reference< resource::XStringResourceManager > lcl_getStringResourceManager(const Reference< XComponentContext >& i_xContext, std::u16string_view i_sURL) + { + INetURLObject aInetObj( i_sURL ); + OUString aDlgName = aInetObj.GetBase(); + aInetObj.removeSegment(); + OUString aDlgLocation = aInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ); + css::lang::Locale aLocale = Application::GetSettings().GetUILanguageTag().getLocale(); + + Reference< task::XInteractionHandler > xDummyHandler; + + Sequence aArgs{ Any(aDlgLocation), + Any(true), // bReadOnly + Any(aLocale), + Any(aDlgName), + Any(OUString()), + Any(xDummyHandler) }; + + Reference< XMultiComponentFactory > xSMgr_( i_xContext->getServiceManager(), UNO_SET_THROW ); + // TODO: Ctor + Reference< resource::XStringResourceManager > xStringResourceManager( xSMgr_->createInstanceWithContext + ( "com.sun.star.resource.StringResourceWithLocation", + i_xContext ), UNO_QUERY ); + if( xStringResourceManager.is() ) + { + Reference< XInitialization > xInit( xStringResourceManager, UNO_QUERY ); + if( xInit.is() ) + xInit->initialize( aArgs ); + } + return xStringResourceManager; + } + Reference< container::XNameContainer > lcl_createControlModel(const Reference< XComponentContext >& i_xContext) + { + Reference< XMultiComponentFactory > xSMgr_( i_xContext->getServiceManager(), UNO_SET_THROW ); + Reference< container::XNameContainer > xControlModel( xSMgr_->createInstanceWithContext("com.sun.star.awt.UnoControlDialogModel", i_xContext ), UNO_QUERY_THROW ); + return xControlModel; + } + Reference< container::XNameContainer > lcl_createDialogModel( const Reference< XComponentContext >& i_xContext, + const Reference< io::XInputStream >& xInput, + const Reference< frame::XModel >& xModel, + const Reference< resource::XStringResourceManager >& xStringResourceManager, + const Any &aDialogSourceURL) + { + Reference< container::XNameContainer > xDialogModel( lcl_createControlModel(i_xContext) ); + + Reference< beans::XPropertySet > xDlgPropSet( xDialogModel, UNO_QUERY ); + xDlgPropSet->setPropertyValue( "DialogSourceURL", aDialogSourceURL ); + + // #TODO we really need to detect the source of the Dialog, is it + // the dialog. E.g. if the dialog was created from basic ( then we just + // can't tell where its from ) + // If we are happy to always substitute the form model for the awt + // one then maybe the presence of a document model is enough to trigger + // swapping out the models ( or perhaps we only want to do this + // for vba mode ) there are a number of feasible and valid possibilities + ::xmlscript::importDialogModel( xInput, xDialogModel, i_xContext, xModel ); + + // Set resource property + if( xStringResourceManager.is() ) + { + Reference< beans::XPropertySet > xDlgPSet( xDialogModel, UNO_QUERY ); + Any aStringResourceManagerAny; + aStringResourceManagerAny <<= xStringResourceManager; + xDlgPSet->setPropertyValue( "ResourceResolver", aStringResourceManagerAny ); + } + + return xDialogModel; + } + + // mutex + + + ::osl::Mutex& getMutex() + { + static ::osl::Mutex s_aMutex; + + return s_aMutex; + } + + + // DialogProviderImpl + + + DialogProviderImpl::DialogProviderImpl( const Reference< XComponentContext >& rxContext ) + :m_xContext( rxContext ) + { + } + + + DialogProviderImpl::~DialogProviderImpl() + { + } + + + static Reference< resource::XStringResourceManager > getStringResourceFromDialogLibrary + ( const Reference< container::XNameContainer >& xDialogLib ) + { + Reference< resource::XStringResourceManager > xStringResourceManager; + if( xDialogLib.is() ) + { + Reference< resource::XStringResourceSupplier > xStringResourceSupplier( xDialogLib, UNO_QUERY ); + if( xStringResourceSupplier.is() ) + { + Reference< resource::XStringResourceResolver > + xStringResourceResolver = xStringResourceSupplier->getStringResource(); + + xStringResourceManager = + Reference< resource::XStringResourceManager >( xStringResourceResolver, UNO_QUERY ); + } + } + return xStringResourceManager; + } + + Reference< container::XNameContainer > DialogProviderImpl::createDialogModel( + const Reference< io::XInputStream >& xInput, + const Reference< resource::XStringResourceManager >& xStringResourceManager, + const Any &aDialogSourceURL) + { + return lcl_createDialogModel(m_xContext,xInput,m_xModel,xStringResourceManager,aDialogSourceURL); + } + + Reference< XControlModel > DialogProviderImpl::createDialogModelForBasic() + { + if (!m_BasicInfo) + // shouldn't get here + throw RuntimeException("No information to create dialog" ); + Reference< resource::XStringResourceManager > xStringResourceManager = getStringResourceFromDialogLibrary( m_BasicInfo->mxDlgLib ); + + Any aDialogSourceURL((OUString())); + Reference< XControlModel > xCtrlModel( createDialogModel( m_BasicInfo->mxInput, xStringResourceManager, aDialogSourceURL ), UNO_QUERY_THROW ); + return xCtrlModel; + } + + Reference< XControlModel > DialogProviderImpl::createDialogModel( const OUString& sURL ) + { + + OUString aURL( sURL ); + + // parse URL + // TODO: use URL parsing class + // TODO: decoding of location + + Reference< uri::XUriReferenceFactory > xFac ( uri::UriReferenceFactory::create( m_xContext ) ); + + // i75778: Support non-script URLs + Reference< io::XInputStream > xInput; + Reference< container::XNameContainer > xDialogLib; + + // Accept file URL to single dialog + bool bSingleDialog = false; + + Reference< util::XMacroExpander > xMacroExpander = + util::theMacroExpander::get(m_xContext); + + Reference< uri::XUriReference > uriRef; + for (;;) + { + uriRef = xFac->parse( aURL ); + if ( !uriRef.is() ) + { + OUString errorMsg = "DialogProviderImpl::getDialogModel: failed to parse URI: " + aURL; + throw IllegalArgumentException( errorMsg, Reference< XInterface >(), 1 ); + } + Reference < uri::XVndSunStarExpandUrl > sxUri( uriRef, UNO_QUERY ); + if( !sxUri.is() ) + break; + + aURL = sxUri->expand( xMacroExpander ); + } + + Reference < uri::XVndSunStarScriptUrl > sfUri( uriRef, UNO_QUERY ); + if( !sfUri.is() ) + { + bSingleDialog = true; + + // Try any other URL with SimpleFileAccess + Reference< ucb::XSimpleFileAccess3 > xSFI = ucb::SimpleFileAccess::create(m_xContext); + + try + { + xInput = xSFI->openFileRead( aURL ); + } + catch( Exception& ) + {} + } + else + { + OUString sDescription = sfUri->getName(); + + sal_Int32 nIndex = 0; + + OUString sLibName = sDescription.getToken( 0, '.', nIndex ); + OUString sDlgName; + if ( nIndex != -1 ) + sDlgName = sDescription.getToken( 0, '.', nIndex ); + + OUString sLocation = sfUri->getParameter( "location" ); + + + // get dialog library container + // TODO: dialogs in packages + Reference< XLibraryContainer > xLibContainer; + + if ( sLocation == "application" ) + { + xLibContainer = SfxGetpApp()->GetDialogContainer(); + } + else if ( sLocation == "document" ) + { + Reference< XEmbeddedScripts > xDocumentScripts( m_xModel, UNO_QUERY ); + if ( xDocumentScripts.is() ) + { + xLibContainer = xDocumentScripts->getDialogLibraries(); + OSL_ENSURE( xLibContainer.is(), + "DialogProviderImpl::createDialogModel: invalid dialog container!" ); + } + } + else + { + const Sequence< OUString > aOpenDocsTdocURLs( MiscUtils::allOpenTDocUrls( m_xContext ) ); + for ( auto const & tdocURL : aOpenDocsTdocURLs ) + { + Reference< frame::XModel > xModel( MiscUtils::tDocUrlToModel( tdocURL ) ); + OSL_ENSURE( xModel.is(), "DialogProviderImpl::createDialogModel: invalid document model!" ); + if ( !xModel.is() ) + continue; + + OUString sDocURL = xModel->getURL(); + if ( sDocURL.isEmpty() ) + { + sDocURL = ::comphelper::NamedValueCollection::getOrDefault( xModel->getArgs(), u"Title", sDocURL ); + } + + if ( sLocation != sDocURL ) + continue; + + Reference< XEmbeddedScripts > xDocumentScripts( m_xModel, UNO_QUERY ); + if ( !xDocumentScripts.is() ) + continue; + + xLibContainer = xDocumentScripts->getDialogLibraries(); + OSL_ENSURE( xLibContainer.is(), + "DialogProviderImpl::createDialogModel: invalid dialog container!" ); + } + } + + // get input stream provider + Reference< io::XInputStreamProvider > xISP; + if ( !xLibContainer.is() ) + { + throw IllegalArgumentException( + "DialogProviderImpl::getDialog: library container not found!", + Reference< XInterface >(), 1 ); + } + + // load dialog library + if ( !xLibContainer->isLibraryLoaded( sLibName ) ) + xLibContainer->loadLibrary( sLibName ); + + // get dialog library + if ( xLibContainer->hasByName( sLibName ) ) + { + Any aElement = xLibContainer->getByName( sLibName ); + aElement >>= xDialogLib; + } + + if ( !xDialogLib.is() ) + { + throw IllegalArgumentException( + "DialogProviderImpl::getDialogModel: library not found!", + Reference< XInterface >(), 1 ); + } + + // get input stream provider + if ( xDialogLib->hasByName( sDlgName ) ) + { + Any aElement = xDialogLib->getByName( sDlgName ); + aElement >>= xISP; + } + + if ( !xISP.is() ) + { + throw IllegalArgumentException( + "DialogProviderImpl::getDialogModel: dialog not found!", + Reference< XInterface >(), 1 ); + } + + + + if ( xISP.is() ) + xInput = xISP->createInputStream(); + msDialogLibName = sLibName; + } + + // import dialog model + Reference< XControlModel > xCtrlModel; + if ( xInput.is() && m_xContext.is() ) + { + Reference< resource::XStringResourceManager > xStringResourceManager; + if( bSingleDialog ) + { + xStringResourceManager = lcl_getStringResourceManager(m_xContext,aURL); + } + else if( xDialogLib.is() ) + { + xStringResourceManager = getStringResourceFromDialogLibrary( xDialogLib ); + } + + Any aDialogSourceURLAny; + aDialogSourceURLAny <<= aURL; + + Reference< container::XNameContainer > xDialogModel( createDialogModel( xInput , xStringResourceManager, aDialogSourceURLAny ), UNO_SET_THROW); + + xCtrlModel.set( xDialogModel, UNO_QUERY ); + } + return xCtrlModel; + } + + + Reference< XUnoControlDialog > DialogProviderImpl::createDialogControl + ( const Reference< XControlModel >& rxDialogModel, const Reference< XWindowPeer >& xParent ) + { + OSL_ENSURE( rxDialogModel.is(), "DialogProviderImpl::getDialogControl: no dialog model" ); + + Reference< XUnoControlDialog > xDialogControl; + + if ( m_xContext.is() ) + { + xDialogControl = UnoControlDialog::create( m_xContext ); + + // set the model + if ( rxDialogModel.is() ) + xDialogControl->setModel( rxDialogModel ); + + // set visible + xDialogControl->setVisible( false ); + + // get the parent of the dialog control + Reference< XWindowPeer > xPeer; + if( xParent.is() ) + { + xPeer = xParent; + } + else if ( m_xModel.is() ) + { + Reference< frame::XController > xController = m_xModel->getCurrentController(); + if ( xController.is() ) + { + Reference< frame::XFrame > xFrame = xController->getFrame(); + if ( xFrame.is() ) + xPeer.set( xFrame->getContainerWindow(), UNO_QUERY ); + } + } + + // create a peer + Reference< XToolkit> xToolkit( Toolkit::create( m_xContext ), UNO_QUERY_THROW ); + xDialogControl->createPeer( xToolkit, xPeer ); + } + + return xDialogControl; + } + + + void DialogProviderImpl::attachControlEvents( + const Reference< XControl >& rxControl, + const Reference< XInterface >& rxHandler, + const Reference< XIntrospectionAccess >& rxIntrospectionAccess, + bool bDialogProviderMode ) + { + if ( !rxControl.is() ) + return; + + Reference< XControlContainer > xControlContainer( rxControl, UNO_QUERY ); + + if ( !xControlContainer.is() ) + return; + + Sequence< Reference< XControl > > aControls = xControlContainer->getControls(); + const Reference< XControl >* pControls = aControls.getConstArray(); + sal_Int32 nControlCount = aControls.getLength(); + + Sequence< Reference< XInterface > > aObjects( nControlCount + 1 ); + Reference< XInterface >* pObjects = aObjects.getArray(); + for ( sal_Int32 i = 0; i < nControlCount; ++i ) + { + pObjects[i].set( pControls[i], UNO_QUERY ); + } + + // also add the dialog control itself to the sequence + pObjects[nControlCount].set( rxControl, UNO_QUERY ); + + Reference xScriptEventsAttacher + = new DialogEventsAttacherImpl( + m_xContext, m_xModel, rxControl, rxHandler, rxIntrospectionAccess, + bDialogProviderMode, + (m_BasicInfo ? m_BasicInfo->mxBasicRTLListener : nullptr), msDialogLibName); + + Any aHelper; + xScriptEventsAttacher->attachEvents( aObjects, Reference< XScriptListener >(), aHelper ); + } + + Reference< XIntrospectionAccess > DialogProviderImpl::inspectHandler( const Reference< XInterface >& rxHandler ) + { + Reference< XIntrospectionAccess > xIntrospectionAccess; + static Reference< XIntrospection > xIntrospection; + + if( !rxHandler.is() ) + return xIntrospectionAccess; + + if( !xIntrospection.is() ) + { + // Get introspection service + xIntrospection = theIntrospection::get( m_xContext ); + } + + // Do introspection + try + { + Any aHandlerAny; + aHandlerAny <<= rxHandler; + xIntrospectionAccess = xIntrospection->inspect( aHandlerAny ); + } + catch( RuntimeException& ) + { + xIntrospectionAccess.clear(); + } + return xIntrospectionAccess; + } + + + // XServiceInfo + + + OUString DialogProviderImpl::getImplementationName( ) + { + return "com.sun.star.comp.scripting.DialogProvider"; + } + + sal_Bool DialogProviderImpl::supportsService( const OUString& rServiceName ) + { + return cppu::supportsService(this, rServiceName); + } + + Sequence< OUString > DialogProviderImpl::getSupportedServiceNames( ) + { + return { "com.sun.star.awt.DialogProvider", + "com.sun.star.awt.DialogProvider2", + "com.sun.star.awt.ContainerWindowProvider" }; + } + + + // XInitialization + + + void DialogProviderImpl::initialize( const Sequence< Any >& aArguments ) + { + ::osl::MutexGuard aGuard( getMutex() ); + + if ( aArguments.getLength() == 1 ) + { + aArguments[0] >>= m_xModel; + + if ( !m_xModel.is() ) + { + throw RuntimeException( "DialogProviderImpl::initialize: invalid argument format!" ); + } + } + else if ( aArguments.getLength() == 4 ) + { + // call from RTL_Impl_CreateUnoDialog + aArguments[0] >>= m_xModel; + m_BasicInfo.reset( new BasicRTLParams ); + m_BasicInfo->mxInput.set( aArguments[ 1 ], UNO_QUERY_THROW ); + // allow null mxDlgLib, a document dialog instantiated from + // from application basic is unable to provide ( or find ) it's + // Library + aArguments[ 2 ] >>= m_BasicInfo->mxDlgLib; + // leave the possibility to optionally allow the old dialog creation + // to use the new XScriptListener ( which converts the old style macro + // to a SF url ) + m_BasicInfo->mxBasicRTLListener.set( aArguments[ 3 ], UNO_QUERY); + } + else if ( aArguments.getLength() > 4 ) + { + throw RuntimeException( "DialogProviderImpl::initialize: invalid number of arguments!" ); + } + } + + + // XDialogProvider + + + constexpr OUStringLiteral aDecorationPropName = u"Decoration"; + + Reference < XControl > DialogProviderImpl::createDialogImpl( + const OUString& URL, const Reference< XInterface >& xHandler, + const Reference< XWindowPeer >& xParent, bool bDialogProviderMode ) + { + // if the dialog is located in a document, the document must already be open! + + ::osl::MutexGuard aGuard( getMutex() ); + + + // m_xHandler = xHandler; + + //Reference< XDialog > xDialog; + Reference< XControl > xCtrl; + Reference< XControlModel > xCtrlMod; + try + { + // add support for basic RTL_FUNCTION + if (m_BasicInfo) + xCtrlMod = createDialogModelForBasic(); + else + { + OSL_ENSURE( !URL.isEmpty(), "DialogProviderImpl::getDialog: no URL!" ); + xCtrlMod = createDialogModel( URL ); + } + } + catch ( const RuntimeException& ) { throw; } + catch ( const Exception& ) + { + const Any aError( ::cppu::getCaughtException() ); + throw WrappedTargetRuntimeException( OUString(), *this, aError ); + } + if ( xCtrlMod.is() ) + { + // i83963 Force decoration + if( bDialogProviderMode ) + { + uno::Reference< beans::XPropertySet > xDlgModPropSet( xCtrlMod, uno::UNO_QUERY ); + if( xDlgModPropSet.is() ) + { + try + { + bool bDecoration = true; + Any aDecorationAny = xDlgModPropSet->getPropertyValue( aDecorationPropName ); + aDecorationAny >>= bDecoration; + if( !bDecoration ) + { + xDlgModPropSet->setPropertyValue( aDecorationPropName, Any( true ) ); + xDlgModPropSet->setPropertyValue( "Title", Any( OUString() ) ); + } + } + catch( UnknownPropertyException& ) + {} + } + } + + xCtrl.set( createDialogControl( xCtrlMod, xParent ) ); + if ( xCtrl.is() ) + { + Reference< XIntrospectionAccess > xIntrospectionAccess = inspectHandler( xHandler ); + attachControlEvents( xCtrl, xHandler, xIntrospectionAccess, bDialogProviderMode ); + } + } + + return xCtrl; + } + + Reference < XDialog > DialogProviderImpl::createDialog( const OUString& URL ) + { + Reference< XInterface > xDummyHandler; + Reference< XWindowPeer > xDummyPeer; + Reference < XControl > xControl = DialogProviderImpl::createDialogImpl( URL, xDummyHandler, xDummyPeer, true ); + Reference< XDialog > xDialog( xControl, UNO_QUERY ); + return xDialog; + } + + Reference < XDialog > DialogProviderImpl::createDialogWithHandler( + const OUString& URL, const Reference< XInterface >& xHandler ) + { + if( !xHandler.is() ) + { + throw IllegalArgumentException( + "DialogProviderImpl::createDialogWithHandler: Invalid xHandler!", + Reference< XInterface >(), 1 ); + } + Reference< XWindowPeer > xDummyPeer; + Reference < XControl > xControl = DialogProviderImpl::createDialogImpl( URL, xHandler, xDummyPeer, true ); + Reference< XDialog > xDialog( xControl, UNO_QUERY ); + return xDialog; + } + + Reference < XDialog > DialogProviderImpl::createDialogWithArguments( + const OUString& URL, const Sequence< NamedValue >& Arguments ) + { + ::comphelper::NamedValueCollection aArguments( Arguments ); + + Reference< XWindowPeer > xParentPeer; + if ( aArguments.has( "ParentWindow" ) ) + { + const Any& aParentWindow( aArguments.get( "ParentWindow" ) ); + if ( !( aParentWindow >>= xParentPeer ) ) + { + const Reference< XControl > xParentControl( aParentWindow, UNO_QUERY ); + if ( xParentControl.is() ) + xParentPeer = xParentControl->getPeer(); + } + } + + const Reference< XInterface > xHandler( aArguments.get( "EventHandler" ), UNO_QUERY ); + + Reference < XControl > xControl = DialogProviderImpl::createDialogImpl( URL, xHandler, xParentPeer, true ); + Reference< XDialog > xDialog( xControl, UNO_QUERY ); + return xDialog; + } + + Reference< XWindow > DialogProviderImpl::createContainerWindow( + const OUString& URL, const OUString&, + const Reference< XWindowPeer >& xParent, const Reference< XInterface >& xHandler ) + { + if( !xParent.is() ) + { + throw IllegalArgumentException( + "DialogProviderImpl::createContainerWindow: Invalid xParent!", + Reference< XInterface >(), 1 ); + } + Reference < XControl > xControl = DialogProviderImpl::createDialogImpl( URL, xHandler, xParent, false ); + Reference< XWindow> xWindow( xControl, UNO_QUERY ); + return xWindow; + } + + + // component operations + + + extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* + scripting_DialogProviderImpl_get_implementation( + css::uno::XComponentContext* context, css::uno::Sequence const&) + { + return cppu::acquire(new DialogProviderImpl(context)); + } + +} // namespace dlgprov + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/scripting/source/dlgprov/dlgprov.hxx b/scripting/source/dlgprov/dlgprov.hxx new file mode 100644 index 000000000..0a5d4483a --- /dev/null +++ b/scripting/source/dlgprov/dlgprov.hxx @@ -0,0 +1,148 @@ +/* -*- 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 . + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + +namespace dlgprov +{ + + + // mutex + + + ::osl::Mutex& getMutex(); + + + + css::uno::Reference< css::container::XNameContainer > lcl_createControlModel(const css::uno::Reference< css::uno::XComponentContext >& i_xContext); + css::uno::Reference< css::resource::XStringResourceManager > lcl_getStringResourceManager(const css::uno::Reference< css::uno::XComponentContext >& i_xContext, std::u16string_view i_sURL); + /// @throws css::uno::Exception + css::uno::Reference< css::container::XNameContainer > lcl_createDialogModel( + const css::uno::Reference< css::uno::XComponentContext >& i_xContext, + const css::uno::Reference< css::io::XInputStream >& xInput, + const css::uno::Reference< css::frame::XModel >& xModel, + const css::uno::Reference< css::resource::XStringResourceManager >& xStringResourceManager, + const css::uno::Any &aDialogSourceURL); + + typedef ::cppu::WeakImplHelper< + css::lang::XServiceInfo, + css::lang::XInitialization, + css::awt::XDialogProvider2, + css::awt::XContainerWindowProvider > DialogProviderImpl_BASE; + + class DialogProviderImpl : public DialogProviderImpl_BASE + { + private: + struct BasicRTLParams + { + css::uno::Reference< css::io::XInputStream > mxInput; + css::uno::Reference< css::container::XNameContainer > mxDlgLib; + css::uno::Reference< css::script::XScriptListener > mxBasicRTLListener; + }; + std::unique_ptr< BasicRTLParams > m_BasicInfo; + css::uno::Reference< css::uno::XComponentContext > m_xContext; + css::uno::Reference< css::frame::XModel > m_xModel; + + OUString msDialogLibName; + css::uno::Reference< css::awt::XControlModel > createDialogModel( const OUString& sURL ); + + css::uno::Reference< css::awt::XUnoControlDialog > createDialogControl( + const css::uno::Reference< css::awt::XControlModel >& rxDialogModel, + const css::uno::Reference< css::awt::XWindowPeer >& xParent ); + + void attachControlEvents( const css::uno::Reference< css::awt::XControl >& rxControlContainer, + const css::uno::Reference< css::uno::XInterface >& rxHandler, + const css::uno::Reference< css::beans::XIntrospectionAccess >& rxIntrospectionAccess, + bool bDialogProviderMode ); + css::uno::Reference< css::beans::XIntrospectionAccess > inspectHandler( + const css::uno::Reference< css::uno::XInterface >& rxHandler ); + // helper methods + /// @throws css::uno::Exception + css::uno::Reference< css::container::XNameContainer > createDialogModel( + const css::uno::Reference< css::io::XInputStream >& xInput, + const css::uno::Reference< css::resource::XStringResourceManager >& xStringResourceManager, + const css::uno::Any &aDialogSourceURL); + /// @throws css::uno::Exception + css::uno::Reference< css::awt::XControlModel > createDialogModelForBasic(); + + // XDialogProvider / XDialogProvider2 impl method + /// @throws css::lang::IllegalArgumentException + /// @throws css::uno::RuntimeException + css::uno::Reference < css::awt::XControl > createDialogImpl( + const OUString& URL, + const css::uno::Reference< css::uno::XInterface >& xHandler, + const css::uno::Reference< css::awt::XWindowPeer >& xParent, + bool bDialogProviderMode ); + + public: + explicit DialogProviderImpl( + const css::uno::Reference< css::uno::XComponentContext >& rxContext ); + virtual ~DialogProviderImpl() override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName( ) override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; + + // XInitialization + virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) override; + + // XDialogProvider + virtual css::uno::Reference < css::awt::XDialog > SAL_CALL createDialog( + const OUString& URL ) override; + + // XDialogProvider2 + virtual css::uno::Reference < css::awt::XDialog > SAL_CALL createDialogWithHandler( + const OUString& URL, + const css::uno::Reference< css::uno::XInterface >& xHandler ) override; + + virtual css::uno::Reference < css::awt::XDialog > SAL_CALL createDialogWithArguments( + const OUString& URL, + const css::uno::Sequence< css::beans::NamedValue >& Arguments ) override; + + virtual css::uno::Reference< css::awt::XWindow > SAL_CALL createContainerWindow( + const OUString& URL, const OUString& WindowType, + const css::uno::Reference< css::awt::XWindowPeer >& xParent, + const css::uno::Reference< css::uno::XInterface >& xHandler ) override; + }; + + +} // namespace dlgprov + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ -- cgit v1.2.3