1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: propshlp.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_cppuhelper.hxx"
34 #include "osl/diagnose.h"
35 #include "cppuhelper/implbase1.hxx"
36 #include "cppuhelper/weak.hxx"
37 #include "cppuhelper/propshlp.hxx"
38 #include "com/sun/star/beans/PropertyAttribute.hpp"
39 #include "com/sun/star/lang/DisposedException.hpp"
43 using namespace com::sun::star::uno
;
44 using namespace com::sun::star::beans
;
45 using namespace com::sun::star::lang
;
51 IPropertyArrayHelper::~IPropertyArrayHelper()
55 inline const ::com::sun::star::uno::Type
& getPropertyTypeIdentifier( ) SAL_THROW( () )
57 return ::getCppuType( (Reference
< XPropertyChangeListener
> *)0 );
59 inline const ::com::sun::star::uno::Type
& getPropertiesTypeIdentifier() SAL_THROW( () )
61 return ::getCppuType( (Reference
< XPropertiesChangeListener
> *)0 );
63 inline const ::com::sun::star::uno::Type
& getVetoableTypeIdentifier() SAL_THROW( () )
65 return ::getCppuType( (Reference
< XVetoableChangeListener
> *)0 );
70 static int compare_OUString_Property_Impl( const void *arg1
, const void *arg2
)
73 return ((OUString
*)arg1
)->compareTo( ((Property
*)arg2
)->Name
);
79 * The class which implements the PropertySetInfo interface.
82 class OPropertySetHelperInfo_Impl
83 : public WeakImplHelper1
< ::com::sun::star::beans::XPropertySetInfo
>
85 Sequence
< Property
> aInfos
;
88 OPropertySetHelperInfo_Impl( IPropertyArrayHelper
& rHelper_
) SAL_THROW( () );
90 // XPropertySetInfo-Methoden
91 virtual Sequence
< Property
> SAL_CALL
getProperties(void) throw(::com::sun::star::uno::RuntimeException
);
92 virtual Property SAL_CALL
getPropertyByName(const OUString
& PropertyName
) throw(::com::sun::star::beans::UnknownPropertyException
, ::com::sun::star::uno::RuntimeException
);
93 virtual sal_Bool SAL_CALL
hasPropertyByName(const OUString
& PropertyName
) throw(::com::sun::star::uno::RuntimeException
);
98 * Create an object that implements XPropertySetInfo IPropertyArrayHelper.
100 OPropertySetHelperInfo_Impl::OPropertySetHelperInfo_Impl(
101 IPropertyArrayHelper
& rHelper_
)
103 :aInfos( rHelper_
.getProperties() )
108 * Return the sequence of properties, which are provided throug the constructor.
110 Sequence
< Property
> OPropertySetHelperInfo_Impl::getProperties(void) throw(::com::sun::star::uno::RuntimeException
)
117 * Return the sequence of properties, which are provided throug the constructor.
119 Property
OPropertySetHelperInfo_Impl::getPropertyByName( const OUString
& PropertyName
) throw(::com::sun::star::beans::UnknownPropertyException
, ::com::sun::star::uno::RuntimeException
)
122 pR
= (Property
*)bsearch( &PropertyName
, aInfos
.getConstArray(), aInfos
.getLength(),
124 compare_OUString_Property_Impl
);
126 throw UnknownPropertyException();
133 * Return the sequence of properties, which are provided throug the constructor.
135 sal_Bool
OPropertySetHelperInfo_Impl::hasPropertyByName( const OUString
& PropertyName
) throw(::com::sun::star::uno::RuntimeException
)
138 pR
= (Property
*)bsearch( &PropertyName
, aInfos
.getConstArray(), aInfos
.getLength(),
140 compare_OUString_Property_Impl
);
144 // ----------------------------------------------------
145 // class PropertySetHelper_Impl
146 // ----------------------------------------------------
147 class OPropertySetHelper::Impl
{
150 Impl ( bool i_bIgnoreRuntimeExceptionsWhileFiring
,
151 IEventNotificationHook
*i_pFireEvents
)
152 : m_bIgnoreRuntimeExceptionsWhileFiring(
153 i_bIgnoreRuntimeExceptionsWhileFiring
),
154 m_pFireEvents( i_pFireEvents
)
157 bool m_bIgnoreRuntimeExceptionsWhileFiring
;
158 class IEventNotificationHook
* const m_pFireEvents
;
162 // ----------------------------------------------------
163 // class PropertySetHelper
164 // ----------------------------------------------------
165 OPropertySetHelper::OPropertySetHelper(
166 OBroadcastHelper
& rBHelper_
) SAL_THROW( () )
167 : rBHelper( rBHelper_
),
168 aBoundLC( rBHelper_
.rMutex
),
169 aVetoableLC( rBHelper_
.rMutex
),
170 m_pReserved( new Impl(false, 0) )
174 OPropertySetHelper::OPropertySetHelper(
175 OBroadcastHelper
& rBHelper_
, bool bIgnoreRuntimeExceptionsWhileFiring
)
176 : rBHelper( rBHelper_
),
177 aBoundLC( rBHelper_
.rMutex
),
178 aVetoableLC( rBHelper_
.rMutex
),
179 m_pReserved( new Impl( bIgnoreRuntimeExceptionsWhileFiring
, 0 ) )
183 OPropertySetHelper::OPropertySetHelper(
184 OBroadcastHelper
& rBHelper_
, IEventNotificationHook
* i_pFireEvents
,
185 bool bIgnoreRuntimeExceptionsWhileFiring
)
186 : rBHelper( rBHelper_
),
187 aBoundLC( rBHelper_
.rMutex
),
188 aVetoableLC( rBHelper_
.rMutex
),
190 new Impl( bIgnoreRuntimeExceptionsWhileFiring
, i_pFireEvents
) )
195 * You must call disposing before.
197 OPropertySetHelper::~OPropertySetHelper() SAL_THROW( () )
202 * These method is called from queryInterface, if no delegator is set.
203 * Otherwise this method is called from the delegator.
206 Any
OPropertySetHelper::queryInterface( const ::com::sun::star::uno::Type
& rType
)
207 throw (RuntimeException
)
209 return ::cppu::queryInterface(
211 static_cast< XPropertySet
* >( this ),
212 static_cast< XMultiPropertySet
* >( this ),
213 static_cast< XFastPropertySet
* >( this ) );
217 * called from the derivee's XTypeProvider::getTypes implementation
219 ::com::sun::star::uno::Sequence
< ::com::sun::star::uno::Type
> OPropertySetHelper::getTypes()
220 throw (RuntimeException
)
222 Sequence
< ::com::sun::star::uno::Type
> aTypes( 3 );
223 aTypes
[ 0 ] = XPropertySet::static_type();
224 aTypes
[ 1 ] = XMultiPropertySet::static_type();
225 aTypes
[ 2 ] = XFastPropertySet::static_type();
230 void OPropertySetHelper::disposing() SAL_THROW( () )
232 // Create an event with this as sender
233 Reference
< XPropertySet
> rSource( SAL_STATIC_CAST( XPropertySet
* , this ) , UNO_QUERY
);
235 aEvt
.Source
= rSource
;
237 // inform all listeners to reelease this object
238 // The listener container are automaticly cleared
239 aBoundLC
.disposeAndClear( aEvt
);
240 aVetoableLC
.disposeAndClear( aEvt
);
243 Reference
< XPropertySetInfo
> OPropertySetHelper::createPropertySetInfo(
244 IPropertyArrayHelper
& rProperties
) SAL_THROW( () )
246 return static_cast< XPropertySetInfo
* >( new OPropertySetHelperInfo_Impl( rProperties
) );
250 void OPropertySetHelper::setPropertyValue(
251 const OUString
& rPropertyName
, const Any
& rValue
)
252 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
)
255 IPropertyArrayHelper
& rPH
= getInfoHelper();
256 // map the name to the handle
257 sal_Int32 nHandle
= rPH
.getHandleByName( rPropertyName
);
258 // call the method of the XFastPropertySet interface
259 setFastPropertyValue( nHandle
, rValue
);
263 Any
OPropertySetHelper::getPropertyValue(
264 const OUString
& rPropertyName
)
265 throw(::com::sun::star::beans::UnknownPropertyException
, ::com::sun::star::lang::WrappedTargetException
, ::com::sun::star::uno::RuntimeException
)
268 IPropertyArrayHelper
& rPH
= getInfoHelper();
269 // map the name to the handle
270 sal_Int32 nHandle
= rPH
.getHandleByName( rPropertyName
);
271 // call the method of the XFastPropertySet interface
272 return getFastPropertyValue( nHandle
);
276 void OPropertySetHelper::addPropertyChangeListener(
277 const OUString
& rPropertyName
,
278 const Reference
< XPropertyChangeListener
> & rxListener
)
279 throw(::com::sun::star::beans::UnknownPropertyException
,
280 ::com::sun::star::lang::WrappedTargetException
,
281 ::com::sun::star::uno::RuntimeException
)
283 MutexGuard
aGuard( rBHelper
.rMutex
);
284 OSL_ENSURE( !rBHelper
.bInDispose
, "do not addPropertyChangeListener in the dispose call" );
285 OSL_ENSURE( !rBHelper
.bDisposed
, "object is disposed" );
286 if( !rBHelper
.bInDispose
&& !rBHelper
.bDisposed
)
288 // only add listeners if you are not disposed
289 // a listener with no name means all properties
290 if( rPropertyName
.getLength() )
293 IPropertyArrayHelper
& rPH
= getInfoHelper();
294 // map the name to the handle
295 sal_Int32 nHandle
= rPH
.getHandleByName( rPropertyName
);
296 if( nHandle
== -1 ) {
297 // property not known throw exception
298 throw UnknownPropertyException() ;
301 sal_Int16 nAttributes
;
302 rPH
.fillPropertyMembersByHandle( NULL
, &nAttributes
, nHandle
);
303 if( !(nAttributes
& ::com::sun::star::beans::PropertyAttribute::BOUND
) )
305 OSL_ENSURE( sal_False
, "add listener to an unbound property" );
306 // silent ignore this
309 // add the change listener to the helper container
311 aBoundLC
.addInterface( (sal_Int32
)nHandle
, rxListener
);
314 // add the change listener to the helper container
315 rBHelper
.aLC
.addInterface(
316 getPropertyTypeIdentifier( ),
324 void OPropertySetHelper::removePropertyChangeListener(
325 const OUString
& rPropertyName
,
326 const Reference
< XPropertyChangeListener
>& rxListener
)
327 throw(::com::sun::star::beans::UnknownPropertyException
,
328 ::com::sun::star::lang::WrappedTargetException
,
329 ::com::sun::star::uno::RuntimeException
)
331 MutexGuard
aGuard( rBHelper
.rMutex
);
332 OSL_ENSURE( !rBHelper
.bDisposed
, "object is disposed" );
333 // all listeners are automaticly released in a dispose call
334 if( !rBHelper
.bInDispose
&& !rBHelper
.bDisposed
)
336 if( rPropertyName
.getLength() )
339 IPropertyArrayHelper
& rPH
= getInfoHelper();
340 // map the name to the handle
341 sal_Int32 nHandle
= rPH
.getHandleByName( rPropertyName
);
343 // property not known throw exception
344 throw UnknownPropertyException();
345 aBoundLC
.removeInterface( (sal_Int32
)nHandle
, rxListener
);
348 // remove the change listener to the helper container
349 rBHelper
.aLC
.removeInterface(
350 getPropertyTypeIdentifier( ),
358 void OPropertySetHelper::addVetoableChangeListener(
359 const OUString
& rPropertyName
,
360 const Reference
< XVetoableChangeListener
> & rxListener
)
361 throw(::com::sun::star::beans::UnknownPropertyException
,
362 ::com::sun::star::lang::WrappedTargetException
,
363 ::com::sun::star::uno::RuntimeException
)
365 MutexGuard
aGuard( rBHelper
.rMutex
);
366 OSL_ENSURE( !rBHelper
.bInDispose
, "do not addVetoableChangeListener in the dispose call" );
367 OSL_ENSURE( !rBHelper
.bDisposed
, "object is disposed" );
368 if( !rBHelper
.bInDispose
&& !rBHelper
.bDisposed
)
370 // only add listeners if you are not disposed
371 // a listener with no name means all properties
372 if( rPropertyName
.getLength() )
375 IPropertyArrayHelper
& rPH
= getInfoHelper();
376 // map the name to the handle
377 sal_Int32 nHandle
= rPH
.getHandleByName( rPropertyName
);
378 if( nHandle
== -1 ) {
379 // property not known throw exception
380 throw UnknownPropertyException();
383 sal_Int16 nAttributes
;
384 rPH
.fillPropertyMembersByHandle( NULL
, &nAttributes
, nHandle
);
385 if( !(nAttributes
& PropertyAttribute::CONSTRAINED
) )
387 OSL_ENSURE( sal_False
, "addVetoableChangeListener, and property is not constrained" );
388 // silent ignore this
391 // add the vetoable listener to the helper container
392 aVetoableLC
.addInterface( (sal_Int32
)nHandle
, rxListener
);
395 // add the vetoable listener to the helper container
396 rBHelper
.aLC
.addInterface(
397 getVetoableTypeIdentifier( ),
404 void OPropertySetHelper::removeVetoableChangeListener(
405 const OUString
& rPropertyName
,
406 const Reference
< XVetoableChangeListener
> & rxListener
)
407 throw(::com::sun::star::beans::UnknownPropertyException
,
408 ::com::sun::star::lang::WrappedTargetException
,
409 ::com::sun::star::uno::RuntimeException
)
411 MutexGuard
aGuard( rBHelper
.rMutex
);
412 OSL_ENSURE( !rBHelper
.bDisposed
, "object is disposed" );
413 // all listeners are automaticly released in a dispose call
414 if( !rBHelper
.bInDispose
&& !rBHelper
.bDisposed
)
416 if( rPropertyName
.getLength() )
419 IPropertyArrayHelper
& rPH
= getInfoHelper();
420 // map the name to the handle
421 sal_Int32 nHandle
= rPH
.getHandleByName( rPropertyName
);
422 if( nHandle
== -1 ) {
423 // property not known throw exception
424 throw UnknownPropertyException();
426 // remove the vetoable listener to the helper container
427 aVetoableLC
.removeInterface( (sal_Int32
)nHandle
, rxListener
);
430 // add the vetoable listener to the helper container
431 rBHelper
.aLC
.removeInterface(
432 getVetoableTypeIdentifier( ),
439 void OPropertySetHelper::setFastPropertyValue( sal_Int32 nHandle
, const Any
& rValue
)
440 throw(::com::sun::star::beans::UnknownPropertyException
,
441 ::com::sun::star::beans::PropertyVetoException
,
442 ::com::sun::star::lang::IllegalArgumentException
,
443 ::com::sun::star::lang::WrappedTargetException
,
444 ::com::sun::star::uno::RuntimeException
)
446 OSL_ENSURE( !rBHelper
.bInDispose
, "do not setFastPropertyValue in the dispose call" );
447 OSL_ENSURE( !rBHelper
.bDisposed
, "object is disposed" );
449 IPropertyArrayHelper
& rInfo
= getInfoHelper();
450 sal_Int16 nAttributes
;
451 if( !rInfo
.fillPropertyMembersByHandle( NULL
, &nAttributes
, nHandle
) ) {
453 throw UnknownPropertyException();
455 if( nAttributes
& PropertyAttribute::READONLY
)
456 throw PropertyVetoException();
461 // Will the property change?
464 MutexGuard
aGuard( rBHelper
.rMutex
);
465 bChanged
= convertFastPropertyValue( aConvertedVal
, aOldVal
, nHandle
, rValue
);
466 // release guard to fire events
470 // Is it a constrained property?
471 if( nAttributes
& PropertyAttribute::CONSTRAINED
)
473 // In aValue is the converted rValue
474 // fire a constarined event
475 // second parameter NULL means constrained
476 fire( &nHandle
, &rValue
, &aOldVal
, 1, sal_True
);
480 MutexGuard
aGuard( rBHelper
.rMutex
);
483 // set the property to the new value
484 setFastPropertyValue_NoBroadcast( nHandle
, aConvertedVal
);
486 catch (const ::com::sun::star::beans::UnknownPropertyException
& ) { throw; /* allowed to leave */ }
487 catch (const ::com::sun::star::beans::PropertyVetoException
& ) { throw; /* allowed to leave */ }
488 catch (const ::com::sun::star::lang::IllegalArgumentException
& ) { throw; /* allowed to leave */ }
489 catch (const ::com::sun::star::lang::WrappedTargetException
& ) { throw; /* allowed to leave */ }
490 catch (const ::com::sun::star::uno::RuntimeException
& ) { throw; /* allowed to leave */ }
491 catch (const ::com::sun::star::uno::Exception
& e
)
493 // not allowed to leave this meathod
494 ::com::sun::star::lang::WrappedTargetException aWrap
;
495 aWrap
.Context
= static_cast< ::com::sun::star::beans::XPropertySet
* >( this );
496 aWrap
.TargetException
<<= e
;
498 throw ::com::sun::star::lang::WrappedTargetException( aWrap
);
501 // release guard to fire events
503 // file a change event, if the value changed
504 fire( &nHandle
, &rValue
, &aOldVal
, 1, sal_False
);
509 Any
OPropertySetHelper::getFastPropertyValue( sal_Int32 nHandle
)
510 throw(::com::sun::star::beans::UnknownPropertyException
,
511 ::com::sun::star::lang::WrappedTargetException
,
512 ::com::sun::star::uno::RuntimeException
)
515 IPropertyArrayHelper
& rInfo
= getInfoHelper();
516 if( !rInfo
.fillPropertyMembersByHandle( NULL
, NULL
, nHandle
) )
518 throw UnknownPropertyException();
521 MutexGuard
aGuard( rBHelper
.rMutex
);
522 getFastPropertyValue( aRet
, nHandle
);
526 //--------------------------------------------------------------------------
527 void OPropertySetHelper::fire
529 sal_Int32
* pnHandles
,
530 const Any
* pNewValues
,
531 const Any
* pOldValues
,
532 sal_Int32 nHandles
, // These is the Count of the array
536 OSL_ENSURE( m_pReserved
.get(), "No OPropertySetHelper::Impl" );
537 if (m_pReserved
->m_pFireEvents
) {
538 m_pReserved
->m_pFireEvents
->fireEvents(
539 pnHandles
, nHandles
, bVetoable
,
540 m_pReserved
->m_bIgnoreRuntimeExceptionsWhileFiring
);
543 // Only fire, if one or more properties changed
546 // create the event sequence of all changed properties
547 Sequence
< PropertyChangeEvent
> aEvts( nHandles
);
548 PropertyChangeEvent
* pEvts
= aEvts
.getArray();
549 Reference
< XInterface
> xSource( (XPropertySet
*)this, UNO_QUERY
);
551 sal_Int32 nChangesLen
= 0;
552 // Loop over all changed properties to fill the event struct
553 for( i
= 0; i
< nHandles
; i
++ )
555 // Vetoable fire and constrained attribute set or
556 // Change fire and Changed and bound attribute set
557 IPropertyArrayHelper
& rInfo
= getInfoHelper();
558 sal_Int16 nAttributes
;
560 rInfo
.fillPropertyMembersByHandle( &aPropName
, &nAttributes
, pnHandles
[i
] );
563 (bVetoable
&& (nAttributes
& PropertyAttribute::CONSTRAINED
)) ||
564 (!bVetoable
&& (nAttributes
& PropertyAttribute::BOUND
))
567 pEvts
[nChangesLen
].Source
= xSource
;
568 pEvts
[nChangesLen
].PropertyName
= aPropName
;
569 pEvts
[nChangesLen
].PropertyHandle
= pnHandles
[i
];
570 pEvts
[nChangesLen
].OldValue
= pOldValues
[i
];
571 pEvts
[nChangesLen
].NewValue
= pNewValues
[i
];
576 bool bIgnoreRuntimeExceptionsWhileFiring
=
577 m_pReserved
->m_bIgnoreRuntimeExceptionsWhileFiring
;
579 // fire the events for all changed properties
580 for( i
= 0; i
< nChangesLen
; i
++ )
582 // get the listener container for the property name
583 OInterfaceContainerHelper
* pLC
;
584 if( bVetoable
) // fire change Events?
585 pLC
= aVetoableLC
.getContainer( pEvts
[i
].PropertyHandle
);
587 pLC
= aBoundLC
.getContainer( pEvts
[i
].PropertyHandle
);
590 // Ueber alle Listener iterieren und Events senden
591 OInterfaceIteratorHelper
aIt( *pLC
);
592 while( aIt
.hasMoreElements() )
594 XInterface
* pL
= aIt
.next();
599 if( bVetoable
) // fire change Events?
601 ((XVetoableChangeListener
*)pL
)->vetoableChange(
606 ((XPropertyChangeListener
*)pL
)->propertyChange(
610 catch (DisposedException
& exc
)
612 OSL_ENSURE( exc
.Context
.is(),
613 "DisposedException without Context!" );
614 if (exc
.Context
== pL
)
620 catch (RuntimeException
& exc
)
624 OUString( RTL_CONSTASCII_USTRINGPARAM(
625 "caught RuntimeException while "
626 "firing listeners: ") ) +
627 exc
.Message
, RTL_TEXTENCODING_UTF8
).getStr() );
628 if (! bIgnoreRuntimeExceptionsWhileFiring
)
633 // broadcast to all listeners with "" property name
635 // fire change Events?
636 pLC
= rBHelper
.aLC
.getContainer(
637 getVetoableTypeIdentifier()
641 pLC
= rBHelper
.aLC
.getContainer(
642 getPropertyTypeIdentifier( )
647 // Ueber alle Listener iterieren und Events senden
648 OInterfaceIteratorHelper
aIt( *pLC
);
649 while( aIt
.hasMoreElements() )
651 XInterface
* pL
= aIt
.next();
656 if( bVetoable
) // fire change Events?
658 ((XVetoableChangeListener
*)pL
)->vetoableChange(
663 ((XPropertyChangeListener
*)pL
)->propertyChange(
667 catch (DisposedException
& exc
)
669 OSL_ENSURE( exc
.Context
.is(),
670 "DisposedException without Context!" );
671 if (exc
.Context
== pL
)
677 catch (RuntimeException
& exc
)
681 OUString( RTL_CONSTASCII_USTRINGPARAM(
682 "caught RuntimeException while "
683 "firing listeners: ") ) +
684 exc
.Message
, RTL_TEXTENCODING_UTF8
).getStr() );
685 if (! bIgnoreRuntimeExceptionsWhileFiring
)
692 // reduce array to changed properties
693 aEvts
.realloc( nChangesLen
);
697 OInterfaceContainerHelper
* pCont
= 0;
698 pCont
= rBHelper
.aLC
.getContainer(
699 getPropertiesTypeIdentifier( )
703 // Here is a Bug, unbound properties are also fired
704 OInterfaceIteratorHelper
aIt( *pCont
);
705 while( aIt
.hasMoreElements() )
707 XPropertiesChangeListener
* pL
=
708 (XPropertiesChangeListener
*)aIt
.next();
713 // fire the hole event sequence to the
714 // XPropertiesChangeListener's
715 pL
->propertiesChange( aEvts
);
717 catch (DisposedException
& exc
)
719 OSL_ENSURE( exc
.Context
.is(),
720 "DisposedException without Context!" );
721 if (exc
.Context
== pL
)
727 catch (RuntimeException
& exc
)
731 OUString( RTL_CONSTASCII_USTRINGPARAM(
732 "caught RuntimeException while "
733 "firing listeners: ") ) +
734 exc
.Message
, RTL_TEXTENCODING_UTF8
).getStr() );
735 if (! bIgnoreRuntimeExceptionsWhileFiring
)
744 // OPropertySetHelper
745 void OPropertySetHelper::setFastPropertyValues(
747 sal_Int32
* pHandles
,
749 sal_Int32 nHitCount
)
750 SAL_THROW( (::com::sun::star::uno::Exception
) )
752 OSL_ENSURE( !rBHelper
.bInDispose
, "do not getFastPropertyValue in the dispose call" );
753 OSL_ENSURE( !rBHelper
.bDisposed
, "object is disposed" );
755 Any
* pConvertedValues
= NULL
;
756 Any
* pOldValues
= NULL
;
761 IPropertyArrayHelper
& rPH
= getInfoHelper();
763 pConvertedValues
= new Any
[ nHitCount
];
764 pOldValues
= new Any
[ nHitCount
];
769 // must lock the mutex outside the loop. So all values are consistent.
770 MutexGuard
aGuard( rBHelper
.rMutex
);
771 for( i
= 0; i
< nSeqLen
; i
++ )
773 if( pHandles
[i
] != -1 )
775 sal_Int16 nAttributes
;
776 rPH
.fillPropertyMembersByHandle( NULL
, &nAttributes
, pHandles
[i
] );
777 if( nAttributes
& PropertyAttribute::READONLY
) {
778 throw PropertyVetoException();
780 // Will the property change?
781 if( convertFastPropertyValue( pConvertedValues
[ n
], pOldValues
[n
],
782 pHandles
[i
], pValues
[i
] ) )
784 // only increment if the property really change
785 pHandles
[n
] = pHandles
[i
];
790 // release guard to fire events
793 // fire vetoable events
794 fire( pHandles
, pConvertedValues
, pOldValues
, n
, sal_True
);
797 // must lock the mutex outside the loop.
798 MutexGuard
aGuard( rBHelper
.rMutex
);
799 // Loop over all changed properties
800 for( i
= 0; i
< n
; i
++ )
802 // Will the property change?
803 setFastPropertyValue_NoBroadcast( pHandles
[i
], pConvertedValues
[i
] );
805 // release guard to fire events
808 // fire change events
809 fire( pHandles
, pConvertedValues
, pOldValues
, n
, sal_False
);
813 delete [] pOldValues
;
814 delete [] pConvertedValues
;
817 delete [] pOldValues
;
818 delete [] pConvertedValues
;
823 * The sequence may be conatain not known properties. The implementation
824 * must ignore these properties.
826 void OPropertySetHelper::setPropertyValues(
827 const Sequence
<OUString
>& rPropertyNames
,
828 const Sequence
<Any
>& rValues
)
829 throw(::com::sun::star::beans::PropertyVetoException
, ::com::sun::star::lang::IllegalArgumentException
, ::com::sun::star::lang::WrappedTargetException
, ::com::sun::star::uno::RuntimeException
)
831 sal_Int32
* pHandles
= NULL
;
834 sal_Int32 nSeqLen
= rPropertyNames
.getLength();
835 pHandles
= new sal_Int32
[ nSeqLen
];
837 IPropertyArrayHelper
& rPH
= getInfoHelper();
838 // fill the handle array
839 sal_Int32 nHitCount
= rPH
.fillHandles( pHandles
, rPropertyNames
);
841 setFastPropertyValues( nSeqLen
, pHandles
, rValues
.getConstArray(), nHitCount
);
852 Sequence
<Any
> OPropertySetHelper::getPropertyValues( const Sequence
<OUString
>& rPropertyNames
)
853 throw(::com::sun::star::uno::RuntimeException
)
855 sal_Int32 nSeqLen
= rPropertyNames
.getLength();
856 sal_Int32
* pHandles
= new sal_Int32
[ nSeqLen
];
857 Sequence
< Any
> aValues( nSeqLen
);
860 IPropertyArrayHelper
& rPH
= getInfoHelper();
861 // fill the handle array
862 rPH
.fillHandles( pHandles
, rPropertyNames
);
864 Any
* pValues
= aValues
.getArray();
866 MutexGuard
aGuard( rBHelper
.rMutex
);
867 // fill the sequence with the values
868 for( sal_Int32 i
= 0; i
< nSeqLen
; i
++ )
869 getFastPropertyValue( pValues
[i
], pHandles
[i
] );
876 void OPropertySetHelper::addPropertiesChangeListener(
877 const Sequence
<OUString
> & ,
878 const Reference
< XPropertiesChangeListener
> & rListener
)
879 throw(::com::sun::star::uno::RuntimeException
)
881 rBHelper
.addListener( getCppuType(&rListener
) , rListener
);
885 void OPropertySetHelper::removePropertiesChangeListener(
886 const Reference
< XPropertiesChangeListener
> & rListener
)
887 throw(::com::sun::star::uno::RuntimeException
)
889 rBHelper
.removeListener( getCppuType(&rListener
) , rListener
);
893 void OPropertySetHelper::firePropertiesChangeEvent(
894 const Sequence
<OUString
>& rPropertyNames
,
895 const Reference
< XPropertiesChangeListener
>& rListener
)
896 throw(::com::sun::star::uno::RuntimeException
)
898 sal_Int32 nLen
= rPropertyNames
.getLength();
899 sal_Int32
* pHandles
= new sal_Int32
[nLen
];
900 IPropertyArrayHelper
& rPH
= getInfoHelper();
901 rPH
.fillHandles( pHandles
, rPropertyNames
);
902 const OUString
* pNames
= rPropertyNames
.getConstArray();
904 // get the count of matching properties
905 sal_Int32 nFireLen
= 0;
907 for( i
= 0; i
< nLen
; i
++ )
908 if( pHandles
[i
] != -1 )
911 Sequence
<PropertyChangeEvent
> aChanges( nFireLen
);
912 PropertyChangeEvent
* pChanges
= aChanges
.getArray();
914 sal_Int32 nFirePos
= 0;
916 // must lock the mutex outside the loop. So all values are consistent.
917 MutexGuard
aGuard( rBHelper
.rMutex
);
918 Reference
< XInterface
> xSource( (XPropertySet
*)this, UNO_QUERY
);
919 for( i
= 0; i
< nLen
; i
++ )
921 if( pHandles
[i
] != -1 )
923 pChanges
[nFirePos
].Source
= xSource
;
924 pChanges
[nFirePos
].PropertyName
= pNames
[i
];
925 pChanges
[nFirePos
].PropertyHandle
= pHandles
[i
];
926 getFastPropertyValue( pChanges
[nFirePos
].OldValue
, pHandles
[i
] );
927 pChanges
[nFirePos
].NewValue
= pChanges
[nFirePos
].OldValue
;
931 // release guard to fire events
934 rListener
->propertiesChange( aChanges
);
941 PropertyState
OPropertySetHelper::getPropertyState( const OUString
& PropertyName
)
943 PropertyState aState
;
948 Sequence
< PropertyState
> OPropertySetHelper::getPropertyStates( const Sequence
< OUString
>& PropertyNames
)
950 ULONG nNames
= PropertyNames
.getLength();
951 const OUString
* pNames
= PropertyNames
.getConstArray();
953 Sequence
< PropertyState
> aStates( nNames
);
958 void OPropertySetHelper::setPropertyToDefault( const OUString
& aPropertyName
)
960 setPropertyValue( aPropertyName
, Any() );
963 Any
OPropertySetHelper::getPropertyDefault( const OUString
& aPropertyName
) const
968 void OPropertySetHelper::addPropertyStateChangeListener( const OUString
& aPropertyName
, const XPropertyStateChangeListenerRef
& Listener
)
972 void OPropertySetHelper::removePropertyStateChangeListener( const OUString
& aPropertyName
, const XPropertyStateChangeListenerRef
& Listener
)
977 //========================================================================
978 //== OPropertyArrayHelper ================================================
979 //========================================================================
981 //========================================================================
983 // static OUString makeOUString( sal_Char *p )
985 // sal_Int32 nLen = strlen(p);
986 // sal_Unicode *pw = new sal_Unicode[nLen];
988 // for( int i = 0 ; i < nLen ; i ++ ) {
990 // // Only ascii strings allowed with this helper !
991 // OSL_ASSERT( p[i] < 127 );
994 // OUString ow( pw , nLen );
1001 static int compare_Property_Impl( const void *arg1
, const void *arg2
)
1002 SAL_THROW_EXTERN_C()
1004 return ((Property
*)arg1
)->Name
.compareTo( ((Property
*)arg2
)->Name
);
1009 void OPropertyArrayHelper::init( sal_Bool bSorted
) SAL_THROW( () )
1011 sal_Int32 i
, nElements
= aInfos
.getLength();
1012 const Property
* pProperties
= aInfos
.getConstArray();
1014 for( i
= 1; i
< nElements
; i
++ )
1016 if( pProperties
[i
-1].Name
>= pProperties
[i
].Name
)
1018 #ifndef OS2 // YD disabled, too many troubles with debug builds!
1020 OSL_ENSURE( false, "Property array is not sorted" );
1024 qsort( aInfos
.getArray(), nElements
, sizeof( Property
),
1025 compare_Property_Impl
);
1029 // may be that the array is resorted
1030 pProperties
= aInfos
.getConstArray();
1031 for( i
= 0; i
< nElements
; i
++ )
1032 if( pProperties
[i
].Handle
!= i
)
1034 // The handle is the index
1035 bRightOrdered
= sal_True
;
1038 OPropertyArrayHelper::OPropertyArrayHelper(
1043 : aInfos(pProps
, nEle
)
1044 , bRightOrdered( sal_False
)
1049 OPropertyArrayHelper::OPropertyArrayHelper(
1050 const Sequence
< Property
> & aProps
,
1054 , bRightOrdered( sal_False
)
1059 //========================================================================
1060 sal_Int32
OPropertyArrayHelper::getCount() const
1062 return aInfos
.getLength();
1065 //========================================================================
1066 sal_Bool
OPropertyArrayHelper::fillPropertyMembersByHandle
1068 OUString
* pPropName
,
1069 sal_Int16
* pAttributes
,
1073 const Property
* pProperties
= aInfos
.getConstArray();
1074 sal_Int32 nElements
= aInfos
.getLength();
1078 if( nHandle
< 0 || nHandle
>= nElements
)
1081 *pPropName
= pProperties
[ nHandle
].Name
;
1083 *pAttributes
= pProperties
[ nHandle
].Attributes
;
1088 // normally the array is sorted
1089 for( sal_Int32 i
= 0; i
< nElements
; i
++ )
1091 if( pProperties
[i
].Handle
== nHandle
)
1094 *pPropName
= pProperties
[ i
].Name
;
1096 *pAttributes
= pProperties
[ i
].Attributes
;
1104 //========================================================================
1105 Sequence
< Property
> OPropertyArrayHelper::getProperties(void)
1107 /*if( aInfos.getLength() != nElements )
1109 ((OPropertyArrayHelper *)this)->aInfos.realloc( nElements );
1110 Property * pProps = ((OPropertyArrayHelper *)this)->aInfos.getArray();
1111 for( sal_Int32 i = 0; i < nElements; i++ )
1113 pProps[i].Name = pProperties[i].Name;
1114 pProps[i].Handle = pProperties[i].Handle;
1115 pProps[i].Type = pProperties[i].Type;
1116 pProps[i].Attributes = pProperties[i].Attributes;
1122 //========================================================================
1123 Property
OPropertyArrayHelper::getPropertyByName(const OUString
& aPropertyName
)
1124 throw (UnknownPropertyException
)
1127 pR
= (Property
*)bsearch( &aPropertyName
, aInfos
.getConstArray(), aInfos
.getLength(),
1129 compare_OUString_Property_Impl
);
1131 throw UnknownPropertyException();
1135 aProp.Name = pR->Name;
1136 aProp.Handle = pR->Handle;
1137 aProp.Type = pR->Type;
1138 aProp.Attributes = pR->Attributes;
1143 //========================================================================
1144 sal_Bool
OPropertyArrayHelper::hasPropertyByName(const OUString
& aPropertyName
)
1147 pR
= (Property
*)bsearch( &aPropertyName
, aInfos
.getConstArray(), aInfos
.getLength(),
1149 compare_OUString_Property_Impl
);
1153 //========================================================================
1154 sal_Int32
OPropertyArrayHelper::getHandleByName( const OUString
& rPropName
)
1157 pR
= (Property
*)bsearch( &rPropName
, aInfos
.getConstArray(), aInfos
.getLength(),
1159 compare_OUString_Property_Impl
);
1160 return pR
? pR
->Handle
: -1;
1163 //========================================================================
1164 sal_Int32
OPropertyArrayHelper::fillHandles( sal_Int32
* pHandles
, const Sequence
< OUString
> & rPropNames
)
1166 sal_Int32 nHitCount
= 0;
1167 const OUString
* pReqProps
= rPropNames
.getConstArray();
1168 sal_Int32 nReqLen
= rPropNames
.getLength();
1169 const Property
* pCur
= aInfos
.getConstArray();
1170 const Property
* pEnd
= pCur
+ aInfos
.getLength();
1172 for( sal_Int32 i
= 0; i
< nReqLen
; i
++ )
1174 // Logarithmus ermitteln
1175 sal_Int32 n
= (sal_Int32
)(pEnd
- pCur
);
1183 // Anzahl der noch zu suchenden Properties * dem Log2 der verbleibenden
1184 // zu dursuchenden Properties.
1185 if( (nReqLen
- i
) * nLog
>= pEnd
- pCur
)
1187 // linear search is better
1188 while( pCur
< pEnd
&& pReqProps
[i
] > pCur
->Name
)
1192 if( pCur
< pEnd
&& pReqProps
[i
] == pCur
->Name
)
1194 pHandles
[i
] = pCur
->Handle
;
1202 // binary search is better
1203 sal_Int32 nCompVal
= 1;
1204 const Property
* pOldEnd
= pEnd
--;
1205 const Property
* pMid
= pCur
;
1207 while( nCompVal
!= 0 && pCur
<= pEnd
)
1209 pMid
= (pEnd
- pCur
) / 2 + pCur
;
1211 nCompVal
= pReqProps
[i
].compareTo( pMid
->Name
);
1221 pHandles
[i
] = pMid
->Handle
;
1225 else if( nCompVal
> 0 )
1241 } // end namespace cppu