/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
/** * Create an object that implements XPropertySetInfo IPropertyArrayHelper.
*/
OPropertySetHelperInfo_Impl::OPropertySetHelperInfo_Impl(IPropertyArrayHelper& rHelper_)
: aInfos(rHelper_.getProperties())
{
}
/** * Return the sequence of properties, which are provided through the constructor.
*/
Sequence<Property> OPropertySetHelperInfo_Impl::getProperties() { return aInfos; }
/** * Return the sequence of properties, which are provided through the constructor.
*/
Property OPropertySetHelperInfo_Impl::getPropertyByName(const OUString& PropertyName)
{
Property* pR
= static_cast<Property*>(bsearch(&PropertyName, aInfos.getConstArray(), aInfos.getLength(), sizeof(Property), compare_OUString_Property_Impl)); if (!pR) throw UnknownPropertyException(PropertyName);
return *pR;
}
/** * Return the sequence of properties, which are provided through the constructor.
*/
sal_Bool OPropertySetHelperInfo_Impl::hasPropertyByName(const OUString& PropertyName)
{
Property* pR
= static_cast<Property*>(bsearch(&PropertyName, aInfos.getConstArray(), aInfos.getLength(), sizeof(Property), compare_OUString_Property_Impl)); return pR != nullptr;
}
/** * called from the derivee's XTypeProvider::getTypes implementation
*/
css::uno::Sequence<css::uno::Type> OPropertySetHelper::getTypes()
{ return { UnoType<css::beans::XPropertySet>::get(),
UnoType<css::beans::XMultiPropertySet>::get(),
UnoType<css::beans::XFastPropertySet>::get() };
}
// ComponentHelper void OPropertySetHelper::disposing(std::unique_lock<std::mutex>& rGuard)
{ // Create an event with this as sender
Reference<XPropertySet> rSource = this;
EventObject aEvt;
aEvt.Source = rSource;
// inform all listeners to release this object // The listener containers are automatically cleared
aBoundLC.disposeAndClear(rGuard, aEvt);
aVetoableLC.disposeAndClear(rGuard, aEvt);
}
Any OPropertySetHelper::getPropertyValueImpl(std::unique_lock<std::mutex>& rGuard, const OUString& rPropertyName)
{ // get the map table
IPropertyArrayHelper& rPH = getInfoHelper(); // map the name to the handle
sal_Int32 nHandle = rPH.getHandleByName(rPropertyName); if (nHandle == -1) throw UnknownPropertyException(rPropertyName); // call the method of the XFastPropertySet interface
Any aAny;
getFastPropertyValue(rGuard, aAny, nHandle); return aAny;
}
// XPropertySet void OPropertySetHelper::addPropertyChangeListener( const OUString& rPropertyName, const Reference<XPropertyChangeListener>& rxListener)
{
std::unique_lock aGuard(m_aMutex);
OSL_ENSURE(!m_bDisposed, "object is disposed"); if (m_bDisposed) return;
// only add listeners if you are not disposed // a listener with no name means all properties if (!rPropertyName.isEmpty())
{ // get the map table
IPropertyArrayHelper& rPH = getInfoHelper(); // map the name to the handle
sal_Int32 nHandle = rPH.getHandleByName(rPropertyName); if (nHandle == -1)
{ // property not known throw exception throw UnknownPropertyException(rPropertyName);
}
sal_Int16 nAttributes;
rPH.fillPropertyMembersByHandle(nullptr, &nAttributes, nHandle); if (!(nAttributes & css::beans::PropertyAttribute::BOUND))
{
OSL_FAIL("add listener to an unbound property"); // silent ignore this return;
} // add the change listener to the helper container
aBoundLC.addInterface(aGuard, nHandle, rxListener);
} else // add the change listener to the helper container
maPropertyChangeListeners.addInterface(aGuard, rxListener);
}
// XPropertySet void OPropertySetHelper::removePropertyChangeListener( const OUString& rPropertyName, const Reference<XPropertyChangeListener>& rxListener)
{
std::unique_lock aGuard(m_aMutex);
OSL_ENSURE(!m_bDisposed, "object is disposed"); // all listeners are automatically released in a dispose call if (m_bDisposed) return;
if (!rPropertyName.isEmpty())
{ // get the map table
IPropertyArrayHelper& rPH = getInfoHelper(); // map the name to the handle
sal_Int32 nHandle = rPH.getHandleByName(rPropertyName); if (nHandle == -1) // property not known throw exception throw UnknownPropertyException(rPropertyName);
aBoundLC.removeInterface(aGuard, nHandle, rxListener);
} else
{ // remove the change listener to the helper container
maPropertyChangeListeners.removeInterface(aGuard, rxListener);
}
}
// XPropertySet void OPropertySetHelper::addVetoableChangeListener( const OUString& rPropertyName, const Reference<XVetoableChangeListener>& rxListener)
{
std::unique_lock aGuard(m_aMutex);
OSL_ENSURE(!m_bDisposed, "object is disposed"); if (m_bDisposed) return;
// only add listeners if you are not disposed // a listener with no name means all properties if (!rPropertyName.isEmpty())
{ // get the map table
IPropertyArrayHelper& rPH = getInfoHelper(); // map the name to the handle
sal_Int32 nHandle = rPH.getHandleByName(rPropertyName); if (nHandle == -1)
{ // property not known throw exception throw UnknownPropertyException(rPropertyName);
}
sal_Int16 nAttributes;
rPH.fillPropertyMembersByHandle(nullptr, &nAttributes, nHandle); if (!(nAttributes & PropertyAttribute::CONSTRAINED))
{
OSL_FAIL("addVetoableChangeListener, and property is not constrained"); // silent ignore this return;
} // add the vetoable listener to the helper container
aVetoableLC.addInterface(aGuard, nHandle, rxListener);
} else // add the vetoable listener to the helper container
maVetoableChangeListeners.addInterface(aGuard, rxListener);
}
// XPropertySet void OPropertySetHelper::removeVetoableChangeListener( const OUString& rPropertyName, const Reference<XVetoableChangeListener>& rxListener)
{
std::unique_lock aGuard(m_aMutex);
OSL_ENSURE(!m_bDisposed, "object is disposed"); // all listeners are automatically released in a dispose call if (m_bDisposed) return;
if (!rPropertyName.isEmpty())
{ // get the map table
IPropertyArrayHelper& rPH = getInfoHelper(); // map the name to the handle
sal_Int32 nHandle = rPH.getHandleByName(rPropertyName); if (nHandle == -1)
{ // property not known throw exception throw UnknownPropertyException(rPropertyName);
} // remove the vetoable listener to the helper container
aVetoableLC.removeInterface(aGuard, nHandle, rxListener);
} else // add the vetoable listener to the helper container
maVetoableChangeListeners.removeInterface(aGuard, rxListener);
}
// no need to check for READONLY-ness of the property. The method is intended to be called internally, which // implies it might be invoked for properties which are read-only to the instance's clients, but well allowed // to change their value.
Any aConverted, aOld; bool bChanged = convertFastPropertyValue(rGuard, aConverted, aOld, i_handle, i_value); if (!bChanged) return;
// don't fire vetoable events. This method is called with our mutex locked, so calling into listeners would not be // a good idea. The caller is responsible for not invoking this for constrained properties.
OSL_ENSURE((nAttributes & PropertyAttribute::CONSTRAINED) == 0, "OPropertySetHelper::setDependentFastPropertyValue: not to be used for constrained " "properties!");
// actually set the new value try
{
setFastPropertyValue_NoBroadcast(rGuard, i_handle, aConverted);
} catch (const UnknownPropertyException&)
{ throw; /* allowed to leave */
} catch (const PropertyVetoException&)
{ throw; /* allowed to leave */
} catch (const IllegalArgumentException&)
{ throw; /* allowed to leave */
} catch (const WrappedTargetException&)
{ throw; /* allowed to leave */
} catch (const RuntimeException&)
{ throw; /* allowed to leave */
} catch (const Exception&)
{ // not allowed to leave this method
WrappedTargetException aWrapped;
aWrapped.TargetException = ::cppu::getCaughtException();
aWrapped.Context = static_cast<XPropertySet*>(this); throw aWrapped;
}
// remember the handle/values, for the events to be fired later
m_handles.push_back(i_handle);
m_newValues.push_back(
aConverted); // TODO: setFastPropertyValue notifies the unconverted value here ...?
m_oldValues.push_back(aOld);
}
// Will the property change? bool bChanged = convertFastPropertyValue(rGuard, aConvertedVal, aOldVal, nHandle, rValue); if (!bChanged) return;
// Is it a constrained property? if (nAttributes & PropertyAttribute::CONSTRAINED)
{ // In aValue is the converted rValue // fire a constrained event // second parameter NULL means constrained
fire(rGuard, &nHandle, &rValue, &aOldVal, 1, true);
}
try
{ // set the property to the new value
setFastPropertyValue_NoBroadcast(rGuard, nHandle, aConvertedVal);
} catch (const css::beans::UnknownPropertyException&)
{ throw; /* allowed to leave */
} catch (const css::beans::PropertyVetoException&)
{ throw; /* allowed to leave */
} catch (const css::lang::IllegalArgumentException&)
{ throw; /* allowed to leave */
} catch (const css::lang::WrappedTargetException&)
{ throw; /* allowed to leave */
} catch (const css::uno::RuntimeException&)
{ throw; /* allowed to leave */
} catch (const css::uno::Exception& e)
{ // not allowed to leave this method
css::lang::WrappedTargetException aWrap;
aWrap.Context = static_cast<css::beans::XPropertySet*>(this);
aWrap.TargetException <<= e;
throw aWrap;
}
// file a change event, if the value changed
impl_fireAll(rGuard, &nHandle, &rValue, &aOldVal, 1);
}
// XFastPropertySet
Any OPropertySetHelper::getFastPropertyValue(sal_Int32 nHandle)
{
IPropertyArrayHelper& rInfo = getInfoHelper(); if (!rInfo.fillPropertyMembersByHandle(nullptr, nullptr, nHandle)) // unknown property throw UnknownPropertyException(OUString::number(nHandle));
Any aRet;
std::unique_lock aGuard(m_aMutex);
getFastPropertyValue(aGuard, aRet, nHandle); return aRet;
}
void OPropertySetHelper::fire(std::unique_lock<std::mutex>& rGuard, const sal_Int32* pnHandles, const Any* pNewValues, const Any* pOldValues,
sal_Int32 nHandles, // This is the Count of the array bool bVetoable)
{ // Only fire, if one or more properties changed if (!nHandles) return;
// create the event sequence of all changed properties
Sequence<PropertyChangeEvent> aEvts(nHandles);
PropertyChangeEvent* pEvts = aEvts.getArray();
Reference<XInterface> xSource(static_cast<XPropertySet*>(this), UNO_QUERY);
sal_Int32 i;
sal_Int32 nChangesLen = 0; // Loop over all changed properties to fill the event struct for (i = 0; i < nHandles; i++)
{ // Vetoable fire and constrained attribute set or // Change fire and Changed and bound attribute set
IPropertyArrayHelper& rInfo = getInfoHelper();
sal_Int16 nAttributes;
OUString aPropName;
rInfo.fillPropertyMembersByHandle(&aPropName, &nAttributes, pnHandles[i]);
// fire the events for all changed properties for (i = 0; i < nChangesLen; i++)
{ if (bVetoable) // fire change Events?
fireVetoableChangeListeners(
rGuard, aVetoableLC.getContainer(rGuard, pEvts[i].PropertyHandle), pEvts[i]); else // get the listener container for the property name
firePropertyChangeListeners(
rGuard, aBoundLC.getContainer(rGuard, pEvts[i].PropertyHandle), pEvts[i]);
// broadcast to all listeners with "" property name if (bVetoable) // fire change Events?
fireVetoableChangeListeners(rGuard, &maVetoableChangeListeners, pEvts[i]); else
firePropertyChangeListeners(rGuard, &maPropertyChangeListeners, pEvts[i]);
}
// reduce array to changed properties
aEvts.realloc(nChangesLen);
if (bVetoable) return;
if (!maPropertiesChangeListeners.getLength(rGuard)) return;
// Here is a Bug, unbound properties are also fired
OInterfaceIteratorHelper4 aIt(rGuard, maPropertiesChangeListeners);
rGuard.unlock(); while (aIt.hasMoreElements())
{
XPropertiesChangeListener* pL = aIt.next().get(); try
{ try
{ // fire the whole event sequence to the // XPropertiesChangeListener's
pL->propertiesChange(aEvts);
} catch (DisposedException& exc)
{
OSL_ENSURE(exc.Context.is(), "DisposedException without Context!"); if (exc.Context == pL)
{
rGuard.lock();
aIt.remove(rGuard);
rGuard.unlock();
} else throw;
}
} catch (RuntimeException& exc)
{
SAL_INFO("cppuhelper", "caught RuntimeException while firing listeners: " << exc); if (!bIgnoreRuntimeExceptionsWhileFiring) throw;
}
}
rGuard.lock();
}
void OPropertySetHelper::fireVetoableChangeListeners(
std::unique_lock<std::mutex>& rGuard,
comphelper::OInterfaceContainerHelper4<css::beans::XVetoableChangeListener>* pListeners, const css::beans::PropertyChangeEvent& rChangeEvent)
{ if (!pListeners || !pListeners->getLength(rGuard)) return; // Iterate over all listeners and send events
OInterfaceIteratorHelper4 aIt(rGuard, *pListeners);
rGuard.unlock(); while (aIt.hasMoreElements())
{
XVetoableChangeListener* pL = aIt.next().get(); try
{ try
{
pL->vetoableChange(rChangeEvent);
} catch (DisposedException& exc)
{
OSL_ENSURE(exc.Context.is(), "DisposedException without Context!"); if (exc.Context == pL)
{
rGuard.lock();
aIt.remove(rGuard);
rGuard.unlock();
} else throw;
}
} catch (RuntimeException& exc)
{
SAL_INFO("cppuhelper", "caught RuntimeException while firing listeners: " << exc); if (!m_bIgnoreRuntimeExceptionsWhileFiring) throw;
}
}
rGuard.lock();
}
void OPropertySetHelper::firePropertyChangeListeners(
std::unique_lock<std::mutex>& rGuard,
comphelper::OInterfaceContainerHelper4<css::beans::XPropertyChangeListener>* pListeners, const css::beans::PropertyChangeEvent& rChangeEvent)
{ if (!pListeners || !pListeners->getLength(rGuard)) return; // Iterate over all listeners and send events
OInterfaceIteratorHelper4 aIt(rGuard, *pListeners);
rGuard.unlock(); while (aIt.hasMoreElements())
{
XPropertyChangeListener* pL = aIt.next().get(); try
{ try
{
pL->propertyChange(rChangeEvent);
} catch (DisposedException& exc)
{
OSL_ENSURE(exc.Context.is(), "DisposedException without Context!"); if (exc.Context == pL)
{
rGuard.lock();
aIt.remove(rGuard);
rGuard.unlock();
} else throw;
}
} catch (RuntimeException& exc)
{
SAL_INFO("cppuhelper", "caught RuntimeException while firing listeners: " << exc); if (!m_bIgnoreRuntimeExceptionsWhileFiring) throw;
}
}
rGuard.lock();
}
for (i = 0; i < nSeqLen; i++)
{ if (pHandles[i] != -1)
{
sal_Int16 nAttributes;
rPH.fillPropertyMembersByHandle(nullptr, &nAttributes, pHandles[i]); if (nAttributes & PropertyAttribute::READONLY) throw PropertyVetoException(); // Will the property change? if (convertFastPropertyValue(rGuard, pConvertedValues[n], pOldValues[n], pHandles[i],
pValues[i]))
{ // only increment if the property really change
pHandles[n] = pHandles[i];
n++;
}
}
}
// fire vetoable events
fire(rGuard, pHandles, pConvertedValues.get(), pOldValues.get(), n, true);
// Loop over all changed properties for (i = 0; i < n; i++)
{ // Will the property change?
setFastPropertyValue_NoBroadcast(rGuard, pHandles[i], pConvertedValues[i]);
}
// fire change events
impl_fireAll(rGuard, pHandles, pConvertedValues.get(), pOldValues.get(), n);
}
// XMultiPropertySet /** * The sequence may be contain not known properties. The implementation * must ignore these properties.
*/ void OPropertySetHelper::setPropertyValues(const Sequence<OUString>& rPropertyNames, const Sequence<Any>& rValues)
{
sal_Int32 nSeqLen = rPropertyNames.getLength(); if (nSeqLen != rValues.getLength()) throw IllegalArgumentException(u"lengths do not match"_ustr, static_cast<XPropertySet*>(this), -1);
std::unique_ptr<sal_Int32[]> pHandles(new sal_Int32[nSeqLen]); // get the map table
IPropertyArrayHelper& rPH = getInfoHelper(); // fill the handle array
sal_Int32 nHitCount = rPH.fillHandles(pHandles.get(), rPropertyNames); if (nHitCount == 0) return;
std::unique_lock aGuard(m_aMutex);
setFastPropertyValues(aGuard, nSeqLen, pHandles.get(), rValues.getConstArray(), nHitCount);
}
// get the map table
IPropertyArrayHelper& rPH = getInfoHelper(); // fill the handle array
rPH.fillHandles(pHandles.get(), rPropertyNames);
Any* pValues = aValues.getArray();
std::unique_lock aGuard(m_aMutex); // fill the sequence with the values for (sal_Int32 i = 0; i < nSeqLen; i++)
getFastPropertyValue(aGuard, pValues[i], pHandles[i]);
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.7Bemerkung:
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.