1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "osl/diagnose.h"
22 #include "cppuhelper/implbase1.hxx"
23 #include "cppuhelper/weak.hxx"
24 #include "cppuhelper/propshlp.hxx"
25 #include "cppuhelper/exc_hlp.hxx"
26 #include "com/sun/star/beans/PropertyAttribute.hpp"
27 #include "com/sun/star/lang/DisposedException.hpp"
31 using namespace com::sun::star::uno
;
32 using namespace com::sun::star::beans
;
33 using namespace com::sun::star::lang
;
36 using ::rtl::OUString
;
40 IPropertyArrayHelper::~IPropertyArrayHelper()
44 inline const ::com::sun::star::uno::Type
& getPropertyTypeIdentifier( ) SAL_THROW(())
46 return ::getCppuType( (Reference
< XPropertyChangeListener
> *)0 );
48 inline const ::com::sun::star::uno::Type
& getPropertiesTypeIdentifier() SAL_THROW(())
50 return ::getCppuType( (Reference
< XPropertiesChangeListener
> *)0 );
52 inline const ::com::sun::star::uno::Type
& getVetoableTypeIdentifier() SAL_THROW(())
54 return ::getCppuType( (Reference
< XVetoableChangeListener
> *)0 );
59 static int compare_OUString_Property_Impl( const void *arg1
, const void *arg2
)
62 return ((OUString
*)arg1
)->compareTo( ((Property
*)arg2
)->Name
);
68 * The class which implements the PropertySetInfo interface.
71 class OPropertySetHelperInfo_Impl
72 : public WeakImplHelper1
< ::com::sun::star::beans::XPropertySetInfo
>
74 Sequence
< Property
> aInfos
;
77 OPropertySetHelperInfo_Impl( IPropertyArrayHelper
& rHelper_
) SAL_THROW(());
79 // XPropertySetInfo-methods
80 virtual Sequence
< Property
> SAL_CALL
getProperties(void) throw(::com::sun::star::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
81 virtual Property SAL_CALL
getPropertyByName(const OUString
& PropertyName
) throw(::com::sun::star::beans::UnknownPropertyException
, ::com::sun::star::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
82 virtual sal_Bool SAL_CALL
hasPropertyByName(const OUString
& PropertyName
) throw(::com::sun::star::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
87 * Create an object that implements XPropertySetInfo IPropertyArrayHelper.
89 OPropertySetHelperInfo_Impl::OPropertySetHelperInfo_Impl(
90 IPropertyArrayHelper
& rHelper_
)
92 :aInfos( rHelper_
.getProperties() )
97 * Return the sequence of properties, which are provided throug the constructor.
99 Sequence
< Property
> OPropertySetHelperInfo_Impl::getProperties(void) throw(::com::sun::star::uno::RuntimeException
, std::exception
)
106 * Return the sequence of properties, which are provided throug the constructor.
108 Property
OPropertySetHelperInfo_Impl::getPropertyByName( const OUString
& PropertyName
) throw(::com::sun::star::beans::UnknownPropertyException
, ::com::sun::star::uno::RuntimeException
, std::exception
)
111 pR
= (Property
*)bsearch( &PropertyName
, aInfos
.getConstArray(), aInfos
.getLength(),
113 compare_OUString_Property_Impl
);
115 throw UnknownPropertyException();
122 * Return the sequence of properties, which are provided throug the constructor.
124 sal_Bool
OPropertySetHelperInfo_Impl::hasPropertyByName( const OUString
& PropertyName
) throw(::com::sun::star::uno::RuntimeException
, std::exception
)
127 pR
= (Property
*)bsearch( &PropertyName
, aInfos
.getConstArray(), aInfos
.getLength(),
129 compare_OUString_Property_Impl
);
134 // class PropertySetHelper_Impl
136 class OPropertySetHelper::Impl
{
139 Impl( bool i_bIgnoreRuntimeExceptionsWhileFiring
,
140 IEventNotificationHook
*i_pFireEvents
142 :m_bIgnoreRuntimeExceptionsWhileFiring( i_bIgnoreRuntimeExceptionsWhileFiring
)
144 ,m_pFireEvents( i_pFireEvents
)
148 bool m_bIgnoreRuntimeExceptionsWhileFiring
;
150 class IEventNotificationHook
* const m_pFireEvents
;
152 ::std::vector
< sal_Int32
> m_handles
;
153 ::std::vector
< Any
> m_newValues
;
154 ::std::vector
< Any
> m_oldValues
;
159 // class PropertySetHelper
161 OPropertySetHelper::OPropertySetHelper(
162 OBroadcastHelper
& rBHelper_
) SAL_THROW(())
163 : rBHelper( rBHelper_
),
164 aBoundLC( rBHelper_
.rMutex
),
165 aVetoableLC( rBHelper_
.rMutex
),
166 m_pReserved( new Impl(false, 0) )
170 OPropertySetHelper::OPropertySetHelper(
171 OBroadcastHelper
& rBHelper_
, bool bIgnoreRuntimeExceptionsWhileFiring
)
172 : rBHelper( rBHelper_
),
173 aBoundLC( rBHelper_
.rMutex
),
174 aVetoableLC( rBHelper_
.rMutex
),
175 m_pReserved( new Impl( bIgnoreRuntimeExceptionsWhileFiring
, 0 ) )
179 OPropertySetHelper::OPropertySetHelper(
180 OBroadcastHelper
& rBHelper_
, IEventNotificationHook
* i_pFireEvents
,
181 bool bIgnoreRuntimeExceptionsWhileFiring
)
182 : rBHelper( rBHelper_
),
183 aBoundLC( rBHelper_
.rMutex
),
184 aVetoableLC( rBHelper_
.rMutex
),
186 new Impl( bIgnoreRuntimeExceptionsWhileFiring
, i_pFireEvents
) )
190 OPropertySetHelper2::OPropertySetHelper2(
191 OBroadcastHelper
& irBHelper
,
192 IEventNotificationHook
*i_pFireEvents
,
193 bool bIgnoreRuntimeExceptionsWhileFiring
)
194 :OPropertySetHelper( irBHelper
, i_pFireEvents
, bIgnoreRuntimeExceptionsWhileFiring
)
199 * You must call disposing before.
201 OPropertySetHelper::~OPropertySetHelper() SAL_THROW(())
204 OPropertySetHelper2::~OPropertySetHelper2() SAL_THROW(())
209 Any
OPropertySetHelper::queryInterface( const ::com::sun::star::uno::Type
& rType
)
210 throw (RuntimeException
, std::exception
)
212 return ::cppu::queryInterface(
214 static_cast< XPropertySet
* >( this ),
215 static_cast< XMultiPropertySet
* >( this ),
216 static_cast< XFastPropertySet
* >( this ) );
219 Any
OPropertySetHelper2::queryInterface( const ::com::sun::star::uno::Type
& rType
)
220 throw (RuntimeException
, std::exception
)
222 Any
cnd(cppu::queryInterface(rType
, static_cast< XPropertySetOption
* >(this)));
223 if ( cnd
.hasValue() )
226 return OPropertySetHelper::queryInterface(rType
);
230 * called from the derivee's XTypeProvider::getTypes implementation
232 ::com::sun::star::uno::Sequence
< ::com::sun::star::uno::Type
> OPropertySetHelper::getTypes()
233 throw (RuntimeException
)
235 Sequence
< ::com::sun::star::uno::Type
> aTypes( 4 );
236 aTypes
[ 0 ] = XPropertySet::static_type();
237 aTypes
[ 1 ] = XPropertySetOption::static_type();
238 aTypes
[ 2 ] = XMultiPropertySet::static_type();
239 aTypes
[ 3 ] = XFastPropertySet::static_type();
244 void OPropertySetHelper::disposing() SAL_THROW(())
246 // Create an event with this as sender
247 Reference
< XPropertySet
> rSource( (static_cast< XPropertySet
* >(this)) , UNO_QUERY
);
249 aEvt
.Source
= rSource
;
251 // inform all listeners to release this object
252 // The listener containers are automatically cleared
253 aBoundLC
.disposeAndClear( aEvt
);
254 aVetoableLC
.disposeAndClear( aEvt
);
257 Reference
< XPropertySetInfo
> OPropertySetHelper::createPropertySetInfo(
258 IPropertyArrayHelper
& rProperties
) SAL_THROW(())
260 return static_cast< XPropertySetInfo
* >( new OPropertySetHelperInfo_Impl( rProperties
) );
264 void OPropertySetHelper::setPropertyValue(
265 const OUString
& rPropertyName
, const Any
& rValue
)
266 throw(::com::sun::star::beans::UnknownPropertyException
, ::com::sun::star::beans::PropertyVetoException
, ::com::sun::star::lang::IllegalArgumentException
, ::com::sun::star::lang::WrappedTargetException
, ::com::sun::star::uno::RuntimeException
, std::exception
)
269 IPropertyArrayHelper
& rPH
= getInfoHelper();
270 // map the name to the handle
271 sal_Int32 nHandle
= rPH
.getHandleByName( rPropertyName
);
272 // call the method of the XFastPropertySet interface
273 setFastPropertyValue( nHandle
, rValue
);
277 Any
OPropertySetHelper::getPropertyValue(
278 const OUString
& rPropertyName
)
279 throw(::com::sun::star::beans::UnknownPropertyException
, ::com::sun::star::lang::WrappedTargetException
, ::com::sun::star::uno::RuntimeException
, std::exception
)
282 IPropertyArrayHelper
& rPH
= getInfoHelper();
283 // map the name to the handle
284 sal_Int32 nHandle
= rPH
.getHandleByName( rPropertyName
);
285 // call the method of the XFastPropertySet interface
286 return getFastPropertyValue( nHandle
);
290 void OPropertySetHelper::addPropertyChangeListener(
291 const OUString
& rPropertyName
,
292 const Reference
< XPropertyChangeListener
> & rxListener
)
293 throw(::com::sun::star::beans::UnknownPropertyException
,
294 ::com::sun::star::lang::WrappedTargetException
,
295 ::com::sun::star::uno::RuntimeException
, std::exception
)
297 MutexGuard
aGuard( rBHelper
.rMutex
);
298 OSL_ENSURE( !rBHelper
.bInDispose
, "do not addPropertyChangeListener in the dispose call" );
299 OSL_ENSURE( !rBHelper
.bDisposed
, "object is disposed" );
300 if( !rBHelper
.bInDispose
&& !rBHelper
.bDisposed
)
302 // only add listeners if you are not disposed
303 // a listener with no name means all properties
304 if( !rPropertyName
.isEmpty() )
307 IPropertyArrayHelper
& rPH
= getInfoHelper();
308 // map the name to the handle
309 sal_Int32 nHandle
= rPH
.getHandleByName( rPropertyName
);
310 if( nHandle
== -1 ) {
311 // property not known throw exception
312 throw UnknownPropertyException() ;
315 sal_Int16 nAttributes
;
316 rPH
.fillPropertyMembersByHandle( NULL
, &nAttributes
, nHandle
);
317 if( !(nAttributes
& ::com::sun::star::beans::PropertyAttribute::BOUND
) )
319 OSL_FAIL( "add listener to an unbound property" );
320 // silent ignore this
323 // add the change listener to the helper container
325 aBoundLC
.addInterface( (sal_Int32
)nHandle
, rxListener
);
328 // add the change listener to the helper container
329 rBHelper
.aLC
.addInterface(
330 getPropertyTypeIdentifier( ),
338 void OPropertySetHelper::removePropertyChangeListener(
339 const OUString
& rPropertyName
,
340 const Reference
< XPropertyChangeListener
>& rxListener
)
341 throw(::com::sun::star::beans::UnknownPropertyException
,
342 ::com::sun::star::lang::WrappedTargetException
,
343 ::com::sun::star::uno::RuntimeException
, std::exception
)
345 MutexGuard
aGuard( rBHelper
.rMutex
);
346 OSL_ENSURE( !rBHelper
.bDisposed
, "object is disposed" );
347 // all listeners are automatically released in a dispose call
348 if( !rBHelper
.bInDispose
&& !rBHelper
.bDisposed
)
350 if( !rPropertyName
.isEmpty() )
353 IPropertyArrayHelper
& rPH
= getInfoHelper();
354 // map the name to the handle
355 sal_Int32 nHandle
= rPH
.getHandleByName( rPropertyName
);
357 // property not known throw exception
358 throw UnknownPropertyException();
359 aBoundLC
.removeInterface( (sal_Int32
)nHandle
, rxListener
);
362 // remove the change listener to the helper container
363 rBHelper
.aLC
.removeInterface(
364 getPropertyTypeIdentifier( ),
372 void OPropertySetHelper::addVetoableChangeListener(
373 const OUString
& rPropertyName
,
374 const Reference
< XVetoableChangeListener
> & rxListener
)
375 throw(::com::sun::star::beans::UnknownPropertyException
,
376 ::com::sun::star::lang::WrappedTargetException
,
377 ::com::sun::star::uno::RuntimeException
, std::exception
)
379 MutexGuard
aGuard( rBHelper
.rMutex
);
380 OSL_ENSURE( !rBHelper
.bInDispose
, "do not addVetoableChangeListener in the dispose call" );
381 OSL_ENSURE( !rBHelper
.bDisposed
, "object is disposed" );
382 if( !rBHelper
.bInDispose
&& !rBHelper
.bDisposed
)
384 // only add listeners if you are not disposed
385 // a listener with no name means all properties
386 if( !rPropertyName
.isEmpty() )
389 IPropertyArrayHelper
& rPH
= getInfoHelper();
390 // map the name to the handle
391 sal_Int32 nHandle
= rPH
.getHandleByName( rPropertyName
);
392 if( nHandle
== -1 ) {
393 // property not known throw exception
394 throw UnknownPropertyException();
397 sal_Int16 nAttributes
;
398 rPH
.fillPropertyMembersByHandle( NULL
, &nAttributes
, nHandle
);
399 if( !(nAttributes
& PropertyAttribute::CONSTRAINED
) )
401 OSL_FAIL( "addVetoableChangeListener, and property is not constrained" );
402 // silent ignore this
405 // add the vetoable listener to the helper container
406 aVetoableLC
.addInterface( (sal_Int32
)nHandle
, rxListener
);
409 // add the vetoable listener to the helper container
410 rBHelper
.aLC
.addInterface(
411 getVetoableTypeIdentifier( ),
418 void OPropertySetHelper::removeVetoableChangeListener(
419 const OUString
& rPropertyName
,
420 const Reference
< XVetoableChangeListener
> & rxListener
)
421 throw(::com::sun::star::beans::UnknownPropertyException
,
422 ::com::sun::star::lang::WrappedTargetException
,
423 ::com::sun::star::uno::RuntimeException
, std::exception
)
425 MutexGuard
aGuard( rBHelper
.rMutex
);
426 OSL_ENSURE( !rBHelper
.bDisposed
, "object is disposed" );
427 // all listeners are automatically released in a dispose call
428 if( !rBHelper
.bInDispose
&& !rBHelper
.bDisposed
)
430 if( !rPropertyName
.isEmpty() )
433 IPropertyArrayHelper
& rPH
= getInfoHelper();
434 // map the name to the handle
435 sal_Int32 nHandle
= rPH
.getHandleByName( rPropertyName
);
436 if( nHandle
== -1 ) {
437 // property not known throw exception
438 throw UnknownPropertyException();
440 // remove the vetoable listener to the helper container
441 aVetoableLC
.removeInterface( (sal_Int32
)nHandle
, rxListener
);
444 // add the vetoable listener to the helper container
445 rBHelper
.aLC
.removeInterface(
446 getVetoableTypeIdentifier( ),
452 void OPropertySetHelper::setDependentFastPropertyValue( sal_Int32 i_handle
, const ::com::sun::star::uno::Any
& i_value
)
454 //OSL_PRECOND( rBHelper.rMutex.isAcquired(), "OPropertySetHelper::setDependentFastPropertyValue: to be called with a locked mutex only!" );
455 // there is no such thing as Mutex.isAcquired, sadly ...
457 sal_Int16
nAttributes(0);
458 IPropertyArrayHelper
& rInfo
= getInfoHelper();
459 if ( !rInfo
.fillPropertyMembersByHandle( NULL
, &nAttributes
, i_handle
) )
461 throw UnknownPropertyException();
463 // no need to check for READONLY-ness of the property. The method is intended to be called internally, which
464 // implies it might be invoked for properties which are read-only to the instance's clients, but well allowed
465 // to change their value.
467 Any aConverted
, aOld
;
468 bool bChanged
= convertFastPropertyValue( aConverted
, aOld
, i_handle
, i_value
);
472 // don't fire vetoable events. This method is called with our mutex locked, so calling into listeners would not be
473 // a good idea. The caler is responsible for not invoking this for constrained properties.
474 OSL_ENSURE( ( nAttributes
& PropertyAttribute::CONSTRAINED
) == 0,
475 "OPropertySetHelper::setDependentFastPropertyValue: not to be used for constrained properties!" );
478 // actually set the new value
481 setFastPropertyValue_NoBroadcast( i_handle
, aConverted
);
483 catch (const UnknownPropertyException
& ) { throw; /* allowed to leave */ }
484 catch (const PropertyVetoException
& ) { throw; /* allowed to leave */ }
485 catch (const IllegalArgumentException
& ) { throw; /* allowed to leave */ }
486 catch (const WrappedTargetException
& ) { throw; /* allowed to leave */ }
487 catch (const RuntimeException
& ) { throw; /* allowed to leave */ }
488 catch (const Exception
& )
490 // not allowed to leave this meathod
491 WrappedTargetException aWrapped
;
492 aWrapped
.TargetException
<<= ::cppu::getCaughtException();
493 aWrapped
.Context
= static_cast< XPropertySet
* >( this );
497 // remember the handle/values, for the events to be fired later
498 m_pReserved
->m_handles
.push_back( i_handle
);
499 m_pReserved
->m_newValues
.push_back( aConverted
); // TODO: setFastPropertyValue notifies the unconverted value here ...?
500 m_pReserved
->m_oldValues
.push_back( aOld
);
504 void OPropertySetHelper::setFastPropertyValue( sal_Int32 nHandle
, const Any
& rValue
)
505 throw(::com::sun::star::beans::UnknownPropertyException
,
506 ::com::sun::star::beans::PropertyVetoException
,
507 ::com::sun::star::lang::IllegalArgumentException
,
508 ::com::sun::star::lang::WrappedTargetException
,
509 ::com::sun::star::uno::RuntimeException
, std::exception
)
511 OSL_ENSURE( !rBHelper
.bInDispose
, "do not setFastPropertyValue in the dispose call" );
512 OSL_ENSURE( !rBHelper
.bDisposed
, "object is disposed" );
514 IPropertyArrayHelper
& rInfo
= getInfoHelper();
515 sal_Int16 nAttributes
;
516 if( !rInfo
.fillPropertyMembersByHandle( NULL
, &nAttributes
, nHandle
) ) {
518 throw UnknownPropertyException();
520 if( nAttributes
& PropertyAttribute::READONLY
)
521 throw PropertyVetoException();
526 // Will the property change?
529 MutexGuard
aGuard( rBHelper
.rMutex
);
530 bChanged
= convertFastPropertyValue( aConvertedVal
, aOldVal
, nHandle
, rValue
);
531 // release guard to fire events
535 // Is it a constrained property?
536 if( nAttributes
& PropertyAttribute::CONSTRAINED
)
538 // In aValue is the converted rValue
539 // fire a constarined event
540 // second parameter NULL means constrained
541 fire( &nHandle
, &rValue
, &aOldVal
, 1, sal_True
);
545 MutexGuard
aGuard( rBHelper
.rMutex
);
548 // set the property to the new value
549 setFastPropertyValue_NoBroadcast( nHandle
, aConvertedVal
);
551 catch (const ::com::sun::star::beans::UnknownPropertyException
& ) { throw; /* allowed to leave */ }
552 catch (const ::com::sun::star::beans::PropertyVetoException
& ) { throw; /* allowed to leave */ }
553 catch (const ::com::sun::star::lang::IllegalArgumentException
& ) { throw; /* allowed to leave */ }
554 catch (const ::com::sun::star::lang::WrappedTargetException
& ) { throw; /* allowed to leave */ }
555 catch (const ::com::sun::star::uno::RuntimeException
& ) { throw; /* allowed to leave */ }
556 catch (const ::com::sun::star::uno::Exception
& e
)
558 // not allowed to leave this meathod
559 ::com::sun::star::lang::WrappedTargetException aWrap
;
560 aWrap
.Context
= static_cast< ::com::sun::star::beans::XPropertySet
* >( this );
561 aWrap
.TargetException
<<= e
;
563 throw ::com::sun::star::lang::WrappedTargetException( aWrap
);
566 // release guard to fire events
568 // file a change event, if the value changed
569 impl_fireAll( &nHandle
, &rValue
, &aOldVal
, 1 );
574 Any
OPropertySetHelper::getFastPropertyValue( sal_Int32 nHandle
)
575 throw(::com::sun::star::beans::UnknownPropertyException
,
576 ::com::sun::star::lang::WrappedTargetException
,
577 ::com::sun::star::uno::RuntimeException
, std::exception
)
580 IPropertyArrayHelper
& rInfo
= getInfoHelper();
581 if( !rInfo
.fillPropertyMembersByHandle( NULL
, NULL
, nHandle
) )
583 throw UnknownPropertyException();
586 MutexGuard
aGuard( rBHelper
.rMutex
);
587 getFastPropertyValue( aRet
, nHandle
);
592 void OPropertySetHelper::impl_fireAll( sal_Int32
* i_handles
, const Any
* i_newValues
, const Any
* i_oldValues
, sal_Int32 i_count
)
594 ClearableMutexGuard
aGuard( rBHelper
.rMutex
);
595 if ( m_pReserved
->m_handles
.empty() )
598 fire( i_handles
, i_newValues
, i_oldValues
, i_count
, sal_False
);
602 const size_t additionalEvents
= m_pReserved
->m_handles
.size();
603 OSL_ENSURE( additionalEvents
== m_pReserved
->m_newValues
.size()
604 && additionalEvents
== m_pReserved
->m_oldValues
.size(),
605 "OPropertySetHelper::impl_fireAll: inconsistency!" );
607 ::std::vector
< sal_Int32
> allHandles( additionalEvents
+ i_count
);
608 ::std::copy( m_pReserved
->m_handles
.begin(), m_pReserved
->m_handles
.end(), allHandles
.begin() );
609 ::std::copy( i_handles
, i_handles
+ i_count
, allHandles
.begin() + additionalEvents
);
611 ::std::vector
< Any
> allNewValues( additionalEvents
+ i_count
);
612 ::std::copy( m_pReserved
->m_newValues
.begin(), m_pReserved
->m_newValues
.end(), allNewValues
.begin() );
613 ::std::copy( i_newValues
, i_newValues
+ i_count
, allNewValues
.begin() + additionalEvents
);
615 ::std::vector
< Any
> allOldValues( additionalEvents
+ i_count
);
616 ::std::copy( m_pReserved
->m_oldValues
.begin(), m_pReserved
->m_oldValues
.end(), allOldValues
.begin() );
617 ::std::copy( i_oldValues
, i_oldValues
+ i_count
, allOldValues
.begin() + additionalEvents
);
619 m_pReserved
->m_handles
.clear();
620 m_pReserved
->m_newValues
.clear();
621 m_pReserved
->m_oldValues
.clear();
624 fire( &allHandles
[0], &allNewValues
[0], &allOldValues
[0], additionalEvents
+ i_count
, sal_False
);
628 void OPropertySetHelper::fire
630 sal_Int32
* pnHandles
,
631 const Any
* pNewValues
,
632 const Any
* pOldValues
,
633 sal_Int32 nHandles
, // These is the Count of the array
637 OSL_ENSURE( m_pReserved
.get(), "No OPropertySetHelper::Impl" );
639 if (! m_pReserved
->m_bFireEvents
)
642 if (m_pReserved
->m_pFireEvents
) {
643 m_pReserved
->m_pFireEvents
->fireEvents(
644 pnHandles
, nHandles
, bVetoable
,
645 m_pReserved
->m_bIgnoreRuntimeExceptionsWhileFiring
);
648 // Only fire, if one or more properties changed
651 // create the event sequence of all changed properties
652 Sequence
< PropertyChangeEvent
> aEvts( nHandles
);
653 PropertyChangeEvent
* pEvts
= aEvts
.getArray();
654 Reference
< XInterface
> xSource( (XPropertySet
*)this, UNO_QUERY
);
656 sal_Int32 nChangesLen
= 0;
657 // Loop over all changed properties to fill the event struct
658 for( i
= 0; i
< nHandles
; i
++ )
660 // Vetoable fire and constrained attribute set or
661 // Change fire and Changed and bound attribute set
662 IPropertyArrayHelper
& rInfo
= getInfoHelper();
663 sal_Int16 nAttributes
;
665 rInfo
.fillPropertyMembersByHandle( &aPropName
, &nAttributes
, pnHandles
[i
] );
668 (bVetoable
&& (nAttributes
& PropertyAttribute::CONSTRAINED
)) ||
669 (!bVetoable
&& (nAttributes
& PropertyAttribute::BOUND
))
672 pEvts
[nChangesLen
].Source
= xSource
;
673 pEvts
[nChangesLen
].PropertyName
= aPropName
;
674 pEvts
[nChangesLen
].PropertyHandle
= pnHandles
[i
];
675 pEvts
[nChangesLen
].OldValue
= pOldValues
[i
];
676 pEvts
[nChangesLen
].NewValue
= pNewValues
[i
];
681 bool bIgnoreRuntimeExceptionsWhileFiring
=
682 m_pReserved
->m_bIgnoreRuntimeExceptionsWhileFiring
;
684 // fire the events for all changed properties
685 for( i
= 0; i
< nChangesLen
; i
++ )
687 // get the listener container for the property name
688 OInterfaceContainerHelper
* pLC
;
689 if( bVetoable
) // fire change Events?
690 pLC
= aVetoableLC
.getContainer( pEvts
[i
].PropertyHandle
);
692 pLC
= aBoundLC
.getContainer( pEvts
[i
].PropertyHandle
);
695 // Iterate over all listeners and send events
696 OInterfaceIteratorHelper
aIt( *pLC
);
697 while( aIt
.hasMoreElements() )
699 XInterface
* pL
= aIt
.next();
704 if( bVetoable
) // fire change Events?
706 ((XVetoableChangeListener
*)pL
)->vetoableChange(
711 ((XPropertyChangeListener
*)pL
)->propertyChange(
715 catch (DisposedException
& exc
)
717 OSL_ENSURE( exc
.Context
.is(),
718 "DisposedException without Context!" );
719 if (exc
.Context
== pL
)
725 catch (RuntimeException
& exc
)
727 SAL_INFO("cppuhelper", "caught RuntimeException while firing listeners: " << exc
.Message
);
728 if (! bIgnoreRuntimeExceptionsWhileFiring
)
733 // broadcast to all listeners with "" property name
735 // fire change Events?
736 pLC
= rBHelper
.aLC
.getContainer(
737 getVetoableTypeIdentifier()
741 pLC
= rBHelper
.aLC
.getContainer(
742 getPropertyTypeIdentifier( )
747 // Iterate over all listeners and send events.
748 OInterfaceIteratorHelper
aIt( *pLC
);
749 while( aIt
.hasMoreElements() )
751 XInterface
* pL
= aIt
.next();
756 if( bVetoable
) // fire change Events?
758 ((XVetoableChangeListener
*)pL
)->vetoableChange(
763 ((XPropertyChangeListener
*)pL
)->propertyChange(
767 catch (DisposedException
& exc
)
769 OSL_ENSURE( exc
.Context
.is(),
770 "DisposedException without Context!" );
771 if (exc
.Context
== pL
)
777 catch (RuntimeException
& exc
)
779 SAL_INFO("cppuhelper", "caught RuntimeException while firing listeners: " << exc
.Message
);
780 if (! bIgnoreRuntimeExceptionsWhileFiring
)
787 // reduce array to changed properties
788 aEvts
.realloc( nChangesLen
);
792 OInterfaceContainerHelper
* pCont
= 0;
793 pCont
= rBHelper
.aLC
.getContainer(
794 getPropertiesTypeIdentifier( )
798 // Here is a Bug, unbound properties are also fired
799 OInterfaceIteratorHelper
aIt( *pCont
);
800 while( aIt
.hasMoreElements() )
802 XPropertiesChangeListener
* pL
=
803 (XPropertiesChangeListener
*)aIt
.next();
808 // fire the hole event sequence to the
809 // XPropertiesChangeListener's
810 pL
->propertiesChange( aEvts
);
812 catch (DisposedException
& exc
)
814 OSL_ENSURE( exc
.Context
.is(),
815 "DisposedException without Context!" );
816 if (exc
.Context
== pL
)
822 catch (RuntimeException
& exc
)
824 SAL_INFO("cppuhelper", "caught RuntimeException while firing listeners: " << exc
.Message
);
825 if (! bIgnoreRuntimeExceptionsWhileFiring
)
834 // OPropertySetHelper
835 void OPropertySetHelper::setFastPropertyValues(
837 sal_Int32
* pHandles
,
839 sal_Int32 nHitCount
)
840 SAL_THROW( (::com::sun::star::uno::Exception
) )
842 OSL_ENSURE( !rBHelper
.bInDispose
, "do not getFastPropertyValue in the dispose call" );
843 OSL_ENSURE( !rBHelper
.bDisposed
, "object is disposed" );
845 Any
* pConvertedValues
= NULL
;
846 Any
* pOldValues
= NULL
;
851 IPropertyArrayHelper
& rPH
= getInfoHelper();
853 pConvertedValues
= new Any
[ nHitCount
];
854 pOldValues
= new Any
[ nHitCount
];
859 // must lock the mutex outside the loop. So all values are consistent.
860 MutexGuard
aGuard( rBHelper
.rMutex
);
861 for( i
= 0; i
< nSeqLen
; i
++ )
863 if( pHandles
[i
] != -1 )
865 sal_Int16 nAttributes
;
866 rPH
.fillPropertyMembersByHandle( NULL
, &nAttributes
, pHandles
[i
] );
867 if( nAttributes
& PropertyAttribute::READONLY
) {
868 throw PropertyVetoException();
870 // Will the property change?
871 if( convertFastPropertyValue( pConvertedValues
[ n
], pOldValues
[n
],
872 pHandles
[i
], pValues
[i
] ) )
874 // only increment if the property really change
875 pHandles
[n
] = pHandles
[i
];
880 // release guard to fire events
883 // fire vetoable events
884 fire( pHandles
, pConvertedValues
, pOldValues
, n
, sal_True
);
887 // must lock the mutex outside the loop.
888 MutexGuard
aGuard( rBHelper
.rMutex
);
889 // Loop over all changed properties
890 for( i
= 0; i
< n
; i
++ )
892 // Will the property change?
893 setFastPropertyValue_NoBroadcast( pHandles
[i
], pConvertedValues
[i
] );
895 // release guard to fire events
898 // fire change events
899 impl_fireAll( pHandles
, pConvertedValues
, pOldValues
, n
);
903 delete [] pOldValues
;
904 delete [] pConvertedValues
;
907 delete [] pOldValues
;
908 delete [] pConvertedValues
;
913 * The sequence may be conatain not known properties. The implementation
914 * must ignore these properties.
916 void OPropertySetHelper::setPropertyValues(
917 const Sequence
<OUString
>& rPropertyNames
,
918 const Sequence
<Any
>& rValues
)
919 throw(::com::sun::star::beans::PropertyVetoException
, ::com::sun::star::lang::IllegalArgumentException
, ::com::sun::star::lang::WrappedTargetException
, ::com::sun::star::uno::RuntimeException
, std::exception
)
921 sal_Int32
* pHandles
= NULL
;
924 sal_Int32 nSeqLen
= rPropertyNames
.getLength();
925 pHandles
= new sal_Int32
[ nSeqLen
];
927 IPropertyArrayHelper
& rPH
= getInfoHelper();
928 // fill the handle array
929 sal_Int32 nHitCount
= rPH
.fillHandles( pHandles
, rPropertyNames
);
931 setFastPropertyValues( nSeqLen
, pHandles
, rValues
.getConstArray(), nHitCount
);
942 Sequence
<Any
> OPropertySetHelper::getPropertyValues( const Sequence
<OUString
>& rPropertyNames
)
943 throw(::com::sun::star::uno::RuntimeException
, std::exception
)
945 sal_Int32 nSeqLen
= rPropertyNames
.getLength();
946 sal_Int32
* pHandles
= new sal_Int32
[ nSeqLen
];
947 Sequence
< Any
> aValues( nSeqLen
);
950 IPropertyArrayHelper
& rPH
= getInfoHelper();
951 // fill the handle array
952 rPH
.fillHandles( pHandles
, rPropertyNames
);
954 Any
* pValues
= aValues
.getArray();
956 MutexGuard
aGuard( rBHelper
.rMutex
);
957 // fill the sequence with the values
958 for( sal_Int32 i
= 0; i
< nSeqLen
; i
++ )
959 getFastPropertyValue( pValues
[i
], pHandles
[i
] );
966 void OPropertySetHelper::addPropertiesChangeListener(
967 const Sequence
<OUString
> & ,
968 const Reference
< XPropertiesChangeListener
> & rListener
)
969 throw(::com::sun::star::uno::RuntimeException
, std::exception
)
971 rBHelper
.addListener( getCppuType(&rListener
) , rListener
);
975 void OPropertySetHelper::removePropertiesChangeListener(
976 const Reference
< XPropertiesChangeListener
> & rListener
)
977 throw(::com::sun::star::uno::RuntimeException
, std::exception
)
979 rBHelper
.removeListener( getCppuType(&rListener
) , rListener
);
983 void OPropertySetHelper::firePropertiesChangeEvent(
984 const Sequence
<OUString
>& rPropertyNames
,
985 const Reference
< XPropertiesChangeListener
>& rListener
)
986 throw(::com::sun::star::uno::RuntimeException
, std::exception
)
988 sal_Int32 nLen
= rPropertyNames
.getLength();
989 sal_Int32
* pHandles
= new sal_Int32
[nLen
];
990 IPropertyArrayHelper
& rPH
= getInfoHelper();
991 rPH
.fillHandles( pHandles
, rPropertyNames
);
992 const OUString
* pNames
= rPropertyNames
.getConstArray();
994 // get the count of matching properties
995 sal_Int32 nFireLen
= 0;
997 for( i
= 0; i
< nLen
; i
++ )
998 if( pHandles
[i
] != -1 )
1001 Sequence
<PropertyChangeEvent
> aChanges( nFireLen
);
1002 PropertyChangeEvent
* pChanges
= aChanges
.getArray();
1005 // must lock the mutex outside the loop. So all values are consistent.
1006 MutexGuard
aGuard( rBHelper
.rMutex
);
1007 Reference
< XInterface
> xSource( (XPropertySet
*)this, UNO_QUERY
);
1008 sal_Int32 nFirePos
= 0;
1009 for( i
= 0; i
< nLen
; i
++ )
1011 if( pHandles
[i
] != -1 )
1013 pChanges
[nFirePos
].Source
= xSource
;
1014 pChanges
[nFirePos
].PropertyName
= pNames
[i
];
1015 pChanges
[nFirePos
].PropertyHandle
= pHandles
[i
];
1016 getFastPropertyValue( pChanges
[nFirePos
].OldValue
, pHandles
[i
] );
1017 pChanges
[nFirePos
].NewValue
= pChanges
[nFirePos
].OldValue
;
1021 // release guard to fire events
1024 rListener
->propertiesChange( aChanges
);
1029 void OPropertySetHelper2::enableChangeListenerNotification( sal_Bool bEnable
)
1030 throw(::com::sun::star::uno::RuntimeException
, std::exception
)
1032 m_pReserved
->m_bFireEvents
= bEnable
;
1036 //== OPropertyArrayHelper ================================================
1041 static int compare_Property_Impl( const void *arg1
, const void *arg2
)
1042 SAL_THROW_EXTERN_C()
1044 return ((Property
*)arg1
)->Name
.compareTo( ((Property
*)arg2
)->Name
);
1049 void OPropertyArrayHelper::init( sal_Bool bSorted
) SAL_THROW(())
1051 sal_Int32 i
, nElements
= aInfos
.getLength();
1052 const Property
* pProperties
= aInfos
.getConstArray();
1054 for( i
= 1; i
< nElements
; i
++ )
1056 if( pProperties
[i
-1].Name
>= pProperties
[i
].Name
)
1059 OSL_FAIL( "Property array is not sorted" );
1062 qsort( aInfos
.getArray(), nElements
, sizeof( Property
),
1063 compare_Property_Impl
);
1067 // may be that the array is resorted
1068 pProperties
= aInfos
.getConstArray();
1069 for( i
= 0; i
< nElements
; i
++ )
1070 if( pProperties
[i
].Handle
!= i
)
1072 // The handle is the index
1073 bRightOrdered
= sal_True
;
1076 OPropertyArrayHelper::OPropertyArrayHelper(
1082 , aInfos(pProps
, nEle
)
1083 , bRightOrdered( sal_False
)
1088 OPropertyArrayHelper::OPropertyArrayHelper(
1089 const Sequence
< Property
> & aProps
,
1094 , bRightOrdered( sal_False
)
1100 sal_Int32
OPropertyArrayHelper::getCount() const
1102 return aInfos
.getLength();
1106 sal_Bool
OPropertyArrayHelper::fillPropertyMembersByHandle
1108 OUString
* pPropName
,
1109 sal_Int16
* pAttributes
,
1113 const Property
* pProperties
= aInfos
.getConstArray();
1114 sal_Int32 nElements
= aInfos
.getLength();
1118 if( nHandle
< 0 || nHandle
>= nElements
)
1121 *pPropName
= pProperties
[ nHandle
].Name
;
1123 *pAttributes
= pProperties
[ nHandle
].Attributes
;
1128 // normally the array is sorted
1129 for( sal_Int32 i
= 0; i
< nElements
; i
++ )
1131 if( pProperties
[i
].Handle
== nHandle
)
1134 *pPropName
= pProperties
[ i
].Name
;
1136 *pAttributes
= pProperties
[ i
].Attributes
;
1145 Sequence
< Property
> OPropertyArrayHelper::getProperties(void)
1151 Property
OPropertyArrayHelper::getPropertyByName(const OUString
& aPropertyName
)
1152 throw (UnknownPropertyException
)
1155 pR
= (Property
*)bsearch( &aPropertyName
, aInfos
.getConstArray(), aInfos
.getLength(),
1157 compare_OUString_Property_Impl
);
1159 throw UnknownPropertyException();
1165 sal_Bool
OPropertyArrayHelper::hasPropertyByName(const OUString
& aPropertyName
)
1168 pR
= (Property
*)bsearch( &aPropertyName
, aInfos
.getConstArray(), aInfos
.getLength(),
1170 compare_OUString_Property_Impl
);
1175 sal_Int32
OPropertyArrayHelper::getHandleByName( const OUString
& rPropName
)
1178 pR
= (Property
*)bsearch( &rPropName
, aInfos
.getConstArray(), aInfos
.getLength(),
1180 compare_OUString_Property_Impl
);
1181 return pR
? pR
->Handle
: -1;
1185 sal_Int32
OPropertyArrayHelper::fillHandles( sal_Int32
* pHandles
, const Sequence
< OUString
> & rPropNames
)
1187 sal_Int32 nHitCount
= 0;
1188 const OUString
* pReqProps
= rPropNames
.getConstArray();
1189 sal_Int32 nReqLen
= rPropNames
.getLength();
1190 const Property
* pCur
= aInfos
.getConstArray();
1191 const Property
* pEnd
= pCur
+ aInfos
.getLength();
1193 for( sal_Int32 i
= 0; i
< nReqLen
; i
++ )
1195 // Calculate logarithm
1196 sal_Int32 n
= (sal_Int32
)(pEnd
- pCur
);
1204 // Number of properties to search for * Log2 of the number of remaining
1205 // properties to search in.
1206 if( (nReqLen
- i
) * nLog
>= pEnd
- pCur
)
1208 // linear search is better
1209 while( pCur
< pEnd
&& pReqProps
[i
] > pCur
->Name
)
1213 if( pCur
< pEnd
&& pReqProps
[i
] == pCur
->Name
)
1215 pHandles
[i
] = pCur
->Handle
;
1223 // binary search is better
1224 sal_Int32 nCompVal
= 1;
1225 const Property
* pOldEnd
= pEnd
--;
1226 const Property
* pMid
= pCur
;
1228 while( nCompVal
!= 0 && pCur
<= pEnd
)
1230 pMid
= (pEnd
- pCur
) / 2 + pCur
;
1232 nCompVal
= pReqProps
[i
].compareTo( pMid
->Name
);
1242 pHandles
[i
] = pMid
->Handle
;
1246 else if( nCompVal
> 0 )
1262 } // end namespace cppu
1266 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */