1 #include <comphelper/processfactory.hxx>
2 #include <comphelper/uno3.hxx>
3 #include <comphelper/proparrhlp.hxx>
4 #include <comphelper/propertycontainer.hxx>
6 #include <ooo/vba/XVBAToOOEventDescGen.hpp>
8 #include <com/sun/star/beans/XPropertySet.hpp>
9 #include <com/sun/star/beans/XIntrospection.hpp>
10 #include <com/sun/star/beans/PropertyAttribute.hpp>
12 #include <com/sun/star/lang/XMultiComponentFactory.hpp>
13 #include <com/sun/star/lang/XServiceName.hpp>
14 #include <com/sun/star/lang/XServiceInfo.hpp>
15 #include <com/sun/star/lang/XInitialization.hpp>
17 #include <com/sun/star/frame/XModel.hpp>
19 #include <com/sun/star/script/XLibraryContainer.hpp>
20 #include <com/sun/star/script/ScriptEventDescriptor.hpp>
21 #include <com/sun/star/script/provider/XScriptProviderSupplier.hpp>
23 #include <com/sun/star/drawing/XControlShape.hpp>
25 #include <com/sun/star/awt/XControl.hpp>
26 #include <com/sun/star/awt/XDialog.hpp>
27 #include <com/sun/star/awt/KeyEvent.hpp>
28 #include <com/sun/star/awt/MouseEvent.hpp>
29 #include <com/sun/star/awt/XFixedText.hpp> //liuchen 2009-6-5
30 #include <com/sun/star/awt/XTextComponent.hpp> //liuchen 2009-6-5
31 #include <com/sun/star/awt/XComboBox.hpp> //liuchen 2009-6-18
32 #include <com/sun/star/awt/XRadioButton.hpp> //liuchen 2009-7-30
34 #include <msforms/ReturnInteger.hpp>
36 #include <sfx2/objsh.hxx>
37 #include <basic/sbstar.hxx>
38 #include <basic/basmgr.hxx>
39 #include <basic/sbmeth.hxx>
40 #include <basic/sbmod.hxx>
41 #include <basic/sbx.hxx>
42 #include <svx/msvbahelper.hxx>
45 #include <comphelper/anytostring.hxx>
47 #include <com/sun/star/lang/XMultiComponentFactory.hpp>
48 #include <com/sun/star/script/XScriptListener.hpp>
49 #include <cppuhelper/implbase1.hxx>
50 #include <cppuhelper/implbase2.hxx>
51 #include <comphelper/evtmethodhelper.hxx>
58 // primitive support for asynchronous handling of
59 // events from controls ( all event will be processed asynchronously
60 // in the application thread )
62 #include <vcl/svapp.hxx>
65 using namespace ::com::sun::star
;
66 using namespace ::com::sun::star::script
;
67 using namespace ::com::sun::star::uno
;
68 using namespace ::ooo::vba
;
70 #define MAP_CHAR_LEN(x) ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(x))//liuchen 2009-6-8
71 #define GET_TYPE(x) ::getCppuType((uno::Reference< x > *)0);
74 const static rtl::OUString DELIM
= rtl::OUString::createFromAscii( "::" );
75 const static sal_Int32 DELIMLEN
= DELIM
.getLength();
78 void dumpListeners( const Reference
< beans::XIntrospection
>& xIntrospection
, const Reference
<XInterface
>& xIfc
)
80 Reference
< beans::XIntrospectionAccess
> xIntrospectionAccess
;
81 if ( xIntrospection
.is() )
83 xIntrospectionAccess
= xIntrospection
->inspect(
85 Sequence
< Type
> aControlListeners
=
86 xIntrospectionAccess
->getSupportedListeners();
87 sal_Int32 nLength
= aControlListeners
.getLength();
89 for ( sal_Int32 i
= 0; i
< nLength
; ++i
)
91 Type
& listType
= aControlListeners
[ i
];
92 rtl::OUString sFullTypeName
= listType
.getTypeName();
93 rtl::OUString sTypeName
= listType
.getTypeName();
94 sal_Int32 lastDotIndex
= -1;
95 if ( ( lastDotIndex
= sFullTypeName
.lastIndexOf( '.' ) ) > -1 )
97 sTypeName
= sFullTypeName
.copy( lastDotIndex
+ 1 );
99 Sequence
< ::rtl::OUString
> sMeths
= comphelper::getEventMethodsForType( listType
);
100 sal_Int32 sMethLen
= sMeths
.getLength();
101 for ( sal_Int32 j
=0 ; j
< sMethLen
; ++j
)
103 OSL_TRACE("**Listener [%d] Type[%s] Method[%s]",j
,
104 rtl::OUStringToOString( sTypeName
,
105 RTL_TEXTENCODING_UTF8
).getStr(),
106 rtl::OUStringToOString( sMeths
[ j
],
107 RTL_TEXTENCODING_UTF8
).getStr() );
114 void dumpEvent( const ScriptEvent
& evt
)
116 OSL_TRACE("dumpEvent: Source %s",
117 rtl::OUStringToOString( comphelper::anyToString( makeAny(evt
.Source
)),
118 RTL_TEXTENCODING_UTF8
).getStr() );
120 OSL_TRACE("dumpEvent: ScriptType %s",
121 rtl::OUStringToOString( evt
.ScriptType
,
122 RTL_TEXTENCODING_UTF8
).getStr() );
124 OSL_TRACE("dumpEvent: ScriptCode %s",
125 rtl::OUStringToOString( evt
.ScriptCode
,
126 RTL_TEXTENCODING_UTF8
).getStr() );
128 OSL_TRACE("dumpEvent: ListenerType %s",
129 rtl::OUStringToOString( evt
.ListenerType
.getTypeName(),
130 RTL_TEXTENCODING_UTF8
).getStr() );
132 OSL_TRACE("dumpEvent: Listener methodname %s",
133 rtl::OUStringToOString( evt
.MethodName
,
134 RTL_TEXTENCODING_UTF8
).getStr() );
136 OSL_TRACE("dumpEvent: arguments;");
137 sal_Int32 nLen
= evt
.Arguments
.getLength();
138 for ( sal_Int32 index
=0; index
< nLen
; ++index
)
140 OSL_TRACE("\t [%d] %s", index
,
141 rtl::OUStringToOString( comphelper::anyToString( evt
.Arguments
[ index
] ),
142 RTL_TEXTENCODING_UTF8
).getStr() );
149 bool isKeyEventOk( awt::KeyEvent
& evt
, const Sequence
< Any
>& params
)
151 if ( !( params
.getLength() > 0 ) ||
152 !( params
[ 0 ] >>= evt
) )
157 bool isMouseEventOk( awt::MouseEvent
& evt
, const Sequence
< Any
>& params
)
159 if ( !( params
.getLength() > 0 ) ||
160 !( params
[ 0 ] >>= evt
) )
165 Sequence
< Any
> ooMouseEvtToVBADblClick( const Sequence
< Any
>& params
)
167 Sequence
< Any
> translatedParams
;
170 if ( !( isMouseEventOk(evt
, params
)) ||
171 (evt
.ClickCount
!= 2) )
172 return Sequence
< Any
>();
173 // give back orig params, this will signal that the event is good
177 Sequence
< Any
> ooMouseEvtToVBAMouseEvt( const Sequence
< Any
>& params
)
179 Sequence
< Any
> translatedParams
;
182 if ( !isMouseEventOk(evt
, params
) )
183 return Sequence
< Any
>();
185 translatedParams
.realloc(4);
188 translatedParams
[ 0 ] <<= evt
.Buttons
;
190 translatedParams
[ 1 ] <<= evt
.Modifiers
;
192 translatedParams
[ 2 ] <<= evt
.X
;
194 translatedParams
[ 3 ] <<= evt
.Y
;
195 return translatedParams
;
198 Sequence
< Any
> ooKeyPressedToVBAKeyPressed( const Sequence
< Any
>& params
)
200 Sequence
< Any
> translatedParams
;
203 if ( !isKeyEventOk( evt
, params
) )
204 return Sequence
< Any
>();
206 translatedParams
.realloc(1);
208 msforms::ReturnInteger keyCode
;
209 keyCode
.Value
= evt
.KeyCode
;
210 translatedParams
[0] <<= keyCode
;
211 return translatedParams
;
214 Sequence
< Any
> ooKeyPressedToVBAKeyUpDown( const Sequence
< Any
>& params
)
216 Sequence
< Any
> translatedParams
;
219 if ( !isKeyEventOk( evt
, params
) )
220 return Sequence
< Any
>();
222 translatedParams
.realloc(2);
224 msforms::ReturnInteger keyCode
;
225 sal_Int8 shift
= evt
.Modifiers
;
227 // #TODO check whether values from OOO conform to values generated from vba
228 keyCode
.Value
= evt
.KeyCode
;
229 translatedParams
[0] <<= keyCode
;
230 translatedParams
[1] <<= shift
;
231 return translatedParams
;
234 typedef Sequence
< Any
> (*Translator
)(const Sequence
< Any
>&);
237 //expand the "TranslateInfo" struct to support more kinds of events
240 rtl::OUString sVBAName
; //vba event name
241 Translator toVBA
; //the method to convert OO event parameters to VBA event parameters
242 bool (*ApproveRule
)(const ScriptEvent
& evt
, void* pPara
); //this method is used to determine which types of controls should execute the event
243 void *pPara
; //Parameters for the above approve method
247 typedef std::hash_map
< rtl::OUString
,
248 std::list
< TranslateInfo
>,
250 ::std::equal_to
< ::rtl::OUString
> > EventInfoHash
;
253 struct TranslatePropMap
255 rtl::OUString sEventInfo
; //OO event name
256 TranslateInfo aTransInfo
;
259 bool ApproveAll(const ScriptEvent
& evt
, void* pPara
); //allow all types of controls to execute the event
260 bool ApproveType(const ScriptEvent
& evt
, void* pPara
); //certain types of controls should execute the event, those types are given by pPara
261 bool DenyType(const ScriptEvent
& evt
, void* pPara
); //certain types of controls should not execute the event, those types are given by pPara
262 bool DenyMouseDrag(const ScriptEvent
& evt
, void* pPara
); //used for VBA MouseMove event when "Shift" key is pressed
266 uno::Type
* pTypeList
;
270 Type typeXFixedText
= GET_TYPE(awt::XFixedText
);
271 Type typeXTextComponent
= GET_TYPE(awt::XTextComponent
);
272 Type typeXComboBox
= GET_TYPE(awt::XComboBox
);
273 Type typeXRadioButton
= GET_TYPE(awt::XRadioButton
);
276 TypeList fixedTextList
= {&typeXFixedText
, 1};
277 TypeList textCompList
= {&typeXTextComponent
, 1};
278 TypeList radioButtonList
= {&typeXRadioButton
, 1};
279 TypeList comboBoxList
= {&typeXComboBox
, 1};
281 //this array stores the OO event to VBA event translation info
282 static TranslatePropMap aTranslatePropMap_Impl
[] =
284 // actionPerformed ooo event
285 { MAP_CHAR_LEN("actionPerformed"), { MAP_CHAR_LEN("_Click"), NULL
, ApproveAll
, NULL
} },
286 { MAP_CHAR_LEN("actionPerformed"), { MAP_CHAR_LEN("_Change"), NULL
, DenyType
, (void*)(&radioButtonList
) } }, //liuchen 2009-7-30, OptionalButton_Change event is not the same as OptionalButton_Click event
288 // itemStateChanged ooo event
289 { MAP_CHAR_LEN("itemStateChanged"), { MAP_CHAR_LEN("_Click"), NULL
, ApproveType
, (void*)(&comboBoxList
) } }, //liuchen, add to support VBA ComboBox_Click event
290 { MAP_CHAR_LEN("itemStateChanged"), { MAP_CHAR_LEN("_Change"), NULL
, ApproveType
, (void*)(&radioButtonList
) } }, //liuchen 2009-7-30, OptionalButton_Change event should be triggered when the button state is changed
293 { MAP_CHAR_LEN("changed"), { MAP_CHAR_LEN("_Change"), NULL
, ApproveAll
, NULL
} },
295 // focusGained ooo event
296 { MAP_CHAR_LEN("focusGained"), { MAP_CHAR_LEN("_GotFocus"), NULL
, ApproveAll
, NULL
} },
298 // focusLost ooo event
299 { MAP_CHAR_LEN("focusLost"), { MAP_CHAR_LEN("_LostFocus"), NULL
, ApproveAll
, NULL
} },
300 { MAP_CHAR_LEN("focusLost"), { MAP_CHAR_LEN("_Exit"), NULL
, ApproveType
, (void*)(&textCompList
) } }, //liuchen, add to support VBA TextBox_Exit event
302 // adjustmentValueChanged ooo event
303 { MAP_CHAR_LEN("adjustmentValueChanged"), { MAP_CHAR_LEN("_Scroll"), NULL
, ApproveAll
, NULL
} },
304 { MAP_CHAR_LEN("adjustmentValueChanged"), { MAP_CHAR_LEN("_Change"), NULL
, ApproveAll
, NULL
} },
306 // textChanged ooo event
307 { MAP_CHAR_LEN("textChanged"), { MAP_CHAR_LEN("_Change"), NULL
, ApproveAll
, NULL
} },
309 // keyReleased ooo event
310 { MAP_CHAR_LEN("keyReleased"), { MAP_CHAR_LEN("_KeyUp"), ooKeyPressedToVBAKeyUpDown
, ApproveAll
, NULL
} },
312 // mouseReleased ooo event
313 { MAP_CHAR_LEN("mouseReleased"), { MAP_CHAR_LEN("_Click"), ooMouseEvtToVBAMouseEvt
, ApproveType
, (void*)(&fixedTextList
) } }, //liuchen, add to support VBA Label_Click event
314 { MAP_CHAR_LEN("mouseReleased"), { MAP_CHAR_LEN("_MouseUp"), ooMouseEvtToVBAMouseEvt
, ApproveAll
, NULL
} },
316 // mousePressed ooo event
317 { MAP_CHAR_LEN("mousePressed"), { MAP_CHAR_LEN("_MouseDown"), ooMouseEvtToVBAMouseEvt
, ApproveAll
, NULL
} },
318 { MAP_CHAR_LEN("mousePressed"), { MAP_CHAR_LEN("_DblClick"), ooMouseEvtToVBADblClick
, ApproveAll
, NULL
} },
320 // mouseMoved ooo event
321 { MAP_CHAR_LEN("mouseMoved"), { MAP_CHAR_LEN("_MouseMove"), ooMouseEvtToVBAMouseEvt
, ApproveAll
, NULL
} },
322 { MAP_CHAR_LEN("mouseDragged"), { MAP_CHAR_LEN("_MouseMove"), ooMouseEvtToVBAMouseEvt
, DenyMouseDrag
, NULL
} }, //liuchen, add to support VBA MouseMove event when the "Shift" key is pressed
324 // keyPressed ooo event
325 { MAP_CHAR_LEN("keyPressed"), { MAP_CHAR_LEN("_KeyDown"), ooKeyPressedToVBAKeyUpDown
, ApproveAll
, NULL
} },
326 { MAP_CHAR_LEN("keyPressed"), { MAP_CHAR_LEN("_KeyPress"), ooKeyPressedToVBAKeyUpDown
, ApproveAll
, NULL
} }
329 EventInfoHash
& getEventTransInfo()
331 static bool initialised
= false;
332 static EventInfoHash eventTransInfo
;
335 rtl::OUString sEventInfo
= MAP_CHAR_LEN("");
336 TranslatePropMap
* pTransProp
= aTranslatePropMap_Impl
;
338 int nCount
= sizeof(aTranslatePropMap_Impl
) / sizeof(aTranslatePropMap_Impl
[0]);
343 if (sEventInfo
!= pTransProp
->sEventInfo
)
345 sEventInfo
= pTransProp
->sEventInfo
;
346 std::list
< TranslateInfo
> infoList
;
349 infoList
.push_back( pTransProp
->aTransInfo
);
353 while( ( i
< nCount
) && ( sEventInfo
== pTransProp
->sEventInfo
) );
354 eventTransInfo
[sEventInfo
] = infoList
;
359 return eventTransInfo
;
361 //liuchen 2009-6-23 end
365 class ScriptEventHelper
368 ScriptEventHelper( const Reference
< XInterface
>& xControl
);
369 Sequence
< ScriptEventDescriptor
> createEvents( const rtl::OUString
& sCodeName
);
370 Sequence
< rtl::OUString
> getEventListeners();
372 Reference
< XComponentContext
> m_xCtx
;
373 Reference
< XInterface
> m_xControl
;
377 eventMethodToDescriptor( const ::rtl::OUString
& rEventMethod
, ScriptEventDescriptor
& evtDesc
, const ::rtl::OUString
& sCodeName
)
379 // format of ControlListener is TypeName::methodname e.g.
380 // "com.sun.star.awt.XActionListener::actionPerformed" or
381 // "XActionListener::actionPerformed
383 ::rtl::OUString sMethodName
;
384 ::rtl::OUString sTypeName
;
385 sal_Int32 nDelimPos
= rEventMethod
.indexOf( DELIM
);
386 if ( nDelimPos
== -1 )
390 sMethodName
= rEventMethod
.copy( nDelimPos
+ DELIMLEN
);
391 sTypeName
= rEventMethod
.copy( 0, nDelimPos
);
393 EventInfoHash
& infos
= getEventTransInfo();
395 // Only create an ScriptEventDescriptor for an event we can translate
397 if ( sMethodName
.getLength()
398 && sTypeName
.getLength()
399 && ( infos
.find( sMethodName
) != infos
.end() ) )
401 // just fill in CodeName, when the event fires the other
402 // info is gathered from the event source to determine what
403 // event handler we try to call
404 evtDesc
.ScriptCode
= sCodeName
;
405 evtDesc
.ListenerType
= sTypeName
;
406 evtDesc
.EventMethod
= sMethodName
;
408 // set this it VBAInterop, ensures that it doesn't
409 // get persisted or shown in property editors
410 evtDesc
.ScriptType
= rtl::OUString::createFromAscii(
418 ScriptEventHelper::ScriptEventHelper( const Reference
< XInterface
>& xControl
) : m_xControl( xControl
)
420 Reference
< beans::XPropertySet
> xProps(
421 ::comphelper::getProcessServiceFactory(), UNO_QUERY_THROW
);
422 m_xCtx
.set( xProps
->getPropertyValue( rtl::OUString(
423 RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))),
424 uno::UNO_QUERY_THROW
);
427 Sequence
< rtl::OUString
>
428 ScriptEventHelper::getEventListeners()
430 Reference
< lang::XMultiComponentFactory
> xMFac(
431 m_xCtx
->getServiceManager(), UNO_QUERY
);
432 std::list
< rtl::OUString
> eventMethods
;
436 Reference
< beans::XIntrospection
> xIntrospection(
437 xMFac
->createInstanceWithContext( rtl::OUString(
438 RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.beans.Introspection" ) ), m_xCtx
), UNO_QUERY
);
440 dumpListeners( xIntrospection
, m_xControl
);
441 dumpListeners( xIntrospection
, m_xControl
->getModel() );
443 Reference
< beans::XIntrospectionAccess
> xIntrospectionAccess
;
444 if ( xIntrospection
.is() )
446 xIntrospectionAccess
= xIntrospection
->inspect(
447 makeAny( m_xControl
) );
448 Sequence
< Type
> aControlListeners
=
449 xIntrospectionAccess
->getSupportedListeners();
450 sal_Int32 nLength
= aControlListeners
.getLength();
451 for ( sal_Int32 i
= 0; i
< nLength
; ++i
)
453 Type
& listType
= aControlListeners
[ i
];
454 rtl::OUString sFullTypeName
= listType
.getTypeName();
455 Sequence
< ::rtl::OUString
> sMeths
=
456 comphelper::getEventMethodsForType( listType
);
457 sal_Int32 sMethLen
= sMeths
.getLength();
458 for ( sal_Int32 j
=0 ; j
< sMethLen
; ++j
)
460 rtl::OUString sEventMethod
= sFullTypeName
;
461 sEventMethod
+= DELIM
;
462 sEventMethod
+= sMeths
[ j
];
463 eventMethods
.push_back( sEventMethod
);
470 Sequence
< rtl::OUString
> sEventMethodNames( eventMethods
.size() );
471 std::list
< rtl::OUString
>::const_iterator it
= eventMethods
.begin();
472 rtl::OUString
* pDest
= sEventMethodNames
.getArray();
474 for ( ; it
!= eventMethods
.end(); ++it
, ++pDest
)
477 return sEventMethodNames
;
480 Sequence
< ScriptEventDescriptor
>
481 ScriptEventHelper::createEvents( const rtl::OUString
& sCodeName
)
483 Sequence
< rtl::OUString
> aControlListeners
= getEventListeners();
484 rtl::OUString
* pSrc
= aControlListeners
.getArray();
485 sal_Int32 nLength
= aControlListeners
.getLength();
487 Sequence
< ScriptEventDescriptor
> aDest( nLength
);
489 for ( sal_Int32 i
= 0; i
< nLength
; ++i
, ++pSrc
)
491 // from getListeners eventName is of form
492 // "com.sun.star.awt.XActionListener::actionPerformed"
493 // we need to strip "com.sun.star.awt." from that for form
495 ScriptEventDescriptor evtDesc
;
496 if ( eventMethodToDescriptor( *pSrc
, evtDesc
, sCodeName
) )
498 sal_Int32 dIndex
= nEvts
;
500 if ( nEvts
> aDest
.getLength() )
501 aDest
.realloc( nEvts
);// should never happen
502 aDest
[ dIndex
] = evtDesc
;
505 aDest
.realloc( nEvts
);
511 typedef ::cppu::WeakImplHelper1
< container::XNameContainer
> NameContainer_BASE
;
513 class ReadOnlyEventsNameContainer
: public NameContainer_BASE
516 ReadOnlyEventsNameContainer( const Sequence
< rtl::OUString
>& eventMethods
, const rtl::OUString
& sCodeName
);
519 virtual void SAL_CALL
insertByName( const ::rtl::OUString
&, const Any
& ) throw (lang::IllegalArgumentException
, container::ElementExistException
, lang::WrappedTargetException
, RuntimeException
)
521 throw RuntimeException( rtl::OUString::createFromAscii( "ReadOnly container" ), Reference
< XInterface
>() );
524 virtual void SAL_CALL
removeByName( const ::rtl::OUString
& ) throw (::com::sun::star::container::NoSuchElementException
, lang::WrappedTargetException
, RuntimeException
)
526 throw RuntimeException( rtl::OUString::createFromAscii( "ReadOnly container" ), Reference
< XInterface
>() );
530 virtual void SAL_CALL
replaceByName( const ::rtl::OUString
&, const Any
& ) throw (lang::IllegalArgumentException
, container::NoSuchElementException
, lang::WrappedTargetException
, RuntimeException
)
532 throw RuntimeException( rtl::OUString::createFromAscii( "ReadOnly container" ), Reference
< XInterface
>() );
537 virtual Any SAL_CALL
getByName( const ::rtl::OUString
& aName
) throw (container::NoSuchElementException
, lang::WrappedTargetException
, RuntimeException
);
538 virtual Sequence
< ::rtl::OUString
> SAL_CALL
getElementNames( ) throw (RuntimeException
);
539 virtual ::sal_Bool SAL_CALL
hasByName( const ::rtl::OUString
& aName
) throw (RuntimeException
);
542 virtual Type SAL_CALL
getElementType( ) throw (RuntimeException
)
543 { return getCppuType(static_cast< const rtl::OUString
* >(0) ); }
544 virtual ::sal_Bool SAL_CALL
hasElements( ) throw (RuntimeException
)
545 { return ( ( m_hEvents
.size() > 0 ? sal_True
: sal_False
) ); }
548 typedef std::hash_map
< rtl::OUString
, Any
, ::rtl::OUStringHash
,
549 ::std::equal_to
< ::rtl::OUString
> > EventSupplierHash
;
551 EventSupplierHash m_hEvents
;
554 ReadOnlyEventsNameContainer::ReadOnlyEventsNameContainer( const Sequence
< rtl::OUString
>& eventMethods
, const rtl::OUString
& sCodeName
)
556 const rtl::OUString
* pSrc
= eventMethods
.getConstArray();
557 sal_Int32 nLen
= eventMethods
.getLength();
558 for ( sal_Int32 index
= 0; index
< nLen
; ++index
, ++pSrc
)
561 ScriptEventDescriptor evtDesc
;
562 if ( eventMethodToDescriptor( *pSrc
, evtDesc
, sCodeName
) )
565 m_hEvents
[ *pSrc
] = aDesc
;
571 ReadOnlyEventsNameContainer::getByName( const ::rtl::OUString
& aName
) throw (container::NoSuchElementException
, lang::WrappedTargetException
, RuntimeException
){
572 EventSupplierHash::const_iterator it
= m_hEvents
.find( aName
);
573 if ( it
== m_hEvents
.end() )
574 throw container::NoSuchElementException();
578 Sequence
< ::rtl::OUString
> SAL_CALL
579 ReadOnlyEventsNameContainer::getElementNames( ) throw (RuntimeException
)
581 Sequence
< ::rtl::OUString
> names(m_hEvents
.size());
582 rtl::OUString
* pDest
= names
.getArray();
583 EventSupplierHash::const_iterator it
= m_hEvents
.begin();
584 EventSupplierHash::const_iterator it_end
= m_hEvents
.end();
585 for ( sal_Int32 index
= 0; it
!= it_end
; ++index
, ++pDest
, ++it
)
591 ReadOnlyEventsNameContainer::hasByName( const ::rtl::OUString
& aName
) throw (RuntimeException
)
593 EventSupplierHash::const_iterator it
= m_hEvents
.find( aName
);
594 if ( it
== m_hEvents
.end() )
599 typedef ::cppu::WeakImplHelper1
< XScriptEventsSupplier
> EventsSupplier_BASE
;
601 class ReadOnlyEventsSupplier
: public EventsSupplier_BASE
604 ReadOnlyEventsSupplier( const Sequence
< ::rtl::OUString
>& eventMethods
, const rtl::OUString
& sCodeName
)
605 { m_xNameContainer
= new ReadOnlyEventsNameContainer( eventMethods
, sCodeName
); }
607 // XScriptEventSupplier
608 virtual Reference
< container::XNameContainer
> SAL_CALL
getEvents( ) throw (RuntimeException
){ return m_xNameContainer
; }
610 Reference
< container::XNameContainer
> m_xNameContainer
;
613 typedef ::cppu::WeakImplHelper2
< XScriptListener
, lang::XInitialization
> EventListener_BASE
;
615 #define EVENTLSTNR_PROPERTY_ID_MODEL 1
616 #define EVENTLSTNR_PROPERTY_MODEL ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Model" ) )
618 class EventListener
: public EventListener_BASE
619 ,public ::comphelper::OMutexAndBroadcastHelper
620 ,public ::comphelper::OPropertyContainer
621 ,public ::comphelper::OPropertyArrayUsageHelper
< EventListener
>
626 EventListener( const Reference
< XComponentContext
>& rxContext
);
628 virtual void SAL_CALL
disposing(const lang::EventObject
& Source
) throw( RuntimeException
);
631 virtual void SAL_CALL
firing(const ScriptEvent
& evt
) throw(RuntimeException
);
632 virtual Any SAL_CALL
approveFiring(const ScriptEvent
& evt
) throw(reflection::InvocationTargetException
, RuntimeException
);
634 virtual ::com::sun::star::uno::Reference
< ::com::sun::star::beans::XPropertySetInfo
> SAL_CALL
getPropertySetInfo( ) throw (::com::sun::star::uno::RuntimeException
);
636 virtual void SAL_CALL
initialize( const Sequence
< Any
>& aArguments
) throw (Exception
, RuntimeException
);
641 DECLARE_XTYPEPROVIDER()
642 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
)
644 OPropertyContainer::setFastPropertyValue( nHandle
, rValue
);
645 if ( nHandle
== EVENTLSTNR_PROPERTY_ID_MODEL
)
650 // OPropertySetHelper
651 virtual ::cppu::IPropertyArrayHelper
& SAL_CALL
getInfoHelper( );
653 // OPropertyArrayUsageHelper
654 virtual ::cppu::IPropertyArrayHelper
* createArrayHelper( ) const;
658 DECL_LINK( OnAsyncScriptEvent
, ScriptEvent
* );
660 void setShellFromModel();
661 void firing_Impl( const ScriptEvent
& evt
, Any
*pSyncRet
=NULL
) throw( RuntimeException
);
663 Reference
< XComponentContext
> m_xContext
;
664 Reference
< frame::XModel
> m_xModel
;
665 SfxObjectShell
* mpShell
;
669 EventListener::EventListener( const Reference
< XComponentContext
>& rxContext
) :
670 OPropertyContainer(GetBroadcastHelper()), m_xContext( rxContext
), mpShell( 0 )
672 registerProperty( EVENTLSTNR_PROPERTY_MODEL
, EVENTLSTNR_PROPERTY_ID_MODEL
,
673 beans::PropertyAttribute::TRANSIENT
, &m_xModel
, ::getCppuType( &m_xModel
) );
678 EventListener::setShellFromModel()
682 SfxObjectShell
* pShell
= SfxObjectShell::GetFirst();
683 while ( m_xModel
.is() && pShell
)
685 if ( pShell
->GetModel() == m_xModel
)
690 pShell
= SfxObjectShell::GetNext( *pShell
);
696 EventListener::disposing(const lang::EventObject
&) throw( RuntimeException
)
703 EventListener::firing(const ScriptEvent
& evt
) throw(RuntimeException
)
706 // needs some logic to check if the event handler is oneway or not
707 // if not oneway then firing_Impl otherwise... as below
709 Application::PostUserEvent( LINK( this, EventListener
, OnAsyncScriptEvent
), new ScriptEvent( evt
) );
716 IMPL_LINK( EventListener
, OnAsyncScriptEvent
, ScriptEvent
*, _pEvent
)
722 // #FIXME if we enable ASYNC we probably need something like
724 //::osl::ClearableMutexGuard aGuard( m_aMutex );
726 //if ( !impl_isDisposed_nothrow() )
727 // impl_doFireScriptEvent_nothrow( aGuard, *_pEvent, NULL );
728 firing_Impl( *_pEvent
, NULL
);
732 // we acquired ourself immediately before posting the event
739 EventListener::approveFiring(const ScriptEvent
& evt
) throw(reflection::InvocationTargetException
, RuntimeException
)
742 firing_Impl( evt
, &ret
);
748 EventListener::initialize( const Sequence
< Any
>& aArguments
) throw (Exception
, RuntimeException
)
750 if ( aArguments
.getLength() == 1 )
751 aArguments
[0] >>= m_xModel
;
752 OSL_TRACE("EventListener::initialize() args %d m_xModel %d", aArguments
.getLength(), m_xModel
.is() );
757 IMPLEMENT_FORWARD_XINTERFACE2( EventListener
, EventListener_BASE
, OPropertyContainer
)
761 IMPLEMENT_FORWARD_XTYPEPROVIDER2( EventListener
, EventListener_BASE
, OPropertyContainer
)
763 // OPropertySetHelper
765 ::cppu::IPropertyArrayHelper
&
766 EventListener::getInfoHelper( )
768 return *getArrayHelper();
771 // OPropertyArrayUsageHelper
773 ::cppu::IPropertyArrayHelper
*
774 EventListener::createArrayHelper( ) const
776 Sequence
< beans::Property
> aProps
;
777 describeProperties( aProps
);
778 return new ::cppu::OPropertyArrayHelper( aProps
);
782 Reference
< beans::XPropertySetInfo
>
783 EventListener::getPropertySetInfo( ) throw (RuntimeException
)
785 Reference
< beans::XPropertySetInfo
> xInfo( createPropertySetInfo( getInfoHelper() ) );
790 //decide if the control should execute the event
791 bool ApproveAll(const ScriptEvent
& evt
, void* pPara
)
796 //for the given control type in evt.Arguments[0], look for if it appears in the type list in pPara
797 bool FindControl(const ScriptEvent
& evt
, void* pPara
)
799 lang::EventObject aEvent
;
800 evt
.Arguments
[ 0 ] >>= aEvent
;
801 uno::Reference
< uno::XInterface
> xInterface( aEvent
.Source
, uno::UNO_QUERY
);
803 TypeList
* pTypeListInfo
= static_cast<TypeList
*>(pPara
);
804 Type
* pType
= pTypeListInfo
->pTypeList
;
805 int nLen
= pTypeListInfo
->nListLength
;
807 for (int i
= 0; i
< nLen
; i
++)
809 if ( xInterface
->queryInterface( *pType
).hasValue() )
819 //if the the given control type in evt.Arguments[0] appears in the type list in pPara, then approve the execution
820 bool ApproveType(const ScriptEvent
& evt
, void* pPara
)
822 return FindControl(evt
, pPara
);
825 //if the the given control type in evt.Arguments[0] appears in the type list in pPara, then deny the execution
826 bool DenyType(const ScriptEvent
& evt
, void* pPara
)
828 return !FindControl(evt
, pPara
);
831 //when mouse is moving, either the mouse button is pressed or some key is pressed can trigger the OO mouseDragged event,
832 //the former should be denyed, and the latter allowed, only by doing so can the VBA MouseMove event when the "Shift" key is
833 //pressed can be correctly triggered
834 bool DenyMouseDrag(const ScriptEvent
& evt
, void* pPara
)
836 awt::MouseEvent aEvent
;
837 evt
.Arguments
[ 0 ] >>= aEvent
;
838 if (aEvent
.Buttons
== 0 )
854 EventListener::firing_Impl(const ScriptEvent
& evt
, Any
* pRet
) throw(RuntimeException
)
856 OSL_TRACE("EventListener::firing_Impl( FAKE VBA_EVENTS )");
857 static const ::rtl::OUString vbaInterOp
=
858 ::rtl::OUString::createFromAscii("VBAInterop");
860 // let default handlers deal with non vba stuff
861 if ( !evt
.ScriptType
.equals( vbaInterOp
) )
863 lang::EventObject aEvent
;
864 evt
.Arguments
[ 0 ] >>= aEvent
;
865 OSL_TRACE("evt.MethodName is %s", rtl::OUStringToOString( evt
.MethodName
, RTL_TEXTENCODING_UTF8
).getStr() );
866 OSL_TRACE("Argument[0] is %s", rtl::OUStringToOString( comphelper::anyToString( evt
.Arguments
[0] ), RTL_TEXTENCODING_UTF8
).getStr() );
867 OSL_TRACE("Getting Control");
868 uno::Reference
< awt::XControl
> xControl( aEvent
.Source
, uno::UNO_QUERY_THROW
);
869 OSL_TRACE("Getting properties");
870 uno::Reference
< beans::XPropertySet
> xProps( xControl
->getModel(), uno::UNO_QUERY_THROW
);
872 rtl::OUString sName
= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("UserForm") );
873 OSL_TRACE("Getting Name");
875 uno::Reference
< awt::XDialog
> xDlg( aEvent
.Source
, uno::UNO_QUERY
);
877 xProps
->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Name") ) ) >>= sName
;
879 EventInfoHash
& infos
= getEventTransInfo();
880 EventInfoHash::const_iterator eventInfo_it
= infos
.find( evt
.MethodName
);
881 EventInfoHash::const_iterator it_end
= infos
.end();
882 if ( eventInfo_it
== it_end
)
884 OSL_TRACE("Bogus event for %s",
885 rtl::OUStringToOString( evt
.ScriptType
, RTL_TEXTENCODING_UTF8
).getStr() );
889 uno::Reference
< script::provider::XScriptProviderSupplier
> xSPS( m_xModel
, uno::UNO_QUERY
);
890 uno::Reference
< script::provider::XScriptProvider
> xScriptProvider
;
892 xScriptProvider
= xSPS
->getScriptProvider();
893 if ( xScriptProvider
.is() && mpShell
)
895 std::list
< TranslateInfo
> matchingMethods
;
896 std::list
< TranslateInfo
>::const_iterator txInfo
=
897 eventInfo_it
->second
.begin();
898 std::list
< TranslateInfo
>::const_iterator txInfo_end
= eventInfo_it
->second
.end();
900 StarBASIC
* pBasic
= mpShell
->GetBasic();
901 BasicManager
* pBasicManager
= mpShell
->GetBasicManager();
902 rtl::OUString sProject
;
903 rtl::OUString
sScriptCode( evt
.ScriptCode
);
904 // dialogs pass their own library, presence of Dot determines that
905 if ( sScriptCode
.indexOf( '.' ) == -1 )
907 //'Project' is a better default but I want to force failures
908 //rtl::OUString sMacroLoc = rtl::OUString::createFromAscii("Project");
909 sProject
= rtl::OUString::createFromAscii("Standard");
911 if ( pBasicManager
->GetName().Len() > 0 )
912 sProject
= pBasicManager
->GetName();
916 sal_Int32 nIndex
= sScriptCode
.indexOf( '.' );
917 sProject
= sScriptCode
.copy( 0, nIndex
);
918 sScriptCode
= sScriptCode
.copy( nIndex
+ 1 );
920 rtl::OUString sMacroLoc
= sProject
;
921 sMacroLoc
= sMacroLoc
.concat( rtl::OUString::createFromAscii(".") );
922 sMacroLoc
= sMacroLoc
.concat( sScriptCode
).concat( rtl::OUString::createFromAscii(".") );
924 OSL_TRACE("sMacroLoc is %s", rtl::OUStringToOString( sMacroLoc
, RTL_TEXTENCODING_UTF8
).getStr() );
925 for ( ; txInfo
!= txInfo_end
; ++txInfo
)
927 rtl::OUString sTemp
= sName
.concat( (*txInfo
).sVBAName
);
928 // see if we have a match for the handlerextension
929 // where ScriptCode is methodname_handlerextension
930 rtl::OUString sToResolve
= sMacroLoc
.concat( sTemp
);
931 OSL_TRACE("*** trying to invoke %s ",
932 rtl::OUStringToOString( sToResolve
, RTL_TEXTENCODING_UTF8
).getStr() );
933 ooo::vba::VBAMacroResolvedInfo aMacroResolvedInfo
= ooo::vba::resolveVBAMacro( mpShell
, sToResolve
);
934 if ( aMacroResolvedInfo
.IsResolved() )
937 if (! txInfo
->ApproveRule(evt
, txInfo
->pPara
) )
942 // !! translate arguments & emulate events where necessary
943 Sequence
< Any
> aArguments
;
944 if ( (*txInfo
).toVBA
)
945 aArguments
= (*txInfo
).toVBA( evt
.Arguments
);
947 aArguments
= evt
.Arguments
;
948 if ( aArguments
.getLength() )
950 // call basic event handlers for event
953 rtl::OUString url
= aMacroResolvedInfo
.ResolvedMacro();
955 OSL_TRACE("resolved script = %s",
956 rtl::OUStringToOString( url
,
957 RTL_TEXTENCODING_UTF8
).getStr() );
960 uno::Any aDummyCaller
= uno::makeAny( rtl::OUString::createFromAscii("Error") );
962 ooo::vba::executeMacro( mpShell
, url
, aArguments
, *pRet
, aDummyCaller
);
966 ooo::vba::executeMacro( mpShell
, url
, aArguments
, aRet
, aDummyCaller
);
969 catch ( uno::Exception
& e
)
971 OSL_TRACE("event script raised %s", rtl::OUStringToOString( e
.Message
, RTL_TEXTENCODING_UTF8
).getStr() );
979 typedef ::cppu::WeakImplHelper1
< XVBAToOOEventDescGen
> VBAToOOEventDescGen_BASE
;
982 class VBAToOOEventDescGen
: public VBAToOOEventDescGen_BASE
985 VBAToOOEventDescGen( const Reference
< XComponentContext
>& rxContext
);
987 // XVBAToOOEventDescGen
988 virtual Sequence
< ScriptEventDescriptor
> SAL_CALL
getEventDescriptions( const Reference
< XInterface
>& control
, const rtl::OUString
& sCodeName
) throw (RuntimeException
);
989 virtual Reference
< XScriptEventsSupplier
> SAL_CALL
getEventSupplier( const Reference
< XInterface
>& xControl
, const rtl::OUString
& sCodeName
) throw (::com::sun::star::uno::RuntimeException
);
991 Reference
< XComponentContext
> m_xContext
;
995 VBAToOOEventDescGen::VBAToOOEventDescGen( const Reference
< XComponentContext
>& rxContext
):m_xContext( rxContext
) {}
997 Sequence
< ScriptEventDescriptor
> SAL_CALL
998 VBAToOOEventDescGen::getEventDescriptions( const Reference
< XInterface
>& xControl
, const rtl::OUString
& sCodeName
) throw (RuntimeException
)
1000 ScriptEventHelper
evntHelper( xControl
);
1001 return evntHelper
.createEvents( sCodeName
);
1004 Reference
< XScriptEventsSupplier
> SAL_CALL
1005 VBAToOOEventDescGen::getEventSupplier( const Reference
< XInterface
>& xControl
, const rtl::OUString
& sCodeName
) throw (::com::sun::star::uno::RuntimeException
)
1007 ScriptEventHelper
evntHelper( xControl
);
1008 Reference
< XScriptEventsSupplier
> xSupplier
=
1009 new ReadOnlyEventsSupplier(
1010 evntHelper
.getEventListeners(), sCodeName
) ;
1014 // Component related
1018 ::rtl::OUString SAL_CALL
getImplementationName()
1020 static ::rtl::OUString
* pImplName
= 0;
1023 ::osl::MutexGuard
aGuard( ::osl::Mutex::getGlobalMutex() );
1026 static ::rtl::OUString
aImplName( RTL_CONSTASCII_USTRINGPARAM( "ooo.vba.EventListener" ) );
1027 pImplName
= &aImplName
;
1033 uno::Reference
< XInterface
> SAL_CALL
create(
1034 Reference
< XComponentContext
> const & xContext
)
1037 return static_cast< lang::XTypeProvider
* >( new EventListener( xContext
) );
1040 Sequence
< ::rtl::OUString
> SAL_CALL
getSupportedServiceNames()
1042 const ::rtl::OUString
strName( ::evtlstner::getImplementationName() );
1043 return Sequence
< ::rtl::OUString
>( &strName
, 1 );
1046 namespace ooevtdescgen
1048 ::rtl::OUString SAL_CALL
getImplementationName()
1050 static ::rtl::OUString
* pImplName
= 0;
1053 ::osl::MutexGuard
aGuard( ::osl::Mutex::getGlobalMutex() );
1056 static ::rtl::OUString
aImplName( RTL_CONSTASCII_USTRINGPARAM( "ooo.vba.VBAToOOEventDesc" ) );
1057 pImplName
= &aImplName
;
1063 uno::Reference
< XInterface
> SAL_CALL
create(
1064 Reference
< XComponentContext
> const & xContext
)
1067 return static_cast< lang::XTypeProvider
* >( new VBAToOOEventDescGen( xContext
) );
1070 Sequence
< ::rtl::OUString
> SAL_CALL
getSupportedServiceNames()
1072 const ::rtl::OUString
strName( ::ooevtdescgen::getImplementationName() );
1073 return Sequence
< ::rtl::OUString
>( &strName
, 1 );