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_extensions.hxx" 26 27 #include "eventhandler.hxx" 28 #include "propctrlr.hrc" 29 #include "formbrowsertools.hxx" 30 #include "formresid.hrc" 31 #include "formstrings.hxx" 32 #include "handlerhelper.hxx" 33 #include "modulepcr.hxx" 34 #include "pcrcommon.hxx" 35 #include "pcrstrings.hxx" 36 #include "propertycontrolextender.hxx" 37 38 /** === begin UNO includes === **/ 39 #include <com/sun/star/awt/XTabControllerModel.hpp> 40 #include <com/sun/star/beans/PropertyAttribute.hpp> 41 #include <com/sun/star/beans/UnknownPropertyException.hpp> 42 #include <com/sun/star/beans/XIntrospection.hpp> 43 #include <com/sun/star/beans/XIntrospectionAccess.hpp> 44 #include <com/sun/star/container/NoSuchElementException.hpp> 45 #include <com/sun/star/container/XChild.hpp> 46 #include <com/sun/star/container/XIndexAccess.hpp> 47 #include <com/sun/star/container/XNameContainer.hpp> 48 #include <com/sun/star/container/XNameReplace.hpp> 49 #include <com/sun/star/form/FormComponentType.hpp> 50 #include <com/sun/star/form/XForm.hpp> 51 #include <com/sun/star/form/runtime/XFormController.hpp> 52 #include <com/sun/star/inspection/PropertyControlType.hpp> 53 #include <com/sun/star/lang/NullPointerException.hpp> 54 #include <com/sun/star/script/XEventAttacherManager.hpp> 55 #include <com/sun/star/script/XScriptEventsSupplier.hpp> 56 #include <com/sun/star/util/XModifiable.hpp> 57 #include <com/sun/star/uri/UriReferenceFactory.hpp> 58 #include <com/sun/star/uri/XVndSunStarScriptUrlReference.hpp> 59 /** === end UNO includes === **/ 60 61 #include <comphelper/namedvaluecollection.hxx> 62 #include <comphelper/evtmethodhelper.hxx> 63 #include <comphelper/types.hxx> 64 #include <cppuhelper/implbase1.hxx> 65 #include <rtl/ref.hxx> 66 #include <rtl/ustrbuf.hxx> 67 #include <sfx2/app.hxx> 68 #include <svl/eitem.hxx> 69 #include <svl/itemset.hxx> 70 #include <svx/svxdlg.hxx> 71 #include <svx/svxids.hrc> 72 #include <tools/diagnose_ex.h> 73 #include <vcl/msgbox.hxx> 74 75 #include <map> 76 #include <algorithm> 77 78 //------------------------------------------------------------------------ 79 extern "C" void SAL_CALL createRegistryInfo_EventHandler() 80 { 81 ::pcr::OAutoRegistration< ::pcr::EventHandler > aAutoRegistration; 82 } 83 84 //........................................................................ 85 namespace pcr 86 { 87 //........................................................................ 88 89 /** === begin UNO using === **/ 90 using ::com::sun::star::uno::Reference; 91 using ::com::sun::star::uno::XComponentContext; 92 using ::com::sun::star::beans::XPropertySet; 93 using ::com::sun::star::uno::Any; 94 using ::com::sun::star::uno::TypeClass_STRING; 95 using ::com::sun::star::uno::Type; 96 using ::com::sun::star::beans::XPropertyChangeListener; 97 using ::com::sun::star::beans::Property; 98 using ::com::sun::star::beans::PropertyState; 99 using ::com::sun::star::beans::PropertyState_DIRECT_VALUE; 100 using ::com::sun::star::uno::Sequence; 101 using ::com::sun::star::script::ScriptEventDescriptor; 102 using ::com::sun::star::script::XScriptEventsSupplier; 103 using ::com::sun::star::lang::NullPointerException; 104 using ::com::sun::star::uno::Exception; 105 using ::com::sun::star::container::XChild; 106 using ::com::sun::star::container::XIndexAccess; 107 using ::com::sun::star::script::XEventAttacherManager; 108 using ::com::sun::star::uno::UNO_QUERY; 109 using ::com::sun::star::uno::UNO_QUERY_THROW; 110 using ::com::sun::star::uno::XInterface; 111 using ::com::sun::star::beans::XIntrospection; 112 using ::com::sun::star::beans::XIntrospectionAccess; 113 using ::com::sun::star::container::XNameContainer; 114 using ::com::sun::star::awt::XTabControllerModel; 115 using ::com::sun::star::form::XForm; 116 using ::com::sun::star::form::runtime::XFormController; 117 using ::com::sun::star::beans::UnknownPropertyException; 118 using ::com::sun::star::uno::makeAny; 119 using ::com::sun::star::container::NoSuchElementException; 120 using ::com::sun::star::beans::XPropertySetInfo; 121 using ::com::sun::star::container::XNameReplace; 122 using ::com::sun::star::lang::IllegalArgumentException; 123 using ::com::sun::star::lang::WrappedTargetException; 124 using ::com::sun::star::uno::RuntimeException; 125 using ::com::sun::star::beans::PropertyValue; 126 using ::com::sun::star::inspection::LineDescriptor; 127 using ::com::sun::star::inspection::XPropertyControlFactory; 128 using ::com::sun::star::inspection::InteractiveSelectionResult; 129 using ::com::sun::star::inspection::InteractiveSelectionResult_Cancelled; 130 using ::com::sun::star::inspection::InteractiveSelectionResult_Success; 131 using ::com::sun::star::inspection::XObjectInspectorUI; 132 using ::com::sun::star::util::XModifiable; 133 using ::com::sun::star::beans::PropertyChangeEvent; 134 using ::com::sun::star::frame::XFrame; 135 using ::com::sun::star::frame::XModel; 136 using ::com::sun::star::frame::XController; 137 using ::com::sun::star::uno::UNO_SET_THROW; 138 using com::sun::star::uri::UriReferenceFactory; 139 using com::sun::star::uri::XUriReferenceFactory; 140 using com::sun::star::uri::XVndSunStarScriptUrlReference; 141 using ::com::sun::star::lang::XEventListener; 142 /** === end UNO using === **/ 143 namespace PropertyControlType = ::com::sun::star::inspection::PropertyControlType; 144 namespace PropertyAttribute = ::com::sun::star::beans::PropertyAttribute; 145 namespace FormComponentType = ::com::sun::star::form::FormComponentType; 146 147 //==================================================================== 148 //= EventDescription 149 //==================================================================== 150 EventDescription::EventDescription( EventId _nId, const sal_Char* _pListenerNamespaceAscii, const sal_Char* _pListenerClassAsciiName, 151 const sal_Char* _pListenerMethodAsciiName, sal_uInt16 _nDisplayNameResId, const rtl::OString& _sHelpId, const rtl::OString& _sUniqueBrowseId ) 152 :sDisplayName( String( PcrRes( _nDisplayNameResId ) ) ) 153 ,sListenerMethodName( ::rtl::OUString::createFromAscii( _pListenerMethodAsciiName ) ) 154 ,sHelpId( _sHelpId ) 155 ,sUniqueBrowseId( _sUniqueBrowseId ) 156 ,nId( _nId ) 157 { 158 ::rtl::OUStringBuffer aQualifiedListenerClass; 159 aQualifiedListenerClass.appendAscii( "com.sun.star." ); 160 aQualifiedListenerClass.appendAscii( _pListenerNamespaceAscii ); 161 aQualifiedListenerClass.appendAscii( "." ); 162 aQualifiedListenerClass.appendAscii( _pListenerClassAsciiName ); 163 sListenerClassName = aQualifiedListenerClass.makeStringAndClear(); 164 } 165 166 //======================================================================== 167 //= helper 168 //======================================================================== 169 namespace 170 { 171 //.................................................................... 172 #define DESCRIBE_EVENT( asciinamespace, asciilistener, asciimethod, id_postfix ) \ 173 s_aKnownEvents.insert( EventMap::value_type( \ 174 ::rtl::OUString::createFromAscii( asciimethod ), \ 175 EventDescription( ++nEventId, asciinamespace, asciilistener, asciimethod, RID_STR_EVT_##id_postfix, HID_EVT_##id_postfix, UID_BRWEVT_##id_postfix ) ) ) 176 177 //.................................................................... 178 bool lcl_getEventDescriptionForMethod( const ::rtl::OUString& _rMethodName, EventDescription& _out_rDescription ) 179 { 180 static EventMap s_aKnownEvents; 181 if ( s_aKnownEvents.empty() ) 182 { 183 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); 184 if ( s_aKnownEvents.empty() ) 185 { 186 static sal_Int32 nEventId = 0; 187 188 DESCRIBE_EVENT( "form", "XApproveActionListener", "approveAction", APPROVEACTIONPERFORMED ); 189 DESCRIBE_EVENT( "awt", "XActionListener", "actionPerformed", ACTIONPERFORMED ); 190 DESCRIBE_EVENT( "form", "XChangeListener", "changed", CHANGED ); 191 DESCRIBE_EVENT( "awt", "XTextListener", "textChanged", TEXTCHANGED ); 192 DESCRIBE_EVENT( "awt", "XItemListener", "itemStateChanged", ITEMSTATECHANGED ); 193 DESCRIBE_EVENT( "awt", "XFocusListener", "focusGained", FOCUSGAINED ); 194 DESCRIBE_EVENT( "awt", "XFocusListener", "focusLost", FOCUSLOST ); 195 DESCRIBE_EVENT( "awt", "XKeyListener", "keyPressed", KEYTYPED ); 196 DESCRIBE_EVENT( "awt", "XKeyListener", "keyReleased", KEYUP ); 197 DESCRIBE_EVENT( "awt", "XMouseListener", "mouseEntered", MOUSEENTERED ); 198 DESCRIBE_EVENT( "awt", "XMouseMotionListener", "mouseDragged", MOUSEDRAGGED ); 199 DESCRIBE_EVENT( "awt", "XMouseMotionListener", "mouseMoved", MOUSEMOVED ); 200 DESCRIBE_EVENT( "awt", "XMouseListener", "mousePressed", MOUSEPRESSED ); 201 DESCRIBE_EVENT( "awt", "XMouseListener", "mouseReleased", MOUSERELEASED ); 202 DESCRIBE_EVENT( "awt", "XMouseListener", "mouseExited", MOUSEEXITED ); 203 DESCRIBE_EVENT( "form", "XResetListener", "approveReset", APPROVERESETTED ); 204 DESCRIBE_EVENT( "form", "XResetListener", "resetted", RESETTED ); 205 DESCRIBE_EVENT( "form", "XSubmitListener", "approveSubmit", SUBMITTED ); 206 DESCRIBE_EVENT( "form", "XUpdateListener", "approveUpdate", BEFOREUPDATE ); 207 DESCRIBE_EVENT( "form", "XUpdateListener", "updated", AFTERUPDATE ); 208 DESCRIBE_EVENT( "form", "XLoadListener", "loaded", LOADED ); 209 DESCRIBE_EVENT( "form", "XLoadListener", "reloading", RELOADING ); 210 DESCRIBE_EVENT( "form", "XLoadListener", "reloaded", RELOADED ); 211 DESCRIBE_EVENT( "form", "XLoadListener", "unloading", UNLOADING ); 212 DESCRIBE_EVENT( "form", "XLoadListener", "unloaded", UNLOADED ); 213 DESCRIBE_EVENT( "form", "XConfirmDeleteListener", "confirmDelete", CONFIRMDELETE ); 214 DESCRIBE_EVENT( "sdb", "XRowSetApproveListener", "approveRowChange", APPROVEROWCHANGE ); 215 DESCRIBE_EVENT( "sdbc", "XRowSetListener", "rowChanged", ROWCHANGE ); 216 DESCRIBE_EVENT( "sdb", "XRowSetApproveListener", "approveCursorMove", POSITIONING ); 217 DESCRIBE_EVENT( "sdbc", "XRowSetListener", "cursorMoved", POSITIONED ); 218 DESCRIBE_EVENT( "form", "XDatabaseParameterListener", "approveParameter", APPROVEPARAMETER ); 219 DESCRIBE_EVENT( "sdb", "XSQLErrorListener", "errorOccured", ERROROCCURED ); 220 DESCRIBE_EVENT( "awt", "XAdjustmentListener", "adjustmentValueChanged", ADJUSTMENTVALUECHANGED ); 221 } 222 } 223 224 EventMap::const_iterator pos = s_aKnownEvents.find( _rMethodName ); 225 if ( pos == s_aKnownEvents.end() ) 226 return false; 227 228 _out_rDescription = pos->second; 229 return true; 230 } 231 232 //.................................................................... 233 ::rtl::OUString lcl_getEventPropertyName( const ::rtl::OUString& _rListenerClassName, const ::rtl::OUString& _rMethodName ) 234 { 235 ::rtl::OUStringBuffer aPropertyName; 236 aPropertyName.append( _rListenerClassName ); 237 aPropertyName.append( (sal_Unicode)';' ); 238 aPropertyName.append( _rMethodName.getStr() ); 239 return aPropertyName.makeStringAndClear(); 240 } 241 242 //................................................................ 243 ScriptEventDescriptor lcl_getAssignedScriptEvent( const EventDescription& _rEvent, const Sequence< ScriptEventDescriptor >& _rAllAssignedMacros ) 244 { 245 ScriptEventDescriptor aScriptEvent; 246 // for the case there is actually no event assigned, initialize at least ListenerType and MethodName, 247 // so this ScriptEventDescriptor properly describes the given event 248 aScriptEvent.ListenerType = _rEvent.sListenerClassName; 249 aScriptEvent.EventMethod = _rEvent.sListenerMethodName; 250 251 const ScriptEventDescriptor* pAssignedEvent = _rAllAssignedMacros.getConstArray(); 252 sal_Int32 assignedEventCount( _rAllAssignedMacros.getLength() ); 253 for ( sal_Int32 assignedEvent = 0; assignedEvent < assignedEventCount; ++assignedEvent, ++pAssignedEvent ) 254 { 255 if ( ( pAssignedEvent->ListenerType != _rEvent.sListenerClassName ) 256 || ( pAssignedEvent->EventMethod != _rEvent.sListenerMethodName ) 257 ) 258 continue; 259 260 if ( ( pAssignedEvent->ScriptCode.getLength() == 0 ) 261 || ( pAssignedEvent->ScriptType.getLength() == 0 ) 262 ) 263 { 264 DBG_ERROR( "lcl_getAssignedScriptEvent: me thinks this should not happen!" ); 265 continue; 266 } 267 268 aScriptEvent = *pAssignedEvent; 269 270 if ( !aScriptEvent.ScriptType.equalsAscii( "StarBasic" ) ) 271 continue; 272 273 // this is an old-style macro specification: 274 // [document|application]:Library.Module.Function 275 // we need to translate this to the new-style macro specification 276 // vnd.sun.star.script:Library.Module.Function?language=Basic&location=[document|application] 277 278 sal_Int32 nPrefixLen = aScriptEvent.ScriptCode.indexOf( ':' ); 279 OSL_ENSURE( nPrefixLen > 0, "lcl_getAssignedScriptEvent: illegal location!" ); 280 ::rtl::OUString sLocation = aScriptEvent.ScriptCode.copy( 0, nPrefixLen ); 281 ::rtl::OUString sMacroPath = aScriptEvent.ScriptCode.copy( nPrefixLen + 1 ); 282 283 ::rtl::OUStringBuffer aNewStyleSpec; 284 aNewStyleSpec.appendAscii( "vnd.sun.star.script:" ); 285 aNewStyleSpec.append ( sMacroPath ); 286 aNewStyleSpec.appendAscii( "?language=Basic&location=" ); 287 aNewStyleSpec.append ( sLocation ); 288 289 aScriptEvent.ScriptCode = aNewStyleSpec.makeStringAndClear(); 290 291 // also, this new-style spec requires the script code to be "Script" instead of "StarBasic" 292 aScriptEvent.ScriptType = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Script" ) ); 293 } 294 return aScriptEvent; 295 } 296 297 //................................................................ 298 ::rtl::OUString lcl_getQualifiedKnownListenerName( const ScriptEventDescriptor& _rFormComponentEventDescriptor ) 299 { 300 EventDescription aKnownEvent; 301 if ( lcl_getEventDescriptionForMethod( _rFormComponentEventDescriptor.EventMethod, aKnownEvent ) ) 302 return aKnownEvent.sListenerClassName; 303 DBG_ERROR( "lcl_getQualifiedKnownListenerName: unknown method name!" ); 304 // somebody assigned an script to a form component event which we don't know 305 // Speaking strictly, this is not really an error - it is possible to do 306 // this programmatically -, but it should rarely happen, since it's not possible 307 // via UI 308 return _rFormComponentEventDescriptor.ListenerType; 309 } 310 311 //................................................................ 312 typedef ::std::set< Type, TypeLessByName > TypeBag; 313 314 //................................................................ 315 void lcl_addListenerTypesFor_throw( const Reference< XInterface >& _rxComponent, 316 const Reference< XIntrospection >& _rxIntrospection, TypeBag& _out_rTypes ) 317 { 318 if ( !_rxComponent.is() ) 319 return; 320 OSL_PRECOND( _rxIntrospection.is(), "lcl_addListenerTypesFor_throw: this will crash!" ); 321 322 Reference< XIntrospectionAccess > xIntrospectionAccess( 323 _rxIntrospection->inspect( makeAny( _rxComponent ) ), UNO_QUERY_THROW ); 324 325 Sequence< Type > aListeners( xIntrospectionAccess->getSupportedListeners() ); 326 327 ::std::copy( aListeners.getConstArray(), aListeners.getConstArray() + aListeners.getLength(), 328 ::std::insert_iterator< TypeBag >( _out_rTypes, _out_rTypes.begin() ) ); 329 } 330 331 //................................................................ 332 bool operator ==( const ScriptEventDescriptor _lhs, const ScriptEventDescriptor _rhs ) 333 { 334 return ( ( _lhs.ListenerType == _rhs.ListenerType ) 335 && ( _lhs.EventMethod == _rhs.EventMethod ) 336 && ( _lhs.AddListenerParam == _rhs.AddListenerParam ) 337 && ( _lhs.ScriptType == _rhs.ScriptType ) 338 && ( _lhs.ScriptCode == _rhs.ScriptCode ) 339 ); 340 } 341 } 342 343 //==================================================================== 344 //= EventHandler 345 //==================================================================== 346 typedef ::cppu::WeakImplHelper1 < ::com::sun::star::container::XNameReplace 347 > EventHolder_Base; 348 /** a UNO component holding assigned event descriptions, for use with a SvxMacroAssignDlg 349 */ 350 class EventHolder : public EventHolder_Base 351 { 352 private: 353 typedef ::std::hash_map< ::rtl::OUString, ScriptEventDescriptor, ::rtl::OUStringHash > EventMap; 354 typedef ::std::map< EventId, EventMap::iterator > EventMapIndexAccess; 355 356 EventMap m_aEventNameAccess; 357 EventMapIndexAccess m_aEventIndexAccess; 358 359 public: 360 EventHolder( ); 361 362 void addEvent( EventId _nId, const ::rtl::OUString& _rEventName, const ScriptEventDescriptor& _rScriptEvent ); 363 364 /** effectively the same as getByName, but instead of converting the ScriptEventDescriptor to the weird 365 format used by the macro assignment dialog, it is returned directly 366 */ 367 ScriptEventDescriptor getNormalizedDescriptorByName( const ::rtl::OUString& _rEventName ) const; 368 369 // XNameReplace 370 virtual void SAL_CALL replaceByName( const ::rtl::OUString& _rName, const Any& aElement ) throw (IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException); 371 virtual Any SAL_CALL getByName( const ::rtl::OUString& _rName ) throw (NoSuchElementException, WrappedTargetException, RuntimeException); 372 virtual Sequence< ::rtl::OUString > SAL_CALL getElementNames( ) throw (RuntimeException); 373 virtual ::sal_Bool SAL_CALL hasByName( const ::rtl::OUString& _rName ) throw (RuntimeException); 374 virtual Type SAL_CALL getElementType( ) throw (RuntimeException); 375 virtual ::sal_Bool SAL_CALL hasElements( ) throw (RuntimeException); 376 377 protected: 378 ~EventHolder( ); 379 380 private: 381 ScriptEventDescriptor impl_getDescriptor_throw( const ::rtl::OUString& _rEventName ) const; 382 }; 383 384 DBG_NAME( EventHolder ) 385 //------------------------------------------------------------------------ 386 EventHolder::EventHolder() 387 { 388 DBG_CTOR( EventHolder, NULL ); 389 } 390 391 //------------------------------------------------------------------------ 392 EventHolder::~EventHolder() 393 { 394 m_aEventNameAccess.clear(); 395 m_aEventIndexAccess.clear(); 396 DBG_DTOR( EventHolder, NULL ); 397 } 398 399 //------------------------------------------------------------------------ 400 void EventHolder::addEvent( EventId _nId, const ::rtl::OUString& _rEventName, const ScriptEventDescriptor& _rScriptEvent ) 401 { 402 ::std::pair< EventMap::iterator, bool > insertionResult = 403 m_aEventNameAccess.insert( EventMap::value_type( _rEventName, _rScriptEvent ) ); 404 OSL_ENSURE( insertionResult.second, "EventHolder::addEvent: there already was a MacroURL for this event!" ); 405 m_aEventIndexAccess[ _nId ] = insertionResult.first; 406 } 407 408 //------------------------------------------------------------------------ 409 ScriptEventDescriptor EventHolder::getNormalizedDescriptorByName( const ::rtl::OUString& _rEventName ) const 410 { 411 return impl_getDescriptor_throw( _rEventName ); 412 } 413 414 //------------------------------------------------------------------------ 415 ScriptEventDescriptor EventHolder::impl_getDescriptor_throw( const ::rtl::OUString& _rEventName ) const 416 { 417 EventMap::const_iterator pos = m_aEventNameAccess.find( _rEventName ); 418 if ( pos == m_aEventNameAccess.end() ) 419 throw NoSuchElementException( ::rtl::OUString(), *const_cast< EventHolder* >( this ) ); 420 return pos->second; 421 } 422 423 //------------------------------------------------------------------------ 424 void SAL_CALL EventHolder::replaceByName( const ::rtl::OUString& _rName, const Any& _rElement ) throw (IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException) 425 { 426 EventMap::iterator pos = m_aEventNameAccess.find( _rName ); 427 if ( pos == m_aEventNameAccess.end() ) 428 throw NoSuchElementException( ::rtl::OUString(), *this ); 429 430 Sequence< PropertyValue > aScriptDescriptor; 431 OSL_VERIFY( _rElement >>= aScriptDescriptor ); 432 433 ::comphelper::NamedValueCollection aExtractor( aScriptDescriptor ); 434 435 pos->second.ScriptType = aExtractor.getOrDefault( "EventType", ::rtl::OUString() ); 436 pos->second.ScriptCode = aExtractor.getOrDefault( "Script", ::rtl::OUString() ); 437 } 438 439 //------------------------------------------------------------------------ 440 Any SAL_CALL EventHolder::getByName( const ::rtl::OUString& _rName ) throw (NoSuchElementException, WrappedTargetException, RuntimeException) 441 { 442 ScriptEventDescriptor aDescriptor( impl_getDescriptor_throw( _rName ) ); 443 444 Any aRet; 445 Sequence< PropertyValue > aScriptDescriptor( 2 ); 446 aScriptDescriptor[0].Name = ::rtl::OUString::createFromAscii( "EventType" ); 447 aScriptDescriptor[0].Value <<= aDescriptor.ScriptType; 448 aScriptDescriptor[1].Name = ::rtl::OUString::createFromAscii( "Script" ); 449 aScriptDescriptor[1].Value <<= aDescriptor.ScriptCode; 450 451 return makeAny( aScriptDescriptor ); 452 } 453 454 //------------------------------------------------------------------------ 455 Sequence< ::rtl::OUString > SAL_CALL EventHolder::getElementNames( ) throw (RuntimeException) 456 { 457 Sequence< ::rtl::OUString > aReturn( m_aEventIndexAccess.size() ); 458 ::rtl::OUString* pReturn = aReturn.getArray(); 459 460 // SvxMacroAssignDlg has a weird API: It expects a XNameReplace, means a container whose 461 // main access method is by name. In it's UI, it shows the possible events in exactly the 462 // order in which XNameAccess::getElementNames returns them. 463 // However, SvxMacroAssignDlg *also* takes an index for the initial selection, which is 464 // relative to the sequence returned by XNameAccess::getElementNames. 465 // This is IMO weird, since it mixes index access with name access, which decreases efficiency 466 // of the implementation. 467 // Well, it means we're forced to return the events in getElementNames in exactly the same as they 468 // appear in the property browser UI. 469 for ( EventMapIndexAccess::const_iterator loop = m_aEventIndexAccess.begin(); 470 loop != m_aEventIndexAccess.end(); 471 ++loop, ++pReturn 472 ) 473 *pReturn = loop->second->first; 474 return aReturn; 475 } 476 477 //------------------------------------------------------------------------ 478 sal_Bool SAL_CALL EventHolder::hasByName( const ::rtl::OUString& _rName ) throw (RuntimeException) 479 { 480 EventMap::const_iterator pos = m_aEventNameAccess.find( _rName ); 481 return pos != m_aEventNameAccess.end(); 482 } 483 484 //------------------------------------------------------------------------ 485 Type SAL_CALL EventHolder::getElementType( ) throw (RuntimeException) 486 { 487 return ::getCppuType( static_cast< Sequence< PropertyValue >* >( NULL ) ); 488 } 489 490 //------------------------------------------------------------------------ 491 sal_Bool SAL_CALL EventHolder::hasElements( ) throw (RuntimeException) 492 { 493 return !m_aEventNameAccess.empty(); 494 } 495 496 497 //==================================================================== 498 //= EventHandler 499 //==================================================================== 500 DBG_NAME( EventHandler ) 501 //-------------------------------------------------------------------- 502 EventHandler::EventHandler( const Reference< XComponentContext >& _rxContext ) 503 :EventHandler_Base( m_aMutex ) 504 ,m_aContext( _rxContext ) 505 ,m_aPropertyListeners( m_aMutex ) 506 ,m_bEventsMapInitialized( false ) 507 ,m_bIsDialogElement( false ) 508 ,m_nGridColumnType( -1 ) 509 { 510 DBG_CTOR( EventHandler, NULL ); 511 } 512 513 //-------------------------------------------------------------------- 514 EventHandler::~EventHandler() 515 { 516 DBG_DTOR( EventHandler, NULL ); 517 } 518 519 //-------------------------------------------------------------------- 520 ::rtl::OUString SAL_CALL EventHandler::getImplementationName( ) throw (RuntimeException) 521 { 522 return getImplementationName_static(); 523 } 524 525 //-------------------------------------------------------------------- 526 ::sal_Bool SAL_CALL EventHandler::supportsService( const ::rtl::OUString& ServiceName ) throw (RuntimeException) 527 { 528 StlSyntaxSequence< ::rtl::OUString > aAllServices( getSupportedServiceNames() ); 529 return ::std::find( aAllServices.begin(), aAllServices.end(), ServiceName ) != aAllServices.end(); 530 } 531 532 //-------------------------------------------------------------------- 533 Sequence< ::rtl::OUString > SAL_CALL EventHandler::getSupportedServiceNames( ) throw (RuntimeException) 534 { 535 return getSupportedServiceNames_static(); 536 } 537 538 //-------------------------------------------------------------------- 539 ::rtl::OUString SAL_CALL EventHandler::getImplementationName_static( ) throw (RuntimeException) 540 { 541 return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.extensions.EventHandler" ) ); 542 } 543 544 //-------------------------------------------------------------------- 545 Sequence< ::rtl::OUString > SAL_CALL EventHandler::getSupportedServiceNames_static( ) throw (RuntimeException) 546 { 547 Sequence< ::rtl::OUString > aSupported( 1 ); 548 aSupported[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.form.inspection.EventHandler" ) ); 549 return aSupported; 550 } 551 552 //-------------------------------------------------------------------- 553 Reference< XInterface > SAL_CALL EventHandler::Create( const Reference< XComponentContext >& _rxContext ) 554 { 555 return *( new EventHandler( _rxContext ) ); 556 } 557 558 //-------------------------------------------------------------------- 559 void SAL_CALL EventHandler::inspect( const Reference< XInterface >& _rxIntrospectee ) throw (RuntimeException, NullPointerException) 560 { 561 ::osl::MutexGuard aGuard( m_aMutex ); 562 563 if ( !_rxIntrospectee.is() ) 564 throw NullPointerException(); 565 566 m_xComponent = Reference< XPropertySet >( _rxIntrospectee, UNO_QUERY_THROW ); 567 568 m_bEventsMapInitialized = false; 569 EventMap aEmpty; 570 m_aEvents.swap( aEmpty ); 571 572 m_bIsDialogElement = false; 573 m_nGridColumnType = -1; 574 try 575 { 576 Reference< XPropertySetInfo > xPSI( m_xComponent->getPropertySetInfo() ); 577 m_bIsDialogElement = xPSI.is() 578 && xPSI->hasPropertyByName( PROPERTY_WIDTH ) 579 && xPSI->hasPropertyByName( PROPERTY_HEIGHT ) 580 && xPSI->hasPropertyByName( PROPERTY_POSITIONX ) 581 && xPSI->hasPropertyByName( PROPERTY_POSITIONY ); 582 583 Reference< XChild > xAsChild( _rxIntrospectee, UNO_QUERY ); 584 if ( xAsChild.is() && !Reference< XForm >( _rxIntrospectee, UNO_QUERY ).is() ) 585 { 586 if ( FormComponentType::GRIDCONTROL == classifyComponent( xAsChild->getParent() ) ) 587 { 588 m_nGridColumnType = classifyComponent( _rxIntrospectee ); 589 } 590 } 591 } 592 catch( const Exception& ) 593 { 594 DBG_UNHANDLED_EXCEPTION(); 595 } 596 } 597 598 //-------------------------------------------------------------------- 599 Any SAL_CALL EventHandler::getPropertyValue( const ::rtl::OUString& _rPropertyName ) throw (UnknownPropertyException, RuntimeException) 600 { 601 ::osl::MutexGuard aGuard( m_aMutex ); 602 603 const EventDescription& rEvent = impl_getEventForName_throw( _rPropertyName ); 604 605 Sequence< ScriptEventDescriptor > aEvents; 606 impl_getComponentScriptEvents_nothrow( aEvents ); 607 608 sal_Int32 nEventCount = aEvents.getLength(); 609 const ScriptEventDescriptor* pEvents = aEvents.getConstArray(); 610 611 ScriptEventDescriptor aPropertyValue; 612 for ( sal_Int32 event = 0; event < nEventCount; ++event, ++pEvents ) 613 { 614 if ( rEvent.sListenerClassName == pEvents->ListenerType 615 && rEvent.sListenerMethodName == pEvents->EventMethod 616 ) 617 { 618 aPropertyValue = *pEvents; 619 break; 620 } 621 } 622 623 return makeAny( aPropertyValue ); 624 } 625 626 //-------------------------------------------------------------------- 627 void SAL_CALL EventHandler::setPropertyValue( const ::rtl::OUString& _rPropertyName, const Any& _rValue ) throw (UnknownPropertyException, RuntimeException) 628 { 629 ::osl::MutexGuard aGuard( m_aMutex ); 630 631 const EventDescription& rEvent = impl_getEventForName_throw( _rPropertyName ); 632 633 ScriptEventDescriptor aNewScriptEvent; 634 OSL_VERIFY( _rValue >>= aNewScriptEvent ); 635 636 ScriptEventDescriptor aOldScriptEvent; 637 OSL_VERIFY( getPropertyValue( _rPropertyName ) >>= aOldScriptEvent ); 638 if ( aOldScriptEvent == aNewScriptEvent ) 639 return; 640 641 if ( m_bIsDialogElement ) 642 impl_setDialogElementScriptEvent_nothrow( aNewScriptEvent ); 643 else 644 impl_setFormComponentScriptEvent_nothrow( aNewScriptEvent ); 645 646 Reference< XModifiable > xDoc( m_aContext.getContextValueByAsciiName( "ContextDocument" ), UNO_QUERY ); 647 if ( xDoc.is() ) 648 xDoc->setModified( sal_True ); 649 650 PropertyChangeEvent aEvent; 651 aEvent.Source = m_xComponent; 652 aEvent.PropertyHandle = rEvent.nId; 653 aEvent.PropertyName = _rPropertyName; 654 aEvent.OldValue <<= aOldScriptEvent; 655 aEvent.NewValue <<= aNewScriptEvent; 656 m_aPropertyListeners.notify( aEvent, &XPropertyChangeListener::propertyChange ); 657 } 658 659 //-------------------------------------------------------------------- 660 Any SAL_CALL EventHandler::convertToPropertyValue( const ::rtl::OUString& _rPropertyName, const Any& _rControlValue ) throw (UnknownPropertyException, RuntimeException) 661 { 662 ::osl::MutexGuard aGuard( m_aMutex ); 663 664 ::rtl::OUString sNewScriptCode; 665 OSL_VERIFY( _rControlValue >>= sNewScriptCode ); 666 667 Sequence< ScriptEventDescriptor > aAllAssignedEvents; 668 impl_getComponentScriptEvents_nothrow( aAllAssignedEvents ); 669 670 const EventDescription& rEvent = impl_getEventForName_throw( _rPropertyName ); 671 ScriptEventDescriptor aAssignedScript = lcl_getAssignedScriptEvent( rEvent, aAllAssignedEvents ); 672 673 OSL_ENSURE( !sNewScriptCode.getLength(), "EventHandler::convertToPropertyValue: cannot convert a non-empty display name!" ); 674 // Usually, there is no possibility for the user to change the content of an event binding directly in the 675 // input field, this instead is done with the macro assignment dialog. 676 // The only exception is the user pressing "DEL" while the control has the focus, in this case, we reset the 677 // control content to an empty string. So this is the only scenario where this method is allowed to be called. 678 679 // Striclty, we would be able to convert the display value to a property value, 680 // using the "name (location, language)" format we used in convertToControlValue. However, 681 // there is no need for this code ... 682 683 aAssignedScript.ScriptCode = sNewScriptCode; 684 return makeAny( aAssignedScript ); 685 } 686 687 //-------------------------------------------------------------------- 688 Any SAL_CALL EventHandler::convertToControlValue( const ::rtl::OUString& /*_rPropertyName*/, const Any& _rPropertyValue, const Type& _rControlValueType ) throw (UnknownPropertyException, RuntimeException) 689 { 690 ::osl::MutexGuard aGuard( m_aMutex ); 691 692 ScriptEventDescriptor aScriptEvent; 693 OSL_VERIFY( _rPropertyValue >>= aScriptEvent ); 694 695 OSL_ENSURE( _rControlValueType.getTypeClass() == TypeClass_STRING, 696 "EventHandler::convertToControlValue: unexpected ControlValue type class!" ); 697 (void)_rControlValueType; 698 699 ::rtl::OUString sScript( aScriptEvent.ScriptCode ); 700 if ( sScript.getLength() ) 701 { 702 // format is: "name (location, language)" 703 try 704 { 705 // parse 706 Reference< XUriReferenceFactory > xUriRefFac = UriReferenceFactory::create( m_aContext.getUNOContext() ); 707 Reference< XVndSunStarScriptUrlReference > xScriptUri( xUriRefFac->parse( sScript ), UNO_QUERY_THROW ); 708 709 ::rtl::OUStringBuffer aComposeBuffer; 710 711 // name 712 aComposeBuffer.append( xScriptUri->getName() ); 713 714 // location 715 const ::rtl::OUString sLocationParamName( RTL_CONSTASCII_USTRINGPARAM( "location" ) ); 716 const ::rtl::OUString sLocation = xScriptUri->getParameter( sLocationParamName ); 717 const ::rtl::OUString sLangParamName( RTL_CONSTASCII_USTRINGPARAM( "language" ) ); 718 const ::rtl::OUString sLanguage = xScriptUri->getParameter( sLangParamName ); 719 720 if ( sLocation.getLength() || sLanguage.getLength() ) 721 { 722 aComposeBuffer.appendAscii( " (" ); 723 724 // location 725 OSL_ENSURE( sLocation.getLength(), "EventHandler::convertToControlValue: unexpected: no location!" ); 726 if ( sLocation.getLength() ) 727 { 728 aComposeBuffer.append( sLocation ); 729 aComposeBuffer.appendAscii( ", " ); 730 } 731 732 // language 733 if ( sLanguage.getLength() ) 734 { 735 aComposeBuffer.append( sLanguage ); 736 } 737 738 aComposeBuffer.append( sal_Unicode( ')' ) ); 739 } 740 741 sScript = aComposeBuffer.makeStringAndClear(); 742 } 743 catch( const Exception& ) 744 { 745 DBG_UNHANDLED_EXCEPTION(); 746 } 747 } 748 749 return makeAny( sScript ); 750 } 751 752 //-------------------------------------------------------------------- 753 PropertyState SAL_CALL EventHandler::getPropertyState( const ::rtl::OUString& /*_rPropertyName*/ ) throw (UnknownPropertyException, RuntimeException) 754 { 755 return PropertyState_DIRECT_VALUE; 756 } 757 758 //-------------------------------------------------------------------- 759 void SAL_CALL EventHandler::addPropertyChangeListener( const Reference< XPropertyChangeListener >& _rxListener ) throw (RuntimeException) 760 { 761 ::osl::MutexGuard aGuard( m_aMutex ); 762 if ( !_rxListener.is() ) 763 throw NullPointerException(); 764 m_aPropertyListeners.addListener( _rxListener ); 765 } 766 767 //-------------------------------------------------------------------- 768 void SAL_CALL EventHandler::removePropertyChangeListener( const Reference< XPropertyChangeListener >& _rxListener ) throw (RuntimeException) 769 { 770 ::osl::MutexGuard aGuard( m_aMutex ); 771 m_aPropertyListeners.removeListener( _rxListener ); 772 } 773 774 //-------------------------------------------------------------------- 775 Sequence< Property > SAL_CALL EventHandler::getSupportedProperties() throw (RuntimeException) 776 { 777 ::osl::MutexGuard aGuard( m_aMutex ); 778 if ( !m_bEventsMapInitialized ) 779 { 780 const_cast< EventHandler* >( this )->m_bEventsMapInitialized = true; 781 try 782 { 783 Sequence< Type > aListeners; 784 impl_getCopmonentListenerTypes_nothrow( aListeners ); 785 sal_Int32 listenerCount = aListeners.getLength(); 786 787 Property aCurrentProperty; 788 ::rtl::OUString sListenerClassName; 789 790 // loop through all listeners and all methods, and see which we can present at the UI 791 const Type* pListeners = aListeners.getConstArray(); 792 for ( sal_Int32 listener = 0; listener < listenerCount; ++listener, ++pListeners ) 793 { 794 aCurrentProperty = Property(); 795 796 // the programmatic name of the listener, to be used as "property" name 797 sListenerClassName = pListeners->getTypeName(); 798 OSL_ENSURE( sListenerClassName.getLength(), "EventHandler::getSupportedProperties: strange - no listener name ..." ); 799 if ( !sListenerClassName.getLength() ) 800 continue; 801 802 // loop through all methods 803 Sequence< ::rtl::OUString > aMethods( comphelper::getEventMethodsForType( *pListeners ) ); 804 805 const ::rtl::OUString* pMethods = aMethods.getConstArray(); 806 sal_uInt32 methodCount = aMethods.getLength(); 807 808 for (sal_uInt32 method = 0 ; method < methodCount ; ++method, ++pMethods ) 809 { 810 EventDescription aEvent; 811 if ( !lcl_getEventDescriptionForMethod( *pMethods, aEvent ) ) 812 continue; 813 814 if ( !impl_filterMethod_nothrow( aEvent ) ) 815 continue; 816 817 const_cast< EventHandler* >( this )->m_aEvents.insert( EventMap::value_type( 818 lcl_getEventPropertyName( sListenerClassName, *pMethods ), aEvent ) ); 819 } 820 } 821 822 } 823 catch( const Exception& ) 824 { 825 DBG_UNHANDLED_EXCEPTION(); 826 } 827 } 828 829 // sort them by ID - this is the relative ordering in the UI 830 ::std::map< EventId, Property > aOrderedProperties; 831 for ( EventMap::const_iterator loop = m_aEvents.begin(); 832 loop != m_aEvents.end(); 833 ++loop 834 ) 835 { 836 aOrderedProperties[ loop->second.nId ] = Property( 837 loop->first, loop->second.nId, 838 ::getCppuType( static_cast< const ::rtl::OUString* >( NULL ) ), 839 PropertyAttribute::BOUND ); 840 } 841 842 StlSyntaxSequence< Property > aReturn( aOrderedProperties.size() ); 843 ::std::transform( aOrderedProperties.begin(), aOrderedProperties.end(), aReturn.begin(), 844 ::std::select2nd< ::std::map< EventId, Property >::value_type >() ); 845 return aReturn; 846 } 847 848 //-------------------------------------------------------------------- 849 Sequence< ::rtl::OUString > SAL_CALL EventHandler::getSupersededProperties( ) throw (RuntimeException) 850 { 851 // none 852 return Sequence< ::rtl::OUString >( ); 853 } 854 855 //-------------------------------------------------------------------- 856 Sequence< ::rtl::OUString > SAL_CALL EventHandler::getActuatingProperties( ) throw (RuntimeException) 857 { 858 // none 859 return Sequence< ::rtl::OUString >( ); 860 } 861 862 //-------------------------------------------------------------------- 863 LineDescriptor SAL_CALL EventHandler::describePropertyLine( const ::rtl::OUString& _rPropertyName, 864 const Reference< XPropertyControlFactory >& _rxControlFactory ) 865 throw (UnknownPropertyException, NullPointerException, RuntimeException) 866 { 867 if ( !_rxControlFactory.is() ) 868 throw NullPointerException(); 869 870 ::osl::MutexGuard aGuard( m_aMutex ); 871 872 LineDescriptor aDescriptor; 873 874 aDescriptor.Control = _rxControlFactory->createPropertyControl( PropertyControlType::TextField, sal_True ); 875 Reference< XEventListener > xControlExtender = new PropertyControlExtender( aDescriptor.Control ); 876 877 const EventDescription& rEvent = impl_getEventForName_throw( _rPropertyName ); 878 aDescriptor.DisplayName = rEvent.sDisplayName; 879 aDescriptor.HelpURL = HelpIdUrl::getHelpURL( rEvent.sHelpId ); 880 aDescriptor.PrimaryButtonId = rtl::OStringToOUString(rEvent.sUniqueBrowseId, RTL_TEXTENCODING_UTF8); 881 aDescriptor.HasPrimaryButton = sal_True; 882 aDescriptor.Category = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Events" ) ); 883 return aDescriptor; 884 } 885 886 //-------------------------------------------------------------------- 887 ::sal_Bool SAL_CALL EventHandler::isComposable( const ::rtl::OUString& /*_rPropertyName*/ ) throw (UnknownPropertyException, RuntimeException) 888 { 889 return sal_False; 890 } 891 892 //-------------------------------------------------------------------- 893 InteractiveSelectionResult SAL_CALL EventHandler::onInteractivePropertySelection( const ::rtl::OUString& _rPropertyName, sal_Bool /*_bPrimary*/, Any& /*_rData*/, const Reference< XObjectInspectorUI >& _rxInspectorUI ) throw (UnknownPropertyException, NullPointerException, RuntimeException) 894 { 895 if ( !_rxInspectorUI.is() ) 896 throw NullPointerException(); 897 898 ::osl::MutexGuard aGuard( m_aMutex ); 899 const EventDescription& rForEvent = impl_getEventForName_throw( _rPropertyName ); 900 901 Sequence< ScriptEventDescriptor > aAllAssignedEvents; 902 impl_getComponentScriptEvents_nothrow( aAllAssignedEvents ); 903 904 // SvxMacroAssignDlg-compatible structure holding all event/assignments 905 ::rtl::Reference< EventHolder > pEventHolder( new EventHolder ); 906 907 for ( EventMap::const_iterator event = m_aEvents.begin(); 908 event != m_aEvents.end(); 909 ++event 910 ) 911 { 912 // the script which is assigned to the current event (if any) 913 ScriptEventDescriptor aAssignedScript = lcl_getAssignedScriptEvent( event->second, aAllAssignedEvents ); 914 pEventHolder->addEvent( event->second.nId, event->second.sListenerMethodName, aAssignedScript ); 915 } 916 917 // the inital selection in the dialog 918 Sequence< ::rtl::OUString > aNames( pEventHolder->getElementNames() ); 919 const ::rtl::OUString* pChosenEvent = ::std::find( aNames.getConstArray(), aNames.getConstArray() + aNames.getLength(), rForEvent.sListenerMethodName ); 920 sal_uInt16 nInitialSelection = (sal_uInt16)( pChosenEvent - aNames.getConstArray() ); 921 922 // the dialog 923 SvxAbstractDialogFactory* pFactory = SvxAbstractDialogFactory::Create(); 924 if ( !pFactory ) 925 return InteractiveSelectionResult_Cancelled; 926 927 ::std::auto_ptr< VclAbstractDialog > pDialog( pFactory->CreateSvxMacroAssignDlg( 928 PropertyHandlerHelper::getDialogParentWindow( m_aContext ), 929 impl_getContextFrame_nothrow(), 930 m_bIsDialogElement, 931 pEventHolder.get(), 932 nInitialSelection 933 ) ); 934 935 if ( !pDialog.get() ) 936 return InteractiveSelectionResult_Cancelled; 937 938 // DF definite problem here 939 // OK & Cancel seem to be both returning 0 940 if ( pDialog->Execute() == RET_CANCEL ) 941 return InteractiveSelectionResult_Cancelled; 942 943 try 944 { 945 for ( EventMap::const_iterator event = m_aEvents.begin(); 946 event != m_aEvents.end(); 947 ++event 948 ) 949 { 950 ScriptEventDescriptor aScriptDescriptor( pEventHolder->getNormalizedDescriptorByName( event->second.sListenerMethodName ) ); 951 952 // set the new "property value" 953 setPropertyValue( 954 lcl_getEventPropertyName( event->second.sListenerClassName, event->second.sListenerMethodName ), 955 makeAny( aScriptDescriptor ) 956 ); 957 } 958 } 959 catch( const Exception& ) 960 { 961 DBG_UNHANDLED_EXCEPTION(); 962 } 963 964 return InteractiveSelectionResult_Success; 965 } 966 967 //-------------------------------------------------------------------- 968 void SAL_CALL EventHandler::actuatingPropertyChanged( const ::rtl::OUString& /*_rActuatingPropertyName*/, const Any& /*_rNewValue*/, const Any& /*_rOldValue*/, const Reference< XObjectInspectorUI >& /*_rxInspectorUI*/, sal_Bool /*_bFirstTimeInit*/ ) throw (NullPointerException, RuntimeException) 969 { 970 DBG_ERROR( "EventHandler::actuatingPropertyChanged: no actuating properties -> no callback (well, this is how it *should* be!)" ); 971 } 972 973 //-------------------------------------------------------------------- 974 IMPLEMENT_FORWARD_XCOMPONENT( EventHandler, EventHandler_Base ) 975 976 //-------------------------------------------------------------------- 977 void SAL_CALL EventHandler::disposing() 978 { 979 EventMap aEmpty; 980 m_aEvents.swap( aEmpty ); 981 m_xComponent.clear(); 982 } 983 984 //-------------------------------------------------------------------- 985 sal_Bool SAL_CALL EventHandler::suspend( sal_Bool /*_bSuspend*/ ) throw (RuntimeException) 986 { 987 return sal_True; 988 } 989 990 //------------------------------------------------------------------------ 991 Reference< XFrame > EventHandler::impl_getContextFrame_nothrow() const 992 { 993 Reference< XFrame > xContextFrame; 994 995 try 996 { 997 Reference< XModel > xContextDocument( m_aContext.getContextValueByAsciiName( "ContextDocument" ), UNO_QUERY_THROW ); 998 Reference< XController > xController( xContextDocument->getCurrentController(), UNO_SET_THROW ); 999 xContextFrame.set( xController->getFrame(), UNO_SET_THROW ); 1000 } 1001 catch( const Exception& ) 1002 { 1003 DBG_UNHANDLED_EXCEPTION(); 1004 } 1005 1006 return xContextFrame; 1007 } 1008 1009 //-------------------------------------------------------------------- 1010 sal_Int32 EventHandler::impl_getComponentIndexInParent_throw() const 1011 { 1012 Reference< XChild > xChild( m_xComponent, UNO_QUERY_THROW ); 1013 Reference< XIndexAccess > xParentAsIndexAccess( xChild->getParent(), UNO_QUERY_THROW ); 1014 1015 // get the index of the inspected object within it's parent container 1016 sal_Int32 nElements = xParentAsIndexAccess->getCount(); 1017 for ( sal_Int32 i=0; i<nElements; ++i ) 1018 { 1019 Reference< XInterface > xElement( xParentAsIndexAccess->getByIndex( i ), UNO_QUERY_THROW ); 1020 if ( xElement == m_xComponent ) 1021 return i; 1022 } 1023 throw NoSuchElementException(); 1024 } 1025 1026 //-------------------------------------------------------------------- 1027 void EventHandler::impl_getFormComponentScriptEvents_nothrow( Sequence < ScriptEventDescriptor >& _out_rEvents ) const 1028 { 1029 _out_rEvents = Sequence < ScriptEventDescriptor >(); 1030 try 1031 { 1032 Reference< XChild > xChild( m_xComponent, UNO_QUERY_THROW ); 1033 Reference< XEventAttacherManager > xEventManager( xChild->getParent(), UNO_QUERY_THROW ); 1034 _out_rEvents = xEventManager->getScriptEvents( impl_getComponentIndexInParent_throw() ); 1035 1036 // the form component script API has unqualified listener names, but for normalization 1037 // purpose, we want fully qualified ones 1038 ScriptEventDescriptor* pEvents = _out_rEvents.getArray(); 1039 ScriptEventDescriptor* pEventsEnd = _out_rEvents.getArray() + _out_rEvents.getLength(); 1040 while ( pEvents != pEventsEnd ) 1041 { 1042 pEvents->ListenerType = lcl_getQualifiedKnownListenerName( *pEvents ); 1043 ++pEvents; 1044 } 1045 } 1046 catch( const Exception& ) 1047 { 1048 DBG_UNHANDLED_EXCEPTION(); 1049 } 1050 } 1051 1052 //-------------------------------------------------------------------- 1053 void EventHandler::impl_getCopmonentListenerTypes_nothrow( Sequence< Type >& _out_rTypes ) const 1054 { 1055 _out_rTypes.realloc( 0 ); 1056 try 1057 { 1058 // we use a set to avoid duplicates 1059 TypeBag aListeners; 1060 1061 Reference< XIntrospection > xIntrospection( m_aContext.createComponent( "com.sun.star.beans.Introspection" ), UNO_QUERY_THROW ); 1062 1063 // --- model listeners 1064 lcl_addListenerTypesFor_throw( 1065 m_xComponent, xIntrospection, aListeners ); 1066 1067 // --- "secondary component" (usually: "control" listeners) 1068 { 1069 Reference< XInterface > xSecondaryComponent( impl_getSecondaryComponentForEventInspection_throw() ); 1070 lcl_addListenerTypesFor_throw( xSecondaryComponent, xIntrospection, aListeners ); 1071 ::comphelper::disposeComponent( xSecondaryComponent ); 1072 } 1073 1074 // now that they're disambiguated, copy these types into our member 1075 _out_rTypes.realloc( aListeners.size() ); 1076 ::std::copy( aListeners.begin(), aListeners.end(), _out_rTypes.getArray() ); 1077 } 1078 catch( const Exception& ) 1079 { 1080 DBG_UNHANDLED_EXCEPTION(); 1081 } 1082 } 1083 1084 //-------------------------------------------------------------------- 1085 void EventHandler::impl_getDialogElementScriptEvents_nothrow( Sequence < ScriptEventDescriptor >& _out_rEvents ) const 1086 { 1087 _out_rEvents = Sequence < ScriptEventDescriptor >(); 1088 try 1089 { 1090 Reference< XScriptEventsSupplier > xEventsSupplier( m_xComponent, UNO_QUERY_THROW ); 1091 Reference< XNameContainer > xEvents( xEventsSupplier->getEvents(), UNO_QUERY_THROW ); 1092 Sequence< ::rtl::OUString > aEventNames( xEvents->getElementNames() ); 1093 1094 sal_Int32 nEventCount = aEventNames.getLength(); 1095 _out_rEvents.realloc( nEventCount ); 1096 1097 const ::rtl::OUString* pNames = aEventNames.getConstArray(); 1098 ScriptEventDescriptor* pDescs = _out_rEvents.getArray(); 1099 1100 for( sal_Int32 i = 0 ; i < nEventCount ; ++i, ++pNames, ++pDescs ) 1101 OSL_VERIFY( xEvents->getByName( *pNames ) >>= *pDescs ); 1102 } 1103 catch( const Exception& ) 1104 { 1105 DBG_UNHANDLED_EXCEPTION(); 1106 } 1107 } 1108 1109 //-------------------------------------------------------------------- 1110 Reference< XInterface > EventHandler::impl_getSecondaryComponentForEventInspection_throw( ) const 1111 { 1112 Reference< XInterface > xReturn; 1113 1114 // if it's a form, create a form controller for the additional events 1115 Reference< XForm > xComponentAsForm( m_xComponent, UNO_QUERY ); 1116 if ( xComponentAsForm.is() ) 1117 { 1118 Reference< XTabControllerModel > xComponentAsTCModel( m_xComponent, UNO_QUERY_THROW ); 1119 Reference< XFormController > xController( 1120 m_aContext.createComponent( "com.sun.star.form.runtime.FormController" ), UNO_QUERY_THROW ); 1121 xController->setModel( xComponentAsTCModel ); 1122 1123 xReturn = xController; 1124 } 1125 else 1126 { 1127 ::rtl::OUString sControlService; 1128 OSL_VERIFY( m_xComponent->getPropertyValue( PROPERTY_DEFAULTCONTROL ) >>= sControlService ); 1129 1130 xReturn = m_aContext.createComponent( sControlService ); 1131 } 1132 return xReturn; 1133 } 1134 1135 //-------------------------------------------------------------------- 1136 const EventDescription& EventHandler::impl_getEventForName_throw( const ::rtl::OUString& _rPropertyName ) const 1137 { 1138 EventMap::const_iterator pos = m_aEvents.find( _rPropertyName ); 1139 if ( pos == m_aEvents.end() ) 1140 throw UnknownPropertyException(); 1141 return pos->second; 1142 } 1143 1144 //-------------------------------------------------------------------- 1145 namespace 1146 { 1147 static bool lcl_endsWith( const ::rtl::OUString& _rText, const ::rtl::OUString& _rCheck ) 1148 { 1149 sal_Int32 nTextLen = _rText.getLength(); 1150 sal_Int32 nCheckLen = _rCheck.getLength(); 1151 if ( nCheckLen > nTextLen ) 1152 return false; 1153 1154 return _rText.indexOf( _rCheck ) == ( nTextLen - nCheckLen ); 1155 } 1156 } 1157 //-------------------------------------------------------------------- 1158 void EventHandler::impl_setFormComponentScriptEvent_nothrow( const ScriptEventDescriptor& _rScriptEvent ) 1159 { 1160 try 1161 { 1162 ::rtl::OUString sScriptCode( _rScriptEvent.ScriptCode ); 1163 ::rtl::OUString sScriptType( _rScriptEvent.ScriptType ); 1164 bool bResetScript = ( sScriptCode.getLength() == 0 ); 1165 1166 sal_Int32 nObjectIndex = impl_getComponentIndexInParent_throw(); 1167 Reference< XChild > xChild( m_xComponent, UNO_QUERY_THROW ); 1168 Reference< XEventAttacherManager > xEventManager( xChild->getParent(), UNO_QUERY_THROW ); 1169 Sequence< ScriptEventDescriptor > aEvents( xEventManager->getScriptEvents( nObjectIndex ) ); 1170 1171 // is there already a registered script for this event? 1172 ScriptEventDescriptor* pEvent = aEvents.getArray(); 1173 sal_Int32 eventCount = aEvents.getLength(), event = 0; 1174 for ( event = 0; event < eventCount; ++event, ++pEvent ) 1175 { 1176 if ( ( pEvent->EventMethod == _rScriptEvent.EventMethod ) 1177 && ( lcl_endsWith( _rScriptEvent.ListenerType, pEvent->ListenerType ) ) 1178 // (strange enough, the events we get from getScriptEvents are not fully qualified) 1179 ) 1180 { 1181 // yes 1182 if ( !bResetScript ) 1183 { 1184 // set to something non-empty -> overwrite 1185 pEvent->ScriptCode = sScriptCode; 1186 pEvent->ScriptType = sScriptType; 1187 } 1188 else 1189 { 1190 // set to empty -> remove from sequence 1191 ::std::copy( pEvent + 1, aEvents.getArray() + eventCount, pEvent ); 1192 aEvents.realloc( eventCount - 1 ); 1193 --eventCount; 1194 } 1195 break; 1196 } 1197 } 1198 if ( ( event >= eventCount ) && !bResetScript ) 1199 { 1200 // no, did not find it -> append 1201 aEvents.realloc( eventCount + 1 ); 1202 aEvents[ eventCount ] = _rScriptEvent; 1203 } 1204 1205 xEventManager->revokeScriptEvents( nObjectIndex ); 1206 xEventManager->registerScriptEvents( nObjectIndex, aEvents ); 1207 1208 PropertyHandlerHelper::setContextDocumentModified( m_aContext ); 1209 } 1210 catch( const Exception& ) 1211 { 1212 DBG_UNHANDLED_EXCEPTION(); 1213 } 1214 } 1215 1216 //-------------------------------------------------------------------- 1217 void EventHandler::impl_setDialogElementScriptEvent_nothrow( const ScriptEventDescriptor& _rScriptEvent ) 1218 { 1219 try 1220 { 1221 ::rtl::OUString sScriptCode( _rScriptEvent.ScriptCode ); 1222 bool bResetScript = ( sScriptCode.getLength() == 0 ); 1223 1224 Reference< XScriptEventsSupplier > xEventsSupplier( m_xComponent, UNO_QUERY_THROW ); 1225 Reference< XNameContainer > xEvents( xEventsSupplier->getEvents(), UNO_QUERY_THROW ); 1226 1227 ::rtl::OUStringBuffer aCompleteName; 1228 aCompleteName.append( _rScriptEvent.ListenerType ); 1229 aCompleteName.appendAscii( "::" ); 1230 aCompleteName.append( _rScriptEvent.EventMethod ); 1231 ::rtl::OUString sCompleteName( aCompleteName.makeStringAndClear() ); 1232 1233 bool bExists = xEvents->hasByName( sCompleteName ); 1234 1235 if ( bResetScript ) 1236 { 1237 if ( bExists ) 1238 xEvents->removeByName( sCompleteName ); 1239 } 1240 else 1241 { 1242 Any aNewValue; aNewValue <<= _rScriptEvent; 1243 1244 if ( bExists ) 1245 xEvents->replaceByName( sCompleteName, aNewValue ); 1246 else 1247 xEvents->insertByName( sCompleteName, aNewValue ); 1248 } 1249 } 1250 catch( const Exception& ) 1251 { 1252 DBG_UNHANDLED_EXCEPTION(); 1253 } 1254 } 1255 1256 //-------------------------------------------------------------------- 1257 bool EventHandler::impl_filterMethod_nothrow( const EventDescription& _rEvent ) const 1258 { 1259 // some (control-triggered) events do not make sense for certain grid control columns. However, 1260 // our mechnism to retrieve control-triggered events does not know about this, so we do some 1261 // late filtering here. 1262 switch ( m_nGridColumnType ) 1263 { 1264 case FormComponentType::COMBOBOX: 1265 if ( UID_BRWEVT_ACTIONPERFORMED == _rEvent.sUniqueBrowseId ) 1266 return false; 1267 break; 1268 case FormComponentType::LISTBOX: 1269 if ( ( UID_BRWEVT_CHANGED == _rEvent.sUniqueBrowseId ) 1270 || ( UID_BRWEVT_ACTIONPERFORMED == _rEvent.sUniqueBrowseId ) 1271 ) 1272 return false; 1273 break; 1274 } 1275 1276 return true; 1277 } 1278 1279 //........................................................................ 1280 } // namespace pcr 1281 //........................................................................ 1282 1283