1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2008 by Sun Microsystems, Inc. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * $RCSfile: eventhelper.cxx,v $ 10 * $Revision: 1.0 $ 11 * 12 * This file is part of OpenOffice.org. 13 * 14 * OpenOffice.org is free software: you can redistribute it and/or modify 15 * it under the terms of the GNU Lesser General Public License version 3 16 * only, as published by the Free Software Foundation. 17 * 18 * OpenOffice.org is distributed in the hope that it will be useful, 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 * GNU Lesser General Public License version 3 for more details 22 * (a copy is included in the LICENSE file that accompanied this code). 23 * 24 * You should have received a copy of the GNU Lesser General Public License 25 * version 3 along with OpenOffice.org. If not, see 26 * <http://www.openoffice.org/license.html> 27 * for a copy of the LGPLv3 License. 28 * 29 ************************************************************************/ 30 31 // MARKER(update_precomp.py): autogen include statement, do not remove 32 #include "precompiled_scripting.hxx" 33 #include <comphelper/processfactory.hxx> 34 #include <comphelper/uno3.hxx> 35 #include <comphelper/proparrhlp.hxx> 36 #include <comphelper/propertycontainer.hxx> 37 38 #include <ooo/vba/XVBAToOOEventDescGen.hpp> 39 40 #include <com/sun/star/beans/XPropertySet.hpp> 41 #include <com/sun/star/beans/XIntrospection.hpp> 42 #include <com/sun/star/beans/PropertyAttribute.hpp> 43 44 #include <com/sun/star/lang/XMultiComponentFactory.hpp> 45 #include <com/sun/star/lang/XServiceName.hpp> 46 #include <com/sun/star/lang/XServiceInfo.hpp> 47 #include <com/sun/star/lang/XInitialization.hpp> 48 49 #include <com/sun/star/frame/XModel.hpp> 50 51 #include <com/sun/star/script/XLibraryContainer.hpp> 52 #include <com/sun/star/script/ScriptEventDescriptor.hpp> 53 #include <com/sun/star/script/provider/XScriptProviderSupplier.hpp> 54 55 #include <com/sun/star/drawing/XControlShape.hpp> 56 57 #include <com/sun/star/awt/XControl.hpp> 58 #include <com/sun/star/awt/XDialog.hpp> 59 #include <com/sun/star/awt/KeyEvent.hpp> 60 #include <com/sun/star/awt/MouseEvent.hpp> 61 #include <com/sun/star/awt/XFixedText.hpp> //liuchen 2009-6-5 62 #include <com/sun/star/awt/XTextComponent.hpp> //liuchen 2009-6-5 63 #include <com/sun/star/awt/XComboBox.hpp> //liuchen 2009-6-18 64 #include <com/sun/star/awt/XRadioButton.hpp> //liuchen 2009-7-30 65 66 #include <msforms/ReturnInteger.hpp> 67 68 #include <sfx2/objsh.hxx> 69 #include <basic/sbstar.hxx> 70 #include <basic/basmgr.hxx> 71 #include <basic/sbmeth.hxx> 72 #include <basic/sbmod.hxx> 73 #include <basic/sbx.hxx> 74 75 76 77 78 // for debug 79 #include <comphelper/anytostring.hxx> 80 81 82 #include <com/sun/star/lang/XMultiComponentFactory.hpp> 83 #include <com/sun/star/script/XScriptListener.hpp> 84 #include <cppuhelper/implbase1.hxx> 85 #include <cppuhelper/implbase2.hxx> 86 #include <comphelper/evtmethodhelper.hxx> 87 88 #include <set> 89 #include <list> 90 #include <hash_map> 91 92 using namespace ::com::sun::star; 93 using namespace ::com::sun::star::script; 94 using namespace ::com::sun::star::uno; 95 using namespace ::ooo::vba; 96 97 #define MAP_CHAR_LEN(x) ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(x))//liuchen 2009-6-8 98 #define GET_TYPE(x) ::getCppuType((uno::Reference< x > *)0); 99 100 // Some constants 101 const static rtl::OUString DELIM = rtl::OUString::createFromAscii( "::" ); 102 const static sal_Int32 DELIMLEN = DELIM.getLength(); 103 104 #if 0 105 void dumpListeners( const Reference< beans::XIntrospection >& xIntrospection, const Reference<XInterface>& xIfc) 106 { 107 Reference< beans::XIntrospectionAccess > xIntrospectionAccess; 108 if ( xIntrospection.is() ) 109 { 110 xIntrospectionAccess = xIntrospection->inspect( 111 makeAny( xIfc ) ); 112 Sequence< Type > aControlListeners = 113 xIntrospectionAccess->getSupportedListeners(); 114 sal_Int32 nLength = aControlListeners.getLength(); 115 116 for ( sal_Int32 i = 0; i< nLength; ++i ) 117 { 118 Type& listType = aControlListeners[ i ]; 119 rtl::OUString sFullTypeName = listType.getTypeName(); 120 rtl::OUString sTypeName = listType.getTypeName(); 121 sal_Int32 lastDotIndex = -1; 122 if ( ( lastDotIndex = sFullTypeName.lastIndexOf( '.' ) ) > -1 ) 123 { 124 sTypeName = sFullTypeName.copy( lastDotIndex + 1 ); 125 } 126 Sequence< ::rtl::OUString > sMeths = comphelper::getEventMethodsForType( listType ); 127 sal_Int32 sMethLen = sMeths.getLength(); 128 for ( sal_Int32 j=0 ; j < sMethLen; ++j ) 129 { 130 OSL_TRACE("**Listener [%d] Type[%s] Method[%s]",j, 131 rtl::OUStringToOString( sTypeName, 132 RTL_TEXTENCODING_UTF8 ).getStr(), 133 rtl::OUStringToOString( sMeths[ j ], 134 RTL_TEXTENCODING_UTF8 ).getStr() ); 135 } 136 } 137 138 } 139 } 140 141 void dumpEvent( const ScriptEvent& evt ) 142 { 143 OSL_TRACE("dumpEvent: Source %s", 144 rtl::OUStringToOString( comphelper::anyToString( makeAny(evt.Source)), 145 RTL_TEXTENCODING_UTF8 ).getStr() ); 146 147 OSL_TRACE("dumpEvent: ScriptType %s", 148 rtl::OUStringToOString( evt.ScriptType, 149 RTL_TEXTENCODING_UTF8 ).getStr() ); 150 151 OSL_TRACE("dumpEvent: ScriptCode %s", 152 rtl::OUStringToOString( evt.ScriptCode, 153 RTL_TEXTENCODING_UTF8 ).getStr() ); 154 155 OSL_TRACE("dumpEvent: ListenerType %s", 156 rtl::OUStringToOString( evt.ListenerType.getTypeName(), 157 RTL_TEXTENCODING_UTF8 ).getStr() ); 158 159 OSL_TRACE("dumpEvent: Listener methodname %s", 160 rtl::OUStringToOString( evt.MethodName, 161 RTL_TEXTENCODING_UTF8 ).getStr() ); 162 163 OSL_TRACE("dumpEvent: arguments;"); 164 sal_Int32 nLen = evt.Arguments.getLength(); 165 for ( sal_Int32 index=0; index < nLen; ++index ) 166 { 167 OSL_TRACE("\t [%d] %s", index, 168 rtl::OUStringToOString( comphelper::anyToString( evt.Arguments[ index ] ), 169 RTL_TEXTENCODING_UTF8 ).getStr() ); 170 171 } 172 } 173 174 #endif 175 176 bool isKeyEventOk( awt::KeyEvent& evt, const Sequence< Any >& params ) 177 { 178 if ( !( params.getLength() > 0 ) || 179 !( params[ 0 ] >>= evt ) ) 180 return false; 181 return true; 182 } 183 184 bool isMouseEventOk( awt::MouseEvent& evt, const Sequence< Any >& params ) 185 { 186 if ( !( params.getLength() > 0 ) || 187 !( params[ 0 ] >>= evt ) ) 188 return false; 189 return true; 190 } 191 192 Sequence< Any > ooMouseEvtToVBADblClick( const Sequence< Any >& params ) 193 { 194 Sequence< Any > translatedParams; 195 awt::MouseEvent evt; 196 197 if ( !( isMouseEventOk(evt, params)) || 198 (evt.ClickCount != 2) ) 199 return Sequence< Any >(); 200 // give back orig params, this will signal that the event is good 201 return params; 202 } 203 204 Sequence< Any > ooMouseEvtToVBAMouseEvt( const Sequence< Any >& params ) 205 { 206 Sequence< Any > translatedParams; 207 awt::MouseEvent evt; 208 209 if ( !isMouseEventOk(evt, params) ) 210 return Sequence< Any >(); 211 212 translatedParams.realloc(4); 213 214 // Buttons 215 translatedParams[ 0 ] <<= evt.Buttons; 216 // Shift 217 translatedParams[ 1 ] <<= evt.Modifiers; 218 // X 219 translatedParams[ 2 ] <<= evt.X; 220 // Y 221 translatedParams[ 3 ] <<= evt.Y; 222 return translatedParams; 223 } 224 225 Sequence< Any > ooKeyPressedToVBAKeyPressed( const Sequence< Any >& params ) 226 { 227 Sequence< Any > translatedParams; 228 awt::KeyEvent evt; 229 230 if ( !isKeyEventOk( evt, params ) ) 231 return Sequence< Any >(); 232 233 translatedParams.realloc(1); 234 235 msforms::ReturnInteger keyCode; 236 keyCode.Value = evt.KeyCode; 237 translatedParams[0] <<= keyCode; 238 return translatedParams; 239 } 240 241 Sequence< Any > ooKeyPressedToVBAKeyUpDown( const Sequence< Any >& params ) 242 { 243 Sequence< Any > translatedParams; 244 awt::KeyEvent evt; 245 246 if ( !isKeyEventOk( evt, params ) ) 247 return Sequence< Any >(); 248 249 translatedParams.realloc(2); 250 251 msforms::ReturnInteger keyCode; 252 sal_Int8 shift = sal::static_int_cast<sal_Int8>( evt.Modifiers ); 253 254 // #TODO check whether values from OOO conform to values generated from vba 255 keyCode.Value = evt.KeyCode; 256 translatedParams[0] <<= keyCode; 257 translatedParams[1] <<= shift; 258 return translatedParams; 259 } 260 261 typedef Sequence< Any > (*Translator)(const Sequence< Any >&); 262 263 //liuchen 2009-6-23 264 //expand the "TranslateInfo" struct to support more kinds of events 265 struct TranslateInfo 266 { 267 rtl::OUString sVBAName; //vba event name 268 Translator toVBA; //the method to convert OO event parameters to VBA event parameters 269 bool (*ApproveRule)(const ScriptEvent& evt, void* pPara); //this method is used to determine which types of controls should execute the event 270 void *pPara; //Parameters for the above approve method 271 }; 272 273 274 typedef std::hash_map< rtl::OUString, 275 std::list< TranslateInfo >, 276 ::rtl::OUStringHash, 277 ::std::equal_to< ::rtl::OUString > > EventInfoHash; 278 279 //liuchen 2009-6-23 280 struct TranslatePropMap 281 { 282 rtl::OUString sEventInfo; //OO event name 283 TranslateInfo aTransInfo; 284 }; 285 286 bool ApproveAll(const ScriptEvent& evt, void* pPara); //allow all types of controls to execute the event 287 bool ApproveType(const ScriptEvent& evt, void* pPara); //certain types of controls should execute the event, those types are given by pPara 288 bool DenyType(const ScriptEvent& evt, void* pPara); //certain types of controls should not execute the event, those types are given by pPara 289 bool DenyMouseDrag(const ScriptEvent& evt, void* pPara); //used for VBA MouseMove event when "Shift" key is pressed 290 291 struct TypeList 292 { 293 uno::Type* pTypeList; 294 int nListLength; 295 }; 296 297 Type typeXFixedText = GET_TYPE(awt::XFixedText) 298 Type typeXTextComponent = GET_TYPE(awt::XTextComponent) 299 Type typeXComboBox = GET_TYPE(awt::XComboBox) 300 Type typeXRadioButton = GET_TYPE(awt::XRadioButton) 301 302 303 TypeList fixedTextList = {&typeXFixedText, 1}; 304 TypeList textCompList = {&typeXTextComponent, 1}; 305 TypeList radioButtonList = {&typeXRadioButton, 1}; 306 TypeList comboBoxList = {&typeXComboBox, 1}; 307 308 //this array stores the OO event to VBA event translation info 309 static TranslatePropMap aTranslatePropMap_Impl[] = 310 { 311 // actionPerformed ooo event 312 { MAP_CHAR_LEN("actionPerformed"), { MAP_CHAR_LEN("_Click"), NULL, ApproveAll, NULL } }, 313 { 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 314 315 // itemStateChanged ooo event 316 { MAP_CHAR_LEN("itemStateChanged"), { MAP_CHAR_LEN("_Click"), NULL, ApproveType, (void*)(&comboBoxList) } }, //liuchen, add to support VBA ComboBox_Click event 317 { 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 318 319 // changed ooo event 320 { MAP_CHAR_LEN("changed"), { MAP_CHAR_LEN("_Change"), NULL, ApproveAll, NULL } }, 321 322 // focusGained ooo event 323 { MAP_CHAR_LEN("focusGained"), { MAP_CHAR_LEN("_GotFocus"), NULL, ApproveAll, NULL } }, 324 325 // focusLost ooo event 326 { MAP_CHAR_LEN("focusLost"), { MAP_CHAR_LEN("_LostFocus"), NULL, ApproveAll, NULL } }, 327 { MAP_CHAR_LEN("focusLost"), { MAP_CHAR_LEN("_Exit"), NULL, ApproveType, (void*)(&textCompList) } }, //liuchen, add to support VBA TextBox_Exit event 328 329 // adjustmentValueChanged ooo event 330 { MAP_CHAR_LEN("adjustmentValueChanged"), { MAP_CHAR_LEN("_Scroll"), NULL, ApproveAll, NULL } }, 331 { MAP_CHAR_LEN("adjustmentValueChanged"), { MAP_CHAR_LEN("_Change"), NULL, ApproveAll, NULL } }, 332 333 // textChanged ooo event 334 { MAP_CHAR_LEN("textChanged"), { MAP_CHAR_LEN("_Change"), NULL, ApproveAll, NULL } }, 335 336 // keyReleased ooo event 337 { MAP_CHAR_LEN("keyReleased"), { MAP_CHAR_LEN("_KeyUp"), ooKeyPressedToVBAKeyUpDown, ApproveAll, NULL } }, 338 339 // mouseReleased ooo event 340 { MAP_CHAR_LEN("mouseReleased"), { MAP_CHAR_LEN("_Click"), ooMouseEvtToVBAMouseEvt, ApproveType, (void*)(&fixedTextList) } }, //liuchen, add to support VBA Label_Click event 341 { MAP_CHAR_LEN("mouseReleased"), { MAP_CHAR_LEN("_MouseUp"), ooMouseEvtToVBAMouseEvt, ApproveAll, NULL } }, 342 343 // mousePressed ooo event 344 { MAP_CHAR_LEN("mousePressed"), { MAP_CHAR_LEN("_MouseDown"), ooMouseEvtToVBAMouseEvt, ApproveAll, NULL } }, 345 { MAP_CHAR_LEN("mousePressed"), { MAP_CHAR_LEN("_DblClick"), ooMouseEvtToVBADblClick, ApproveAll, NULL } }, 346 347 // mouseMoved ooo event 348 { MAP_CHAR_LEN("mouseMoved"), { MAP_CHAR_LEN("_MouseMove"), ooMouseEvtToVBAMouseEvt, ApproveAll, NULL } }, 349 { MAP_CHAR_LEN("mouseDragged"), { MAP_CHAR_LEN("_MouseMove"), ooMouseEvtToVBAMouseEvt, DenyMouseDrag, NULL } }, //liuchen, add to support VBA MouseMove event when the "Shift" key is pressed 350 351 // keyPressed ooo event 352 { MAP_CHAR_LEN("keyPressed"), { MAP_CHAR_LEN("_KeyDown"), ooKeyPressedToVBAKeyPressed, ApproveAll, NULL } }, 353 { MAP_CHAR_LEN("keyPressed"), { MAP_CHAR_LEN("_KeyPress"), ooKeyPressedToVBAKeyPressed, ApproveAll, NULL } } 354 }; 355 356 EventInfoHash& getEventTransInfo() 357 { 358 static bool initialised = false; 359 static EventInfoHash eventTransInfo; 360 if ( !initialised ) 361 { 362 rtl::OUString sEventInfo = MAP_CHAR_LEN(""); 363 TranslatePropMap* pTransProp = aTranslatePropMap_Impl; 364 int nCount = sizeof(aTranslatePropMap_Impl) / sizeof(aTranslatePropMap_Impl[0]); 365 366 int i = 0; 367 while (i < nCount) 368 { 369 sEventInfo = pTransProp->sEventInfo; 370 std::list< TranslateInfo > infoList; 371 do 372 { 373 infoList.push_back( pTransProp->aTransInfo ); 374 pTransProp++; 375 i++; 376 }while(i < nCount && sEventInfo == pTransProp->sEventInfo); 377 eventTransInfo[sEventInfo] = infoList; 378 } 379 initialised = true; 380 } 381 return eventTransInfo; 382 } 383 //liuchen 2009-6-23 end 384 385 // Helper class 386 387 class ScriptEventHelper 388 { 389 public: 390 ScriptEventHelper( const Reference< XInterface >& xControl ); 391 Sequence< ScriptEventDescriptor > createEvents( const rtl::OUString& sCodeName ); 392 Sequence< rtl::OUString > getEventListeners(); 393 private: 394 Reference< XComponentContext > m_xCtx; 395 Reference< XInterface > m_xControl; 396 }; 397 398 bool 399 eventMethodToDescriptor( const ::rtl::OUString& rEventMethod, ScriptEventDescriptor& evtDesc, const ::rtl::OUString& sCodeName ) 400 { 401 // format of ControlListener is TypeName::methodname e.g. 402 // "com.sun.star.awt.XActionListener::actionPerformed" or 403 // "XActionListener::actionPerformed 404 405 ::rtl::OUString sMethodName; 406 ::rtl::OUString sTypeName; 407 sal_Int32 nDelimPos = rEventMethod.indexOf( DELIM ); 408 if ( nDelimPos == -1 ) 409 { 410 return false; 411 } 412 sMethodName = rEventMethod.copy( nDelimPos + DELIMLEN ); 413 sTypeName = rEventMethod.copy( 0, nDelimPos ); 414 415 EventInfoHash& infos = getEventTransInfo(); 416 417 // Only create an ScriptEventDescriptor for an event we can translate 418 // or emulate 419 if ( sMethodName.getLength() 420 && sTypeName.getLength() 421 && ( infos.find( sMethodName ) != infos.end() ) ) 422 { 423 // just fill in CodeName, when the event fires the other 424 // info is gathered from the event source to determine what 425 // event handler we try to call 426 evtDesc.ScriptCode = sCodeName; 427 evtDesc.ListenerType = sTypeName; 428 evtDesc.EventMethod = sMethodName; 429 430 // set this it VBAInterop, ensures that it doesn't 431 // get persisted or shown in property editors 432 evtDesc.ScriptType = rtl::OUString::createFromAscii( 433 "VBAInterop" ); 434 return true; 435 } 436 return false; 437 438 } 439 440 ScriptEventHelper::ScriptEventHelper( const Reference< XInterface >& xControl ) : m_xControl( xControl ) 441 { 442 Reference < beans::XPropertySet > xProps( 443 ::comphelper::getProcessServiceFactory(), UNO_QUERY_THROW ); 444 m_xCtx.set( xProps->getPropertyValue( rtl::OUString( 445 RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))), 446 uno::UNO_QUERY_THROW ); 447 } 448 449 Sequence< rtl::OUString > 450 ScriptEventHelper::getEventListeners() 451 { 452 Reference< lang::XMultiComponentFactory > xMFac( 453 m_xCtx->getServiceManager(), UNO_QUERY ); 454 std::list< rtl::OUString > eventMethods; 455 456 if ( xMFac.is() ) 457 { 458 Reference< beans::XIntrospection > xIntrospection( 459 xMFac->createInstanceWithContext( rtl::OUString( 460 RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.beans.Introspection" ) ), m_xCtx ), UNO_QUERY ); 461 #if 0 462 dumpListeners( xIntrospection, m_xControl ); 463 dumpListeners( xIntrospection, m_xControl->getModel() ); 464 #endif 465 Reference< beans::XIntrospectionAccess > xIntrospectionAccess; 466 if ( xIntrospection.is() ) 467 { 468 xIntrospectionAccess = xIntrospection->inspect( 469 makeAny( m_xControl ) ); 470 Sequence< Type > aControlListeners = 471 xIntrospectionAccess->getSupportedListeners(); 472 sal_Int32 nLength = aControlListeners.getLength(); 473 for ( sal_Int32 i = 0; i< nLength; ++i ) 474 { 475 Type& listType = aControlListeners[ i ]; 476 rtl::OUString sFullTypeName = listType.getTypeName(); 477 Sequence< ::rtl::OUString > sMeths = 478 comphelper::getEventMethodsForType( listType ); 479 sal_Int32 sMethLen = sMeths.getLength(); 480 for ( sal_Int32 j=0 ; j < sMethLen; ++j ) 481 { 482 rtl::OUString sEventMethod = sFullTypeName; 483 sEventMethod += DELIM; 484 sEventMethod += sMeths[ j ]; 485 eventMethods.push_back( sEventMethod ); 486 } 487 } 488 489 } 490 } 491 492 Sequence< rtl::OUString > sEventMethodNames( eventMethods.size() ); 493 std::list< rtl::OUString >::const_iterator it = eventMethods.begin(); 494 rtl::OUString* pDest = sEventMethodNames.getArray(); 495 496 for ( ; it != eventMethods.end(); ++it, ++pDest ) 497 *pDest = *it; 498 499 return sEventMethodNames; 500 } 501 502 Sequence< ScriptEventDescriptor > 503 ScriptEventHelper::createEvents( const rtl::OUString& sCodeName ) 504 { 505 Sequence< rtl::OUString > aControlListeners = getEventListeners(); 506 rtl::OUString* pSrc = aControlListeners.getArray(); 507 sal_Int32 nLength = aControlListeners.getLength(); 508 509 Sequence< ScriptEventDescriptor > aDest( nLength ); 510 sal_Int32 nEvts = 0; 511 for ( sal_Int32 i = 0; i< nLength; ++i, ++pSrc ) 512 { 513 // from getListeners eventName is of form 514 // "com.sun.star.awt.XActionListener::actionPerformed" 515 // we need to strip "com.sun.star.awt." from that for form 516 // controls 517 ScriptEventDescriptor evtDesc; 518 if ( eventMethodToDescriptor( *pSrc, evtDesc, sCodeName ) ) 519 { 520 sal_Int32 dIndex = nEvts; 521 ++nEvts; 522 if ( nEvts > aDest.getLength() ) 523 aDest.realloc( nEvts );// should never happen 524 aDest[ dIndex ] = evtDesc; 525 } 526 } 527 aDest.realloc( nEvts ); 528 529 return aDest; 530 } 531 532 533 typedef ::cppu::WeakImplHelper1< container::XNameContainer > NameContainer_BASE; 534 535 class ReadOnlyEventsNameContainer : public NameContainer_BASE 536 { 537 public: 538 ReadOnlyEventsNameContainer( const Sequence< rtl::OUString >& eventMethods, const rtl::OUString& sCodeName ); 539 // XNameContainer 540 541 virtual void SAL_CALL insertByName( const ::rtl::OUString&, const Any& ) throw (lang::IllegalArgumentException, container::ElementExistException, lang::WrappedTargetException, RuntimeException) 542 { 543 throw RuntimeException( rtl::OUString::createFromAscii( "ReadOnly container" ), Reference< XInterface >() ); 544 545 } 546 virtual void SAL_CALL removeByName( const ::rtl::OUString& ) throw (::com::sun::star::container::NoSuchElementException, lang::WrappedTargetException, RuntimeException) 547 { 548 throw RuntimeException( rtl::OUString::createFromAscii( "ReadOnly container" ), Reference< XInterface >() ); 549 } 550 551 // XNameReplace 552 virtual void SAL_CALL replaceByName( const ::rtl::OUString&, const Any& ) throw (lang::IllegalArgumentException, container::NoSuchElementException, lang::WrappedTargetException, RuntimeException) 553 { 554 throw RuntimeException( rtl::OUString::createFromAscii( "ReadOnly container" ), Reference< XInterface >() ); 555 556 } 557 558 // XNameAccess 559 virtual Any SAL_CALL getByName( const ::rtl::OUString& aName ) throw (container::NoSuchElementException, lang::WrappedTargetException, RuntimeException); 560 virtual Sequence< ::rtl::OUString > SAL_CALL getElementNames( ) throw (RuntimeException); 561 virtual ::sal_Bool SAL_CALL hasByName( const ::rtl::OUString& aName ) throw (RuntimeException); 562 563 // XElementAccess 564 virtual Type SAL_CALL getElementType( ) throw (RuntimeException) 565 { return getCppuType(static_cast< const rtl::OUString * >(0) ); } 566 virtual ::sal_Bool SAL_CALL hasElements( ) throw (RuntimeException) 567 { return ( ( m_hEvents.size() > 0 ? sal_True : sal_False ) ); } 568 private: 569 570 typedef std::hash_map< rtl::OUString, Any, ::rtl::OUStringHash, 571 ::std::equal_to< ::rtl::OUString > > EventSupplierHash; 572 573 EventSupplierHash m_hEvents; 574 }; 575 576 ReadOnlyEventsNameContainer::ReadOnlyEventsNameContainer( const Sequence< rtl::OUString >& eventMethods, const rtl::OUString& sCodeName ) 577 { 578 const rtl::OUString* pSrc = eventMethods.getConstArray(); 579 sal_Int32 nLen = eventMethods.getLength(); 580 for ( sal_Int32 index = 0; index < nLen; ++index, ++pSrc ) 581 { 582 Any aDesc; 583 ScriptEventDescriptor evtDesc; 584 if ( eventMethodToDescriptor( *pSrc, evtDesc, sCodeName ) ) 585 { 586 aDesc <<= evtDesc; 587 m_hEvents[ *pSrc ] = aDesc; 588 } 589 } 590 } 591 592 Any SAL_CALL 593 ReadOnlyEventsNameContainer::getByName( const ::rtl::OUString& aName ) throw (container::NoSuchElementException, lang::WrappedTargetException, RuntimeException){ 594 EventSupplierHash::const_iterator it = m_hEvents.find( aName ); 595 if ( it == m_hEvents.end() ) 596 throw container::NoSuchElementException(); 597 return it->second; 598 } 599 600 Sequence< ::rtl::OUString > SAL_CALL 601 ReadOnlyEventsNameContainer::getElementNames( ) throw (RuntimeException) 602 { 603 Sequence< ::rtl::OUString > names(m_hEvents.size()); 604 rtl::OUString* pDest = names.getArray(); 605 EventSupplierHash::const_iterator it = m_hEvents.begin(); 606 EventSupplierHash::const_iterator it_end = m_hEvents.end(); 607 for ( sal_Int32 index = 0; it != it_end; ++index, ++pDest, ++it ) 608 *pDest = it->first; 609 return names; 610 } 611 612 sal_Bool SAL_CALL 613 ReadOnlyEventsNameContainer::hasByName( const ::rtl::OUString& aName ) throw (RuntimeException) 614 { 615 EventSupplierHash::const_iterator it = m_hEvents.find( aName ); 616 if ( it == m_hEvents.end() ) 617 return sal_False; 618 return sal_True; 619 } 620 621 typedef ::cppu::WeakImplHelper1< XScriptEventsSupplier > EventsSupplier_BASE; 622 623 class ReadOnlyEventsSupplier : public EventsSupplier_BASE 624 { 625 public: 626 ReadOnlyEventsSupplier( const Sequence< ::rtl::OUString >& eventMethods, const rtl::OUString& sCodeName ) 627 { m_xNameContainer = new ReadOnlyEventsNameContainer( eventMethods, sCodeName ); } 628 629 // XScriptEventSupplier 630 virtual Reference< container::XNameContainer > SAL_CALL getEvents( ) throw (RuntimeException){ return m_xNameContainer; } 631 private: 632 Reference< container::XNameContainer > m_xNameContainer; 633 }; 634 635 typedef ::cppu::WeakImplHelper2< XScriptListener, lang::XInitialization > EventListener_BASE; 636 637 #define EVENTLSTNR_PROPERTY_ID_MODEL 1 638 #define EVENTLSTNR_PROPERTY_MODEL ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Model" ) ) 639 640 class EventListener : public EventListener_BASE 641 ,public ::comphelper::OMutexAndBroadcastHelper 642 ,public ::comphelper::OPropertyContainer 643 ,public ::comphelper::OPropertyArrayUsageHelper< EventListener > 644 645 { 646 647 public: 648 EventListener( const Reference< XComponentContext >& rxContext ); 649 // XEventListener 650 virtual void SAL_CALL disposing(const lang::EventObject& Source) throw( RuntimeException ); 651 using cppu::OPropertySetHelper::disposing; 652 653 // XScriptListener 654 virtual void SAL_CALL firing(const ScriptEvent& evt) throw(RuntimeException); 655 virtual Any SAL_CALL approveFiring(const ScriptEvent& evt) throw(reflection::InvocationTargetException, RuntimeException); 656 // XPropertySet 657 virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) throw (::com::sun::star::uno::RuntimeException); 658 // XInitialization 659 virtual void SAL_CALL initialize( const Sequence< Any >& aArguments ) throw (Exception, RuntimeException); 660 // XInterface 661 DECLARE_XINTERFACE() 662 663 // XTypeProvider 664 DECLARE_XTYPEPROVIDER() 665 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) 666 { 667 OPropertyContainer::setFastPropertyValue( nHandle, rValue ); 668 if ( nHandle == EVENTLSTNR_PROPERTY_ID_MODEL ) 669 setShellFromModel(); 670 } 671 672 protected: 673 // OPropertySetHelper 674 virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper( ); 675 676 // OPropertyArrayUsageHelper 677 virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const; 678 679 private: 680 void setShellFromModel(); 681 void firing_Impl( const ScriptEvent& evt, Any *pSyncRet=NULL ) throw( RuntimeException ); 682 683 Reference< XComponentContext > m_xContext; 684 Reference< frame::XModel > m_xModel; 685 SfxObjectShell* mpShell; 686 687 }; 688 689 EventListener::EventListener( const Reference< XComponentContext >& rxContext ) : 690 OPropertyContainer(GetBroadcastHelper()), m_xContext( rxContext ), mpShell( 0 ) 691 { 692 registerProperty( EVENTLSTNR_PROPERTY_MODEL, EVENTLSTNR_PROPERTY_ID_MODEL, 693 beans::PropertyAttribute::TRANSIENT, &m_xModel, ::getCppuType( &m_xModel ) ); 694 695 } 696 697 void 698 EventListener::setShellFromModel() 699 { 700 // reset mpShell 701 mpShell = 0; 702 SfxObjectShell* pShell = SfxObjectShell::GetFirst(); 703 while ( m_xModel.is() && pShell ) 704 { 705 if ( pShell->GetModel() == m_xModel ) 706 { 707 mpShell = pShell; 708 break; 709 } 710 pShell = SfxObjectShell::GetNext( *pShell ); 711 } 712 } 713 714 //XEventListener 715 void 716 EventListener::disposing(const lang::EventObject&) throw( RuntimeException ) 717 { 718 } 719 720 //XScriptListener 721 722 void SAL_CALL 723 EventListener::firing(const ScriptEvent& evt) throw(RuntimeException) 724 { 725 firing_Impl( evt ); 726 } 727 728 Any SAL_CALL 729 EventListener::approveFiring(const ScriptEvent& evt) throw(reflection::InvocationTargetException, RuntimeException) 730 { 731 Any ret; 732 firing_Impl( evt, &ret ); 733 return ret; 734 } 735 736 // XInitialization 737 void SAL_CALL 738 EventListener::initialize( const Sequence< Any >& aArguments ) throw (Exception, RuntimeException) 739 { 740 if ( aArguments.getLength() == 1 ) 741 aArguments[0] >>= m_xModel; 742 OSL_TRACE("EventListener::initialize() args %d m_xModel %d", aArguments.getLength(), m_xModel.is() ); 743 } 744 745 // XInterface 746 747 IMPLEMENT_FORWARD_XINTERFACE2( EventListener, EventListener_BASE, OPropertyContainer ) 748 749 // XTypeProvider 750 751 IMPLEMENT_FORWARD_XTYPEPROVIDER2( EventListener, EventListener_BASE, OPropertyContainer ) 752 753 // OPropertySetHelper 754 755 ::cppu::IPropertyArrayHelper& 756 EventListener::getInfoHelper( ) 757 { 758 return *getArrayHelper(); 759 } 760 761 // OPropertyArrayUsageHelper 762 763 ::cppu::IPropertyArrayHelper* 764 EventListener::createArrayHelper( ) const 765 { 766 Sequence< beans::Property > aProps; 767 describeProperties( aProps ); 768 return new ::cppu::OPropertyArrayHelper( aProps ); 769 } 770 771 // XPropertySet 772 Reference< beans::XPropertySetInfo > 773 EventListener::getPropertySetInfo( ) throw (RuntimeException) 774 { 775 Reference< beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) ); 776 return xInfo; 777 } 778 779 //liuchen 2009-6-23 780 //decide if the control should execute the event 781 bool ApproveAll(const ScriptEvent&, void* ) 782 { 783 return true; 784 } 785 786 //for the given control type in evt.Arguments[0], look for if it appears in the type list in pPara 787 bool FindControl(const ScriptEvent& evt, void* pPara) 788 { 789 lang::EventObject aEvent; 790 evt.Arguments[ 0 ] >>= aEvent; 791 uno::Reference< uno::XInterface > xInterface( aEvent.Source, uno::UNO_QUERY ); 792 793 TypeList* pTypeListInfo = static_cast<TypeList*>(pPara); 794 Type* pType = pTypeListInfo->pTypeList; 795 int nLen = pTypeListInfo->nListLength; 796 797 for (int i = 0; i < nLen; i++) 798 { 799 if ( xInterface->queryInterface( *pType ).hasValue() ) 800 { 801 return true; 802 } 803 pType++; 804 } 805 806 return false; 807 } 808 809 //if the the given control type in evt.Arguments[0] appears in the type list in pPara, then approve the execution 810 bool ApproveType(const ScriptEvent& evt, void* pPara) 811 { 812 return FindControl(evt, pPara); 813 } 814 815 //if the the given control type in evt.Arguments[0] appears in the type list in pPara, then deny the execution 816 bool DenyType(const ScriptEvent& evt, void* pPara) 817 { 818 return !FindControl(evt, pPara); 819 } 820 821 //when mouse is moving, either the mouse button is pressed or some key is pressed can trigger the OO mouseDragged event, 822 //the former should be denyed, and the latter allowed, only by doing so can the VBA MouseMove event when the "Shift" key is 823 //pressed can be correctly triggered 824 bool DenyMouseDrag(const ScriptEvent& evt, void* ) 825 { 826 awt::MouseEvent aEvent; 827 evt.Arguments[ 0 ] >>= aEvent; 828 if (aEvent.Buttons == 0 ) 829 { 830 return true; 831 } 832 else 833 { 834 return false; 835 } 836 } 837 838 839 840 //liuchen 2009-6-23 841 // EventListener 842 843 void 844 EventListener::firing_Impl(const ScriptEvent& evt, Any* /*pRet*/ ) throw(RuntimeException) 845 { 846 OSL_TRACE("EventListener::firing_Impl( FAKE VBA_EVENTS )"); 847 static const ::rtl::OUString vbaInterOp = 848 ::rtl::OUString::createFromAscii("VBAInterop"); 849 850 // let default handlers deal with non vba stuff 851 if ( !evt.ScriptType.equals( vbaInterOp ) ) 852 return; 853 lang::EventObject aEvent; 854 evt.Arguments[ 0 ] >>= aEvent; 855 OSL_TRACE("Argument[0] is %s", rtl::OUStringToOString( comphelper::anyToString( evt.Arguments[0] ), RTL_TEXTENCODING_UTF8 ).getStr() ); 856 OSL_TRACE("Getting Control"); 857 uno::Reference< awt::XControl > xControl( aEvent.Source, uno::UNO_QUERY_THROW ); 858 OSL_TRACE("Getting properties"); 859 uno::Reference< beans::XPropertySet > xProps( xControl->getModel(), uno::UNO_QUERY_THROW ); 860 861 rtl::OUString sName = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("UserForm") ); 862 OSL_TRACE("Getting Name"); 863 864 uno::Reference< awt::XDialog > xDlg( aEvent.Source, uno::UNO_QUERY ); 865 if ( !xDlg.is() ) 866 xProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Name") ) ) >>= sName; 867 //dumpEvent( evt ); 868 EventInfoHash& infos = getEventTransInfo(); 869 EventInfoHash::const_iterator eventInfo_it = infos.find( evt.MethodName ); 870 EventInfoHash::const_iterator it_end = infos.end(); 871 if ( eventInfo_it == it_end ) 872 { 873 OSL_TRACE("Bogus event for %s", 874 rtl::OUStringToOString( evt.ScriptType, RTL_TEXTENCODING_UTF8 ).getStr() ); 875 return; 876 } 877 878 uno::Reference< script::provider::XScriptProviderSupplier > xSPS( m_xModel, uno::UNO_QUERY ); 879 uno::Reference< script::provider::XScriptProvider > xScriptProvider; 880 if ( xSPS.is() ) 881 xScriptProvider = xSPS->getScriptProvider(); 882 if ( xScriptProvider.is() && mpShell ) 883 { 884 std::list< TranslateInfo > matchingMethods; 885 std::list< TranslateInfo >::const_iterator txInfo = 886 eventInfo_it->second.begin(); 887 std::list< TranslateInfo >::const_iterator txInfo_end = eventInfo_it->second.end(); 888 rtl::OUString sMacroLoc = rtl::OUString::createFromAscii("Standard.").concat( evt.ScriptCode ).concat( rtl::OUString::createFromAscii(".") ); 889 890 StarBASIC* pBasic = mpShell->GetBasic(); 891 SbModule* pModule = pBasic->FindModule( evt.ScriptCode ); 892 for ( ; pModule && txInfo != txInfo_end; ++txInfo ) 893 { 894 // see if we have a match for the handlerextension 895 // where ScriptCode is methodname_handlerextension 896 rtl::OUString sTemp = sName.concat( (*txInfo).sVBAName ); 897 898 OSL_TRACE("*** trying to invoke %s ", 899 rtl::OUStringToOString( sTemp, RTL_TEXTENCODING_UTF8 ).getStr() ); 900 SbMethod* pMeth = static_cast< SbMethod* >( pModule->Find( sTemp, SbxCLASS_METHOD ) ); 901 if ( pMeth ) 902 { 903 //liuchen 2009-6-8 904 if (! txInfo->ApproveRule(evt, txInfo->pPara) ) 905 { 906 continue; 907 } 908 //liuchen 2009-6-8 909 // !! translate arguments & emulate events where necessary 910 Sequence< Any > aArguments; 911 if ( (*txInfo).toVBA ) 912 aArguments = (*txInfo).toVBA( evt.Arguments ); 913 else 914 aArguments = evt.Arguments; 915 if ( aArguments.getLength() ) 916 { 917 // call basic event handlers for event 918 919 static rtl::OUString part1 = rtl::OUString::createFromAscii( "vnd.sun.star.script:"); 920 static rtl::OUString part2 = rtl::OUString::createFromAscii("?language=Basic&location=document"); 921 922 // create script url 923 rtl::OUString url = part1 + sMacroLoc + sTemp + part2; 924 925 OSL_TRACE("script url = %s", 926 rtl::OUStringToOString( url, 927 RTL_TEXTENCODING_UTF8 ).getStr() ); 928 Sequence< sal_Int16 > aOutArgsIndex; 929 Sequence< Any > aOutArgs; 930 try 931 { 932 if ( mpShell ) 933 { 934 uno::Any aRet; 935 mpShell->CallXScript( url, 936 aArguments, aRet, aOutArgsIndex, aOutArgs, false ); 937 } 938 } 939 catch ( uno::Exception& e ) 940 { 941 OSL_TRACE("event script raised %s", rtl::OUStringToOString( e.Message, RTL_TEXTENCODING_UTF8 ).getStr() ); 942 } 943 } 944 } 945 } 946 } 947 } 948 949 typedef ::cppu::WeakImplHelper1< XVBAToOOEventDescGen > VBAToOOEventDescGen_BASE; 950 951 952 class VBAToOOEventDescGen : public VBAToOOEventDescGen_BASE 953 { 954 public: 955 VBAToOOEventDescGen( const Reference< XComponentContext >& rxContext ); 956 957 // XVBAToOOEventDescGen 958 virtual Sequence< ScriptEventDescriptor > SAL_CALL getEventDescriptions( const Reference< XInterface >& control, const rtl::OUString& sCodeName ) throw (RuntimeException); 959 virtual Reference< XScriptEventsSupplier > SAL_CALL getEventSupplier( const Reference< XInterface >& xControl, const rtl::OUString& sCodeName ) throw (::com::sun::star::uno::RuntimeException); 960 private: 961 Reference< XComponentContext > m_xContext; 962 963 }; 964 965 VBAToOOEventDescGen::VBAToOOEventDescGen( const Reference< XComponentContext >& rxContext ):m_xContext( rxContext ) {} 966 967 Sequence< ScriptEventDescriptor > SAL_CALL 968 VBAToOOEventDescGen::getEventDescriptions( const Reference< XInterface >& xControl, const rtl::OUString& sCodeName ) throw (RuntimeException) 969 { 970 ScriptEventHelper evntHelper( xControl ); 971 return evntHelper.createEvents( sCodeName ); 972 } 973 974 Reference< XScriptEventsSupplier > SAL_CALL 975 VBAToOOEventDescGen::getEventSupplier( const Reference< XInterface >& xControl, const rtl::OUString& sCodeName ) throw (::com::sun::star::uno::RuntimeException) 976 { 977 ScriptEventHelper evntHelper( xControl ); 978 Reference< XScriptEventsSupplier > xSupplier = 979 new ReadOnlyEventsSupplier( 980 evntHelper.getEventListeners(), sCodeName ) ; 981 return xSupplier; 982 } 983 984 // Component related 985 986 namespace evtlstner 987 { 988 ::rtl::OUString SAL_CALL getImplementationName() 989 { 990 static ::rtl::OUString* pImplName = 0; 991 if ( !pImplName ) 992 { 993 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); 994 if ( !pImplName ) 995 { 996 static ::rtl::OUString aImplName( RTL_CONSTASCII_USTRINGPARAM( "ooo.vba.EventListener" ) ); 997 pImplName = &aImplName; 998 } 999 } 1000 return *pImplName; 1001 } 1002 1003 uno::Reference< XInterface > SAL_CALL create( 1004 Reference< XComponentContext > const & xContext ) 1005 SAL_THROW( () ) 1006 { 1007 return static_cast< lang::XTypeProvider * >( new EventListener( xContext ) ); 1008 } 1009 1010 Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() 1011 { 1012 const ::rtl::OUString strName( ::evtlstner::getImplementationName() ); 1013 return Sequence< ::rtl::OUString >( &strName, 1 ); 1014 } 1015 } 1016 namespace ooevtdescgen 1017 { 1018 ::rtl::OUString SAL_CALL getImplementationName() 1019 { 1020 static ::rtl::OUString* pImplName = 0; 1021 if ( !pImplName ) 1022 { 1023 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); 1024 if ( !pImplName ) 1025 { 1026 static ::rtl::OUString aImplName( RTL_CONSTASCII_USTRINGPARAM( "ooo.vba.VBAToOOEventDesc" ) ); 1027 pImplName = &aImplName; 1028 } 1029 } 1030 return *pImplName; 1031 } 1032 1033 uno::Reference< XInterface > SAL_CALL create( 1034 Reference< XComponentContext > const & xContext ) 1035 SAL_THROW( () ) 1036 { 1037 return static_cast< lang::XTypeProvider * >( new VBAToOOEventDescGen( xContext ) ); 1038 } 1039 1040 Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() 1041 { 1042 const ::rtl::OUString strName( ::ooevtdescgen::getImplementationName() ); 1043 return Sequence< ::rtl::OUString >( &strName, 1 ); 1044 } 1045 } 1046