Line data Source code
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 : #include "genericpropertyhandler.hxx"
21 : #include "formmetadata.hxx"
22 : #include "handlerhelper.hxx"
23 :
24 : #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
25 : #include <com/sun/star/reflection/XEnumTypeDescription.hpp>
26 : #include <com/sun/star/beans/Introspection.hpp>
27 : #include <com/sun/star/inspection/PropertyControlType.hpp>
28 : #include <com/sun/star/inspection/XHyperlinkControl.hpp>
29 : #include <com/sun/star/awt/XActionListener.hpp>
30 : #include <com/sun/star/script/Converter.hpp>
31 : #include <com/sun/star/util/URLTransformer.hpp>
32 : #include <com/sun/star/util/XURLTransformer.hpp>
33 : #include <com/sun/star/frame/Desktop.hpp>
34 : #include <com/sun/star/frame/XDispatchProvider.hpp>
35 : #include <tools/debug.hxx>
36 : #include <comphelper/extract.hxx>
37 :
38 : #include <algorithm>
39 : #include <o3tl/compat_functional.hxx>
40 :
41 : //------------------------------------------------------------------------
42 0 : extern "C" void SAL_CALL createRegistryInfo_GenericPropertyHandler()
43 : {
44 0 : ::pcr::OAutoRegistration< ::pcr::GenericPropertyHandler > aAutoRegistration;
45 0 : }
46 :
47 : //........................................................................
48 : namespace pcr
49 : {
50 : //........................................................................
51 :
52 : using namespace ::com::sun::star::uno;
53 : using namespace ::com::sun::star::beans;
54 : using namespace ::com::sun::star::script;
55 : using namespace ::com::sun::star::frame;
56 : using namespace ::com::sun::star::lang;
57 : using namespace ::com::sun::star::util;
58 : using namespace ::com::sun::star::container;
59 : using namespace ::com::sun::star::reflection;
60 : using namespace ::com::sun::star::inspection;
61 : using ::com::sun::star::awt::XActionListener;
62 : using ::com::sun::star::awt::ActionEvent;
63 :
64 : //====================================================================
65 : //= EnumRepresentation
66 : //====================================================================
67 0 : class EnumRepresentation : public IPropertyEnumRepresentation
68 : {
69 : private:
70 : oslInterlockedCount m_refCount;
71 : Reference< XEnumTypeDescription > m_xTypeDescription;
72 : Type m_aEnumType;
73 :
74 : public:
75 : EnumRepresentation( const Reference< XComponentContext >& _rxContext, const Type& _rEnumType );
76 :
77 : // IPropertyEnumRepresentation implementqation
78 : virtual ::std::vector< ::rtl::OUString >
79 : SAL_CALL getDescriptions() const;
80 : virtual void SAL_CALL getValueFromDescription( const ::rtl::OUString& _rDescription, ::com::sun::star::uno::Any& _out_rValue ) const;
81 : virtual ::rtl::OUString SAL_CALL getDescriptionForValue( const ::com::sun::star::uno::Any& _rEnumValue ) const;
82 :
83 : // IReference implementqation
84 : virtual oslInterlockedCount SAL_CALL acquire();
85 : virtual oslInterlockedCount SAL_CALL release();
86 :
87 : private:
88 : void impl_getValues( Sequence< sal_Int32 >& _out_rValues ) const;
89 :
90 : private:
91 : EnumRepresentation(); // never implemented
92 : EnumRepresentation( const EnumRepresentation& ); // never implemented
93 : EnumRepresentation& operator=( const EnumRepresentation& ); // never implemented
94 : };
95 :
96 : //--------------------------------------------------------------------
97 0 : EnumRepresentation::EnumRepresentation( const Reference< XComponentContext >& _rxContext, const Type& _rEnumType )
98 : :m_refCount( 0 )
99 0 : ,m_aEnumType( _rEnumType )
100 : {
101 : try
102 : {
103 0 : if ( _rxContext.is() )
104 : {
105 : Reference< XHierarchicalNameAccess > xTypeDescProv(
106 0 : _rxContext->getValueByName( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/singletons/com.sun.star.reflection.theTypeDescriptionManager" ) ) ),
107 0 : UNO_QUERY_THROW );
108 :
109 0 : m_xTypeDescription = Reference< XEnumTypeDescription >( xTypeDescProv->getByHierarchicalName( m_aEnumType.getTypeName() ), UNO_QUERY_THROW );
110 : }
111 : }
112 0 : catch( const Exception& )
113 : {
114 : OSL_FAIL( "EnumRepresentation::EnumRepresentation: caught an exception!" );
115 : }
116 0 : }
117 :
118 : //--------------------------------------------------------------------
119 0 : ::std::vector< ::rtl::OUString > EnumRepresentation::getDescriptions() const
120 : {
121 0 : Sequence< ::rtl::OUString > aNames;
122 : try
123 : {
124 0 : if ( m_xTypeDescription.is() )
125 0 : aNames = m_xTypeDescription->getEnumNames();
126 : }
127 0 : catch( const Exception& )
128 : {
129 : OSL_FAIL( "EnumRepresentation::getDescriptions: caught an exception!" );
130 : }
131 :
132 0 : return ::std::vector< ::rtl::OUString >( aNames.getConstArray(), aNames.getConstArray() + aNames.getLength() );
133 : }
134 :
135 : //--------------------------------------------------------------------
136 0 : void EnumRepresentation::impl_getValues( Sequence< sal_Int32 >& _out_rValues ) const
137 : {
138 0 : _out_rValues.realloc( 0 );
139 : try
140 : {
141 0 : if ( m_xTypeDescription.is() )
142 0 : _out_rValues = m_xTypeDescription->getEnumValues();
143 : }
144 0 : catch( const Exception& )
145 : {
146 : OSL_FAIL( "EnumRepresentation::impl_getValues: caught an exception!" );
147 : }
148 0 : }
149 :
150 : //--------------------------------------------------------------------
151 0 : void EnumRepresentation::getValueFromDescription( const ::rtl::OUString& _rDescription, Any& _out_rValue ) const
152 : {
153 0 : ::std::vector< ::rtl::OUString > aDescriptions( getDescriptions() );
154 :
155 : sal_Int32 index = ::std::find( aDescriptions.begin(), aDescriptions.end(),
156 0 : _rDescription ) - aDescriptions.begin();
157 :
158 0 : Sequence< sal_Int32 > aValues;
159 0 : impl_getValues( aValues );
160 :
161 0 : if ( ( index >= 0 ) && ( index < aValues.getLength() ) )
162 0 : _out_rValue = ::cppu::int2enum( aValues[ index ], m_aEnumType );
163 : else
164 : {
165 : OSL_FAIL( "EnumRepresentation::getValueFromDescription: cannot convert!" );
166 0 : _out_rValue.clear();
167 0 : }
168 0 : }
169 :
170 : //--------------------------------------------------------------------
171 0 : ::rtl::OUString EnumRepresentation::getDescriptionForValue( const Any& _rEnumValue ) const
172 : {
173 0 : ::rtl::OUString sDescription;
174 :
175 0 : sal_Int32 nAsInt = 0;
176 0 : OSL_VERIFY( ::cppu::enum2int( nAsInt, _rEnumValue ) );
177 :
178 0 : Sequence< sal_Int32 > aValues;
179 0 : impl_getValues( aValues );
180 :
181 0 : sal_Int32 index = ::std::find( aValues.getConstArray(), aValues.getConstArray() + aValues.getLength(),
182 0 : nAsInt ) - aValues.getConstArray();
183 :
184 0 : ::std::vector< ::rtl::OUString > aDescriptions( getDescriptions() );
185 0 : if ( ( index >= 0 ) && ( index < (sal_Int32)aDescriptions.size() ) )
186 0 : sDescription = aDescriptions[ index ];
187 : else
188 : {
189 : OSL_FAIL( "EnumRepresentation::getDescriptionForValue: cannot convert!" );
190 : }
191 0 : return sDescription;
192 : }
193 :
194 : //--------------------------------------------------------------------
195 0 : oslInterlockedCount SAL_CALL EnumRepresentation::acquire()
196 : {
197 0 : return osl_atomic_increment( &m_refCount );
198 : }
199 :
200 : //--------------------------------------------------------------------
201 0 : oslInterlockedCount SAL_CALL EnumRepresentation::release()
202 : {
203 0 : if ( 0 == osl_atomic_decrement( &m_refCount ) )
204 : {
205 0 : delete this;
206 0 : return 0;
207 : }
208 0 : return m_refCount;
209 : }
210 :
211 : //====================================================================
212 : //= UrlClickHandler
213 : //====================================================================
214 : typedef ::cppu::WeakImplHelper1 < XActionListener
215 : > UrlClickHandler_Base;
216 : class UrlClickHandler : public UrlClickHandler_Base
217 : {
218 : ComponentContext m_aContext;
219 : public:
220 : UrlClickHandler( const ComponentContext& _rContext, const Reference< XHyperlinkControl >& _rxControl );
221 :
222 : protected:
223 : ~UrlClickHandler();
224 :
225 : // XActionListener
226 : virtual void SAL_CALL actionPerformed( const ActionEvent& rEvent ) throw (RuntimeException);
227 :
228 : // XEventListener
229 : virtual void SAL_CALL disposing( const EventObject& Source ) throw (RuntimeException);
230 :
231 : protected:
232 : void impl_dispatch_throw( const ::rtl::OUString& _rURL );
233 : };
234 :
235 : //--------------------------------------------------------------------
236 : DBG_NAME( UrlClickHandler )
237 : //--------------------------------------------------------------------
238 0 : UrlClickHandler::UrlClickHandler( const ComponentContext& _rContext, const Reference< XHyperlinkControl >& _rxControl )
239 0 : :m_aContext( _rContext )
240 : {
241 0 : if ( !_rxControl.is() )
242 0 : throw NullPointerException();
243 :
244 0 : osl_atomic_increment( &m_refCount );
245 : {
246 0 : _rxControl->addActionListener( this );
247 : }
248 0 : osl_atomic_decrement( &m_refCount );
249 : OSL_ENSURE( m_refCount > 0, "UrlClickHandler::UrlClickHandler: leaking!" );
250 :
251 : DBG_CTOR( UrlClickHandler, NULL );
252 0 : }
253 :
254 : //--------------------------------------------------------------------
255 0 : UrlClickHandler::~UrlClickHandler()
256 : {
257 : DBG_DTOR( UrlClickHandler, NULL );
258 0 : }
259 :
260 : //--------------------------------------------------------------------
261 0 : void SAL_CALL UrlClickHandler::actionPerformed( const ActionEvent& rEvent ) throw (RuntimeException)
262 : {
263 0 : Reference< XPropertyControl > xControl( rEvent.Source, UNO_QUERY_THROW );
264 0 : Any aControlValue( xControl->getValue() );
265 :
266 0 : ::rtl::OUString sURL;
267 0 : if ( aControlValue.hasValue() && !( aControlValue >>= sURL ) )
268 0 : throw RuntimeException( ::rtl::OUString(), *this );
269 :
270 0 : if ( sURL.isEmpty() )
271 0 : return;
272 :
273 0 : impl_dispatch_throw( sURL );
274 : }
275 :
276 : //--------------------------------------------------------------------
277 0 : void SAL_CALL UrlClickHandler::disposing( const EventObject& /*Source*/ ) throw (RuntimeException)
278 : {
279 : // not interested in
280 0 : }
281 :
282 : //--------------------------------------------------------------------
283 0 : void UrlClickHandler::impl_dispatch_throw( const ::rtl::OUString& _rURL )
284 : {
285 0 : Reference< XURLTransformer > xTransformer( URLTransformer::create(m_aContext.getUNOContext()) );
286 0 : URL aURL; aURL.Complete = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:OpenHyperlink" ) );
287 0 : xTransformer->parseStrict( aURL );
288 :
289 0 : Reference< XDesktop2 > xDispProv = Desktop::create( m_aContext.getUNOContext() );
290 0 : Reference< XDispatch > xDispatch( xDispProv->queryDispatch( aURL, ::rtl::OUString(), 0 ), UNO_QUERY_THROW );
291 :
292 0 : Sequence< PropertyValue > aDispatchArgs(1);
293 0 : aDispatchArgs[0].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("URL"));
294 0 : aDispatchArgs[0].Value <<= _rURL;
295 :
296 0 : xDispatch->dispatch( aURL, aDispatchArgs );
297 0 : }
298 :
299 : //====================================================================
300 : //= GenericPropertyHandler
301 : //====================================================================
302 : DBG_NAME( GenericPropertyHandler )
303 : //--------------------------------------------------------------------
304 0 : GenericPropertyHandler::GenericPropertyHandler( const Reference< XComponentContext >& _rxContext )
305 : :GenericPropertyHandler_Base( m_aMutex )
306 : ,m_aContext( _rxContext )
307 : ,m_aPropertyListeners( m_aMutex )
308 0 : ,m_bPropertyMapInitialized( false )
309 : {
310 : DBG_CTOR( GenericPropertyHandler, NULL );
311 :
312 0 : m_xTypeConverter = Converter::create(_rxContext);
313 0 : }
314 :
315 : //--------------------------------------------------------------------
316 0 : GenericPropertyHandler::~GenericPropertyHandler()
317 : {
318 : DBG_DTOR( GenericPropertyHandler, NULL );
319 0 : }
320 :
321 : //--------------------------------------------------------------------
322 0 : ::rtl::OUString SAL_CALL GenericPropertyHandler::getImplementationName( ) throw (RuntimeException)
323 : {
324 0 : return getImplementationName_static();
325 : }
326 :
327 : //--------------------------------------------------------------------
328 0 : ::sal_Bool SAL_CALL GenericPropertyHandler::supportsService( const ::rtl::OUString& ServiceName ) throw (RuntimeException)
329 : {
330 0 : StlSyntaxSequence< ::rtl::OUString > aAllServices( getSupportedServiceNames() );
331 0 : return ::std::find( aAllServices.begin(), aAllServices.end(), ServiceName ) != aAllServices.end();
332 : }
333 :
334 : //--------------------------------------------------------------------
335 0 : Sequence< ::rtl::OUString > SAL_CALL GenericPropertyHandler::getSupportedServiceNames( ) throw (RuntimeException)
336 : {
337 0 : return getSupportedServiceNames_static();
338 : }
339 :
340 : //--------------------------------------------------------------------
341 0 : ::rtl::OUString SAL_CALL GenericPropertyHandler::getImplementationName_static( ) throw (RuntimeException)
342 : {
343 0 : return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.extensions.GenericPropertyHandler" ) );
344 : }
345 :
346 : //--------------------------------------------------------------------
347 0 : Sequence< ::rtl::OUString > SAL_CALL GenericPropertyHandler::getSupportedServiceNames_static( ) throw (RuntimeException)
348 : {
349 0 : Sequence< ::rtl::OUString > aSupported( 1 );
350 0 : aSupported[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.inspection.GenericPropertyHandler" ) );
351 0 : return aSupported;
352 : }
353 :
354 : //--------------------------------------------------------------------
355 0 : Reference< XInterface > SAL_CALL GenericPropertyHandler::Create( const Reference< XComponentContext >& _rxContext )
356 : {
357 0 : return *( new GenericPropertyHandler( _rxContext ) );
358 : }
359 :
360 : //--------------------------------------------------------------------
361 0 : void SAL_CALL GenericPropertyHandler::inspect( const Reference< XInterface >& _rxIntrospectee ) throw (RuntimeException, NullPointerException)
362 : {
363 0 : ::osl::MutexGuard aGuard( m_aMutex );
364 :
365 0 : if ( !_rxIntrospectee.is() )
366 0 : throw NullPointerException();
367 :
368 : // revoke old property change listeners
369 0 : ::cppu::OInterfaceIteratorHelper iterRemove( m_aPropertyListeners );
370 0 : ::cppu::OInterfaceIteratorHelper iterReAdd( m_aPropertyListeners ); // this holds a copy of the container ...
371 0 : while ( iterRemove.hasMoreElements() )
372 0 : m_xComponent->removePropertyChangeListener( ::rtl::OUString(), static_cast< XPropertyChangeListener* >( iterRemove.next() ) );
373 :
374 0 : m_xComponentIntrospectionAccess.clear();
375 0 : m_xComponent.clear();
376 0 : m_xPropertyState.clear();
377 :
378 : // create an introspection adapter for the component
379 0 : Reference< XIntrospection > xIntrospection = Introspection::create( m_aContext.getUNOContext() );
380 :
381 0 : Reference< XIntrospectionAccess > xIntrospectionAccess( xIntrospection->inspect( makeAny( _rxIntrospectee ) ) );
382 0 : if ( !xIntrospectionAccess.is() )
383 0 : throw RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "The introspection service could not handle the given component." ) ), *this );
384 :
385 0 : m_xComponent = Reference< XPropertySet >( xIntrospectionAccess->queryAdapter( XPropertySet::static_type() ), UNO_QUERY_THROW );
386 : // now that we survived so far, remember m_xComponentIntrospectionAccess
387 0 : m_xComponentIntrospectionAccess = xIntrospectionAccess;
388 0 : m_xPropertyState = m_xPropertyState.query( m_xComponent );
389 :
390 0 : m_bPropertyMapInitialized = false;
391 0 : m_aProperties.clear();
392 :
393 : // re-add the property change listeners
394 0 : while ( iterReAdd.hasMoreElements() )
395 0 : m_xComponent->addPropertyChangeListener( ::rtl::OUString(), static_cast< XPropertyChangeListener* >( iterReAdd.next() ) );
396 0 : }
397 :
398 : //--------------------------------------------------------------------
399 0 : Any SAL_CALL GenericPropertyHandler::getPropertyValue( const ::rtl::OUString& _rPropertyName ) throw (UnknownPropertyException, RuntimeException)
400 : {
401 0 : ::osl::MutexGuard aGuard( m_aMutex );
402 0 : if ( !m_xComponent.is() )
403 0 : throw UnknownPropertyException();
404 :
405 0 : return m_xComponent->getPropertyValue( _rPropertyName );
406 : }
407 :
408 : //--------------------------------------------------------------------
409 0 : void SAL_CALL GenericPropertyHandler::setPropertyValue( const ::rtl::OUString& _rPropertyName, const Any& _rValue ) throw (UnknownPropertyException, RuntimeException)
410 : {
411 0 : ::osl::MutexGuard aGuard( m_aMutex );
412 0 : if ( !m_xComponent.is() )
413 0 : throw UnknownPropertyException();
414 :
415 0 : m_xComponent->setPropertyValue( _rPropertyName, _rValue );
416 0 : }
417 :
418 : //--------------------------------------------------------------------
419 0 : ::rtl::Reference< IPropertyEnumRepresentation > GenericPropertyHandler::impl_getEnumConverter( const Type& _rEnumType )
420 : {
421 0 : ::rtl::Reference< IPropertyEnumRepresentation >& rConverter = m_aEnumConverters[ _rEnumType ];
422 0 : if ( !rConverter.is() )
423 0 : rConverter = new EnumRepresentation( m_aContext.getUNOContext(), _rEnumType );
424 0 : return rConverter;
425 : }
426 :
427 : //--------------------------------------------------------------------
428 0 : Any SAL_CALL GenericPropertyHandler::convertToPropertyValue( const ::rtl::OUString& _rPropertyName, const Any& _rControlValue ) throw (UnknownPropertyException, RuntimeException)
429 : {
430 0 : ::osl::MutexGuard aGuard( m_aMutex );
431 0 : const_cast< GenericPropertyHandler* >( this )->impl_ensurePropertyMap();
432 :
433 0 : PropertyMap::const_iterator pos = m_aProperties.find( _rPropertyName );
434 0 : if ( pos == m_aProperties.end() )
435 0 : throw UnknownPropertyException();
436 :
437 0 : Any aPropertyValue;
438 0 : if ( !_rControlValue.hasValue() )
439 : // NULL is converted to NULL
440 : return aPropertyValue;
441 :
442 0 : if ( pos->second.Type.getTypeClass() == TypeClass_ENUM )
443 : {
444 0 : ::rtl::OUString sControlValue;
445 0 : OSL_VERIFY( _rControlValue >>= sControlValue );
446 0 : impl_getEnumConverter( pos->second.Type )->getValueFromDescription( sControlValue, aPropertyValue );
447 : }
448 : else
449 0 : aPropertyValue = PropertyHandlerHelper::convertToPropertyValue( m_aContext.getContext(),m_xTypeConverter, pos->second, _rControlValue );
450 :
451 0 : return aPropertyValue;
452 : }
453 :
454 : //--------------------------------------------------------------------
455 0 : Any SAL_CALL GenericPropertyHandler::convertToControlValue( const ::rtl::OUString& _rPropertyName, const Any& _rPropertyValue, const Type& _rControlValueType ) throw (UnknownPropertyException, RuntimeException)
456 : {
457 0 : ::osl::MutexGuard aGuard( m_aMutex );
458 0 : const_cast< GenericPropertyHandler* >( this )->impl_ensurePropertyMap();
459 :
460 0 : PropertyMap::const_iterator pos = m_aProperties.find( _rPropertyName );
461 0 : if ( pos == m_aProperties.end() )
462 0 : throw UnknownPropertyException();
463 :
464 0 : Any aControlValue;
465 0 : if ( !_rPropertyValue.hasValue() )
466 : // NULL is converted to NULL
467 : return aControlValue;
468 :
469 0 : if ( pos->second.Type.getTypeClass() == TypeClass_ENUM )
470 : {
471 0 : aControlValue <<= impl_getEnumConverter( pos->second.Type )->getDescriptionForValue( _rPropertyValue );
472 : }
473 : else
474 0 : aControlValue = PropertyHandlerHelper::convertToControlValue( m_aContext.getContext(),m_xTypeConverter, _rPropertyValue, _rControlValueType );
475 0 : return aControlValue;
476 : }
477 :
478 : //--------------------------------------------------------------------
479 0 : PropertyState SAL_CALL GenericPropertyHandler::getPropertyState( const ::rtl::OUString& _rPropertyName ) throw (UnknownPropertyException, RuntimeException)
480 : {
481 0 : ::osl::MutexGuard aGuard( m_aMutex );
482 0 : PropertyState eState = PropertyState_DIRECT_VALUE;
483 0 : if ( m_xPropertyState.is() )
484 0 : eState = m_xPropertyState->getPropertyState( _rPropertyName );
485 0 : return eState;
486 : }
487 :
488 : //--------------------------------------------------------------------
489 0 : void SAL_CALL GenericPropertyHandler::addPropertyChangeListener( const Reference< XPropertyChangeListener >& _rxListener ) throw (RuntimeException)
490 : {
491 0 : if ( !_rxListener.is() )
492 0 : throw NullPointerException();
493 :
494 0 : ::osl::MutexGuard aGuard( m_aMutex );
495 0 : m_aPropertyListeners.addInterface( _rxListener );
496 0 : if ( m_xComponent.is() )
497 : {
498 : try
499 : {
500 0 : m_xComponent->addPropertyChangeListener( ::rtl::OUString(), _rxListener );
501 : }
502 0 : catch( const UnknownPropertyException& )
503 : {
504 : OSL_FAIL( "GenericPropertyHandler::addPropertyChangeListener:\nThe inspected component does not allow registering for all properties at once! This violates the interface contract!" );
505 : }
506 0 : }
507 0 : }
508 :
509 : //--------------------------------------------------------------------
510 0 : void SAL_CALL GenericPropertyHandler::removePropertyChangeListener( const Reference< XPropertyChangeListener >& _rxListener ) throw (RuntimeException)
511 : {
512 0 : ::osl::MutexGuard aGuard( m_aMutex );
513 0 : if ( m_xComponent.is() )
514 : {
515 : try
516 : {
517 0 : m_xComponent->removePropertyChangeListener( ::rtl::OUString(), _rxListener );
518 : }
519 0 : catch( const UnknownPropertyException& )
520 : {
521 : OSL_FAIL( "GenericPropertyHandler::removePropertyChangeListener:\nThe inspected component does not allow de-registering for all properties at once! This violates the interface contract!" );
522 : }
523 : }
524 0 : m_aPropertyListeners.removeInterface( _rxListener );
525 0 : }
526 :
527 : //--------------------------------------------------------------------
528 0 : void GenericPropertyHandler::impl_ensurePropertyMap()
529 : {
530 0 : if ( !m_bPropertyMapInitialized )
531 : {
532 0 : m_bPropertyMapInitialized = true;
533 : try
534 : {
535 0 : Reference< XPropertySetInfo > xPSI;
536 0 : if ( m_xComponent.is() )
537 0 : xPSI = m_xComponent->getPropertySetInfo();
538 0 : Sequence< Property > aProperties;
539 0 : if ( xPSI.is() )
540 0 : aProperties = xPSI->getProperties();
541 : DBG_ASSERT( aProperties.getLength(), "GenericPropertyHandler::getSupportedProperties: no properties!" );
542 :
543 0 : for ( const Property* pProperties = aProperties.getConstArray();
544 0 : pProperties != aProperties.getConstArray() + aProperties.getLength();
545 : ++pProperties
546 : )
547 : {
548 0 : switch ( pProperties->Type.getTypeClass() )
549 : {
550 : case TypeClass_BOOLEAN:
551 : case TypeClass_BYTE:
552 : case TypeClass_SHORT:
553 : case TypeClass_UNSIGNED_SHORT:
554 : case TypeClass_LONG:
555 : case TypeClass_UNSIGNED_LONG:
556 : case TypeClass_HYPER:
557 : case TypeClass_UNSIGNED_HYPER:
558 : case TypeClass_FLOAT:
559 : case TypeClass_DOUBLE:
560 : case TypeClass_ENUM:
561 : case TypeClass_STRING:
562 : // allowed, we can handle this type
563 0 : break;
564 :
565 : case TypeClass_SEQUENCE:
566 : {
567 0 : TypeClass eElementTypeClass = ::comphelper::getSequenceElementType( pProperties->Type ).getTypeClass();
568 0 : if ( ( eElementTypeClass != TypeClass_STRING )
569 : && ( eElementTypeClass != TypeClass_BYTE )
570 : && ( eElementTypeClass != TypeClass_SHORT )
571 : && ( eElementTypeClass != TypeClass_UNSIGNED_SHORT )
572 : && ( eElementTypeClass != TypeClass_LONG )
573 : && ( eElementTypeClass != TypeClass_UNSIGNED_LONG )
574 : )
575 : // can only handle the above
576 0 : continue;
577 : }
578 0 : break;
579 :
580 : default:
581 : // next property, we don't support this type
582 0 : continue;
583 : }
584 :
585 0 : m_aProperties.insert( PropertyMap::value_type( pProperties->Name, *pProperties ) );
586 0 : }
587 : }
588 0 : catch( const Exception& )
589 : {
590 : OSL_FAIL( "GenericPropertyHandler::impl_ensurePropertyMap: caught an exception!" );
591 : }
592 : }
593 0 : }
594 :
595 : //--------------------------------------------------------------------
596 0 : Sequence< Property > SAL_CALL GenericPropertyHandler::getSupportedProperties() throw (RuntimeException)
597 : {
598 0 : ::osl::MutexGuard aGuard( m_aMutex );
599 0 : const_cast< GenericPropertyHandler* >( this )->impl_ensurePropertyMap();
600 :
601 0 : Sequence< Property > aReturn( m_aProperties.size() );
602 : ::std::transform( m_aProperties.begin(), m_aProperties.end(),
603 0 : aReturn.getArray(), ::o3tl::select2nd< PropertyMap::value_type >() );
604 0 : return aReturn;
605 : }
606 :
607 : //--------------------------------------------------------------------
608 0 : Sequence< ::rtl::OUString > SAL_CALL GenericPropertyHandler::getSupersededProperties( ) throw (RuntimeException)
609 : {
610 : // no superseded properties at all. This handler offers the very basic PropertyHandler
611 : // functionality, so it's much more likely that other handlers want to supersede
612 : // *our* properties ....
613 0 : return Sequence< ::rtl::OUString >( );
614 : }
615 :
616 : //--------------------------------------------------------------------
617 0 : Sequence< ::rtl::OUString > SAL_CALL GenericPropertyHandler::getActuatingProperties( ) throw (RuntimeException)
618 : {
619 : // This basic PropertyHandler implementation is too dumb^Wgeneric to know
620 : // anything about property dependencies
621 0 : return Sequence< ::rtl::OUString >( );
622 : }
623 :
624 : //--------------------------------------------------------------------
625 0 : LineDescriptor SAL_CALL GenericPropertyHandler::describePropertyLine( const ::rtl::OUString& _rPropertyName,
626 : const Reference< XPropertyControlFactory >& _rxControlFactory )
627 : throw (UnknownPropertyException, NullPointerException, RuntimeException)
628 : {
629 0 : if ( !_rxControlFactory.is() )
630 0 : throw NullPointerException();
631 :
632 0 : ::osl::MutexGuard aGuard( m_aMutex );
633 0 : const_cast< GenericPropertyHandler* >( this )->impl_ensurePropertyMap();
634 :
635 0 : PropertyMap::const_iterator pos = m_aProperties.find( _rPropertyName );
636 0 : if ( pos == m_aProperties.end() )
637 0 : throw UnknownPropertyException();
638 :
639 0 : LineDescriptor aDescriptor;
640 0 : aDescriptor.DisplayName = _rPropertyName;
641 0 : switch ( pos->second.Type.getTypeClass() )
642 : {
643 : case TypeClass_ENUM:
644 : aDescriptor.Control = PropertyHandlerHelper::createListBoxControl( _rxControlFactory,
645 0 : impl_getEnumConverter( pos->second.Type )->getDescriptions(),
646 0 : PropertyHandlerHelper::requiresReadOnlyControl( pos->second.Attributes ),
647 0 : sal_False );
648 0 : break;
649 : case TypeClass_STRING:
650 : {
651 : // some special handling for URL properties
652 0 : bool bIsURLProperty = ( _rPropertyName.getLength() >= 3 ) && _rPropertyName.matchAsciiL( "URL", 3, _rPropertyName.getLength() - 3 );
653 0 : if ( bIsURLProperty )
654 : {
655 0 : aDescriptor.Control = _rxControlFactory->createPropertyControl(
656 0 : PropertyControlType::HyperlinkField, PropertyHandlerHelper::requiresReadOnlyControl( pos->second.Attributes ) );
657 :
658 0 : Reference< XHyperlinkControl > xControl( aDescriptor.Control, UNO_QUERY_THROW );
659 0 : Reference< XActionListener > xEnsureDelete( new UrlClickHandler( m_aContext, xControl ) );
660 : }
661 : }
662 0 : break;
663 : default:
664 0 : break;
665 : }
666 : // fallback
667 0 : if ( !aDescriptor.Control.is() )
668 0 : PropertyHandlerHelper::describePropertyLine( pos->second, aDescriptor, _rxControlFactory );
669 :
670 0 : aDescriptor.Category = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "General" ) );
671 0 : return aDescriptor;
672 : }
673 :
674 : //--------------------------------------------------------------------
675 0 : ::sal_Bool SAL_CALL GenericPropertyHandler::isComposable( const ::rtl::OUString& /*_rPropertyName*/ ) throw (UnknownPropertyException, RuntimeException)
676 : {
677 0 : return sal_False;
678 : }
679 :
680 : //--------------------------------------------------------------------
681 0 : InteractiveSelectionResult SAL_CALL GenericPropertyHandler::onInteractivePropertySelection( const ::rtl::OUString& /*_rPropertyName*/, sal_Bool /*_bPrimary*/, Any& /*_rData*/, const Reference< XObjectInspectorUI >& /*_rxInspectorUI*/ ) throw (UnknownPropertyException, NullPointerException, RuntimeException)
682 : {
683 : OSL_FAIL( "GenericPropertyHandler::onInteractivePropertySelection: I'm too dumb to know anything about property browse buttons!" );
684 0 : return InteractiveSelectionResult_Cancelled;
685 : }
686 :
687 : //--------------------------------------------------------------------
688 0 : void SAL_CALL GenericPropertyHandler::actuatingPropertyChanged( const ::rtl::OUString& /*_rActuatingPropertyName*/, const Any& /*_rNewValue*/, const Any& /*_rOldValue*/, const Reference< XObjectInspectorUI >& /*_rxInspectorUI*/, sal_Bool /*_bFirstTimeInit*/ ) throw (NullPointerException, RuntimeException)
689 : {
690 : OSL_FAIL( "GenericPropertyHandler::actuatingPropertyChanged: no no no, I did not register for any actuating properties!" );
691 0 : }
692 :
693 : //--------------------------------------------------------------------
694 0 : sal_Bool SAL_CALL GenericPropertyHandler::suspend( sal_Bool /*_bSuspend*/ ) throw (RuntimeException)
695 : {
696 0 : return sal_True;
697 : }
698 :
699 : //--------------------------------------------------------------------
700 0 : void SAL_CALL GenericPropertyHandler::disposing()
701 : {
702 0 : m_aPropertyListeners.clear();
703 : // not disposeAndClear: the listeners are (virtually) listeners at our introspectee, not
704 : // at this handler instance
705 0 : }
706 :
707 : //--------------------------------------------------------------------
708 0 : IMPLEMENT_FORWARD_XCOMPONENT( GenericPropertyHandler, GenericPropertyHandler_Base );
709 :
710 : //........................................................................
711 : } // namespace pcr
712 : //........................................................................
713 :
714 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|