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 .
20 #include <osl/diagnose.h>
21 #include <cppuhelper/implbase.hxx>
22 #include <cppuhelper/queryinterface.hxx>
23 #include <comphelper/propshlp.hxx>
24 #include <cppuhelper/exc_hlp.hxx>
25 #include <com/sun/star/beans/PropertyAttribute.hpp>
26 #include <com/sun/star/lang/DisposedException.hpp>
27 #include <com/sun/star/lang/IllegalArgumentException.hpp>
29 #include <sal/log.hxx>
32 using namespace com::sun::star::uno
;
33 using namespace com::sun::star::beans
;
34 using namespace com::sun::star::lang
;
41 static int compare_OUString_Property_Impl(const void* arg1
, const void* arg2
) SAL_THROW_EXTERN_C()
43 return static_cast<OUString
const*>(arg1
)->compareTo(static_cast<Property
const*>(arg2
)->Name
);
48 * The class which implements the PropertySetInfo interface.
53 class OPropertySetHelperInfo_Impl
: public WeakImplHelper
<css::beans::XPropertySetInfo
>
55 Sequence
<Property
> aInfos
;
58 explicit OPropertySetHelperInfo_Impl(IPropertyArrayHelper
& rHelper_
);
60 // XPropertySetInfo-methods
61 virtual Sequence
<Property
> SAL_CALL
getProperties() override
;
62 virtual Property SAL_CALL
getPropertyByName(const OUString
& PropertyName
) override
;
63 virtual sal_Bool SAL_CALL
hasPropertyByName(const OUString
& PropertyName
) override
;
68 * Create an object that implements XPropertySetInfo IPropertyArrayHelper.
70 OPropertySetHelperInfo_Impl::OPropertySetHelperInfo_Impl(IPropertyArrayHelper
& rHelper_
)
71 : aInfos(rHelper_
.getProperties())
76 * Return the sequence of properties, which are provided through the constructor.
78 Sequence
<Property
> OPropertySetHelperInfo_Impl::getProperties() { return aInfos
; }
81 * Return the sequence of properties, which are provided through the constructor.
83 Property
OPropertySetHelperInfo_Impl::getPropertyByName(const OUString
& PropertyName
)
86 = static_cast<Property
*>(bsearch(&PropertyName
, aInfos
.getConstArray(), aInfos
.getLength(),
87 sizeof(Property
), compare_OUString_Property_Impl
));
89 throw UnknownPropertyException(PropertyName
);
95 * Return the sequence of properties, which are provided through the constructor.
97 sal_Bool
OPropertySetHelperInfo_Impl::hasPropertyByName(const OUString
& PropertyName
)
100 = static_cast<Property
*>(bsearch(&PropertyName
, aInfos
.getConstArray(), aInfos
.getLength(),
101 sizeof(Property
), compare_OUString_Property_Impl
));
102 return pR
!= nullptr;
105 OPropertySetHelper::OPropertySetHelper() {}
107 OPropertySetHelper::OPropertySetHelper(bool bIgnoreRuntimeExceptionsWhileFiring
)
108 : m_bIgnoreRuntimeExceptionsWhileFiring(bIgnoreRuntimeExceptionsWhileFiring
)
113 * You must call disposing before.
115 OPropertySetHelper::~OPropertySetHelper() {}
118 Any
OPropertySetHelper::queryInterface(const css::uno::Type
& rType
)
120 return ::cppu::queryInterface(rType
, static_cast<XPropertySet
*>(this),
121 static_cast<XMultiPropertySet
*>(this),
122 static_cast<XFastPropertySet
*>(this));
126 * called from the derivee's XTypeProvider::getTypes implementation
128 css::uno::Sequence
<css::uno::Type
> OPropertySetHelper::getTypes()
130 return { UnoType
<css::beans::XPropertySet
>::get(),
131 UnoType
<css::beans::XMultiPropertySet
>::get(),
132 UnoType
<css::beans::XFastPropertySet
>::get() };
136 void OPropertySetHelper::disposing(std::unique_lock
<std::mutex
>& rGuard
)
138 // Create an event with this as sender
139 Reference
<XPropertySet
> rSource
= this;
141 aEvt
.Source
= rSource
;
143 // inform all listeners to release this object
144 // The listener containers are automatically cleared
145 aBoundLC
.disposeAndClear(rGuard
, aEvt
);
146 aVetoableLC
.disposeAndClear(rGuard
, aEvt
);
149 Reference
<XPropertySetInfo
>
150 OPropertySetHelper::createPropertySetInfo(IPropertyArrayHelper
& rProperties
)
152 return new OPropertySetHelperInfo_Impl(rProperties
);
156 void OPropertySetHelper::setPropertyValue(const OUString
& rPropertyName
, const Any
& rValue
)
159 IPropertyArrayHelper
& rPH
= getInfoHelper();
160 // map the name to the handle
161 sal_Int32 nHandle
= rPH
.getHandleByName(rPropertyName
);
162 std::unique_lock
aGuard(m_aMutex
);
163 setFastPropertyValueImpl(aGuard
, nHandle
, rValue
);
167 Any
OPropertySetHelper::getPropertyValue(const OUString
& rPropertyName
)
169 std::unique_lock
aGuard(m_aMutex
);
170 return getPropertyValueImpl(aGuard
, rPropertyName
);
173 Any
OPropertySetHelper::getPropertyValueImpl(std::unique_lock
<std::mutex
>& rGuard
,
174 const OUString
& rPropertyName
)
177 IPropertyArrayHelper
& rPH
= getInfoHelper();
178 // map the name to the handle
179 sal_Int32 nHandle
= rPH
.getHandleByName(rPropertyName
);
180 // call the method of the XFastPropertySet interface
182 getFastPropertyValue(rGuard
, aAny
, nHandle
);
187 void OPropertySetHelper::addPropertyChangeListener(
188 const OUString
& rPropertyName
, const Reference
<XPropertyChangeListener
>& rxListener
)
190 std::unique_lock
aGuard(m_aMutex
);
191 OSL_ENSURE(!m_bDisposed
, "object is disposed");
195 // only add listeners if you are not disposed
196 // a listener with no name means all properties
197 if (!rPropertyName
.isEmpty())
200 IPropertyArrayHelper
& rPH
= getInfoHelper();
201 // map the name to the handle
202 sal_Int32 nHandle
= rPH
.getHandleByName(rPropertyName
);
205 // property not known throw exception
206 throw UnknownPropertyException(rPropertyName
);
209 sal_Int16 nAttributes
;
210 rPH
.fillPropertyMembersByHandle(nullptr, &nAttributes
, nHandle
);
211 if (!(nAttributes
& css::beans::PropertyAttribute::BOUND
))
213 OSL_FAIL("add listener to an unbound property");
214 // silent ignore this
217 // add the change listener to the helper container
218 aBoundLC
.addInterface(aGuard
, nHandle
, rxListener
);
221 // add the change listener to the helper container
222 maPropertyChangeListeners
.addInterface(aGuard
, rxListener
);
226 void OPropertySetHelper::removePropertyChangeListener(
227 const OUString
& rPropertyName
, const Reference
<XPropertyChangeListener
>& rxListener
)
229 std::unique_lock
aGuard(m_aMutex
);
230 OSL_ENSURE(!m_bDisposed
, "object is disposed");
231 // all listeners are automatically released in a dispose call
235 if (!rPropertyName
.isEmpty())
238 IPropertyArrayHelper
& rPH
= getInfoHelper();
239 // map the name to the handle
240 sal_Int32 nHandle
= rPH
.getHandleByName(rPropertyName
);
242 // property not known throw exception
243 throw UnknownPropertyException(rPropertyName
);
244 aBoundLC
.removeInterface(aGuard
, nHandle
, rxListener
);
248 // remove the change listener to the helper container
249 maPropertyChangeListeners
.removeInterface(aGuard
, rxListener
);
254 void OPropertySetHelper::addVetoableChangeListener(
255 const OUString
& rPropertyName
, const Reference
<XVetoableChangeListener
>& rxListener
)
257 std::unique_lock
aGuard(m_aMutex
);
258 OSL_ENSURE(!m_bDisposed
, "object is disposed");
262 // only add listeners if you are not disposed
263 // a listener with no name means all properties
264 if (!rPropertyName
.isEmpty())
267 IPropertyArrayHelper
& rPH
= getInfoHelper();
268 // map the name to the handle
269 sal_Int32 nHandle
= rPH
.getHandleByName(rPropertyName
);
272 // property not known throw exception
273 throw UnknownPropertyException(rPropertyName
);
276 sal_Int16 nAttributes
;
277 rPH
.fillPropertyMembersByHandle(nullptr, &nAttributes
, nHandle
);
278 if (!(nAttributes
& PropertyAttribute::CONSTRAINED
))
280 OSL_FAIL("addVetoableChangeListener, and property is not constrained");
281 // silent ignore this
284 // add the vetoable listener to the helper container
285 aVetoableLC
.addInterface(aGuard
, nHandle
, rxListener
);
288 // add the vetoable listener to the helper container
289 maVetoableChangeListeners
.addInterface(aGuard
, rxListener
);
293 void OPropertySetHelper::removeVetoableChangeListener(
294 const OUString
& rPropertyName
, const Reference
<XVetoableChangeListener
>& rxListener
)
296 std::unique_lock
aGuard(m_aMutex
);
297 OSL_ENSURE(!m_bDisposed
, "object is disposed");
298 // all listeners are automatically released in a dispose call
302 if (!rPropertyName
.isEmpty())
305 IPropertyArrayHelper
& rPH
= getInfoHelper();
306 // map the name to the handle
307 sal_Int32 nHandle
= rPH
.getHandleByName(rPropertyName
);
310 // property not known throw exception
311 throw UnknownPropertyException(rPropertyName
);
313 // remove the vetoable listener to the helper container
314 aVetoableLC
.removeInterface(aGuard
, nHandle
, rxListener
);
317 // add the vetoable listener to the helper container
318 maVetoableChangeListeners
.removeInterface(aGuard
, rxListener
);
321 void OPropertySetHelper::setDependentFastPropertyValue(std::unique_lock
<std::mutex
>& rGuard
,
323 const css::uno::Any
& i_value
)
325 sal_Int16
nAttributes(0);
326 IPropertyArrayHelper
& rInfo
= getInfoHelper();
327 if (!rInfo
.fillPropertyMembersByHandle(nullptr, &nAttributes
, i_handle
))
329 throw UnknownPropertyException(OUString::number(i_handle
));
331 // no need to check for READONLY-ness of the property. The method is intended to be called internally, which
332 // implies it might be invoked for properties which are read-only to the instance's clients, but well allowed
333 // to change their value.
335 Any aConverted
, aOld
;
336 bool bChanged
= convertFastPropertyValue(rGuard
, aConverted
, aOld
, i_handle
, i_value
);
340 // don't fire vetoable events. This method is called with our mutex locked, so calling into listeners would not be
341 // a good idea. The caller is responsible for not invoking this for constrained properties.
342 OSL_ENSURE((nAttributes
& PropertyAttribute::CONSTRAINED
) == 0,
343 "OPropertySetHelper::setDependentFastPropertyValue: not to be used for constrained "
346 // actually set the new value
349 setFastPropertyValue_NoBroadcast(rGuard
, i_handle
, aConverted
);
351 catch (const UnknownPropertyException
&)
353 throw; /* allowed to leave */
355 catch (const PropertyVetoException
&)
357 throw; /* allowed to leave */
359 catch (const IllegalArgumentException
&)
361 throw; /* allowed to leave */
363 catch (const WrappedTargetException
&)
365 throw; /* allowed to leave */
367 catch (const RuntimeException
&)
369 throw; /* allowed to leave */
371 catch (const Exception
&)
373 // not allowed to leave this method
374 WrappedTargetException aWrapped
;
375 aWrapped
.TargetException
= ::cppu::getCaughtException();
376 aWrapped
.Context
= static_cast<XPropertySet
*>(this);
380 // remember the handle/values, for the events to be fired later
381 m_handles
.push_back(i_handle
);
382 m_newValues
.push_back(
383 aConverted
); // TODO: setFastPropertyValue notifies the unconverted value here ...?
384 m_oldValues
.push_back(aOld
);
388 void OPropertySetHelper::setFastPropertyValue(sal_Int32 nHandle
, const Any
& rValue
)
390 std::unique_lock
aGuard(m_aMutex
);
391 setFastPropertyValueImpl(aGuard
, nHandle
, rValue
);
394 void OPropertySetHelper::setFastPropertyValueImpl(std::unique_lock
<std::mutex
>& rGuard
,
395 sal_Int32 nHandle
, const Any
& rValue
)
397 OSL_ENSURE(!m_bDisposed
, "object is disposed");
399 IPropertyArrayHelper
& rInfo
= getInfoHelper();
400 sal_Int16 nAttributes
;
401 if (!rInfo
.fillPropertyMembersByHandle(nullptr, &nAttributes
, nHandle
))
404 throw UnknownPropertyException(OUString::number(nHandle
));
406 if (nAttributes
& PropertyAttribute::READONLY
)
407 throw PropertyVetoException();
412 // Will the property change?
413 bool bChanged
= convertFastPropertyValue(rGuard
, aConvertedVal
, aOldVal
, nHandle
, rValue
);
417 // Is it a constrained property?
418 if (nAttributes
& PropertyAttribute::CONSTRAINED
)
420 // In aValue is the converted rValue
421 // fire a constrained event
422 // second parameter NULL means constrained
423 fire(rGuard
, &nHandle
, &rValue
, &aOldVal
, 1, true);
428 // set the property to the new value
429 setFastPropertyValue_NoBroadcast(rGuard
, nHandle
, aConvertedVal
);
431 catch (const css::beans::UnknownPropertyException
&)
433 throw; /* allowed to leave */
435 catch (const css::beans::PropertyVetoException
&)
437 throw; /* allowed to leave */
439 catch (const css::lang::IllegalArgumentException
&)
441 throw; /* allowed to leave */
443 catch (const css::lang::WrappedTargetException
&)
445 throw; /* allowed to leave */
447 catch (const css::uno::RuntimeException
&)
449 throw; /* allowed to leave */
451 catch (const css::uno::Exception
& e
)
453 // not allowed to leave this method
454 css::lang::WrappedTargetException aWrap
;
455 aWrap
.Context
= static_cast<css::beans::XPropertySet
*>(this);
456 aWrap
.TargetException
<<= e
;
461 // file a change event, if the value changed
462 impl_fireAll(rGuard
, &nHandle
, &rValue
, &aOldVal
, 1);
466 Any
OPropertySetHelper::getFastPropertyValue(sal_Int32 nHandle
)
468 IPropertyArrayHelper
& rInfo
= getInfoHelper();
469 if (!rInfo
.fillPropertyMembersByHandle(nullptr, nullptr, nHandle
))
471 throw UnknownPropertyException(OUString::number(nHandle
));
474 std::unique_lock
aGuard(m_aMutex
);
475 getFastPropertyValue(aGuard
, aRet
, nHandle
);
479 void OPropertySetHelper::impl_fireAll(std::unique_lock
<std::mutex
>& rGuard
, sal_Int32
* i_handles
,
480 const Any
* i_newValues
, const Any
* i_oldValues
,
483 if (m_handles
.empty())
485 fire(rGuard
, i_handles
, i_newValues
, i_oldValues
, i_count
, false);
489 const size_t additionalEvents
= m_handles
.size();
490 OSL_ENSURE(additionalEvents
== m_newValues
.size() && additionalEvents
== m_oldValues
.size(),
491 "OPropertySetHelper::impl_fireAll: inconsistency!");
493 std::vector
<sal_Int32
> allHandles(additionalEvents
+ i_count
);
494 std::copy(m_handles
.begin(), m_handles
.end(), allHandles
.begin());
495 std::copy(i_handles
, i_handles
+ i_count
, allHandles
.begin() + additionalEvents
);
497 std::vector
<Any
> allNewValues(additionalEvents
+ i_count
);
498 std::copy(m_newValues
.begin(), m_newValues
.end(), allNewValues
.begin());
499 std::copy(i_newValues
, i_newValues
+ i_count
, allNewValues
.begin() + additionalEvents
);
501 std::vector
<Any
> allOldValues(additionalEvents
+ i_count
);
502 std::copy(m_oldValues
.begin(), m_oldValues
.end(), allOldValues
.begin());
503 std::copy(i_oldValues
, i_oldValues
+ i_count
, allOldValues
.begin() + additionalEvents
);
509 fire(rGuard
, allHandles
.data(), allNewValues
.data(), allOldValues
.data(),
510 additionalEvents
+ i_count
, false);
513 void OPropertySetHelper::fire(std::unique_lock
<std::mutex
>& rGuard
, sal_Int32
* pnHandles
,
514 const Any
* pNewValues
, const Any
* pOldValues
,
515 sal_Int32 nHandles
, // This is the Count of the array
521 // Only fire, if one or more properties changed
525 // create the event sequence of all changed properties
526 Sequence
<PropertyChangeEvent
> aEvts(nHandles
);
527 PropertyChangeEvent
* pEvts
= aEvts
.getArray();
528 Reference
<XInterface
> xSource(static_cast<XPropertySet
*>(this), UNO_QUERY
);
530 sal_Int32 nChangesLen
= 0;
531 // Loop over all changed properties to fill the event struct
532 for (i
= 0; i
< nHandles
; i
++)
534 // Vetoable fire and constrained attribute set or
535 // Change fire and Changed and bound attribute set
536 IPropertyArrayHelper
& rInfo
= getInfoHelper();
537 sal_Int16 nAttributes
;
539 rInfo
.fillPropertyMembersByHandle(&aPropName
, &nAttributes
, pnHandles
[i
]);
541 if ((bVetoable
&& (nAttributes
& PropertyAttribute::CONSTRAINED
))
542 || (!bVetoable
&& (nAttributes
& PropertyAttribute::BOUND
)))
544 pEvts
[nChangesLen
].Source
= xSource
;
545 pEvts
[nChangesLen
].PropertyName
= aPropName
;
546 pEvts
[nChangesLen
].PropertyHandle
= pnHandles
[i
];
547 pEvts
[nChangesLen
].OldValue
= pOldValues
[i
];
548 pEvts
[nChangesLen
].NewValue
= pNewValues
[i
];
553 bool bIgnoreRuntimeExceptionsWhileFiring
= m_bIgnoreRuntimeExceptionsWhileFiring
;
555 // fire the events for all changed properties
556 for (i
= 0; i
< nChangesLen
; i
++)
558 if (bVetoable
) // fire change Events?
559 fireVetoableChangeListeners(
560 rGuard
, aVetoableLC
.getContainer(rGuard
, pEvts
[i
].PropertyHandle
), pEvts
[i
]);
562 // get the listener container for the property name
563 firePropertyChangeListeners(
564 rGuard
, aBoundLC
.getContainer(rGuard
, pEvts
[i
].PropertyHandle
), pEvts
[i
]);
566 // broadcast to all listeners with "" property name
568 // fire change Events?
569 fireVetoableChangeListeners(rGuard
, &maVetoableChangeListeners
, pEvts
[i
]);
571 firePropertyChangeListeners(rGuard
, &maPropertyChangeListeners
, pEvts
[i
]);
574 // reduce array to changed properties
575 aEvts
.realloc(nChangesLen
);
580 if (!maPropertiesChangeListeners
.getLength(rGuard
))
583 // Here is a Bug, unbound properties are also fired
584 OInterfaceIteratorHelper4
aIt(rGuard
, maPropertiesChangeListeners
);
586 while (aIt
.hasMoreElements())
588 XPropertiesChangeListener
* pL
= aIt
.next().get();
593 // fire the whole event sequence to the
594 // XPropertiesChangeListener's
595 pL
->propertiesChange(aEvts
);
597 catch (DisposedException
& exc
)
599 OSL_ENSURE(exc
.Context
.is(), "DisposedException without Context!");
600 if (exc
.Context
== pL
)
610 catch (RuntimeException
& exc
)
612 SAL_INFO("cppuhelper", "caught RuntimeException while firing listeners: " << exc
);
613 if (!bIgnoreRuntimeExceptionsWhileFiring
)
620 void OPropertySetHelper::fireVetoableChangeListeners(
621 std::unique_lock
<std::mutex
>& rGuard
,
622 comphelper::OInterfaceContainerHelper4
<css::beans::XVetoableChangeListener
>* pListeners
,
623 const css::beans::PropertyChangeEvent
& rChangeEvent
)
625 if (!pListeners
|| !pListeners
->getLength(rGuard
))
627 // Iterate over all listeners and send events
628 OInterfaceIteratorHelper4
aIt(rGuard
, *pListeners
);
630 while (aIt
.hasMoreElements())
632 XVetoableChangeListener
* pL
= aIt
.next().get();
637 pL
->vetoableChange(rChangeEvent
);
639 catch (DisposedException
& exc
)
641 OSL_ENSURE(exc
.Context
.is(), "DisposedException without Context!");
642 if (exc
.Context
== pL
)
652 catch (RuntimeException
& exc
)
654 SAL_INFO("cppuhelper", "caught RuntimeException while firing listeners: " << exc
);
655 if (!m_bIgnoreRuntimeExceptionsWhileFiring
)
662 void OPropertySetHelper::firePropertyChangeListeners(
663 std::unique_lock
<std::mutex
>& rGuard
,
664 comphelper::OInterfaceContainerHelper4
<css::beans::XPropertyChangeListener
>* pListeners
,
665 const css::beans::PropertyChangeEvent
& rChangeEvent
)
667 if (!pListeners
|| !pListeners
->getLength(rGuard
))
669 // Iterate over all listeners and send events
670 OInterfaceIteratorHelper4
aIt(rGuard
, *pListeners
);
672 while (aIt
.hasMoreElements())
674 XPropertyChangeListener
* pL
= aIt
.next().get();
679 pL
->propertyChange(rChangeEvent
);
681 catch (DisposedException
& exc
)
683 OSL_ENSURE(exc
.Context
.is(), "DisposedException without Context!");
684 if (exc
.Context
== pL
)
694 catch (RuntimeException
& exc
)
696 SAL_INFO("cppuhelper", "caught RuntimeException while firing listeners: " << exc
);
697 if (!m_bIgnoreRuntimeExceptionsWhileFiring
)
704 // OPropertySetHelper
705 void OPropertySetHelper::setFastPropertyValues(std::unique_lock
<std::mutex
>& rGuard
,
706 sal_Int32 nSeqLen
, sal_Int32
* pHandles
,
707 const Any
* pValues
, sal_Int32 nHitCount
)
709 OSL_ENSURE(!m_bDisposed
, "object is disposed");
712 IPropertyArrayHelper
& rPH
= getInfoHelper();
714 std::unique_ptr
<Any
[]> pConvertedValues(new Any
[nHitCount
]);
715 std::unique_ptr
<Any
[]> pOldValues(new Any
[nHitCount
]);
719 for (i
= 0; i
< nSeqLen
; i
++)
721 if (pHandles
[i
] != -1)
723 sal_Int16 nAttributes
;
724 rPH
.fillPropertyMembersByHandle(nullptr, &nAttributes
, pHandles
[i
]);
725 if (nAttributes
& PropertyAttribute::READONLY
)
726 throw PropertyVetoException();
727 // Will the property change?
728 if (convertFastPropertyValue(rGuard
, pConvertedValues
[n
], pOldValues
[n
], pHandles
[i
],
731 // only increment if the property really change
732 pHandles
[n
] = pHandles
[i
];
738 // fire vetoable events
739 fire(rGuard
, pHandles
, pConvertedValues
.get(), pOldValues
.get(), n
, true);
741 // Loop over all changed properties
742 for (i
= 0; i
< n
; i
++)
744 // Will the property change?
745 setFastPropertyValue_NoBroadcast(rGuard
, pHandles
[i
], pConvertedValues
[i
]);
748 // fire change events
749 impl_fireAll(rGuard
, pHandles
, pConvertedValues
.get(), pOldValues
.get(), n
);
754 * The sequence may be contain not known properties. The implementation
755 * must ignore these properties.
757 void OPropertySetHelper::setPropertyValues(const Sequence
<OUString
>& rPropertyNames
,
758 const Sequence
<Any
>& rValues
)
760 sal_Int32 nSeqLen
= rPropertyNames
.getLength();
761 if (nSeqLen
!= rValues
.getLength())
762 throw IllegalArgumentException("lengths do not match", static_cast<XPropertySet
*>(this),
764 std::unique_ptr
<sal_Int32
[]> pHandles(new sal_Int32
[nSeqLen
]);
766 IPropertyArrayHelper
& rPH
= getInfoHelper();
767 // fill the handle array
768 sal_Int32 nHitCount
= rPH
.fillHandles(pHandles
.get(), rPropertyNames
);
771 std::unique_lock
aGuard(m_aMutex
);
772 setFastPropertyValues(aGuard
, nSeqLen
, pHandles
.get(), rValues
.getConstArray(), nHitCount
);
776 Sequence
<Any
> OPropertySetHelper::getPropertyValues(const Sequence
<OUString
>& rPropertyNames
)
778 sal_Int32 nSeqLen
= rPropertyNames
.getLength();
779 std::unique_ptr
<sal_Int32
[]> pHandles(new sal_Int32
[nSeqLen
]);
780 Sequence
<Any
> aValues(nSeqLen
);
783 IPropertyArrayHelper
& rPH
= getInfoHelper();
784 // fill the handle array
785 rPH
.fillHandles(pHandles
.get(), rPropertyNames
);
787 Any
* pValues
= aValues
.getArray();
789 std::unique_lock
aGuard(m_aMutex
);
790 // fill the sequence with the values
791 for (sal_Int32 i
= 0; i
< nSeqLen
; i
++)
792 getFastPropertyValue(aGuard
, pValues
[i
], pHandles
[i
]);
798 void OPropertySetHelper::addPropertiesChangeListener(
799 const Sequence
<OUString
>&, const Reference
<XPropertiesChangeListener
>& rListener
)
801 std::unique_lock
g(m_aMutex
);
802 maPropertiesChangeListeners
.addInterface(g
, rListener
);
806 void OPropertySetHelper::removePropertiesChangeListener(
807 const Reference
<XPropertiesChangeListener
>& rListener
)
809 std::unique_lock
g(m_aMutex
);
810 maPropertiesChangeListeners
.removeInterface(g
, rListener
);
814 void OPropertySetHelper::firePropertiesChangeEvent(
815 const Sequence
<OUString
>& rPropertyNames
, const Reference
<XPropertiesChangeListener
>& rListener
)
817 sal_Int32 nLen
= rPropertyNames
.getLength();
818 std::unique_ptr
<sal_Int32
[]> pHandles(new sal_Int32
[nLen
]);
819 IPropertyArrayHelper
& rPH
= getInfoHelper();
820 rPH
.fillHandles(pHandles
.get(), rPropertyNames
);
821 const OUString
* pNames
= rPropertyNames
.getConstArray();
823 // get the count of matching properties
824 sal_Int32 nFireLen
= 0;
826 for (i
= 0; i
< nLen
; i
++)
827 if (pHandles
[i
] != -1)
830 Sequence
<PropertyChangeEvent
> aChanges(nFireLen
);
831 PropertyChangeEvent
* pChanges
= aChanges
.getArray();
834 // must lock the mutex outside the loop. So all values are consistent.
835 std::unique_lock
aGuard(m_aMutex
);
836 Reference
<XInterface
> xSource(static_cast<XPropertySet
*>(this), UNO_QUERY
);
837 sal_Int32 nFirePos
= 0;
838 for (i
= 0; i
< nLen
; i
++)
840 if (pHandles
[i
] != -1)
842 pChanges
[nFirePos
].Source
= xSource
;
843 pChanges
[nFirePos
].PropertyName
= pNames
[i
];
844 pChanges
[nFirePos
].PropertyHandle
= pHandles
[i
];
845 getFastPropertyValue(aGuard
, pChanges
[nFirePos
].OldValue
, pHandles
[i
]);
846 pChanges
[nFirePos
].NewValue
= pChanges
[nFirePos
].OldValue
;
850 // release guard to fire events
853 rListener
->propertiesChange(aChanges
);
856 UnoImplBase::~UnoImplBase() {}
858 } // end namespace comphelper
860 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */