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/proparrhlp.hxx>
25 #include <comphelper/propertycontainer.hxx>
26 #include <comphelper/diagnose_ex.hxx>
28 #include <ooo/vba/XVBAToOOEventDescGen.hpp>
30 #include <com/sun/star/beans/XPropertySet.hpp>
31 #include <com/sun/star/beans/theIntrospection.hpp>
32 #include <com/sun/star/beans/PropertyAttribute.hpp>
34 #include <com/sun/star/lang/XMultiComponentFactory.hpp>
35 #include <com/sun/star/lang/XServiceInfo.hpp>
36 #include <com/sun/star/lang/XInitialization.hpp>
38 #include <com/sun/star/util/XCloseListener.hpp>
39 #include <com/sun/star/util/XCloseBroadcaster.hpp>
41 #include <com/sun/star/frame/XModel.hpp>
43 #include <com/sun/star/script/ScriptEventDescriptor.hpp>
44 #include <com/sun/star/script/provider/XScriptProviderSupplier.hpp>
46 #include <com/sun/star/container/XNamed.hpp>
48 #include <com/sun/star/drawing/XControlShape.hpp>
50 #include <com/sun/star/awt/XControl.hpp>
51 #include <com/sun/star/awt/XDialog.hpp>
52 #include <com/sun/star/awt/KeyEvent.hpp>
53 #include <com/sun/star/awt/MouseEvent.hpp>
54 #include <com/sun/star/awt/XFixedText.hpp>
55 #include <com/sun/star/awt/XTextComponent.hpp>
56 #include <com/sun/star/awt/XComboBox.hpp>
57 #include <com/sun/star/awt/XRadioButton.hpp>
58 #include <com/sun/star/awt/XListBox.hpp>
60 #include <sfx2/objsh.hxx>
61 #include <basic/basmgr.hxx>
62 #include <filter/msfilter/msvbahelper.hxx>
63 #include <vbahelper/vbareturntypes.hxx>
65 #include <com/sun/star/script/XScriptListener.hpp>
66 #include <cppuhelper/implbase.hxx>
67 #include <cppuhelper/supportsservice.hxx>
68 #include <comphelper/evtmethodhelper.hxx>
71 #include <unordered_map>
73 using namespace ::com::sun::star
;
74 using namespace ::com::sun::star::script
;
75 using namespace ::com::sun::star::uno
;
76 using namespace ::ooo::vba
;
79 constexpr std::u16string_view DELIM
= u
"::";
80 constexpr sal_Int32 DELIMLEN
= DELIM
.size();
82 static bool isKeyEventOk( awt::KeyEvent
& evt
, const Sequence
< Any
>& params
)
84 return params
.hasElements() && ( params
[ 0 ] >>= evt
);
87 static bool isMouseEventOk( awt::MouseEvent
& evt
, const Sequence
< Any
>& params
)
89 return params
.hasElements() && ( params
[ 0 ] >>= evt
);
92 static Sequence
< Any
> ooMouseEvtToVBADblClick( const Sequence
< Any
>& params
)
96 if ( !( isMouseEventOk(evt
, params
)) ||
97 (evt
.ClickCount
!= 2) )
98 return Sequence
< Any
>();
99 // give back orig params, this will signal that the event is good
103 static Sequence
< Any
> ooMouseEvtToVBAMouseEvt( const Sequence
< Any
>& params
)
107 if ( !isMouseEventOk(evt
, params
) )
108 return Sequence
< Any
>();
110 Sequence
< Any
> translatedParams
{ Any(evt
.Buttons
), // Buttons
111 Any(evt
.Modifiers
), // Shift
114 return translatedParams
;
117 static Sequence
< Any
> ooKeyPressedToVBAKeyPressed( const Sequence
< Any
>& params
)
121 if ( !isKeyEventOk( evt
, params
) )
122 return Sequence
< Any
>();
124 Reference
< msforms::XReturnInteger
> xKeyCode
= new ReturnInteger( sal_Int32( evt
.KeyCode
) );
125 Sequence
< Any
> translatedParams
{ Any(xKeyCode
) };
126 return translatedParams
;
129 static Sequence
< Any
> ooKeyPressedToVBAKeyUpDown( const Sequence
< Any
>& params
)
133 if ( !isKeyEventOk( evt
, params
) )
134 return Sequence
< Any
>();
136 Reference
< msforms::XReturnInteger
> xKeyCode
= new ReturnInteger( evt
.KeyCode
);
137 sal_Int8 shift
= sal::static_int_cast
<sal_Int8
>( evt
.Modifiers
);
139 // #TODO check whether values from OOO conform to values generated from vba
140 Sequence
< Any
> translatedParams
{ Any(xKeyCode
), Any(shift
) };
141 return translatedParams
;
144 typedef Sequence
< Any
> (*Translator
)(const Sequence
< Any
>&);
148 //expand the "TranslateInfo" struct to support more kinds of events
151 OUString sVBAName
; //vba event name
152 Translator toVBA
; //the method to convert OO event parameters to VBA event parameters
153 bool (*ApproveRule
)(const ScriptEvent
& evt
, void const * pPara
); //this method is used to determine which types of controls should execute the event
154 void const *pPara
; //Parameters for the above approve method
159 typedef std::unordered_map
<
161 std::vector
< TranslateInfo
> > EventInfoHash
;
165 struct TranslatePropMap
167 OUString sEventInfo
; //OO event name
168 TranslateInfo aTransInfo
;
173 static bool ApproveAll(const ScriptEvent
& evt
, void const * pPara
); //allow all types of controls to execute the event
174 static bool ApproveType(const ScriptEvent
& evt
, void const * pPara
); //certain types of controls should execute the event, those types are given by pPara
175 static bool DenyType(const ScriptEvent
& evt
, void const * pPara
); //certain types of controls should not execute the event, those types are given by pPara
176 static bool DenyMouseDrag(const ScriptEvent
& evt
, void const * pPara
); //used for VBA MouseMove event when "Shift" key is pressed
182 uno::Type
const * pTypeList
;
188 Type
const typeXFixedText
= cppu::UnoType
<awt::XFixedText
>::get();
189 Type
const typeXTextComponent
= cppu::UnoType
<awt::XTextComponent
>::get();
190 Type
const typeXComboBox
= cppu::UnoType
<awt::XComboBox
>::get();
191 Type
const typeXRadioButton
= cppu::UnoType
<awt::XRadioButton
>::get();
192 Type
const typeXListBox
= cppu::UnoType
<awt::XListBox
>::get();
195 TypeList
const fixedTextList
= {&typeXFixedText
, 1};
196 TypeList
const textCompList
= {&typeXTextComponent
, 1};
197 TypeList
const radioButtonList
= {&typeXRadioButton
, 1};
198 TypeList
const comboBoxList
= {&typeXComboBox
, 1};
199 TypeList
const listBoxList
= {&typeXListBox
, 1};
201 //this array stores the OO event to VBA event translation info
202 static TranslatePropMap aTranslatePropMap_Impl
[] =
204 { OUString("actionPerformed"), { OUString("_Change"), nullptr, DenyType
, static_cast<void const *>(&radioButtonList
) } },
205 // actionPerformed ooo event
206 { OUString("actionPerformed"), { OUString("_Click"), nullptr, ApproveAll
, nullptr } },
207 { OUString("itemStateChanged"), { OUString("_Change"), nullptr, ApproveType
, static_cast<void const *>(&radioButtonList
) } },
208 // itemStateChanged ooo event
209 { OUString("itemStateChanged"), { OUString("_Click"), nullptr, ApproveType
, static_cast<void const *>(&comboBoxList
) } },
211 { OUString("itemStateChanged"), { OUString("_Click"), nullptr, ApproveType
, static_cast<void const *>(&listBoxList
) } },
213 { OUString("changed"), { OUString("_Change"), nullptr, ApproveAll
, nullptr } },
215 // focusGained ooo event
216 { OUString("focusGained"), { OUString("_GotFocus"), nullptr, ApproveAll
, nullptr } },
218 // focusLost ooo event
219 { OUString("focusLost"), { OUString("_LostFocus"), nullptr, ApproveAll
, nullptr } },
220 { OUString("focusLost"), { OUString("_Exit"), nullptr, ApproveType
, static_cast<void const *>(&textCompList
) } }, // support VBA TextBox_Exit event
222 // adjustmentValueChanged ooo event
223 { OUString("adjustmentValueChanged"), { OUString("_Scroll"), nullptr, ApproveAll
, nullptr } },
224 { OUString("adjustmentValueChanged"), { OUString("_Change"), nullptr, ApproveAll
, nullptr } },
226 // textChanged ooo event
227 { OUString("textChanged"), { OUString("_Change"), nullptr, ApproveAll
, nullptr } },
229 // keyReleased ooo event
230 { OUString("keyReleased"), { OUString("_KeyUp"), ooKeyPressedToVBAKeyUpDown
, ApproveAll
, nullptr } },
232 // mouseReleased ooo event
233 { OUString("mouseReleased"), { OUString("_Click"), ooMouseEvtToVBAMouseEvt
, ApproveType
, static_cast<void const *>(&fixedTextList
) } },
234 { OUString("mouseReleased"), { OUString("_MouseUp"), ooMouseEvtToVBAMouseEvt
, ApproveAll
, nullptr } },
236 // mousePressed ooo event
237 { OUString("mousePressed"), { OUString("_MouseDown"), ooMouseEvtToVBAMouseEvt
, ApproveAll
, nullptr } },
238 { OUString("mousePressed"), { OUString("_DblClick"), ooMouseEvtToVBADblClick
, ApproveAll
, nullptr } },
240 // mouseMoved ooo event
241 { OUString("mouseMoved"), { OUString("_MouseMove"), ooMouseEvtToVBAMouseEvt
, ApproveAll
, nullptr } },
242 { OUString("mouseDragged"), { OUString("_MouseMove"), ooMouseEvtToVBAMouseEvt
, DenyMouseDrag
, nullptr } },
244 // keyPressed ooo event
245 { OUString("keyPressed"), { OUString("_KeyDown"), ooKeyPressedToVBAKeyUpDown
, ApproveAll
, nullptr } },
246 { OUString("keyPressed"), { OUString("_KeyPress"), ooKeyPressedToVBAKeyPressed
, ApproveAll
, nullptr } }
249 static EventInfoHash
& getEventTransInfo()
251 static EventInfoHash eventTransInfo
= []()
255 TranslatePropMap
* pTransProp
= aTranslatePropMap_Impl
;
256 int nCount
= SAL_N_ELEMENTS(aTranslatePropMap_Impl
);
261 sEventInfo
= pTransProp
->sEventInfo
;
262 std::vector
< TranslateInfo
> infoList
;
265 infoList
.push_back( pTransProp
->aTransInfo
);
268 }while(i
< nCount
&& sEventInfo
== pTransProp
->sEventInfo
);
269 tmp
[sEventInfo
] = std::move(infoList
);
273 return eventTransInfo
;
281 class ScriptEventHelper
284 explicit ScriptEventHelper( const Reference
< XInterface
>& xControl
);
285 explicit ScriptEventHelper( const OUString
& sCntrlServiceName
);
286 ~ScriptEventHelper();
287 Sequence
< ScriptEventDescriptor
> createEvents( const OUString
& sCodeName
);
288 Sequence
< OUString
> getEventListeners() const;
290 Reference
< XComponentContext
> m_xCtx
;
291 Reference
< XInterface
> m_xControl
;
298 eventMethodToDescriptor( std::u16string_view rEventMethod
, ScriptEventDescriptor
& evtDesc
, const OUString
& sCodeName
)
300 // format of ControlListener is TypeName::methodname e.g.
301 // "com.sun.star.awt.XActionListener::actionPerformed" or
302 // "XActionListener::actionPerformed
304 OUString sMethodName
;
306 size_t nDelimPos
= rEventMethod
.find( DELIM
);
307 if ( nDelimPos
== std::u16string_view::npos
)
311 sMethodName
= rEventMethod
.substr( nDelimPos
+ DELIMLEN
);
312 sTypeName
= rEventMethod
.substr( 0, nDelimPos
);
314 EventInfoHash
& infos
= getEventTransInfo();
316 // Only create an ScriptEventDescriptor for an event we can translate
318 if ( !sMethodName
.isEmpty()
319 && !sTypeName
.isEmpty()
320 && ( infos
.find( sMethodName
) != infos
.end() ) )
322 // just fill in CodeName, when the event fires the other
323 // info is gathered from the event source to determine what
324 // event handler we try to call
325 evtDesc
.ScriptCode
= sCodeName
;
326 evtDesc
.ListenerType
= sTypeName
;
327 evtDesc
.EventMethod
= sMethodName
;
329 // set this it VBAInterop, ensures that it doesn't
330 // get persisted or shown in property editors
331 evtDesc
.ScriptType
= "VBAInterop";
338 ScriptEventHelper::ScriptEventHelper( const Reference
< XInterface
>& xControl
) :
339 m_xCtx( comphelper::getProcessComponentContext() ),
340 m_xControl( xControl
),
344 ScriptEventHelper::ScriptEventHelper( const OUString
& sCntrlServiceName
) :
345 m_xCtx( comphelper::getProcessComponentContext() ),
348 m_xControl
.set( m_xCtx
->getServiceManager()->createInstanceWithContext( sCntrlServiceName
, m_xCtx
), uno::UNO_QUERY
);
351 ScriptEventHelper::~ScriptEventHelper()
353 // dispose control ( and remove any associated event registrations )
358 uno::Reference
< lang::XComponent
> xComp( m_xControl
, uno::UNO_QUERY_THROW
);
361 // destructor can't throw
362 catch( uno::Exception
& )
369 ScriptEventHelper::getEventListeners() const
371 std::vector
< OUString
> eventMethods
;
373 Reference
< beans::XIntrospection
> xIntrospection
= beans::theIntrospection::get( m_xCtx
);
375 Reference
< beans::XIntrospectionAccess
> xIntrospectionAccess
=
376 xIntrospection
->inspect( Any( m_xControl
) );
377 const Sequence
< Type
> aControlListeners
=
378 xIntrospectionAccess
->getSupportedListeners();
379 for ( const Type
& listType
: aControlListeners
)
381 OUString sFullTypeName
= listType
.getTypeName();
382 const Sequence
< OUString
> sMeths
=
383 comphelper::getEventMethodsForType( listType
);
384 std::transform(sMeths
.begin(), sMeths
.end(), std::back_inserter(eventMethods
),
385 [&sFullTypeName
](const OUString
& rMeth
) -> OUString
{ return sFullTypeName
+ DELIM
+ rMeth
; });
388 return comphelper::containerToSequence(eventMethods
);
391 Sequence
< ScriptEventDescriptor
>
392 ScriptEventHelper::createEvents( const OUString
& sCodeName
)
394 const Sequence
< OUString
> aControlListeners
= getEventListeners();
395 sal_Int32 nLength
= aControlListeners
.getLength();
397 Sequence
< ScriptEventDescriptor
> aDest( nLength
);
399 for ( OUString
const & i
: aControlListeners
)
401 // from getListeners eventName is of form
402 // "com.sun.star.awt.XActionListener::actionPerformed"
403 // we need to strip "com.sun.star.awt." from that for form
405 ScriptEventDescriptor evtDesc
;
406 if ( eventMethodToDescriptor( i
, evtDesc
, sCodeName
) )
408 sal_Int32 dIndex
= nEvts
;
410 if ( nEvts
> aDest
.getLength() )
411 aDest
.realloc( nEvts
);// should never happen
412 aDest
.getArray()[ dIndex
] = evtDesc
;
415 aDest
.realloc( nEvts
);
421 typedef ::cppu::WeakImplHelper
< container::XNameContainer
> NameContainer_BASE
;
425 class ReadOnlyEventsNameContainer
: public NameContainer_BASE
428 ReadOnlyEventsNameContainer( const Sequence
< OUString
>& eventMethods
, const OUString
& sCodeName
);
431 virtual void SAL_CALL
insertByName( const OUString
&, const Any
& ) override
433 throw RuntimeException("ReadOnly container" );
436 virtual void SAL_CALL
removeByName( const OUString
& ) override
438 throw RuntimeException("ReadOnly container" );
442 virtual void SAL_CALL
replaceByName( const OUString
&, const Any
& ) override
444 throw RuntimeException("ReadOnly container" );
449 virtual Any SAL_CALL
getByName( const OUString
& aName
) override
;
450 virtual Sequence
< OUString
> SAL_CALL
getElementNames( ) override
;
451 virtual sal_Bool SAL_CALL
hasByName( const OUString
& aName
) override
;
454 virtual Type SAL_CALL
getElementType( ) override
455 { return cppu::UnoType
<OUString
>::get(); }
456 virtual sal_Bool SAL_CALL
hasElements( ) override
457 { return !m_hEvents
.empty(); }
460 typedef std::unordered_map
< OUString
, Any
> EventSupplierHash
;
462 EventSupplierHash m_hEvents
;
467 ReadOnlyEventsNameContainer::ReadOnlyEventsNameContainer( const Sequence
< OUString
>& eventMethods
, const OUString
& sCodeName
)
469 for ( const OUString
& rSrc
: eventMethods
)
472 ScriptEventDescriptor evtDesc
;
473 if ( eventMethodToDescriptor( rSrc
, evtDesc
, sCodeName
) )
476 m_hEvents
[ rSrc
] = aDesc
;
482 ReadOnlyEventsNameContainer::getByName( const OUString
& aName
){
483 EventSupplierHash::const_iterator it
= m_hEvents
.find( aName
);
484 if ( it
== m_hEvents
.end() )
485 throw container::NoSuchElementException();
489 Sequence
< OUString
> SAL_CALL
490 ReadOnlyEventsNameContainer::getElementNames( )
492 return comphelper::mapKeysToSequence(m_hEvents
);
496 ReadOnlyEventsNameContainer::hasByName( const OUString
& aName
)
498 EventSupplierHash::const_iterator it
= m_hEvents
.find( aName
);
499 if ( it
== m_hEvents
.end() )
506 class ReadOnlyEventsSupplier
: public ::cppu::WeakImplHelper
< XScriptEventsSupplier
>
509 ReadOnlyEventsSupplier( const Sequence
< OUString
>& eventMethods
, const OUString
& sCodeName
)
510 { m_xNameContainer
= new ReadOnlyEventsNameContainer( eventMethods
, sCodeName
); }
512 // XScriptEventSupplier
513 virtual Reference
< container::XNameContainer
> SAL_CALL
getEvents( ) override
{ return m_xNameContainer
; }
515 Reference
< container::XNameContainer
> m_xNameContainer
;
520 typedef ::cppu::WeakImplHelper
< XScriptListener
, util::XCloseListener
, lang::XInitialization
, css::lang::XServiceInfo
> EventListener_BASE
;
522 #define EVENTLSTNR_PROPERTY_ID_MODEL 1
523 constexpr OUStringLiteral EVENTLSTNR_PROPERTY_MODEL
= u
"Model";
527 class EventListener
: public EventListener_BASE
528 ,public ::comphelper::OMutexAndBroadcastHelper
529 ,public ::comphelper::OPropertyContainer
530 ,public ::comphelper::OPropertyArrayUsageHelper
< EventListener
>
536 virtual void SAL_CALL
disposing(const lang::EventObject
& Source
) override
;
537 using cppu::OPropertySetHelper::disposing
;
540 virtual void SAL_CALL
firing(const ScriptEvent
& evt
) override
;
541 virtual Any SAL_CALL
approveFiring(const ScriptEvent
& evt
) override
;
543 virtual void SAL_CALL
queryClosing( const lang::EventObject
& Source
, sal_Bool GetsOwnership
) override
;
544 virtual void SAL_CALL
notifyClosing( const lang::EventObject
& Source
) override
;
546 virtual css::uno::Reference
< css::beans::XPropertySetInfo
> SAL_CALL
getPropertySetInfo( ) override
;
548 virtual void SAL_CALL
initialize( const Sequence
< Any
>& aArguments
) override
;
553 DECLARE_XTYPEPROVIDER()
554 virtual void SAL_CALL
setFastPropertyValue( sal_Int32 nHandle
, const css::uno::Any
& rValue
) override
556 if ( nHandle
== EVENTLSTNR_PROPERTY_ID_MODEL
)
558 uno::Reference
< frame::XModel
> xModel( rValue
, uno::UNO_QUERY
);
559 if( xModel
!= m_xModel
)
561 // Remove the listener from the old XCloseBroadcaster.
562 uno::Reference
< util::XCloseBroadcaster
> xCloseBroadcaster( m_xModel
, uno::UNO_QUERY
);
563 if (xCloseBroadcaster
.is())
565 xCloseBroadcaster
->removeCloseListener( this );
567 // Add the listener into the new XCloseBroadcaster.
568 xCloseBroadcaster
.set( xModel
, uno::UNO_QUERY
);
569 if (xCloseBroadcaster
.is())
571 xCloseBroadcaster
->addCloseListener( this );
575 OPropertyContainer::setFastPropertyValue( nHandle
, rValue
);
576 if ( nHandle
== EVENTLSTNR_PROPERTY_ID_MODEL
)
580 OUString SAL_CALL
getImplementationName() override
582 return "ooo.vba.EventListener";
585 sal_Bool SAL_CALL
supportsService(OUString
const & ServiceName
) override
587 return cppu::supportsService(this, ServiceName
);
590 css::uno::Sequence
<OUString
> SAL_CALL
getSupportedServiceNames() override
592 return { getImplementationName() };
596 // OPropertySetHelper
597 virtual ::cppu::IPropertyArrayHelper
& SAL_CALL
getInfoHelper( ) override
;
599 // OPropertyArrayUsageHelper
600 virtual ::cppu::IPropertyArrayHelper
* createArrayHelper( ) const override
;
603 void setShellFromModel();
604 /// @throws RuntimeException
605 void firing_Impl( const ScriptEvent
& evt
, Any
*pSyncRet
);
607 Reference
< frame::XModel
> m_xModel
;
609 SfxObjectShell
* mpShell
;
614 EventListener::EventListener() :
615 OPropertyContainer(GetBroadcastHelper()), m_bDocClosed(false), mpShell( nullptr )
617 registerProperty( EVENTLSTNR_PROPERTY_MODEL
, EVENTLSTNR_PROPERTY_ID_MODEL
,
618 beans::PropertyAttribute::TRANSIENT
, &m_xModel
, cppu::UnoType
<decltype(m_xModel
)>::get() );
622 EventListener::setShellFromModel()
626 SfxObjectShell
* pShell
= SfxObjectShell::GetFirst();
627 while ( m_xModel
.is() && pShell
)
629 if ( pShell
->GetModel() == m_xModel
)
634 pShell
= SfxObjectShell::GetNext( *pShell
);
640 EventListener::disposing(const lang::EventObject
&)
647 EventListener::firing(const ScriptEvent
& evt
)
649 firing_Impl( evt
, nullptr );
653 EventListener::approveFiring(const ScriptEvent
& evt
)
656 firing_Impl( evt
, &ret
);
662 EventListener::queryClosing( const lang::EventObject
& /*Source*/, sal_Bool
/*GetsOwnership*/ )
668 EventListener::notifyClosing( const lang::EventObject
& /*Source*/ )
671 uno::Reference
< util::XCloseBroadcaster
> xCloseBroadcaster( m_xModel
, uno::UNO_QUERY
);
672 if (xCloseBroadcaster
.is())
674 xCloseBroadcaster
->removeCloseListener( this );
680 EventListener::initialize( const Sequence
< Any
>& aArguments
)
682 if ( aArguments
.getLength() == 1 )
683 aArguments
[0] >>= m_xModel
;
686 "args " << aArguments
.getLength() << " m_xModel " << m_xModel
.is());
691 IMPLEMENT_FORWARD_XINTERFACE2( EventListener
, EventListener_BASE
, OPropertyContainer
)
695 IMPLEMENT_FORWARD_XTYPEPROVIDER2( EventListener
, EventListener_BASE
, OPropertyContainer
)
697 // OPropertySetHelper
699 ::cppu::IPropertyArrayHelper
&
700 EventListener::getInfoHelper( )
702 return *getArrayHelper();
705 // OPropertyArrayUsageHelper
707 ::cppu::IPropertyArrayHelper
*
708 EventListener::createArrayHelper( ) const
710 Sequence
< beans::Property
> aProps
;
711 describeProperties( aProps
);
712 return new ::cppu::OPropertyArrayHelper( aProps
);
716 Reference
< beans::XPropertySetInfo
>
717 EventListener::getPropertySetInfo( )
719 Reference
< beans::XPropertySetInfo
> xInfo( createPropertySetInfo( getInfoHelper() ) );
724 //decide if the control should execute the event
725 bool ApproveAll(SAL_UNUSED_PARAMETER
const ScriptEvent
&, SAL_UNUSED_PARAMETER
void const * )
730 //for the given control type in evt.Arguments[0], look for if it appears in the type list in pPara
731 static bool FindControl(const ScriptEvent
& evt
, void const * pPara
)
733 lang::EventObject aEvent
;
734 evt
.Arguments
[ 0 ] >>= aEvent
;
735 uno::Reference
< uno::XInterface
> xInterface( aEvent
.Source
, uno::UNO_QUERY
);
737 TypeList
const * pTypeListInfo
= static_cast<TypeList
const *>(pPara
);
738 Type
const * pType
= pTypeListInfo
->pTypeList
;
739 int nLen
= pTypeListInfo
->nListLength
;
741 for (int i
= 0; i
< nLen
; i
++)
743 if ( xInterface
->queryInterface( *pType
).hasValue() )
753 //if the given control type in evt.Arguments[0] appears in the type list in pPara, then approve the execution
754 bool ApproveType(const ScriptEvent
& evt
, void const * pPara
)
756 return FindControl(evt
, pPara
);
759 //if the given control type in evt.Arguments[0] appears in the type list in pPara, then deny the execution
760 bool DenyType(const ScriptEvent
& evt
, void const * pPara
)
762 return !FindControl(evt
, pPara
);
765 //when mouse is moving, either the mouse button is pressed or some key is pressed can trigger the OO mouseDragged event,
766 //the former should be denied, and the latter allowed, only by doing so can the VBA MouseMove event when the "Shift" key is
767 //pressed can be correctly triggered
768 bool DenyMouseDrag(const ScriptEvent
& evt
, SAL_UNUSED_PARAMETER
void const * )
770 awt::MouseEvent aEvent
;
771 evt
.Arguments
[ 0 ] >>= aEvent
;
772 return aEvent
.Buttons
== 0;
779 EventListener::firing_Impl(const ScriptEvent
& evt
, Any
* pRet
)
781 // let default handlers deal with non vba stuff
782 if ( evt
.ScriptType
!= "VBAInterop" )
784 lang::EventObject aEvent
;
785 evt
.Arguments
[ 0 ] >>= aEvent
;
786 OUString sName
= "UserForm";
788 uno::Reference
< awt::XDialog
> xDlg( aEvent
.Source
, uno::UNO_QUERY
);
793 // b) xShapeControl ( from api (sheet control) )
794 // c) eventmanager ( I guess )
795 // d) vba control ( from api also )
796 uno::Reference
< drawing::XControlShape
> xCntrlShape( evt
.Source
, uno::UNO_QUERY
);
797 uno::Reference
< awt::XControl
> xControl( aEvent
.Source
, uno::UNO_QUERY
);
798 if ( xCntrlShape
.is() )
800 // for sheet controls ( that fire from the api ) we don't
801 // have the real control ( that's only available from the view )
802 // api code creates just a control instance that is transferred
803 // via aEvent.Arguments[ 0 ] that control though has no
804 // info like name etc.
805 uno::Reference
< container::XNamed
> xName( xCntrlShape
->getControl(), uno::UNO_QUERY_THROW
);
806 sName
= xName
->getName();
810 // Userform control ( fired from the api or from event manager )
811 uno::Reference
< beans::XPropertySet
> xProps
;
812 xProps
.set( xControl
->getModel(), uno::UNO_QUERY_THROW
);
813 xProps
->getPropertyValue("Name") >>= sName
;
817 EventInfoHash
& infos
= getEventTransInfo();
818 EventInfoHash::const_iterator eventInfo_it
= infos
.find( evt
.MethodName
);
819 EventInfoHash::const_iterator it_end
= infos
.end();
820 if ( eventInfo_it
== it_end
)
822 SAL_WARN("scripting", "Bogus event for " << evt
.ScriptType
);
826 uno::Reference
< script::provider::XScriptProviderSupplier
> xSPS( m_xModel
, uno::UNO_QUERY
);
827 uno::Reference
< script::provider::XScriptProvider
> xScriptProvider
;
830 xScriptProvider
= xSPS
->getScriptProvider();
832 if ( !(xScriptProvider
.is() && mpShell
) )
835 BasicManager
* pBasicManager
= mpShell
->GetBasicManager();
837 OUString
sScriptCode( evt
.ScriptCode
);
838 // dialogs pass their own library, presence of Dot determines that
839 if ( sScriptCode
.indexOf( '.' ) == -1 )
841 //'Project' is a better default but I want to force failures
842 //OUString sMacroLoc("Project");
843 sProject
= "Standard";
845 if (!pBasicManager
->GetName().isEmpty())
847 sProject
= pBasicManager
->GetName();
852 sal_Int32 nIndex
= sScriptCode
.indexOf( '.' );
853 sProject
= sScriptCode
.copy( 0, nIndex
);
854 sScriptCode
= sScriptCode
.copy( nIndex
+ 1 );
856 OUString sMacroLoc
= sProject
+ "." + sScriptCode
+ ".";
858 for (const auto& rTxInfo
: eventInfo_it
->second
)
860 // If the document is closed, we should not execute macro.
866 // see if we have a match for the handlerextension
867 // where ScriptCode is methodname_handlerextension
868 OUString sToResolve
= sMacroLoc
+ sName
+ rTxInfo
.sVBAName
;
870 ooo::vba::MacroResolvedInfo aMacroResolvedInfo
= ooo::vba::resolveVBAMacro( mpShell
, sToResolve
);
871 if ( aMacroResolvedInfo
.mbFound
)
874 if (! rTxInfo
.ApproveRule(evt
, rTxInfo
.pPara
) )
879 // !! translate arguments & emulate events where necessary
880 Sequence
< Any
> aArguments
;
883 aArguments
= rTxInfo
.toVBA( evt
.Arguments
);
887 aArguments
= evt
.Arguments
;
889 if ( aArguments
.hasElements() )
891 // call basic event handlers for event
894 OUString url
= aMacroResolvedInfo
.msResolvedMacro
;
897 uno::Any
aDummyCaller( OUString("Error") );
900 ooo::vba::executeMacro( mpShell
, url
, aArguments
, *pRet
, aDummyCaller
);
905 ooo::vba::executeMacro( mpShell
, url
, aArguments
, aRet
, aDummyCaller
);
908 catch ( const uno::Exception
& )
910 TOOLS_WARN_EXCEPTION("scripting", "event script raised" );
919 class VBAToOOEventDescGen
: public ::cppu::WeakImplHelper
< XVBAToOOEventDescGen
, css::lang::XServiceInfo
>
922 VBAToOOEventDescGen();
924 // XVBAToOOEventDescGen
925 virtual Sequence
< ScriptEventDescriptor
> SAL_CALL
getEventDescriptions( const OUString
& sCtrlServiceName
, const OUString
& sCodeName
) override
;
926 virtual Reference
< XScriptEventsSupplier
> SAL_CALL
getEventSupplier( const Reference
< XInterface
>& xControl
, const OUString
& sCodeName
) override
;
928 OUString SAL_CALL
getImplementationName() override
930 return "ooo.vba.VBAToOOEventDesc";
933 sal_Bool SAL_CALL
supportsService(OUString
const & ServiceName
) override
935 return cppu::supportsService(this, ServiceName
);
938 css::uno::Sequence
<OUString
> SAL_CALL
getSupportedServiceNames() override
940 return { getImplementationName() };
947 VBAToOOEventDescGen::VBAToOOEventDescGen() {}
949 Sequence
< ScriptEventDescriptor
> SAL_CALL
950 VBAToOOEventDescGen::getEventDescriptions( const OUString
& sCntrlServiceName
, const OUString
& sCodeName
)
952 ScriptEventHelper
evntHelper( sCntrlServiceName
);
953 return evntHelper
.createEvents( sCodeName
);
956 Reference
< XScriptEventsSupplier
> SAL_CALL
957 VBAToOOEventDescGen::getEventSupplier( const Reference
< XInterface
>& xControl
, const OUString
& sCodeName
)
959 ScriptEventHelper
evntHelper( xControl
);
960 Reference
< XScriptEventsSupplier
> xSupplier
=
961 new ReadOnlyEventsSupplier(
962 evntHelper
.getEventListeners(), sCodeName
) ;
966 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
967 ooo_vba_EventListener_get_implementation(css::uno::XComponentContext
*,
968 css::uno::Sequence
<css::uno::Any
> const &)
970 return cppu::acquire(new EventListener
);
974 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
975 ooo_vba_VBAToOOEventDesc_get_implementation(css::uno::XComponentContext
*,
976 css::uno::Sequence
<css::uno::Any
> const &)
978 return cppu::acquire(new VBAToOOEventDescGen
);
982 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */