1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 "pcrservices.hxx"
23 #include "propctrlr.hrc"
24 #include "formbrowsertools.hxx"
25 #include "formresid.hrc"
26 #include "formstrings.hxx"
27 #include "handlerhelper.hxx"
28 #include "modulepcr.hxx"
29 #include "pcrcommon.hxx"
30 #include "pcrstrings.hxx"
31 #include "propertycontrolextender.hxx"
33 #include <com/sun/star/awt/XTabControllerModel.hpp>
34 #include <com/sun/star/beans/PropertyAttribute.hpp>
35 #include <com/sun/star/beans/UnknownPropertyException.hpp>
36 #include <com/sun/star/beans/theIntrospection.hpp>
37 #include <com/sun/star/beans/XIntrospectionAccess.hpp>
38 #include <com/sun/star/container/NoSuchElementException.hpp>
39 #include <com/sun/star/container/XChild.hpp>
40 #include <com/sun/star/container/XIndexAccess.hpp>
41 #include <com/sun/star/container/XNameContainer.hpp>
42 #include <com/sun/star/container/XNameReplace.hpp>
43 #include <com/sun/star/form/FormComponentType.hpp>
44 #include <com/sun/star/form/XForm.hpp>
45 #include <com/sun/star/form/runtime/FormController.hpp>
46 #include <com/sun/star/inspection/PropertyControlType.hpp>
47 #include <com/sun/star/lang/NullPointerException.hpp>
48 #include <com/sun/star/script/XEventAttacherManager.hpp>
49 #include <com/sun/star/script/XScriptEventsSupplier.hpp>
50 #include <com/sun/star/util/XModifiable.hpp>
51 #include <com/sun/star/uri/UriReferenceFactory.hpp>
52 #include <com/sun/star/uri/XVndSunStarScriptUrlReference.hpp>
54 #include <comphelper/namedvaluecollection.hxx>
55 #include <comphelper/evtmethodhelper.hxx>
56 #include <comphelper/types.hxx>
57 #include <cppuhelper/implbase1.hxx>
58 #include <cppuhelper/supportsservice.hxx>
59 #include <rtl/ref.hxx>
60 #include <rtl/ustrbuf.hxx>
61 #include <sfx2/app.hxx>
62 #include <svl/eitem.hxx>
63 #include <svl/itemset.hxx>
64 #include <svx/svxdlg.hxx>
65 #include <svx/svxids.hrc>
66 #include <tools/diagnose_ex.h>
67 #include <vcl/msgbox.hxx>
71 #include <o3tl/compat_functional.hxx>
73 extern "C" void SAL_CALL
createRegistryInfo_EventHandler()
75 ::pcr::OAutoRegistration
< ::pcr::EventHandler
> aAutoRegistration
;
81 using ::com::sun::star::uno::Reference
;
82 using ::com::sun::star::uno::XComponentContext
;
83 using ::com::sun::star::beans::XPropertySet
;
84 using ::com::sun::star::uno::Any
;
85 using ::com::sun::star::uno::TypeClass_STRING
;
86 using ::com::sun::star::uno::Type
;
87 using ::com::sun::star::beans::theIntrospection
;
88 using ::com::sun::star::beans::XPropertyChangeListener
;
89 using ::com::sun::star::beans::Property
;
90 using ::com::sun::star::beans::PropertyState
;
91 using ::com::sun::star::beans::PropertyState_DIRECT_VALUE
;
92 using ::com::sun::star::uno::Sequence
;
93 using ::com::sun::star::script::ScriptEventDescriptor
;
94 using ::com::sun::star::script::XScriptEventsSupplier
;
95 using ::com::sun::star::lang::NullPointerException
;
96 using ::com::sun::star::uno::Exception
;
97 using ::com::sun::star::container::XChild
;
98 using ::com::sun::star::container::XIndexAccess
;
99 using ::com::sun::star::script::XEventAttacherManager
;
100 using ::com::sun::star::uno::UNO_QUERY
;
101 using ::com::sun::star::uno::UNO_QUERY_THROW
;
102 using ::com::sun::star::uno::XInterface
;
103 using ::com::sun::star::beans::XIntrospection
;
104 using ::com::sun::star::beans::XIntrospectionAccess
;
105 using ::com::sun::star::container::XNameContainer
;
106 using ::com::sun::star::awt::XTabControllerModel
;
107 using ::com::sun::star::form::XForm
;
108 using ::com::sun::star::form::runtime::FormController
;
109 using ::com::sun::star::form::runtime::XFormController
;
110 using ::com::sun::star::beans::UnknownPropertyException
;
111 using ::com::sun::star::uno::makeAny
;
112 using ::com::sun::star::container::NoSuchElementException
;
113 using ::com::sun::star::beans::XPropertySetInfo
;
114 using ::com::sun::star::container::XNameReplace
;
115 using ::com::sun::star::lang::IllegalArgumentException
;
116 using ::com::sun::star::lang::WrappedTargetException
;
117 using ::com::sun::star::uno::RuntimeException
;
118 using ::com::sun::star::beans::PropertyValue
;
119 using ::com::sun::star::inspection::LineDescriptor
;
120 using ::com::sun::star::inspection::XPropertyControlFactory
;
121 using ::com::sun::star::inspection::InteractiveSelectionResult
;
122 using ::com::sun::star::inspection::InteractiveSelectionResult_Cancelled
;
123 using ::com::sun::star::inspection::InteractiveSelectionResult_Success
;
124 using ::com::sun::star::inspection::XObjectInspectorUI
;
125 using ::com::sun::star::util::XModifiable
;
126 using ::com::sun::star::beans::PropertyChangeEvent
;
127 using ::com::sun::star::frame::XFrame
;
128 using ::com::sun::star::frame::XModel
;
129 using ::com::sun::star::frame::XController
;
130 using ::com::sun::star::uno::UNO_SET_THROW
;
131 using com::sun::star::uri::UriReferenceFactory
;
132 using com::sun::star::uri::XUriReferenceFactory
;
133 using com::sun::star::uri::XVndSunStarScriptUrlReference
;
134 using ::com::sun::star::lang::XEventListener
;
136 namespace PropertyControlType
= ::com::sun::star::inspection::PropertyControlType
;
137 namespace PropertyAttribute
= ::com::sun::star::beans::PropertyAttribute
;
138 namespace FormComponentType
= ::com::sun::star::form::FormComponentType
;
140 EventDescription::EventDescription( EventId _nId
, const sal_Char
* _pListenerNamespaceAscii
, const sal_Char
* _pListenerClassAsciiName
,
141 const sal_Char
* _pListenerMethodAsciiName
, sal_uInt16 _nDisplayNameResId
, const OString
& _sHelpId
, const OString
& _sUniqueBrowseId
)
142 :sDisplayName(PcrRes( _nDisplayNameResId
).toString())
143 ,sListenerMethodName( OUString::createFromAscii( _pListenerMethodAsciiName
) )
145 ,sUniqueBrowseId( _sUniqueBrowseId
)
148 OUStringBuffer aQualifiedListenerClass
;
149 aQualifiedListenerClass
.appendAscii( "com.sun.star." );
150 aQualifiedListenerClass
.appendAscii( _pListenerNamespaceAscii
);
151 aQualifiedListenerClass
.appendAscii( "." );
152 aQualifiedListenerClass
.appendAscii( _pListenerClassAsciiName
);
153 sListenerClassName
= aQualifiedListenerClass
.makeStringAndClear();
158 #define DESCRIBE_EVENT( asciinamespace, asciilistener, asciimethod, id_postfix ) \
159 s_aKnownEvents.insert( EventMap::value_type( \
161 EventDescription( ++nEventId, asciinamespace, asciilistener, asciimethod, RID_STR_EVT_##id_postfix, HID_EVT_##id_postfix, UID_BRWEVT_##id_postfix ) ) )
163 bool lcl_getEventDescriptionForMethod( const OUString
& _rMethodName
, EventDescription
& _out_rDescription
)
165 static EventMap s_aKnownEvents
;
166 if ( s_aKnownEvents
.empty() )
168 ::osl::MutexGuard
aGuard( ::osl::Mutex::getGlobalMutex() );
169 if ( s_aKnownEvents
.empty() )
171 static sal_Int32 nEventId
= 0;
173 DESCRIBE_EVENT( "form", "XApproveActionListener", "approveAction", APPROVEACTIONPERFORMED
);
174 DESCRIBE_EVENT( "awt", "XActionListener", "actionPerformed", ACTIONPERFORMED
);
175 DESCRIBE_EVENT( "form", "XChangeListener", "changed", CHANGED
);
176 DESCRIBE_EVENT( "awt", "XTextListener", "textChanged", TEXTCHANGED
);
177 DESCRIBE_EVENT( "awt", "XItemListener", "itemStateChanged", ITEMSTATECHANGED
);
178 DESCRIBE_EVENT( "awt", "XFocusListener", "focusGained", FOCUSGAINED
);
179 DESCRIBE_EVENT( "awt", "XFocusListener", "focusLost", FOCUSLOST
);
180 DESCRIBE_EVENT( "awt", "XKeyListener", "keyPressed", KEYTYPED
);
181 DESCRIBE_EVENT( "awt", "XKeyListener", "keyReleased", KEYUP
);
182 DESCRIBE_EVENT( "awt", "XMouseListener", "mouseEntered", MOUSEENTERED
);
183 DESCRIBE_EVENT( "awt", "XMouseMotionListener", "mouseDragged", MOUSEDRAGGED
);
184 DESCRIBE_EVENT( "awt", "XMouseMotionListener", "mouseMoved", MOUSEMOVED
);
185 DESCRIBE_EVENT( "awt", "XMouseListener", "mousePressed", MOUSEPRESSED
);
186 DESCRIBE_EVENT( "awt", "XMouseListener", "mouseReleased", MOUSERELEASED
);
187 DESCRIBE_EVENT( "awt", "XMouseListener", "mouseExited", MOUSEEXITED
);
188 DESCRIBE_EVENT( "form", "XResetListener", "approveReset", APPROVERESETTED
);
189 DESCRIBE_EVENT( "form", "XResetListener", "resetted", RESETTED
);
190 DESCRIBE_EVENT( "form", "XSubmitListener", "approveSubmit", SUBMITTED
);
191 DESCRIBE_EVENT( "form", "XUpdateListener", "approveUpdate", BEFOREUPDATE
);
192 DESCRIBE_EVENT( "form", "XUpdateListener", "updated", AFTERUPDATE
);
193 DESCRIBE_EVENT( "form", "XLoadListener", "loaded", LOADED
);
194 DESCRIBE_EVENT( "form", "XLoadListener", "reloading", RELOADING
);
195 DESCRIBE_EVENT( "form", "XLoadListener", "reloaded", RELOADED
);
196 DESCRIBE_EVENT( "form", "XLoadListener", "unloading", UNLOADING
);
197 DESCRIBE_EVENT( "form", "XLoadListener", "unloaded", UNLOADED
);
198 DESCRIBE_EVENT( "form", "XConfirmDeleteListener", "confirmDelete", CONFIRMDELETE
);
199 DESCRIBE_EVENT( "sdb", "XRowSetApproveListener", "approveRowChange", APPROVEROWCHANGE
);
200 DESCRIBE_EVENT( "sdbc", "XRowSetListener", "rowChanged", ROWCHANGE
);
201 DESCRIBE_EVENT( "sdb", "XRowSetApproveListener", "approveCursorMove", POSITIONING
);
202 DESCRIBE_EVENT( "sdbc", "XRowSetListener", "cursorMoved", POSITIONED
);
203 DESCRIBE_EVENT( "form", "XDatabaseParameterListener", "approveParameter", APPROVEPARAMETER
);
204 DESCRIBE_EVENT( "sdb", "XSQLErrorListener", "errorOccured", ERROROCCURRED
);
205 DESCRIBE_EVENT( "awt", "XAdjustmentListener", "adjustmentValueChanged", ADJUSTMENTVALUECHANGED
);
209 EventMap::const_iterator pos
= s_aKnownEvents
.find( _rMethodName
);
210 if ( pos
== s_aKnownEvents
.end() )
213 _out_rDescription
= pos
->second
;
217 OUString
lcl_getEventPropertyName( const OUString
& _rListenerClassName
, const OUString
& _rMethodName
)
219 OUStringBuffer aPropertyName
;
220 aPropertyName
.append( _rListenerClassName
);
221 aPropertyName
.append( ';' );
222 aPropertyName
.append( _rMethodName
.getStr() );
223 return aPropertyName
.makeStringAndClear();
226 ScriptEventDescriptor
lcl_getAssignedScriptEvent( const EventDescription
& _rEvent
, const Sequence
< ScriptEventDescriptor
>& _rAllAssignedMacros
)
228 ScriptEventDescriptor aScriptEvent
;
229 // for the case there is actually no event assigned, initialize at least ListenerType and MethodName,
230 // so this ScriptEventDescriptor properly describes the given event
231 aScriptEvent
.ListenerType
= _rEvent
.sListenerClassName
;
232 aScriptEvent
.EventMethod
= _rEvent
.sListenerMethodName
;
234 const ScriptEventDescriptor
* pAssignedEvent
= _rAllAssignedMacros
.getConstArray();
235 sal_Int32
assignedEventCount( _rAllAssignedMacros
.getLength() );
236 for ( sal_Int32 assignedEvent
= 0; assignedEvent
< assignedEventCount
; ++assignedEvent
, ++pAssignedEvent
)
238 if ( ( pAssignedEvent
->ListenerType
!= _rEvent
.sListenerClassName
)
239 || ( pAssignedEvent
->EventMethod
!= _rEvent
.sListenerMethodName
)
243 if ( ( pAssignedEvent
->ScriptCode
.isEmpty() )
244 || ( pAssignedEvent
->ScriptType
.isEmpty() )
247 OSL_FAIL( "lcl_getAssignedScriptEvent: me thinks this should not happen!" );
251 aScriptEvent
= *pAssignedEvent
;
253 if ( aScriptEvent
.ScriptType
!= "StarBasic" )
256 // this is an old-style macro specification:
257 // [document|application]:Library.Module.Function
258 // we need to translate this to the new-style macro specification
259 // vnd.sun.star.script:Library.Module.Function?language=Basic&location=[document|application]
261 sal_Int32 nPrefixLen
= aScriptEvent
.ScriptCode
.indexOf( ':' );
262 OSL_ENSURE( nPrefixLen
> 0, "lcl_getAssignedScriptEvent: illegal location!" );
263 OUString sLocation
= aScriptEvent
.ScriptCode
.copy( 0, nPrefixLen
);
264 OUString sMacroPath
= aScriptEvent
.ScriptCode
.copy( nPrefixLen
+ 1 );
266 OUStringBuffer aNewStyleSpec
;
267 aNewStyleSpec
.appendAscii( "vnd.sun.star.script:" );
268 aNewStyleSpec
.append ( sMacroPath
);
269 aNewStyleSpec
.appendAscii( "?language=Basic&location=" );
270 aNewStyleSpec
.append ( sLocation
);
272 aScriptEvent
.ScriptCode
= aNewStyleSpec
.makeStringAndClear();
274 // also, this new-style spec requires the script code to be "Script" instead of "StarBasic"
275 aScriptEvent
.ScriptType
= "Script";
280 OUString
lcl_getQualifiedKnownListenerName( const ScriptEventDescriptor
& _rFormComponentEventDescriptor
)
282 EventDescription aKnownEvent
;
283 if ( lcl_getEventDescriptionForMethod( _rFormComponentEventDescriptor
.EventMethod
, aKnownEvent
) )
284 return aKnownEvent
.sListenerClassName
;
285 OSL_FAIL( "lcl_getQualifiedKnownListenerName: unknown method name!" );
286 // somebody assigned an script to a form component event which we don't know
287 // Speaking strictly, this is not really an error - it is possible to do
288 // this programmatically -, but it should rarely happen, since it's not possible
290 return _rFormComponentEventDescriptor
.ListenerType
;
293 typedef ::std::set
< Type
, TypeLessByName
> TypeBag
;
295 void lcl_addListenerTypesFor_throw( const Reference
< XInterface
>& _rxComponent
,
296 const Reference
< XIntrospection
>& _rxIntrospection
, TypeBag
& _out_rTypes
)
298 if ( !_rxComponent
.is() )
300 OSL_PRECOND( _rxIntrospection
.is(), "lcl_addListenerTypesFor_throw: this will crash!" );
302 Reference
< XIntrospectionAccess
> xIntrospectionAccess(
303 _rxIntrospection
->inspect( makeAny( _rxComponent
) ), UNO_QUERY_THROW
);
305 Sequence
< Type
> aListeners( xIntrospectionAccess
->getSupportedListeners() );
307 ::std::copy( aListeners
.getConstArray(), aListeners
.getConstArray() + aListeners
.getLength(),
308 ::std::insert_iterator
< TypeBag
>( _out_rTypes
, _out_rTypes
.begin() ) );
311 bool operator ==( const ScriptEventDescriptor
& _lhs
, const ScriptEventDescriptor
& _rhs
)
313 return ( ( _lhs
.ListenerType
== _rhs
.ListenerType
)
314 && ( _lhs
.EventMethod
== _rhs
.EventMethod
)
315 && ( _lhs
.AddListenerParam
== _rhs
.AddListenerParam
)
316 && ( _lhs
.ScriptType
== _rhs
.ScriptType
)
317 && ( _lhs
.ScriptCode
== _rhs
.ScriptCode
)
322 typedef ::cppu::WeakImplHelper1
< ::com::sun::star::container::XNameReplace
324 /* An UNO component holding assigned event descriptions, for use with a SvxMacroAssignDlg */
325 class EventHolder
: public EventHolder_Base
328 typedef std::unordered_map
< OUString
, ScriptEventDescriptor
, OUStringHash
> EventMap
;
329 typedef ::std::map
< EventId
, EventMap::iterator
> EventMapIndexAccess
;
331 EventMap m_aEventNameAccess
;
332 EventMapIndexAccess m_aEventIndexAccess
;
337 void addEvent( EventId _nId
, const OUString
& _rEventName
, const ScriptEventDescriptor
& _rScriptEvent
);
339 /** effectively the same as getByName, but instead of converting the ScriptEventDescriptor to the weird
340 format used by the macro assignment dialog, it is returned directly
342 ScriptEventDescriptor
getNormalizedDescriptorByName( const OUString
& _rEventName
) const;
345 virtual void SAL_CALL
replaceByName( const OUString
& _rName
, const Any
& aElement
) throw (IllegalArgumentException
, NoSuchElementException
, WrappedTargetException
, RuntimeException
, std::exception
) SAL_OVERRIDE
;
346 virtual Any SAL_CALL
getByName( const OUString
& _rName
) throw (NoSuchElementException
, WrappedTargetException
, RuntimeException
, std::exception
) SAL_OVERRIDE
;
347 virtual Sequence
< OUString
> SAL_CALL
getElementNames( ) throw (RuntimeException
, std::exception
) SAL_OVERRIDE
;
348 virtual sal_Bool SAL_CALL
hasByName( const OUString
& _rName
) throw (RuntimeException
, std::exception
) SAL_OVERRIDE
;
349 virtual Type SAL_CALL
getElementType( ) throw (RuntimeException
, std::exception
) SAL_OVERRIDE
;
350 virtual sal_Bool SAL_CALL
hasElements( ) throw (RuntimeException
, std::exception
) SAL_OVERRIDE
;
353 virtual ~EventHolder( );
356 ScriptEventDescriptor
impl_getDescriptor_throw( const OUString
& _rEventName
) const;
360 EventHolder::EventHolder()
364 EventHolder::~EventHolder()
366 m_aEventNameAccess
.clear();
367 m_aEventIndexAccess
.clear();
370 void EventHolder::addEvent( EventId _nId
, const OUString
& _rEventName
, const ScriptEventDescriptor
& _rScriptEvent
)
372 ::std::pair
< EventMap::iterator
, bool > insertionResult
=
373 m_aEventNameAccess
.insert( EventMap::value_type( _rEventName
, _rScriptEvent
) );
374 OSL_ENSURE( insertionResult
.second
, "EventHolder::addEvent: there already was a MacroURL for this event!" );
375 m_aEventIndexAccess
[ _nId
] = insertionResult
.first
;
378 ScriptEventDescriptor
EventHolder::getNormalizedDescriptorByName( const OUString
& _rEventName
) const
380 return impl_getDescriptor_throw( _rEventName
);
383 ScriptEventDescriptor
EventHolder::impl_getDescriptor_throw( const OUString
& _rEventName
) const
385 EventMap::const_iterator pos
= m_aEventNameAccess
.find( _rEventName
);
386 if ( pos
== m_aEventNameAccess
.end() )
387 throw NoSuchElementException( OUString(), *const_cast< EventHolder
* >( this ) );
391 void SAL_CALL
EventHolder::replaceByName( const OUString
& _rName
, const Any
& _rElement
) throw (IllegalArgumentException
, NoSuchElementException
, WrappedTargetException
, RuntimeException
, std::exception
)
393 EventMap::iterator pos
= m_aEventNameAccess
.find( _rName
);
394 if ( pos
== m_aEventNameAccess
.end() )
395 throw NoSuchElementException( OUString(), *this );
397 Sequence
< PropertyValue
> aScriptDescriptor
;
398 OSL_VERIFY( _rElement
>>= aScriptDescriptor
);
400 ::comphelper::NamedValueCollection
aExtractor( aScriptDescriptor
);
402 pos
->second
.ScriptType
= aExtractor
.getOrDefault( "EventType", OUString() );
403 pos
->second
.ScriptCode
= aExtractor
.getOrDefault( "Script", OUString() );
406 Any SAL_CALL
EventHolder::getByName( const OUString
& _rName
) throw (NoSuchElementException
, WrappedTargetException
, RuntimeException
, std::exception
)
408 ScriptEventDescriptor
aDescriptor( impl_getDescriptor_throw( _rName
) );
410 Sequence
< PropertyValue
> aScriptDescriptor( 2 );
411 aScriptDescriptor
[0].Name
= "EventType";
412 aScriptDescriptor
[0].Value
<<= aDescriptor
.ScriptType
;
413 aScriptDescriptor
[1].Name
= "Script";
414 aScriptDescriptor
[1].Value
<<= aDescriptor
.ScriptCode
;
416 return makeAny( aScriptDescriptor
);
419 Sequence
< OUString
> SAL_CALL
EventHolder::getElementNames( ) throw (RuntimeException
, std::exception
)
421 Sequence
< OUString
> aReturn( m_aEventIndexAccess
.size() );
422 OUString
* pReturn
= aReturn
.getArray();
424 // SvxMacroAssignDlg has a weird API: It expects a XNameReplace, means a container whose
425 // main access method is by name. In its UI, it shows the possible events in exactly the
426 // order in which XNameAccess::getElementNames returns them.
427 // However, SvxMacroAssignDlg *also* takes an index for the initial selection, which is
428 // relative to the sequence returned by XNameAccess::getElementNames.
429 // This is IMO weird, since it mixes index access with name access, which decreases efficiency
430 // of the implementation.
431 // Well, it means we're forced to return the events in getElementNames in exactly the same as they
432 // appear in the property browser UI.
433 for ( EventMapIndexAccess::const_iterator loop
= m_aEventIndexAccess
.begin();
434 loop
!= m_aEventIndexAccess
.end();
437 *pReturn
= loop
->second
->first
;
441 sal_Bool SAL_CALL
EventHolder::hasByName( const OUString
& _rName
) throw (RuntimeException
, std::exception
)
443 EventMap::const_iterator pos
= m_aEventNameAccess
.find( _rName
);
444 return pos
!= m_aEventNameAccess
.end();
447 Type SAL_CALL
EventHolder::getElementType( ) throw (RuntimeException
, std::exception
)
449 return cppu::UnoType
<Sequence
< PropertyValue
>>::get();
452 sal_Bool SAL_CALL
EventHolder::hasElements( ) throw (RuntimeException
, std::exception
)
454 return !m_aEventNameAccess
.empty();
458 EventHandler::EventHandler( const Reference
< XComponentContext
>& _rxContext
)
459 :EventHandler_Base( m_aMutex
)
460 ,m_xContext( _rxContext
)
461 ,m_aPropertyListeners( m_aMutex
)
462 ,m_bEventsMapInitialized( false )
463 ,m_bIsDialogElement( false )
464 ,m_nGridColumnType( -1 )
468 EventHandler::~EventHandler()
472 OUString SAL_CALL
EventHandler::getImplementationName( ) throw (RuntimeException
, std::exception
)
474 return getImplementationName_static();
477 sal_Bool SAL_CALL
EventHandler::supportsService( const OUString
& ServiceName
) throw (RuntimeException
, std::exception
)
479 return cppu::supportsService(this, ServiceName
);
482 Sequence
< OUString
> SAL_CALL
EventHandler::getSupportedServiceNames( ) throw (RuntimeException
, std::exception
)
484 return getSupportedServiceNames_static();
487 OUString SAL_CALL
EventHandler::getImplementationName_static( ) throw (RuntimeException
)
489 return OUString( "com.sun.star.comp.extensions.EventHandler" );
492 Sequence
< OUString
> SAL_CALL
EventHandler::getSupportedServiceNames_static( ) throw (RuntimeException
)
494 Sequence
< OUString
> aSupported( 1 );
495 aSupported
[0] = "com.sun.star.form.inspection.EventHandler";
499 Reference
< XInterface
> SAL_CALL
EventHandler::Create( const Reference
< XComponentContext
>& _rxContext
)
501 return *( new EventHandler( _rxContext
) );
504 void SAL_CALL
EventHandler::inspect( const Reference
< XInterface
>& _rxIntrospectee
) throw (RuntimeException
, NullPointerException
, std::exception
)
506 ::osl::MutexGuard
aGuard( m_aMutex
);
508 if ( !_rxIntrospectee
.is() )
509 throw NullPointerException();
511 m_xComponent
= Reference
< XPropertySet
>( _rxIntrospectee
, UNO_QUERY_THROW
);
513 m_bEventsMapInitialized
= false;
515 m_aEvents
.swap( aEmpty
);
517 m_bIsDialogElement
= false;
518 m_nGridColumnType
= -1;
521 Reference
< XPropertySetInfo
> xPSI( m_xComponent
->getPropertySetInfo() );
522 m_bIsDialogElement
= xPSI
.is()
523 && xPSI
->hasPropertyByName( PROPERTY_WIDTH
)
524 && xPSI
->hasPropertyByName( PROPERTY_HEIGHT
)
525 && xPSI
->hasPropertyByName( PROPERTY_POSITIONX
)
526 && xPSI
->hasPropertyByName( PROPERTY_POSITIONY
);
528 Reference
< XChild
> xAsChild( _rxIntrospectee
, UNO_QUERY
);
529 if ( xAsChild
.is() && !Reference
< XForm
>( _rxIntrospectee
, UNO_QUERY
).is() )
531 if ( FormComponentType::GRIDCONTROL
== classifyComponent( xAsChild
->getParent() ) )
533 m_nGridColumnType
= classifyComponent( _rxIntrospectee
);
537 catch( const Exception
& )
539 DBG_UNHANDLED_EXCEPTION();
543 Any SAL_CALL
EventHandler::getPropertyValue( const OUString
& _rPropertyName
) throw (UnknownPropertyException
, RuntimeException
, std::exception
)
545 ::osl::MutexGuard
aGuard( m_aMutex
);
547 const EventDescription
& rEvent
= impl_getEventForName_throw( _rPropertyName
);
549 Sequence
< ScriptEventDescriptor
> aEvents
;
550 impl_getComponentScriptEvents_nothrow( aEvents
);
552 sal_Int32 nEventCount
= aEvents
.getLength();
553 const ScriptEventDescriptor
* pEvents
= aEvents
.getConstArray();
555 ScriptEventDescriptor aPropertyValue
;
556 for ( sal_Int32 event
= 0; event
< nEventCount
; ++event
, ++pEvents
)
558 if ( rEvent
.sListenerClassName
== pEvents
->ListenerType
559 && rEvent
.sListenerMethodName
== pEvents
->EventMethod
562 aPropertyValue
= *pEvents
;
567 return makeAny( aPropertyValue
);
570 void SAL_CALL
EventHandler::setPropertyValue( const OUString
& _rPropertyName
, const Any
& _rValue
) throw (UnknownPropertyException
, RuntimeException
, std::exception
)
572 ::osl::MutexGuard
aGuard( m_aMutex
);
574 const EventDescription
& rEvent
= impl_getEventForName_throw( _rPropertyName
);
576 ScriptEventDescriptor aNewScriptEvent
;
577 OSL_VERIFY( _rValue
>>= aNewScriptEvent
);
579 ScriptEventDescriptor aOldScriptEvent
;
580 OSL_VERIFY( getPropertyValue( _rPropertyName
) >>= aOldScriptEvent
);
581 if ( aOldScriptEvent
== aNewScriptEvent
)
584 if ( m_bIsDialogElement
)
585 impl_setDialogElementScriptEvent_nothrow( aNewScriptEvent
);
587 impl_setFormComponentScriptEvent_nothrow( aNewScriptEvent
);
589 PropertyHandlerHelper::setContextDocumentModified( m_xContext
);
591 PropertyChangeEvent aEvent
;
592 aEvent
.Source
= m_xComponent
;
593 aEvent
.PropertyHandle
= rEvent
.nId
;
594 aEvent
.PropertyName
= _rPropertyName
;
595 aEvent
.OldValue
<<= aOldScriptEvent
;
596 aEvent
.NewValue
<<= aNewScriptEvent
;
597 m_aPropertyListeners
.notify( aEvent
, &XPropertyChangeListener::propertyChange
);
600 Any SAL_CALL
EventHandler::convertToPropertyValue( const OUString
& _rPropertyName
, const Any
& _rControlValue
) throw (UnknownPropertyException
, RuntimeException
, std::exception
)
602 ::osl::MutexGuard
aGuard( m_aMutex
);
604 OUString sNewScriptCode
;
605 OSL_VERIFY( _rControlValue
>>= sNewScriptCode
);
607 Sequence
< ScriptEventDescriptor
> aAllAssignedEvents
;
608 impl_getComponentScriptEvents_nothrow( aAllAssignedEvents
);
610 const EventDescription
& rEvent
= impl_getEventForName_throw( _rPropertyName
);
611 ScriptEventDescriptor aAssignedScript
= lcl_getAssignedScriptEvent( rEvent
, aAllAssignedEvents
);
613 OSL_ENSURE( sNewScriptCode
.isEmpty(), "EventHandler::convertToPropertyValue: cannot convert a non-empty display name!" );
614 // Usually, there is no possibility for the user to change the content of an event binding directly in the
615 // input field, this instead is done with the macro assignment dialog.
616 // The only exception is the user pressing "DEL" while the control has the focus, in this case, we reset the
617 // control content to an empty string. So this is the only scenario where this method is allowed to be called.
619 // Striclty, we would be able to convert the display value to a property value,
620 // using the "name (location, language)" format we used in convertToControlValue. However,
621 // there is no need for this code ...
623 aAssignedScript
.ScriptCode
= sNewScriptCode
;
624 return makeAny( aAssignedScript
);
627 Any SAL_CALL
EventHandler::convertToControlValue( const OUString
& /*_rPropertyName*/, const Any
& _rPropertyValue
, const Type
& _rControlValueType
) throw (UnknownPropertyException
, RuntimeException
, std::exception
)
629 ::osl::MutexGuard
aGuard( m_aMutex
);
631 ScriptEventDescriptor aScriptEvent
;
632 OSL_VERIFY( _rPropertyValue
>>= aScriptEvent
);
634 OSL_ENSURE( _rControlValueType
.getTypeClass() == TypeClass_STRING
,
635 "EventHandler::convertToControlValue: unexpected ControlValue type class!" );
636 (void)_rControlValueType
;
638 OUString
sScript( aScriptEvent
.ScriptCode
);
639 if ( !sScript
.isEmpty() )
641 // format is: "name (location, language)"
645 Reference
< XUriReferenceFactory
> xUriRefFac
= UriReferenceFactory::create( m_xContext
);
646 Reference
< XVndSunStarScriptUrlReference
> xScriptUri( xUriRefFac
->parse( sScript
), UNO_QUERY_THROW
);
648 OUStringBuffer aComposeBuffer
;
651 aComposeBuffer
.append( xScriptUri
->getName() );
654 const OUString
sLocationParamName( "location" );
655 const OUString sLocation
= xScriptUri
->getParameter( sLocationParamName
);
656 const OUString
sLangParamName( "language" );
657 const OUString sLanguage
= xScriptUri
->getParameter( sLangParamName
);
659 if ( !(sLocation
.isEmpty() && sLanguage
.isEmpty()) )
661 aComposeBuffer
.appendAscii( " (" );
664 OSL_ENSURE( !sLocation
.isEmpty(), "EventHandler::convertToControlValue: unexpected: no location!" );
665 if ( !sLocation
.isEmpty() )
667 aComposeBuffer
.append( sLocation
);
668 aComposeBuffer
.appendAscii( ", " );
672 if ( !sLanguage
.isEmpty() )
674 aComposeBuffer
.append( sLanguage
);
677 aComposeBuffer
.append( ')' );
680 sScript
= aComposeBuffer
.makeStringAndClear();
682 catch( const Exception
& )
684 DBG_UNHANDLED_EXCEPTION();
688 return makeAny( sScript
);
691 PropertyState SAL_CALL
EventHandler::getPropertyState( const OUString
& /*_rPropertyName*/ ) throw (UnknownPropertyException
, RuntimeException
, std::exception
)
693 return PropertyState_DIRECT_VALUE
;
696 void SAL_CALL
EventHandler::addPropertyChangeListener( const Reference
< XPropertyChangeListener
>& _rxListener
) throw (NullPointerException
, RuntimeException
, std::exception
)
698 ::osl::MutexGuard
aGuard( m_aMutex
);
699 if ( !_rxListener
.is() )
700 throw NullPointerException();
701 m_aPropertyListeners
.addListener( _rxListener
);
704 void SAL_CALL
EventHandler::removePropertyChangeListener( const Reference
< XPropertyChangeListener
>& _rxListener
) throw (RuntimeException
, std::exception
)
706 ::osl::MutexGuard
aGuard( m_aMutex
);
707 m_aPropertyListeners
.removeListener( _rxListener
);
710 Sequence
< Property
> SAL_CALL
EventHandler::getSupportedProperties() throw (RuntimeException
, std::exception
)
712 ::osl::MutexGuard
aGuard( m_aMutex
);
713 if ( !m_bEventsMapInitialized
)
715 const_cast< EventHandler
* >( this )->m_bEventsMapInitialized
= true;
718 Sequence
< Type
> aListeners
;
719 impl_getCopmonentListenerTypes_nothrow( aListeners
);
720 sal_Int32 listenerCount
= aListeners
.getLength();
722 Property aCurrentProperty
;
723 OUString sListenerClassName
;
725 // loop through all listeners and all methods, and see which we can present at the UI
726 const Type
* pListeners
= aListeners
.getConstArray();
727 for ( sal_Int32 listener
= 0; listener
< listenerCount
; ++listener
, ++pListeners
)
729 aCurrentProperty
= Property();
731 // the programmatic name of the listener, to be used as "property" name
732 sListenerClassName
= pListeners
->getTypeName();
733 OSL_ENSURE( !sListenerClassName
.isEmpty(), "EventHandler::getSupportedProperties: strange - no listener name ..." );
734 if ( sListenerClassName
.isEmpty() )
737 // loop through all methods
738 Sequence
< OUString
> aMethods( comphelper::getEventMethodsForType( *pListeners
) );
740 const OUString
* pMethods
= aMethods
.getConstArray();
741 sal_uInt32 methodCount
= aMethods
.getLength();
743 for (sal_uInt32 method
= 0 ; method
< methodCount
; ++method
, ++pMethods
)
745 EventDescription aEvent
;
746 if ( !lcl_getEventDescriptionForMethod( *pMethods
, aEvent
) )
749 if ( !impl_filterMethod_nothrow( aEvent
) )
752 const_cast< EventHandler
* >( this )->m_aEvents
.insert( EventMap::value_type(
753 lcl_getEventPropertyName( sListenerClassName
, *pMethods
), aEvent
) );
758 catch( const Exception
& )
760 DBG_UNHANDLED_EXCEPTION();
764 // sort them by ID - this is the relative ordering in the UI
765 ::std::map
< EventId
, Property
> aOrderedProperties
;
766 for ( EventMap::const_iterator loop
= m_aEvents
.begin();
767 loop
!= m_aEvents
.end();
771 aOrderedProperties
[ loop
->second
.nId
] = Property(
772 loop
->first
, loop
->second
.nId
,
773 ::cppu::UnoType
<OUString
>::get(),
774 PropertyAttribute::BOUND
);
777 StlSyntaxSequence
< Property
> aReturn( aOrderedProperties
.size() );
778 ::std::transform( aOrderedProperties
.begin(), aOrderedProperties
.end(), aReturn
.begin(),
779 ::o3tl::select2nd
< ::std::map
< EventId
, Property
>::value_type
>() );
783 Sequence
< OUString
> SAL_CALL
EventHandler::getSupersededProperties( ) throw (RuntimeException
, std::exception
)
786 return Sequence
< OUString
>( );
789 Sequence
< OUString
> SAL_CALL
EventHandler::getActuatingProperties( ) throw (RuntimeException
, std::exception
)
792 return Sequence
< OUString
>( );
795 LineDescriptor SAL_CALL
EventHandler::describePropertyLine( const OUString
& _rPropertyName
,
796 const Reference
< XPropertyControlFactory
>& _rxControlFactory
)
797 throw (UnknownPropertyException
, NullPointerException
, RuntimeException
, std::exception
)
799 if ( !_rxControlFactory
.is() )
800 throw NullPointerException();
802 ::osl::MutexGuard
aGuard( m_aMutex
);
804 LineDescriptor aDescriptor
;
806 aDescriptor
.Control
= _rxControlFactory
->createPropertyControl( PropertyControlType::TextField
, sal_True
);
807 Reference
< XEventListener
> xControlExtender
= new PropertyControlExtender( aDescriptor
.Control
);
809 const EventDescription
& rEvent
= impl_getEventForName_throw( _rPropertyName
);
810 aDescriptor
.DisplayName
= rEvent
.sDisplayName
;
811 aDescriptor
.HelpURL
= HelpIdUrl::getHelpURL( rEvent
.sHelpId
);
812 aDescriptor
.PrimaryButtonId
= OStringToOUString(rEvent
.sUniqueBrowseId
, RTL_TEXTENCODING_UTF8
);
813 aDescriptor
.HasPrimaryButton
= sal_True
;
814 aDescriptor
.Category
= "Events";
818 sal_Bool SAL_CALL
EventHandler::isComposable( const OUString
& /*_rPropertyName*/ ) throw (UnknownPropertyException
, RuntimeException
, std::exception
)
823 InteractiveSelectionResult SAL_CALL
EventHandler::onInteractivePropertySelection( const OUString
& _rPropertyName
, sal_Bool
/*_bPrimary*/, Any
& /*_rData*/, const Reference
< XObjectInspectorUI
>& _rxInspectorUI
) throw (UnknownPropertyException
, NullPointerException
, RuntimeException
, std::exception
)
825 if ( !_rxInspectorUI
.is() )
826 throw NullPointerException();
828 ::osl::MutexGuard
aGuard( m_aMutex
);
829 const EventDescription
& rForEvent
= impl_getEventForName_throw( _rPropertyName
);
831 Sequence
< ScriptEventDescriptor
> aAllAssignedEvents
;
832 impl_getComponentScriptEvents_nothrow( aAllAssignedEvents
);
834 // SvxMacroAssignDlg-compatible structure holding all event/assignments
835 ::rtl::Reference
< EventHolder
> pEventHolder( new EventHolder
);
837 for ( EventMap::const_iterator event
= m_aEvents
.begin();
838 event
!= m_aEvents
.end();
842 // the script which is assigned to the current event (if any)
843 ScriptEventDescriptor aAssignedScript
= lcl_getAssignedScriptEvent( event
->second
, aAllAssignedEvents
);
844 pEventHolder
->addEvent( event
->second
.nId
, event
->second
.sListenerMethodName
, aAssignedScript
);
847 // the initial selection in the dialog
848 Sequence
< OUString
> aNames( pEventHolder
->getElementNames() );
849 const OUString
* pChosenEvent
= ::std::find( aNames
.getConstArray(), aNames
.getConstArray() + aNames
.getLength(), rForEvent
.sListenerMethodName
);
850 sal_uInt16 nInitialSelection
= (sal_uInt16
)( pChosenEvent
- aNames
.getConstArray() );
853 SvxAbstractDialogFactory
* pFactory
= SvxAbstractDialogFactory::Create();
855 return InteractiveSelectionResult_Cancelled
;
857 ::std::unique_ptr
< VclAbstractDialog
> pDialog( pFactory
->CreateSvxMacroAssignDlg(
858 PropertyHandlerHelper::getDialogParentWindow( m_xContext
),
859 impl_getContextFrame_nothrow(),
865 if ( !pDialog
.get() )
866 return InteractiveSelectionResult_Cancelled
;
868 // DF definite problem here
869 // OK & Cancel seem to be both returning 0
870 if ( pDialog
->Execute() == RET_CANCEL
)
871 return InteractiveSelectionResult_Cancelled
;
875 for ( EventMap::const_iterator event
= m_aEvents
.begin();
876 event
!= m_aEvents
.end();
880 ScriptEventDescriptor
aScriptDescriptor( pEventHolder
->getNormalizedDescriptorByName( event
->second
.sListenerMethodName
) );
882 // set the new "property value"
884 lcl_getEventPropertyName( event
->second
.sListenerClassName
, event
->second
.sListenerMethodName
),
885 makeAny( aScriptDescriptor
)
889 catch( const Exception
& )
891 DBG_UNHANDLED_EXCEPTION();
894 return InteractiveSelectionResult_Success
;
897 void SAL_CALL
EventHandler::actuatingPropertyChanged( const OUString
& /*_rActuatingPropertyName*/, const Any
& /*_rNewValue*/, const Any
& /*_rOldValue*/, const Reference
< XObjectInspectorUI
>& /*_rxInspectorUI*/, sal_Bool
/*_bFirstTimeInit*/ ) throw (NullPointerException
, RuntimeException
, std::exception
)
899 OSL_FAIL( "EventHandler::actuatingPropertyChanged: no actuating properties -> no callback (well, this is how it *should* be!)" );
902 IMPLEMENT_FORWARD_XCOMPONENT( EventHandler
, EventHandler_Base
)
904 void SAL_CALL
EventHandler::disposing()
907 m_aEvents
.swap( aEmpty
);
908 m_xComponent
.clear();
911 sal_Bool SAL_CALL
EventHandler::suspend( sal_Bool
/*_bSuspend*/ ) throw (RuntimeException
, std::exception
)
916 Reference
< XFrame
> EventHandler::impl_getContextFrame_nothrow() const
918 Reference
< XFrame
> xContextFrame
;
922 Reference
< XModel
> xContextDocument( PropertyHandlerHelper::getContextDocument(m_xContext
), UNO_QUERY_THROW
);
923 Reference
< XController
> xController( xContextDocument
->getCurrentController(), UNO_SET_THROW
);
924 xContextFrame
.set( xController
->getFrame(), UNO_SET_THROW
);
926 catch( const Exception
& )
928 DBG_UNHANDLED_EXCEPTION();
931 return xContextFrame
;
934 sal_Int32
EventHandler::impl_getComponentIndexInParent_throw() const
936 Reference
< XChild
> xChild( m_xComponent
, UNO_QUERY_THROW
);
937 Reference
< XIndexAccess
> xParentAsIndexAccess( xChild
->getParent(), UNO_QUERY_THROW
);
939 // get the index of the inspected object within its parent container
940 sal_Int32 nElements
= xParentAsIndexAccess
->getCount();
941 for ( sal_Int32 i
=0; i
<nElements
; ++i
)
943 Reference
< XInterface
> xElement( xParentAsIndexAccess
->getByIndex( i
), UNO_QUERY_THROW
);
944 if ( xElement
== m_xComponent
)
947 throw NoSuchElementException();
950 void EventHandler::impl_getFormComponentScriptEvents_nothrow( Sequence
< ScriptEventDescriptor
>& _out_rEvents
) const
952 _out_rEvents
= Sequence
< ScriptEventDescriptor
>();
955 Reference
< XChild
> xChild( m_xComponent
, UNO_QUERY_THROW
);
956 Reference
< XEventAttacherManager
> xEventManager( xChild
->getParent(), UNO_QUERY_THROW
);
957 _out_rEvents
= xEventManager
->getScriptEvents( impl_getComponentIndexInParent_throw() );
959 // the form component script API has unqualified listener names, but for normalization
960 // purpose, we want fully qualified ones
961 ScriptEventDescriptor
* pEvents
= _out_rEvents
.getArray();
962 ScriptEventDescriptor
* pEventsEnd
= _out_rEvents
.getArray() + _out_rEvents
.getLength();
963 while ( pEvents
!= pEventsEnd
)
965 pEvents
->ListenerType
= lcl_getQualifiedKnownListenerName( *pEvents
);
969 catch( const Exception
& )
971 DBG_UNHANDLED_EXCEPTION();
975 void EventHandler::impl_getCopmonentListenerTypes_nothrow( Sequence
< Type
>& _out_rTypes
) const
977 _out_rTypes
.realloc( 0 );
980 // we use a set to avoid duplicates
983 Reference
< XIntrospection
> xIntrospection
= theIntrospection::get( m_xContext
);
985 // --- model listeners
986 lcl_addListenerTypesFor_throw(
987 m_xComponent
, xIntrospection
, aListeners
);
989 // --- "secondary component" (usually: "control" listeners)
991 Reference
< XInterface
> xSecondaryComponent( impl_getSecondaryComponentForEventInspection_throw() );
992 lcl_addListenerTypesFor_throw( xSecondaryComponent
, xIntrospection
, aListeners
);
993 ::comphelper::disposeComponent( xSecondaryComponent
);
996 // now that they're disambiguated, copy these types into our member
997 _out_rTypes
.realloc( aListeners
.size() );
998 ::std::copy( aListeners
.begin(), aListeners
.end(), _out_rTypes
.getArray() );
1000 catch( const Exception
& )
1002 DBG_UNHANDLED_EXCEPTION();
1006 void EventHandler::impl_getDialogElementScriptEvents_nothrow( Sequence
< ScriptEventDescriptor
>& _out_rEvents
) const
1008 _out_rEvents
= Sequence
< ScriptEventDescriptor
>();
1011 Reference
< XScriptEventsSupplier
> xEventsSupplier( m_xComponent
, UNO_QUERY_THROW
);
1012 Reference
< XNameContainer
> xEvents( xEventsSupplier
->getEvents(), UNO_QUERY_THROW
);
1013 Sequence
< OUString
> aEventNames( xEvents
->getElementNames() );
1015 sal_Int32 nEventCount
= aEventNames
.getLength();
1016 _out_rEvents
.realloc( nEventCount
);
1018 const OUString
* pNames
= aEventNames
.getConstArray();
1019 ScriptEventDescriptor
* pDescs
= _out_rEvents
.getArray();
1021 for( sal_Int32 i
= 0 ; i
< nEventCount
; ++i
, ++pNames
, ++pDescs
)
1022 OSL_VERIFY( xEvents
->getByName( *pNames
) >>= *pDescs
);
1024 catch( const Exception
& )
1026 DBG_UNHANDLED_EXCEPTION();
1030 Reference
< XInterface
> EventHandler::impl_getSecondaryComponentForEventInspection_throw( ) const
1032 Reference
< XInterface
> xReturn
;
1034 // if it's a form, create a form controller for the additional events
1035 Reference
< XForm
> xComponentAsForm( m_xComponent
, UNO_QUERY
);
1036 if ( xComponentAsForm
.is() )
1038 Reference
< XTabControllerModel
> xComponentAsTCModel( m_xComponent
, UNO_QUERY_THROW
);
1039 Reference
< XFormController
> xController
= FormController::create( m_xContext
);
1040 xController
->setModel( xComponentAsTCModel
);
1042 xReturn
= xController
;
1046 OUString sControlService
;
1047 OSL_VERIFY( m_xComponent
->getPropertyValue( PROPERTY_DEFAULTCONTROL
) >>= sControlService
);
1049 xReturn
= m_xContext
->getServiceManager()->createInstanceWithContext( sControlService
, m_xContext
);
1054 const EventDescription
& EventHandler::impl_getEventForName_throw( const OUString
& _rPropertyName
) const
1056 EventMap::const_iterator pos
= m_aEvents
.find( _rPropertyName
);
1057 if ( pos
== m_aEvents
.end() )
1058 throw UnknownPropertyException();
1064 static bool lcl_endsWith( const OUString
& _rText
, const OUString
& _rCheck
)
1066 sal_Int32 nTextLen
= _rText
.getLength();
1067 sal_Int32 nCheckLen
= _rCheck
.getLength();
1068 if ( nCheckLen
> nTextLen
)
1071 return _rText
.indexOf( _rCheck
) == ( nTextLen
- nCheckLen
);
1075 void EventHandler::impl_setFormComponentScriptEvent_nothrow( const ScriptEventDescriptor
& _rScriptEvent
)
1079 OUString
sScriptCode( _rScriptEvent
.ScriptCode
);
1080 OUString
sScriptType( _rScriptEvent
.ScriptType
);
1081 bool bResetScript
= sScriptCode
.isEmpty();
1083 sal_Int32 nObjectIndex
= impl_getComponentIndexInParent_throw();
1084 Reference
< XChild
> xChild( m_xComponent
, UNO_QUERY_THROW
);
1085 Reference
< XEventAttacherManager
> xEventManager( xChild
->getParent(), UNO_QUERY_THROW
);
1086 Sequence
< ScriptEventDescriptor
> aEvents( xEventManager
->getScriptEvents( nObjectIndex
) );
1088 // is there already a registered script for this event?
1089 ScriptEventDescriptor
* pEvent
= aEvents
.getArray();
1090 sal_Int32 eventCount
= aEvents
.getLength(), event
= 0;
1091 for ( event
= 0; event
< eventCount
; ++event
, ++pEvent
)
1093 if ( ( pEvent
->EventMethod
== _rScriptEvent
.EventMethod
)
1094 && ( lcl_endsWith( _rScriptEvent
.ListenerType
, pEvent
->ListenerType
) )
1095 // (strange enough, the events we get from getScriptEvents are not fully qualified)
1099 if ( !bResetScript
)
1101 // set to something non-empty -> overwrite
1102 pEvent
->ScriptCode
= sScriptCode
;
1103 pEvent
->ScriptType
= sScriptType
;
1107 // set to empty -> remove from sequence
1108 ::std::copy( pEvent
+ 1, aEvents
.getArray() + eventCount
, pEvent
);
1109 aEvents
.realloc( eventCount
- 1 );
1115 if ( ( event
>= eventCount
) && !bResetScript
)
1117 // no, did not find it -> append
1118 aEvents
.realloc( eventCount
+ 1 );
1119 aEvents
[ eventCount
] = _rScriptEvent
;
1122 xEventManager
->revokeScriptEvents( nObjectIndex
);
1123 xEventManager
->registerScriptEvents( nObjectIndex
, aEvents
);
1125 PropertyHandlerHelper::setContextDocumentModified( m_xContext
);
1127 catch( const Exception
& )
1129 DBG_UNHANDLED_EXCEPTION();
1133 void EventHandler::impl_setDialogElementScriptEvent_nothrow( const ScriptEventDescriptor
& _rScriptEvent
)
1137 OUString
sScriptCode( _rScriptEvent
.ScriptCode
);
1138 bool bResetScript
= sScriptCode
.isEmpty();
1140 Reference
< XScriptEventsSupplier
> xEventsSupplier( m_xComponent
, UNO_QUERY_THROW
);
1141 Reference
< XNameContainer
> xEvents( xEventsSupplier
->getEvents(), UNO_QUERY_THROW
);
1143 OUStringBuffer aCompleteName
;
1144 aCompleteName
.append( _rScriptEvent
.ListenerType
);
1145 aCompleteName
.appendAscii( "::" );
1146 aCompleteName
.append( _rScriptEvent
.EventMethod
);
1147 OUString
sCompleteName( aCompleteName
.makeStringAndClear() );
1149 bool bExists
= xEvents
->hasByName( sCompleteName
);
1154 xEvents
->removeByName( sCompleteName
);
1158 Any aNewValue
; aNewValue
<<= _rScriptEvent
;
1161 xEvents
->replaceByName( sCompleteName
, aNewValue
);
1163 xEvents
->insertByName( sCompleteName
, aNewValue
);
1166 catch( const Exception
& )
1168 DBG_UNHANDLED_EXCEPTION();
1172 bool EventHandler::impl_filterMethod_nothrow( const EventDescription
& _rEvent
) const
1174 // some (control-triggered) events do not make sense for certain grid control columns. However,
1175 // our mechnism to retrieve control-triggered events does not know about this, so we do some
1176 // late filtering here.
1177 switch ( m_nGridColumnType
)
1179 case FormComponentType::COMBOBOX
:
1180 if ( UID_BRWEVT_ACTIONPERFORMED
== _rEvent
.sUniqueBrowseId
)
1183 case FormComponentType::LISTBOX
:
1184 if ( ( UID_BRWEVT_CHANGED
== _rEvent
.sUniqueBrowseId
)
1185 || ( UID_BRWEVT_ACTIONPERFORMED
== _rEvent
.sUniqueBrowseId
)
1196 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */