LibreOffice Module extensions (master) 1
eventhandler.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20
21#include "eventhandler.hxx"
22#include <helpids.h>
23#include <propctrlr.h>
24#include "formbrowsertools.hxx"
25#include <strings.hrc>
26#include "formstrings.hxx"
27#include "handlerhelper.hxx"
28#include "modulepcr.hxx"
29#include "pcrcommon.hxx"
31
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/theIntrospection.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/uri/UriReferenceFactory.hpp>
50#include <com/sun/star/uri/XVndSunStarScriptUrlReference.hpp>
51
56#include <comphelper/types.hxx>
59#include <rtl/ref.hxx>
60#include <rtl/ustrbuf.hxx>
61#include <svx/svxdlg.hxx>
63
64#include <map>
65#include <algorithm>
66#include <iterator>
67#include <string_view>
68#include <utility>
69
70namespace pcr
71{
72
73 using ::com::sun::star::uno::Reference;
74 using ::com::sun::star::uno::XComponentContext;
75 using ::com::sun::star::uno::Any;
76 using ::com::sun::star::uno::TypeClass_STRING;
77 using ::com::sun::star::uno::Type;
78 using ::com::sun::star::beans::theIntrospection;
79 using ::com::sun::star::beans::XPropertyChangeListener;
80 using ::com::sun::star::beans::Property;
81 using ::com::sun::star::beans::PropertyState;
82 using ::com::sun::star::beans::PropertyState_DIRECT_VALUE;
83 using ::com::sun::star::uno::Sequence;
84 using ::com::sun::star::script::ScriptEventDescriptor;
85 using ::com::sun::star::script::XScriptEventsSupplier;
86 using ::com::sun::star::lang::NullPointerException;
87 using ::com::sun::star::uno::Exception;
88 using ::com::sun::star::container::XChild;
89 using ::com::sun::star::container::XIndexAccess;
90 using ::com::sun::star::script::XEventAttacherManager;
91 using ::com::sun::star::uno::UNO_QUERY;
92 using ::com::sun::star::uno::UNO_QUERY_THROW;
93 using ::com::sun::star::uno::XInterface;
94 using ::com::sun::star::beans::XIntrospection;
95 using ::com::sun::star::beans::XIntrospectionAccess;
96 using ::com::sun::star::container::XNameContainer;
97 using ::com::sun::star::awt::XTabControllerModel;
98 using ::com::sun::star::form::XForm;
99 using ::com::sun::star::form::runtime::FormController;
100 using ::com::sun::star::form::runtime::XFormController;
101 using ::com::sun::star::beans::UnknownPropertyException;
102 using ::com::sun::star::container::NoSuchElementException;
103 using ::com::sun::star::beans::XPropertySetInfo;
104 using ::com::sun::star::container::XNameReplace;
105 using ::com::sun::star::beans::PropertyValue;
106 using ::com::sun::star::inspection::LineDescriptor;
107 using ::com::sun::star::inspection::XPropertyControlFactory;
108 using ::com::sun::star::inspection::InteractiveSelectionResult;
109 using ::com::sun::star::inspection::InteractiveSelectionResult_Cancelled;
110 using ::com::sun::star::inspection::InteractiveSelectionResult_Success;
111 using ::com::sun::star::inspection::XObjectInspectorUI;
112 using ::com::sun::star::beans::PropertyChangeEvent;
113 using ::com::sun::star::frame::XFrame;
114 using ::com::sun::star::frame::XModel;
115 using ::com::sun::star::frame::XController;
116 using ::com::sun::star::uno::UNO_SET_THROW;
117 using com::sun::star::uri::UriReferenceFactory;
118 using com::sun::star::uri::XUriReferenceFactory;
119 using com::sun::star::uri::XVndSunStarScriptUrlReference;
120
121 namespace PropertyControlType = css::inspection::PropertyControlType;
122 namespace PropertyAttribute = css::beans::PropertyAttribute;
123 namespace FormComponentType = css::form::FormComponentType;
124
125 EventDescription::EventDescription( EventId _nId, std::u16string_view listenerClassName,
126 std::u16string_view listenerMethodName, TranslateId pDisplayNameResId, OUString _sHelpId, OString _sUniqueBrowseId )
127 :sDisplayName(PcrRes( pDisplayNameResId ))
128 ,sListenerClassName( listenerClassName )
129 ,sListenerMethodName( listenerMethodName )
130 ,sHelpId(std::move( _sHelpId ))
131 ,sUniqueBrowseId(std::move( _sUniqueBrowseId ))
132 ,nId( _nId )
133 {
134 }
135
136 namespace
137 {
138 #define DESCRIBE_EVENT( map, listener, method, id_postfix ) \
139 map.emplace( \
140 u"" method, \
141 EventDescription( ++nEventId, u"com.sun.star." listener, u"" method, RID_STR_EVT_##id_postfix, HID_EVT_##id_postfix, UID_BRWEVT_##id_postfix ) )
142
143 bool lcl_getEventDescriptionForMethod( const OUString& _rMethodName, EventDescription& _out_rDescription )
144 {
145 static EventMap s_aKnownEvents = []() {
147 sal_Int32 nEventId = 0;
148
149 DESCRIBE_EVENT(aMap, "form.XApproveActionListener", "approveAction", APPROVEACTIONPERFORMED);
150 DESCRIBE_EVENT(aMap, "awt.XActionListener", "actionPerformed", ACTIONPERFORMED);
151 DESCRIBE_EVENT(aMap, "form.XChangeListener", "changed", CHANGED);
152 DESCRIBE_EVENT(aMap, "awt.XTextListener", "textChanged", TEXTCHANGED);
153 DESCRIBE_EVENT(aMap, "awt.XItemListener", "itemStateChanged", ITEMSTATECHANGED);
154 DESCRIBE_EVENT(aMap, "awt.XFocusListener", "focusGained", FOCUSGAINED);
155 DESCRIBE_EVENT(aMap, "awt.XFocusListener", "focusLost", FOCUSLOST);
156 DESCRIBE_EVENT(aMap, "awt.XKeyListener", "keyPressed", KEYTYPED);
157 DESCRIBE_EVENT(aMap, "awt.XKeyListener", "keyReleased", KEYUP);
158 DESCRIBE_EVENT(aMap, "awt.XMouseListener", "mouseEntered", MOUSEENTERED);
159 DESCRIBE_EVENT(aMap, "awt.XMouseMotionListener", "mouseDragged", MOUSEDRAGGED);
160 DESCRIBE_EVENT(aMap, "awt.XMouseMotionListener", "mouseMoved", MOUSEMOVED);
161 DESCRIBE_EVENT(aMap, "awt.XMouseListener", "mousePressed", MOUSEPRESSED);
162 DESCRIBE_EVENT(aMap, "awt.XMouseListener", "mouseReleased", MOUSERELEASED);
163 DESCRIBE_EVENT(aMap, "awt.XMouseListener", "mouseExited", MOUSEEXITED);
164 DESCRIBE_EVENT(aMap, "form.XResetListener", "approveReset", APPROVERESETTED);
165 DESCRIBE_EVENT(aMap, "form.XResetListener", "resetted", RESETTED);
166 DESCRIBE_EVENT(aMap, "form.XSubmitListener", "approveSubmit", SUBMITTED);
167 DESCRIBE_EVENT(aMap, "form.XUpdateListener", "approveUpdate", BEFOREUPDATE);
168 DESCRIBE_EVENT(aMap, "form.XUpdateListener", "updated", AFTERUPDATE);
169 DESCRIBE_EVENT(aMap, "form.XLoadListener", "loaded", LOADED);
170 DESCRIBE_EVENT(aMap, "form.XLoadListener", "reloading", RELOADING);
171 DESCRIBE_EVENT(aMap, "form.XLoadListener", "reloaded", RELOADED);
172 DESCRIBE_EVENT(aMap, "form.XLoadListener", "unloading", UNLOADING);
173 DESCRIBE_EVENT(aMap, "form.XLoadListener", "unloaded", UNLOADED);
174 DESCRIBE_EVENT(aMap, "form.XConfirmDeleteListener", "confirmDelete", CONFIRMDELETE);
175 DESCRIBE_EVENT(aMap, "sdb.XRowSetApproveListener", "approveRowChange", APPROVEROWCHANGE);
176 DESCRIBE_EVENT(aMap, "sdbc.XRowSetListener", "rowChanged", ROWCHANGE);
177 DESCRIBE_EVENT(aMap, "sdb.XRowSetApproveListener", "approveCursorMove", POSITIONING);
178 DESCRIBE_EVENT(aMap, "sdbc.XRowSetListener", "cursorMoved", POSITIONED);
179 DESCRIBE_EVENT(aMap, "form.XDatabaseParameterListener", "approveParameter", APPROVEPARAMETER);
180 DESCRIBE_EVENT(aMap, "sdb.XSQLErrorListener", "errorOccured", ERROROCCURRED);
181 DESCRIBE_EVENT(aMap, "awt.XAdjustmentListener", "adjustmentValueChanged", ADJUSTMENTVALUECHANGED);
182
183 return aMap;
184 }();
185
186 EventMap::const_iterator pos = s_aKnownEvents.find( _rMethodName );
187 if ( pos == s_aKnownEvents.end() )
188 return false;
189
190 _out_rDescription = pos->second;
191 return true;
192 }
193
194 OUString lcl_getEventPropertyName( std::u16string_view _rListenerClassName, std::u16string_view _rMethodName )
195 {
196 return _rListenerClassName + OUStringChar(';') + _rMethodName;
197 }
198
199 ScriptEventDescriptor lcl_getAssignedScriptEvent( const EventDescription& _rEvent, const std::vector< ScriptEventDescriptor >& _rAllAssignedMacros )
200 {
201 ScriptEventDescriptor aScriptEvent;
202 // for the case there is actually no event assigned, initialize at least ListenerType and MethodName,
203 // so this ScriptEventDescriptor properly describes the given event
204 aScriptEvent.ListenerType = _rEvent.sListenerClassName;
205 aScriptEvent.EventMethod = _rEvent.sListenerMethodName;
206
207 for ( const ScriptEventDescriptor& rSED : _rAllAssignedMacros )
208 {
209 if ( rSED.ListenerType != _rEvent.sListenerClassName
210 || rSED.EventMethod != _rEvent.sListenerMethodName
211 )
212 continue;
213
214 if ( rSED.ScriptCode.isEmpty()
215 || rSED.ScriptType.isEmpty()
216 )
217 {
218 OSL_FAIL( "lcl_getAssignedScriptEvent: me thinks this should not happen!" );
219 continue;
220 }
221
222 aScriptEvent = rSED;
223
224 if ( aScriptEvent.ScriptType != "StarBasic" )
225 continue;
226
227 // this is an old-style macro specification:
228 // [document|application]:Library.Module.Function
229 // we need to translate this to the new-style macro specification
230 // vnd.sun.star.script:Library.Module.Function?language=Basic&location=[document|application]
231
232 sal_Int32 nPrefixLen = aScriptEvent.ScriptCode.indexOf( ':' );
233 OSL_ENSURE( nPrefixLen > 0, "lcl_getAssignedScriptEvent: illegal location!" );
234 std::u16string_view sLocation = aScriptEvent.ScriptCode.subView( 0, nPrefixLen );
235 std::u16string_view sMacroPath = aScriptEvent.ScriptCode.subView( nPrefixLen + 1 );
236
237 aScriptEvent.ScriptCode =
238 OUString::Concat("vnd.sun.star.script:") +
239 sMacroPath +
240 "?language=Basic&location=" +
241 sLocation;
242
243 // also, this new-style spec requires the script code to be "Script" instead of "StarBasic"
244 aScriptEvent.ScriptType = "Script";
245 }
246 return aScriptEvent;
247 }
248
249 OUString lcl_getQualifiedKnownListenerName( const ScriptEventDescriptor& _rFormComponentEventDescriptor )
250 {
251 EventDescription aKnownEvent;
252 if ( lcl_getEventDescriptionForMethod( _rFormComponentEventDescriptor.EventMethod, aKnownEvent ) )
253 return aKnownEvent.sListenerClassName;
254 OSL_FAIL( "lcl_getQualifiedKnownListenerName: unknown method name!" );
255 // somebody assigned an script to a form component event which we don't know
256 // Speaking strictly, this is not really an error - it is possible to do
257 // this programmatically -, but it should rarely happen, since it's not possible
258 // via UI
259 return _rFormComponentEventDescriptor.ListenerType;
260 }
261
262 typedef std::set< Type, TypeLessByName > TypeBag;
263
264 void lcl_addListenerTypesFor_throw( const Reference< XInterface >& _rxComponent,
265 const Reference< XIntrospection >& _rxIntrospection, TypeBag& _out_rTypes )
266 {
267 if ( !_rxComponent.is() )
268 return;
269 OSL_PRECOND( _rxIntrospection.is(), "lcl_addListenerTypesFor_throw: this will crash!" );
270
271 Reference< XIntrospectionAccess > xIntrospectionAccess(
272 _rxIntrospection->inspect( Any( _rxComponent ) ), UNO_SET_THROW );
273
274 const Sequence< Type > aListeners( xIntrospectionAccess->getSupportedListeners() );
275
276 std::copy( aListeners.begin(), aListeners.end(),
277 std::insert_iterator< TypeBag >( _out_rTypes, _out_rTypes.begin() ) );
278 }
279 }
280
281 typedef ::cppu::WeakImplHelper < css::container::XNameReplace
283
284 namespace {
285
286 /* A UNO component holding assigned event descriptions, for use with a SvxMacroAssignDlg */
287 class EventHolder : public EventHolder_Base
288 {
289 private:
290 typedef std::unordered_map< OUString, ScriptEventDescriptor > EventMap;
291 typedef std::map< EventId, OUString > EventMapIndexAccess;
292
293 EventMap m_aEventNameAccess;
294 EventMapIndexAccess m_aEventIndexAccess;
295
296 public:
297 EventHolder( );
298
299 void addEvent( EventId _nId, const OUString& _rEventName, const ScriptEventDescriptor& _rScriptEvent );
300
304 ScriptEventDescriptor getNormalizedDescriptorByName( const OUString& _rEventName ) const;
305
306 // XNameReplace
307 virtual void SAL_CALL replaceByName( const OUString& _rName, const Any& aElement ) override;
308 virtual Any SAL_CALL getByName( const OUString& _rName ) override;
309 virtual Sequence< OUString > SAL_CALL getElementNames( ) override;
310 virtual sal_Bool SAL_CALL hasByName( const OUString& _rName ) override;
311 virtual Type SAL_CALL getElementType( ) override;
312 virtual sal_Bool SAL_CALL hasElements( ) override;
313
314 protected:
315 virtual ~EventHolder( ) override;
316
317 private:
318 ScriptEventDescriptor const & impl_getDescriptor_throw( const OUString& _rEventName ) const;
319 };
320
321 }
322
323 EventHolder::EventHolder()
324 {
325 }
326
327 EventHolder::~EventHolder()
328 {
329 m_aEventNameAccess.clear();
330 m_aEventIndexAccess.clear();
331 }
332
333 void EventHolder::addEvent( EventId _nId, const OUString& _rEventName, const ScriptEventDescriptor& _rScriptEvent )
334 {
335 std::pair< EventMap::iterator, bool > insertionResult =
336 m_aEventNameAccess.emplace( _rEventName, _rScriptEvent );
337 OSL_ENSURE( insertionResult.second, "EventHolder::addEvent: there already was a MacroURL for this event!" );
338 m_aEventIndexAccess[ _nId ] = _rEventName;
339 }
340
341 ScriptEventDescriptor EventHolder::getNormalizedDescriptorByName( const OUString& _rEventName ) const
342 {
343 return impl_getDescriptor_throw( _rEventName );
344 }
345
346 ScriptEventDescriptor const & EventHolder::impl_getDescriptor_throw( const OUString& _rEventName ) const
347 {
348 EventMap::const_iterator pos = m_aEventNameAccess.find( _rEventName );
349 if ( pos == m_aEventNameAccess.end() )
350 throw NoSuchElementException( OUString(), *const_cast< EventHolder* >( this ) );
351 return pos->second;
352 }
353
354 void SAL_CALL EventHolder::replaceByName( const OUString& _rName, const Any& _rElement )
355 {
356 EventMap::iterator pos = m_aEventNameAccess.find( _rName );
357 if ( pos == m_aEventNameAccess.end() )
358 throw NoSuchElementException( OUString(), *this );
359
360 Sequence< PropertyValue > aScriptDescriptor;
361 OSL_VERIFY( _rElement >>= aScriptDescriptor );
362
363 ::comphelper::NamedValueCollection aExtractor( aScriptDescriptor );
364
365 pos->second.ScriptType = aExtractor.getOrDefault( "EventType", OUString() );
366 pos->second.ScriptCode = aExtractor.getOrDefault( "Script", OUString() );
367 }
368
369 Any SAL_CALL EventHolder::getByName( const OUString& _rName )
370 {
371 ScriptEventDescriptor aDescriptor( impl_getDescriptor_throw( _rName ) );
372
373 Sequence< PropertyValue > aScriptDescriptor{
374 comphelper::makePropertyValue("EventType", aDescriptor.ScriptType),
375 comphelper::makePropertyValue("Script", aDescriptor.ScriptCode)
376 };
377
378 return Any( aScriptDescriptor );
379 }
380
381 Sequence< OUString > SAL_CALL EventHolder::getElementNames( )
382 {
383 Sequence< OUString > aReturn( m_aEventIndexAccess.size() );
384 OUString* pReturn = aReturn.getArray();
385
386 // SvxMacroAssignDlg has a weird API: It expects a XNameReplace, means a container whose
387 // main access method is by name. In its UI, it shows the possible events in exactly the
388 // order in which XNameAccess::getElementNames returns them.
389 // However, SvxMacroAssignDlg *also* takes an index for the initial selection, which is
390 // relative to the sequence returned by XNameAccess::getElementNames.
391 // This is IMO weird, since it mixes index access with name access, which decreases efficiency
392 // of the implementation.
393 // Well, it means we're forced to return the events in getElementNames in exactly the same as they
394 // appear in the property browser UI.
395 for (auto const& elem : m_aEventIndexAccess)
396 {
397 *pReturn = elem.second;
398 ++pReturn;
399 }
400 return aReturn;
401 }
402
403 sal_Bool SAL_CALL EventHolder::hasByName( const OUString& _rName )
404 {
405 EventMap::const_iterator pos = m_aEventNameAccess.find( _rName );
406 return pos != m_aEventNameAccess.end();
407 }
408
409 Type SAL_CALL EventHolder::getElementType( )
410 {
412 }
413
414 sal_Bool SAL_CALL EventHolder::hasElements( )
415 {
416 return !m_aEventNameAccess.empty();
417 }
418
419
420 EventHandler::EventHandler( const Reference< XComponentContext >& _rxContext )
422 ,m_xContext( _rxContext )
423 ,m_aPropertyListeners( m_aMutex )
424 ,m_bEventsMapInitialized( false )
425 ,m_bIsDialogElement( false )
426 ,m_nGridColumnType( -1 )
427 {
428 }
429
430 EventHandler::~EventHandler()
431 {
432 }
433
434 OUString SAL_CALL EventHandler::getImplementationName( )
435 {
436 return "com.sun.star.comp.extensions.EventHandler";
437 }
438
439 sal_Bool SAL_CALL EventHandler::supportsService( const OUString& ServiceName )
440 {
442 }
443
444 Sequence< OUString > SAL_CALL EventHandler::getSupportedServiceNames( )
445 {
446 return { "com.sun.star.form.inspection.EventHandler" };
447 }
448
449 void SAL_CALL EventHandler::inspect( const Reference< XInterface >& _rxIntrospectee )
450 {
451 ::osl::MutexGuard aGuard( m_aMutex );
452
453 if ( !_rxIntrospectee.is() )
454 throw NullPointerException();
455
456 m_xComponent.set( _rxIntrospectee, UNO_QUERY_THROW );
457
458 m_bEventsMapInitialized = false;
459 EventMap().swap(m_aEvents);
460
461 m_bIsDialogElement = false;
462 m_nGridColumnType = -1;
463 try
464 {
465 Reference< XPropertySetInfo > xPSI( m_xComponent->getPropertySetInfo() );
466 m_bIsDialogElement = xPSI.is()
467 && xPSI->hasPropertyByName( PROPERTY_WIDTH )
468 && xPSI->hasPropertyByName( PROPERTY_HEIGHT )
469 && xPSI->hasPropertyByName( PROPERTY_POSITIONX )
470 && xPSI->hasPropertyByName( PROPERTY_POSITIONY );
471
472 Reference< XChild > xAsChild( _rxIntrospectee, UNO_QUERY );
473 if ( xAsChild.is() && !Reference< XForm >( _rxIntrospectee, UNO_QUERY ).is() )
474 {
475 if ( FormComponentType::GRIDCONTROL == classifyComponent( xAsChild->getParent() ) )
476 {
477 m_nGridColumnType = classifyComponent( _rxIntrospectee );
478 }
479 }
480 }
481 catch( const Exception& )
482 {
483 DBG_UNHANDLED_EXCEPTION("extensions.propctrlr");
484 }
485 }
486
487 Any SAL_CALL EventHandler::getPropertyValue( const OUString& _rPropertyName )
488 {
489 ::osl::MutexGuard aGuard( m_aMutex );
490
491 const EventDescription& rEvent = impl_getEventForName_throw( _rPropertyName );
492
493 std::vector< ScriptEventDescriptor > aEvents;
494 impl_getComponentScriptEvents_nothrow( aEvents );
495
496 ScriptEventDescriptor aPropertyValue;
497 for ( const ScriptEventDescriptor& rSCD : aEvents )
498 {
499 if ( rEvent.sListenerClassName == rSCD.ListenerType
500 && rEvent.sListenerMethodName == rSCD.EventMethod
501 )
502 {
503 aPropertyValue = rSCD;
504 break;
505 }
506 }
507
508 return Any( aPropertyValue );
509 }
510
511 void SAL_CALL EventHandler::setPropertyValue( const OUString& _rPropertyName, const Any& _rValue )
512 {
513 ::osl::MutexGuard aGuard( m_aMutex );
514
515 const EventDescription& rEvent = impl_getEventForName_throw( _rPropertyName );
516
517 ScriptEventDescriptor aNewScriptEvent;
518 OSL_VERIFY( _rValue >>= aNewScriptEvent );
519
520 ScriptEventDescriptor aOldScriptEvent;
521 OSL_VERIFY( getPropertyValue( _rPropertyName ) >>= aOldScriptEvent );
522 if ( aOldScriptEvent == aNewScriptEvent )
523 return;
524
525 if ( m_bIsDialogElement )
526 impl_setDialogElementScriptEvent_nothrow( aNewScriptEvent );
527 else
528 impl_setFormComponentScriptEvent_nothrow( aNewScriptEvent );
529
530 PropertyHandlerHelper::setContextDocumentModified( m_xContext );
531
532 PropertyChangeEvent aEvent;
533 aEvent.Source = m_xComponent;
534 aEvent.PropertyHandle = rEvent.nId;
535 aEvent.PropertyName = _rPropertyName;
536 aEvent.OldValue <<= aOldScriptEvent;
537 aEvent.NewValue <<= aNewScriptEvent;
538 m_aPropertyListeners.notifyEach( &XPropertyChangeListener::propertyChange, aEvent );
539 }
540
541 Any SAL_CALL EventHandler::convertToPropertyValue( const OUString& _rPropertyName, const Any& _rControlValue )
542 {
543 ::osl::MutexGuard aGuard( m_aMutex );
544
545 OUString sNewScriptCode;
546 OSL_VERIFY( _rControlValue >>= sNewScriptCode );
547
548 std::vector< ScriptEventDescriptor > aAllAssignedEvents;
549 impl_getComponentScriptEvents_nothrow( aAllAssignedEvents );
550
551 const EventDescription& rEvent = impl_getEventForName_throw( _rPropertyName );
552 ScriptEventDescriptor aAssignedScript = lcl_getAssignedScriptEvent( rEvent, aAllAssignedEvents );
553
554 OSL_ENSURE( sNewScriptCode.isEmpty(), "EventHandler::convertToPropertyValue: cannot convert a non-empty display name!" );
555 // Usually, there is no possibility for the user to change the content of an event binding directly in the
556 // input field, this instead is done with the macro assignment dialog.
557 // The only exception is the user pressing "DEL" while the control has the focus, in this case, we reset the
558 // control content to an empty string. So this is the only scenario where this method is allowed to be called.
559
560 // Strictly, we would be able to convert the display value to a property value,
561 // using the "name (location, language)" format we used in convertToControlValue. However,
562 // there is no need for this code...
563
564 aAssignedScript.ScriptCode = sNewScriptCode;
565 return Any( aAssignedScript );
566 }
567
568 Any SAL_CALL EventHandler::convertToControlValue( const OUString& /*_rPropertyName*/, const Any& _rPropertyValue, const Type& _rControlValueType )
569 {
570 ::osl::MutexGuard aGuard( m_aMutex );
571
572 ScriptEventDescriptor aScriptEvent;
573 OSL_VERIFY( _rPropertyValue >>= aScriptEvent );
574
575 OSL_ENSURE( _rControlValueType.getTypeClass() == TypeClass_STRING,
576 "EventHandler::convertToControlValue: unexpected ControlValue type class!" );
577
578 OUString sScript( aScriptEvent.ScriptCode );
579 if ( !sScript.isEmpty() )
580 {
581 // format is: "name (location, language)"
582 try
583 {
584 // parse
585 Reference< XUriReferenceFactory > xUriRefFac = UriReferenceFactory::create( m_xContext );
586 Reference< XVndSunStarScriptUrlReference > xScriptUri( xUriRefFac->parse( sScript ), UNO_QUERY_THROW );
587
588 OUStringBuffer aComposeBuffer;
589
590 // name
591 aComposeBuffer.append( xScriptUri->getName() );
592
593 // location
594 const OUString sLocation = xScriptUri->getParameter( "location" );
595 const OUString sLanguage = xScriptUri->getParameter( "language" );
596
597 if ( !(sLocation.isEmpty() && sLanguage.isEmpty()) )
598 {
599 aComposeBuffer.append( " (" );
600
601 // location
602 OSL_ENSURE( !sLocation.isEmpty(), "EventHandler::convertToControlValue: unexpected: no location!" );
603 if ( !sLocation.isEmpty() )
604 {
605 aComposeBuffer.append( sLocation + ", " );
606 }
607
608 // language
609 if ( !sLanguage.isEmpty() )
610 {
611 aComposeBuffer.append( sLanguage );
612 }
613
614 aComposeBuffer.append( ')' );
615 }
616
617 sScript = aComposeBuffer.makeStringAndClear();
618 }
619 catch( const Exception& )
620 {
621 DBG_UNHANDLED_EXCEPTION("extensions.propctrlr");
622 }
623 }
624
625 return Any( sScript );
626 }
627
628 PropertyState SAL_CALL EventHandler::getPropertyState( const OUString& /*_rPropertyName*/ )
629 {
630 return PropertyState_DIRECT_VALUE;
631 }
632
633 void SAL_CALL EventHandler::addPropertyChangeListener( const Reference< XPropertyChangeListener >& _rxListener )
634 {
635 ::osl::MutexGuard aGuard( m_aMutex );
636 if ( !_rxListener.is() )
637 throw NullPointerException();
638 m_aPropertyListeners.addInterface( _rxListener );
639 }
640
641 void SAL_CALL EventHandler::removePropertyChangeListener( const Reference< XPropertyChangeListener >& _rxListener )
642 {
643 ::osl::MutexGuard aGuard( m_aMutex );
644 m_aPropertyListeners.removeInterface( _rxListener );
645 }
646
647 Sequence< Property > SAL_CALL EventHandler::getSupportedProperties()
648 {
649 ::osl::MutexGuard aGuard( m_aMutex );
650 if ( !m_bEventsMapInitialized )
651 {
652 m_bEventsMapInitialized = true;
653 try
654 {
655 std::vector< Type > aListeners;
656 impl_getComponentListenerTypes_nothrow( aListeners );
657
658 OUString sListenerClassName;
659
660 // loop through all listeners and all methods, and see which we can present at the UI
661 for ( const Type& rListener : aListeners )
662 {
663 // the programmatic name of the listener, to be used as "property" name
664 sListenerClassName = rListener.getTypeName();
665 OSL_ENSURE( !sListenerClassName.isEmpty(), "EventHandler::getSupportedProperties: strange - no listener name ..." );
666 if ( sListenerClassName.isEmpty() )
667 continue;
668
669 // loop through all methods
670 const Sequence<OUString> aEventMethods = comphelper::getEventMethodsForType( rListener );
671 for (const OUString& rMethod : aEventMethods)
672 {
674 if ( !lcl_getEventDescriptionForMethod( rMethod, aEvent ) )
675 continue;
676
677 if ( !impl_filterMethod_nothrow( aEvent ) )
678 continue;
679
680 m_aEvents.emplace(
681 lcl_getEventPropertyName( sListenerClassName, rMethod ), aEvent );
682 }
683 }
684
685 }
686 catch( const Exception& )
687 {
688 DBG_UNHANDLED_EXCEPTION("extensions.propctrlr");
689 }
690 }
691
692 // sort them by ID - this is the relative ordering in the UI
693 std::map< EventId, Property > aOrderedProperties;
694 for (auto const& event : m_aEvents)
695 {
696 aOrderedProperties[ event.second.nId ] = Property(
697 event.first, event.second.nId,
699 PropertyAttribute::BOUND );
700 }
701
702 return comphelper::mapValuesToSequence( aOrderedProperties );
703 }
704
705 Sequence< OUString > SAL_CALL EventHandler::getSupersededProperties( )
706 {
707 // none
708 return Sequence< OUString >( );
709 }
710
711 Sequence< OUString > SAL_CALL EventHandler::getActuatingProperties( )
712 {
713 // none
714 return Sequence< OUString >( );
715 }
716
717 LineDescriptor SAL_CALL EventHandler::describePropertyLine( const OUString& _rPropertyName,
718 const Reference< XPropertyControlFactory >& _rxControlFactory )
719 {
720 if ( !_rxControlFactory.is() )
721 throw NullPointerException();
722
723 ::osl::MutexGuard aGuard( m_aMutex );
724
725 LineDescriptor aDescriptor;
726
727 aDescriptor.Control = _rxControlFactory->createPropertyControl( PropertyControlType::TextField, true );
728 new PropertyControlExtender( aDescriptor.Control );
729
730 const EventDescription& rEvent = impl_getEventForName_throw( _rPropertyName );
731 aDescriptor.DisplayName = rEvent.sDisplayName;
732 aDescriptor.HelpURL = HelpIdUrl::getHelpURL( rEvent.sHelpId );
733 aDescriptor.PrimaryButtonId = OStringToOUString(rEvent.sUniqueBrowseId, RTL_TEXTENCODING_UTF8);
734 aDescriptor.HasPrimaryButton = true;
735 aDescriptor.Category = "Events";
736 return aDescriptor;
737 }
738
739 sal_Bool SAL_CALL EventHandler::isComposable( const OUString& /*_rPropertyName*/ )
740 {
741 return false;
742 }
743
744 InteractiveSelectionResult SAL_CALL EventHandler::onInteractivePropertySelection( const OUString& _rPropertyName, sal_Bool /*_bPrimary*/, Any& /*_rData*/, const Reference< XObjectInspectorUI >& _rxInspectorUI )
745 {
746 if ( !_rxInspectorUI.is() )
747 throw NullPointerException();
748
749 ::osl::MutexGuard aGuard( m_aMutex );
750 const EventDescription& rForEvent = impl_getEventForName_throw( _rPropertyName );
751
752 std::vector< ScriptEventDescriptor > aAllAssignedEvents;
753 impl_getComponentScriptEvents_nothrow( aAllAssignedEvents );
754
755 // SvxMacroAssignDlg-compatible structure holding all event/assignments
756 ::rtl::Reference< EventHolder > pEventHolder( new EventHolder );
757
758 for (auto const& event : m_aEvents)
759 {
760 // the script which is assigned to the current event (if any)
761 ScriptEventDescriptor aAssignedScript = lcl_getAssignedScriptEvent( event.second, aAllAssignedEvents );
762 pEventHolder->addEvent( event.second.nId, event.second.sListenerMethodName, aAssignedScript );
763 }
764
765 // the initial selection in the dialog
766 const Sequence< OUString > aNames( pEventHolder->getElementNames() );
767 const OUString* pChosenEvent = std::find( aNames.begin(), aNames.end(), rForEvent.sListenerMethodName );
768 sal_uInt16 nInitialSelection = static_cast<sal_uInt16>( pChosenEvent - aNames.begin() );
769
770 // the dialog
772
774 PropertyHandlerHelper::getDialogParentFrame( m_xContext ),
775 impl_getContextFrame_nothrow(),
776 m_bIsDialogElement,
777 pEventHolder,
778 nInitialSelection
779 ) );
780
781 if ( !pDialog )
782 return InteractiveSelectionResult_Cancelled;
783
784 // DF definite problem here
785 // OK & Cancel seem to be both returning 0
786 if ( pDialog->Execute() == RET_CANCEL )
787 return InteractiveSelectionResult_Cancelled;
788
789 try
790 {
791 for (auto const& event : m_aEvents)
792 {
793 ScriptEventDescriptor aScriptDescriptor( pEventHolder->getNormalizedDescriptorByName( event.second.sListenerMethodName ) );
794
795 // set the new "property value"
797 lcl_getEventPropertyName( event.second.sListenerClassName, event.second.sListenerMethodName ),
798 Any( aScriptDescriptor )
799 );
800 }
801 }
802 catch( const Exception& )
803 {
804 DBG_UNHANDLED_EXCEPTION("extensions.propctrlr");
805 }
806
807 return InteractiveSelectionResult_Success;
808 }
809
810 void SAL_CALL EventHandler::actuatingPropertyChanged( const OUString& /*_rActuatingPropertyName*/, const Any& /*_rNewValue*/, const Any& /*_rOldValue*/, const Reference< XObjectInspectorUI >& /*_rxInspectorUI*/, sal_Bool /*_bFirstTimeInit*/ )
811 {
812 OSL_FAIL( "EventHandler::actuatingPropertyChanged: no actuating properties -> no callback (well, this is how it *should* be!)" );
813 }
814
816
817 void SAL_CALL EventHandler::disposing()
818 {
819 EventMap().swap(m_aEvents);
820 m_xComponent.clear();
821 }
822
823 sal_Bool SAL_CALL EventHandler::suspend( sal_Bool /*_bSuspend*/ )
824 {
825 return true;
826 }
827
828 Reference< XFrame > EventHandler::impl_getContextFrame_nothrow() const
829 {
830 Reference< XFrame > xContextFrame;
831
832 try
833 {
834 Reference< XModel > xContextDocument( PropertyHandlerHelper::getContextDocument(m_xContext), UNO_QUERY_THROW );
835 Reference< XController > xController( xContextDocument->getCurrentController(), UNO_SET_THROW );
836 xContextFrame.set( xController->getFrame(), UNO_SET_THROW );
837 }
838 catch( const Exception& )
839 {
840 DBG_UNHANDLED_EXCEPTION("extensions.propctrlr");
841 }
842
843 return xContextFrame;
844 }
845
846 sal_Int32 EventHandler::impl_getComponentIndexInParent_throw() const
847 {
848 Reference< XChild > xChild( m_xComponent, UNO_QUERY_THROW );
849 Reference< XIndexAccess > xParentAsIndexAccess( xChild->getParent(), UNO_QUERY_THROW );
850
851 // get the index of the inspected object within its parent container
852 sal_Int32 nElements = xParentAsIndexAccess->getCount();
853 for ( sal_Int32 i=0; i<nElements; ++i )
854 {
855 Reference< XInterface > xElement( xParentAsIndexAccess->getByIndex( i ), UNO_QUERY_THROW );
856 if ( xElement == m_xComponent )
857 return i;
858 }
859 throw NoSuchElementException();
860 }
861
862 void EventHandler::impl_getFormComponentScriptEvents_nothrow( std::vector < ScriptEventDescriptor >& _out_rEvents ) const
863 {
864 _out_rEvents.clear();
865 try
866 {
867 Reference< XChild > xChild( m_xComponent, UNO_QUERY_THROW );
868 Reference< XEventAttacherManager > xEventManager( xChild->getParent(), UNO_QUERY_THROW );
869 comphelper::sequenceToContainer(_out_rEvents, xEventManager->getScriptEvents( impl_getComponentIndexInParent_throw() ));
870
871 // the form component script API has unqualified listener names, but for normalization
872 // purpose, we want fully qualified ones
873 for ( ScriptEventDescriptor& rSED : _out_rEvents)
874 {
875 rSED.ListenerType = lcl_getQualifiedKnownListenerName( rSED );
876 }
877 }
878 catch( const Exception& )
879 {
880 DBG_UNHANDLED_EXCEPTION("extensions.propctrlr");
881 }
882 }
883
884 void EventHandler::impl_getComponentListenerTypes_nothrow( std::vector< Type >& _out_rTypes ) const
885 {
886 _out_rTypes.clear();
887 try
888 {
889 // we use a set to avoid duplicates
891
892 Reference< XIntrospection > xIntrospection = theIntrospection::get( m_xContext );
893
894 // --- model listeners
895 lcl_addListenerTypesFor_throw(
896 m_xComponent, xIntrospection, aListeners );
897
898 // --- "secondary component" (usually: "control" listeners)
899 {
900 Reference< XInterface > xSecondaryComponent( impl_getSecondaryComponentForEventInspection_throw() );
901 lcl_addListenerTypesFor_throw( xSecondaryComponent, xIntrospection, aListeners );
902 ::comphelper::disposeComponent( xSecondaryComponent );
903 }
904
905 // now that they're disambiguated, copy these types into our member
906 _out_rTypes.insert( _out_rTypes.end(), aListeners.begin(), aListeners.end() );
907 }
908 catch( const Exception& )
909 {
910 DBG_UNHANDLED_EXCEPTION("extensions.propctrlr");
911 }
912 }
913
914 void EventHandler::impl_getDialogElementScriptEvents_nothrow( std::vector < ScriptEventDescriptor >& _out_rEvents ) const
915 {
916 _out_rEvents.clear();
917 try
918 {
919 Reference< XScriptEventsSupplier > xEventsSupplier( m_xComponent, UNO_QUERY_THROW );
920 Reference< XNameContainer > xEvents( xEventsSupplier->getEvents(), UNO_SET_THROW );
921 Sequence< OUString > aEventNames( xEvents->getElementNames() );
922
923 sal_Int32 nEventCount = aEventNames.getLength();
924 _out_rEvents.resize( nEventCount );
925
926 for( sal_Int32 i = 0; i < nEventCount; ++i )
927 OSL_VERIFY( xEvents->getByName( aEventNames[i] ) >>= _out_rEvents[i] );
928 }
929 catch( const Exception& )
930 {
931 DBG_UNHANDLED_EXCEPTION("extensions.propctrlr");
932 }
933 }
934
935 Reference< XInterface > EventHandler::impl_getSecondaryComponentForEventInspection_throw( ) const
936 {
938
939 // if it's a form, create a form controller for the additional events
940 Reference< XForm > xComponentAsForm( m_xComponent, UNO_QUERY );
941 if ( xComponentAsForm.is() )
942 {
943 Reference< XTabControllerModel > xComponentAsTCModel( m_xComponent, UNO_QUERY_THROW );
944 Reference< XFormController > xController = FormController::create( m_xContext );
945 xController->setModel( xComponentAsTCModel );
946
947 xReturn = xController;
948 }
949 else
950 {
951 OUString sControlService;
952 OSL_VERIFY( m_xComponent->getPropertyValue( PROPERTY_DEFAULTCONTROL ) >>= sControlService );
953
954 xReturn = m_xContext->getServiceManager()->createInstanceWithContext( sControlService, m_xContext );
955 }
956 return xReturn;
957 }
958
959 const EventDescription& EventHandler::impl_getEventForName_throw( const OUString& _rPropertyName ) const
960 {
961 EventMap::const_iterator pos = m_aEvents.find( _rPropertyName );
962 if ( pos == m_aEvents.end() )
963 throw UnknownPropertyException(_rPropertyName);
964 return pos->second;
965 }
966
967 namespace
968 {
969 bool lcl_endsWith( std::u16string_view _rText, std::u16string_view _rCheck )
970 {
971 size_t nTextLen = _rText.size();
972 size_t nCheckLen = _rCheck.size();
973 if ( nCheckLen > nTextLen )
974 return false;
975
976 return _rText.find( _rCheck ) == ( nTextLen - nCheckLen );
977 }
978 }
979
980 void EventHandler::impl_setFormComponentScriptEvent_nothrow( const ScriptEventDescriptor& _rScriptEvent )
981 {
982 try
983 {
984 OUString sScriptCode( _rScriptEvent.ScriptCode );
985 OUString sScriptType( _rScriptEvent.ScriptType );
986 bool bResetScript = sScriptCode.isEmpty();
987
988 sal_Int32 nObjectIndex = impl_getComponentIndexInParent_throw();
989 Reference< XChild > xChild( m_xComponent, UNO_QUERY_THROW );
990 Reference< XEventAttacherManager > xEventManager( xChild->getParent(), UNO_QUERY_THROW );
991 std::vector< ScriptEventDescriptor > aEvents;
992 comphelper::sequenceToContainer( aEvents, xEventManager->getScriptEvents( nObjectIndex ) );
993
994 // is there already a registered script for this event?
995 sal_Int32 eventCount = aEvents.size(), event = 0;
996 for ( event = 0; event < eventCount; ++event )
997 {
998 ScriptEventDescriptor* pEvent = &aEvents[event];
999 if ( ( pEvent->EventMethod == _rScriptEvent.EventMethod )
1000 && ( lcl_endsWith( _rScriptEvent.ListenerType, pEvent->ListenerType ) )
1001 // (strange enough, the events we get from getScriptEvents are not fully qualified)
1002 )
1003 {
1004 // yes
1005 if ( !bResetScript )
1006 {
1007 // set to something non-empty -> overwrite
1008 pEvent->ScriptCode = sScriptCode;
1009 pEvent->ScriptType = sScriptType;
1010 }
1011 else
1012 {
1013 // set to empty -> remove from vector
1014 aEvents.erase(aEvents.begin() + event );
1015 --eventCount;
1016 }
1017 break;
1018 }
1019 }
1020 if ( ( event >= eventCount ) && !bResetScript )
1021 {
1022 // no, did not find it -> append
1023 aEvents.push_back( _rScriptEvent );
1024 }
1025
1026 xEventManager->revokeScriptEvents( nObjectIndex );
1027 xEventManager->registerScriptEvents( nObjectIndex, comphelper::containerToSequence(aEvents) );
1028
1029 PropertyHandlerHelper::setContextDocumentModified( m_xContext );
1030 }
1031 catch( const Exception& )
1032 {
1033 DBG_UNHANDLED_EXCEPTION("extensions.propctrlr");
1034 }
1035 }
1036
1037 void EventHandler::impl_setDialogElementScriptEvent_nothrow( const ScriptEventDescriptor& _rScriptEvent )
1038 {
1039 try
1040 {
1041 OUString sScriptCode( _rScriptEvent.ScriptCode );
1042 bool bResetScript = sScriptCode.isEmpty();
1043
1044 Reference< XScriptEventsSupplier > xEventsSupplier( m_xComponent, UNO_QUERY_THROW );
1045 Reference< XNameContainer > xEvents( xEventsSupplier->getEvents(), UNO_SET_THROW );
1046
1047 OUString sCompleteName =
1048 _rScriptEvent.ListenerType +
1049 "::" +
1050 _rScriptEvent.EventMethod;
1051
1052 bool bExists = xEvents->hasByName( sCompleteName );
1053
1054 if ( bResetScript )
1055 {
1056 if ( bExists )
1057 xEvents->removeByName( sCompleteName );
1058 }
1059 else
1060 {
1061 Any aNewValue; aNewValue <<= _rScriptEvent;
1062
1063 if ( bExists )
1064 xEvents->replaceByName( sCompleteName, aNewValue );
1065 else
1066 xEvents->insertByName( sCompleteName, aNewValue );
1067 }
1068 }
1069 catch( const Exception& )
1070 {
1071 DBG_UNHANDLED_EXCEPTION("extensions.propctrlr");
1072 }
1073 }
1074
1075 bool EventHandler::impl_filterMethod_nothrow( const EventDescription& _rEvent ) const
1076 {
1077 // some (control-triggered) events do not make sense for certain grid control columns. However,
1078 // our mechanism to retrieve control-triggered events does not know about this, so we do some
1079 // late filtering here.
1080 switch ( m_nGridColumnType )
1081 {
1082 case FormComponentType::COMBOBOX:
1084 return false;
1085 break;
1086 case FormComponentType::LISTBOX:
1087 if ( ( UID_BRWEVT_CHANGED == _rEvent.sUniqueBrowseId )
1089 )
1090 return false;
1091 break;
1092 }
1093
1094 return true;
1095 }
1096
1097} // namespace pcr
1098
1099extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
1101 css::uno::XComponentContext* context , css::uno::Sequence<css::uno::Any> const&)
1102{
1103 return cppu::acquire(new pcr::EventHandler(context));
1104}
1105
1106/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
AnyEventRef aEvent
static SvxAbstractDialogFactory * Create()
virtual VclPtr< VclAbstractDialog > CreateSvxMacroAssignDlg(weld::Window *_pParent, const css::uno::Reference< css::frame::XFrame > &_rxDocumentFrame, const bool _bUnoDialogMode, const css::uno::Reference< css::container::XNameReplace > &_rxEvents, const sal_uInt16 _nInitiallySelectedEvent)=0
EventHandler(const css::uno::Reference< css::uno::XComponentContext > &_rxContext)
sal_Int32 nElements
Listeners aListeners
#define DBG_UNHANDLED_EXCEPTION(...)
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * extensions_propctrlr_EventHandler_get_implementation(css::uno::XComponentContext *context, css::uno::Sequence< css::uno::Any > const &)
#define DESCRIBE_EVENT(map, listener, method, id_postfix)
Reference< XComponentContext > m_xContext
Definition: filehandler.cxx:78
constexpr OUStringLiteral PROPERTY_DEFAULTCONTROL
Definition: formstrings.hxx:24
constexpr OUStringLiteral PROPERTY_HEIGHT
constexpr OUStringLiteral PROPERTY_POSITIONX
constexpr OUStringLiteral PROPERTY_POSITIONY
constexpr OUStringLiteral PROPERTY_WIDTH
Definition: formstrings.hxx:48
OUString sDisplayName
Reference< XIntrospection > xIntrospection
::osl::Mutex m_aMutex
Definition: logger.cxx:98
@ Exception
Sequence< OUString > getEventMethodsForType(const Type &type)
DstType sequenceToContainer(const css::uno::Sequence< SrcType > &i_Sequence)
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
css::uno::Sequence< typename M::mapped_type > mapValuesToSequence(M const &map)
css::beans::PropertyValue makePropertyValue(const OUString &rName, T &&rValue)
std::set< css::uno::Type, UnoTypeLess > TypeBag
Type
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
int i
VBAHELPER_DLLPUBLIC bool setPropertyValue(css::uno::Sequence< css::beans::PropertyValue > &aProp, const OUString &aName, const css::uno::Any &aValue)
a property handler for any virtual string properties
Definition: browserline.cxx:39
::cppu::WeakImplHelper< css::container::XNameReplace > EventHolder_Base
std::unordered_map< OUString, EventDescription > EventMap
sal_Int32 EventId
sal_Int16 classifyComponent(const Reference< XInterface > &_rxComponent)
OUString PcrRes(TranslateId aId)
Definition: modulepcr.cxx:26
::cppu::WeakComponentImplHelper< css::inspection::XPropertyHandler, css::lang::XServiceInfo > EventHandler_Base
bool getPropertyValue(ValueType &rValue, css::uno::Reference< css::beans::XPropertySet > const &xPropSet, OUString const &propName)
HashMap_OWString_Interface aMap
sal_Int16 nId
#define IMPLEMENT_FORWARD_XCOMPONENT(classname, baseclass)
Definition: pcrcommon.hxx:105
constexpr OStringLiteral UID_BRWEVT_CHANGED
Definition: propctrlr.h:52
constexpr OStringLiteral UID_BRWEVT_ACTIONPERFORMED
Definition: propctrlr.h:51
Reference< XController > xController
unsigned char sal_Bool
constexpr OUStringLiteral sScript
RET_CANCEL
size_t pos