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 <comphelper/processfactory.hxx>
22 #include <comphelper/uno3.hxx>
23 #include <comphelper/proparrhlp.hxx>
24 #include <comphelper/propertycontainer.hxx>
26 #include <ooo/vba/XVBAToOOEventDescGen.hpp>
28 #include <com/sun/star/beans/XPropertySet.hpp>
29 #include <com/sun/star/beans/Introspection.hpp>
30 #include <com/sun/star/beans/PropertyAttribute.hpp>
32 #include <com/sun/star/lang/XMultiComponentFactory.hpp>
33 #include <com/sun/star/lang/XServiceName.hpp>
34 #include <com/sun/star/lang/XServiceInfo.hpp>
35 #include <com/sun/star/lang/XInitialization.hpp>
37 #include <com/sun/star/util/XCloseListener.hpp>
38 #include <com/sun/star/util/XCloseBroadcaster.hpp>
40 #include <com/sun/star/frame/XModel.hpp>
42 #include <com/sun/star/script/XLibraryContainer.hpp>
43 #include <com/sun/star/script/ScriptEventDescriptor.hpp>
44 #include <com/sun/star/script/provider/XScriptProviderSupplier.hpp>
45 #include <com/sun/star/script/vba/XVBACompatibility.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/sbstar.hxx>
63 #include <basic/basmgr.hxx>
64 #include <basic/sbmeth.hxx>
65 #include <basic/sbmod.hxx>
66 #include <basic/sbx.hxx>
67 #include <filter/msfilter/msvbahelper.hxx>
68 #include <vbahelper/vbareturntypes.hxx>
71 #include <comphelper/anytostring.hxx>
73 #include <com/sun/star/script/XScriptListener.hpp>
74 #include <cppuhelper/implbase1.hxx>
75 #include <cppuhelper/implbase3.hxx>
76 #include <cppuhelper/implbase2.hxx>
77 #include <comphelper/evtmethodhelper.hxx>
81 #include <boost/unordered_map.hpp>
84 // primitive support for asynchronous handling of
85 // events from controls ( all event will be processed asynchronously
86 // in the application thread )
88 #include <vcl/svapp.hxx>
91 using namespace ::com::sun::star
;
92 using namespace ::com::sun::star::script
;
93 using namespace ::com::sun::star::uno
;
94 using namespace ::ooo::vba
;
96 #define MAP_CHAR_LEN(x) OUString(x)
97 #define GET_TYPE(x) ::getCppuType((uno::Reference< x > *)0);
100 const static OUString
DELIM("::");
101 const static sal_Int32 DELIMLEN
= DELIM
.getLength();
103 bool isKeyEventOk( awt::KeyEvent
& evt
, const Sequence
< Any
>& params
)
105 if ( !( params
.getLength() > 0 ) ||
106 !( params
[ 0 ] >>= evt
) )
111 bool isMouseEventOk( awt::MouseEvent
& evt
, const Sequence
< Any
>& params
)
113 if ( !( params
.getLength() > 0 ) ||
114 !( params
[ 0 ] >>= evt
) )
119 Sequence
< Any
> ooMouseEvtToVBADblClick( const Sequence
< Any
>& params
)
121 Sequence
< Any
> translatedParams
;
124 if ( !( isMouseEventOk(evt
, params
)) ||
125 (evt
.ClickCount
!= 2) )
126 return Sequence
< Any
>();
127 // give back orig params, this will signal that the event is good
131 Sequence
< Any
> ooMouseEvtToVBAMouseEvt( const Sequence
< Any
>& params
)
133 Sequence
< Any
> translatedParams
;
136 if ( !isMouseEventOk(evt
, params
) )
137 return Sequence
< Any
>();
139 translatedParams
.realloc(4);
142 translatedParams
[ 0 ] <<= evt
.Buttons
;
144 translatedParams
[ 1 ] <<= evt
.Modifiers
;
146 translatedParams
[ 2 ] <<= evt
.X
;
148 translatedParams
[ 3 ] <<= evt
.Y
;
149 return translatedParams
;
152 Sequence
< Any
> ooKeyPressedToVBAKeyPressed( const Sequence
< Any
>& params
)
154 Sequence
< Any
> translatedParams
;
157 if ( !isKeyEventOk( evt
, params
) )
158 return Sequence
< Any
>();
160 translatedParams
.realloc(1);
162 Reference
< msforms::XReturnInteger
> xKeyCode
= new ReturnInteger( sal_Int32( evt
.KeyCode
) );
163 translatedParams
[0] <<= xKeyCode
;
164 return translatedParams
;
167 Sequence
< Any
> ooKeyPressedToVBAKeyUpDown( const Sequence
< Any
>& params
)
169 Sequence
< Any
> translatedParams
;
172 if ( !isKeyEventOk( evt
, params
) )
173 return Sequence
< Any
>();
175 translatedParams
.realloc(2);
177 Reference
< msforms::XReturnInteger
> xKeyCode
= new ReturnInteger( evt
.KeyCode
);
178 sal_Int8 shift
= sal::static_int_cast
<sal_Int8
>( evt
.Modifiers
);
180 // #TODO check whether values from OOO conform to values generated from vba
181 translatedParams
[0] <<= xKeyCode
;
182 translatedParams
[1] <<= shift
;
183 return translatedParams
;
186 typedef Sequence
< Any
> (*Translator
)(const Sequence
< Any
>&);
188 //expand the "TranslateInfo" struct to support more kinds of events
191 OUString sVBAName
; //vba event name
192 Translator toVBA
; //the method to convert OO event parameters to VBA event parameters
193 bool (*ApproveRule
)(const ScriptEvent
& evt
, void* pPara
); //this method is used to determine which types of controls should execute the event
194 void *pPara
; //Parameters for the above approve method
198 typedef boost::unordered_map
< OUString
,
199 std::list
< TranslateInfo
>,
201 ::std::equal_to
< OUString
> > EventInfoHash
;
204 struct TranslatePropMap
206 OUString sEventInfo
; //OO event name
207 TranslateInfo aTransInfo
;
210 bool ApproveAll(const ScriptEvent
& evt
, void* pPara
); //allow all types of controls to execute the event
211 bool ApproveType(const ScriptEvent
& evt
, void* pPara
); //certain types of controls should execute the event, those types are given by pPara
212 bool DenyType(const ScriptEvent
& evt
, void* pPara
); //certain types of controls should not execute the event, those types are given by pPara
213 bool DenyMouseDrag(const ScriptEvent
& evt
, void* pPara
); //used for VBA MouseMove event when "Shift" key is pressed
217 uno::Type
* pTypeList
;
221 Type typeXFixedText
= GET_TYPE(awt::XFixedText
);
222 Type typeXTextComponent
= GET_TYPE(awt::XTextComponent
);
223 Type typeXComboBox
= GET_TYPE(awt::XComboBox
);
224 Type typeXRadioButton
= GET_TYPE(awt::XRadioButton
);
225 Type typeXListBox
= GET_TYPE(awt::XListBox
);
228 TypeList fixedTextList
= {&typeXFixedText
, 1};
229 TypeList textCompList
= {&typeXTextComponent
, 1};
230 TypeList radioButtonList
= {&typeXRadioButton
, 1};
231 TypeList comboBoxList
= {&typeXComboBox
, 1};
232 TypeList listBoxList
= {&typeXListBox
, 1};
234 //this array stores the OO event to VBA event translation info
235 static TranslatePropMap aTranslatePropMap_Impl
[] =
237 { MAP_CHAR_LEN("actionPerformed"), { MAP_CHAR_LEN("_Change"), NULL
, DenyType
, (void*)(&radioButtonList
) } },
238 // actionPerformed ooo event
239 { MAP_CHAR_LEN("actionPerformed"), { MAP_CHAR_LEN("_Click"), NULL
, ApproveAll
, NULL
} },
240 { MAP_CHAR_LEN("itemStateChanged"), { MAP_CHAR_LEN("_Change"), NULL
, ApproveType
, (void*)(&radioButtonList
) } },
241 // itemStateChanged ooo event
242 { MAP_CHAR_LEN("itemStateChanged"), { MAP_CHAR_LEN("_Click"), NULL
, ApproveType
, (void*)(&comboBoxList
) } },
244 { MAP_CHAR_LEN("itemStateChanged"), { MAP_CHAR_LEN("_Click"), NULL
, ApproveType
, (void*)(&listBoxList
) } },
246 { MAP_CHAR_LEN("changed"), { MAP_CHAR_LEN("_Change"), NULL
, ApproveAll
, NULL
} },
248 // focusGained ooo event
249 { MAP_CHAR_LEN("focusGained"), { MAP_CHAR_LEN("_GotFocus"), NULL
, ApproveAll
, NULL
} },
251 // focusLost ooo event
252 { MAP_CHAR_LEN("focusLost"), { MAP_CHAR_LEN("_LostFocus"), NULL
, ApproveAll
, NULL
} },
253 { MAP_CHAR_LEN("focusLost"), { MAP_CHAR_LEN("_Exit"), NULL
, ApproveType
, (void*)(&textCompList
) } }, // support VBA TextBox_Exit event
255 // adjustmentValueChanged ooo event
256 { MAP_CHAR_LEN("adjustmentValueChanged"), { MAP_CHAR_LEN("_Scroll"), NULL
, ApproveAll
, NULL
} },
257 { MAP_CHAR_LEN("adjustmentValueChanged"), { MAP_CHAR_LEN("_Change"), NULL
, ApproveAll
, NULL
} },
259 // textChanged ooo event
260 { MAP_CHAR_LEN("textChanged"), { MAP_CHAR_LEN("_Change"), NULL
, ApproveAll
, NULL
} },
262 // keyReleased ooo event
263 { MAP_CHAR_LEN("keyReleased"), { MAP_CHAR_LEN("_KeyUp"), ooKeyPressedToVBAKeyUpDown
, ApproveAll
, NULL
} },
265 // mouseReleased ooo event
266 { MAP_CHAR_LEN("mouseReleased"), { MAP_CHAR_LEN("_Click"), ooMouseEvtToVBAMouseEvt
, ApproveType
, (void*)(&fixedTextList
) } },
267 { MAP_CHAR_LEN("mouseReleased"), { MAP_CHAR_LEN("_MouseUp"), ooMouseEvtToVBAMouseEvt
, ApproveAll
, NULL
} },
269 // mousePressed ooo event
270 { MAP_CHAR_LEN("mousePressed"), { MAP_CHAR_LEN("_MouseDown"), ooMouseEvtToVBAMouseEvt
, ApproveAll
, NULL
} },
271 { MAP_CHAR_LEN("mousePressed"), { MAP_CHAR_LEN("_DblClick"), ooMouseEvtToVBADblClick
, ApproveAll
, NULL
} },
273 // mouseMoved ooo event
274 { MAP_CHAR_LEN("mouseMoved"), { MAP_CHAR_LEN("_MouseMove"), ooMouseEvtToVBAMouseEvt
, ApproveAll
, NULL
} },
275 { MAP_CHAR_LEN("mouseDragged"), { MAP_CHAR_LEN("_MouseMove"), ooMouseEvtToVBAMouseEvt
, DenyMouseDrag
, NULL
} },
277 // keyPressed ooo event
278 { MAP_CHAR_LEN("keyPressed"), { MAP_CHAR_LEN("_KeyDown"), ooKeyPressedToVBAKeyUpDown
, ApproveAll
, NULL
} },
279 { MAP_CHAR_LEN("keyPressed"), { MAP_CHAR_LEN("_KeyPress"), ooKeyPressedToVBAKeyPressed
, ApproveAll
, NULL
} }
282 EventInfoHash
& getEventTransInfo()
284 static bool initialised
= false;
285 static EventInfoHash eventTransInfo
;
288 OUString sEventInfo
= MAP_CHAR_LEN("");
289 TranslatePropMap
* pTransProp
= aTranslatePropMap_Impl
;
290 int nCount
= sizeof(aTranslatePropMap_Impl
) / sizeof(aTranslatePropMap_Impl
[0]);
295 sEventInfo
= pTransProp
->sEventInfo
;
296 std::list
< TranslateInfo
> infoList
;
299 infoList
.push_back( pTransProp
->aTransInfo
);
302 }while(i
< nCount
&& sEventInfo
== pTransProp
->sEventInfo
);
303 eventTransInfo
[sEventInfo
] = infoList
;
307 return eventTransInfo
;
313 class ScriptEventHelper
316 ScriptEventHelper( const Reference
< XInterface
>& xControl
);
317 ScriptEventHelper( const OUString
& sCntrlServiceName
);
318 ~ScriptEventHelper();
319 Sequence
< ScriptEventDescriptor
> createEvents( const OUString
& sCodeName
);
320 Sequence
< OUString
> getEventListeners();
322 Reference
< XComponentContext
> m_xCtx
;
323 Reference
< XInterface
> m_xControl
;
328 eventMethodToDescriptor( const OUString
& rEventMethod
, ScriptEventDescriptor
& evtDesc
, const OUString
& sCodeName
)
330 // format of ControlListener is TypeName::methodname e.g.
331 // "com.sun.star.awt.XActionListener::actionPerformed" or
332 // "XActionListener::actionPerformed
334 OUString sMethodName
;
336 sal_Int32 nDelimPos
= rEventMethod
.indexOf( DELIM
);
337 if ( nDelimPos
== -1 )
341 sMethodName
= rEventMethod
.copy( nDelimPos
+ DELIMLEN
);
342 sTypeName
= rEventMethod
.copy( 0, nDelimPos
);
344 EventInfoHash
& infos
= getEventTransInfo();
346 // Only create an ScriptEventDescriptor for an event we can translate
348 if ( !sMethodName
.isEmpty()
349 && !sTypeName
.isEmpty()
350 && ( infos
.find( sMethodName
) != infos
.end() ) )
352 // just fill in CodeName, when the event fires the other
353 // info is gathered from the event source to determine what
354 // event handler we try to call
355 evtDesc
.ScriptCode
= sCodeName
;
356 evtDesc
.ListenerType
= sTypeName
;
357 evtDesc
.EventMethod
= sMethodName
;
359 // set this it VBAInterop, ensures that it doesn't
360 // get persisted or shown in property editors
361 evtDesc
.ScriptType
= OUString(
369 ScriptEventHelper::ScriptEventHelper( const Reference
< XInterface
>& xControl
) :
370 m_xCtx( comphelper::getProcessComponentContext() ),
371 m_xControl( xControl
),
375 ScriptEventHelper::ScriptEventHelper( const OUString
& sCntrlServiceName
) :
376 m_xCtx( comphelper::getProcessComponentContext() ),
379 m_xControl
.set( m_xCtx
->getServiceManager()->createInstanceWithContext( sCntrlServiceName
, m_xCtx
), uno::UNO_QUERY
);
382 ScriptEventHelper::~ScriptEventHelper()
384 // dispose control ( and remove any associated event registrations )
389 uno::Reference
< lang::XComponent
> xComp( m_xControl
, uno::UNO_QUERY_THROW
);
392 // destructor can't throw
393 catch( uno::Exception
& )
400 ScriptEventHelper::getEventListeners()
402 std::list
< OUString
> eventMethods
;
404 Reference
< beans::XIntrospection
> xIntrospection
= beans::Introspection::create( m_xCtx
);
406 Reference
< beans::XIntrospectionAccess
> xIntrospectionAccess
=
407 xIntrospection
->inspect( makeAny( m_xControl
) );
408 Sequence
< Type
> aControlListeners
=
409 xIntrospectionAccess
->getSupportedListeners();
410 sal_Int32 nLength
= aControlListeners
.getLength();
411 for ( sal_Int32 i
= 0; i
< nLength
; ++i
)
413 Type
& listType
= aControlListeners
[ i
];
414 OUString sFullTypeName
= listType
.getTypeName();
415 Sequence
< OUString
> sMeths
=
416 comphelper::getEventMethodsForType( listType
);
417 sal_Int32 sMethLen
= sMeths
.getLength();
418 for ( sal_Int32 j
=0 ; j
< sMethLen
; ++j
)
420 OUString sEventMethod
= sFullTypeName
;
421 sEventMethod
+= DELIM
;
422 sEventMethod
+= sMeths
[ j
];
423 eventMethods
.push_back( sEventMethod
);
427 Sequence
< OUString
> sEventMethodNames( eventMethods
.size() );
428 std::list
< OUString
>::const_iterator it
= eventMethods
.begin();
429 OUString
* pDest
= sEventMethodNames
.getArray();
431 for ( ; it
!= eventMethods
.end(); ++it
, ++pDest
)
434 return sEventMethodNames
;
437 Sequence
< ScriptEventDescriptor
>
438 ScriptEventHelper::createEvents( const OUString
& sCodeName
)
440 Sequence
< OUString
> aControlListeners
= getEventListeners();
441 OUString
* pSrc
= aControlListeners
.getArray();
442 sal_Int32 nLength
= aControlListeners
.getLength();
444 Sequence
< ScriptEventDescriptor
> aDest( nLength
);
446 for ( sal_Int32 i
= 0; i
< nLength
; ++i
, ++pSrc
)
448 // from getListeners eventName is of form
449 // "com.sun.star.awt.XActionListener::actionPerformed"
450 // we need to strip "com.sun.star.awt." from that for form
452 ScriptEventDescriptor evtDesc
;
453 if ( eventMethodToDescriptor( *pSrc
, evtDesc
, sCodeName
) )
455 sal_Int32 dIndex
= nEvts
;
457 if ( nEvts
> aDest
.getLength() )
458 aDest
.realloc( nEvts
);// should never happen
459 aDest
[ dIndex
] = evtDesc
;
462 aDest
.realloc( nEvts
);
468 typedef ::cppu::WeakImplHelper1
< container::XNameContainer
> NameContainer_BASE
;
470 class ReadOnlyEventsNameContainer
: public NameContainer_BASE
473 ReadOnlyEventsNameContainer( const Sequence
< OUString
>& eventMethods
, const OUString
& sCodeName
);
476 virtual void SAL_CALL
insertByName( const OUString
&, const Any
& ) throw (lang::IllegalArgumentException
, container::ElementExistException
, lang::WrappedTargetException
, RuntimeException
)
478 throw RuntimeException( OUString("ReadOnly container"), Reference
< XInterface
>() );
481 virtual void SAL_CALL
removeByName( const OUString
& ) throw (::com::sun::star::container::NoSuchElementException
, lang::WrappedTargetException
, RuntimeException
)
483 throw RuntimeException( OUString("ReadOnly container"), Reference
< XInterface
>() );
487 virtual void SAL_CALL
replaceByName( const OUString
&, const Any
& ) throw (lang::IllegalArgumentException
, container::NoSuchElementException
, lang::WrappedTargetException
, RuntimeException
)
489 throw RuntimeException( OUString("ReadOnly container"), Reference
< XInterface
>() );
494 virtual Any SAL_CALL
getByName( const OUString
& aName
) throw (container::NoSuchElementException
, lang::WrappedTargetException
, RuntimeException
);
495 virtual Sequence
< OUString
> SAL_CALL
getElementNames( ) throw (RuntimeException
);
496 virtual ::sal_Bool SAL_CALL
hasByName( const OUString
& aName
) throw (RuntimeException
);
499 virtual Type SAL_CALL
getElementType( ) throw (RuntimeException
)
500 { return getCppuType(static_cast< const OUString
* >(0) ); }
501 virtual ::sal_Bool SAL_CALL
hasElements( ) throw (RuntimeException
)
502 { return ( ( m_hEvents
.size() > 0 ? sal_True
: sal_False
) ); }
505 typedef boost::unordered_map
< OUString
, Any
, OUStringHash
,
506 ::std::equal_to
< OUString
> > EventSupplierHash
;
508 EventSupplierHash m_hEvents
;
511 ReadOnlyEventsNameContainer::ReadOnlyEventsNameContainer( const Sequence
< OUString
>& eventMethods
, const OUString
& sCodeName
)
513 const OUString
* pSrc
= eventMethods
.getConstArray();
514 sal_Int32 nLen
= eventMethods
.getLength();
515 for ( sal_Int32 index
= 0; index
< nLen
; ++index
, ++pSrc
)
518 ScriptEventDescriptor evtDesc
;
519 if ( eventMethodToDescriptor( *pSrc
, evtDesc
, sCodeName
) )
522 m_hEvents
[ *pSrc
] = aDesc
;
528 ReadOnlyEventsNameContainer::getByName( const OUString
& aName
) throw (container::NoSuchElementException
, lang::WrappedTargetException
, RuntimeException
){
529 EventSupplierHash::const_iterator it
= m_hEvents
.find( aName
);
530 if ( it
== m_hEvents
.end() )
531 throw container::NoSuchElementException();
535 Sequence
< OUString
> SAL_CALL
536 ReadOnlyEventsNameContainer::getElementNames( ) throw (RuntimeException
)
538 Sequence
< OUString
> names(m_hEvents
.size());
539 OUString
* pDest
= names
.getArray();
540 EventSupplierHash::const_iterator it
= m_hEvents
.begin();
541 EventSupplierHash::const_iterator it_end
= m_hEvents
.end();
542 for ( sal_Int32 index
= 0; it
!= it_end
; ++index
, ++pDest
, ++it
)
548 ReadOnlyEventsNameContainer::hasByName( const OUString
& aName
) throw (RuntimeException
)
550 EventSupplierHash::const_iterator it
= m_hEvents
.find( aName
);
551 if ( it
== m_hEvents
.end() )
556 typedef ::cppu::WeakImplHelper1
< XScriptEventsSupplier
> EventsSupplier_BASE
;
558 class ReadOnlyEventsSupplier
: public EventsSupplier_BASE
561 ReadOnlyEventsSupplier( const Sequence
< OUString
>& eventMethods
, const OUString
& sCodeName
)
562 { m_xNameContainer
= new ReadOnlyEventsNameContainer( eventMethods
, sCodeName
); }
564 // XScriptEventSupplier
565 virtual Reference
< container::XNameContainer
> SAL_CALL
getEvents( ) throw (RuntimeException
){ return m_xNameContainer
; }
567 Reference
< container::XNameContainer
> m_xNameContainer
;
570 typedef ::cppu::WeakImplHelper3
< XScriptListener
, util::XCloseListener
, lang::XInitialization
> EventListener_BASE
;
572 #define EVENTLSTNR_PROPERTY_ID_MODEL 1
573 #define EVENTLSTNR_PROPERTY_MODEL OUString( "Model" )
575 class EventListener
: public EventListener_BASE
576 ,public ::comphelper::OMutexAndBroadcastHelper
577 ,public ::comphelper::OPropertyContainer
578 ,public ::comphelper::OPropertyArrayUsageHelper
< EventListener
>
583 EventListener( const Reference
< XComponentContext
>& rxContext
);
585 virtual void SAL_CALL
disposing(const lang::EventObject
& Source
) throw( RuntimeException
);
586 using cppu::OPropertySetHelper::disposing
;
589 virtual void SAL_CALL
firing(const ScriptEvent
& evt
) throw(RuntimeException
);
590 virtual Any SAL_CALL
approveFiring(const ScriptEvent
& evt
) throw(reflection::InvocationTargetException
, RuntimeException
);
592 virtual void SAL_CALL
queryClosing( const lang::EventObject
& Source
, ::sal_Bool GetsOwnership
) throw (util::CloseVetoException
, uno::RuntimeException
);
593 virtual void SAL_CALL
notifyClosing( const lang::EventObject
& Source
) throw (uno::RuntimeException
);
595 virtual ::com::sun::star::uno::Reference
< ::com::sun::star::beans::XPropertySetInfo
> SAL_CALL
getPropertySetInfo( ) throw (::com::sun::star::uno::RuntimeException
);
597 virtual void SAL_CALL
initialize( const Sequence
< Any
>& aArguments
) throw (Exception
, RuntimeException
);
602 DECLARE_XTYPEPROVIDER()
603 virtual void SAL_CALL
setFastPropertyValue( sal_Int32 nHandle
, const ::com::sun::star::uno::Any
& rValue
) throw(::com::sun::star::beans::UnknownPropertyException
, ::com::sun::star::beans::PropertyVetoException
, ::com::sun::star::lang::IllegalArgumentException
, ::com::sun::star::lang::WrappedTargetException
, ::com::sun::star::uno::RuntimeException
)
605 if ( nHandle
== EVENTLSTNR_PROPERTY_ID_MODEL
)
607 uno::Reference
< frame::XModel
> xModel( rValue
, uno::UNO_QUERY
);
608 if( xModel
!= m_xModel
)
610 // Remove the listener from the old XCloseBroadcaster.
611 uno::Reference
< util::XCloseBroadcaster
> xCloseBroadcaster( m_xModel
, uno::UNO_QUERY
);
612 if (xCloseBroadcaster
.is())
614 xCloseBroadcaster
->removeCloseListener( this );
616 // Add the listener into the new XCloseBroadcaster.
617 xCloseBroadcaster
= uno::Reference
< util::XCloseBroadcaster
>( xModel
, uno::UNO_QUERY
);
618 if (xCloseBroadcaster
.is())
620 xCloseBroadcaster
->addCloseListener( this );
624 OPropertyContainer::setFastPropertyValue( nHandle
, rValue
);
625 if ( nHandle
== EVENTLSTNR_PROPERTY_ID_MODEL
)
630 // OPropertySetHelper
631 virtual ::cppu::IPropertyArrayHelper
& SAL_CALL
getInfoHelper( );
633 // OPropertyArrayUsageHelper
634 virtual ::cppu::IPropertyArrayHelper
* createArrayHelper( ) const;
638 DECL_LINK( OnAsyncScriptEvent
, ScriptEvent
* );
640 void setShellFromModel();
641 void firing_Impl( const ScriptEvent
& evt
, Any
*pSyncRet
=NULL
) throw( RuntimeException
);
643 Reference
< XComponentContext
> m_xContext
;
644 Reference
< frame::XModel
> m_xModel
;
646 SfxObjectShell
* mpShell
;
650 EventListener::EventListener( const Reference
< XComponentContext
>& rxContext
) :
651 OPropertyContainer(GetBroadcastHelper()), m_xContext( rxContext
), m_bDocClosed(false), mpShell( 0 )
653 registerProperty( EVENTLSTNR_PROPERTY_MODEL
, EVENTLSTNR_PROPERTY_ID_MODEL
,
654 beans::PropertyAttribute::TRANSIENT
, &m_xModel
, ::getCppuType( &m_xModel
) );
655 msProject
= OUString("Standard");
659 EventListener::setShellFromModel()
663 SfxObjectShell
* pShell
= SfxObjectShell::GetFirst();
664 while ( m_xModel
.is() && pShell
)
666 if ( pShell
->GetModel() == m_xModel
)
671 pShell
= SfxObjectShell::GetNext( *pShell
);
673 // set ProjectName from model
676 uno::Reference
< beans::XPropertySet
> xProps( m_xModel
, UNO_QUERY_THROW
);
677 uno::Reference
< script::vba::XVBACompatibility
> xVBAMode( xProps
->getPropertyValue( OUString( "BasicLibraries" ) ), uno::UNO_QUERY_THROW
);
678 msProject
= xVBAMode
->getProjectName();
680 catch ( uno::Exception
& ) {}
685 EventListener::disposing(const lang::EventObject
&) throw( RuntimeException
)
692 EventListener::firing(const ScriptEvent
& evt
) throw(RuntimeException
)
695 // needs some logic to check if the event handler is oneway or not
696 // if not oneway then firing_Impl otherwise... as below
698 Application::PostUserEvent( LINK( this, EventListener
, OnAsyncScriptEvent
), new ScriptEvent( evt
) );
705 IMPL_LINK( EventListener
, OnAsyncScriptEvent
, ScriptEvent
*, _pEvent
)
711 // #FIXME if we enable ASYNC we probably need something like
713 //::osl::ClearableMutexGuard aGuard( m_aMutex );
715 //if ( !impl_isDisposed_nothrow() )
716 // impl_doFireScriptEvent_nothrow( aGuard, *_pEvent, NULL );
717 firing_Impl( *_pEvent
, NULL
);
721 // we acquired ourself immediately before posting the event
728 EventListener::approveFiring(const ScriptEvent
& evt
) throw(reflection::InvocationTargetException
, RuntimeException
)
731 firing_Impl( evt
, &ret
);
737 EventListener::queryClosing( const lang::EventObject
& /*Source*/, ::sal_Bool
/*GetsOwnership*/ ) throw (util::CloseVetoException
, uno::RuntimeException
)
743 EventListener::notifyClosing( const lang::EventObject
& /*Source*/ ) throw (uno::RuntimeException
)
746 uno::Reference
< util::XCloseBroadcaster
> xCloseBroadcaster( m_xModel
, uno::UNO_QUERY
);
747 if (xCloseBroadcaster
.is())
749 xCloseBroadcaster
->removeCloseListener( this );
755 EventListener::initialize( const Sequence
< Any
>& aArguments
) throw (Exception
, RuntimeException
)
757 if ( aArguments
.getLength() == 1 )
758 aArguments
[0] >>= m_xModel
;
759 OSL_TRACE("EventListener::initialize() args %d m_xModel %d", aArguments
.getLength(), m_xModel
.is() );
764 IMPLEMENT_FORWARD_XINTERFACE2( EventListener
, EventListener_BASE
, OPropertyContainer
)
768 IMPLEMENT_FORWARD_XTYPEPROVIDER2( EventListener
, EventListener_BASE
, OPropertyContainer
)
770 // OPropertySetHelper
772 ::cppu::IPropertyArrayHelper
&
773 EventListener::getInfoHelper( )
775 return *getArrayHelper();
778 // OPropertyArrayUsageHelper
780 ::cppu::IPropertyArrayHelper
*
781 EventListener::createArrayHelper( ) const
783 Sequence
< beans::Property
> aProps
;
784 describeProperties( aProps
);
785 return new ::cppu::OPropertyArrayHelper( aProps
);
789 Reference
< beans::XPropertySetInfo
>
790 EventListener::getPropertySetInfo( ) throw (RuntimeException
)
792 Reference
< beans::XPropertySetInfo
> xInfo( createPropertySetInfo( getInfoHelper() ) );
797 //decide if the control should execute the event
798 bool ApproveAll(const ScriptEvent
&, void* )
803 //for the given control type in evt.Arguments[0], look for if it appears in the type list in pPara
804 bool FindControl(const ScriptEvent
& evt
, void* pPara
)
806 lang::EventObject aEvent
;
807 evt
.Arguments
[ 0 ] >>= aEvent
;
808 uno::Reference
< uno::XInterface
> xInterface( aEvent
.Source
, uno::UNO_QUERY
);
810 TypeList
* pTypeListInfo
= static_cast<TypeList
*>(pPara
);
811 Type
* pType
= pTypeListInfo
->pTypeList
;
812 int nLen
= pTypeListInfo
->nListLength
;
814 for (int i
= 0; i
< nLen
; i
++)
816 if ( xInterface
->queryInterface( *pType
).hasValue() )
826 //if the given control type in evt.Arguments[0] appears in the type list in pPara, then approve the execution
827 bool ApproveType(const ScriptEvent
& evt
, void* pPara
)
829 return FindControl(evt
, pPara
);
832 //if the given control type in evt.Arguments[0] appears in the type list in pPara, then deny the execution
833 bool DenyType(const ScriptEvent
& evt
, void* pPara
)
835 return !FindControl(evt
, pPara
);
838 //when mouse is moving, either the mouse button is pressed or some key is pressed can trigger the OO mouseDragged event,
839 //the former should be denyed, and the latter allowed, only by doing so can the VBA MouseMove event when the "Shift" key is
840 //pressed can be correctly triggered
841 bool DenyMouseDrag(const ScriptEvent
& evt
, void* )
843 awt::MouseEvent aEvent
;
844 evt
.Arguments
[ 0 ] >>= aEvent
;
845 if (aEvent
.Buttons
== 0 )
859 EventListener::firing_Impl(const ScriptEvent
& evt
, Any
* pRet
) throw(RuntimeException
)
861 OSL_TRACE("EventListener::firing_Impl( FAKE VBA_EVENTS )");
862 static const OUString vbaInterOp
=
863 OUString("VBAInterop");
865 // let default handlers deal with non vba stuff
866 if ( !evt
.ScriptType
.equals( vbaInterOp
) )
868 lang::EventObject aEvent
;
869 evt
.Arguments
[ 0 ] >>= aEvent
;
870 OSL_TRACE("evt.MethodName is %s", OUStringToOString( evt
.MethodName
, RTL_TEXTENCODING_UTF8
).getStr() );
871 OSL_TRACE("Argument[0] is %s", OUStringToOString( comphelper::anyToString( evt
.Arguments
[0] ), RTL_TEXTENCODING_UTF8
).getStr() );
872 OSL_TRACE("Getting Control");
873 OUString sName
= OUString( "UserForm" );
874 OSL_TRACE("Getting Name");
876 uno::Reference
< awt::XDialog
> xDlg( aEvent
.Source
, uno::UNO_QUERY
);
879 OSL_TRACE("Getting Control");
882 // b) xShapeControl ( from api (sheet control) )
883 // c) eventmanager ( I guess )
884 // d) vba control ( from api also )
885 uno::Reference
< drawing::XControlShape
> xCntrlShape( evt
.Source
, uno::UNO_QUERY
);
886 uno::Reference
< awt::XControl
> xControl( aEvent
.Source
, uno::UNO_QUERY
);
887 if ( xCntrlShape
.is() )
889 // for sheet controls ( that fire from the api ) we don't
890 // have the real control ( thats only available from the view )
891 // api code creates just a control instance that is transferred
892 // via aEvent.Arguments[ 0 ] that control though has no
893 // info like name etc.
894 OSL_TRACE("Got control shape");
895 uno::Reference
< container::XNamed
> xName( xCntrlShape
->getControl(), uno::UNO_QUERY_THROW
);
896 OSL_TRACE("Got xnamed ");
897 sName
= xName
->getName();
901 // Userform control ( fired from the api or from event manager )
902 uno::Reference
< beans::XPropertySet
> xProps
;
903 OSL_TRACE("Getting properties");
904 xProps
.set( xControl
->getModel(), uno::UNO_QUERY_THROW
);
905 xProps
->getPropertyValue( OUString( "Name" ) ) >>= sName
;
909 EventInfoHash
& infos
= getEventTransInfo();
910 EventInfoHash::const_iterator eventInfo_it
= infos
.find( evt
.MethodName
);
911 EventInfoHash::const_iterator it_end
= infos
.end();
912 if ( eventInfo_it
== it_end
)
914 OSL_TRACE("Bogus event for %s",
915 OUStringToOString( evt
.ScriptType
, RTL_TEXTENCODING_UTF8
).getStr() );
919 uno::Reference
< script::provider::XScriptProviderSupplier
> xSPS( m_xModel
, uno::UNO_QUERY
);
920 uno::Reference
< script::provider::XScriptProvider
> xScriptProvider
;
923 xScriptProvider
= xSPS
->getScriptProvider();
925 if ( xScriptProvider
.is() && mpShell
)
927 std::list
< TranslateInfo
>::const_iterator txInfo
=
928 eventInfo_it
->second
.begin();
929 std::list
< TranslateInfo
>::const_iterator txInfo_end
= eventInfo_it
->second
.end();
931 BasicManager
* pBasicManager
= mpShell
->GetBasicManager();
933 OUString
sScriptCode( evt
.ScriptCode
);
934 // dialogs pass their own library, presence of Dot determines that
935 if ( sScriptCode
.indexOf( '.' ) == -1 )
937 //'Project' is a better default but I want to force failures
938 //OUString sMacroLoc("Project");
939 sProject
= "Standard";
941 if (!pBasicManager
->GetName().isEmpty())
943 sProject
= pBasicManager
->GetName();
948 sal_Int32 nIndex
= sScriptCode
.indexOf( '.' );
949 sProject
= sScriptCode
.copy( 0, nIndex
);
950 sScriptCode
= sScriptCode
.copy( nIndex
+ 1 );
952 OUString sMacroLoc
= sProject
;
953 sMacroLoc
= sMacroLoc
.concat( OUString(".") );
954 sMacroLoc
= sMacroLoc
.concat( sScriptCode
).concat( OUString(".") );
956 OSL_TRACE("sMacroLoc is %s", OUStringToOString( sMacroLoc
, RTL_TEXTENCODING_UTF8
).getStr() );
957 for ( ; txInfo
!= txInfo_end
; ++txInfo
)
959 // If the document is closed, we should not execute macro.
965 OUString sTemp
= sName
.concat( (*txInfo
).sVBAName
);
966 // see if we have a match for the handlerextension
967 // where ScriptCode is methodname_handlerextension
968 OUString sToResolve
= sMacroLoc
.concat( sTemp
);
970 OSL_TRACE("*** trying to invoke %s ",
971 OUStringToOString( sToResolve
, RTL_TEXTENCODING_UTF8
).getStr() );
972 ooo::vba::MacroResolvedInfo aMacroResolvedInfo
= ooo::vba::resolveVBAMacro( mpShell
, sToResolve
);
973 if ( aMacroResolvedInfo
.mbFound
)
976 if (! txInfo
->ApproveRule(evt
, txInfo
->pPara
) )
981 // !! translate arguments & emulate events where necessary
982 Sequence
< Any
> aArguments
;
983 if ( (*txInfo
).toVBA
)
985 aArguments
= (*txInfo
).toVBA( evt
.Arguments
);
989 aArguments
= evt
.Arguments
;
991 if ( aArguments
.getLength() )
993 // call basic event handlers for event
996 OUString url
= aMacroResolvedInfo
.msResolvedMacro
;
998 OSL_TRACE("resolved script = %s",
999 OUStringToOString( url
,
1000 RTL_TEXTENCODING_UTF8
).getStr() );
1003 uno::Any aDummyCaller
= uno::makeAny( OUString("Error") );
1006 ooo::vba::executeMacro( mpShell
, url
, aArguments
, *pRet
, aDummyCaller
);
1011 ooo::vba::executeMacro( mpShell
, url
, aArguments
, aRet
, aDummyCaller
);
1014 catch ( uno::Exception
& e
)
1016 OSL_TRACE("event script raised %s", OUStringToOString( e
.Message
, RTL_TEXTENCODING_UTF8
).getStr() );
1024 typedef ::cppu::WeakImplHelper1
< XVBAToOOEventDescGen
> VBAToOOEventDescGen_BASE
;
1027 class VBAToOOEventDescGen
: public VBAToOOEventDescGen_BASE
1030 VBAToOOEventDescGen( const Reference
< XComponentContext
>& rxContext
);
1032 // XVBAToOOEventDescGen
1033 virtual Sequence
< ScriptEventDescriptor
> SAL_CALL
getEventDescriptions( const OUString
& sCtrlServiceName
, const OUString
& sCodeName
) throw (RuntimeException
);
1034 virtual Reference
< XScriptEventsSupplier
> SAL_CALL
getEventSupplier( const Reference
< XInterface
>& xControl
, const OUString
& sCodeName
) throw (::com::sun::star::uno::RuntimeException
);
1036 Reference
< XComponentContext
> m_xContext
;
1040 VBAToOOEventDescGen::VBAToOOEventDescGen( const Reference
< XComponentContext
>& rxContext
):m_xContext( rxContext
) {}
1042 Sequence
< ScriptEventDescriptor
> SAL_CALL
1043 VBAToOOEventDescGen::getEventDescriptions( const OUString
& sCntrlServiceName
, const OUString
& sCodeName
) throw (RuntimeException
)
1045 ScriptEventHelper
evntHelper( sCntrlServiceName
);
1046 return evntHelper
.createEvents( sCodeName
);
1049 Reference
< XScriptEventsSupplier
> SAL_CALL
1050 VBAToOOEventDescGen::getEventSupplier( const Reference
< XInterface
>& xControl
, const OUString
& sCodeName
) throw (::com::sun::star::uno::RuntimeException
)
1052 ScriptEventHelper
evntHelper( xControl
);
1053 Reference
< XScriptEventsSupplier
> xSupplier
=
1054 new ReadOnlyEventsSupplier(
1055 evntHelper
.getEventListeners(), sCodeName
) ;
1059 // Component related
1063 OUString SAL_CALL
getImplementationName()
1065 static OUString
* pImplName
= 0;
1068 ::osl::MutexGuard
aGuard( ::osl::Mutex::getGlobalMutex() );
1071 static OUString
aImplName( "ooo.vba.EventListener" );
1072 pImplName
= &aImplName
;
1078 uno::Reference
< XInterface
> SAL_CALL
create(
1079 Reference
< XComponentContext
> const & xContext
)
1082 return static_cast< lang::XTypeProvider
* >( new EventListener( xContext
) );
1085 Sequence
< OUString
> SAL_CALL
getSupportedServiceNames()
1087 const OUString
strName( ::evtlstner::getImplementationName() );
1088 return Sequence
< OUString
>( &strName
, 1 );
1091 namespace ooevtdescgen
1093 OUString SAL_CALL
getImplementationName()
1095 static OUString
* pImplName
= 0;
1098 ::osl::MutexGuard
aGuard( ::osl::Mutex::getGlobalMutex() );
1101 static OUString
aImplName( "ooo.vba.VBAToOOEventDesc" );
1102 pImplName
= &aImplName
;
1108 uno::Reference
< XInterface
> SAL_CALL
create(
1109 Reference
< XComponentContext
> const & xContext
)
1112 return static_cast< lang::XTypeProvider
* >( new VBAToOOEventDescGen( xContext
) );
1115 Sequence
< OUString
> SAL_CALL
getSupportedServiceNames()
1117 const OUString
strName( ::ooevtdescgen::getImplementationName() );
1118 return Sequence
< OUString
>( &strName
, 1 );
1122 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */