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