merge the formfield patch from ooo-build
[ooovba.git] / extensions / source / propctrlr / eventhandler.cxx
blobfa5af81303f6b375dcf7eca8c667349e8a872c1b
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: eventhandler.cxx,v $
10 * $Revision: 1.13 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_extensions.hxx"
34 #include "eventhandler.hxx"
35 #include "extensio.hrc"
36 #include "formbrowsertools.hxx"
37 #include "formresid.hrc"
38 #include "formstrings.hxx"
39 #include "handlerhelper.hxx"
40 #include "modulepcr.hxx"
41 #include "pcrcommon.hxx"
42 #include "pcrstrings.hxx"
43 #include "propertycontrolextender.hxx"
45 /** === begin UNO includes === **/
46 #include <com/sun/star/awt/XTabControllerModel.hpp>
47 #include <com/sun/star/beans/PropertyAttribute.hpp>
48 #include <com/sun/star/beans/UnknownPropertyException.hpp>
49 #include <com/sun/star/beans/XIntrospection.hpp>
50 #include <com/sun/star/beans/XIntrospectionAccess.hpp>
51 #include <com/sun/star/container/NoSuchElementException.hpp>
52 #include <com/sun/star/container/XChild.hpp>
53 #include <com/sun/star/container/XIndexAccess.hpp>
54 #include <com/sun/star/container/XNameContainer.hpp>
55 #include <com/sun/star/container/XNameReplace.hpp>
56 #include <com/sun/star/form/FormComponentType.hpp>
57 #include <com/sun/star/form/XForm.hpp>
58 #include <com/sun/star/form/XFormController.hpp>
59 #include <com/sun/star/inspection/PropertyControlType.hpp>
60 #include <com/sun/star/lang/NullPointerException.hpp>
61 #include <com/sun/star/script/XEventAttacherManager.hpp>
62 #include <com/sun/star/script/XScriptEventsSupplier.hpp>
63 #include <com/sun/star/util/XModifiable.hpp>
64 #include <com/sun/star/uri/UriReferenceFactory.hpp>
65 #include <com/sun/star/uri/XVndSunStarScriptUrlReference.hpp>
66 /** === end UNO includes === **/
68 #include <comphelper/namedvaluecollection.hxx>
69 #include <comphelper/evtmethodhelper.hxx>
70 #include <comphelper/types.hxx>
71 #include <cppuhelper/implbase1.hxx>
72 #include <rtl/ref.hxx>
73 #include <rtl/ustrbuf.hxx>
74 #include <sfx2/app.hxx>
75 #include <svtools/eitem.hxx>
76 #include <svtools/itemset.hxx>
77 #include <svx/svxdlg.hxx>
78 #include <svx/svxids.hrc>
79 #include <tools/diagnose_ex.h>
81 #include <map>
82 #include <algorithm>
84 //------------------------------------------------------------------------
85 extern "C" void SAL_CALL createRegistryInfo_EventHandler()
87 ::pcr::OAutoRegistration< ::pcr::EventHandler > aAutoRegistration;
90 //........................................................................
91 namespace pcr
93 //........................................................................
95 /** === begin UNO using === **/
96 using ::com::sun::star::uno::Reference;
97 using ::com::sun::star::uno::XComponentContext;
98 using ::com::sun::star::beans::XPropertySet;
99 using ::com::sun::star::uno::Any;
100 using ::com::sun::star::uno::TypeClass_STRING;
101 using ::com::sun::star::uno::Type;
102 using ::com::sun::star::beans::XPropertyChangeListener;
103 using ::com::sun::star::beans::Property;
104 using ::com::sun::star::beans::PropertyState;
105 using ::com::sun::star::beans::PropertyState_DIRECT_VALUE;
106 using ::com::sun::star::uno::Sequence;
107 using ::com::sun::star::script::ScriptEventDescriptor;
108 using ::com::sun::star::script::XScriptEventsSupplier;
109 using ::com::sun::star::lang::NullPointerException;
110 using ::com::sun::star::uno::Exception;
111 using ::com::sun::star::container::XChild;
112 using ::com::sun::star::container::XIndexAccess;
113 using ::com::sun::star::script::XEventAttacherManager;
114 using ::com::sun::star::uno::UNO_QUERY;
115 using ::com::sun::star::uno::UNO_QUERY_THROW;
116 using ::com::sun::star::uno::XInterface;
117 using ::com::sun::star::beans::XIntrospection;
118 using ::com::sun::star::beans::XIntrospectionAccess;
119 using ::com::sun::star::container::XNameContainer;
120 using ::com::sun::star::awt::XTabControllerModel;
121 using ::com::sun::star::form::XForm;
122 using ::com::sun::star::form::XFormController;
123 using ::com::sun::star::beans::UnknownPropertyException;
124 using ::com::sun::star::uno::makeAny;
125 using ::com::sun::star::container::NoSuchElementException;
126 using ::com::sun::star::beans::XPropertySetInfo;
127 using ::com::sun::star::container::XNameReplace;
128 using ::com::sun::star::lang::IllegalArgumentException;
129 using ::com::sun::star::lang::WrappedTargetException;
130 using ::com::sun::star::uno::RuntimeException;
131 using ::com::sun::star::beans::PropertyValue;
132 using ::com::sun::star::inspection::LineDescriptor;
133 using ::com::sun::star::inspection::XPropertyControlFactory;
134 using ::com::sun::star::inspection::InteractiveSelectionResult;
135 using ::com::sun::star::inspection::InteractiveSelectionResult_Cancelled;
136 using ::com::sun::star::inspection::InteractiveSelectionResult_Success;
137 using ::com::sun::star::inspection::XObjectInspectorUI;
138 using ::com::sun::star::util::XModifiable;
139 using ::com::sun::star::beans::PropertyChangeEvent;
140 using ::com::sun::star::frame::XFrame;
141 using ::com::sun::star::frame::XModel;
142 using ::com::sun::star::frame::XController;
143 using ::com::sun::star::uno::UNO_SET_THROW;
144 using com::sun::star::uri::UriReferenceFactory;
145 using com::sun::star::uri::XUriReferenceFactory;
146 using com::sun::star::uri::XVndSunStarScriptUrlReference;
147 using ::com::sun::star::lang::XEventListener;
148 /** === end UNO using === **/
149 namespace PropertyControlType = ::com::sun::star::inspection::PropertyControlType;
150 namespace PropertyAttribute = ::com::sun::star::beans::PropertyAttribute;
151 namespace FormComponentType = ::com::sun::star::form::FormComponentType;
153 //====================================================================
154 //= EventDescription
155 //====================================================================
156 EventDescription::EventDescription( EventId _nId, const sal_Char* _pListenerNamespaceAscii, const sal_Char* _pListenerClassAsciiName,
157 const sal_Char* _pListenerMethodAsciiName, sal_uInt16 _nDisplayNameResId, sal_Int32 _nHelpId, sal_Int32 _nUniqueBrowseId )
158 :sDisplayName( String( PcrRes( _nDisplayNameResId ) ) )
159 ,sListenerMethodName( ::rtl::OUString::createFromAscii( _pListenerMethodAsciiName ) )
160 ,nHelpId( _nHelpId )
161 ,nUniqueBrowseId( _nUniqueBrowseId )
162 ,nId( _nId )
164 ::rtl::OUStringBuffer aQualifiedListenerClass;
165 aQualifiedListenerClass.appendAscii( "com.sun.star." );
166 aQualifiedListenerClass.appendAscii( _pListenerNamespaceAscii );
167 aQualifiedListenerClass.appendAscii( "." );
168 aQualifiedListenerClass.appendAscii( _pListenerClassAsciiName );
169 sListenerClassName = aQualifiedListenerClass.makeStringAndClear();
172 //========================================================================
173 //= helper
174 //========================================================================
175 namespace
177 //....................................................................
178 #define DESCRIBE_EVENT( asciinamespace, asciilistener, asciimethod, id_postfix ) \
179 s_aKnownEvents.insert( EventMap::value_type( \
180 ::rtl::OUString::createFromAscii( asciimethod ), \
181 EventDescription( ++nEventId, asciinamespace, asciilistener, asciimethod, RID_STR_EVT_##id_postfix, HID_EVT_##id_postfix, UID_BRWEVT_##id_postfix ) ) )
183 //....................................................................
184 bool lcl_getEventDescriptionForMethod( const ::rtl::OUString& _rMethodName, EventDescription& _out_rDescription )
186 static EventMap s_aKnownEvents;
187 if ( s_aKnownEvents.empty() )
189 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
190 if ( s_aKnownEvents.empty() )
192 static sal_Int32 nEventId = 0;
194 DESCRIBE_EVENT( "form", "XApproveActionListener", "approveAction", APPROVEACTIONPERFORMED );
195 DESCRIBE_EVENT( "awt", "XActionListener", "actionPerformed", ACTIONPERFORMED );
196 DESCRIBE_EVENT( "form", "XChangeListener", "changed", CHANGED );
197 DESCRIBE_EVENT( "awt", "XTextListener", "textChanged", TEXTCHANGED );
198 DESCRIBE_EVENT( "awt", "XItemListener", "itemStateChanged", ITEMSTATECHANGED );
199 DESCRIBE_EVENT( "awt", "XFocusListener", "focusGained", FOCUSGAINED );
200 DESCRIBE_EVENT( "awt", "XFocusListener", "focusLost", FOCUSLOST );
201 DESCRIBE_EVENT( "awt", "XKeyListener", "keyPressed", KEYTYPED );
202 DESCRIBE_EVENT( "awt", "XKeyListener", "keyReleased", KEYUP );
203 DESCRIBE_EVENT( "awt", "XMouseListener", "mouseEntered", MOUSEENTERED );
204 DESCRIBE_EVENT( "awt", "XMouseMotionListener", "mouseDragged", MOUSEDRAGGED );
205 DESCRIBE_EVENT( "awt", "XMouseMotionListener", "mouseMoved", MOUSEMOVED );
206 DESCRIBE_EVENT( "awt", "XMouseListener", "mousePressed", MOUSEPRESSED );
207 DESCRIBE_EVENT( "awt", "XMouseListener", "mouseReleased", MOUSERELEASED );
208 DESCRIBE_EVENT( "awt", "XMouseListener", "mouseExited", MOUSEEXITED );
209 DESCRIBE_EVENT( "form", "XResetListener", "approveReset", APPROVERESETTED );
210 DESCRIBE_EVENT( "form", "XResetListener", "resetted", RESETTED );
211 DESCRIBE_EVENT( "form", "XSubmitListener", "approveSubmit", SUBMITTED );
212 DESCRIBE_EVENT( "form", "XUpdateListener", "approveUpdate", BEFOREUPDATE );
213 DESCRIBE_EVENT( "form", "XUpdateListener", "updated", AFTERUPDATE );
214 DESCRIBE_EVENT( "form", "XLoadListener", "loaded", LOADED );
215 DESCRIBE_EVENT( "form", "XLoadListener", "reloading", RELOADING );
216 DESCRIBE_EVENT( "form", "XLoadListener", "reloaded", RELOADED );
217 DESCRIBE_EVENT( "form", "XLoadListener", "unloading", UNLOADING );
218 DESCRIBE_EVENT( "form", "XLoadListener", "unloaded", UNLOADED );
219 DESCRIBE_EVENT( "form", "XConfirmDeleteListener", "confirmDelete", CONFIRMDELETE );
220 DESCRIBE_EVENT( "sdb", "XRowSetApproveListener", "approveRowChange", APPROVEROWCHANGE );
221 DESCRIBE_EVENT( "sdbc", "XRowSetListener", "rowChanged", ROWCHANGE );
222 DESCRIBE_EVENT( "sdb", "XRowSetApproveListener", "approveCursorMove", POSITIONING );
223 DESCRIBE_EVENT( "sdbc", "XRowSetListener", "cursorMoved", POSITIONED );
224 DESCRIBE_EVENT( "form", "XDatabaseParameterListener", "approveParameter", APPROVEPARAMETER );
225 DESCRIBE_EVENT( "sdb", "XSQLErrorListener", "errorOccured", ERROROCCURED );
226 DESCRIBE_EVENT( "awt", "XAdjustmentListener", "adjustmentValueChanged", ADJUSTMENTVALUECHANGED );
230 EventMap::const_iterator pos = s_aKnownEvents.find( _rMethodName );
231 if ( pos == s_aKnownEvents.end() )
232 return false;
234 _out_rDescription = pos->second;
235 return true;
238 //....................................................................
239 ::rtl::OUString lcl_getEventPropertyName( const ::rtl::OUString& _rListenerClassName, const ::rtl::OUString& _rMethodName )
241 ::rtl::OUStringBuffer aPropertyName;
242 aPropertyName.append( _rListenerClassName );
243 aPropertyName.append( (sal_Unicode)';' );
244 aPropertyName.append( _rMethodName.getStr() );
245 return aPropertyName.makeStringAndClear();
248 //................................................................
249 ScriptEventDescriptor lcl_getAssignedScriptEvent( const EventDescription& _rEvent, const Sequence< ScriptEventDescriptor >& _rAllAssignedMacros )
251 ScriptEventDescriptor aScriptEvent;
252 // for the case there is actually no event assigned, initialize at least ListenerType and MethodName,
253 // so this ScriptEventDescriptor properly describes the given event
254 aScriptEvent.ListenerType = _rEvent.sListenerClassName;
255 aScriptEvent.EventMethod = _rEvent.sListenerMethodName;
257 const ScriptEventDescriptor* pAssignedEvent = _rAllAssignedMacros.getConstArray();
258 sal_Int32 assignedEventCount( _rAllAssignedMacros.getLength() );
259 for ( sal_Int32 assignedEvent = 0; assignedEvent < assignedEventCount; ++assignedEvent, ++pAssignedEvent )
261 if ( ( pAssignedEvent->ListenerType != _rEvent.sListenerClassName )
262 || ( pAssignedEvent->EventMethod != _rEvent.sListenerMethodName )
264 continue;
266 if ( ( pAssignedEvent->ScriptCode.getLength() == 0 )
267 || ( pAssignedEvent->ScriptType.getLength() == 0 )
270 DBG_ERROR( "lcl_getAssignedScriptEvent: me thinks this should not happen!" );
271 continue;
274 aScriptEvent = *pAssignedEvent;
276 if ( !aScriptEvent.ScriptType.equalsAscii( "StarBasic" ) )
277 continue;
279 // this is an old-style macro specification:
280 // [document|application]:Library.Module.Function
281 // we need to translate this to the new-style macro specification
282 // vnd.sun.star.script:Library.Module.Function?language=Basic&location=[document|application]
284 sal_Int32 nPrefixLen = aScriptEvent.ScriptCode.indexOf( ':' );
285 OSL_ENSURE( nPrefixLen > 0, "lcl_getAssignedScriptEvent: illegal location!" );
286 ::rtl::OUString sLocation = aScriptEvent.ScriptCode.copy( 0, nPrefixLen );
287 ::rtl::OUString sMacroPath = aScriptEvent.ScriptCode.copy( nPrefixLen + 1 );
289 ::rtl::OUStringBuffer aNewStyleSpec;
290 aNewStyleSpec.appendAscii( "vnd.sun.star.script:" );
291 aNewStyleSpec.append ( sMacroPath );
292 aNewStyleSpec.appendAscii( "?language=Basic&location=" );
293 aNewStyleSpec.append ( sLocation );
295 aScriptEvent.ScriptCode = aNewStyleSpec.makeStringAndClear();
297 // also, this new-style spec requires the script code to be "Script" instead of "StarBasic"
298 aScriptEvent.ScriptType = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Script" ) );
300 return aScriptEvent;
303 //................................................................
304 ::rtl::OUString lcl_getQualifiedKnownListenerName( const ScriptEventDescriptor& _rFormComponentEventDescriptor )
306 EventDescription aKnownEvent;
307 if ( lcl_getEventDescriptionForMethod( _rFormComponentEventDescriptor.EventMethod, aKnownEvent ) )
308 return aKnownEvent.sListenerClassName;
309 DBG_ERROR( "lcl_getQualifiedKnownListenerName: unknown method name!" );
310 // somebody assigned an script to a form component event which we don't know
311 // Speaking strictly, this is not really an error - it is possible to do
312 // this programmatically -, but it should rarely happen, since it's not possible
313 // via UI
314 return _rFormComponentEventDescriptor.ListenerType;
317 //................................................................
318 typedef ::std::set< Type, TypeLessByName > TypeBag;
320 //................................................................
321 void lcl_addListenerTypesFor_throw( const Reference< XInterface >& _rxComponent,
322 const Reference< XIntrospection >& _rxIntrospection, TypeBag& _out_rTypes )
324 if ( !_rxComponent.is() )
325 return;
326 OSL_PRECOND( _rxIntrospection.is(), "lcl_addListenerTypesFor_throw: this will crash!" );
328 Reference< XIntrospectionAccess > xIntrospectionAccess(
329 _rxIntrospection->inspect( makeAny( _rxComponent ) ), UNO_QUERY_THROW );
331 Sequence< Type > aListeners( xIntrospectionAccess->getSupportedListeners() );
333 ::std::copy( aListeners.getConstArray(), aListeners.getConstArray() + aListeners.getLength(),
334 ::std::insert_iterator< TypeBag >( _out_rTypes, _out_rTypes.begin() ) );
337 //................................................................
338 bool operator ==( const ScriptEventDescriptor _lhs, const ScriptEventDescriptor _rhs )
340 return ( ( _lhs.ListenerType == _rhs.ListenerType )
341 && ( _lhs.EventMethod == _rhs.EventMethod )
342 && ( _lhs.AddListenerParam == _rhs.AddListenerParam )
343 && ( _lhs.ScriptType == _rhs.ScriptType )
344 && ( _lhs.ScriptCode == _rhs.ScriptCode )
349 //====================================================================
350 //= EventHandler
351 //====================================================================
352 typedef ::cppu::WeakImplHelper1 < ::com::sun::star::container::XNameReplace
353 > EventHolder_Base;
354 /** a UNO component holding assigned event descriptions, for use with a SvxMacroAssignDlg
356 class EventHolder : public EventHolder_Base
358 private:
359 typedef ::std::hash_map< ::rtl::OUString, ScriptEventDescriptor, ::rtl::OUStringHash > EventMap;
360 typedef ::std::map< EventId, EventMap::iterator > EventMapIndexAccess;
362 EventMap m_aEventNameAccess;
363 EventMapIndexAccess m_aEventIndexAccess;
365 public:
366 EventHolder( );
368 void addEvent( EventId _nId, const ::rtl::OUString& _rEventName, const ScriptEventDescriptor& _rScriptEvent );
370 /** effectively the same as getByName, but instead of converting the ScriptEventDescriptor to the weird
371 format used by the macro assignment dialog, it is returned directly
373 ScriptEventDescriptor getNormalizedDescriptorByName( const ::rtl::OUString& _rEventName ) const;
375 // XNameReplace
376 virtual void SAL_CALL replaceByName( const ::rtl::OUString& _rName, const Any& aElement ) throw (IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException);
377 virtual Any SAL_CALL getByName( const ::rtl::OUString& _rName ) throw (NoSuchElementException, WrappedTargetException, RuntimeException);
378 virtual Sequence< ::rtl::OUString > SAL_CALL getElementNames( ) throw (RuntimeException);
379 virtual ::sal_Bool SAL_CALL hasByName( const ::rtl::OUString& _rName ) throw (RuntimeException);
380 virtual Type SAL_CALL getElementType( ) throw (RuntimeException);
381 virtual ::sal_Bool SAL_CALL hasElements( ) throw (RuntimeException);
383 protected:
384 ~EventHolder( );
386 private:
387 ScriptEventDescriptor impl_getDescriptor_throw( const ::rtl::OUString& _rEventName ) const;
390 DBG_NAME( EventHolder )
391 //------------------------------------------------------------------------
392 EventHolder::EventHolder()
394 DBG_CTOR( EventHolder, NULL );
397 //------------------------------------------------------------------------
398 EventHolder::~EventHolder()
400 m_aEventNameAccess.clear();
401 m_aEventIndexAccess.clear();
402 DBG_DTOR( EventHolder, NULL );
405 //------------------------------------------------------------------------
406 void EventHolder::addEvent( EventId _nId, const ::rtl::OUString& _rEventName, const ScriptEventDescriptor& _rScriptEvent )
408 ::std::pair< EventMap::iterator, bool > insertionResult =
409 m_aEventNameAccess.insert( EventMap::value_type( _rEventName, _rScriptEvent ) );
410 OSL_ENSURE( insertionResult.second, "EventHolder::addEvent: there already was a MacroURL for this event!" );
411 m_aEventIndexAccess[ _nId ] = insertionResult.first;
414 //------------------------------------------------------------------------
415 ScriptEventDescriptor EventHolder::getNormalizedDescriptorByName( const ::rtl::OUString& _rEventName ) const
417 return impl_getDescriptor_throw( _rEventName );
420 //------------------------------------------------------------------------
421 ScriptEventDescriptor EventHolder::impl_getDescriptor_throw( const ::rtl::OUString& _rEventName ) const
423 EventMap::const_iterator pos = m_aEventNameAccess.find( _rEventName );
424 if ( pos == m_aEventNameAccess.end() )
425 throw NoSuchElementException( ::rtl::OUString(), *const_cast< EventHolder* >( this ) );
426 return pos->second;
429 //------------------------------------------------------------------------
430 void SAL_CALL EventHolder::replaceByName( const ::rtl::OUString& _rName, const Any& _rElement ) throw (IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException)
432 EventMap::iterator pos = m_aEventNameAccess.find( _rName );
433 if ( pos == m_aEventNameAccess.end() )
434 throw NoSuchElementException( ::rtl::OUString(), *this );
436 Sequence< PropertyValue > aScriptDescriptor;
437 OSL_VERIFY( _rElement >>= aScriptDescriptor );
439 ::comphelper::NamedValueCollection aExtractor( aScriptDescriptor );
441 pos->second.ScriptType = aExtractor.getOrDefault( "EventType", ::rtl::OUString() );
442 pos->second.ScriptCode = aExtractor.getOrDefault( "Script", ::rtl::OUString() );
445 //------------------------------------------------------------------------
446 Any SAL_CALL EventHolder::getByName( const ::rtl::OUString& _rName ) throw (NoSuchElementException, WrappedTargetException, RuntimeException)
448 ScriptEventDescriptor aDescriptor( impl_getDescriptor_throw( _rName ) );
450 Any aRet;
451 Sequence< PropertyValue > aScriptDescriptor( 2 );
452 aScriptDescriptor[0].Name = ::rtl::OUString::createFromAscii( "EventType" );
453 aScriptDescriptor[0].Value <<= aDescriptor.ScriptType;
454 aScriptDescriptor[1].Name = ::rtl::OUString::createFromAscii( "Script" );
455 aScriptDescriptor[1].Value <<= aDescriptor.ScriptCode;
457 return makeAny( aScriptDescriptor );
460 //------------------------------------------------------------------------
461 Sequence< ::rtl::OUString > SAL_CALL EventHolder::getElementNames( ) throw (RuntimeException)
463 Sequence< ::rtl::OUString > aReturn( m_aEventIndexAccess.size() );
464 ::rtl::OUString* pReturn = aReturn.getArray();
466 // SvxMacroAssignDlg has a weird API: It expects a XNameReplace, means a container whose
467 // main access method is by name. In it's UI, it shows the possible events in exactly the
468 // order in which XNameAccess::getElementNames returns them.
469 // However, SvxMacroAssignDlg *also* takes an index for the initial selection, which is
470 // relative to the sequence returned by XNameAccess::getElementNames.
471 // This is IMO weird, since it mixes index access with name access, which decreases efficiency
472 // of the implementation.
473 // Well, it means we're forced to return the events in getElementNames in exactly the same as they
474 // appear in the property browser UI.
475 for ( EventMapIndexAccess::const_iterator loop = m_aEventIndexAccess.begin();
476 loop != m_aEventIndexAccess.end();
477 ++loop, ++pReturn
479 *pReturn = loop->second->first;
480 return aReturn;
483 //------------------------------------------------------------------------
484 sal_Bool SAL_CALL EventHolder::hasByName( const ::rtl::OUString& _rName ) throw (RuntimeException)
486 EventMap::const_iterator pos = m_aEventNameAccess.find( _rName );
487 return pos != m_aEventNameAccess.end();
490 //------------------------------------------------------------------------
491 Type SAL_CALL EventHolder::getElementType( ) throw (RuntimeException)
493 return ::getCppuType( static_cast< Sequence< PropertyValue >* >( NULL ) );
496 //------------------------------------------------------------------------
497 sal_Bool SAL_CALL EventHolder::hasElements( ) throw (RuntimeException)
499 return !m_aEventNameAccess.empty();
503 //====================================================================
504 //= EventHandler
505 //====================================================================
506 DBG_NAME( EventHandler )
507 //--------------------------------------------------------------------
508 EventHandler::EventHandler( const Reference< XComponentContext >& _rxContext )
509 :EventHandler_Base( m_aMutex )
510 ,m_aContext( _rxContext )
511 ,m_aPropertyListeners( m_aMutex )
512 ,m_bEventsMapInitialized( false )
513 ,m_bIsDialogElement( false )
514 ,m_nGridColumnType( -1 )
516 DBG_CTOR( EventHandler, NULL );
519 //--------------------------------------------------------------------
520 EventHandler::~EventHandler()
522 DBG_DTOR( EventHandler, NULL );
525 //--------------------------------------------------------------------
526 ::rtl::OUString SAL_CALL EventHandler::getImplementationName( ) throw (RuntimeException)
528 return getImplementationName_static();
531 //--------------------------------------------------------------------
532 ::sal_Bool SAL_CALL EventHandler::supportsService( const ::rtl::OUString& ServiceName ) throw (RuntimeException)
534 StlSyntaxSequence< ::rtl::OUString > aAllServices( getSupportedServiceNames() );
535 return ::std::find( aAllServices.begin(), aAllServices.end(), ServiceName ) != aAllServices.end();
538 //--------------------------------------------------------------------
539 Sequence< ::rtl::OUString > SAL_CALL EventHandler::getSupportedServiceNames( ) throw (RuntimeException)
541 return getSupportedServiceNames_static();
544 //--------------------------------------------------------------------
545 ::rtl::OUString SAL_CALL EventHandler::getImplementationName_static( ) throw (RuntimeException)
547 return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.extensions.EventHandler" ) );
550 //--------------------------------------------------------------------
551 Sequence< ::rtl::OUString > SAL_CALL EventHandler::getSupportedServiceNames_static( ) throw (RuntimeException)
553 Sequence< ::rtl::OUString > aSupported( 1 );
554 aSupported[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.form.inspection.EventHandler" ) );
555 return aSupported;
558 //--------------------------------------------------------------------
559 Reference< XInterface > SAL_CALL EventHandler::Create( const Reference< XComponentContext >& _rxContext )
561 return *( new EventHandler( _rxContext ) );
564 //--------------------------------------------------------------------
565 void SAL_CALL EventHandler::inspect( const Reference< XInterface >& _rxIntrospectee ) throw (RuntimeException, NullPointerException)
567 ::osl::MutexGuard aGuard( m_aMutex );
569 if ( !_rxIntrospectee.is() )
570 throw NullPointerException();
572 m_xComponent = Reference< XPropertySet >( _rxIntrospectee, UNO_QUERY_THROW );
574 m_bEventsMapInitialized = false;
575 EventMap aEmpty;
576 m_aEvents.swap( aEmpty );
578 m_bIsDialogElement = false;
579 m_nGridColumnType = -1;
582 Reference< XPropertySetInfo > xPSI( m_xComponent->getPropertySetInfo() );
583 m_bIsDialogElement = xPSI.is()
584 && xPSI->hasPropertyByName( PROPERTY_WIDTH )
585 && xPSI->hasPropertyByName( PROPERTY_HEIGHT )
586 && xPSI->hasPropertyByName( PROPERTY_POSITIONX )
587 && xPSI->hasPropertyByName( PROPERTY_POSITIONY );
589 Reference< XChild > xAsChild( _rxIntrospectee, UNO_QUERY );
590 if ( xAsChild.is() && !Reference< XForm >( _rxIntrospectee, UNO_QUERY ).is() )
592 if ( FormComponentType::GRIDCONTROL == classifyComponent( xAsChild->getParent() ) )
594 m_nGridColumnType = classifyComponent( _rxIntrospectee );
598 catch( const Exception& )
600 OSL_ENSURE( false, "EventHandler::EventHandler: caught an exception while classifying the component!" );
604 //--------------------------------------------------------------------
605 Any SAL_CALL EventHandler::getPropertyValue( const ::rtl::OUString& _rPropertyName ) throw (UnknownPropertyException, RuntimeException)
607 ::osl::MutexGuard aGuard( m_aMutex );
609 const EventDescription& rEvent = impl_getEventForName_throw( _rPropertyName );
611 Sequence< ScriptEventDescriptor > aEvents;
612 impl_getComponentScriptEvents_nothrow( aEvents );
614 sal_Int32 nEventCount = aEvents.getLength();
615 const ScriptEventDescriptor* pEvents = aEvents.getConstArray();
617 ScriptEventDescriptor aPropertyValue;
618 for ( sal_Int32 event = 0; event < nEventCount; ++event, ++pEvents )
620 if ( rEvent.sListenerClassName == pEvents->ListenerType
621 && rEvent.sListenerMethodName == pEvents->EventMethod
624 aPropertyValue = *pEvents;
625 break;
629 return makeAny( aPropertyValue );
632 //--------------------------------------------------------------------
633 void SAL_CALL EventHandler::setPropertyValue( const ::rtl::OUString& _rPropertyName, const Any& _rValue ) throw (UnknownPropertyException, RuntimeException)
635 ::osl::MutexGuard aGuard( m_aMutex );
637 const EventDescription& rEvent = impl_getEventForName_throw( _rPropertyName );
639 ScriptEventDescriptor aNewScriptEvent;
640 OSL_VERIFY( _rValue >>= aNewScriptEvent );
642 ScriptEventDescriptor aOldScriptEvent;
643 OSL_VERIFY( getPropertyValue( _rPropertyName ) >>= aOldScriptEvent );
644 if ( aOldScriptEvent == aNewScriptEvent )
645 return;
647 if ( m_bIsDialogElement )
648 impl_setDialogElementScriptEvent_nothrow( aNewScriptEvent );
649 else
650 impl_setFormComponentScriptEvent_nothrow( aNewScriptEvent );
652 Reference< XModifiable > xDoc( m_aContext.getContextValueByAsciiName( "ContextDocument" ), UNO_QUERY );
653 if ( xDoc.is() )
654 xDoc->setModified( sal_True );
656 PropertyChangeEvent aEvent;
657 aEvent.Source = m_xComponent;
658 aEvent.PropertyHandle = rEvent.nId;
659 aEvent.PropertyName = _rPropertyName;
660 aEvent.OldValue <<= aOldScriptEvent;
661 aEvent.NewValue <<= aNewScriptEvent;
662 m_aPropertyListeners.notify( aEvent, &XPropertyChangeListener::propertyChange );
665 //--------------------------------------------------------------------
666 Any SAL_CALL EventHandler::convertToPropertyValue( const ::rtl::OUString& _rPropertyName, const Any& _rControlValue ) throw (UnknownPropertyException, RuntimeException)
668 ::osl::MutexGuard aGuard( m_aMutex );
670 ::rtl::OUString sNewScriptCode;
671 OSL_VERIFY( _rControlValue >>= sNewScriptCode );
673 Sequence< ScriptEventDescriptor > aAllAssignedEvents;
674 impl_getComponentScriptEvents_nothrow( aAllAssignedEvents );
676 const EventDescription& rEvent = impl_getEventForName_throw( _rPropertyName );
677 ScriptEventDescriptor aAssignedScript = lcl_getAssignedScriptEvent( rEvent, aAllAssignedEvents );
679 OSL_ENSURE( !sNewScriptCode.getLength(), "EventHandler::convertToPropertyValue: cannot convert a non-empty display name!" );
680 // Usually, there is no possibility for the user to change the content of an event binding directly in the
681 // input field, this instead is done with the macro assignment dialog.
682 // The only exception is the user pressing "DEL" while the control has the focus, in this case, we reset the
683 // control content to an empty string. So this is the only scenario where this method is allowed to be called.
685 // Striclty, we would be able to convert the display value to a property value,
686 // using the "name (location, language)" format we used in convertToControlValue. However,
687 // there is no need for this code ...
689 aAssignedScript.ScriptCode = sNewScriptCode;
690 return makeAny( aAssignedScript );
693 //--------------------------------------------------------------------
694 Any SAL_CALL EventHandler::convertToControlValue( const ::rtl::OUString& /*_rPropertyName*/, const Any& _rPropertyValue, const Type& _rControlValueType ) throw (UnknownPropertyException, RuntimeException)
696 ::osl::MutexGuard aGuard( m_aMutex );
698 ScriptEventDescriptor aScriptEvent;
699 OSL_VERIFY( _rPropertyValue >>= aScriptEvent );
701 OSL_ENSURE( _rControlValueType.getTypeClass() == TypeClass_STRING,
702 "EventHandler::convertToControlValue: unexpected ControlValue type class!" );
703 (void)_rControlValueType;
705 ::rtl::OUString sScript( aScriptEvent.ScriptCode );
706 if ( sScript.getLength() )
708 // format is: "name (location, language)"
711 // parse
712 Reference< XUriReferenceFactory > xUriRefFac = UriReferenceFactory::create( m_aContext.getUNOContext() );
713 Reference< XVndSunStarScriptUrlReference > xScriptUri( xUriRefFac->parse( sScript ), UNO_QUERY_THROW );
715 ::rtl::OUStringBuffer aComposeBuffer;
717 // name
718 aComposeBuffer.append( xScriptUri->getName() );
720 // location
721 const ::rtl::OUString sLocationParamName( RTL_CONSTASCII_USTRINGPARAM( "location" ) );
722 const ::rtl::OUString sLocation = xScriptUri->getParameter( sLocationParamName );
723 const ::rtl::OUString sLangParamName( RTL_CONSTASCII_USTRINGPARAM( "language" ) );
724 const ::rtl::OUString sLanguage = xScriptUri->getParameter( sLangParamName );
726 if ( sLocation.getLength() || sLanguage.getLength() )
728 aComposeBuffer.appendAscii( " (" );
730 // location
731 OSL_ENSURE( sLocation.getLength(), "EventHandler::convertToControlValue: unexpected: no location!" );
732 if ( sLocation.getLength() )
734 aComposeBuffer.append( sLocation );
735 aComposeBuffer.appendAscii( ", " );
738 // language
739 if ( sLanguage.getLength() )
741 aComposeBuffer.append( sLanguage );
744 aComposeBuffer.append( sal_Unicode( ')' ) );
747 sScript = aComposeBuffer.makeStringAndClear();
749 catch( const Exception& )
751 DBG_UNHANDLED_EXCEPTION();
755 return makeAny( sScript );
758 //--------------------------------------------------------------------
759 PropertyState SAL_CALL EventHandler::getPropertyState( const ::rtl::OUString& /*_rPropertyName*/ ) throw (UnknownPropertyException, RuntimeException)
761 return PropertyState_DIRECT_VALUE;
764 //--------------------------------------------------------------------
765 void SAL_CALL EventHandler::addPropertyChangeListener( const Reference< XPropertyChangeListener >& _rxListener ) throw (RuntimeException)
767 ::osl::MutexGuard aGuard( m_aMutex );
768 if ( !_rxListener.is() )
769 throw NullPointerException();
770 m_aPropertyListeners.addListener( _rxListener );
773 //--------------------------------------------------------------------
774 void SAL_CALL EventHandler::removePropertyChangeListener( const Reference< XPropertyChangeListener >& _rxListener ) throw (RuntimeException)
776 ::osl::MutexGuard aGuard( m_aMutex );
777 m_aPropertyListeners.removeListener( _rxListener );
780 //--------------------------------------------------------------------
781 Sequence< Property > SAL_CALL EventHandler::getSupportedProperties() throw (RuntimeException)
783 ::osl::MutexGuard aGuard( m_aMutex );
784 if ( !m_bEventsMapInitialized )
786 const_cast< EventHandler* >( this )->m_bEventsMapInitialized = true;
789 Sequence< Type > aListeners;
790 impl_getCopmonentListenerTypes_nothrow( aListeners );
791 sal_Int32 listenerCount = aListeners.getLength();
793 Property aCurrentProperty;
794 ::rtl::OUString sListenerClassName;
796 // loop through all listeners and all methods, and see which we can present at the UI
797 const Type* pListeners = aListeners.getConstArray();
798 for ( sal_Int32 listener = 0; listener < listenerCount; ++listener, ++pListeners )
800 aCurrentProperty = Property();
802 // the programmatic name of the listener, to be used as "property" name
803 sListenerClassName = pListeners->getTypeName();
804 OSL_ENSURE( sListenerClassName.getLength(), "EventHandler::getSupportedProperties: strange - no listener name ..." );
805 if ( !sListenerClassName.getLength() )
806 continue;
808 // loop through all methods
809 Sequence< ::rtl::OUString > aMethods( comphelper::getEventMethodsForType( *pListeners ) );
811 const ::rtl::OUString* pMethods = aMethods.getConstArray();
812 sal_uInt32 methodCount = aMethods.getLength();
814 for (sal_uInt32 method = 0 ; method < methodCount ; ++method, ++pMethods )
816 EventDescription aEvent;
817 if ( !lcl_getEventDescriptionForMethod( *pMethods, aEvent ) )
818 continue;
820 if ( !impl_filterMethod_nothrow( aEvent ) )
821 continue;
823 const_cast< EventHandler* >( this )->m_aEvents.insert( EventMap::value_type(
824 lcl_getEventPropertyName( sListenerClassName, *pMethods ), aEvent ) );
829 catch( const Exception& )
831 DBG_ERROR( "EventHandler::getSupportedProperties: caught an exception !" );
835 // sort them by ID - this is the relative ordering in the UI
836 ::std::map< EventId, Property > aOrderedProperties;
837 for ( EventMap::const_iterator loop = m_aEvents.begin();
838 loop != m_aEvents.end();
839 ++loop
842 aOrderedProperties[ loop->second.nId ] = Property(
843 loop->first, loop->second.nId,
844 ::getCppuType( static_cast< const ::rtl::OUString* >( NULL ) ),
845 PropertyAttribute::BOUND );
848 StlSyntaxSequence< Property > aReturn( aOrderedProperties.size() );
849 ::std::transform( aOrderedProperties.begin(), aOrderedProperties.end(), aReturn.begin(),
850 ::std::select2nd< ::std::map< EventId, Property >::value_type >() );
851 return aReturn;
854 //--------------------------------------------------------------------
855 Sequence< ::rtl::OUString > SAL_CALL EventHandler::getSupersededProperties( ) throw (RuntimeException)
857 // none
858 return Sequence< ::rtl::OUString >( );
861 //--------------------------------------------------------------------
862 Sequence< ::rtl::OUString > SAL_CALL EventHandler::getActuatingProperties( ) throw (RuntimeException)
864 // none
865 return Sequence< ::rtl::OUString >( );
868 //--------------------------------------------------------------------
869 LineDescriptor SAL_CALL EventHandler::describePropertyLine( const ::rtl::OUString& _rPropertyName,
870 const Reference< XPropertyControlFactory >& _rxControlFactory )
871 throw (UnknownPropertyException, NullPointerException, RuntimeException)
873 if ( !_rxControlFactory.is() )
874 throw NullPointerException();
876 ::osl::MutexGuard aGuard( m_aMutex );
878 LineDescriptor aDescriptor;
880 aDescriptor.Control = _rxControlFactory->createPropertyControl( PropertyControlType::TextField, sal_True );
881 Reference< XEventListener > xControlExtender = new PropertyControlExtender( aDescriptor.Control );
883 const EventDescription& rEvent = impl_getEventForName_throw( _rPropertyName );
884 aDescriptor.DisplayName = rEvent.sDisplayName;
885 aDescriptor.HelpURL = HelpIdUrl::getHelpURL( rEvent.nHelpId );
886 aDescriptor.PrimaryButtonId = rEvent.nUniqueBrowseId;
887 aDescriptor.HasPrimaryButton = sal_True;
888 aDescriptor.Category = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Events" ) );
889 return aDescriptor;
892 //--------------------------------------------------------------------
893 ::sal_Bool SAL_CALL EventHandler::isComposable( const ::rtl::OUString& /*_rPropertyName*/ ) throw (UnknownPropertyException, RuntimeException)
895 return sal_False;
898 //--------------------------------------------------------------------
899 InteractiveSelectionResult SAL_CALL EventHandler::onInteractivePropertySelection( const ::rtl::OUString& _rPropertyName, sal_Bool /*_bPrimary*/, Any& /*_rData*/, const Reference< XObjectInspectorUI >& _rxInspectorUI ) throw (UnknownPropertyException, NullPointerException, RuntimeException)
901 if ( !_rxInspectorUI.is() )
902 throw NullPointerException();
904 ::osl::MutexGuard aGuard( m_aMutex );
905 const EventDescription& rForEvent = impl_getEventForName_throw( _rPropertyName );
907 Sequence< ScriptEventDescriptor > aAllAssignedEvents;
908 impl_getComponentScriptEvents_nothrow( aAllAssignedEvents );
910 // SvxMacroAssignDlg-compatible structure holding all event/assignments
911 ::rtl::Reference< EventHolder > pEventHolder( new EventHolder );
913 for ( EventMap::const_iterator event = m_aEvents.begin();
914 event != m_aEvents.end();
915 ++event
918 // the script which is assigned to the current event (if any)
919 ScriptEventDescriptor aAssignedScript = lcl_getAssignedScriptEvent( event->second, aAllAssignedEvents );
920 pEventHolder->addEvent( event->second.nId, event->second.sListenerMethodName, aAssignedScript );
923 // the inital selection in the dialog
924 Sequence< ::rtl::OUString > aNames( pEventHolder->getElementNames() );
925 const ::rtl::OUString* pChosenEvent = ::std::find( aNames.getConstArray(), aNames.getConstArray() + aNames.getLength(), rForEvent.sListenerMethodName );
926 sal_uInt16 nInitialSelection = (sal_uInt16)( pChosenEvent - aNames.getConstArray() );
928 // the dialog
929 SvxAbstractDialogFactory* pFactory = SvxAbstractDialogFactory::Create();
930 if ( !pFactory )
931 return InteractiveSelectionResult_Cancelled;
933 ::std::auto_ptr< VclAbstractDialog > pDialog( pFactory->CreateSvxMacroAssignDlg(
934 PropertyHandlerHelper::getDialogParentWindow( m_aContext ),
935 impl_getContextFrame_nothrow(),
936 m_bIsDialogElement,
937 pEventHolder.get(),
938 nInitialSelection
939 ) );
941 if ( !pDialog.get() )
942 return InteractiveSelectionResult_Cancelled;
944 // DF definite problem here
945 // OK & Cancel seem to be both returning 0
946 if ( pDialog->Execute() != 0 )
947 return InteractiveSelectionResult_Cancelled;
951 for ( EventMap::const_iterator event = m_aEvents.begin();
952 event != m_aEvents.end();
953 ++event
956 ScriptEventDescriptor aScriptDescriptor( pEventHolder->getNormalizedDescriptorByName( event->second.sListenerMethodName ) );
958 // set the new "property value"
959 setPropertyValue(
960 lcl_getEventPropertyName( event->second.sListenerClassName, event->second.sListenerMethodName ),
961 makeAny( aScriptDescriptor )
965 catch( const Exception& )
967 DBG_UNHANDLED_EXCEPTION();
970 return InteractiveSelectionResult_Success;
973 //--------------------------------------------------------------------
974 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)
976 DBG_ERROR( "EventHandler::actuatingPropertyChanged: no actuating properties -> no callback (well, this is how it *should* be!)" );
979 //--------------------------------------------------------------------
980 IMPLEMENT_FORWARD_XCOMPONENT( EventHandler, EventHandler_Base )
982 //--------------------------------------------------------------------
983 void SAL_CALL EventHandler::disposing()
985 EventMap aEmpty;
986 m_aEvents.swap( aEmpty );
987 m_xComponent.clear();
990 //--------------------------------------------------------------------
991 sal_Bool SAL_CALL EventHandler::suspend( sal_Bool /*_bSuspend*/ ) throw (RuntimeException)
993 return sal_True;
996 //------------------------------------------------------------------------
997 Reference< XFrame > EventHandler::impl_getContextFrame_nothrow() const
999 Reference< XFrame > xContextFrame;
1003 Reference< XModel > xContextDocument( m_aContext.getContextValueByAsciiName( "ContextDocument" ), UNO_QUERY_THROW );
1004 Reference< XController > xController( xContextDocument->getCurrentController(), UNO_SET_THROW );
1005 xContextFrame.set( xController->getFrame(), UNO_SET_THROW );
1007 catch( const Exception& )
1009 DBG_UNHANDLED_EXCEPTION();
1012 return xContextFrame;
1015 //--------------------------------------------------------------------
1016 sal_Int32 EventHandler::impl_getComponentIndexInParent_throw() const
1018 Reference< XChild > xChild( m_xComponent, UNO_QUERY_THROW );
1019 Reference< XIndexAccess > xParentAsIndexAccess( xChild->getParent(), UNO_QUERY_THROW );
1021 // get the index of the inspected object within it's parent container
1022 sal_Int32 nElements = xParentAsIndexAccess->getCount();
1023 for ( sal_Int32 i=0; i<nElements; ++i )
1025 Reference< XInterface > xElement( xParentAsIndexAccess->getByIndex( i ), UNO_QUERY_THROW );
1026 if ( xElement == m_xComponent )
1027 return i;
1029 throw NoSuchElementException();
1032 //--------------------------------------------------------------------
1033 void EventHandler::impl_getFormComponentScriptEvents_nothrow( Sequence < ScriptEventDescriptor >& _out_rEvents ) const
1035 _out_rEvents = Sequence < ScriptEventDescriptor >();
1038 Reference< XChild > xChild( m_xComponent, UNO_QUERY_THROW );
1039 Reference< XEventAttacherManager > xEventManager( xChild->getParent(), UNO_QUERY_THROW );
1040 _out_rEvents = xEventManager->getScriptEvents( impl_getComponentIndexInParent_throw() );
1042 // the form component script API has unqualified listener names, but for normalization
1043 // purpose, we want fully qualified ones
1044 ScriptEventDescriptor* pEvents = _out_rEvents.getArray();
1045 ScriptEventDescriptor* pEventsEnd = _out_rEvents.getArray() + _out_rEvents.getLength();
1046 while ( pEvents != pEventsEnd )
1048 pEvents->ListenerType = lcl_getQualifiedKnownListenerName( *pEvents );
1049 ++pEvents;
1052 catch( const Exception& )
1054 OSL_ENSURE( false, "EventHandler::impl_getFormComponentScriptEvents_nothrow: caught an exception!" );
1058 //--------------------------------------------------------------------
1059 void EventHandler::impl_getCopmonentListenerTypes_nothrow( Sequence< Type >& _out_rTypes ) const
1061 _out_rTypes.realloc( 0 );
1064 // we use a set to avoid duplicates
1065 TypeBag aListeners;
1067 Reference< XIntrospection > xIntrospection( m_aContext.createComponent( "com.sun.star.beans.Introspection" ), UNO_QUERY_THROW );
1069 // --- model listeners
1070 lcl_addListenerTypesFor_throw(
1071 m_xComponent, xIntrospection, aListeners );
1073 // --- "secondary component" (usually: "control" listeners)
1075 Reference< XInterface > xSecondaryComponent( impl_getSecondaryComponentForEventInspection_throw() );
1076 lcl_addListenerTypesFor_throw( xSecondaryComponent, xIntrospection, aListeners );
1077 ::comphelper::disposeComponent( xSecondaryComponent );
1080 // now that they're disambiguated, copy these types into our member
1081 _out_rTypes.realloc( aListeners.size() );
1082 ::std::copy( aListeners.begin(), aListeners.end(), _out_rTypes.getArray() );
1084 catch( const Exception& )
1086 OSL_ENSURE( false, "EventHandler::impl_getCopmonentListenerTypes_nothrow: caught an exception!" );
1090 //--------------------------------------------------------------------
1091 void EventHandler::impl_getDialogElementScriptEvents_nothrow( Sequence < ScriptEventDescriptor >& _out_rEvents ) const
1093 _out_rEvents = Sequence < ScriptEventDescriptor >();
1096 Reference< XScriptEventsSupplier > xEventsSupplier( m_xComponent, UNO_QUERY_THROW );
1097 Reference< XNameContainer > xEvents( xEventsSupplier->getEvents(), UNO_QUERY_THROW );
1098 Sequence< ::rtl::OUString > aEventNames( xEvents->getElementNames() );
1100 sal_Int32 nEventCount = aEventNames.getLength();
1101 _out_rEvents.realloc( nEventCount );
1103 const ::rtl::OUString* pNames = aEventNames.getConstArray();
1104 ScriptEventDescriptor* pDescs = _out_rEvents.getArray();
1106 for( sal_Int32 i = 0 ; i < nEventCount ; ++i, ++pNames, ++pDescs )
1107 OSL_VERIFY( xEvents->getByName( *pNames ) >>= *pDescs );
1109 catch( const Exception& )
1111 OSL_ENSURE( false, "EventHandler::impl_getDialogElementScriptEvents_nothrow: caught an exception!" );
1115 //--------------------------------------------------------------------
1116 Reference< XInterface > EventHandler::impl_getSecondaryComponentForEventInspection_throw( ) const
1118 Reference< XInterface > xReturn;
1120 // if it's a form, create a form controller for the additional events
1121 Reference< XForm > xComponentAsForm( m_xComponent, UNO_QUERY );
1122 if ( xComponentAsForm.is() )
1124 Reference< XTabControllerModel > xComponentAsTCModel( m_xComponent, UNO_QUERY_THROW );
1125 Reference< XFormController > xController(
1126 m_aContext.createComponent( (const rtl::OUString&)SERVICE_FORMCONTROLLER ), UNO_QUERY_THROW );
1127 xController->setModel( xComponentAsTCModel );
1129 xReturn = xController.get();
1131 else
1133 ::rtl::OUString sControlService;
1134 OSL_VERIFY( m_xComponent->getPropertyValue( PROPERTY_DEFAULTCONTROL ) >>= sControlService );
1136 xReturn = m_aContext.createComponent( sControlService );
1138 return xReturn;
1141 //--------------------------------------------------------------------
1142 const EventDescription& EventHandler::impl_getEventForName_throw( const ::rtl::OUString& _rPropertyName ) const
1144 EventMap::const_iterator pos = m_aEvents.find( _rPropertyName );
1145 if ( pos == m_aEvents.end() )
1146 throw UnknownPropertyException();
1147 return pos->second;
1150 //--------------------------------------------------------------------
1151 namespace
1153 static bool lcl_endsWith( const ::rtl::OUString& _rText, const ::rtl::OUString& _rCheck )
1155 sal_Int32 nTextLen = _rText.getLength();
1156 sal_Int32 nCheckLen = _rCheck.getLength();
1157 if ( nCheckLen > nTextLen )
1158 return false;
1160 return _rText.indexOf( _rCheck ) == ( nTextLen - nCheckLen );
1163 //--------------------------------------------------------------------
1164 void EventHandler::impl_setFormComponentScriptEvent_nothrow( const ScriptEventDescriptor& _rScriptEvent )
1168 ::rtl::OUString sScriptCode( _rScriptEvent.ScriptCode );
1169 ::rtl::OUString sScriptType( _rScriptEvent.ScriptType );
1170 bool bResetScript = ( sScriptCode.getLength() == 0 );
1172 sal_Int32 nObjectIndex = impl_getComponentIndexInParent_throw();
1173 Reference< XChild > xChild( m_xComponent, UNO_QUERY_THROW );
1174 Reference< XEventAttacherManager > xEventManager( xChild->getParent(), UNO_QUERY_THROW );
1175 Sequence< ScriptEventDescriptor > aEvents( xEventManager->getScriptEvents( nObjectIndex ) );
1177 // is there already a registered script for this event?
1178 ScriptEventDescriptor* pEvent = aEvents.getArray();
1179 sal_Int32 eventCount = aEvents.getLength(), event = 0;
1180 for ( event = 0; event < eventCount; ++event, ++pEvent )
1182 if ( ( pEvent->EventMethod == _rScriptEvent.EventMethod )
1183 && ( lcl_endsWith( _rScriptEvent.ListenerType, pEvent->ListenerType ) )
1184 // (strange enough, the events we get from getScriptEvents are not fully qualified)
1187 // yes
1188 if ( !bResetScript )
1190 // set to something non-empty -> overwrite
1191 pEvent->ScriptCode = sScriptCode;
1192 pEvent->ScriptType = sScriptType;
1194 else
1196 // set to empty -> remove from sequence
1197 ::std::copy( pEvent + 1, aEvents.getArray() + eventCount, pEvent );
1198 aEvents.realloc( eventCount - 1 );
1199 --eventCount;
1201 break;
1204 if ( ( event >= eventCount ) && !bResetScript )
1206 // no, did not find it -> append
1207 aEvents.realloc( eventCount + 1 );
1208 aEvents[ eventCount ] = _rScriptEvent;
1211 xEventManager->revokeScriptEvents( nObjectIndex );
1212 xEventManager->registerScriptEvents( nObjectIndex, aEvents );
1214 PropertyHandlerHelper::setContextDocumentModified( m_aContext );
1216 catch( const Exception& )
1218 OSL_ENSURE( false, "EventHandler::impl_setFormComponentScriptEvent_nothrow: caught an exception!" );
1222 //--------------------------------------------------------------------
1223 void EventHandler::impl_setDialogElementScriptEvent_nothrow( const ScriptEventDescriptor& _rScriptEvent )
1227 ::rtl::OUString sScriptCode( _rScriptEvent.ScriptCode );
1228 bool bResetScript = ( sScriptCode.getLength() == 0 );
1230 Reference< XScriptEventsSupplier > xEventsSupplier( m_xComponent, UNO_QUERY_THROW );
1231 Reference< XNameContainer > xEvents( xEventsSupplier->getEvents(), UNO_QUERY_THROW );
1233 ::rtl::OUStringBuffer aCompleteName;
1234 aCompleteName.append( _rScriptEvent.ListenerType );
1235 aCompleteName.appendAscii( "::" );
1236 aCompleteName.append( _rScriptEvent.EventMethod );
1237 ::rtl::OUString sCompleteName( aCompleteName.makeStringAndClear() );
1239 bool bExists = xEvents->hasByName( sCompleteName );
1241 if ( bResetScript )
1243 if ( bExists )
1244 xEvents->removeByName( sCompleteName );
1246 else
1248 Any aNewValue; aNewValue <<= _rScriptEvent;
1250 if ( bExists )
1251 xEvents->replaceByName( sCompleteName, aNewValue );
1252 else
1253 xEvents->insertByName( sCompleteName, aNewValue );
1256 catch( const Exception& )
1258 DBG_UNHANDLED_EXCEPTION();
1262 //--------------------------------------------------------------------
1263 bool EventHandler::impl_filterMethod_nothrow( const EventDescription& _rEvent ) const
1265 // some (control-triggered) events do not make sense for certain grid control columns. However,
1266 // our mechnism to retrieve control-triggered events does not know about this, so we do some
1267 // late filtering here.
1268 switch ( m_nGridColumnType )
1270 case FormComponentType::COMBOBOX:
1271 if ( UID_BRWEVT_ACTIONPERFORMED == _rEvent.nUniqueBrowseId )
1272 return false;
1273 break;
1274 case FormComponentType::LISTBOX:
1275 if ( ( UID_BRWEVT_CHANGED == _rEvent.nUniqueBrowseId )
1276 || ( UID_BRWEVT_ACTIONPERFORMED == _rEvent.nUniqueBrowseId )
1278 return false;
1279 break;
1282 return true;
1285 //........................................................................
1286 } // namespace pcr
1287 //........................................................................