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