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>
31 using namespace com::sun::star::uno
;
32 using namespace com::sun::star::beans
;
33 using namespace com::sun::star::lang
;
40 static int compare_OUString_Property_Impl(const void* arg1
, const void* arg2
) noexcept
42 return static_cast<OUString
const*>(arg1
)->compareTo(static_cast<Property
const*>(arg2
)->Name
);
47 * The class which implements the PropertySetInfo interface.
52 class OPropertySetHelperInfo_Impl
: public WeakImplHelper
<css::beans::XPropertySetInfo
>
54 Sequence
<Property
> aInfos
;
57 explicit OPropertySetHelperInfo_Impl(IPropertyArrayHelper
& rHelper_
);
59 // XPropertySetInfo-methods
60 virtual Sequence
<Property
> SAL_CALL
getProperties() override
;
61 virtual Property SAL_CALL
getPropertyByName(const OUString
& PropertyName
) override
;
62 virtual sal_Bool SAL_CALL
hasPropertyByName(const OUString
& PropertyName
) override
;
67 * Create an object that implements XPropertySetInfo IPropertyArrayHelper.
69 OPropertySetHelperInfo_Impl::OPropertySetHelperInfo_Impl(IPropertyArrayHelper
& rHelper_
)
70 : aInfos(rHelper_
.getProperties())
75 * Return the sequence of properties, which are provided through the constructor.
77 Sequence
<Property
> OPropertySetHelperInfo_Impl::getProperties() { return aInfos
; }
80 * Return the sequence of properties, which are provided through the constructor.
82 Property
OPropertySetHelperInfo_Impl::getPropertyByName(const OUString
& PropertyName
)
85 = static_cast<Property
*>(bsearch(&PropertyName
, aInfos
.getConstArray(), aInfos
.getLength(),
86 sizeof(Property
), compare_OUString_Property_Impl
));
88 throw UnknownPropertyException(PropertyName
);
94 * Return the sequence of properties, which are provided through the constructor.
96 sal_Bool
OPropertySetHelperInfo_Impl::hasPropertyByName(const OUString
& PropertyName
)
99 = static_cast<Property
*>(bsearch(&PropertyName
, aInfos
.getConstArray(), aInfos
.getLength(),
100 sizeof(Property
), compare_OUString_Property_Impl
));
101 return pR
!= nullptr;
104 OPropertySetHelper::OPropertySetHelper() {}
106 OPropertySetHelper::OPropertySetHelper(bool bIgnoreRuntimeExceptionsWhileFiring
)
107 : m_bIgnoreRuntimeExceptionsWhileFiring(bIgnoreRuntimeExceptionsWhileFiring
)
112 * You must call disposing before.
114 OPropertySetHelper::~OPropertySetHelper() {}
117 Any
OPropertySetHelper::queryInterface(const css::uno::Type
& rType
)
119 return ::cppu::queryInterface(rType
, static_cast<XPropertySet
*>(this),
120 static_cast<XMultiPropertySet
*>(this),
121 static_cast<XFastPropertySet
*>(this));
125 * called from the derivee's XTypeProvider::getTypes implementation
127 css::uno::Sequence
<css::uno::Type
> OPropertySetHelper::getTypes()
129 return { UnoType
<css::beans::XPropertySet
>::get(),
130 UnoType
<css::beans::XMultiPropertySet
>::get(),
131 UnoType
<css::beans::XFastPropertySet
>::get() };
135 void OPropertySetHelper::disposing(std::unique_lock
<std::mutex
>& rGuard
)
137 // Create an event with this as sender
138 Reference
<XPropertySet
> rSource
= this;
140 aEvt
.Source
= rSource
;
142 // inform all listeners to release this object
143 // The listener containers are automatically cleared
144 aBoundLC
.disposeAndClear(rGuard
, aEvt
);
145 aVetoableLC
.disposeAndClear(rGuard
, aEvt
);
148 Reference
<XPropertySetInfo
>
149 OPropertySetHelper::createPropertySetInfo(IPropertyArrayHelper
& rProperties
)
151 return new OPropertySetHelperInfo_Impl(rProperties
);
155 void OPropertySetHelper::setPropertyValue(const OUString
& rPropertyName
, const Any
& rValue
)
158 IPropertyArrayHelper
& rPH
= getInfoHelper();
159 // map the name to the handle
160 sal_Int32 nHandle
= rPH
.getHandleByName(rPropertyName
);
161 std::unique_lock
aGuard(m_aMutex
);
162 setFastPropertyValueImpl(aGuard
, nHandle
, rValue
);
166 Any
OPropertySetHelper::getPropertyValue(const OUString
& rPropertyName
)
168 std::unique_lock
aGuard(m_aMutex
);
169 return getPropertyValueImpl(aGuard
, rPropertyName
);
172 Any
OPropertySetHelper::getPropertyValueImpl(std::unique_lock
<std::mutex
>& rGuard
,
173 const OUString
& rPropertyName
)
176 IPropertyArrayHelper
& rPH
= getInfoHelper();
177 // map the name to the handle
178 sal_Int32 nHandle
= rPH
.getHandleByName(rPropertyName
);
180 throw UnknownPropertyException(rPropertyName
);
181 // call the method of the XFastPropertySet interface
183 getFastPropertyValue(rGuard
, aAny
, nHandle
);
188 void OPropertySetHelper::addPropertyChangeListener(
189 const OUString
& rPropertyName
, const Reference
<XPropertyChangeListener
>& rxListener
)
191 std::unique_lock
aGuard(m_aMutex
);
192 OSL_ENSURE(!m_bDisposed
, "object is disposed");
196 // only add listeners if you are not disposed
197 // a listener with no name means all properties
198 if (!rPropertyName
.isEmpty())
201 IPropertyArrayHelper
& rPH
= getInfoHelper();
202 // map the name to the handle
203 sal_Int32 nHandle
= rPH
.getHandleByName(rPropertyName
);
206 // property not known throw exception
207 throw UnknownPropertyException(rPropertyName
);
210 sal_Int16 nAttributes
;
211 rPH
.fillPropertyMembersByHandle(nullptr, &nAttributes
, nHandle
);
212 if (!(nAttributes
& css::beans::PropertyAttribute::BOUND
))
214 OSL_FAIL("add listener to an unbound property");
215 // silent ignore this
218 // add the change listener to the helper container
219 aBoundLC
.addInterface(aGuard
, nHandle
, rxListener
);
222 // add the change listener to the helper container
223 maPropertyChangeListeners
.addInterface(aGuard
, rxListener
);
227 void OPropertySetHelper::removePropertyChangeListener(
228 const OUString
& rPropertyName
, const Reference
<XPropertyChangeListener
>& rxListener
)
230 std::unique_lock
aGuard(m_aMutex
);
231 OSL_ENSURE(!m_bDisposed
, "object is disposed");
232 // all listeners are automatically released in a dispose call
236 if (!rPropertyName
.isEmpty())
239 IPropertyArrayHelper
& rPH
= getInfoHelper();
240 // map the name to the handle
241 sal_Int32 nHandle
= rPH
.getHandleByName(rPropertyName
);
243 // property not known throw exception
244 throw UnknownPropertyException(rPropertyName
);
245 aBoundLC
.removeInterface(aGuard
, nHandle
, rxListener
);
249 // remove the change listener to the helper container
250 maPropertyChangeListeners
.removeInterface(aGuard
, rxListener
);
255 void OPropertySetHelper::addVetoableChangeListener(
256 const OUString
& rPropertyName
, const Reference
<XVetoableChangeListener
>& rxListener
)
258 std::unique_lock
aGuard(m_aMutex
);
259 OSL_ENSURE(!m_bDisposed
, "object is disposed");
263 // only add listeners if you are not disposed
264 // a listener with no name means all properties
265 if (!rPropertyName
.isEmpty())
268 IPropertyArrayHelper
& rPH
= getInfoHelper();
269 // map the name to the handle
270 sal_Int32 nHandle
= rPH
.getHandleByName(rPropertyName
);
273 // property not known throw exception
274 throw UnknownPropertyException(rPropertyName
);
277 sal_Int16 nAttributes
;
278 rPH
.fillPropertyMembersByHandle(nullptr, &nAttributes
, nHandle
);
279 if (!(nAttributes
& PropertyAttribute::CONSTRAINED
))
281 OSL_FAIL("addVetoableChangeListener, and property is not constrained");
282 // silent ignore this
285 // add the vetoable listener to the helper container
286 aVetoableLC
.addInterface(aGuard
, nHandle
, rxListener
);
289 // add the vetoable listener to the helper container
290 maVetoableChangeListeners
.addInterface(aGuard
, rxListener
);
294 void OPropertySetHelper::removeVetoableChangeListener(
295 const OUString
& rPropertyName
, const Reference
<XVetoableChangeListener
>& rxListener
)
297 std::unique_lock
aGuard(m_aMutex
);
298 OSL_ENSURE(!m_bDisposed
, "object is disposed");
299 // all listeners are automatically released in a dispose call
303 if (!rPropertyName
.isEmpty())
306 IPropertyArrayHelper
& rPH
= getInfoHelper();
307 // map the name to the handle
308 sal_Int32 nHandle
= rPH
.getHandleByName(rPropertyName
);
311 // property not known throw exception
312 throw UnknownPropertyException(rPropertyName
);
314 // remove the vetoable listener to the helper container
315 aVetoableLC
.removeInterface(aGuard
, nHandle
, rxListener
);
318 // add the vetoable listener to the helper container
319 maVetoableChangeListeners
.removeInterface(aGuard
, rxListener
);
322 void OPropertySetHelper::setDependentFastPropertyValue(std::unique_lock
<std::mutex
>& rGuard
,
324 const css::uno::Any
& i_value
)
326 sal_Int16
nAttributes(0);
327 IPropertyArrayHelper
& rInfo
= getInfoHelper();
328 if (!rInfo
.fillPropertyMembersByHandle(nullptr, &nAttributes
, i_handle
))
330 throw UnknownPropertyException(OUString::number(i_handle
));
332 // no need to check for READONLY-ness of the property. The method is intended to be called internally, which
333 // implies it might be invoked for properties which are read-only to the instance's clients, but well allowed
334 // to change their value.
336 Any aConverted
, aOld
;
337 bool bChanged
= convertFastPropertyValue(rGuard
, aConverted
, aOld
, i_handle
, i_value
);
341 // don't fire vetoable events. This method is called with our mutex locked, so calling into listeners would not be
342 // a good idea. The caller is responsible for not invoking this for constrained properties.
343 OSL_ENSURE((nAttributes
& PropertyAttribute::CONSTRAINED
) == 0,
344 "OPropertySetHelper::setDependentFastPropertyValue: not to be used for constrained "
347 // actually set the new value
350 setFastPropertyValue_NoBroadcast(rGuard
, i_handle
, aConverted
);
352 catch (const UnknownPropertyException
&)
354 throw; /* allowed to leave */
356 catch (const PropertyVetoException
&)
358 throw; /* allowed to leave */
360 catch (const IllegalArgumentException
&)
362 throw; /* allowed to leave */
364 catch (const WrappedTargetException
&)
366 throw; /* allowed to leave */
368 catch (const RuntimeException
&)
370 throw; /* allowed to leave */
372 catch (const Exception
&)
374 // not allowed to leave this method
375 WrappedTargetException aWrapped
;
376 aWrapped
.TargetException
= ::cppu::getCaughtException();
377 aWrapped
.Context
= static_cast<XPropertySet
*>(this);
381 // remember the handle/values, for the events to be fired later
382 m_handles
.push_back(i_handle
);
383 m_newValues
.push_back(
384 aConverted
); // TODO: setFastPropertyValue notifies the unconverted value here ...?
385 m_oldValues
.push_back(aOld
);
389 void OPropertySetHelper::setFastPropertyValue(sal_Int32 nHandle
, const Any
& rValue
)
391 std::unique_lock
aGuard(m_aMutex
);
392 setFastPropertyValueImpl(aGuard
, nHandle
, rValue
);
395 void OPropertySetHelper::setFastPropertyValueImpl(std::unique_lock
<std::mutex
>& rGuard
,
396 sal_Int32 nHandle
, const Any
& rValue
)
398 OSL_ENSURE(!m_bDisposed
, "object is disposed");
400 IPropertyArrayHelper
& rInfo
= getInfoHelper();
401 sal_Int16 nAttributes
;
402 if (!rInfo
.fillPropertyMembersByHandle(nullptr, &nAttributes
, nHandle
))
405 throw UnknownPropertyException(OUString::number(nHandle
));
407 if (nAttributes
& PropertyAttribute::READONLY
)
408 throw PropertyVetoException();
413 // Will the property change?
414 bool bChanged
= convertFastPropertyValue(rGuard
, aConvertedVal
, aOldVal
, nHandle
, rValue
);
418 // Is it a constrained property?
419 if (nAttributes
& PropertyAttribute::CONSTRAINED
)
421 // In aValue is the converted rValue
422 // fire a constrained event
423 // second parameter NULL means constrained
424 fire(rGuard
, &nHandle
, &rValue
, &aOldVal
, 1, true);
429 // set the property to the new value
430 setFastPropertyValue_NoBroadcast(rGuard
, nHandle
, aConvertedVal
);
432 catch (const css::beans::UnknownPropertyException
&)
434 throw; /* allowed to leave */
436 catch (const css::beans::PropertyVetoException
&)
438 throw; /* allowed to leave */
440 catch (const css::lang::IllegalArgumentException
&)
442 throw; /* allowed to leave */
444 catch (const css::lang::WrappedTargetException
&)
446 throw; /* allowed to leave */
448 catch (const css::uno::RuntimeException
&)
450 throw; /* allowed to leave */
452 catch (const css::uno::Exception
& e
)
454 // not allowed to leave this method
455 css::lang::WrappedTargetException aWrap
;
456 aWrap
.Context
= static_cast<css::beans::XPropertySet
*>(this);
457 aWrap
.TargetException
<<= e
;
462 // file a change event, if the value changed
463 impl_fireAll(rGuard
, &nHandle
, &rValue
, &aOldVal
, 1);
467 Any
OPropertySetHelper::getFastPropertyValue(sal_Int32 nHandle
)
469 IPropertyArrayHelper
& rInfo
= getInfoHelper();
470 if (!rInfo
.fillPropertyMembersByHandle(nullptr, nullptr, nHandle
))
472 throw UnknownPropertyException(OUString::number(nHandle
));
475 std::unique_lock
aGuard(m_aMutex
);
476 getFastPropertyValue(aGuard
, aRet
, nHandle
);
480 void OPropertySetHelper::impl_fireAll(std::unique_lock
<std::mutex
>& rGuard
, sal_Int32
* i_handles
,
481 const Any
* i_newValues
, const Any
* i_oldValues
,
484 if (m_handles
.empty())
486 fire(rGuard
, i_handles
, i_newValues
, i_oldValues
, i_count
, false);
490 const size_t additionalEvents
= m_handles
.size();
491 OSL_ENSURE(additionalEvents
== m_newValues
.size() && additionalEvents
== m_oldValues
.size(),
492 "OPropertySetHelper::impl_fireAll: inconsistency!");
494 std::vector
<sal_Int32
> allHandles(additionalEvents
+ i_count
);
495 std::copy(m_handles
.begin(), m_handles
.end(), allHandles
.begin());
496 std::copy(i_handles
, i_handles
+ i_count
, allHandles
.begin() + additionalEvents
);
498 std::vector
<Any
> allNewValues(additionalEvents
+ i_count
);
499 std::copy(m_newValues
.begin(), m_newValues
.end(), allNewValues
.begin());
500 std::copy(i_newValues
, i_newValues
+ i_count
, allNewValues
.begin() + additionalEvents
);
502 std::vector
<Any
> allOldValues(additionalEvents
+ i_count
);
503 std::copy(m_oldValues
.begin(), m_oldValues
.end(), allOldValues
.begin());
504 std::copy(i_oldValues
, i_oldValues
+ i_count
, allOldValues
.begin() + additionalEvents
);
510 fire(rGuard
, allHandles
.data(), allNewValues
.data(), allOldValues
.data(),
511 additionalEvents
+ i_count
, false);
514 void OPropertySetHelper::fire(std::unique_lock
<std::mutex
>& rGuard
, sal_Int32
* pnHandles
,
515 const Any
* pNewValues
, const Any
* pOldValues
,
516 sal_Int32 nHandles
, // This is the Count of the array
519 // Only fire, if one or more properties changed
523 // create the event sequence of all changed properties
524 Sequence
<PropertyChangeEvent
> aEvts(nHandles
);
525 PropertyChangeEvent
* pEvts
= aEvts
.getArray();
526 Reference
<XInterface
> xSource(static_cast<XPropertySet
*>(this), UNO_QUERY
);
528 sal_Int32 nChangesLen
= 0;
529 // Loop over all changed properties to fill the event struct
530 for (i
= 0; i
< nHandles
; i
++)
532 // Vetoable fire and constrained attribute set or
533 // Change fire and Changed and bound attribute set
534 IPropertyArrayHelper
& rInfo
= getInfoHelper();
535 sal_Int16 nAttributes
;
537 rInfo
.fillPropertyMembersByHandle(&aPropName
, &nAttributes
, pnHandles
[i
]);
539 if ((bVetoable
&& (nAttributes
& PropertyAttribute::CONSTRAINED
))
540 || (!bVetoable
&& (nAttributes
& PropertyAttribute::BOUND
)))
542 pEvts
[nChangesLen
].Source
= xSource
;
543 pEvts
[nChangesLen
].PropertyName
= aPropName
;
544 pEvts
[nChangesLen
].PropertyHandle
= pnHandles
[i
];
545 pEvts
[nChangesLen
].OldValue
= pOldValues
[i
];
546 pEvts
[nChangesLen
].NewValue
= pNewValues
[i
];
551 bool bIgnoreRuntimeExceptionsWhileFiring
= m_bIgnoreRuntimeExceptionsWhileFiring
;
553 // fire the events for all changed properties
554 for (i
= 0; i
< nChangesLen
; i
++)
556 if (bVetoable
) // fire change Events?
557 fireVetoableChangeListeners(
558 rGuard
, aVetoableLC
.getContainer(rGuard
, pEvts
[i
].PropertyHandle
), pEvts
[i
]);
560 // get the listener container for the property name
561 firePropertyChangeListeners(
562 rGuard
, aBoundLC
.getContainer(rGuard
, pEvts
[i
].PropertyHandle
), pEvts
[i
]);
564 // broadcast to all listeners with "" property name
566 // fire change Events?
567 fireVetoableChangeListeners(rGuard
, &maVetoableChangeListeners
, pEvts
[i
]);
569 firePropertyChangeListeners(rGuard
, &maPropertyChangeListeners
, pEvts
[i
]);
572 // reduce array to changed properties
573 aEvts
.realloc(nChangesLen
);
578 if (!maPropertiesChangeListeners
.getLength(rGuard
))
581 // Here is a Bug, unbound properties are also fired
582 OInterfaceIteratorHelper4
aIt(rGuard
, maPropertiesChangeListeners
);
584 while (aIt
.hasMoreElements())
586 XPropertiesChangeListener
* pL
= aIt
.next().get();
591 // fire the whole event sequence to the
592 // XPropertiesChangeListener's
593 pL
->propertiesChange(aEvts
);
595 catch (DisposedException
& exc
)
597 OSL_ENSURE(exc
.Context
.is(), "DisposedException without Context!");
598 if (exc
.Context
== pL
)
608 catch (RuntimeException
& exc
)
610 SAL_INFO("cppuhelper", "caught RuntimeException while firing listeners: " << exc
);
611 if (!bIgnoreRuntimeExceptionsWhileFiring
)
618 void OPropertySetHelper::fireVetoableChangeListeners(
619 std::unique_lock
<std::mutex
>& rGuard
,
620 comphelper::OInterfaceContainerHelper4
<css::beans::XVetoableChangeListener
>* pListeners
,
621 const css::beans::PropertyChangeEvent
& rChangeEvent
)
623 if (!pListeners
|| !pListeners
->getLength(rGuard
))
625 // Iterate over all listeners and send events
626 OInterfaceIteratorHelper4
aIt(rGuard
, *pListeners
);
628 while (aIt
.hasMoreElements())
630 XVetoableChangeListener
* pL
= aIt
.next().get();
635 pL
->vetoableChange(rChangeEvent
);
637 catch (DisposedException
& exc
)
639 OSL_ENSURE(exc
.Context
.is(), "DisposedException without Context!");
640 if (exc
.Context
== pL
)
650 catch (RuntimeException
& exc
)
652 SAL_INFO("cppuhelper", "caught RuntimeException while firing listeners: " << exc
);
653 if (!m_bIgnoreRuntimeExceptionsWhileFiring
)
660 void OPropertySetHelper::firePropertyChangeListeners(
661 std::unique_lock
<std::mutex
>& rGuard
,
662 comphelper::OInterfaceContainerHelper4
<css::beans::XPropertyChangeListener
>* pListeners
,
663 const css::beans::PropertyChangeEvent
& rChangeEvent
)
665 if (!pListeners
|| !pListeners
->getLength(rGuard
))
667 // Iterate over all listeners and send events
668 OInterfaceIteratorHelper4
aIt(rGuard
, *pListeners
);
670 while (aIt
.hasMoreElements())
672 XPropertyChangeListener
* pL
= aIt
.next().get();
677 pL
->propertyChange(rChangeEvent
);
679 catch (DisposedException
& exc
)
681 OSL_ENSURE(exc
.Context
.is(), "DisposedException without Context!");
682 if (exc
.Context
== pL
)
692 catch (RuntimeException
& exc
)
694 SAL_INFO("cppuhelper", "caught RuntimeException while firing listeners: " << exc
);
695 if (!m_bIgnoreRuntimeExceptionsWhileFiring
)
702 // OPropertySetHelper
703 void OPropertySetHelper::setFastPropertyValues(std::unique_lock
<std::mutex
>& rGuard
,
704 sal_Int32 nSeqLen
, sal_Int32
* pHandles
,
705 const Any
* pValues
, sal_Int32 nHitCount
)
707 OSL_ENSURE(!m_bDisposed
, "object is disposed");
710 IPropertyArrayHelper
& rPH
= getInfoHelper();
712 std::unique_ptr
<Any
[]> pConvertedValues(new Any
[nHitCount
]);
713 std::unique_ptr
<Any
[]> pOldValues(new Any
[nHitCount
]);
717 for (i
= 0; i
< nSeqLen
; i
++)
719 if (pHandles
[i
] != -1)
721 sal_Int16 nAttributes
;
722 rPH
.fillPropertyMembersByHandle(nullptr, &nAttributes
, pHandles
[i
]);
723 if (nAttributes
& PropertyAttribute::READONLY
)
724 throw PropertyVetoException();
725 // Will the property change?
726 if (convertFastPropertyValue(rGuard
, pConvertedValues
[n
], pOldValues
[n
], pHandles
[i
],
729 // only increment if the property really change
730 pHandles
[n
] = pHandles
[i
];
736 // fire vetoable events
737 fire(rGuard
, pHandles
, pConvertedValues
.get(), pOldValues
.get(), n
, true);
739 // Loop over all changed properties
740 for (i
= 0; i
< n
; i
++)
742 // Will the property change?
743 setFastPropertyValue_NoBroadcast(rGuard
, pHandles
[i
], pConvertedValues
[i
]);
746 // fire change events
747 impl_fireAll(rGuard
, pHandles
, pConvertedValues
.get(), pOldValues
.get(), n
);
752 * The sequence may be contain not known properties. The implementation
753 * must ignore these properties.
755 void OPropertySetHelper::setPropertyValues(const Sequence
<OUString
>& rPropertyNames
,
756 const Sequence
<Any
>& rValues
)
758 sal_Int32 nSeqLen
= rPropertyNames
.getLength();
759 if (nSeqLen
!= rValues
.getLength())
760 throw IllegalArgumentException(u
"lengths do not match"_ustr
,
761 static_cast<XPropertySet
*>(this), -1);
762 std::unique_ptr
<sal_Int32
[]> pHandles(new sal_Int32
[nSeqLen
]);
764 IPropertyArrayHelper
& rPH
= getInfoHelper();
765 // fill the handle array
766 sal_Int32 nHitCount
= rPH
.fillHandles(pHandles
.get(), rPropertyNames
);
769 std::unique_lock
aGuard(m_aMutex
);
770 setFastPropertyValues(aGuard
, nSeqLen
, pHandles
.get(), rValues
.getConstArray(), nHitCount
);
774 Sequence
<Any
> OPropertySetHelper::getPropertyValues(const Sequence
<OUString
>& rPropertyNames
)
776 sal_Int32 nSeqLen
= rPropertyNames
.getLength();
777 std::unique_ptr
<sal_Int32
[]> pHandles(new sal_Int32
[nSeqLen
]);
778 Sequence
<Any
> aValues(nSeqLen
);
781 IPropertyArrayHelper
& rPH
= getInfoHelper();
782 // fill the handle array
783 rPH
.fillHandles(pHandles
.get(), rPropertyNames
);
785 Any
* pValues
= aValues
.getArray();
787 std::unique_lock
aGuard(m_aMutex
);
788 // fill the sequence with the values
789 for (sal_Int32 i
= 0; i
< nSeqLen
; i
++)
790 getFastPropertyValue(aGuard
, pValues
[i
], pHandles
[i
]);
796 void OPropertySetHelper::addPropertiesChangeListener(
797 const Sequence
<OUString
>&, const Reference
<XPropertiesChangeListener
>& rListener
)
799 std::unique_lock
g(m_aMutex
);
800 maPropertiesChangeListeners
.addInterface(g
, rListener
);
804 void OPropertySetHelper::removePropertiesChangeListener(
805 const Reference
<XPropertiesChangeListener
>& rListener
)
807 std::unique_lock
g(m_aMutex
);
808 maPropertiesChangeListeners
.removeInterface(g
, rListener
);
812 void OPropertySetHelper::firePropertiesChangeEvent(
813 const Sequence
<OUString
>& rPropertyNames
, const Reference
<XPropertiesChangeListener
>& rListener
)
815 sal_Int32 nLen
= rPropertyNames
.getLength();
816 std::unique_ptr
<sal_Int32
[]> pHandles(new sal_Int32
[nLen
]);
817 IPropertyArrayHelper
& rPH
= getInfoHelper();
818 rPH
.fillHandles(pHandles
.get(), rPropertyNames
);
820 // get the count of matching properties
821 sal_Int32 nFireLen
= 0;
823 for (i
= 0; i
< nLen
; i
++)
824 if (pHandles
[i
] != -1)
827 Sequence
<PropertyChangeEvent
> aChanges(nFireLen
);
828 PropertyChangeEvent
* pChanges
= aChanges
.getArray();
831 // must lock the mutex outside the loop. So all values are consistent.
832 std::unique_lock
aGuard(m_aMutex
);
833 Reference
<XInterface
> xSource(static_cast<XPropertySet
*>(this), UNO_QUERY
);
834 sal_Int32 nFirePos
= 0;
835 for (i
= 0; i
< nLen
; i
++)
837 if (pHandles
[i
] != -1)
839 pChanges
[nFirePos
].Source
= xSource
;
840 pChanges
[nFirePos
].PropertyName
= rPropertyNames
[i
];
841 pChanges
[nFirePos
].PropertyHandle
= pHandles
[i
];
842 getFastPropertyValue(aGuard
, pChanges
[nFirePos
].OldValue
, pHandles
[i
]);
843 pChanges
[nFirePos
].NewValue
= pChanges
[nFirePos
].OldValue
;
847 // release guard to fire events
850 rListener
->propertiesChange(aChanges
);
853 UnoImplBase::~UnoImplBase() {}
855 } // end namespace comphelper
857 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */