1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 #include "osl/diagnose.h"
31 #include "cppuhelper/implbase1.hxx"
32 #include "cppuhelper/weak.hxx"
33 #include "cppuhelper/propshlp.hxx"
34 #include "cppuhelper/exc_hlp.hxx"
35 #include "com/sun/star/beans/PropertyAttribute.hpp"
36 #include "com/sun/star/lang/DisposedException.hpp"
40 using namespace com::sun::star::uno
;
41 using namespace com::sun::star::beans
;
42 using namespace com::sun::star::lang
;
45 using ::rtl::OUString
;
46 using ::rtl::OUStringToOString
;
50 IPropertyArrayHelper::~IPropertyArrayHelper()
54 inline const ::com::sun::star::uno::Type
& getPropertyTypeIdentifier( ) SAL_THROW(())
56 return ::getCppuType( (Reference
< XPropertyChangeListener
> *)0 );
58 inline const ::com::sun::star::uno::Type
& getPropertiesTypeIdentifier() SAL_THROW(())
60 return ::getCppuType( (Reference
< XPropertiesChangeListener
> *)0 );
62 inline const ::com::sun::star::uno::Type
& getVetoableTypeIdentifier() SAL_THROW(())
64 return ::getCppuType( (Reference
< XVetoableChangeListener
> *)0 );
69 static int compare_OUString_Property_Impl( const void *arg1
, const void *arg2
)
72 return ((OUString
*)arg1
)->compareTo( ((Property
*)arg2
)->Name
);
78 * The class which implements the PropertySetInfo interface.
81 class OPropertySetHelperInfo_Impl
82 : public WeakImplHelper1
< ::com::sun::star::beans::XPropertySetInfo
>
84 Sequence
< Property
> aInfos
;
87 OPropertySetHelperInfo_Impl( IPropertyArrayHelper
& rHelper_
) SAL_THROW(());
89 // XPropertySetInfo-methods
90 virtual Sequence
< Property
> SAL_CALL
getProperties(void) throw(::com::sun::star::uno::RuntimeException
);
91 virtual Property SAL_CALL
getPropertyByName(const OUString
& PropertyName
) throw(::com::sun::star::beans::UnknownPropertyException
, ::com::sun::star::uno::RuntimeException
);
92 virtual sal_Bool SAL_CALL
hasPropertyByName(const OUString
& PropertyName
) throw(::com::sun::star::uno::RuntimeException
);
97 * Create an object that implements XPropertySetInfo IPropertyArrayHelper.
99 OPropertySetHelperInfo_Impl::OPropertySetHelperInfo_Impl(
100 IPropertyArrayHelper
& rHelper_
)
102 :aInfos( rHelper_
.getProperties() )
107 * Return the sequence of properties, which are provided throug the constructor.
109 Sequence
< Property
> OPropertySetHelperInfo_Impl::getProperties(void) throw(::com::sun::star::uno::RuntimeException
)
116 * Return the sequence of properties, which are provided throug the constructor.
118 Property
OPropertySetHelperInfo_Impl::getPropertyByName( const OUString
& PropertyName
) throw(::com::sun::star::beans::UnknownPropertyException
, ::com::sun::star::uno::RuntimeException
)
121 pR
= (Property
*)bsearch( &PropertyName
, aInfos
.getConstArray(), aInfos
.getLength(),
123 compare_OUString_Property_Impl
);
125 throw UnknownPropertyException();
132 * Return the sequence of properties, which are provided throug the constructor.
134 sal_Bool
OPropertySetHelperInfo_Impl::hasPropertyByName( const OUString
& PropertyName
) throw(::com::sun::star::uno::RuntimeException
)
137 pR
= (Property
*)bsearch( &PropertyName
, aInfos
.getConstArray(), aInfos
.getLength(),
139 compare_OUString_Property_Impl
);
143 // ----------------------------------------------------
144 // class PropertySetHelper_Impl
145 // ----------------------------------------------------
146 class OPropertySetHelper::Impl
{
149 Impl( bool i_bIgnoreRuntimeExceptionsWhileFiring
,
150 IEventNotificationHook
*i_pFireEvents
152 :m_bIgnoreRuntimeExceptionsWhileFiring( i_bIgnoreRuntimeExceptionsWhileFiring
)
154 ,m_pFireEvents( i_pFireEvents
)
158 bool m_bIgnoreRuntimeExceptionsWhileFiring
;
160 class IEventNotificationHook
* const m_pFireEvents
;
162 ::std::vector
< sal_Int32
> m_handles
;
163 ::std::vector
< Any
> m_newValues
;
164 ::std::vector
< Any
> m_oldValues
;
168 // ----------------------------------------------------
169 // class PropertySetHelper
170 // ----------------------------------------------------
171 OPropertySetHelper::OPropertySetHelper(
172 OBroadcastHelper
& rBHelper_
) SAL_THROW(())
173 : rBHelper( rBHelper_
),
174 aBoundLC( rBHelper_
.rMutex
),
175 aVetoableLC( rBHelper_
.rMutex
),
176 m_pReserved( new Impl(false, 0) )
180 OPropertySetHelper::OPropertySetHelper(
181 OBroadcastHelper
& rBHelper_
, bool bIgnoreRuntimeExceptionsWhileFiring
)
182 : rBHelper( rBHelper_
),
183 aBoundLC( rBHelper_
.rMutex
),
184 aVetoableLC( rBHelper_
.rMutex
),
185 m_pReserved( new Impl( bIgnoreRuntimeExceptionsWhileFiring
, 0 ) )
189 OPropertySetHelper::OPropertySetHelper(
190 OBroadcastHelper
& rBHelper_
, IEventNotificationHook
* i_pFireEvents
,
191 bool bIgnoreRuntimeExceptionsWhileFiring
)
192 : rBHelper( rBHelper_
),
193 aBoundLC( rBHelper_
.rMutex
),
194 aVetoableLC( rBHelper_
.rMutex
),
196 new Impl( bIgnoreRuntimeExceptionsWhileFiring
, i_pFireEvents
) )
200 OPropertySetHelper2::OPropertySetHelper2(
201 OBroadcastHelper
& irBHelper
,
202 IEventNotificationHook
*i_pFireEvents
,
203 bool bIgnoreRuntimeExceptionsWhileFiring
)
204 :OPropertySetHelper( irBHelper
, i_pFireEvents
, bIgnoreRuntimeExceptionsWhileFiring
)
209 * You must call disposing before.
211 OPropertySetHelper::~OPropertySetHelper() SAL_THROW(())
214 OPropertySetHelper2::~OPropertySetHelper2() SAL_THROW(())
219 Any
OPropertySetHelper::queryInterface( const ::com::sun::star::uno::Type
& rType
)
220 throw (RuntimeException
)
222 return ::cppu::queryInterface(
224 static_cast< XPropertySet
* >( this ),
225 static_cast< XMultiPropertySet
* >( this ),
226 static_cast< XFastPropertySet
* >( this ) );
229 Any
OPropertySetHelper2::queryInterface( const ::com::sun::star::uno::Type
& rType
)
230 throw (RuntimeException
)
232 Any
cnd(cppu::queryInterface(rType
, static_cast< XPropertySetOption
* >(this)));
233 if ( cnd
.hasValue() )
236 return OPropertySetHelper::queryInterface(rType
);
240 * called from the derivee's XTypeProvider::getTypes implementation
242 ::com::sun::star::uno::Sequence
< ::com::sun::star::uno::Type
> OPropertySetHelper::getTypes()
243 throw (RuntimeException
)
245 Sequence
< ::com::sun::star::uno::Type
> aTypes( 4 );
246 aTypes
[ 0 ] = XPropertySet::static_type();
247 aTypes
[ 1 ] = XPropertySetOption::static_type();
248 aTypes
[ 2 ] = XMultiPropertySet::static_type();
249 aTypes
[ 3 ] = XFastPropertySet::static_type();
254 void OPropertySetHelper::disposing() SAL_THROW(())
256 // Create an event with this as sender
257 Reference
< XPropertySet
> rSource( (static_cast< XPropertySet
* >(this)) , UNO_QUERY
);
259 aEvt
.Source
= rSource
;
261 // inform all listeners to release this object
262 // The listener containers are automatically cleared
263 aBoundLC
.disposeAndClear( aEvt
);
264 aVetoableLC
.disposeAndClear( aEvt
);
267 Reference
< XPropertySetInfo
> OPropertySetHelper::createPropertySetInfo(
268 IPropertyArrayHelper
& rProperties
) SAL_THROW(())
270 return static_cast< XPropertySetInfo
* >( new OPropertySetHelperInfo_Impl( rProperties
) );
274 void OPropertySetHelper::setPropertyValue(
275 const OUString
& rPropertyName
, const Any
& rValue
)
276 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
)
279 IPropertyArrayHelper
& rPH
= getInfoHelper();
280 // map the name to the handle
281 sal_Int32 nHandle
= rPH
.getHandleByName( rPropertyName
);
282 // call the method of the XFastPropertySet interface
283 setFastPropertyValue( nHandle
, rValue
);
287 Any
OPropertySetHelper::getPropertyValue(
288 const OUString
& rPropertyName
)
289 throw(::com::sun::star::beans::UnknownPropertyException
, ::com::sun::star::lang::WrappedTargetException
, ::com::sun::star::uno::RuntimeException
)
292 IPropertyArrayHelper
& rPH
= getInfoHelper();
293 // map the name to the handle
294 sal_Int32 nHandle
= rPH
.getHandleByName( rPropertyName
);
295 // call the method of the XFastPropertySet interface
296 return getFastPropertyValue( nHandle
);
300 void OPropertySetHelper::addPropertyChangeListener(
301 const OUString
& rPropertyName
,
302 const Reference
< XPropertyChangeListener
> & rxListener
)
303 throw(::com::sun::star::beans::UnknownPropertyException
,
304 ::com::sun::star::lang::WrappedTargetException
,
305 ::com::sun::star::uno::RuntimeException
)
307 MutexGuard
aGuard( rBHelper
.rMutex
);
308 OSL_ENSURE( !rBHelper
.bInDispose
, "do not addPropertyChangeListener in the dispose call" );
309 OSL_ENSURE( !rBHelper
.bDisposed
, "object is disposed" );
310 if( !rBHelper
.bInDispose
&& !rBHelper
.bDisposed
)
312 // only add listeners if you are not disposed
313 // a listener with no name means all properties
314 if( !rPropertyName
.isEmpty() )
317 IPropertyArrayHelper
& rPH
= getInfoHelper();
318 // map the name to the handle
319 sal_Int32 nHandle
= rPH
.getHandleByName( rPropertyName
);
320 if( nHandle
== -1 ) {
321 // property not known throw exception
322 throw UnknownPropertyException() ;
325 sal_Int16 nAttributes
;
326 rPH
.fillPropertyMembersByHandle( NULL
, &nAttributes
, nHandle
);
327 if( !(nAttributes
& ::com::sun::star::beans::PropertyAttribute::BOUND
) )
329 OSL_FAIL( "add listener to an unbound property" );
330 // silent ignore this
333 // add the change listener to the helper container
335 aBoundLC
.addInterface( (sal_Int32
)nHandle
, rxListener
);
338 // add the change listener to the helper container
339 rBHelper
.aLC
.addInterface(
340 getPropertyTypeIdentifier( ),
348 void OPropertySetHelper::removePropertyChangeListener(
349 const OUString
& rPropertyName
,
350 const Reference
< XPropertyChangeListener
>& rxListener
)
351 throw(::com::sun::star::beans::UnknownPropertyException
,
352 ::com::sun::star::lang::WrappedTargetException
,
353 ::com::sun::star::uno::RuntimeException
)
355 MutexGuard
aGuard( rBHelper
.rMutex
);
356 OSL_ENSURE( !rBHelper
.bDisposed
, "object is disposed" );
357 // all listeners are automaticly released in a dispose call
358 if( !rBHelper
.bInDispose
&& !rBHelper
.bDisposed
)
360 if( !rPropertyName
.isEmpty() )
363 IPropertyArrayHelper
& rPH
= getInfoHelper();
364 // map the name to the handle
365 sal_Int32 nHandle
= rPH
.getHandleByName( rPropertyName
);
367 // property not known throw exception
368 throw UnknownPropertyException();
369 aBoundLC
.removeInterface( (sal_Int32
)nHandle
, rxListener
);
372 // remove the change listener to the helper container
373 rBHelper
.aLC
.removeInterface(
374 getPropertyTypeIdentifier( ),
382 void OPropertySetHelper::addVetoableChangeListener(
383 const OUString
& rPropertyName
,
384 const Reference
< XVetoableChangeListener
> & rxListener
)
385 throw(::com::sun::star::beans::UnknownPropertyException
,
386 ::com::sun::star::lang::WrappedTargetException
,
387 ::com::sun::star::uno::RuntimeException
)
389 MutexGuard
aGuard( rBHelper
.rMutex
);
390 OSL_ENSURE( !rBHelper
.bInDispose
, "do not addVetoableChangeListener in the dispose call" );
391 OSL_ENSURE( !rBHelper
.bDisposed
, "object is disposed" );
392 if( !rBHelper
.bInDispose
&& !rBHelper
.bDisposed
)
394 // only add listeners if you are not disposed
395 // a listener with no name means all properties
396 if( !rPropertyName
.isEmpty() )
399 IPropertyArrayHelper
& rPH
= getInfoHelper();
400 // map the name to the handle
401 sal_Int32 nHandle
= rPH
.getHandleByName( rPropertyName
);
402 if( nHandle
== -1 ) {
403 // property not known throw exception
404 throw UnknownPropertyException();
407 sal_Int16 nAttributes
;
408 rPH
.fillPropertyMembersByHandle( NULL
, &nAttributes
, nHandle
);
409 if( !(nAttributes
& PropertyAttribute::CONSTRAINED
) )
411 OSL_FAIL( "addVetoableChangeListener, and property is not constrained" );
412 // silent ignore this
415 // add the vetoable listener to the helper container
416 aVetoableLC
.addInterface( (sal_Int32
)nHandle
, rxListener
);
419 // add the vetoable listener to the helper container
420 rBHelper
.aLC
.addInterface(
421 getVetoableTypeIdentifier( ),
428 void OPropertySetHelper::removeVetoableChangeListener(
429 const OUString
& rPropertyName
,
430 const Reference
< XVetoableChangeListener
> & rxListener
)
431 throw(::com::sun::star::beans::UnknownPropertyException
,
432 ::com::sun::star::lang::WrappedTargetException
,
433 ::com::sun::star::uno::RuntimeException
)
435 MutexGuard
aGuard( rBHelper
.rMutex
);
436 OSL_ENSURE( !rBHelper
.bDisposed
, "object is disposed" );
437 // all listeners are automaticly released in a dispose call
438 if( !rBHelper
.bInDispose
&& !rBHelper
.bDisposed
)
440 if( !rPropertyName
.isEmpty() )
443 IPropertyArrayHelper
& rPH
= getInfoHelper();
444 // map the name to the handle
445 sal_Int32 nHandle
= rPH
.getHandleByName( rPropertyName
);
446 if( nHandle
== -1 ) {
447 // property not known throw exception
448 throw UnknownPropertyException();
450 // remove the vetoable listener to the helper container
451 aVetoableLC
.removeInterface( (sal_Int32
)nHandle
, rxListener
);
454 // add the vetoable listener to the helper container
455 rBHelper
.aLC
.removeInterface(
456 getVetoableTypeIdentifier( ),
462 void OPropertySetHelper::setDependentFastPropertyValue( sal_Int32 i_handle
, const ::com::sun::star::uno::Any
& i_value
)
464 //OSL_PRECOND( rBHelper.rMutex.isAcquired(), "OPropertySetHelper::setDependentFastPropertyValue: to be called with a locked mutex only!" );
465 // there is no such thing as Mutex.isAcquired, sadly ...
467 sal_Int16
nAttributes(0);
468 IPropertyArrayHelper
& rInfo
= getInfoHelper();
469 if ( !rInfo
.fillPropertyMembersByHandle( NULL
, &nAttributes
, i_handle
) )
471 throw UnknownPropertyException();
473 // no need to check for READONLY-ness of the property. The method is intended to be called internally, which
474 // implies it might be invoked for properties which are read-only to the instance's clients, but well allowed
475 // to change their value.
477 Any aConverted
, aOld
;
478 sal_Bool bChanged
= convertFastPropertyValue( aConverted
, aOld
, i_handle
, i_value
);
482 // don't fire vetoable events. This method is called with our mutex locked, so calling into listeners would not be
483 // a good idea. The caler is responsible for not invoking this for constrained properties.
484 OSL_ENSURE( ( nAttributes
& PropertyAttribute::CONSTRAINED
) == 0,
485 "OPropertySetHelper::setDependentFastPropertyValue: not to be used for constrained properties!" );
488 // actually set the new value
491 setFastPropertyValue_NoBroadcast( i_handle
, aConverted
);
493 catch (const UnknownPropertyException
& ) { throw; /* allowed to leave */ }
494 catch (const PropertyVetoException
& ) { throw; /* allowed to leave */ }
495 catch (const IllegalArgumentException
& ) { throw; /* allowed to leave */ }
496 catch (const WrappedTargetException
& ) { throw; /* allowed to leave */ }
497 catch (const RuntimeException
& ) { throw; /* allowed to leave */ }
498 catch (const Exception
& )
500 // not allowed to leave this meathod
501 WrappedTargetException aWrapped
;
502 aWrapped
.TargetException
<<= ::cppu::getCaughtException();
503 aWrapped
.Context
= static_cast< XPropertySet
* >( this );
507 // remember the handle/values, for the events to be fired later
508 m_pReserved
->m_handles
.push_back( i_handle
);
509 m_pReserved
->m_newValues
.push_back( aConverted
); // TODO: setFastPropertyValue notifies the unconverted value here ...?
510 m_pReserved
->m_oldValues
.push_back( aOld
);
514 void OPropertySetHelper::setFastPropertyValue( sal_Int32 nHandle
, const Any
& rValue
)
515 throw(::com::sun::star::beans::UnknownPropertyException
,
516 ::com::sun::star::beans::PropertyVetoException
,
517 ::com::sun::star::lang::IllegalArgumentException
,
518 ::com::sun::star::lang::WrappedTargetException
,
519 ::com::sun::star::uno::RuntimeException
)
521 OSL_ENSURE( !rBHelper
.bInDispose
, "do not setFastPropertyValue in the dispose call" );
522 OSL_ENSURE( !rBHelper
.bDisposed
, "object is disposed" );
524 IPropertyArrayHelper
& rInfo
= getInfoHelper();
525 sal_Int16 nAttributes
;
526 if( !rInfo
.fillPropertyMembersByHandle( NULL
, &nAttributes
, nHandle
) ) {
528 throw UnknownPropertyException();
530 if( nAttributes
& PropertyAttribute::READONLY
)
531 throw PropertyVetoException();
536 // Will the property change?
539 MutexGuard
aGuard( rBHelper
.rMutex
);
540 bChanged
= convertFastPropertyValue( aConvertedVal
, aOldVal
, nHandle
, rValue
);
541 // release guard to fire events
545 // Is it a constrained property?
546 if( nAttributes
& PropertyAttribute::CONSTRAINED
)
548 // In aValue is the converted rValue
549 // fire a constarined event
550 // second parameter NULL means constrained
551 fire( &nHandle
, &rValue
, &aOldVal
, 1, sal_True
);
555 MutexGuard
aGuard( rBHelper
.rMutex
);
558 // set the property to the new value
559 setFastPropertyValue_NoBroadcast( nHandle
, aConvertedVal
);
561 catch (const ::com::sun::star::beans::UnknownPropertyException
& ) { throw; /* allowed to leave */ }
562 catch (const ::com::sun::star::beans::PropertyVetoException
& ) { throw; /* allowed to leave */ }
563 catch (const ::com::sun::star::lang::IllegalArgumentException
& ) { throw; /* allowed to leave */ }
564 catch (const ::com::sun::star::lang::WrappedTargetException
& ) { throw; /* allowed to leave */ }
565 catch (const ::com::sun::star::uno::RuntimeException
& ) { throw; /* allowed to leave */ }
566 catch (const ::com::sun::star::uno::Exception
& e
)
568 // not allowed to leave this meathod
569 ::com::sun::star::lang::WrappedTargetException aWrap
;
570 aWrap
.Context
= static_cast< ::com::sun::star::beans::XPropertySet
* >( this );
571 aWrap
.TargetException
<<= e
;
573 throw ::com::sun::star::lang::WrappedTargetException( aWrap
);
576 // release guard to fire events
578 // file a change event, if the value changed
579 impl_fireAll( &nHandle
, &rValue
, &aOldVal
, 1 );
584 Any
OPropertySetHelper::getFastPropertyValue( sal_Int32 nHandle
)
585 throw(::com::sun::star::beans::UnknownPropertyException
,
586 ::com::sun::star::lang::WrappedTargetException
,
587 ::com::sun::star::uno::RuntimeException
)
590 IPropertyArrayHelper
& rInfo
= getInfoHelper();
591 if( !rInfo
.fillPropertyMembersByHandle( NULL
, NULL
, nHandle
) )
593 throw UnknownPropertyException();
596 MutexGuard
aGuard( rBHelper
.rMutex
);
597 getFastPropertyValue( aRet
, nHandle
);
601 //--------------------------------------------------------------------------
602 void OPropertySetHelper::impl_fireAll( sal_Int32
* i_handles
, const Any
* i_newValues
, const Any
* i_oldValues
, sal_Int32 i_count
)
604 ClearableMutexGuard
aGuard( rBHelper
.rMutex
);
605 if ( m_pReserved
->m_handles
.empty() )
608 fire( i_handles
, i_newValues
, i_oldValues
, i_count
, sal_False
);
612 const size_t additionalEvents
= m_pReserved
->m_handles
.size();
613 OSL_ENSURE( additionalEvents
== m_pReserved
->m_newValues
.size()
614 && additionalEvents
== m_pReserved
->m_oldValues
.size(),
615 "OPropertySetHelper::impl_fireAll: inconsistency!" );
617 ::std::vector
< sal_Int32
> allHandles( additionalEvents
+ i_count
);
618 ::std::copy( m_pReserved
->m_handles
.begin(), m_pReserved
->m_handles
.end(), allHandles
.begin() );
619 ::std::copy( i_handles
, i_handles
+ i_count
, allHandles
.begin() + additionalEvents
);
621 ::std::vector
< Any
> allNewValues( additionalEvents
+ i_count
);
622 ::std::copy( m_pReserved
->m_newValues
.begin(), m_pReserved
->m_newValues
.end(), allNewValues
.begin() );
623 ::std::copy( i_newValues
, i_newValues
+ i_count
, allNewValues
.begin() + additionalEvents
);
625 ::std::vector
< Any
> allOldValues( additionalEvents
+ i_count
);
626 ::std::copy( m_pReserved
->m_oldValues
.begin(), m_pReserved
->m_oldValues
.end(), allOldValues
.begin() );
627 ::std::copy( i_oldValues
, i_oldValues
+ i_count
, allOldValues
.begin() + additionalEvents
);
629 m_pReserved
->m_handles
.clear();
630 m_pReserved
->m_newValues
.clear();
631 m_pReserved
->m_oldValues
.clear();
634 fire( &allHandles
[0], &allNewValues
[0], &allOldValues
[0], additionalEvents
+ i_count
, sal_False
);
637 //--------------------------------------------------------------------------
638 void OPropertySetHelper::fire
640 sal_Int32
* pnHandles
,
641 const Any
* pNewValues
,
642 const Any
* pOldValues
,
643 sal_Int32 nHandles
, // These is the Count of the array
647 OSL_ENSURE( m_pReserved
.get(), "No OPropertySetHelper::Impl" );
649 if (! m_pReserved
->m_bFireEvents
)
652 if (m_pReserved
->m_pFireEvents
) {
653 m_pReserved
->m_pFireEvents
->fireEvents(
654 pnHandles
, nHandles
, bVetoable
,
655 m_pReserved
->m_bIgnoreRuntimeExceptionsWhileFiring
);
658 // Only fire, if one or more properties changed
661 // create the event sequence of all changed properties
662 Sequence
< PropertyChangeEvent
> aEvts( nHandles
);
663 PropertyChangeEvent
* pEvts
= aEvts
.getArray();
664 Reference
< XInterface
> xSource( (XPropertySet
*)this, UNO_QUERY
);
666 sal_Int32 nChangesLen
= 0;
667 // Loop over all changed properties to fill the event struct
668 for( i
= 0; i
< nHandles
; i
++ )
670 // Vetoable fire and constrained attribute set or
671 // Change fire and Changed and bound attribute set
672 IPropertyArrayHelper
& rInfo
= getInfoHelper();
673 sal_Int16 nAttributes
;
675 rInfo
.fillPropertyMembersByHandle( &aPropName
, &nAttributes
, pnHandles
[i
] );
678 (bVetoable
&& (nAttributes
& PropertyAttribute::CONSTRAINED
)) ||
679 (!bVetoable
&& (nAttributes
& PropertyAttribute::BOUND
))
682 pEvts
[nChangesLen
].Source
= xSource
;
683 pEvts
[nChangesLen
].PropertyName
= aPropName
;
684 pEvts
[nChangesLen
].PropertyHandle
= pnHandles
[i
];
685 pEvts
[nChangesLen
].OldValue
= pOldValues
[i
];
686 pEvts
[nChangesLen
].NewValue
= pNewValues
[i
];
691 bool bIgnoreRuntimeExceptionsWhileFiring
=
692 m_pReserved
->m_bIgnoreRuntimeExceptionsWhileFiring
;
694 // fire the events for all changed properties
695 for( i
= 0; i
< nChangesLen
; i
++ )
697 // get the listener container for the property name
698 OInterfaceContainerHelper
* pLC
;
699 if( bVetoable
) // fire change Events?
700 pLC
= aVetoableLC
.getContainer( pEvts
[i
].PropertyHandle
);
702 pLC
= aBoundLC
.getContainer( pEvts
[i
].PropertyHandle
);
705 // Iterate over all listeners and send events
706 OInterfaceIteratorHelper
aIt( *pLC
);
707 while( aIt
.hasMoreElements() )
709 XInterface
* pL
= aIt
.next();
714 if( bVetoable
) // fire change Events?
716 ((XVetoableChangeListener
*)pL
)->vetoableChange(
721 ((XPropertyChangeListener
*)pL
)->propertyChange(
725 catch (DisposedException
& exc
)
727 OSL_ENSURE( exc
.Context
.is(),
728 "DisposedException without Context!" );
729 if (exc
.Context
== pL
)
735 catch (RuntimeException
& exc
)
739 OUString( RTL_CONSTASCII_USTRINGPARAM(
740 "caught RuntimeException while "
741 "firing listeners: ") ) +
742 exc
.Message
, RTL_TEXTENCODING_UTF8
).getStr() );
743 if (! bIgnoreRuntimeExceptionsWhileFiring
)
748 // broadcast to all listeners with "" property name
750 // fire change Events?
751 pLC
= rBHelper
.aLC
.getContainer(
752 getVetoableTypeIdentifier()
756 pLC
= rBHelper
.aLC
.getContainer(
757 getPropertyTypeIdentifier( )
762 // Iterate over all listeners and send events.
763 OInterfaceIteratorHelper
aIt( *pLC
);
764 while( aIt
.hasMoreElements() )
766 XInterface
* pL
= aIt
.next();
771 if( bVetoable
) // fire change Events?
773 ((XVetoableChangeListener
*)pL
)->vetoableChange(
778 ((XPropertyChangeListener
*)pL
)->propertyChange(
782 catch (DisposedException
& exc
)
784 OSL_ENSURE( exc
.Context
.is(),
785 "DisposedException without Context!" );
786 if (exc
.Context
== pL
)
792 catch (RuntimeException
& exc
)
796 OUString( RTL_CONSTASCII_USTRINGPARAM(
797 "caught RuntimeException while "
798 "firing listeners: ") ) +
799 exc
.Message
, RTL_TEXTENCODING_UTF8
).getStr() );
800 if (! bIgnoreRuntimeExceptionsWhileFiring
)
807 // reduce array to changed properties
808 aEvts
.realloc( nChangesLen
);
812 OInterfaceContainerHelper
* pCont
= 0;
813 pCont
= rBHelper
.aLC
.getContainer(
814 getPropertiesTypeIdentifier( )
818 // Here is a Bug, unbound properties are also fired
819 OInterfaceIteratorHelper
aIt( *pCont
);
820 while( aIt
.hasMoreElements() )
822 XPropertiesChangeListener
* pL
=
823 (XPropertiesChangeListener
*)aIt
.next();
828 // fire the hole event sequence to the
829 // XPropertiesChangeListener's
830 pL
->propertiesChange( aEvts
);
832 catch (DisposedException
& exc
)
834 OSL_ENSURE( exc
.Context
.is(),
835 "DisposedException without Context!" );
836 if (exc
.Context
== pL
)
842 catch (RuntimeException
& exc
)
846 OUString( RTL_CONSTASCII_USTRINGPARAM(
847 "caught RuntimeException while "
848 "firing listeners: ") ) +
849 exc
.Message
, RTL_TEXTENCODING_UTF8
).getStr() );
850 if (! bIgnoreRuntimeExceptionsWhileFiring
)
859 // OPropertySetHelper
860 void OPropertySetHelper::setFastPropertyValues(
862 sal_Int32
* pHandles
,
864 sal_Int32 nHitCount
)
865 SAL_THROW( (::com::sun::star::uno::Exception
) )
867 OSL_ENSURE( !rBHelper
.bInDispose
, "do not getFastPropertyValue in the dispose call" );
868 OSL_ENSURE( !rBHelper
.bDisposed
, "object is disposed" );
870 Any
* pConvertedValues
= NULL
;
871 Any
* pOldValues
= NULL
;
876 IPropertyArrayHelper
& rPH
= getInfoHelper();
878 pConvertedValues
= new Any
[ nHitCount
];
879 pOldValues
= new Any
[ nHitCount
];
884 // must lock the mutex outside the loop. So all values are consistent.
885 MutexGuard
aGuard( rBHelper
.rMutex
);
886 for( i
= 0; i
< nSeqLen
; i
++ )
888 if( pHandles
[i
] != -1 )
890 sal_Int16 nAttributes
;
891 rPH
.fillPropertyMembersByHandle( NULL
, &nAttributes
, pHandles
[i
] );
892 if( nAttributes
& PropertyAttribute::READONLY
) {
893 throw PropertyVetoException();
895 // Will the property change?
896 if( convertFastPropertyValue( pConvertedValues
[ n
], pOldValues
[n
],
897 pHandles
[i
], pValues
[i
] ) )
899 // only increment if the property really change
900 pHandles
[n
] = pHandles
[i
];
905 // release guard to fire events
908 // fire vetoable events
909 fire( pHandles
, pConvertedValues
, pOldValues
, n
, sal_True
);
912 // must lock the mutex outside the loop.
913 MutexGuard
aGuard( rBHelper
.rMutex
);
914 // Loop over all changed properties
915 for( i
= 0; i
< n
; i
++ )
917 // Will the property change?
918 setFastPropertyValue_NoBroadcast( pHandles
[i
], pConvertedValues
[i
] );
920 // release guard to fire events
923 // fire change events
924 impl_fireAll( pHandles
, pConvertedValues
, pOldValues
, n
);
928 delete [] pOldValues
;
929 delete [] pConvertedValues
;
932 delete [] pOldValues
;
933 delete [] pConvertedValues
;
938 * The sequence may be conatain not known properties. The implementation
939 * must ignore these properties.
941 void OPropertySetHelper::setPropertyValues(
942 const Sequence
<OUString
>& rPropertyNames
,
943 const Sequence
<Any
>& rValues
)
944 throw(::com::sun::star::beans::PropertyVetoException
, ::com::sun::star::lang::IllegalArgumentException
, ::com::sun::star::lang::WrappedTargetException
, ::com::sun::star::uno::RuntimeException
)
946 sal_Int32
* pHandles
= NULL
;
949 sal_Int32 nSeqLen
= rPropertyNames
.getLength();
950 pHandles
= new sal_Int32
[ nSeqLen
];
952 IPropertyArrayHelper
& rPH
= getInfoHelper();
953 // fill the handle array
954 sal_Int32 nHitCount
= rPH
.fillHandles( pHandles
, rPropertyNames
);
956 setFastPropertyValues( nSeqLen
, pHandles
, rValues
.getConstArray(), nHitCount
);
967 Sequence
<Any
> OPropertySetHelper::getPropertyValues( const Sequence
<OUString
>& rPropertyNames
)
968 throw(::com::sun::star::uno::RuntimeException
)
970 sal_Int32 nSeqLen
= rPropertyNames
.getLength();
971 sal_Int32
* pHandles
= new sal_Int32
[ nSeqLen
];
972 Sequence
< Any
> aValues( nSeqLen
);
975 IPropertyArrayHelper
& rPH
= getInfoHelper();
976 // fill the handle array
977 rPH
.fillHandles( pHandles
, rPropertyNames
);
979 Any
* pValues
= aValues
.getArray();
981 MutexGuard
aGuard( rBHelper
.rMutex
);
982 // fill the sequence with the values
983 for( sal_Int32 i
= 0; i
< nSeqLen
; i
++ )
984 getFastPropertyValue( pValues
[i
], pHandles
[i
] );
991 void OPropertySetHelper::addPropertiesChangeListener(
992 const Sequence
<OUString
> & ,
993 const Reference
< XPropertiesChangeListener
> & rListener
)
994 throw(::com::sun::star::uno::RuntimeException
)
996 rBHelper
.addListener( getCppuType(&rListener
) , rListener
);
1000 void OPropertySetHelper::removePropertiesChangeListener(
1001 const Reference
< XPropertiesChangeListener
> & rListener
)
1002 throw(::com::sun::star::uno::RuntimeException
)
1004 rBHelper
.removeListener( getCppuType(&rListener
) , rListener
);
1007 // XMultiPropertySet
1008 void OPropertySetHelper::firePropertiesChangeEvent(
1009 const Sequence
<OUString
>& rPropertyNames
,
1010 const Reference
< XPropertiesChangeListener
>& rListener
)
1011 throw(::com::sun::star::uno::RuntimeException
)
1013 sal_Int32 nLen
= rPropertyNames
.getLength();
1014 sal_Int32
* pHandles
= new sal_Int32
[nLen
];
1015 IPropertyArrayHelper
& rPH
= getInfoHelper();
1016 rPH
.fillHandles( pHandles
, rPropertyNames
);
1017 const OUString
* pNames
= rPropertyNames
.getConstArray();
1019 // get the count of matching properties
1020 sal_Int32 nFireLen
= 0;
1022 for( i
= 0; i
< nLen
; i
++ )
1023 if( pHandles
[i
] != -1 )
1026 Sequence
<PropertyChangeEvent
> aChanges( nFireLen
);
1027 PropertyChangeEvent
* pChanges
= aChanges
.getArray();
1030 // must lock the mutex outside the loop. So all values are consistent.
1031 MutexGuard
aGuard( rBHelper
.rMutex
);
1032 Reference
< XInterface
> xSource( (XPropertySet
*)this, UNO_QUERY
);
1033 sal_Int32 nFirePos
= 0;
1034 for( i
= 0; i
< nLen
; i
++ )
1036 if( pHandles
[i
] != -1 )
1038 pChanges
[nFirePos
].Source
= xSource
;
1039 pChanges
[nFirePos
].PropertyName
= pNames
[i
];
1040 pChanges
[nFirePos
].PropertyHandle
= pHandles
[i
];
1041 getFastPropertyValue( pChanges
[nFirePos
].OldValue
, pHandles
[i
] );
1042 pChanges
[nFirePos
].NewValue
= pChanges
[nFirePos
].OldValue
;
1046 // release guard to fire events
1049 rListener
->propertiesChange( aChanges
);
1054 void OPropertySetHelper2::enableChangeListenerNotification( sal_Bool bEnable
)
1055 throw(::com::sun::star::uno::RuntimeException
)
1057 m_pReserved
->m_bFireEvents
= bEnable
;
1060 //========================================================================
1061 //== OPropertyArrayHelper ================================================
1062 //========================================================================
1066 static int compare_Property_Impl( const void *arg1
, const void *arg2
)
1067 SAL_THROW_EXTERN_C()
1069 return ((Property
*)arg1
)->Name
.compareTo( ((Property
*)arg2
)->Name
);
1074 void OPropertyArrayHelper::init( sal_Bool bSorted
) SAL_THROW(())
1076 sal_Int32 i
, nElements
= aInfos
.getLength();
1077 const Property
* pProperties
= aInfos
.getConstArray();
1079 for( i
= 1; i
< nElements
; i
++ )
1081 if( pProperties
[i
-1].Name
>= pProperties
[i
].Name
)
1084 OSL_FAIL( "Property array is not sorted" );
1087 qsort( aInfos
.getArray(), nElements
, sizeof( Property
),
1088 compare_Property_Impl
);
1092 // may be that the array is resorted
1093 pProperties
= aInfos
.getConstArray();
1094 for( i
= 0; i
< nElements
; i
++ )
1095 if( pProperties
[i
].Handle
!= i
)
1097 // The handle is the index
1098 bRightOrdered
= sal_True
;
1101 OPropertyArrayHelper::OPropertyArrayHelper(
1106 : aInfos(pProps
, nEle
)
1107 , bRightOrdered( sal_False
)
1112 OPropertyArrayHelper::OPropertyArrayHelper(
1113 const Sequence
< Property
> & aProps
,
1117 , bRightOrdered( sal_False
)
1122 //========================================================================
1123 sal_Int32
OPropertyArrayHelper::getCount() const
1125 return aInfos
.getLength();
1128 //========================================================================
1129 sal_Bool
OPropertyArrayHelper::fillPropertyMembersByHandle
1131 OUString
* pPropName
,
1132 sal_Int16
* pAttributes
,
1136 const Property
* pProperties
= aInfos
.getConstArray();
1137 sal_Int32 nElements
= aInfos
.getLength();
1141 if( nHandle
< 0 || nHandle
>= nElements
)
1144 *pPropName
= pProperties
[ nHandle
].Name
;
1146 *pAttributes
= pProperties
[ nHandle
].Attributes
;
1151 // normally the array is sorted
1152 for( sal_Int32 i
= 0; i
< nElements
; i
++ )
1154 if( pProperties
[i
].Handle
== nHandle
)
1157 *pPropName
= pProperties
[ i
].Name
;
1159 *pAttributes
= pProperties
[ i
].Attributes
;
1167 //========================================================================
1168 Sequence
< Property
> OPropertyArrayHelper::getProperties(void)
1173 //========================================================================
1174 Property
OPropertyArrayHelper::getPropertyByName(const OUString
& aPropertyName
)
1175 throw (UnknownPropertyException
)
1178 pR
= (Property
*)bsearch( &aPropertyName
, aInfos
.getConstArray(), aInfos
.getLength(),
1180 compare_OUString_Property_Impl
);
1182 throw UnknownPropertyException();
1187 //========================================================================
1188 sal_Bool
OPropertyArrayHelper::hasPropertyByName(const OUString
& aPropertyName
)
1191 pR
= (Property
*)bsearch( &aPropertyName
, aInfos
.getConstArray(), aInfos
.getLength(),
1193 compare_OUString_Property_Impl
);
1197 //========================================================================
1198 sal_Int32
OPropertyArrayHelper::getHandleByName( const OUString
& rPropName
)
1201 pR
= (Property
*)bsearch( &rPropName
, aInfos
.getConstArray(), aInfos
.getLength(),
1203 compare_OUString_Property_Impl
);
1204 return pR
? pR
->Handle
: -1;
1207 //========================================================================
1208 sal_Int32
OPropertyArrayHelper::fillHandles( sal_Int32
* pHandles
, const Sequence
< OUString
> & rPropNames
)
1210 sal_Int32 nHitCount
= 0;
1211 const OUString
* pReqProps
= rPropNames
.getConstArray();
1212 sal_Int32 nReqLen
= rPropNames
.getLength();
1213 const Property
* pCur
= aInfos
.getConstArray();
1214 const Property
* pEnd
= pCur
+ aInfos
.getLength();
1216 for( sal_Int32 i
= 0; i
< nReqLen
; i
++ )
1218 // Calculate logarithm
1219 sal_Int32 n
= (sal_Int32
)(pEnd
- pCur
);
1227 // Number of properties to search for * Log2 of the number of remaining
1228 // properties to search in.
1229 if( (nReqLen
- i
) * nLog
>= pEnd
- pCur
)
1231 // linear search is better
1232 while( pCur
< pEnd
&& pReqProps
[i
] > pCur
->Name
)
1236 if( pCur
< pEnd
&& pReqProps
[i
] == pCur
->Name
)
1238 pHandles
[i
] = pCur
->Handle
;
1246 // binary search is better
1247 sal_Int32 nCompVal
= 1;
1248 const Property
* pOldEnd
= pEnd
--;
1249 const Property
* pMid
= pCur
;
1251 while( nCompVal
!= 0 && pCur
<= pEnd
)
1253 pMid
= (pEnd
- pCur
) / 2 + pCur
;
1255 nCompVal
= pReqProps
[i
].compareTo( pMid
->Name
);
1265 pHandles
[i
] = pMid
->Handle
;
1269 else if( nCompVal
> 0 )
1285 } // end namespace cppu
1289 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */