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