bump product version to 4.1.6.2
[LibreOffice.git] / extensions / source / propctrlr / eventhandler.cxx
blobfb058aa7427997f1664b3cc564e7fae3b550e745
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "eventhandler.hxx"
22 #include "propctrlr.hrc"
23 #include "formbrowsertools.hxx"
24 #include "formresid.hrc"
25 #include "formstrings.hxx"
26 #include "handlerhelper.hxx"
27 #include "modulepcr.hxx"
28 #include "pcrcommon.hxx"
29 #include "pcrstrings.hxx"
30 #include "propertycontrolextender.hxx"
32 #include <com/sun/star/awt/XTabControllerModel.hpp>
33 #include <com/sun/star/beans/PropertyAttribute.hpp>
34 #include <com/sun/star/beans/UnknownPropertyException.hpp>
35 #include <com/sun/star/beans/Introspection.hpp>
36 #include <com/sun/star/beans/XIntrospectionAccess.hpp>
37 #include <com/sun/star/container/NoSuchElementException.hpp>
38 #include <com/sun/star/container/XChild.hpp>
39 #include <com/sun/star/container/XIndexAccess.hpp>
40 #include <com/sun/star/container/XNameContainer.hpp>
41 #include <com/sun/star/container/XNameReplace.hpp>
42 #include <com/sun/star/form/FormComponentType.hpp>
43 #include <com/sun/star/form/XForm.hpp>
44 #include <com/sun/star/form/runtime/FormController.hpp>
45 #include <com/sun/star/inspection/PropertyControlType.hpp>
46 #include <com/sun/star/lang/NullPointerException.hpp>
47 #include <com/sun/star/script/XEventAttacherManager.hpp>
48 #include <com/sun/star/script/XScriptEventsSupplier.hpp>
49 #include <com/sun/star/util/XModifiable.hpp>
50 #include <com/sun/star/uri/UriReferenceFactory.hpp>
51 #include <com/sun/star/uri/XVndSunStarScriptUrlReference.hpp>
53 #include <comphelper/namedvaluecollection.hxx>
54 #include <comphelper/evtmethodhelper.hxx>
55 #include <comphelper/types.hxx>
56 #include <cppuhelper/implbase1.hxx>
57 #include <rtl/ref.hxx>
58 #include <rtl/ustrbuf.hxx>
59 #include <sfx2/app.hxx>
60 #include <svl/eitem.hxx>
61 #include <svl/itemset.hxx>
62 #include <svx/svxdlg.hxx>
63 #include <svx/svxids.hrc>
64 #include <tools/diagnose_ex.h>
65 #include <vcl/msgbox.hxx>
67 #include <map>
68 #include <algorithm>
69 #include <o3tl/compat_functional.hxx>
71 //------------------------------------------------------------------------
72 extern "C" void SAL_CALL createRegistryInfo_EventHandler()
74 ::pcr::OAutoRegistration< ::pcr::EventHandler > aAutoRegistration;
77 //........................................................................
78 namespace pcr
80 //........................................................................
82 using ::com::sun::star::uno::Reference;
83 using ::com::sun::star::uno::XComponentContext;
84 using ::com::sun::star::beans::XPropertySet;
85 using ::com::sun::star::uno::Any;
86 using ::com::sun::star::uno::TypeClass_STRING;
87 using ::com::sun::star::uno::Type;
88 using ::com::sun::star::beans::Introspection;
89 using ::com::sun::star::beans::XPropertyChangeListener;
90 using ::com::sun::star::beans::Property;
91 using ::com::sun::star::beans::PropertyState;
92 using ::com::sun::star::beans::PropertyState_DIRECT_VALUE;
93 using ::com::sun::star::uno::Sequence;
94 using ::com::sun::star::script::ScriptEventDescriptor;
95 using ::com::sun::star::script::XScriptEventsSupplier;
96 using ::com::sun::star::lang::NullPointerException;
97 using ::com::sun::star::uno::Exception;
98 using ::com::sun::star::container::XChild;
99 using ::com::sun::star::container::XIndexAccess;
100 using ::com::sun::star::script::XEventAttacherManager;
101 using ::com::sun::star::uno::UNO_QUERY;
102 using ::com::sun::star::uno::UNO_QUERY_THROW;
103 using ::com::sun::star::uno::XInterface;
104 using ::com::sun::star::beans::XIntrospection;
105 using ::com::sun::star::beans::XIntrospectionAccess;
106 using ::com::sun::star::container::XNameContainer;
107 using ::com::sun::star::awt::XTabControllerModel;
108 using ::com::sun::star::form::XForm;
109 using ::com::sun::star::form::runtime::FormController;
110 using ::com::sun::star::form::runtime::XFormController;
111 using ::com::sun::star::beans::UnknownPropertyException;
112 using ::com::sun::star::uno::makeAny;
113 using ::com::sun::star::container::NoSuchElementException;
114 using ::com::sun::star::beans::XPropertySetInfo;
115 using ::com::sun::star::container::XNameReplace;
116 using ::com::sun::star::lang::IllegalArgumentException;
117 using ::com::sun::star::lang::WrappedTargetException;
118 using ::com::sun::star::uno::RuntimeException;
119 using ::com::sun::star::beans::PropertyValue;
120 using ::com::sun::star::inspection::LineDescriptor;
121 using ::com::sun::star::inspection::XPropertyControlFactory;
122 using ::com::sun::star::inspection::InteractiveSelectionResult;
123 using ::com::sun::star::inspection::InteractiveSelectionResult_Cancelled;
124 using ::com::sun::star::inspection::InteractiveSelectionResult_Success;
125 using ::com::sun::star::inspection::XObjectInspectorUI;
126 using ::com::sun::star::util::XModifiable;
127 using ::com::sun::star::beans::PropertyChangeEvent;
128 using ::com::sun::star::frame::XFrame;
129 using ::com::sun::star::frame::XModel;
130 using ::com::sun::star::frame::XController;
131 using ::com::sun::star::uno::UNO_SET_THROW;
132 using com::sun::star::uri::UriReferenceFactory;
133 using com::sun::star::uri::XUriReferenceFactory;
134 using com::sun::star::uri::XVndSunStarScriptUrlReference;
135 using ::com::sun::star::lang::XEventListener;
137 namespace PropertyControlType = ::com::sun::star::inspection::PropertyControlType;
138 namespace PropertyAttribute = ::com::sun::star::beans::PropertyAttribute;
139 namespace FormComponentType = ::com::sun::star::form::FormComponentType;
141 //====================================================================
142 //= EventDescription
143 //====================================================================
144 EventDescription::EventDescription( EventId _nId, const sal_Char* _pListenerNamespaceAscii, const sal_Char* _pListenerClassAsciiName,
145 const sal_Char* _pListenerMethodAsciiName, sal_uInt16 _nDisplayNameResId, const OString& _sHelpId, const OString& _sUniqueBrowseId )
146 :sDisplayName( String( PcrRes( _nDisplayNameResId ) ) )
147 ,sListenerMethodName( OUString::createFromAscii( _pListenerMethodAsciiName ) )
148 ,sHelpId( _sHelpId )
149 ,sUniqueBrowseId( _sUniqueBrowseId )
150 ,nId( _nId )
152 OUStringBuffer aQualifiedListenerClass;
153 aQualifiedListenerClass.appendAscii( "com.sun.star." );
154 aQualifiedListenerClass.appendAscii( _pListenerNamespaceAscii );
155 aQualifiedListenerClass.appendAscii( "." );
156 aQualifiedListenerClass.appendAscii( _pListenerClassAsciiName );
157 sListenerClassName = aQualifiedListenerClass.makeStringAndClear();
160 //========================================================================
161 //= helper
162 //========================================================================
163 namespace
165 //....................................................................
166 #define DESCRIBE_EVENT( asciinamespace, asciilistener, asciimethod, id_postfix ) \
167 s_aKnownEvents.insert( EventMap::value_type( \
168 OUString::createFromAscii( asciimethod ), \
169 EventDescription( ++nEventId, asciinamespace, asciilistener, asciimethod, RID_STR_EVT_##id_postfix, HID_EVT_##id_postfix, UID_BRWEVT_##id_postfix ) ) )
171 //....................................................................
172 bool lcl_getEventDescriptionForMethod( const OUString& _rMethodName, EventDescription& _out_rDescription )
174 static EventMap s_aKnownEvents;
175 if ( s_aKnownEvents.empty() )
177 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
178 if ( s_aKnownEvents.empty() )
180 static sal_Int32 nEventId = 0;
182 DESCRIBE_EVENT( "form", "XApproveActionListener", "approveAction", APPROVEACTIONPERFORMED );
183 DESCRIBE_EVENT( "awt", "XActionListener", "actionPerformed", ACTIONPERFORMED );
184 DESCRIBE_EVENT( "form", "XChangeListener", "changed", CHANGED );
185 DESCRIBE_EVENT( "awt", "XTextListener", "textChanged", TEXTCHANGED );
186 DESCRIBE_EVENT( "awt", "XItemListener", "itemStateChanged", ITEMSTATECHANGED );
187 DESCRIBE_EVENT( "awt", "XFocusListener", "focusGained", FOCUSGAINED );
188 DESCRIBE_EVENT( "awt", "XFocusListener", "focusLost", FOCUSLOST );
189 DESCRIBE_EVENT( "awt", "XKeyListener", "keyPressed", KEYTYPED );
190 DESCRIBE_EVENT( "awt", "XKeyListener", "keyReleased", KEYUP );
191 DESCRIBE_EVENT( "awt", "XMouseListener", "mouseEntered", MOUSEENTERED );
192 DESCRIBE_EVENT( "awt", "XMouseMotionListener", "mouseDragged", MOUSEDRAGGED );
193 DESCRIBE_EVENT( "awt", "XMouseMotionListener", "mouseMoved", MOUSEMOVED );
194 DESCRIBE_EVENT( "awt", "XMouseListener", "mousePressed", MOUSEPRESSED );
195 DESCRIBE_EVENT( "awt", "XMouseListener", "mouseReleased", MOUSERELEASED );
196 DESCRIBE_EVENT( "awt", "XMouseListener", "mouseExited", MOUSEEXITED );
197 DESCRIBE_EVENT( "form", "XResetListener", "approveReset", APPROVERESETTED );
198 DESCRIBE_EVENT( "form", "XResetListener", "resetted", RESETTED );
199 DESCRIBE_EVENT( "form", "XSubmitListener", "approveSubmit", SUBMITTED );
200 DESCRIBE_EVENT( "form", "XUpdateListener", "approveUpdate", BEFOREUPDATE );
201 DESCRIBE_EVENT( "form", "XUpdateListener", "updated", AFTERUPDATE );
202 DESCRIBE_EVENT( "form", "XLoadListener", "loaded", LOADED );
203 DESCRIBE_EVENT( "form", "XLoadListener", "reloading", RELOADING );
204 DESCRIBE_EVENT( "form", "XLoadListener", "reloaded", RELOADED );
205 DESCRIBE_EVENT( "form", "XLoadListener", "unloading", UNLOADING );
206 DESCRIBE_EVENT( "form", "XLoadListener", "unloaded", UNLOADED );
207 DESCRIBE_EVENT( "form", "XConfirmDeleteListener", "confirmDelete", CONFIRMDELETE );
208 DESCRIBE_EVENT( "sdb", "XRowSetApproveListener", "approveRowChange", APPROVEROWCHANGE );
209 DESCRIBE_EVENT( "sdbc", "XRowSetListener", "rowChanged", ROWCHANGE );
210 DESCRIBE_EVENT( "sdb", "XRowSetApproveListener", "approveCursorMove", POSITIONING );
211 DESCRIBE_EVENT( "sdbc", "XRowSetListener", "cursorMoved", POSITIONED );
212 DESCRIBE_EVENT( "form", "XDatabaseParameterListener", "approveParameter", APPROVEPARAMETER );
213 DESCRIBE_EVENT( "sdb", "XSQLErrorListener", "errorOccured", ERROROCCURRED );
214 DESCRIBE_EVENT( "awt", "XAdjustmentListener", "adjustmentValueChanged", ADJUSTMENTVALUECHANGED );
218 EventMap::const_iterator pos = s_aKnownEvents.find( _rMethodName );
219 if ( pos == s_aKnownEvents.end() )
220 return false;
222 _out_rDescription = pos->second;
223 return true;
226 //....................................................................
227 OUString lcl_getEventPropertyName( const OUString& _rListenerClassName, const OUString& _rMethodName )
229 OUStringBuffer aPropertyName;
230 aPropertyName.append( _rListenerClassName );
231 aPropertyName.append( (sal_Unicode)';' );
232 aPropertyName.append( _rMethodName.getStr() );
233 return aPropertyName.makeStringAndClear();
236 //................................................................
237 ScriptEventDescriptor lcl_getAssignedScriptEvent( const EventDescription& _rEvent, const Sequence< ScriptEventDescriptor >& _rAllAssignedMacros )
239 ScriptEventDescriptor aScriptEvent;
240 // for the case there is actually no event assigned, initialize at least ListenerType and MethodName,
241 // so this ScriptEventDescriptor properly describes the given event
242 aScriptEvent.ListenerType = _rEvent.sListenerClassName;
243 aScriptEvent.EventMethod = _rEvent.sListenerMethodName;
245 const ScriptEventDescriptor* pAssignedEvent = _rAllAssignedMacros.getConstArray();
246 sal_Int32 assignedEventCount( _rAllAssignedMacros.getLength() );
247 for ( sal_Int32 assignedEvent = 0; assignedEvent < assignedEventCount; ++assignedEvent, ++pAssignedEvent )
249 if ( ( pAssignedEvent->ListenerType != _rEvent.sListenerClassName )
250 || ( pAssignedEvent->EventMethod != _rEvent.sListenerMethodName )
252 continue;
254 if ( ( pAssignedEvent->ScriptCode.isEmpty() )
255 || ( pAssignedEvent->ScriptType.isEmpty() )
258 OSL_FAIL( "lcl_getAssignedScriptEvent: me thinks this should not happen!" );
259 continue;
262 aScriptEvent = *pAssignedEvent;
264 if ( aScriptEvent.ScriptType != "StarBasic" )
265 continue;
267 // this is an old-style macro specification:
268 // [document|application]:Library.Module.Function
269 // we need to translate this to the new-style macro specification
270 // vnd.sun.star.script:Library.Module.Function?language=Basic&location=[document|application]
272 sal_Int32 nPrefixLen = aScriptEvent.ScriptCode.indexOf( ':' );
273 OSL_ENSURE( nPrefixLen > 0, "lcl_getAssignedScriptEvent: illegal location!" );
274 OUString sLocation = aScriptEvent.ScriptCode.copy( 0, nPrefixLen );
275 OUString sMacroPath = aScriptEvent.ScriptCode.copy( nPrefixLen + 1 );
277 OUStringBuffer aNewStyleSpec;
278 aNewStyleSpec.appendAscii( "vnd.sun.star.script:" );
279 aNewStyleSpec.append ( sMacroPath );
280 aNewStyleSpec.appendAscii( "?language=Basic&location=" );
281 aNewStyleSpec.append ( sLocation );
283 aScriptEvent.ScriptCode = aNewStyleSpec.makeStringAndClear();
285 // also, this new-style spec requires the script code to be "Script" instead of "StarBasic"
286 aScriptEvent.ScriptType = OUString( "Script" );
288 return aScriptEvent;
291 //................................................................
292 OUString lcl_getQualifiedKnownListenerName( const ScriptEventDescriptor& _rFormComponentEventDescriptor )
294 EventDescription aKnownEvent;
295 if ( lcl_getEventDescriptionForMethod( _rFormComponentEventDescriptor.EventMethod, aKnownEvent ) )
296 return aKnownEvent.sListenerClassName;
297 OSL_FAIL( "lcl_getQualifiedKnownListenerName: unknown method name!" );
298 // somebody assigned an script to a form component event which we don't know
299 // Speaking strictly, this is not really an error - it is possible to do
300 // this programmatically -, but it should rarely happen, since it's not possible
301 // via UI
302 return _rFormComponentEventDescriptor.ListenerType;
305 //................................................................
306 typedef ::std::set< Type, TypeLessByName > TypeBag;
308 //................................................................
309 void lcl_addListenerTypesFor_throw( const Reference< XInterface >& _rxComponent,
310 const Reference< XIntrospection >& _rxIntrospection, TypeBag& _out_rTypes )
312 if ( !_rxComponent.is() )
313 return;
314 OSL_PRECOND( _rxIntrospection.is(), "lcl_addListenerTypesFor_throw: this will crash!" );
316 Reference< XIntrospectionAccess > xIntrospectionAccess(
317 _rxIntrospection->inspect( makeAny( _rxComponent ) ), UNO_QUERY_THROW );
319 Sequence< Type > aListeners( xIntrospectionAccess->getSupportedListeners() );
321 ::std::copy( aListeners.getConstArray(), aListeners.getConstArray() + aListeners.getLength(),
322 ::std::insert_iterator< TypeBag >( _out_rTypes, _out_rTypes.begin() ) );
325 //................................................................
326 bool operator ==( const ScriptEventDescriptor _lhs, const ScriptEventDescriptor _rhs )
328 return ( ( _lhs.ListenerType == _rhs.ListenerType )
329 && ( _lhs.EventMethod == _rhs.EventMethod )
330 && ( _lhs.AddListenerParam == _rhs.AddListenerParam )
331 && ( _lhs.ScriptType == _rhs.ScriptType )
332 && ( _lhs.ScriptCode == _rhs.ScriptCode )
337 //====================================================================
338 //= EventHandler
339 //====================================================================
340 typedef ::cppu::WeakImplHelper1 < ::com::sun::star::container::XNameReplace
341 > EventHolder_Base;
342 /** a UNO component holding assigned event descriptions, for use with a SvxMacroAssignDlg
344 class EventHolder : public EventHolder_Base
346 private:
347 typedef ::boost::unordered_map< OUString, ScriptEventDescriptor, OUStringHash > EventMap;
348 typedef ::std::map< EventId, EventMap::iterator > EventMapIndexAccess;
350 EventMap m_aEventNameAccess;
351 EventMapIndexAccess m_aEventIndexAccess;
353 public:
354 EventHolder( );
356 void addEvent( EventId _nId, const OUString& _rEventName, const ScriptEventDescriptor& _rScriptEvent );
358 /** effectively the same as getByName, but instead of converting the ScriptEventDescriptor to the weird
359 format used by the macro assignment dialog, it is returned directly
361 ScriptEventDescriptor getNormalizedDescriptorByName( const OUString& _rEventName ) const;
363 // XNameReplace
364 virtual void SAL_CALL replaceByName( const OUString& _rName, const Any& aElement ) throw (IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException);
365 virtual Any SAL_CALL getByName( const OUString& _rName ) throw (NoSuchElementException, WrappedTargetException, RuntimeException);
366 virtual Sequence< OUString > SAL_CALL getElementNames( ) throw (RuntimeException);
367 virtual ::sal_Bool SAL_CALL hasByName( const OUString& _rName ) throw (RuntimeException);
368 virtual Type SAL_CALL getElementType( ) throw (RuntimeException);
369 virtual ::sal_Bool SAL_CALL hasElements( ) throw (RuntimeException);
371 protected:
372 ~EventHolder( );
374 private:
375 ScriptEventDescriptor impl_getDescriptor_throw( const OUString& _rEventName ) const;
378 DBG_NAME( EventHolder )
379 //------------------------------------------------------------------------
380 EventHolder::EventHolder()
382 DBG_CTOR( EventHolder, NULL );
385 //------------------------------------------------------------------------
386 EventHolder::~EventHolder()
388 m_aEventNameAccess.clear();
389 m_aEventIndexAccess.clear();
390 DBG_DTOR( EventHolder, NULL );
393 //------------------------------------------------------------------------
394 void EventHolder::addEvent( EventId _nId, const OUString& _rEventName, const ScriptEventDescriptor& _rScriptEvent )
396 ::std::pair< EventMap::iterator, bool > insertionResult =
397 m_aEventNameAccess.insert( EventMap::value_type( _rEventName, _rScriptEvent ) );
398 OSL_ENSURE( insertionResult.second, "EventHolder::addEvent: there already was a MacroURL for this event!" );
399 m_aEventIndexAccess[ _nId ] = insertionResult.first;
402 //------------------------------------------------------------------------
403 ScriptEventDescriptor EventHolder::getNormalizedDescriptorByName( const OUString& _rEventName ) const
405 return impl_getDescriptor_throw( _rEventName );
408 //------------------------------------------------------------------------
409 ScriptEventDescriptor EventHolder::impl_getDescriptor_throw( const OUString& _rEventName ) const
411 EventMap::const_iterator pos = m_aEventNameAccess.find( _rEventName );
412 if ( pos == m_aEventNameAccess.end() )
413 throw NoSuchElementException( OUString(), *const_cast< EventHolder* >( this ) );
414 return pos->second;
417 //------------------------------------------------------------------------
418 void SAL_CALL EventHolder::replaceByName( const OUString& _rName, const Any& _rElement ) throw (IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException)
420 EventMap::iterator pos = m_aEventNameAccess.find( _rName );
421 if ( pos == m_aEventNameAccess.end() )
422 throw NoSuchElementException( OUString(), *this );
424 Sequence< PropertyValue > aScriptDescriptor;
425 OSL_VERIFY( _rElement >>= aScriptDescriptor );
427 ::comphelper::NamedValueCollection aExtractor( aScriptDescriptor );
429 pos->second.ScriptType = aExtractor.getOrDefault( "EventType", OUString() );
430 pos->second.ScriptCode = aExtractor.getOrDefault( "Script", OUString() );
433 //------------------------------------------------------------------------
434 Any SAL_CALL EventHolder::getByName( const OUString& _rName ) throw (NoSuchElementException, WrappedTargetException, RuntimeException)
436 ScriptEventDescriptor aDescriptor( impl_getDescriptor_throw( _rName ) );
438 Any aRet;
439 Sequence< PropertyValue > aScriptDescriptor( 2 );
440 aScriptDescriptor[0].Name = OUString("EventType");
441 aScriptDescriptor[0].Value <<= aDescriptor.ScriptType;
442 aScriptDescriptor[1].Name = OUString("Script");
443 aScriptDescriptor[1].Value <<= aDescriptor.ScriptCode;
445 return makeAny( aScriptDescriptor );
448 //------------------------------------------------------------------------
449 Sequence< OUString > SAL_CALL EventHolder::getElementNames( ) throw (RuntimeException)
451 Sequence< OUString > aReturn( m_aEventIndexAccess.size() );
452 OUString* pReturn = aReturn.getArray();
454 // SvxMacroAssignDlg has a weird API: It expects a XNameReplace, means a container whose
455 // main access method is by name. In it's UI, it shows the possible events in exactly the
456 // order in which XNameAccess::getElementNames returns them.
457 // However, SvxMacroAssignDlg *also* takes an index for the initial selection, which is
458 // relative to the sequence returned by XNameAccess::getElementNames.
459 // This is IMO weird, since it mixes index access with name access, which decreases efficiency
460 // of the implementation.
461 // Well, it means we're forced to return the events in getElementNames in exactly the same as they
462 // appear in the property browser UI.
463 for ( EventMapIndexAccess::const_iterator loop = m_aEventIndexAccess.begin();
464 loop != m_aEventIndexAccess.end();
465 ++loop, ++pReturn
467 *pReturn = loop->second->first;
468 return aReturn;
471 //------------------------------------------------------------------------
472 sal_Bool SAL_CALL EventHolder::hasByName( const OUString& _rName ) throw (RuntimeException)
474 EventMap::const_iterator pos = m_aEventNameAccess.find( _rName );
475 return pos != m_aEventNameAccess.end();
478 //------------------------------------------------------------------------
479 Type SAL_CALL EventHolder::getElementType( ) throw (RuntimeException)
481 return ::getCppuType( static_cast< Sequence< PropertyValue >* >( NULL ) );
484 //------------------------------------------------------------------------
485 sal_Bool SAL_CALL EventHolder::hasElements( ) throw (RuntimeException)
487 return !m_aEventNameAccess.empty();
491 //====================================================================
492 //= EventHandler
493 //====================================================================
494 DBG_NAME( EventHandler )
495 //--------------------------------------------------------------------
496 EventHandler::EventHandler( const Reference< XComponentContext >& _rxContext )
497 :EventHandler_Base( m_aMutex )
498 ,m_aContext( _rxContext )
499 ,m_aPropertyListeners( m_aMutex )
500 ,m_bEventsMapInitialized( false )
501 ,m_bIsDialogElement( false )
502 ,m_nGridColumnType( -1 )
504 DBG_CTOR( EventHandler, NULL );
507 //--------------------------------------------------------------------
508 EventHandler::~EventHandler()
510 DBG_DTOR( EventHandler, NULL );
513 //--------------------------------------------------------------------
514 OUString SAL_CALL EventHandler::getImplementationName( ) throw (RuntimeException)
516 return getImplementationName_static();
519 //--------------------------------------------------------------------
520 ::sal_Bool SAL_CALL EventHandler::supportsService( const OUString& ServiceName ) throw (RuntimeException)
522 StlSyntaxSequence< OUString > aAllServices( getSupportedServiceNames() );
523 return ::std::find( aAllServices.begin(), aAllServices.end(), ServiceName ) != aAllServices.end();
526 //--------------------------------------------------------------------
527 Sequence< OUString > SAL_CALL EventHandler::getSupportedServiceNames( ) throw (RuntimeException)
529 return getSupportedServiceNames_static();
532 //--------------------------------------------------------------------
533 OUString SAL_CALL EventHandler::getImplementationName_static( ) throw (RuntimeException)
535 return OUString( "com.sun.star.comp.extensions.EventHandler" );
538 //--------------------------------------------------------------------
539 Sequence< OUString > SAL_CALL EventHandler::getSupportedServiceNames_static( ) throw (RuntimeException)
541 Sequence< OUString > aSupported( 1 );
542 aSupported[0] = OUString( "com.sun.star.form.inspection.EventHandler" );
543 return aSupported;
546 //--------------------------------------------------------------------
547 Reference< XInterface > SAL_CALL EventHandler::Create( const Reference< XComponentContext >& _rxContext )
549 return *( new EventHandler( _rxContext ) );
552 //--------------------------------------------------------------------
553 void SAL_CALL EventHandler::inspect( const Reference< XInterface >& _rxIntrospectee ) throw (RuntimeException, NullPointerException)
555 ::osl::MutexGuard aGuard( m_aMutex );
557 if ( !_rxIntrospectee.is() )
558 throw NullPointerException();
560 m_xComponent = Reference< XPropertySet >( _rxIntrospectee, UNO_QUERY_THROW );
562 m_bEventsMapInitialized = false;
563 EventMap aEmpty;
564 m_aEvents.swap( aEmpty );
566 m_bIsDialogElement = false;
567 m_nGridColumnType = -1;
570 Reference< XPropertySetInfo > xPSI( m_xComponent->getPropertySetInfo() );
571 m_bIsDialogElement = xPSI.is()
572 && xPSI->hasPropertyByName( PROPERTY_WIDTH )
573 && xPSI->hasPropertyByName( PROPERTY_HEIGHT )
574 && xPSI->hasPropertyByName( PROPERTY_POSITIONX )
575 && xPSI->hasPropertyByName( PROPERTY_POSITIONY );
577 Reference< XChild > xAsChild( _rxIntrospectee, UNO_QUERY );
578 if ( xAsChild.is() && !Reference< XForm >( _rxIntrospectee, UNO_QUERY ).is() )
580 if ( FormComponentType::GRIDCONTROL == classifyComponent( xAsChild->getParent() ) )
582 m_nGridColumnType = classifyComponent( _rxIntrospectee );
586 catch( const Exception& )
588 DBG_UNHANDLED_EXCEPTION();
592 //--------------------------------------------------------------------
593 Any SAL_CALL EventHandler::getPropertyValue( const OUString& _rPropertyName ) throw (UnknownPropertyException, RuntimeException)
595 ::osl::MutexGuard aGuard( m_aMutex );
597 const EventDescription& rEvent = impl_getEventForName_throw( _rPropertyName );
599 Sequence< ScriptEventDescriptor > aEvents;
600 impl_getComponentScriptEvents_nothrow( aEvents );
602 sal_Int32 nEventCount = aEvents.getLength();
603 const ScriptEventDescriptor* pEvents = aEvents.getConstArray();
605 ScriptEventDescriptor aPropertyValue;
606 for ( sal_Int32 event = 0; event < nEventCount; ++event, ++pEvents )
608 if ( rEvent.sListenerClassName == pEvents->ListenerType
609 && rEvent.sListenerMethodName == pEvents->EventMethod
612 aPropertyValue = *pEvents;
613 break;
617 return makeAny( aPropertyValue );
620 //--------------------------------------------------------------------
621 void SAL_CALL EventHandler::setPropertyValue( const OUString& _rPropertyName, const Any& _rValue ) throw (UnknownPropertyException, RuntimeException)
623 ::osl::MutexGuard aGuard( m_aMutex );
625 const EventDescription& rEvent = impl_getEventForName_throw( _rPropertyName );
627 ScriptEventDescriptor aNewScriptEvent;
628 OSL_VERIFY( _rValue >>= aNewScriptEvent );
630 ScriptEventDescriptor aOldScriptEvent;
631 OSL_VERIFY( getPropertyValue( _rPropertyName ) >>= aOldScriptEvent );
632 if ( aOldScriptEvent == aNewScriptEvent )
633 return;
635 if ( m_bIsDialogElement )
636 impl_setDialogElementScriptEvent_nothrow( aNewScriptEvent );
637 else
638 impl_setFormComponentScriptEvent_nothrow( aNewScriptEvent );
640 Reference< XModifiable > xDoc( m_aContext.getContextValueByAsciiName( "ContextDocument" ), UNO_QUERY );
641 if ( xDoc.is() )
642 xDoc->setModified( sal_True );
644 PropertyChangeEvent aEvent;
645 aEvent.Source = m_xComponent;
646 aEvent.PropertyHandle = rEvent.nId;
647 aEvent.PropertyName = _rPropertyName;
648 aEvent.OldValue <<= aOldScriptEvent;
649 aEvent.NewValue <<= aNewScriptEvent;
650 m_aPropertyListeners.notify( aEvent, &XPropertyChangeListener::propertyChange );
653 //--------------------------------------------------------------------
654 Any SAL_CALL EventHandler::convertToPropertyValue( const OUString& _rPropertyName, const Any& _rControlValue ) throw (UnknownPropertyException, RuntimeException)
656 ::osl::MutexGuard aGuard( m_aMutex );
658 OUString sNewScriptCode;
659 OSL_VERIFY( _rControlValue >>= sNewScriptCode );
661 Sequence< ScriptEventDescriptor > aAllAssignedEvents;
662 impl_getComponentScriptEvents_nothrow( aAllAssignedEvents );
664 const EventDescription& rEvent = impl_getEventForName_throw( _rPropertyName );
665 ScriptEventDescriptor aAssignedScript = lcl_getAssignedScriptEvent( rEvent, aAllAssignedEvents );
667 OSL_ENSURE( sNewScriptCode.isEmpty(), "EventHandler::convertToPropertyValue: cannot convert a non-empty display name!" );
668 // Usually, there is no possibility for the user to change the content of an event binding directly in the
669 // input field, this instead is done with the macro assignment dialog.
670 // The only exception is the user pressing "DEL" while the control has the focus, in this case, we reset the
671 // control content to an empty string. So this is the only scenario where this method is allowed to be called.
673 // Striclty, we would be able to convert the display value to a property value,
674 // using the "name (location, language)" format we used in convertToControlValue. However,
675 // there is no need for this code ...
677 aAssignedScript.ScriptCode = sNewScriptCode;
678 return makeAny( aAssignedScript );
681 //--------------------------------------------------------------------
682 Any SAL_CALL EventHandler::convertToControlValue( const OUString& /*_rPropertyName*/, const Any& _rPropertyValue, const Type& _rControlValueType ) throw (UnknownPropertyException, RuntimeException)
684 ::osl::MutexGuard aGuard( m_aMutex );
686 ScriptEventDescriptor aScriptEvent;
687 OSL_VERIFY( _rPropertyValue >>= aScriptEvent );
689 OSL_ENSURE( _rControlValueType.getTypeClass() == TypeClass_STRING,
690 "EventHandler::convertToControlValue: unexpected ControlValue type class!" );
691 (void)_rControlValueType;
693 OUString sScript( aScriptEvent.ScriptCode );
694 if ( !sScript.isEmpty() )
696 // format is: "name (location, language)"
699 // parse
700 Reference< XUriReferenceFactory > xUriRefFac = UriReferenceFactory::create( m_aContext.getUNOContext() );
701 Reference< XVndSunStarScriptUrlReference > xScriptUri( xUriRefFac->parse( sScript ), UNO_QUERY_THROW );
703 OUStringBuffer aComposeBuffer;
705 // name
706 aComposeBuffer.append( xScriptUri->getName() );
708 // location
709 const OUString sLocationParamName( "location" );
710 const OUString sLocation = xScriptUri->getParameter( sLocationParamName );
711 const OUString sLangParamName( "language" );
712 const OUString sLanguage = xScriptUri->getParameter( sLangParamName );
714 if ( !(sLocation.isEmpty() && sLanguage.isEmpty()) )
716 aComposeBuffer.appendAscii( " (" );
718 // location
719 OSL_ENSURE( !sLocation.isEmpty(), "EventHandler::convertToControlValue: unexpected: no location!" );
720 if ( !sLocation.isEmpty() )
722 aComposeBuffer.append( sLocation );
723 aComposeBuffer.appendAscii( ", " );
726 // language
727 if ( !sLanguage.isEmpty() )
729 aComposeBuffer.append( sLanguage );
732 aComposeBuffer.append( sal_Unicode( ')' ) );
735 sScript = aComposeBuffer.makeStringAndClear();
737 catch( const Exception& )
739 DBG_UNHANDLED_EXCEPTION();
743 return makeAny( sScript );
746 //--------------------------------------------------------------------
747 PropertyState SAL_CALL EventHandler::getPropertyState( const OUString& /*_rPropertyName*/ ) throw (UnknownPropertyException, RuntimeException)
749 return PropertyState_DIRECT_VALUE;
752 //--------------------------------------------------------------------
753 void SAL_CALL EventHandler::addPropertyChangeListener( const Reference< XPropertyChangeListener >& _rxListener ) throw (RuntimeException)
755 ::osl::MutexGuard aGuard( m_aMutex );
756 if ( !_rxListener.is() )
757 throw NullPointerException();
758 m_aPropertyListeners.addListener( _rxListener );
761 //--------------------------------------------------------------------
762 void SAL_CALL EventHandler::removePropertyChangeListener( const Reference< XPropertyChangeListener >& _rxListener ) throw (RuntimeException)
764 ::osl::MutexGuard aGuard( m_aMutex );
765 m_aPropertyListeners.removeListener( _rxListener );
768 //--------------------------------------------------------------------
769 Sequence< Property > SAL_CALL EventHandler::getSupportedProperties() throw (RuntimeException)
771 ::osl::MutexGuard aGuard( m_aMutex );
772 if ( !m_bEventsMapInitialized )
774 const_cast< EventHandler* >( this )->m_bEventsMapInitialized = true;
777 Sequence< Type > aListeners;
778 impl_getCopmonentListenerTypes_nothrow( aListeners );
779 sal_Int32 listenerCount = aListeners.getLength();
781 Property aCurrentProperty;
782 OUString sListenerClassName;
784 // loop through all listeners and all methods, and see which we can present at the UI
785 const Type* pListeners = aListeners.getConstArray();
786 for ( sal_Int32 listener = 0; listener < listenerCount; ++listener, ++pListeners )
788 aCurrentProperty = Property();
790 // the programmatic name of the listener, to be used as "property" name
791 sListenerClassName = pListeners->getTypeName();
792 OSL_ENSURE( !sListenerClassName.isEmpty(), "EventHandler::getSupportedProperties: strange - no listener name ..." );
793 if ( sListenerClassName.isEmpty() )
794 continue;
796 // loop through all methods
797 Sequence< OUString > aMethods( comphelper::getEventMethodsForType( *pListeners ) );
799 const OUString* pMethods = aMethods.getConstArray();
800 sal_uInt32 methodCount = aMethods.getLength();
802 for (sal_uInt32 method = 0 ; method < methodCount ; ++method, ++pMethods )
804 EventDescription aEvent;
805 if ( !lcl_getEventDescriptionForMethod( *pMethods, aEvent ) )
806 continue;
808 if ( !impl_filterMethod_nothrow( aEvent ) )
809 continue;
811 const_cast< EventHandler* >( this )->m_aEvents.insert( EventMap::value_type(
812 lcl_getEventPropertyName( sListenerClassName, *pMethods ), aEvent ) );
817 catch( const Exception& )
819 DBG_UNHANDLED_EXCEPTION();
823 // sort them by ID - this is the relative ordering in the UI
824 ::std::map< EventId, Property > aOrderedProperties;
825 for ( EventMap::const_iterator loop = m_aEvents.begin();
826 loop != m_aEvents.end();
827 ++loop
830 aOrderedProperties[ loop->second.nId ] = Property(
831 loop->first, loop->second.nId,
832 ::getCppuType( static_cast< const OUString* >( NULL ) ),
833 PropertyAttribute::BOUND );
836 StlSyntaxSequence< Property > aReturn( aOrderedProperties.size() );
837 ::std::transform( aOrderedProperties.begin(), aOrderedProperties.end(), aReturn.begin(),
838 ::o3tl::select2nd< ::std::map< EventId, Property >::value_type >() );
839 return aReturn;
842 //--------------------------------------------------------------------
843 Sequence< OUString > SAL_CALL EventHandler::getSupersededProperties( ) throw (RuntimeException)
845 // none
846 return Sequence< OUString >( );
849 //--------------------------------------------------------------------
850 Sequence< OUString > SAL_CALL EventHandler::getActuatingProperties( ) throw (RuntimeException)
852 // none
853 return Sequence< OUString >( );
856 //--------------------------------------------------------------------
857 LineDescriptor SAL_CALL EventHandler::describePropertyLine( const OUString& _rPropertyName,
858 const Reference< XPropertyControlFactory >& _rxControlFactory )
859 throw (UnknownPropertyException, NullPointerException, RuntimeException)
861 if ( !_rxControlFactory.is() )
862 throw NullPointerException();
864 ::osl::MutexGuard aGuard( m_aMutex );
866 LineDescriptor aDescriptor;
868 aDescriptor.Control = _rxControlFactory->createPropertyControl( PropertyControlType::TextField, sal_True );
869 Reference< XEventListener > xControlExtender = new PropertyControlExtender( aDescriptor.Control );
871 const EventDescription& rEvent = impl_getEventForName_throw( _rPropertyName );
872 aDescriptor.DisplayName = rEvent.sDisplayName;
873 aDescriptor.HelpURL = HelpIdUrl::getHelpURL( rEvent.sHelpId );
874 aDescriptor.PrimaryButtonId = OStringToOUString(rEvent.sUniqueBrowseId, RTL_TEXTENCODING_UTF8);
875 aDescriptor.HasPrimaryButton = sal_True;
876 aDescriptor.Category = OUString( "Events" );
877 return aDescriptor;
880 //--------------------------------------------------------------------
881 ::sal_Bool SAL_CALL EventHandler::isComposable( const OUString& /*_rPropertyName*/ ) throw (UnknownPropertyException, RuntimeException)
883 return sal_False;
886 //--------------------------------------------------------------------
887 InteractiveSelectionResult SAL_CALL EventHandler::onInteractivePropertySelection( const OUString& _rPropertyName, sal_Bool /*_bPrimary*/, Any& /*_rData*/, const Reference< XObjectInspectorUI >& _rxInspectorUI ) throw (UnknownPropertyException, NullPointerException, RuntimeException)
889 if ( !_rxInspectorUI.is() )
890 throw NullPointerException();
892 ::osl::MutexGuard aGuard( m_aMutex );
893 const EventDescription& rForEvent = impl_getEventForName_throw( _rPropertyName );
895 Sequence< ScriptEventDescriptor > aAllAssignedEvents;
896 impl_getComponentScriptEvents_nothrow( aAllAssignedEvents );
898 // SvxMacroAssignDlg-compatible structure holding all event/assignments
899 ::rtl::Reference< EventHolder > pEventHolder( new EventHolder );
901 for ( EventMap::const_iterator event = m_aEvents.begin();
902 event != m_aEvents.end();
903 ++event
906 // the script which is assigned to the current event (if any)
907 ScriptEventDescriptor aAssignedScript = lcl_getAssignedScriptEvent( event->second, aAllAssignedEvents );
908 pEventHolder->addEvent( event->second.nId, event->second.sListenerMethodName, aAssignedScript );
911 // the initial selection in the dialog
912 Sequence< OUString > aNames( pEventHolder->getElementNames() );
913 const OUString* pChosenEvent = ::std::find( aNames.getConstArray(), aNames.getConstArray() + aNames.getLength(), rForEvent.sListenerMethodName );
914 sal_uInt16 nInitialSelection = (sal_uInt16)( pChosenEvent - aNames.getConstArray() );
916 // the dialog
917 SvxAbstractDialogFactory* pFactory = SvxAbstractDialogFactory::Create();
918 if ( !pFactory )
919 return InteractiveSelectionResult_Cancelled;
921 ::std::auto_ptr< VclAbstractDialog > pDialog( pFactory->CreateSvxMacroAssignDlg(
922 PropertyHandlerHelper::getDialogParentWindow( m_aContext ),
923 impl_getContextFrame_nothrow(),
924 m_bIsDialogElement,
925 pEventHolder.get(),
926 nInitialSelection
927 ) );
929 if ( !pDialog.get() )
930 return InteractiveSelectionResult_Cancelled;
932 // DF definite problem here
933 // OK & Cancel seem to be both returning 0
934 if ( pDialog->Execute() == RET_CANCEL )
935 return InteractiveSelectionResult_Cancelled;
939 for ( EventMap::const_iterator event = m_aEvents.begin();
940 event != m_aEvents.end();
941 ++event
944 ScriptEventDescriptor aScriptDescriptor( pEventHolder->getNormalizedDescriptorByName( event->second.sListenerMethodName ) );
946 // set the new "property value"
947 setPropertyValue(
948 lcl_getEventPropertyName( event->second.sListenerClassName, event->second.sListenerMethodName ),
949 makeAny( aScriptDescriptor )
953 catch( const Exception& )
955 DBG_UNHANDLED_EXCEPTION();
958 return InteractiveSelectionResult_Success;
961 //--------------------------------------------------------------------
962 void SAL_CALL EventHandler::actuatingPropertyChanged( const OUString& /*_rActuatingPropertyName*/, const Any& /*_rNewValue*/, const Any& /*_rOldValue*/, const Reference< XObjectInspectorUI >& /*_rxInspectorUI*/, sal_Bool /*_bFirstTimeInit*/ ) throw (NullPointerException, RuntimeException)
964 OSL_FAIL( "EventHandler::actuatingPropertyChanged: no actuating properties -> no callback (well, this is how it *should* be!)" );
967 //--------------------------------------------------------------------
968 IMPLEMENT_FORWARD_XCOMPONENT( EventHandler, EventHandler_Base )
970 //--------------------------------------------------------------------
971 void SAL_CALL EventHandler::disposing()
973 EventMap aEmpty;
974 m_aEvents.swap( aEmpty );
975 m_xComponent.clear();
978 //--------------------------------------------------------------------
979 sal_Bool SAL_CALL EventHandler::suspend( sal_Bool /*_bSuspend*/ ) throw (RuntimeException)
981 return sal_True;
984 //------------------------------------------------------------------------
985 Reference< XFrame > EventHandler::impl_getContextFrame_nothrow() const
987 Reference< XFrame > xContextFrame;
991 Reference< XModel > xContextDocument( m_aContext.getContextValueByAsciiName( "ContextDocument" ), UNO_QUERY_THROW );
992 Reference< XController > xController( xContextDocument->getCurrentController(), UNO_SET_THROW );
993 xContextFrame.set( xController->getFrame(), UNO_SET_THROW );
995 catch( const Exception& )
997 DBG_UNHANDLED_EXCEPTION();
1000 return xContextFrame;
1003 //--------------------------------------------------------------------
1004 sal_Int32 EventHandler::impl_getComponentIndexInParent_throw() const
1006 Reference< XChild > xChild( m_xComponent, UNO_QUERY_THROW );
1007 Reference< XIndexAccess > xParentAsIndexAccess( xChild->getParent(), UNO_QUERY_THROW );
1009 // get the index of the inspected object within it's parent container
1010 sal_Int32 nElements = xParentAsIndexAccess->getCount();
1011 for ( sal_Int32 i=0; i<nElements; ++i )
1013 Reference< XInterface > xElement( xParentAsIndexAccess->getByIndex( i ), UNO_QUERY_THROW );
1014 if ( xElement == m_xComponent )
1015 return i;
1017 throw NoSuchElementException();
1020 //--------------------------------------------------------------------
1021 void EventHandler::impl_getFormComponentScriptEvents_nothrow( Sequence < ScriptEventDescriptor >& _out_rEvents ) const
1023 _out_rEvents = Sequence < ScriptEventDescriptor >();
1026 Reference< XChild > xChild( m_xComponent, UNO_QUERY_THROW );
1027 Reference< XEventAttacherManager > xEventManager( xChild->getParent(), UNO_QUERY_THROW );
1028 _out_rEvents = xEventManager->getScriptEvents( impl_getComponentIndexInParent_throw() );
1030 // the form component script API has unqualified listener names, but for normalization
1031 // purpose, we want fully qualified ones
1032 ScriptEventDescriptor* pEvents = _out_rEvents.getArray();
1033 ScriptEventDescriptor* pEventsEnd = _out_rEvents.getArray() + _out_rEvents.getLength();
1034 while ( pEvents != pEventsEnd )
1036 pEvents->ListenerType = lcl_getQualifiedKnownListenerName( *pEvents );
1037 ++pEvents;
1040 catch( const Exception& )
1042 DBG_UNHANDLED_EXCEPTION();
1046 //--------------------------------------------------------------------
1047 void EventHandler::impl_getCopmonentListenerTypes_nothrow( Sequence< Type >& _out_rTypes ) const
1049 _out_rTypes.realloc( 0 );
1052 // we use a set to avoid duplicates
1053 TypeBag aListeners;
1055 Reference< XIntrospection > xIntrospection = Introspection::create( m_aContext.getUNOContext() );
1057 // --- model listeners
1058 lcl_addListenerTypesFor_throw(
1059 m_xComponent, xIntrospection, aListeners );
1061 // --- "secondary component" (usually: "control" listeners)
1063 Reference< XInterface > xSecondaryComponent( impl_getSecondaryComponentForEventInspection_throw() );
1064 lcl_addListenerTypesFor_throw( xSecondaryComponent, xIntrospection, aListeners );
1065 ::comphelper::disposeComponent( xSecondaryComponent );
1068 // now that they're disambiguated, copy these types into our member
1069 _out_rTypes.realloc( aListeners.size() );
1070 ::std::copy( aListeners.begin(), aListeners.end(), _out_rTypes.getArray() );
1072 catch( const Exception& )
1074 DBG_UNHANDLED_EXCEPTION();
1078 //--------------------------------------------------------------------
1079 void EventHandler::impl_getDialogElementScriptEvents_nothrow( Sequence < ScriptEventDescriptor >& _out_rEvents ) const
1081 _out_rEvents = Sequence < ScriptEventDescriptor >();
1084 Reference< XScriptEventsSupplier > xEventsSupplier( m_xComponent, UNO_QUERY_THROW );
1085 Reference< XNameContainer > xEvents( xEventsSupplier->getEvents(), UNO_QUERY_THROW );
1086 Sequence< OUString > aEventNames( xEvents->getElementNames() );
1088 sal_Int32 nEventCount = aEventNames.getLength();
1089 _out_rEvents.realloc( nEventCount );
1091 const OUString* pNames = aEventNames.getConstArray();
1092 ScriptEventDescriptor* pDescs = _out_rEvents.getArray();
1094 for( sal_Int32 i = 0 ; i < nEventCount ; ++i, ++pNames, ++pDescs )
1095 OSL_VERIFY( xEvents->getByName( *pNames ) >>= *pDescs );
1097 catch( const Exception& )
1099 DBG_UNHANDLED_EXCEPTION();
1103 //--------------------------------------------------------------------
1104 Reference< XInterface > EventHandler::impl_getSecondaryComponentForEventInspection_throw( ) const
1106 Reference< XInterface > xReturn;
1108 // if it's a form, create a form controller for the additional events
1109 Reference< XForm > xComponentAsForm( m_xComponent, UNO_QUERY );
1110 if ( xComponentAsForm.is() )
1112 Reference< XTabControllerModel > xComponentAsTCModel( m_xComponent, UNO_QUERY_THROW );
1113 Reference< XFormController > xController = FormController::create( m_aContext.getUNOContext() );
1114 xController->setModel( xComponentAsTCModel );
1116 xReturn = xController;
1118 else
1120 OUString sControlService;
1121 OSL_VERIFY( m_xComponent->getPropertyValue( PROPERTY_DEFAULTCONTROL ) >>= sControlService );
1123 xReturn = m_aContext.createComponent( sControlService );
1125 return xReturn;
1128 //--------------------------------------------------------------------
1129 const EventDescription& EventHandler::impl_getEventForName_throw( const OUString& _rPropertyName ) const
1131 EventMap::const_iterator pos = m_aEvents.find( _rPropertyName );
1132 if ( pos == m_aEvents.end() )
1133 throw UnknownPropertyException();
1134 return pos->second;
1137 //--------------------------------------------------------------------
1138 namespace
1140 static bool lcl_endsWith( const OUString& _rText, const OUString& _rCheck )
1142 sal_Int32 nTextLen = _rText.getLength();
1143 sal_Int32 nCheckLen = _rCheck.getLength();
1144 if ( nCheckLen > nTextLen )
1145 return false;
1147 return _rText.indexOf( _rCheck ) == ( nTextLen - nCheckLen );
1150 //--------------------------------------------------------------------
1151 void EventHandler::impl_setFormComponentScriptEvent_nothrow( const ScriptEventDescriptor& _rScriptEvent )
1155 OUString sScriptCode( _rScriptEvent.ScriptCode );
1156 OUString sScriptType( _rScriptEvent.ScriptType );
1157 bool bResetScript = sScriptCode.isEmpty();
1159 sal_Int32 nObjectIndex = impl_getComponentIndexInParent_throw();
1160 Reference< XChild > xChild( m_xComponent, UNO_QUERY_THROW );
1161 Reference< XEventAttacherManager > xEventManager( xChild->getParent(), UNO_QUERY_THROW );
1162 Sequence< ScriptEventDescriptor > aEvents( xEventManager->getScriptEvents( nObjectIndex ) );
1164 // is there already a registered script for this event?
1165 ScriptEventDescriptor* pEvent = aEvents.getArray();
1166 sal_Int32 eventCount = aEvents.getLength(), event = 0;
1167 for ( event = 0; event < eventCount; ++event, ++pEvent )
1169 if ( ( pEvent->EventMethod == _rScriptEvent.EventMethod )
1170 && ( lcl_endsWith( _rScriptEvent.ListenerType, pEvent->ListenerType ) )
1171 // (strange enough, the events we get from getScriptEvents are not fully qualified)
1174 // yes
1175 if ( !bResetScript )
1177 // set to something non-empty -> overwrite
1178 pEvent->ScriptCode = sScriptCode;
1179 pEvent->ScriptType = sScriptType;
1181 else
1183 // set to empty -> remove from sequence
1184 ::std::copy( pEvent + 1, aEvents.getArray() + eventCount, pEvent );
1185 aEvents.realloc( eventCount - 1 );
1186 --eventCount;
1188 break;
1191 if ( ( event >= eventCount ) && !bResetScript )
1193 // no, did not find it -> append
1194 aEvents.realloc( eventCount + 1 );
1195 aEvents[ eventCount ] = _rScriptEvent;
1198 xEventManager->revokeScriptEvents( nObjectIndex );
1199 xEventManager->registerScriptEvents( nObjectIndex, aEvents );
1201 PropertyHandlerHelper::setContextDocumentModified( m_aContext );
1203 catch( const Exception& )
1205 DBG_UNHANDLED_EXCEPTION();
1209 //--------------------------------------------------------------------
1210 void EventHandler::impl_setDialogElementScriptEvent_nothrow( const ScriptEventDescriptor& _rScriptEvent )
1214 OUString sScriptCode( _rScriptEvent.ScriptCode );
1215 bool bResetScript = sScriptCode.isEmpty();
1217 Reference< XScriptEventsSupplier > xEventsSupplier( m_xComponent, UNO_QUERY_THROW );
1218 Reference< XNameContainer > xEvents( xEventsSupplier->getEvents(), UNO_QUERY_THROW );
1220 OUStringBuffer aCompleteName;
1221 aCompleteName.append( _rScriptEvent.ListenerType );
1222 aCompleteName.appendAscii( "::" );
1223 aCompleteName.append( _rScriptEvent.EventMethod );
1224 OUString sCompleteName( aCompleteName.makeStringAndClear() );
1226 bool bExists = xEvents->hasByName( sCompleteName );
1228 if ( bResetScript )
1230 if ( bExists )
1231 xEvents->removeByName( sCompleteName );
1233 else
1235 Any aNewValue; aNewValue <<= _rScriptEvent;
1237 if ( bExists )
1238 xEvents->replaceByName( sCompleteName, aNewValue );
1239 else
1240 xEvents->insertByName( sCompleteName, aNewValue );
1243 catch( const Exception& )
1245 DBG_UNHANDLED_EXCEPTION();
1249 //--------------------------------------------------------------------
1250 bool EventHandler::impl_filterMethod_nothrow( const EventDescription& _rEvent ) const
1252 // some (control-triggered) events do not make sense for certain grid control columns. However,
1253 // our mechnism to retrieve control-triggered events does not know about this, so we do some
1254 // late filtering here.
1255 switch ( m_nGridColumnType )
1257 case FormComponentType::COMBOBOX:
1258 if ( UID_BRWEVT_ACTIONPERFORMED == _rEvent.sUniqueBrowseId )
1259 return false;
1260 break;
1261 case FormComponentType::LISTBOX:
1262 if ( ( UID_BRWEVT_CHANGED == _rEvent.sUniqueBrowseId )
1263 || ( UID_BRWEVT_ACTIONPERFORMED == _rEvent.sUniqueBrowseId )
1265 return false;
1266 break;
1269 return true;
1272 //........................................................................
1273 } // namespace pcr
1274 //........................................................................
1276 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */