Update git submodules
[LibreOffice.git] / scripting / source / dlgprov / dlgevtatt.cxx
blobdd0465eb01982cfd1056a2218114d567e2113a17
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "dlgevtatt.hxx"
22 #include "dlgprov.hxx"
24 #include <sfx2/strings.hrc>
25 #include <sfx2/sfxresid.hxx>
26 #include <utility>
27 #include <vcl/svapp.hxx>
28 #include <vcl/weld.hxx>
29 #include <comphelper/diagnose_ex.hxx>
31 #include <com/sun/star/awt/XControl.hpp>
32 #include <com/sun/star/awt/XControlContainer.hpp>
33 #include <com/sun/star/awt/XDialogEventHandler.hpp>
34 #include <com/sun/star/awt/XContainerWindowEventHandler.hpp>
35 #include <com/sun/star/beans/XPropertySet.hpp>
36 #include <com/sun/star/script/ScriptEventDescriptor.hpp>
37 #include <com/sun/star/script/XScriptEventsSupplier.hpp>
38 #include <com/sun/star/script/provider/XScriptProvider.hpp>
39 #include <com/sun/star/script/provider/theMasterScriptProviderFactory.hpp>
40 #include <com/sun/star/script/provider/XScriptProviderSupplier.hpp>
41 #include <com/sun/star/script/vba/XVBACompatibility.hpp>
42 #include <com/sun/star/lang/ServiceNotRegisteredException.hpp>
43 #include <com/sun/star/reflection/XIdlMethod.hpp>
44 #include <com/sun/star/beans/MethodConcept.hpp>
45 #include <com/sun/star/beans/XMaterialHolder.hpp>
47 #include <ooo/vba/XVBAToOOEventDescGen.hpp>
49 using namespace ::com::sun::star;
50 using namespace ::com::sun::star::awt;
51 using namespace ::com::sun::star::beans;
52 using namespace ::com::sun::star::lang;
53 using namespace ::com::sun::star::script;
54 using namespace ::com::sun::star::uno;
55 using namespace ::com::sun::star::reflection;
58 namespace dlgprov
60 namespace {
62 class DialogSFScriptListenerImpl : public DialogScriptListenerImpl
64 protected:
65 Reference< frame::XModel > m_xModel;
66 virtual void firing_impl( const script::ScriptEvent& aScriptEvent, uno::Any* pRet ) override;
67 public:
68 DialogSFScriptListenerImpl( const Reference< XComponentContext >& rxContext, const Reference< frame::XModel >& rxModel ) : DialogScriptListenerImpl( rxContext ), m_xModel( rxModel ) {}
71 class DialogLegacyScriptListenerImpl : public DialogSFScriptListenerImpl
73 protected:
74 virtual void firing_impl( const script::ScriptEvent& aScriptEvent, uno::Any* pRet ) override;
75 public:
76 DialogLegacyScriptListenerImpl( const Reference< XComponentContext >& rxContext, const Reference< frame::XModel >& rxModel ) : DialogSFScriptListenerImpl( rxContext, rxModel ){}
79 class DialogUnoScriptListenerImpl : public DialogSFScriptListenerImpl
81 Reference< awt::XControl > m_xControl;
82 Reference< XInterface > m_xHandler;
83 Reference< beans::XIntrospectionAccess > m_xIntrospectionAccess;
84 bool m_bDialogProviderMode;
86 virtual void firing_impl( const script::ScriptEvent& aScriptEvent, uno::Any* pRet ) override;
88 public:
89 DialogUnoScriptListenerImpl( const Reference< XComponentContext >& rxContext,
90 const Reference< frame::XModel >& rxModel,
91 const Reference< awt::XControl >& rxControl,
92 const Reference< XInterface >& rxHandler,
93 const Reference< beans::XIntrospectionAccess >& rxIntrospectionAccess,
94 bool bDialogProviderMode ); // false: ContainerWindowProvider mode
98 class DialogVBAScriptListenerImpl : public DialogScriptListenerImpl
100 protected:
101 OUString msDialogCodeName;
102 OUString msDialogLibName;
103 Reference< script::XScriptListener > mxListener;
104 virtual void firing_impl( const script::ScriptEvent& aScriptEvent, uno::Any* pRet ) override;
105 public:
106 DialogVBAScriptListenerImpl( const Reference< XComponentContext >& rxContext, const Reference< awt::XControl >& rxControl, const Reference< frame::XModel >& xModel, OUString sDialogLibName );
111 DialogVBAScriptListenerImpl::DialogVBAScriptListenerImpl( const Reference< XComponentContext >& rxContext, const Reference< awt::XControl >& rxControl, const Reference< frame::XModel >& xModel, OUString sDialogLibName ) : DialogScriptListenerImpl( rxContext ), msDialogLibName(std::move( sDialogLibName ))
113 Reference< XMultiComponentFactory > xSMgr( m_xContext->getServiceManager() );
114 Sequence< Any > args(1);
115 if ( xSMgr.is() )
117 args.getArray()[0] <<= xModel;
118 mxListener.set( xSMgr->createInstanceWithArgumentsAndContext( u"ooo.vba.EventListener"_ustr, args, m_xContext ), UNO_QUERY );
120 if ( !rxControl.is() )
121 return;
125 Reference< XPropertySet > xProps( rxControl->getModel(), UNO_QUERY_THROW );
126 xProps->getPropertyValue(u"Name"_ustr) >>= msDialogCodeName;
127 xProps.set( mxListener, UNO_QUERY_THROW );
128 xProps->setPropertyValue(u"Model"_ustr, args[ 0 ] );
130 catch( const Exception& )
132 DBG_UNHANDLED_EXCEPTION("scripting");
137 void DialogVBAScriptListenerImpl::firing_impl( const script::ScriptEvent& aScriptEvent, uno::Any* )
139 if ( !(aScriptEvent.ScriptType == "VBAInterop" && mxListener.is()) )
140 return;
142 ScriptEvent aScriptEventCopy( aScriptEvent );
143 aScriptEventCopy.ScriptCode = msDialogLibName + "." + msDialogCodeName;
146 mxListener->firing( aScriptEventCopy );
148 catch( const Exception& )
150 DBG_UNHANDLED_EXCEPTION("scripting");
155 // DialogEventsAttacherImpl
158 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 )
159 :mbUseFakeVBAEvents( false ), m_xContext( rxContext )
161 // key listeners by protocol when ScriptType = 'Script'
162 // otherwise key is the ScriptType e.g. StarBasic
163 if ( rxRTLListener.is() ) // set up handler for RTL_BASIC
164 listenersForTypes[ u"StarBasic"_ustr ] = rxRTLListener;
165 else
166 listenersForTypes[ u"StarBasic"_ustr ] = new DialogLegacyScriptListenerImpl( rxContext, rxModel );
167 // handler for Script & OUString("vnd.sun.star.UNO:")
168 listenersForTypes[ u"vnd.sun.star.UNO"_ustr ] = new DialogUnoScriptListenerImpl( rxContext, rxModel, rxControl, rxHandler, rxIntrospect, bProviderMode );
169 listenersForTypes[ u"vnd.sun.star.script"_ustr ] = new DialogSFScriptListenerImpl( rxContext, rxModel );
171 // determine the VBA compatibility mode from the Basic library container
174 uno::Reference< beans::XPropertySet > xModelProps( rxModel, uno::UNO_QUERY_THROW );
175 uno::Reference< script::vba::XVBACompatibility > xVBACompat(
176 xModelProps->getPropertyValue(u"BasicLibraries"_ustr), uno::UNO_QUERY_THROW );
177 mbUseFakeVBAEvents = xVBACompat->getVBACompatibilityMode();
179 catch( uno::Exception& )
182 if ( mbUseFakeVBAEvents )
183 listenersForTypes[ u"VBAInterop"_ustr ] = new DialogVBAScriptListenerImpl( rxContext, rxControl, rxModel, sDialogLibName );
187 DialogEventsAttacherImpl::~DialogEventsAttacherImpl()
192 Reference< script::XScriptListener > const &
193 DialogEventsAttacherImpl::getScriptListenerForKey( const OUString& sKey )
195 ListenerHash::iterator it = listenersForTypes.find( sKey );
196 if ( it == listenersForTypes.end() )
197 throw RuntimeException(); // more text info here please
198 return it->second;
200 Reference< XScriptEventsSupplier > DialogEventsAttacherImpl::getFakeVbaEventsSupplier( const Reference< XControl >& xControl, OUString const & sControlName )
202 Reference< XScriptEventsSupplier > xEventsSupplier;
203 Reference< XMultiComponentFactory > xSMgr( m_xContext->getServiceManager() );
204 if ( xSMgr.is() )
206 Reference< ooo::vba::XVBAToOOEventDescGen > xVBAToOOEvtDesc( xSMgr->createInstanceWithContext(u"ooo.vba.VBAToOOEventDesc"_ustr, m_xContext ), UNO_QUERY );
207 if ( xVBAToOOEvtDesc.is() )
208 xEventsSupplier = xVBAToOOEvtDesc->getEventSupplier( xControl, sControlName );
211 return xEventsSupplier;
215 void DialogEventsAttacherImpl::attachEventsToControl( const Reference< XControl>& xControl, const Reference< XScriptEventsSupplier >& xEventsSupplier, const Any& Helper )
217 if ( !xEventsSupplier.is() )
218 return;
220 Reference< container::XNameContainer > xEventCont = xEventsSupplier->getEvents();
222 Reference< XControlModel > xControlModel = xControl->getModel();
223 if ( !xEventCont.is() )
224 return;
226 const Sequence< OUString > aNames = xEventCont->getElementNames();
228 for ( const OUString& rName : aNames )
230 ScriptEventDescriptor aDesc;
232 Any aElement = xEventCont->getByName( rName );
233 aElement >>= aDesc;
234 OUString sKey = aDesc.ScriptType;
235 if ( aDesc.ScriptType == "Script" || aDesc.ScriptType == "UNO" )
237 sal_Int32 nIndex = aDesc.ScriptCode.indexOf( ':' );
238 sKey = aDesc.ScriptCode.copy( 0, nIndex );
240 Reference< XAllListener > xAllListener =
241 new DialogAllListenerImpl( getScriptListenerForKey( sKey ), aDesc.ScriptType, aDesc.ScriptCode );
243 // try first to attach event to the ControlModel
244 bool bSuccess = false;
247 Reference< XEventListener > xListener_ = m_xEventAttacher->attachSingleEventListener(
248 xControlModel, xAllListener, Helper, aDesc.ListenerType,
249 aDesc.AddListenerParam, aDesc.EventMethod );
251 if ( xListener_.is() )
252 bSuccess = true;
254 catch ( const Exception& )
256 DBG_UNHANDLED_EXCEPTION("scripting");
261 // if we had no success, try to attach to the control
262 if ( !bSuccess )
264 m_xEventAttacher->attachSingleEventListener(
265 xControl, xAllListener, Helper, aDesc.ListenerType,
266 aDesc.AddListenerParam, aDesc.EventMethod );
269 catch ( const Exception& )
271 DBG_UNHANDLED_EXCEPTION("scripting");
277 void DialogEventsAttacherImpl::nestedAttachEvents( const Sequence< Reference< XInterface > >& Objects, const Any& Helper, OUString& sDialogCodeName )
279 for ( const Reference< XInterface >& rObject : Objects )
281 // We know that we have to do with instances of XControl.
282 // Otherwise this is not the right implementation for
283 // XScriptEventsAttacher and we have to give up.
284 nestedAttachEvents(rObject.query<XControl>(), Helper, sDialogCodeName);
288 void DialogEventsAttacherImpl::nestedAttachEvents(
289 const css::uno::Reference<css::awt::XControl>& xControl, const css::uno::Any& Helper,
290 OUString& sDialogCodeName)
292 if (!xControl.is())
293 throw IllegalArgumentException();
294 Reference<XControlContainer> xControlContainer(xControl, UNO_QUERY);
295 Reference<XDialog> xDialog(xControl, UNO_QUERY);
297 // get XEventsSupplier from control model
298 Reference<XControlModel> xControlModel = xControl->getModel();
299 Reference<XScriptEventsSupplier> xEventsSupplier(xControlModel, UNO_QUERY);
300 attachEventsToControl(xControl, xEventsSupplier, Helper);
301 if (mbUseFakeVBAEvents)
303 xEventsSupplier.set(getFakeVbaEventsSupplier(xControl, sDialogCodeName));
304 Any newHelper(xControl);
305 attachEventsToControl(xControl, xEventsSupplier, newHelper);
307 if (xControlContainer.is() && !xDialog.is())
309 for (auto& xChildControl : xControlContainer->getControls())
310 nestedAttachEvents(xChildControl, Helper, sDialogCodeName);
315 // XScriptEventsAttacher
318 void SAL_CALL DialogEventsAttacherImpl::attachEvents( const Sequence< Reference< XInterface > >& Objects,
319 const css::uno::Reference<css::script::XScriptListener>&,
320 const Any& Helper )
322 // get EventAttacher
324 ::osl::MutexGuard aGuard( getMutex() );
326 if ( !m_xEventAttacher.is() )
328 Reference< XMultiComponentFactory > xSMgr( m_xContext->getServiceManager() );
329 if ( !xSMgr.is() )
330 throw RuntimeException();
332 m_xEventAttacher.set( xSMgr->createInstanceWithContext(
333 u"com.sun.star.script.EventAttacher"_ustr, m_xContext ), UNO_QUERY );
335 if ( !m_xEventAttacher.is() )
336 throw ServiceNotRegisteredException();
339 OUString sDialogCodeName;
340 sal_Int32 nObjCount = Objects.getLength();
341 Reference< awt::XControl > xDlgControl( Objects[ nObjCount - 1 ], uno::UNO_QUERY ); // last object is the dialog
342 if ( xDlgControl.is() )
344 Reference< XPropertySet > xProps( xDlgControl->getModel(), UNO_QUERY );
347 xProps->getPropertyValue(u"Name"_ustr) >>= sDialogCodeName;
349 catch( Exception& ){}
351 // go over all objects
352 nestedAttachEvents( Objects, Helper, sDialogCodeName );
356 // DialogAllListenerImpl
359 DialogAllListenerImpl::DialogAllListenerImpl( const Reference< XScriptListener >& rxListener,
360 OUString sScriptType, OUString sScriptCode )
361 :m_xScriptListener( rxListener )
362 ,m_sScriptType(std::move( sScriptType ))
363 ,m_sScriptCode(std::move( sScriptCode ))
368 DialogAllListenerImpl::~DialogAllListenerImpl()
373 void DialogAllListenerImpl::firing_impl( const AllEventObject& Event, Any* pRet )
375 ScriptEvent aScriptEvent;
376 aScriptEvent.Source = getXWeak(); // get correct XInterface
377 aScriptEvent.ListenerType = Event.ListenerType;
378 aScriptEvent.MethodName = Event.MethodName;
379 aScriptEvent.Arguments = Event.Arguments;
380 aScriptEvent.Helper = Event.Helper;
381 aScriptEvent.ScriptType = m_sScriptType;
382 aScriptEvent.ScriptCode = m_sScriptCode;
384 if ( m_xScriptListener.is() )
386 if ( pRet )
387 *pRet = m_xScriptListener->approveFiring( aScriptEvent );
388 else
389 m_xScriptListener->firing( aScriptEvent );
394 // XEventListener
397 void DialogAllListenerImpl::disposing(const EventObject& )
402 // XAllListener
405 void DialogAllListenerImpl::firing( const AllEventObject& Event )
407 //::osl::MutexGuard aGuard( getMutex() );
409 firing_impl( Event, nullptr );
413 Any DialogAllListenerImpl::approveFiring( const AllEventObject& Event )
415 //::osl::MutexGuard aGuard( getMutex() );
417 Any aReturn;
418 firing_impl( Event, &aReturn );
419 return aReturn;
423 // DialogScriptListenerImpl
426 DialogUnoScriptListenerImpl::DialogUnoScriptListenerImpl( const Reference< XComponentContext >& rxContext,
427 const Reference< css::frame::XModel >& rxModel,
428 const Reference< css::awt::XControl >& rxControl,
429 const Reference< css::uno::XInterface >& rxHandler,
430 const Reference< css::beans::XIntrospectionAccess >& rxIntrospectionAccess,
431 bool bDialogProviderMode )
432 : DialogSFScriptListenerImpl( rxContext, rxModel )
433 ,m_xControl( rxControl )
434 ,m_xHandler( rxHandler )
435 ,m_xIntrospectionAccess( rxIntrospectionAccess )
436 ,m_bDialogProviderMode( bDialogProviderMode )
441 DialogScriptListenerImpl::~DialogScriptListenerImpl()
446 void DialogSFScriptListenerImpl::firing_impl( const ScriptEvent& aScriptEvent, Any* pRet )
450 Reference< provider::XScriptProvider > xScriptProvider;
451 if ( m_xModel.is() )
453 Reference< provider::XScriptProviderSupplier > xSupplier( m_xModel, UNO_QUERY );
454 OSL_ENSURE( xSupplier.is(), "DialogScriptListenerImpl::firing_impl: failed to get script provider supplier" );
455 if ( xSupplier.is() )
456 xScriptProvider.set( xSupplier->getScriptProvider() );
458 else
460 OSL_ASSERT( m_xContext.is() );
461 if ( m_xContext.is() )
463 Reference< provider::XScriptProviderFactory > xFactory =
464 provider::theMasterScriptProviderFactory::get( m_xContext );
466 Any aCtx;
467 aCtx <<= u"user"_ustr;
468 xScriptProvider = xFactory->createScriptProvider( aCtx );
472 OSL_ENSURE( xScriptProvider.is(), "DialogScriptListenerImpl::firing_impl: failed to get script provider" );
474 if ( xScriptProvider.is() )
476 Reference< provider::XScript > xScript = xScriptProvider->getScript( aScriptEvent.ScriptCode );
477 OSL_ENSURE( xScript.is(), "DialogScriptListenerImpl::firing_impl: failed to get script" );
479 if ( xScript.is() )
481 Sequence< Any > aInParams;
482 Sequence< sal_Int16 > aOutParamsIndex;
483 Sequence< Any > aOutParams;
485 // get arguments for script
486 aInParams = aScriptEvent.Arguments;
488 Any aResult = xScript->invoke( aInParams, aOutParamsIndex, aOutParams );
489 if ( pRet )
490 *pRet = std::move(aResult);
494 catch ( const Exception& )
496 DBG_UNHANDLED_EXCEPTION("scripting");
500 void DialogLegacyScriptListenerImpl::firing_impl( const ScriptEvent& aScriptEvent, Any* pRet )
502 OUString sScriptURL;
503 OUString sScriptCode( aScriptEvent.ScriptCode );
505 if ( aScriptEvent.ScriptType != "StarBasic" )
506 return;
508 // StarBasic script: convert ScriptCode to scriptURL
509 sal_Int32 nIndex = sScriptCode.indexOf( ':' );
510 if ( nIndex >= 0 && nIndex < sScriptCode.getLength() )
512 sScriptURL = OUString::Concat("vnd.sun.star.script:") +
513 sScriptCode.subView( nIndex + 1 ) +
514 "?language=Basic&location=" +
515 sScriptCode.subView( 0, nIndex );
517 ScriptEvent aSFScriptEvent( aScriptEvent );
518 aSFScriptEvent.ScriptCode = sScriptURL;
519 DialogSFScriptListenerImpl::firing_impl( aSFScriptEvent, pRet );
522 void DialogUnoScriptListenerImpl::firing_impl( const ScriptEvent& aScriptEvent, Any* pRet )
524 OUString aMethodName = aScriptEvent.ScriptCode.copy( strlen("vnd.sun.star.UNO:") );
526 Any aEventObject = aScriptEvent.Arguments[0];
528 bool bHandled = false;
529 if( m_xHandler.is() )
531 if( m_bDialogProviderMode )
533 Reference< XDialogEventHandler > xDialogEventHandler( m_xHandler, UNO_QUERY );
534 if( xDialogEventHandler.is() )
536 Reference< XDialog > xDialog( m_xControl, UNO_QUERY );
537 bHandled = xDialogEventHandler->callHandlerMethod( xDialog, aEventObject, aMethodName );
540 else
542 Reference< XContainerWindowEventHandler > xContainerWindowEventHandler( m_xHandler, UNO_QUERY );
543 if( xContainerWindowEventHandler.is() )
545 Reference< XWindow > xWindow( m_xControl, UNO_QUERY );
546 bHandled = xContainerWindowEventHandler->callHandlerMethod( xWindow, aEventObject, aMethodName );
551 Any aRet;
552 if( !bHandled && m_xIntrospectionAccess.is() )
556 // call method
557 const Reference< XIdlMethod > xMethod = m_xIntrospectionAccess->
558 getMethod( aMethodName, MethodConcept::ALL - MethodConcept::DANGEROUS );
560 Reference< XMaterialHolder > xMaterialHolder =
561 Reference< XMaterialHolder >::query( m_xIntrospectionAccess );
562 Any aHandlerObject = xMaterialHolder->getMaterial();
564 Sequence< Reference< XIdlClass > > aParamTypeSeq = xMethod->getParameterTypes();
565 sal_Int32 nParamCount = aParamTypeSeq.getLength();
566 if( nParamCount == 0 )
568 Sequence<Any> args;
569 xMethod->invoke( aHandlerObject, args );
570 bHandled = true;
572 else if( nParamCount == 2 )
574 // Signature check automatically done by reflection
575 Sequence<Any> Args(2);
576 Any* pArgs = Args.getArray();
577 if( m_bDialogProviderMode )
579 Reference< XDialog > xDialog( m_xControl, UNO_QUERY );
580 pArgs[0] <<= xDialog;
582 else
584 Reference< XWindow > xWindow( m_xControl, UNO_QUERY );
585 pArgs[0] <<= xWindow;
587 pArgs[1] = std::move(aEventObject);
588 aRet = xMethod->invoke( aHandlerObject, Args );
589 bHandled = true;
592 catch( const Exception& )
594 DBG_UNHANDLED_EXCEPTION("scripting");
598 if( bHandled )
600 if( pRet )
601 *pRet = std::move(aRet);
603 else
605 OUString aRes(SfxResId(STR_ERRUNOEVENTBINDUNG));
606 OUString aQuoteChar( u"\""_ustr );
608 sal_Int32 nIndex = aRes.indexOf( '%' );
610 OUString aOUFinal =
611 aRes.subView( 0, nIndex ) +
612 aQuoteChar + aMethodName + aQuoteChar +
613 aRes.subView( nIndex + 2 );
615 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(nullptr,
616 VclMessageType::Warning, VclButtonsType::Ok, aOUFinal));
617 xBox->run();
622 // XEventListener
625 void DialogScriptListenerImpl::disposing(const EventObject& )
630 // XScriptListener
633 void DialogScriptListenerImpl::firing( const ScriptEvent& aScriptEvent )
635 //::osl::MutexGuard aGuard( getMutex() );
637 firing_impl( aScriptEvent, nullptr );
641 Any DialogScriptListenerImpl::approveFiring( const ScriptEvent& aScriptEvent )
643 //::osl::MutexGuard aGuard( getMutex() );
645 Any aReturn;
646 firing_impl( aScriptEvent, &aReturn );
647 return aReturn;
651 } // namespace dlgprov
654 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */