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