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
;
37 using ::rtl::OUStringToOString
;
41 IPropertyArrayHelper::~IPropertyArrayHelper()
45 inline const ::com::sun::star::uno::Type
& getPropertyTypeIdentifier( ) SAL_THROW(())
47 return ::getCppuType( (Reference
< XPropertyChangeListener
> *)0 );
49 inline const ::com::sun::star::uno::Type
& getPropertiesTypeIdentifier() SAL_THROW(())
51 return ::getCppuType( (Reference
< XPropertiesChangeListener
> *)0 );
53 inline const ::com::sun::star::uno::Type
& getVetoableTypeIdentifier() SAL_THROW(())
55 return ::getCppuType( (Reference
< XVetoableChangeListener
> *)0 );
60 static int compare_OUString_Property_Impl( const void *arg1
, const void *arg2
)
63 return ((OUString
*)arg1
)->compareTo( ((Property
*)arg2
)->Name
);
69 * The class which implements the PropertySetInfo interface.
72 class OPropertySetHelperInfo_Impl
73 : public WeakImplHelper1
< ::com::sun::star::beans::XPropertySetInfo
>
75 Sequence
< Property
> aInfos
;
78 OPropertySetHelperInfo_Impl( IPropertyArrayHelper
& rHelper_
) SAL_THROW(());
80 // XPropertySetInfo-methods
81 virtual Sequence
< Property
> SAL_CALL
getProperties(void) throw(::com::sun::star::uno::RuntimeException
);
82 virtual Property SAL_CALL
getPropertyByName(const OUString
& PropertyName
) throw(::com::sun::star::beans::UnknownPropertyException
, ::com::sun::star::uno::RuntimeException
);
83 virtual sal_Bool SAL_CALL
hasPropertyByName(const OUString
& PropertyName
) throw(::com::sun::star::uno::RuntimeException
);
88 * Create an object that implements XPropertySetInfo IPropertyArrayHelper.
90 OPropertySetHelperInfo_Impl::OPropertySetHelperInfo_Impl(
91 IPropertyArrayHelper
& rHelper_
)
93 :aInfos( rHelper_
.getProperties() )
98 * Return the sequence of properties, which are provided throug the constructor.
100 Sequence
< Property
> OPropertySetHelperInfo_Impl::getProperties(void) throw(::com::sun::star::uno::RuntimeException
)
107 * Return the sequence of properties, which are provided throug the constructor.
109 Property
OPropertySetHelperInfo_Impl::getPropertyByName( const OUString
& PropertyName
) throw(::com::sun::star::beans::UnknownPropertyException
, ::com::sun::star::uno::RuntimeException
)
112 pR
= (Property
*)bsearch( &PropertyName
, aInfos
.getConstArray(), aInfos
.getLength(),
114 compare_OUString_Property_Impl
);
116 throw UnknownPropertyException();
123 * Return the sequence of properties, which are provided throug the constructor.
125 sal_Bool
OPropertySetHelperInfo_Impl::hasPropertyByName( const OUString
& PropertyName
) throw(::com::sun::star::uno::RuntimeException
)
128 pR
= (Property
*)bsearch( &PropertyName
, aInfos
.getConstArray(), aInfos
.getLength(),
130 compare_OUString_Property_Impl
);
134 // ----------------------------------------------------
135 // class PropertySetHelper_Impl
136 // ----------------------------------------------------
137 class OPropertySetHelper::Impl
{
140 Impl( bool i_bIgnoreRuntimeExceptionsWhileFiring
,
141 IEventNotificationHook
*i_pFireEvents
143 :m_bIgnoreRuntimeExceptionsWhileFiring( i_bIgnoreRuntimeExceptionsWhileFiring
)
145 ,m_pFireEvents( i_pFireEvents
)
149 bool m_bIgnoreRuntimeExceptionsWhileFiring
;
151 class IEventNotificationHook
* const m_pFireEvents
;
153 ::std::vector
< sal_Int32
> m_handles
;
154 ::std::vector
< Any
> m_newValues
;
155 ::std::vector
< Any
> m_oldValues
;
159 // ----------------------------------------------------
160 // class PropertySetHelper
161 // ----------------------------------------------------
162 OPropertySetHelper::OPropertySetHelper(
163 OBroadcastHelper
& rBHelper_
) SAL_THROW(())
164 : rBHelper( rBHelper_
),
165 aBoundLC( rBHelper_
.rMutex
),
166 aVetoableLC( rBHelper_
.rMutex
),
167 m_pReserved( new Impl(false, 0) )
171 OPropertySetHelper::OPropertySetHelper(
172 OBroadcastHelper
& rBHelper_
, bool bIgnoreRuntimeExceptionsWhileFiring
)
173 : rBHelper( rBHelper_
),
174 aBoundLC( rBHelper_
.rMutex
),
175 aVetoableLC( rBHelper_
.rMutex
),
176 m_pReserved( new Impl( bIgnoreRuntimeExceptionsWhileFiring
, 0 ) )
180 OPropertySetHelper::OPropertySetHelper(
181 OBroadcastHelper
& rBHelper_
, IEventNotificationHook
* i_pFireEvents
,
182 bool bIgnoreRuntimeExceptionsWhileFiring
)
183 : rBHelper( rBHelper_
),
184 aBoundLC( rBHelper_
.rMutex
),
185 aVetoableLC( rBHelper_
.rMutex
),
187 new Impl( bIgnoreRuntimeExceptionsWhileFiring
, i_pFireEvents
) )
191 OPropertySetHelper2::OPropertySetHelper2(
192 OBroadcastHelper
& irBHelper
,
193 IEventNotificationHook
*i_pFireEvents
,
194 bool bIgnoreRuntimeExceptionsWhileFiring
)
195 :OPropertySetHelper( irBHelper
, i_pFireEvents
, bIgnoreRuntimeExceptionsWhileFiring
)
200 * You must call disposing before.
202 OPropertySetHelper::~OPropertySetHelper() SAL_THROW(())
205 OPropertySetHelper2::~OPropertySetHelper2() SAL_THROW(())
210 Any
OPropertySetHelper::queryInterface( const ::com::sun::star::uno::Type
& rType
)
211 throw (RuntimeException
)
213 return ::cppu::queryInterface(
215 static_cast< XPropertySet
* >( this ),
216 static_cast< XMultiPropertySet
* >( this ),
217 static_cast< XFastPropertySet
* >( this ) );
220 Any
OPropertySetHelper2::queryInterface( const ::com::sun::star::uno::Type
& rType
)
221 throw (RuntimeException
)
223 Any
cnd(cppu::queryInterface(rType
, static_cast< XPropertySetOption
* >(this)));
224 if ( cnd
.hasValue() )
227 return OPropertySetHelper::queryInterface(rType
);
231 * called from the derivee's XTypeProvider::getTypes implementation
233 ::com::sun::star::uno::Sequence
< ::com::sun::star::uno::Type
> OPropertySetHelper::getTypes()
234 throw (RuntimeException
)
236 Sequence
< ::com::sun::star::uno::Type
> aTypes( 4 );
237 aTypes
[ 0 ] = XPropertySet::static_type();
238 aTypes
[ 1 ] = XPropertySetOption::static_type();
239 aTypes
[ 2 ] = XMultiPropertySet::static_type();
240 aTypes
[ 3 ] = XFastPropertySet::static_type();
245 void OPropertySetHelper::disposing() SAL_THROW(())
247 // Create an event with this as sender
248 Reference
< XPropertySet
> rSource( (static_cast< XPropertySet
* >(this)) , UNO_QUERY
);
250 aEvt
.Source
= rSource
;
252 // inform all listeners to release this object
253 // The listener containers are automatically cleared
254 aBoundLC
.disposeAndClear( aEvt
);
255 aVetoableLC
.disposeAndClear( aEvt
);
258 Reference
< XPropertySetInfo
> OPropertySetHelper::createPropertySetInfo(
259 IPropertyArrayHelper
& rProperties
) SAL_THROW(())
261 return static_cast< XPropertySetInfo
* >( new OPropertySetHelperInfo_Impl( rProperties
) );
265 void OPropertySetHelper::setPropertyValue(
266 const OUString
& rPropertyName
, const Any
& rValue
)
267 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
)
270 IPropertyArrayHelper
& rPH
= getInfoHelper();
271 // map the name to the handle
272 sal_Int32 nHandle
= rPH
.getHandleByName( rPropertyName
);
273 // call the method of the XFastPropertySet interface
274 setFastPropertyValue( nHandle
, rValue
);
278 Any
OPropertySetHelper::getPropertyValue(
279 const OUString
& rPropertyName
)
280 throw(::com::sun::star::beans::UnknownPropertyException
, ::com::sun::star::lang::WrappedTargetException
, ::com::sun::star::uno::RuntimeException
)
283 IPropertyArrayHelper
& rPH
= getInfoHelper();
284 // map the name to the handle
285 sal_Int32 nHandle
= rPH
.getHandleByName( rPropertyName
);
286 // call the method of the XFastPropertySet interface
287 return getFastPropertyValue( nHandle
);
291 void OPropertySetHelper::addPropertyChangeListener(
292 const OUString
& rPropertyName
,
293 const Reference
< XPropertyChangeListener
> & rxListener
)
294 throw(::com::sun::star::beans::UnknownPropertyException
,
295 ::com::sun::star::lang::WrappedTargetException
,
296 ::com::sun::star::uno::RuntimeException
)
298 MutexGuard
aGuard( rBHelper
.rMutex
);
299 OSL_ENSURE( !rBHelper
.bInDispose
, "do not addPropertyChangeListener in the dispose call" );
300 OSL_ENSURE( !rBHelper
.bDisposed
, "object is disposed" );
301 if( !rBHelper
.bInDispose
&& !rBHelper
.bDisposed
)
303 // only add listeners if you are not disposed
304 // a listener with no name means all properties
305 if( !rPropertyName
.isEmpty() )
308 IPropertyArrayHelper
& rPH
= getInfoHelper();
309 // map the name to the handle
310 sal_Int32 nHandle
= rPH
.getHandleByName( rPropertyName
);
311 if( nHandle
== -1 ) {
312 // property not known throw exception
313 throw UnknownPropertyException() ;
316 sal_Int16 nAttributes
;
317 rPH
.fillPropertyMembersByHandle( NULL
, &nAttributes
, nHandle
);
318 if( !(nAttributes
& ::com::sun::star::beans::PropertyAttribute::BOUND
) )
320 OSL_FAIL( "add listener to an unbound property" );
321 // silent ignore this
324 // add the change listener to the helper container
326 aBoundLC
.addInterface( (sal_Int32
)nHandle
, rxListener
);
329 // add the change listener to the helper container
330 rBHelper
.aLC
.addInterface(
331 getPropertyTypeIdentifier( ),
339 void OPropertySetHelper::removePropertyChangeListener(
340 const OUString
& rPropertyName
,
341 const Reference
< XPropertyChangeListener
>& rxListener
)
342 throw(::com::sun::star::beans::UnknownPropertyException
,
343 ::com::sun::star::lang::WrappedTargetException
,
344 ::com::sun::star::uno::RuntimeException
)
346 MutexGuard
aGuard( rBHelper
.rMutex
);
347 OSL_ENSURE( !rBHelper
.bDisposed
, "object is disposed" );
348 // all listeners are automaticly released in a dispose call
349 if( !rBHelper
.bInDispose
&& !rBHelper
.bDisposed
)
351 if( !rPropertyName
.isEmpty() )
354 IPropertyArrayHelper
& rPH
= getInfoHelper();
355 // map the name to the handle
356 sal_Int32 nHandle
= rPH
.getHandleByName( rPropertyName
);
358 // property not known throw exception
359 throw UnknownPropertyException();
360 aBoundLC
.removeInterface( (sal_Int32
)nHandle
, rxListener
);
363 // remove the change listener to the helper container
364 rBHelper
.aLC
.removeInterface(
365 getPropertyTypeIdentifier( ),
373 void OPropertySetHelper::addVetoableChangeListener(
374 const OUString
& rPropertyName
,
375 const Reference
< XVetoableChangeListener
> & rxListener
)
376 throw(::com::sun::star::beans::UnknownPropertyException
,
377 ::com::sun::star::lang::WrappedTargetException
,
378 ::com::sun::star::uno::RuntimeException
)
380 MutexGuard
aGuard( rBHelper
.rMutex
);
381 OSL_ENSURE( !rBHelper
.bInDispose
, "do not addVetoableChangeListener in the dispose call" );
382 OSL_ENSURE( !rBHelper
.bDisposed
, "object is disposed" );
383 if( !rBHelper
.bInDispose
&& !rBHelper
.bDisposed
)
385 // only add listeners if you are not disposed
386 // a listener with no name means all properties
387 if( !rPropertyName
.isEmpty() )
390 IPropertyArrayHelper
& rPH
= getInfoHelper();
391 // map the name to the handle
392 sal_Int32 nHandle
= rPH
.getHandleByName( rPropertyName
);
393 if( nHandle
== -1 ) {
394 // property not known throw exception
395 throw UnknownPropertyException();
398 sal_Int16 nAttributes
;
399 rPH
.fillPropertyMembersByHandle( NULL
, &nAttributes
, nHandle
);
400 if( !(nAttributes
& PropertyAttribute::CONSTRAINED
) )
402 OSL_FAIL( "addVetoableChangeListener, and property is not constrained" );
403 // silent ignore this
406 // add the vetoable listener to the helper container
407 aVetoableLC
.addInterface( (sal_Int32
)nHandle
, rxListener
);
410 // add the vetoable listener to the helper container
411 rBHelper
.aLC
.addInterface(
412 getVetoableTypeIdentifier( ),
419 void OPropertySetHelper::removeVetoableChangeListener(
420 const OUString
& rPropertyName
,
421 const Reference
< XVetoableChangeListener
> & rxListener
)
422 throw(::com::sun::star::beans::UnknownPropertyException
,
423 ::com::sun::star::lang::WrappedTargetException
,
424 ::com::sun::star::uno::RuntimeException
)
426 MutexGuard
aGuard( rBHelper
.rMutex
);
427 OSL_ENSURE( !rBHelper
.bDisposed
, "object is disposed" );
428 // all listeners are automaticly released in a dispose call
429 if( !rBHelper
.bInDispose
&& !rBHelper
.bDisposed
)
431 if( !rPropertyName
.isEmpty() )
434 IPropertyArrayHelper
& rPH
= getInfoHelper();
435 // map the name to the handle
436 sal_Int32 nHandle
= rPH
.getHandleByName( rPropertyName
);
437 if( nHandle
== -1 ) {
438 // property not known throw exception
439 throw UnknownPropertyException();
441 // remove the vetoable listener to the helper container
442 aVetoableLC
.removeInterface( (sal_Int32
)nHandle
, rxListener
);
445 // add the vetoable listener to the helper container
446 rBHelper
.aLC
.removeInterface(
447 getVetoableTypeIdentifier( ),
453 void OPropertySetHelper::setDependentFastPropertyValue( sal_Int32 i_handle
, const ::com::sun::star::uno::Any
& i_value
)
455 //OSL_PRECOND( rBHelper.rMutex.isAcquired(), "OPropertySetHelper::setDependentFastPropertyValue: to be called with a locked mutex only!" );
456 // there is no such thing as Mutex.isAcquired, sadly ...
458 sal_Int16
nAttributes(0);
459 IPropertyArrayHelper
& rInfo
= getInfoHelper();
460 if ( !rInfo
.fillPropertyMembersByHandle( NULL
, &nAttributes
, i_handle
) )
462 throw UnknownPropertyException();
464 // no need to check for READONLY-ness of the property. The method is intended to be called internally, which
465 // implies it might be invoked for properties which are read-only to the instance's clients, but well allowed
466 // to change their value.
468 Any aConverted
, aOld
;
469 sal_Bool bChanged
= convertFastPropertyValue( aConverted
, aOld
, i_handle
, i_value
);
473 // don't fire vetoable events. This method is called with our mutex locked, so calling into listeners would not be
474 // a good idea. The caler is responsible for not invoking this for constrained properties.
475 OSL_ENSURE( ( nAttributes
& PropertyAttribute::CONSTRAINED
) == 0,
476 "OPropertySetHelper::setDependentFastPropertyValue: not to be used for constrained properties!" );
479 // actually set the new value
482 setFastPropertyValue_NoBroadcast( i_handle
, aConverted
);
484 catch (const UnknownPropertyException
& ) { throw; /* allowed to leave */ }
485 catch (const PropertyVetoException
& ) { throw; /* allowed to leave */ }
486 catch (const IllegalArgumentException
& ) { throw; /* allowed to leave */ }
487 catch (const WrappedTargetException
& ) { throw; /* allowed to leave */ }
488 catch (const RuntimeException
& ) { throw; /* allowed to leave */ }
489 catch (const Exception
& )
491 // not allowed to leave this meathod
492 WrappedTargetException aWrapped
;
493 aWrapped
.TargetException
<<= ::cppu::getCaughtException();
494 aWrapped
.Context
= static_cast< XPropertySet
* >( this );
498 // remember the handle/values, for the events to be fired later
499 m_pReserved
->m_handles
.push_back( i_handle
);
500 m_pReserved
->m_newValues
.push_back( aConverted
); // TODO: setFastPropertyValue notifies the unconverted value here ...?
501 m_pReserved
->m_oldValues
.push_back( aOld
);
505 void OPropertySetHelper::setFastPropertyValue( sal_Int32 nHandle
, const Any
& rValue
)
506 throw(::com::sun::star::beans::UnknownPropertyException
,
507 ::com::sun::star::beans::PropertyVetoException
,
508 ::com::sun::star::lang::IllegalArgumentException
,
509 ::com::sun::star::lang::WrappedTargetException
,
510 ::com::sun::star::uno::RuntimeException
)
512 OSL_ENSURE( !rBHelper
.bInDispose
, "do not setFastPropertyValue in the dispose call" );
513 OSL_ENSURE( !rBHelper
.bDisposed
, "object is disposed" );
515 IPropertyArrayHelper
& rInfo
= getInfoHelper();
516 sal_Int16 nAttributes
;
517 if( !rInfo
.fillPropertyMembersByHandle( NULL
, &nAttributes
, nHandle
) ) {
519 throw UnknownPropertyException();
521 if( nAttributes
& PropertyAttribute::READONLY
)
522 throw PropertyVetoException();
527 // Will the property change?
530 MutexGuard
aGuard( rBHelper
.rMutex
);
531 bChanged
= convertFastPropertyValue( aConvertedVal
, aOldVal
, nHandle
, rValue
);
532 // release guard to fire events
536 // Is it a constrained property?
537 if( nAttributes
& PropertyAttribute::CONSTRAINED
)
539 // In aValue is the converted rValue
540 // fire a constarined event
541 // second parameter NULL means constrained
542 fire( &nHandle
, &rValue
, &aOldVal
, 1, sal_True
);
546 MutexGuard
aGuard( rBHelper
.rMutex
);
549 // set the property to the new value
550 setFastPropertyValue_NoBroadcast( nHandle
, aConvertedVal
);
552 catch (const ::com::sun::star::beans::UnknownPropertyException
& ) { throw; /* allowed to leave */ }
553 catch (const ::com::sun::star::beans::PropertyVetoException
& ) { throw; /* allowed to leave */ }
554 catch (const ::com::sun::star::lang::IllegalArgumentException
& ) { throw; /* allowed to leave */ }
555 catch (const ::com::sun::star::lang::WrappedTargetException
& ) { throw; /* allowed to leave */ }
556 catch (const ::com::sun::star::uno::RuntimeException
& ) { throw; /* allowed to leave */ }
557 catch (const ::com::sun::star::uno::Exception
& e
)
559 // not allowed to leave this meathod
560 ::com::sun::star::lang::WrappedTargetException aWrap
;
561 aWrap
.Context
= static_cast< ::com::sun::star::beans::XPropertySet
* >( this );
562 aWrap
.TargetException
<<= e
;
564 throw ::com::sun::star::lang::WrappedTargetException( aWrap
);
567 // release guard to fire events
569 // file a change event, if the value changed
570 impl_fireAll( &nHandle
, &rValue
, &aOldVal
, 1 );
575 Any
OPropertySetHelper::getFastPropertyValue( sal_Int32 nHandle
)
576 throw(::com::sun::star::beans::UnknownPropertyException
,
577 ::com::sun::star::lang::WrappedTargetException
,
578 ::com::sun::star::uno::RuntimeException
)
581 IPropertyArrayHelper
& rInfo
= getInfoHelper();
582 if( !rInfo
.fillPropertyMembersByHandle( NULL
, NULL
, nHandle
) )
584 throw UnknownPropertyException();
587 MutexGuard
aGuard( rBHelper
.rMutex
);
588 getFastPropertyValue( aRet
, nHandle
);
592 //--------------------------------------------------------------------------
593 void OPropertySetHelper::impl_fireAll( sal_Int32
* i_handles
, const Any
* i_newValues
, const Any
* i_oldValues
, sal_Int32 i_count
)
595 ClearableMutexGuard
aGuard( rBHelper
.rMutex
);
596 if ( m_pReserved
->m_handles
.empty() )
599 fire( i_handles
, i_newValues
, i_oldValues
, i_count
, sal_False
);
603 const size_t additionalEvents
= m_pReserved
->m_handles
.size();
604 OSL_ENSURE( additionalEvents
== m_pReserved
->m_newValues
.size()
605 && additionalEvents
== m_pReserved
->m_oldValues
.size(),
606 "OPropertySetHelper::impl_fireAll: inconsistency!" );
608 ::std::vector
< sal_Int32
> allHandles( additionalEvents
+ i_count
);
609 ::std::copy( m_pReserved
->m_handles
.begin(), m_pReserved
->m_handles
.end(), allHandles
.begin() );
610 ::std::copy( i_handles
, i_handles
+ i_count
, allHandles
.begin() + additionalEvents
);
612 ::std::vector
< Any
> allNewValues( additionalEvents
+ i_count
);
613 ::std::copy( m_pReserved
->m_newValues
.begin(), m_pReserved
->m_newValues
.end(), allNewValues
.begin() );
614 ::std::copy( i_newValues
, i_newValues
+ i_count
, allNewValues
.begin() + additionalEvents
);
616 ::std::vector
< Any
> allOldValues( additionalEvents
+ i_count
);
617 ::std::copy( m_pReserved
->m_oldValues
.begin(), m_pReserved
->m_oldValues
.end(), allOldValues
.begin() );
618 ::std::copy( i_oldValues
, i_oldValues
+ i_count
, allOldValues
.begin() + additionalEvents
);
620 m_pReserved
->m_handles
.clear();
621 m_pReserved
->m_newValues
.clear();
622 m_pReserved
->m_oldValues
.clear();
625 fire( &allHandles
[0], &allNewValues
[0], &allOldValues
[0], additionalEvents
+ i_count
, sal_False
);
628 //--------------------------------------------------------------------------
629 void OPropertySetHelper::fire
631 sal_Int32
* pnHandles
,
632 const Any
* pNewValues
,
633 const Any
* pOldValues
,
634 sal_Int32 nHandles
, // These is the Count of the array
638 OSL_ENSURE( m_pReserved
.get(), "No OPropertySetHelper::Impl" );
640 if (! m_pReserved
->m_bFireEvents
)
643 if (m_pReserved
->m_pFireEvents
) {
644 m_pReserved
->m_pFireEvents
->fireEvents(
645 pnHandles
, nHandles
, bVetoable
,
646 m_pReserved
->m_bIgnoreRuntimeExceptionsWhileFiring
);
649 // Only fire, if one or more properties changed
652 // create the event sequence of all changed properties
653 Sequence
< PropertyChangeEvent
> aEvts( nHandles
);
654 PropertyChangeEvent
* pEvts
= aEvts
.getArray();
655 Reference
< XInterface
> xSource( (XPropertySet
*)this, UNO_QUERY
);
657 sal_Int32 nChangesLen
= 0;
658 // Loop over all changed properties to fill the event struct
659 for( i
= 0; i
< nHandles
; i
++ )
661 // Vetoable fire and constrained attribute set or
662 // Change fire and Changed and bound attribute set
663 IPropertyArrayHelper
& rInfo
= getInfoHelper();
664 sal_Int16 nAttributes
;
666 rInfo
.fillPropertyMembersByHandle( &aPropName
, &nAttributes
, pnHandles
[i
] );
669 (bVetoable
&& (nAttributes
& PropertyAttribute::CONSTRAINED
)) ||
670 (!bVetoable
&& (nAttributes
& PropertyAttribute::BOUND
))
673 pEvts
[nChangesLen
].Source
= xSource
;
674 pEvts
[nChangesLen
].PropertyName
= aPropName
;
675 pEvts
[nChangesLen
].PropertyHandle
= pnHandles
[i
];
676 pEvts
[nChangesLen
].OldValue
= pOldValues
[i
];
677 pEvts
[nChangesLen
].NewValue
= pNewValues
[i
];
682 bool bIgnoreRuntimeExceptionsWhileFiring
=
683 m_pReserved
->m_bIgnoreRuntimeExceptionsWhileFiring
;
685 // fire the events for all changed properties
686 for( i
= 0; i
< nChangesLen
; i
++ )
688 // get the listener container for the property name
689 OInterfaceContainerHelper
* pLC
;
690 if( bVetoable
) // fire change Events?
691 pLC
= aVetoableLC
.getContainer( pEvts
[i
].PropertyHandle
);
693 pLC
= aBoundLC
.getContainer( pEvts
[i
].PropertyHandle
);
696 // Iterate over all listeners and send events
697 OInterfaceIteratorHelper
aIt( *pLC
);
698 while( aIt
.hasMoreElements() )
700 XInterface
* pL
= aIt
.next();
705 if( bVetoable
) // fire change Events?
707 ((XVetoableChangeListener
*)pL
)->vetoableChange(
712 ((XPropertyChangeListener
*)pL
)->propertyChange(
716 catch (DisposedException
& exc
)
718 OSL_ENSURE( exc
.Context
.is(),
719 "DisposedException without Context!" );
720 if (exc
.Context
== pL
)
726 catch (RuntimeException
& exc
)
730 OUString( RTL_CONSTASCII_USTRINGPARAM(
731 "caught RuntimeException while "
732 "firing listeners: ") ) +
733 exc
.Message
, RTL_TEXTENCODING_UTF8
).getStr() );
734 if (! bIgnoreRuntimeExceptionsWhileFiring
)
739 // broadcast to all listeners with "" property name
741 // fire change Events?
742 pLC
= rBHelper
.aLC
.getContainer(
743 getVetoableTypeIdentifier()
747 pLC
= rBHelper
.aLC
.getContainer(
748 getPropertyTypeIdentifier( )
753 // Iterate over all listeners and send events.
754 OInterfaceIteratorHelper
aIt( *pLC
);
755 while( aIt
.hasMoreElements() )
757 XInterface
* pL
= aIt
.next();
762 if( bVetoable
) // fire change Events?
764 ((XVetoableChangeListener
*)pL
)->vetoableChange(
769 ((XPropertyChangeListener
*)pL
)->propertyChange(
773 catch (DisposedException
& exc
)
775 OSL_ENSURE( exc
.Context
.is(),
776 "DisposedException without Context!" );
777 if (exc
.Context
== pL
)
783 catch (RuntimeException
& exc
)
787 OUString( RTL_CONSTASCII_USTRINGPARAM(
788 "caught RuntimeException while "
789 "firing listeners: ") ) +
790 exc
.Message
, RTL_TEXTENCODING_UTF8
).getStr() );
791 if (! bIgnoreRuntimeExceptionsWhileFiring
)
798 // reduce array to changed properties
799 aEvts
.realloc( nChangesLen
);
803 OInterfaceContainerHelper
* pCont
= 0;
804 pCont
= rBHelper
.aLC
.getContainer(
805 getPropertiesTypeIdentifier( )
809 // Here is a Bug, unbound properties are also fired
810 OInterfaceIteratorHelper
aIt( *pCont
);
811 while( aIt
.hasMoreElements() )
813 XPropertiesChangeListener
* pL
=
814 (XPropertiesChangeListener
*)aIt
.next();
819 // fire the hole event sequence to the
820 // XPropertiesChangeListener's
821 pL
->propertiesChange( aEvts
);
823 catch (DisposedException
& exc
)
825 OSL_ENSURE( exc
.Context
.is(),
826 "DisposedException without Context!" );
827 if (exc
.Context
== pL
)
833 catch (RuntimeException
& exc
)
837 OUString( RTL_CONSTASCII_USTRINGPARAM(
838 "caught RuntimeException while "
839 "firing listeners: ") ) +
840 exc
.Message
, RTL_TEXTENCODING_UTF8
).getStr() );
841 if (! bIgnoreRuntimeExceptionsWhileFiring
)
850 // OPropertySetHelper
851 void OPropertySetHelper::setFastPropertyValues(
853 sal_Int32
* pHandles
,
855 sal_Int32 nHitCount
)
856 SAL_THROW( (::com::sun::star::uno::Exception
) )
858 OSL_ENSURE( !rBHelper
.bInDispose
, "do not getFastPropertyValue in the dispose call" );
859 OSL_ENSURE( !rBHelper
.bDisposed
, "object is disposed" );
861 Any
* pConvertedValues
= NULL
;
862 Any
* pOldValues
= NULL
;
867 IPropertyArrayHelper
& rPH
= getInfoHelper();
869 pConvertedValues
= new Any
[ nHitCount
];
870 pOldValues
= new Any
[ nHitCount
];
875 // must lock the mutex outside the loop. So all values are consistent.
876 MutexGuard
aGuard( rBHelper
.rMutex
);
877 for( i
= 0; i
< nSeqLen
; i
++ )
879 if( pHandles
[i
] != -1 )
881 sal_Int16 nAttributes
;
882 rPH
.fillPropertyMembersByHandle( NULL
, &nAttributes
, pHandles
[i
] );
883 if( nAttributes
& PropertyAttribute::READONLY
) {
884 throw PropertyVetoException();
886 // Will the property change?
887 if( convertFastPropertyValue( pConvertedValues
[ n
], pOldValues
[n
],
888 pHandles
[i
], pValues
[i
] ) )
890 // only increment if the property really change
891 pHandles
[n
] = pHandles
[i
];
896 // release guard to fire events
899 // fire vetoable events
900 fire( pHandles
, pConvertedValues
, pOldValues
, n
, sal_True
);
903 // must lock the mutex outside the loop.
904 MutexGuard
aGuard( rBHelper
.rMutex
);
905 // Loop over all changed properties
906 for( i
= 0; i
< n
; i
++ )
908 // Will the property change?
909 setFastPropertyValue_NoBroadcast( pHandles
[i
], pConvertedValues
[i
] );
911 // release guard to fire events
914 // fire change events
915 impl_fireAll( pHandles
, pConvertedValues
, pOldValues
, n
);
919 delete [] pOldValues
;
920 delete [] pConvertedValues
;
923 delete [] pOldValues
;
924 delete [] pConvertedValues
;
929 * The sequence may be conatain not known properties. The implementation
930 * must ignore these properties.
932 void OPropertySetHelper::setPropertyValues(
933 const Sequence
<OUString
>& rPropertyNames
,
934 const Sequence
<Any
>& rValues
)
935 throw(::com::sun::star::beans::PropertyVetoException
, ::com::sun::star::lang::IllegalArgumentException
, ::com::sun::star::lang::WrappedTargetException
, ::com::sun::star::uno::RuntimeException
)
937 sal_Int32
* pHandles
= NULL
;
940 sal_Int32 nSeqLen
= rPropertyNames
.getLength();
941 pHandles
= new sal_Int32
[ nSeqLen
];
943 IPropertyArrayHelper
& rPH
= getInfoHelper();
944 // fill the handle array
945 sal_Int32 nHitCount
= rPH
.fillHandles( pHandles
, rPropertyNames
);
947 setFastPropertyValues( nSeqLen
, pHandles
, rValues
.getConstArray(), nHitCount
);
958 Sequence
<Any
> OPropertySetHelper::getPropertyValues( const Sequence
<OUString
>& rPropertyNames
)
959 throw(::com::sun::star::uno::RuntimeException
)
961 sal_Int32 nSeqLen
= rPropertyNames
.getLength();
962 sal_Int32
* pHandles
= new sal_Int32
[ nSeqLen
];
963 Sequence
< Any
> aValues( nSeqLen
);
966 IPropertyArrayHelper
& rPH
= getInfoHelper();
967 // fill the handle array
968 rPH
.fillHandles( pHandles
, rPropertyNames
);
970 Any
* pValues
= aValues
.getArray();
972 MutexGuard
aGuard( rBHelper
.rMutex
);
973 // fill the sequence with the values
974 for( sal_Int32 i
= 0; i
< nSeqLen
; i
++ )
975 getFastPropertyValue( pValues
[i
], pHandles
[i
] );
982 void OPropertySetHelper::addPropertiesChangeListener(
983 const Sequence
<OUString
> & ,
984 const Reference
< XPropertiesChangeListener
> & rListener
)
985 throw(::com::sun::star::uno::RuntimeException
)
987 rBHelper
.addListener( getCppuType(&rListener
) , rListener
);
991 void OPropertySetHelper::removePropertiesChangeListener(
992 const Reference
< XPropertiesChangeListener
> & rListener
)
993 throw(::com::sun::star::uno::RuntimeException
)
995 rBHelper
.removeListener( getCppuType(&rListener
) , rListener
);
999 void OPropertySetHelper::firePropertiesChangeEvent(
1000 const Sequence
<OUString
>& rPropertyNames
,
1001 const Reference
< XPropertiesChangeListener
>& rListener
)
1002 throw(::com::sun::star::uno::RuntimeException
)
1004 sal_Int32 nLen
= rPropertyNames
.getLength();
1005 sal_Int32
* pHandles
= new sal_Int32
[nLen
];
1006 IPropertyArrayHelper
& rPH
= getInfoHelper();
1007 rPH
.fillHandles( pHandles
, rPropertyNames
);
1008 const OUString
* pNames
= rPropertyNames
.getConstArray();
1010 // get the count of matching properties
1011 sal_Int32 nFireLen
= 0;
1013 for( i
= 0; i
< nLen
; i
++ )
1014 if( pHandles
[i
] != -1 )
1017 Sequence
<PropertyChangeEvent
> aChanges( nFireLen
);
1018 PropertyChangeEvent
* pChanges
= aChanges
.getArray();
1021 // must lock the mutex outside the loop. So all values are consistent.
1022 MutexGuard
aGuard( rBHelper
.rMutex
);
1023 Reference
< XInterface
> xSource( (XPropertySet
*)this, UNO_QUERY
);
1024 sal_Int32 nFirePos
= 0;
1025 for( i
= 0; i
< nLen
; i
++ )
1027 if( pHandles
[i
] != -1 )
1029 pChanges
[nFirePos
].Source
= xSource
;
1030 pChanges
[nFirePos
].PropertyName
= pNames
[i
];
1031 pChanges
[nFirePos
].PropertyHandle
= pHandles
[i
];
1032 getFastPropertyValue( pChanges
[nFirePos
].OldValue
, pHandles
[i
] );
1033 pChanges
[nFirePos
].NewValue
= pChanges
[nFirePos
].OldValue
;
1037 // release guard to fire events
1040 rListener
->propertiesChange( aChanges
);
1045 void OPropertySetHelper2::enableChangeListenerNotification( sal_Bool bEnable
)
1046 throw(::com::sun::star::uno::RuntimeException
)
1048 m_pReserved
->m_bFireEvents
= bEnable
;
1051 //========================================================================
1052 //== OPropertyArrayHelper ================================================
1053 //========================================================================
1057 static int compare_Property_Impl( const void *arg1
, const void *arg2
)
1058 SAL_THROW_EXTERN_C()
1060 return ((Property
*)arg1
)->Name
.compareTo( ((Property
*)arg2
)->Name
);
1065 void OPropertyArrayHelper::init( sal_Bool bSorted
) SAL_THROW(())
1067 sal_Int32 i
, nElements
= aInfos
.getLength();
1068 const Property
* pProperties
= aInfos
.getConstArray();
1070 for( i
= 1; i
< nElements
; i
++ )
1072 if( pProperties
[i
-1].Name
>= pProperties
[i
].Name
)
1075 OSL_FAIL( "Property array is not sorted" );
1078 qsort( aInfos
.getArray(), nElements
, sizeof( Property
),
1079 compare_Property_Impl
);
1083 // may be that the array is resorted
1084 pProperties
= aInfos
.getConstArray();
1085 for( i
= 0; i
< nElements
; i
++ )
1086 if( pProperties
[i
].Handle
!= i
)
1088 // The handle is the index
1089 bRightOrdered
= sal_True
;
1092 OPropertyArrayHelper::OPropertyArrayHelper(
1097 : aInfos(pProps
, nEle
)
1098 , bRightOrdered( sal_False
)
1103 OPropertyArrayHelper::OPropertyArrayHelper(
1104 const Sequence
< Property
> & aProps
,
1108 , bRightOrdered( sal_False
)
1113 //========================================================================
1114 sal_Int32
OPropertyArrayHelper::getCount() const
1116 return aInfos
.getLength();
1119 //========================================================================
1120 sal_Bool
OPropertyArrayHelper::fillPropertyMembersByHandle
1122 OUString
* pPropName
,
1123 sal_Int16
* pAttributes
,
1127 const Property
* pProperties
= aInfos
.getConstArray();
1128 sal_Int32 nElements
= aInfos
.getLength();
1132 if( nHandle
< 0 || nHandle
>= nElements
)
1135 *pPropName
= pProperties
[ nHandle
].Name
;
1137 *pAttributes
= pProperties
[ nHandle
].Attributes
;
1142 // normally the array is sorted
1143 for( sal_Int32 i
= 0; i
< nElements
; i
++ )
1145 if( pProperties
[i
].Handle
== nHandle
)
1148 *pPropName
= pProperties
[ i
].Name
;
1150 *pAttributes
= pProperties
[ i
].Attributes
;
1158 //========================================================================
1159 Sequence
< Property
> OPropertyArrayHelper::getProperties(void)
1164 //========================================================================
1165 Property
OPropertyArrayHelper::getPropertyByName(const OUString
& aPropertyName
)
1166 throw (UnknownPropertyException
)
1169 pR
= (Property
*)bsearch( &aPropertyName
, aInfos
.getConstArray(), aInfos
.getLength(),
1171 compare_OUString_Property_Impl
);
1173 throw UnknownPropertyException();
1178 //========================================================================
1179 sal_Bool
OPropertyArrayHelper::hasPropertyByName(const OUString
& aPropertyName
)
1182 pR
= (Property
*)bsearch( &aPropertyName
, aInfos
.getConstArray(), aInfos
.getLength(),
1184 compare_OUString_Property_Impl
);
1188 //========================================================================
1189 sal_Int32
OPropertyArrayHelper::getHandleByName( const OUString
& rPropName
)
1192 pR
= (Property
*)bsearch( &rPropName
, aInfos
.getConstArray(), aInfos
.getLength(),
1194 compare_OUString_Property_Impl
);
1195 return pR
? pR
->Handle
: -1;
1198 //========================================================================
1199 sal_Int32
OPropertyArrayHelper::fillHandles( sal_Int32
* pHandles
, const Sequence
< OUString
> & rPropNames
)
1201 sal_Int32 nHitCount
= 0;
1202 const OUString
* pReqProps
= rPropNames
.getConstArray();
1203 sal_Int32 nReqLen
= rPropNames
.getLength();
1204 const Property
* pCur
= aInfos
.getConstArray();
1205 const Property
* pEnd
= pCur
+ aInfos
.getLength();
1207 for( sal_Int32 i
= 0; i
< nReqLen
; i
++ )
1209 // Calculate logarithm
1210 sal_Int32 n
= (sal_Int32
)(pEnd
- pCur
);
1218 // Number of properties to search for * Log2 of the number of remaining
1219 // properties to search in.
1220 if( (nReqLen
- i
) * nLog
>= pEnd
- pCur
)
1222 // linear search is better
1223 while( pCur
< pEnd
&& pReqProps
[i
] > pCur
->Name
)
1227 if( pCur
< pEnd
&& pReqProps
[i
] == pCur
->Name
)
1229 pHandles
[i
] = pCur
->Handle
;
1237 // binary search is better
1238 sal_Int32 nCompVal
= 1;
1239 const Property
* pOldEnd
= pEnd
--;
1240 const Property
* pMid
= pCur
;
1242 while( nCompVal
!= 0 && pCur
<= pEnd
)
1244 pMid
= (pEnd
- pCur
) / 2 + pCur
;
1246 nCompVal
= pReqProps
[i
].compareTo( pMid
->Name
);
1256 pHandles
[i
] = pMid
->Handle
;
1260 else if( nCompVal
> 0 )
1276 } // end namespace cppu
1280 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */