1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 <sal/macros.h>
21 #include <sal/log.hxx>
22 #include <comphelper/processfactory.hxx>
23 #include <comphelper/uno3.hxx>
24 #include <comphelper/compbase.hxx>
25 #include <comphelper/proparrhlp.hxx>
26 #include <comphelper/propertycontainer2.hxx>
27 #include <comphelper/diagnose_ex.hxx>
29 #include <ooo/vba/XVBAToOOEventDescGen.hpp>
31 #include <com/sun/star/beans/XPropertySet.hpp>
32 #include <com/sun/star/beans/theIntrospection.hpp>
33 #include <com/sun/star/beans/PropertyAttribute.hpp>
35 #include <com/sun/star/lang/XMultiComponentFactory.hpp>
36 #include <com/sun/star/lang/XServiceInfo.hpp>
37 #include <com/sun/star/lang/XInitialization.hpp>
39 #include <com/sun/star/util/XCloseListener.hpp>
40 #include <com/sun/star/util/XCloseBroadcaster.hpp>
42 #include <com/sun/star/frame/XModel.hpp>
44 #include <com/sun/star/script/ScriptEventDescriptor.hpp>
45 #include <com/sun/star/script/provider/XScriptProviderSupplier.hpp>
47 #include <com/sun/star/container/XNamed.hpp>
49 #include <com/sun/star/drawing/XControlShape.hpp>
51 #include <com/sun/star/awt/XControl.hpp>
52 #include <com/sun/star/awt/XDialog.hpp>
53 #include <com/sun/star/awt/KeyEvent.hpp>
54 #include <com/sun/star/awt/MouseEvent.hpp>
55 #include <com/sun/star/awt/XFixedText.hpp>
56 #include <com/sun/star/awt/XTextComponent.hpp>
57 #include <com/sun/star/awt/XComboBox.hpp>
58 #include <com/sun/star/awt/XRadioButton.hpp>
59 #include <com/sun/star/awt/XListBox.hpp>
61 #include <sfx2/objsh.hxx>
62 #include <basic/basmgr.hxx>
63 #include <filter/msfilter/msvbahelper.hxx>
64 #include <vbahelper/vbareturntypes.hxx>
66 #include <com/sun/star/script/XScriptListener.hpp>
67 #include <cppuhelper/implbase.hxx>
68 #include <cppuhelper/supportsservice.hxx>
69 #include <comphelper/evtmethodhelper.hxx>
72 #include <unordered_map>
74 using namespace ::com::sun::star
;
75 using namespace ::com::sun::star::script
;
76 using namespace ::com::sun::star::uno
;
77 using namespace ::ooo::vba
;
80 constexpr std::u16string_view DELIM
= u
"::";
81 constexpr sal_Int32 DELIMLEN
= DELIM
.size();
83 static bool isKeyEventOk( awt::KeyEvent
& evt
, const Sequence
< Any
>& params
)
85 return params
.hasElements() && ( params
[ 0 ] >>= evt
);
88 static bool isMouseEventOk( awt::MouseEvent
& evt
, const Sequence
< Any
>& params
)
90 return params
.hasElements() && ( params
[ 0 ] >>= evt
);
93 static Sequence
< Any
> ooMouseEvtToVBADblClick( const Sequence
< Any
>& params
)
97 if ( !( isMouseEventOk(evt
, params
)) ||
98 (evt
.ClickCount
!= 2) )
99 return Sequence
< Any
>();
100 // give back orig params, this will signal that the event is good
104 static Sequence
< Any
> ooMouseEvtToVBAMouseEvt( const Sequence
< Any
>& params
)
108 if ( !isMouseEventOk(evt
, params
) )
109 return Sequence
< Any
>();
111 Sequence
< Any
> translatedParams
{ Any(evt
.Buttons
), // Buttons
112 Any(evt
.Modifiers
), // Shift
115 return translatedParams
;
118 static Sequence
< Any
> ooKeyPressedToVBAKeyPressed( const Sequence
< Any
>& params
)
122 if ( !isKeyEventOk( evt
, params
) )
123 return Sequence
< Any
>();
125 Reference
< msforms::XReturnInteger
> xKeyCode
= new ReturnInteger( sal_Int32( evt
.KeyCode
) );
126 Sequence
< Any
> translatedParams
{ Any(xKeyCode
) };
127 return translatedParams
;
130 static Sequence
< Any
> ooKeyPressedToVBAKeyUpDown( const Sequence
< Any
>& params
)
134 if ( !isKeyEventOk( evt
, params
) )
135 return Sequence
< Any
>();
137 Reference
< msforms::XReturnInteger
> xKeyCode
= new ReturnInteger( evt
.KeyCode
);
138 sal_Int8 shift
= sal::static_int_cast
<sal_Int8
>( evt
.Modifiers
);
140 // #TODO check whether values from OOO conform to values generated from vba
141 Sequence
< Any
> translatedParams
{ Any(xKeyCode
), Any(shift
) };
142 return translatedParams
;
145 typedef Sequence
< Any
> (*Translator
)(const Sequence
< Any
>&);
149 //expand the "TranslateInfo" struct to support more kinds of events
152 OUString sVBAName
; //vba event name
153 Translator toVBA
; //the method to convert OO event parameters to VBA event parameters
154 bool (*ApproveRule
)(const ScriptEvent
& evt
, void const * pPara
); //this method is used to determine which types of controls should execute the event
155 void const *pPara
; //Parameters for the above approve method
160 typedef std::unordered_map
<
162 std::vector
< TranslateInfo
> > EventInfoHash
;
166 struct TranslatePropMap
168 OUString sEventInfo
; //OO event name
169 TranslateInfo aTransInfo
;
174 static bool ApproveAll(const ScriptEvent
& evt
, void const * pPara
); //allow all types of controls to execute the event
175 static bool ApproveType(const ScriptEvent
& evt
, void const * pPara
); //certain types of controls should execute the event, those types are given by pPara
176 static bool DenyType(const ScriptEvent
& evt
, void const * pPara
); //certain types of controls should not execute the event, those types are given by pPara
177 static bool DenyMouseDrag(const ScriptEvent
& evt
, void const * pPara
); //used for VBA MouseMove event when "Shift" key is pressed
183 uno::Type
const * pTypeList
;
189 Type
const typeXFixedText
= cppu::UnoType
<awt::XFixedText
>::get();
190 Type
const typeXTextComponent
= cppu::UnoType
<awt::XTextComponent
>::get();
191 Type
const typeXComboBox
= cppu::UnoType
<awt::XComboBox
>::get();
192 Type
const typeXRadioButton
= cppu::UnoType
<awt::XRadioButton
>::get();
193 Type
const typeXListBox
= cppu::UnoType
<awt::XListBox
>::get();
196 TypeList
const fixedTextList
= {&typeXFixedText
, 1};
197 TypeList
const textCompList
= {&typeXTextComponent
, 1};
198 TypeList
const radioButtonList
= {&typeXRadioButton
, 1};
199 TypeList
const comboBoxList
= {&typeXComboBox
, 1};
200 TypeList
const listBoxList
= {&typeXListBox
, 1};
202 //this array stores the OO event to VBA event translation info
203 static TranslatePropMap aTranslatePropMap_Impl
[] =
205 { u
"actionPerformed"_ustr
, { u
"_Change"_ustr
, nullptr, DenyType
, static_cast<void const *>(&radioButtonList
) } },
206 // actionPerformed ooo event
207 { u
"actionPerformed"_ustr
, { u
"_Click"_ustr
, nullptr, ApproveAll
, nullptr } },
208 { u
"itemStateChanged"_ustr
, { u
"_Change"_ustr
, nullptr, ApproveType
, static_cast<void const *>(&radioButtonList
) } },
209 // itemStateChanged ooo event
210 { u
"itemStateChanged"_ustr
, { u
"_Click"_ustr
, nullptr, ApproveType
, static_cast<void const *>(&comboBoxList
) } },
212 { u
"itemStateChanged"_ustr
, { u
"_Click"_ustr
, nullptr, ApproveType
, static_cast<void const *>(&listBoxList
) } },
214 { u
"changed"_ustr
, { u
"_Change"_ustr
, nullptr, ApproveAll
, nullptr } },
216 // focusGained ooo event
217 { u
"focusGained"_ustr
, { u
"_GotFocus"_ustr
, nullptr, ApproveAll
, nullptr } },
219 // focusLost ooo event
220 { u
"focusLost"_ustr
, { u
"_LostFocus"_ustr
, nullptr, ApproveAll
, nullptr } },
221 { u
"focusLost"_ustr
, { u
"_Exit"_ustr
, nullptr, ApproveType
, static_cast<void const *>(&textCompList
) } }, // support VBA TextBox_Exit event
223 // adjustmentValueChanged ooo event
224 { u
"adjustmentValueChanged"_ustr
, { u
"_Scroll"_ustr
, nullptr, ApproveAll
, nullptr } },
225 { u
"adjustmentValueChanged"_ustr
, { u
"_Change"_ustr
, nullptr, ApproveAll
, nullptr } },
227 // textChanged ooo event
228 { u
"textChanged"_ustr
, { u
"_Change"_ustr
, nullptr, ApproveAll
, nullptr } },
230 // keyReleased ooo event
231 { u
"keyReleased"_ustr
, { u
"_KeyUp"_ustr
, ooKeyPressedToVBAKeyUpDown
, ApproveAll
, nullptr } },
233 // mouseReleased ooo event
234 { u
"mouseReleased"_ustr
, { u
"_Click"_ustr
, ooMouseEvtToVBAMouseEvt
, ApproveType
, static_cast<void const *>(&fixedTextList
) } },
235 { u
"mouseReleased"_ustr
, { u
"_MouseUp"_ustr
, ooMouseEvtToVBAMouseEvt
, ApproveAll
, nullptr } },
237 // mousePressed ooo event
238 { u
"mousePressed"_ustr
, { u
"_MouseDown"_ustr
, ooMouseEvtToVBAMouseEvt
, ApproveAll
, nullptr } },
239 { u
"mousePressed"_ustr
, { u
"_DblClick"_ustr
, ooMouseEvtToVBADblClick
, ApproveAll
, nullptr } },
241 // mouseMoved ooo event
242 { u
"mouseMoved"_ustr
, { u
"_MouseMove"_ustr
, ooMouseEvtToVBAMouseEvt
, ApproveAll
, nullptr } },
243 { u
"mouseDragged"_ustr
, { u
"_MouseMove"_ustr
, ooMouseEvtToVBAMouseEvt
, DenyMouseDrag
, nullptr } },
245 // keyPressed ooo event
246 { u
"keyPressed"_ustr
, { u
"_KeyDown"_ustr
, ooKeyPressedToVBAKeyUpDown
, ApproveAll
, nullptr } },
247 { u
"keyPressed"_ustr
, { u
"_KeyPress"_ustr
, ooKeyPressedToVBAKeyPressed
, ApproveAll
, nullptr } }
250 static EventInfoHash
& getEventTransInfo()
252 static EventInfoHash eventTransInfo
= []()
256 TranslatePropMap
* pTransProp
= aTranslatePropMap_Impl
;
257 int nCount
= SAL_N_ELEMENTS(aTranslatePropMap_Impl
);
262 sEventInfo
= pTransProp
->sEventInfo
;
263 std::vector
< TranslateInfo
> infoList
;
266 infoList
.push_back( pTransProp
->aTransInfo
);
269 }while(i
< nCount
&& sEventInfo
== pTransProp
->sEventInfo
);
270 tmp
[sEventInfo
] = std::move(infoList
);
274 return eventTransInfo
;
282 class ScriptEventHelper
285 explicit ScriptEventHelper( const Reference
< XInterface
>& xControl
);
286 explicit ScriptEventHelper( const OUString
& sCntrlServiceName
);
287 ~ScriptEventHelper();
288 Sequence
< ScriptEventDescriptor
> createEvents( const OUString
& sCodeName
);
289 Sequence
< OUString
> getEventListeners() const;
291 Reference
< XComponentContext
> m_xCtx
;
292 Reference
< XInterface
> m_xControl
;
299 eventMethodToDescriptor( std::u16string_view rEventMethod
, ScriptEventDescriptor
& evtDesc
, const OUString
& sCodeName
)
301 // format of ControlListener is TypeName::methodname e.g.
302 // "com.sun.star.awt.XActionListener::actionPerformed" or
303 // "XActionListener::actionPerformed
305 OUString sMethodName
;
307 size_t nDelimPos
= rEventMethod
.find( DELIM
);
308 if ( nDelimPos
== std::u16string_view::npos
)
312 sMethodName
= rEventMethod
.substr( nDelimPos
+ DELIMLEN
);
313 sTypeName
= rEventMethod
.substr( 0, nDelimPos
);
315 EventInfoHash
& infos
= getEventTransInfo();
317 // Only create an ScriptEventDescriptor for an event we can translate
319 if ( !sMethodName
.isEmpty()
320 && !sTypeName
.isEmpty()
321 && ( infos
.find( sMethodName
) != infos
.end() ) )
323 // just fill in CodeName, when the event fires the other
324 // info is gathered from the event source to determine what
325 // event handler we try to call
326 evtDesc
.ScriptCode
= sCodeName
;
327 evtDesc
.ListenerType
= sTypeName
;
328 evtDesc
.EventMethod
= sMethodName
;
330 // set this it VBAInterop, ensures that it doesn't
331 // get persisted or shown in property editors
332 evtDesc
.ScriptType
= "VBAInterop";
339 ScriptEventHelper::ScriptEventHelper( const Reference
< XInterface
>& xControl
) :
340 m_xCtx( comphelper::getProcessComponentContext() ),
341 m_xControl( xControl
),
345 ScriptEventHelper::ScriptEventHelper( const OUString
& sCntrlServiceName
) :
346 m_xCtx( comphelper::getProcessComponentContext() ),
349 m_xControl
.set( m_xCtx
->getServiceManager()->createInstanceWithContext( sCntrlServiceName
, m_xCtx
), uno::UNO_QUERY
);
352 ScriptEventHelper::~ScriptEventHelper()
354 // dispose control ( and remove any associated event registrations )
359 uno::Reference
< lang::XComponent
> xComp( m_xControl
, uno::UNO_QUERY
);
363 // destructor can't throw
364 catch( uno::Exception
& )
371 ScriptEventHelper::getEventListeners() const
373 std::vector
< OUString
> eventMethods
;
375 Reference
< beans::XIntrospection
> xIntrospection
= beans::theIntrospection::get( m_xCtx
);
377 Reference
< beans::XIntrospectionAccess
> xIntrospectionAccess
=
378 xIntrospection
->inspect( Any( m_xControl
) );
379 const Sequence
< Type
> aControlListeners
=
380 xIntrospectionAccess
->getSupportedListeners();
381 for ( const Type
& listType
: aControlListeners
)
383 OUString sFullTypeName
= listType
.getTypeName();
384 const Sequence
< OUString
> sMeths
=
385 comphelper::getEventMethodsForType( listType
);
386 std::transform(sMeths
.begin(), sMeths
.end(), std::back_inserter(eventMethods
),
387 [&sFullTypeName
](const OUString
& rMeth
) -> OUString
{ return sFullTypeName
+ DELIM
+ rMeth
; });
390 return comphelper::containerToSequence(eventMethods
);
393 Sequence
< ScriptEventDescriptor
>
394 ScriptEventHelper::createEvents( const OUString
& sCodeName
)
396 const Sequence
< OUString
> aControlListeners
= getEventListeners();
397 sal_Int32 nLength
= aControlListeners
.getLength();
399 Sequence
< ScriptEventDescriptor
> aDest( nLength
);
401 for ( OUString
const & i
: aControlListeners
)
403 // from getListeners eventName is of form
404 // "com.sun.star.awt.XActionListener::actionPerformed"
405 // we need to strip "com.sun.star.awt." from that for form
407 ScriptEventDescriptor evtDesc
;
408 if ( eventMethodToDescriptor( i
, evtDesc
, sCodeName
) )
410 sal_Int32 dIndex
= nEvts
;
412 if ( nEvts
> aDest
.getLength() )
413 aDest
.realloc( nEvts
);// should never happen
414 aDest
.getArray()[ dIndex
] = std::move(evtDesc
);
417 aDest
.realloc( nEvts
);
423 typedef ::cppu::WeakImplHelper
< container::XNameContainer
> NameContainer_BASE
;
427 class ReadOnlyEventsNameContainer
: public NameContainer_BASE
430 ReadOnlyEventsNameContainer( const Sequence
< OUString
>& eventMethods
, const OUString
& sCodeName
);
433 virtual void SAL_CALL
insertByName( const OUString
&, const Any
& ) override
435 throw RuntimeException(u
"ReadOnly container"_ustr
);
438 virtual void SAL_CALL
removeByName( const OUString
& ) override
440 throw RuntimeException(u
"ReadOnly container"_ustr
);
444 virtual void SAL_CALL
replaceByName( const OUString
&, const Any
& ) override
446 throw RuntimeException(u
"ReadOnly container"_ustr
);
451 virtual Any SAL_CALL
getByName( const OUString
& aName
) override
;
452 virtual Sequence
< OUString
> SAL_CALL
getElementNames( ) override
;
453 virtual sal_Bool SAL_CALL
hasByName( const OUString
& aName
) override
;
456 virtual Type SAL_CALL
getElementType( ) override
457 { return cppu::UnoType
<OUString
>::get(); }
458 virtual sal_Bool SAL_CALL
hasElements( ) override
459 { return !m_hEvents
.empty(); }
462 typedef std::unordered_map
< OUString
, Any
> EventSupplierHash
;
464 EventSupplierHash m_hEvents
;
469 ReadOnlyEventsNameContainer::ReadOnlyEventsNameContainer( const Sequence
< OUString
>& eventMethods
, const OUString
& sCodeName
)
471 for ( const OUString
& rSrc
: eventMethods
)
474 ScriptEventDescriptor evtDesc
;
475 if ( eventMethodToDescriptor( rSrc
, evtDesc
, sCodeName
) )
478 m_hEvents
[ rSrc
] = std::move(aDesc
);
484 ReadOnlyEventsNameContainer::getByName( const OUString
& aName
){
485 EventSupplierHash::const_iterator it
= m_hEvents
.find( aName
);
486 if ( it
== m_hEvents
.end() )
487 throw container::NoSuchElementException();
491 Sequence
< OUString
> SAL_CALL
492 ReadOnlyEventsNameContainer::getElementNames( )
494 return comphelper::mapKeysToSequence(m_hEvents
);
498 ReadOnlyEventsNameContainer::hasByName( const OUString
& aName
)
500 EventSupplierHash::const_iterator it
= m_hEvents
.find( aName
);
501 if ( it
== m_hEvents
.end() )
508 class ReadOnlyEventsSupplier
: public ::cppu::WeakImplHelper
< XScriptEventsSupplier
>
511 ReadOnlyEventsSupplier( const Sequence
< OUString
>& eventMethods
, const OUString
& sCodeName
)
512 { m_xNameContainer
= new ReadOnlyEventsNameContainer( eventMethods
, sCodeName
); }
514 // XScriptEventSupplier
515 virtual Reference
< container::XNameContainer
> SAL_CALL
getEvents( ) override
{ return m_xNameContainer
; }
517 rtl::Reference
< ReadOnlyEventsNameContainer
> m_xNameContainer
;
522 typedef ::comphelper::WeakImplHelper
< XScriptListener
, util::XCloseListener
, lang::XInitialization
, css::lang::XServiceInfo
> EventListener_BASE
;
524 #define EVENTLSTNR_PROPERTY_ID_MODEL 1
525 constexpr OUStringLiteral EVENTLSTNR_PROPERTY_MODEL
= u
"Model";
529 class EventListener
: public EventListener_BASE
530 ,public ::comphelper::OPropertyContainer2
531 ,public ::comphelper::OPropertyArrayUsageHelper
< EventListener
>
537 virtual void SAL_CALL
disposing(const lang::EventObject
& Source
) override
;
538 using comphelper::OPropertySetHelper::disposing
;
541 virtual void SAL_CALL
firing(const ScriptEvent
& evt
) override
;
542 virtual Any SAL_CALL
approveFiring(const ScriptEvent
& evt
) override
;
544 virtual void SAL_CALL
queryClosing( const lang::EventObject
& Source
, sal_Bool GetsOwnership
) override
;
545 virtual void SAL_CALL
notifyClosing( const lang::EventObject
& Source
) override
;
547 virtual css::uno::Reference
< css::beans::XPropertySetInfo
> SAL_CALL
getPropertySetInfo( ) override
;
549 virtual void SAL_CALL
initialize( const Sequence
< Any
>& aArguments
) override
;
554 DECLARE_XTYPEPROVIDER()
555 virtual void setFastPropertyValueImpl( std::unique_lock
<std::mutex
>& rGuard
, sal_Int32 nHandle
, const css::uno::Any
& rValue
) override
557 if ( nHandle
== EVENTLSTNR_PROPERTY_ID_MODEL
)
559 uno::Reference
< frame::XModel
> xModel( rValue
, uno::UNO_QUERY
);
560 if( xModel
!= m_xModel
)
562 // Remove the listener from the old XCloseBroadcaster.
563 uno::Reference
< util::XCloseBroadcaster
> xCloseBroadcaster( m_xModel
, uno::UNO_QUERY
);
564 if (xCloseBroadcaster
.is())
566 xCloseBroadcaster
->removeCloseListener( this );
568 // Add the listener into the new XCloseBroadcaster.
569 xCloseBroadcaster
.set( xModel
, uno::UNO_QUERY
);
570 if (xCloseBroadcaster
.is())
572 xCloseBroadcaster
->addCloseListener( this );
576 OPropertyContainer2::setFastPropertyValueImpl( rGuard
, nHandle
, rValue
);
577 if ( nHandle
== EVENTLSTNR_PROPERTY_ID_MODEL
)
581 OUString SAL_CALL
getImplementationName() override
583 return u
"ooo.vba.EventListener"_ustr
;
586 sal_Bool SAL_CALL
supportsService(OUString
const & ServiceName
) override
588 return cppu::supportsService(this, ServiceName
);
591 css::uno::Sequence
<OUString
> SAL_CALL
getSupportedServiceNames() override
593 return { getImplementationName() };
597 // OPropertySetHelper
598 virtual ::cppu::IPropertyArrayHelper
& getInfoHelper( ) override
;
600 // OPropertyArrayUsageHelper
601 virtual ::cppu::IPropertyArrayHelper
* createArrayHelper( ) const override
;
604 void setShellFromModel();
605 /// @throws RuntimeException
606 void firing_Impl( const ScriptEvent
& evt
, Any
*pSyncRet
);
608 Reference
< frame::XModel
> m_xModel
;
610 SfxObjectShell
* mpShell
;
615 EventListener::EventListener() :
616 m_bDocClosed(false), mpShell( nullptr )
618 registerProperty( EVENTLSTNR_PROPERTY_MODEL
, EVENTLSTNR_PROPERTY_ID_MODEL
,
619 beans::PropertyAttribute::TRANSIENT
, &m_xModel
, cppu::UnoType
<decltype(m_xModel
)>::get() );
623 EventListener::setShellFromModel()
627 SfxObjectShell
* pShell
= SfxObjectShell::GetFirst();
628 while ( m_xModel
.is() && pShell
)
630 if ( pShell
->GetModel() == m_xModel
)
635 pShell
= SfxObjectShell::GetNext( *pShell
);
641 EventListener::disposing(const lang::EventObject
&)
648 EventListener::firing(const ScriptEvent
& evt
)
650 firing_Impl( evt
, nullptr );
654 EventListener::approveFiring(const ScriptEvent
& evt
)
657 firing_Impl( evt
, &ret
);
663 EventListener::queryClosing( const lang::EventObject
& /*Source*/, sal_Bool
/*GetsOwnership*/ )
669 EventListener::notifyClosing( const lang::EventObject
& /*Source*/ )
672 uno::Reference
< util::XCloseBroadcaster
> xCloseBroadcaster( m_xModel
, uno::UNO_QUERY
);
673 if (xCloseBroadcaster
.is())
675 xCloseBroadcaster
->removeCloseListener( this );
681 EventListener::initialize( const Sequence
< Any
>& aArguments
)
683 if ( aArguments
.getLength() == 1 )
684 aArguments
[0] >>= m_xModel
;
687 "args " << aArguments
.getLength() << " m_xModel " << m_xModel
.is());
692 IMPLEMENT_FORWARD_XINTERFACE2( EventListener
, EventListener_BASE
, comphelper::OPropertyContainer2
)
696 IMPLEMENT_FORWARD_XTYPEPROVIDER2( EventListener
, EventListener_BASE
, comphelper::OPropertyContainer2
)
698 // OPropertySetHelper
700 ::cppu::IPropertyArrayHelper
&
701 EventListener::getInfoHelper( )
703 return *getArrayHelper();
706 // OPropertyArrayUsageHelper
708 ::cppu::IPropertyArrayHelper
*
709 EventListener::createArrayHelper( ) const
711 Sequence
< beans::Property
> aProps
;
712 describeProperties( aProps
);
713 return new ::cppu::OPropertyArrayHelper( aProps
);
717 Reference
< beans::XPropertySetInfo
>
718 EventListener::getPropertySetInfo( )
720 Reference
< beans::XPropertySetInfo
> xInfo( createPropertySetInfo( getInfoHelper() ) );
725 //decide if the control should execute the event
726 bool ApproveAll(SAL_UNUSED_PARAMETER
const ScriptEvent
&, SAL_UNUSED_PARAMETER
void const * )
731 //for the given control type in evt.Arguments[0], look for if it appears in the type list in pPara
732 static bool FindControl(const ScriptEvent
& evt
, void const * pPara
)
734 lang::EventObject aEvent
;
735 evt
.Arguments
[ 0 ] >>= aEvent
;
736 uno::Reference
< uno::XInterface
> xInterface( aEvent
.Source
, uno::UNO_QUERY
);
738 TypeList
const * pTypeListInfo
= static_cast<TypeList
const *>(pPara
);
739 Type
const * pType
= pTypeListInfo
->pTypeList
;
740 int nLen
= pTypeListInfo
->nListLength
;
742 for (int i
= 0; i
< nLen
; i
++)
744 if ( xInterface
->queryInterface( *pType
).hasValue() )
754 //if the given control type in evt.Arguments[0] appears in the type list in pPara, then approve the execution
755 bool ApproveType(const ScriptEvent
& evt
, void const * pPara
)
757 return FindControl(evt
, pPara
);
760 //if the given control type in evt.Arguments[0] appears in the type list in pPara, then deny the execution
761 bool DenyType(const ScriptEvent
& evt
, void const * pPara
)
763 return !FindControl(evt
, pPara
);
766 //when mouse is moving, either the mouse button is pressed or some key is pressed can trigger the OO mouseDragged event,
767 //the former should be denied, and the latter allowed, only by doing so can the VBA MouseMove event when the "Shift" key is
768 //pressed can be correctly triggered
769 bool DenyMouseDrag(const ScriptEvent
& evt
, SAL_UNUSED_PARAMETER
void const * )
771 awt::MouseEvent aEvent
;
772 evt
.Arguments
[ 0 ] >>= aEvent
;
773 return aEvent
.Buttons
== 0;
780 EventListener::firing_Impl(const ScriptEvent
& evt
, Any
* pRet
)
782 // let default handlers deal with non vba stuff
783 if ( evt
.ScriptType
!= "VBAInterop" )
785 lang::EventObject aEvent
;
786 evt
.Arguments
[ 0 ] >>= aEvent
;
787 OUString sName
= u
"UserForm"_ustr
;
789 uno::Reference
< awt::XDialog
> xDlg( aEvent
.Source
, uno::UNO_QUERY
);
794 // b) xShapeControl ( from api (sheet control) )
795 // c) eventmanager ( I guess )
796 // d) vba control ( from api also )
797 uno::Reference
< drawing::XControlShape
> xCntrlShape( evt
.Source
, uno::UNO_QUERY
);
798 uno::Reference
< awt::XControl
> xControl( aEvent
.Source
, uno::UNO_QUERY
);
799 if ( xCntrlShape
.is() )
801 // for sheet controls ( that fire from the api ) we don't
802 // have the real control ( that's only available from the view )
803 // api code creates just a control instance that is transferred
804 // via aEvent.Arguments[ 0 ] that control though has no
805 // info like name etc.
806 uno::Reference
< container::XNamed
> xName( xCntrlShape
->getControl(), uno::UNO_QUERY_THROW
);
807 sName
= xName
->getName();
811 // Userform control ( fired from the api or from event manager )
812 uno::Reference
< beans::XPropertySet
> xProps
;
813 xProps
.set( xControl
->getModel(), uno::UNO_QUERY_THROW
);
814 xProps
->getPropertyValue(u
"Name"_ustr
) >>= sName
;
818 EventInfoHash
& infos
= getEventTransInfo();
819 EventInfoHash::const_iterator eventInfo_it
= infos
.find( evt
.MethodName
);
820 EventInfoHash::const_iterator it_end
= infos
.end();
821 if ( eventInfo_it
== it_end
)
823 SAL_WARN("scripting", "Bogus event for " << evt
.ScriptType
);
827 uno::Reference
< script::provider::XScriptProviderSupplier
> xSPS( m_xModel
, uno::UNO_QUERY
);
828 uno::Reference
< script::provider::XScriptProvider
> xScriptProvider
;
831 xScriptProvider
= xSPS
->getScriptProvider();
833 if ( !(xScriptProvider
.is() && mpShell
) )
836 BasicManager
* pBasicManager
= mpShell
->GetBasicManager();
838 OUString
sScriptCode( evt
.ScriptCode
);
839 // dialogs pass their own library, presence of Dot determines that
840 if ( sScriptCode
.indexOf( '.' ) == -1 )
842 //'Project' is a better default but I want to force failures
843 //OUString sMacroLoc("Project");
844 sProject
= "Standard";
846 if (!pBasicManager
->GetName().isEmpty())
848 sProject
= pBasicManager
->GetName();
853 sal_Int32 nIndex
= sScriptCode
.indexOf( '.' );
854 sProject
= sScriptCode
.copy( 0, nIndex
);
855 sScriptCode
= sScriptCode
.copy( nIndex
+ 1 );
857 OUString sMacroLoc
= sProject
+ "." + sScriptCode
+ ".";
859 for (const auto& rTxInfo
: eventInfo_it
->second
)
861 // If the document is closed, we should not execute macro.
867 // see if we have a match for the handlerextension
868 // where ScriptCode is methodname_handlerextension
869 OUString sToResolve
= sMacroLoc
+ sName
+ rTxInfo
.sVBAName
;
871 ooo::vba::MacroResolvedInfo aMacroResolvedInfo
= ooo::vba::resolveVBAMacro( mpShell
, sToResolve
);
872 if ( aMacroResolvedInfo
.mbFound
)
875 if (! rTxInfo
.ApproveRule(evt
, rTxInfo
.pPara
) )
880 // !! translate arguments & emulate events where necessary
881 Sequence
< Any
> aArguments
;
884 aArguments
= rTxInfo
.toVBA( evt
.Arguments
);
888 aArguments
= evt
.Arguments
;
890 if ( aArguments
.hasElements() )
892 // call basic event handlers for event
895 OUString url
= aMacroResolvedInfo
.msResolvedMacro
;
898 uno::Any
aDummyCaller( u
"Error"_ustr
);
901 ooo::vba::executeMacro( mpShell
, url
, aArguments
, *pRet
, aDummyCaller
);
906 ooo::vba::executeMacro( mpShell
, url
, aArguments
, aRet
, aDummyCaller
);
909 catch ( const uno::Exception
& )
911 TOOLS_WARN_EXCEPTION("scripting", "event script raised" );
920 class VBAToOOEventDescGen
: public ::cppu::WeakImplHelper
< XVBAToOOEventDescGen
, css::lang::XServiceInfo
>
923 VBAToOOEventDescGen();
925 // XVBAToOOEventDescGen
926 virtual Sequence
< ScriptEventDescriptor
> SAL_CALL
getEventDescriptions( const OUString
& sCtrlServiceName
, const OUString
& sCodeName
) override
;
927 virtual Reference
< XScriptEventsSupplier
> SAL_CALL
getEventSupplier( const Reference
< XInterface
>& xControl
, const OUString
& sCodeName
) override
;
929 OUString SAL_CALL
getImplementationName() override
931 return u
"ooo.vba.VBAToOOEventDesc"_ustr
;
934 sal_Bool SAL_CALL
supportsService(OUString
const & ServiceName
) override
936 return cppu::supportsService(this, ServiceName
);
939 css::uno::Sequence
<OUString
> SAL_CALL
getSupportedServiceNames() override
941 return { getImplementationName() };
948 VBAToOOEventDescGen::VBAToOOEventDescGen() {}
950 Sequence
< ScriptEventDescriptor
> SAL_CALL
951 VBAToOOEventDescGen::getEventDescriptions( const OUString
& sCntrlServiceName
, const OUString
& sCodeName
)
953 ScriptEventHelper
evntHelper( sCntrlServiceName
);
954 return evntHelper
.createEvents( sCodeName
);
957 Reference
< XScriptEventsSupplier
> SAL_CALL
958 VBAToOOEventDescGen::getEventSupplier( const Reference
< XInterface
>& xControl
, const OUString
& sCodeName
)
960 ScriptEventHelper
evntHelper( xControl
);
961 Reference
< XScriptEventsSupplier
> xSupplier
=
962 new ReadOnlyEventsSupplier(
963 evntHelper
.getEventListeners(), sCodeName
) ;
967 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
968 ooo_vba_EventListener_get_implementation(css::uno::XComponentContext
*,
969 css::uno::Sequence
<css::uno::Any
> const &)
971 return cppu::acquire(new EventListener
);
975 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
976 ooo_vba_VBAToOOEventDesc_get_implementation(css::uno::XComponentContext
*,
977 css::uno::Sequence
<css::uno::Any
> const &)
979 return cppu::acquire(new VBAToOOEventDescGen
);
983 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */