summaryrefslogtreecommitdiff
path: root/comphelper/source/property/composedprops.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'comphelper/source/property/composedprops.cxx')
-rw-r--r--comphelper/source/property/composedprops.cxx359
1 files changed, 359 insertions, 0 deletions
diff --git a/comphelper/source/property/composedprops.cxx b/comphelper/source/property/composedprops.cxx
new file mode 100644
index 000000000000..aa864f7ca47f
--- /dev/null
+++ b/comphelper/source/property/composedprops.cxx
@@ -0,0 +1,359 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_comphelper.hxx"
+#include <comphelper/composedprops.hxx>
+#include <com/sun/star/container/XChild.hpp>
+#include <com/sun/star/beans/XPropertySetInfo.hpp>
+#include <cppuhelper/implbase1.hxx>
+
+//.........................................................................
+namespace comphelper
+{
+//.........................................................................
+
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::lang;
+
+ //=====================================================================
+ //= OComposedPropertySetInfo
+ //=====================================================================
+ class OComposedPropertySetInfo : public ::cppu::WeakImplHelper1< XPropertySetInfo >
+ {
+ private:
+ Sequence< Property> m_aProperties;
+
+ public:
+ OComposedPropertySetInfo(const Sequence< Property>& _rProperties);
+
+ virtual Sequence< Property > SAL_CALL getProperties( ) throw(RuntimeException);
+ virtual Property SAL_CALL getPropertyByName( const ::rtl::OUString& _rName ) throw(UnknownPropertyException, RuntimeException);
+ virtual sal_Bool SAL_CALL hasPropertyByName( const ::rtl::OUString& _rName ) throw(RuntimeException);
+ };
+
+ //=====================================================================
+ //= OComposedPropertySet
+ //=====================================================================
+ //---------------------------------------------------------------------
+ OComposedPropertySet::OComposedPropertySet(
+ const Sequence< Reference< XPropertySet> > & _rElements,
+ const IPropertySetComposerCallback* _pPropertyMetaData)
+ :m_pInfo(NULL)
+ {
+ // copy the sequence
+ sal_Int32 nSingleSets = _rElements.getLength();
+ if (nSingleSets)
+ {
+ m_aSingleSets.resize(nSingleSets);
+ const Reference< XPropertySet >* pSingleSets = _rElements.getConstArray();
+ ::std::copy(pSingleSets, pSingleSets + nSingleSets, m_aSingleSets.begin());
+ }
+
+ // impl ctor
+ compose(_pPropertyMetaData);
+ }
+
+ //---------------------------------------------------------------------
+ OComposedPropertySet::~OComposedPropertySet()
+ {
+ if (m_pInfo)
+ m_pInfo->release();
+ }
+
+ //---------------------------------------------------------------------
+ void OComposedPropertySet::compose(const IPropertySetComposerCallback* _pMetaData)
+ {
+ sal_Int32 nSingleSets = m_aSingleSets.size();
+
+ if (nSingleSets>0)
+ {
+ // get the properties of the first set
+ Reference< XPropertySet > xMasterSet = m_aSingleSets[0];
+ Sequence< Property> aMasterProps;
+ if (xMasterSet.is())
+ aMasterProps = xMasterSet->getPropertySetInfo()->getProperties();
+ sal_Int32 nMasterPropsCount = aMasterProps.getLength();
+ const Property* pMasterProps = aMasterProps.getConstArray();
+
+ // check which of the master properties should be included
+ Sequence<sal_Bool> aInclusionFlags(nMasterPropsCount);
+ sal_Bool* pInclusionFlags = aInclusionFlags.getArray();
+
+ // the states of all these properties
+ Sequence< PropertyState > aPropertyStates(nMasterPropsCount);
+
+ for (sal_Int32 i=0; i<nMasterPropsCount; ++i)
+ pInclusionFlags[i] = sal_True;
+
+ Reference< XPropertySet > xSecondarySet;
+ sal_Int32 nSecondaryPropertyCount;
+ Sequence< Property > aSecondaryProperties;
+ const Property* pPrimaryProperty = aMasterProps.getConstArray();
+ for (sal_Int32 nPrimary=0; nPrimary<nMasterPropsCount; ++nPrimary, ++pPrimaryProperty)
+ {
+ if (_pMetaData && !_pMetaData->isComposeable(pPrimaryProperty->Name))
+ // do not include this property
+ pInclusionFlags[nPrimary] = sal_False;
+ else
+ {
+ // search the property in all secondary sets
+ for (sal_Int32 i=1; i<nSingleSets; ++i)
+ {
+ xSecondarySet = m_aSingleSets[i];
+ aSecondaryProperties = xSecondarySet->getPropertySetInfo()->getProperties();
+ nSecondaryPropertyCount = aSecondaryProperties.getLength();
+ const Property* pSecondaryProperties = aSecondaryProperties.getConstArray();
+
+ // search the current primary property in the secondary property sequence
+ sal_Int32 k=0;
+ while (k<nSecondaryPropertyCount && (pSecondaryProperties[k].Name != pPrimaryProperty->Name))
+ ++k;
+
+ if (k >= nSecondaryPropertyCount)
+ // not found -> do not include
+ pInclusionFlags[nPrimary] = sal_False;
+ }
+ }
+ }
+
+ // count what's left ....
+ sal_Int32 nOverallProperties = 0;
+ for (sal_Int32 nCounter=0; nCounter<nMasterPropsCount; ++nCounter)
+ {
+ if (pInclusionFlags[nCounter])
+ ++nOverallProperties;
+ }
+
+ // and finally construct our sequence
+ m_aProperties = Sequence< Property >(nOverallProperties);
+ Property* pProperties = m_aProperties.getArray();
+ const Property* pMasterProperties = pMasterProps;
+ sal_Int32 nOwnProperties = 0;
+ for (sal_Int32 nCopy = 0; nCopy < nMasterPropsCount; ++nCopy, ++pMasterProperties)
+ {
+ if (pInclusionFlags[nCopy])
+ pProperties[nOwnProperties++] = *pMasterProperties;
+ }
+ }
+ }
+
+ //------------------------------------------------------------------------------
+ Reference< XPropertySetInfo > SAL_CALL OComposedPropertySet::getPropertySetInfo( ) throw(RuntimeException)
+ {
+ ::osl::MutexGuard aGuard(m_aMutex);
+ if (!m_pInfo)
+ {
+ m_pInfo = new OComposedPropertySetInfo(m_aProperties);
+ m_pInfo->acquire();
+ }
+ return m_pInfo;
+ }
+
+ //------------------------------------------------------------------------------
+ PropertyState SAL_CALL OComposedPropertySet::getPropertyState( const ::rtl::OUString& _rPropertyName ) throw(UnknownPropertyException, RuntimeException)
+ {
+ // assume DIRECT for the moment
+ PropertyState eState = PropertyState_DIRECT_VALUE;
+
+ sal_Int32 nSingleSets = m_aSingleSets.size();
+ if (nSingleSets>0)
+ {
+ // check the master state
+ Reference< XPropertySet > xMasterSet(m_aSingleSets[0]);
+ Any aPrimaryValue;
+ if (xMasterSet.is())
+ {
+ Reference< XPropertyState > xMasterState(xMasterSet,UNO_QUERY);
+ aPrimaryValue = xMasterSet->getPropertyValue(_rPropertyName);
+
+ if (xMasterState.is())
+ eState = xMasterState->getPropertyState(_rPropertyName);
+ }
+
+ // loop through the secondary sets
+ PropertyState eSecondaryState;
+ for (sal_Int32 i=1; i<nSingleSets; ++i)
+ {
+ Reference< XPropertySet > xSecondary(m_aSingleSets[i]);
+ Reference< XPropertyState > xSecondaryState(xSecondary, UNO_QUERY);
+
+ // the secondary state
+ eSecondaryState = PropertyState_DIRECT_VALUE;
+ if(xSecondaryState.is())
+ eSecondaryState = xSecondaryState->getPropertyState(_rPropertyName);
+
+ // the secondary value
+ Any aSecondaryValue(xSecondary->getPropertyValue(_rPropertyName));
+
+ if ( (PropertyState_AMBIGUOUS_VALUE == eSecondaryState) // secondary is ambiguous
+ || !::comphelper::compare(aPrimaryValue, aSecondaryValue) // unequal values
+ )
+ {
+ eState = PropertyState_AMBIGUOUS_VALUE;
+ break;
+ }
+ }
+ }
+ else
+ {
+ throw UnknownPropertyException( _rPropertyName, *this );
+ }
+
+ return eState;
+ }
+
+ //---------------------------------------------------------------------
+ Sequence< PropertyState > SAL_CALL OComposedPropertySet::getPropertyStates( const Sequence< ::rtl::OUString >& _rPropertyName ) throw(UnknownPropertyException, RuntimeException)
+ {
+ sal_Int32 nCount = _rPropertyName.getLength();
+ Sequence< PropertyState > aReturn(nCount);
+ const ::rtl::OUString* pNames = _rPropertyName.getConstArray();
+ PropertyState* pStates = aReturn.getArray();
+ for (sal_Int32 i=0; i<nCount; ++i, ++pNames, ++pStates)
+ *pStates = getPropertyState(*pNames);
+ return aReturn;
+ }
+
+ //---------------------------------------------------------------------
+ void SAL_CALL OComposedPropertySet::setPropertyToDefault( const ::rtl::OUString& _rPropertyName ) throw(UnknownPropertyException, RuntimeException)
+ {
+ sal_Int32 nSingleSets = m_aSingleSets.size();
+ for (sal_Int32 i=0; i<nSingleSets; ++i)
+ {
+ Reference< XPropertyState > xState(m_aSingleSets[i], UNO_QUERY);
+ if(xState.is())
+ xState->setPropertyToDefault(_rPropertyName);
+ }
+ }
+
+ //---------------------------------------------------------------------
+ Any SAL_CALL OComposedPropertySet::getPropertyDefault( const ::rtl::OUString& ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+ {
+ return Any();
+ }
+
+ //------------------------------------------------------------------------------
+ void SAL_CALL OComposedPropertySet::setPropertyValue( const ::rtl::OUString& _rPropertyName, const Any& _rValue ) throw(UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException)
+ {
+ sal_Int32 nSingleSets = m_aSingleSets.size();
+ for (sal_Int32 i=0; i<nSingleSets; ++i)
+ {
+ if (m_aSingleSets[i].is())
+ m_aSingleSets[i]->setPropertyValue(_rPropertyName, _rValue);
+ }
+ }
+
+ //------------------------------------------------------------------------------
+ Any SAL_CALL OComposedPropertySet::getPropertyValue( const ::rtl::OUString& _rPropertyName ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+ {
+ sal_Int32 nSingleSets = m_aSingleSets.size();
+
+ if ((nSingleSets>0) && (m_aSingleSets[0].is()))
+ return m_aSingleSets[0]->getPropertyValue(_rPropertyName);
+ return Any();
+ }
+
+ //------------------------------------------------------------------------------
+ void SAL_CALL OComposedPropertySet::addPropertyChangeListener( const ::rtl::OUString&, const Reference< XPropertyChangeListener >& ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+ {
+ // TODO:
+ // hold the single property sets weak
+ // be a property change listener on all single property sets (for all composed properties)
+ // upon property change
+ // determine the new state/value of the composed property
+ // broadcast the new composed property value
+ }
+
+ //------------------------------------------------------------------------------
+ void SAL_CALL OComposedPropertySet::removePropertyChangeListener( const ::rtl::OUString&, const Reference< XPropertyChangeListener >& ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+ {
+ // TODO
+ }
+
+ //------------------------------------------------------------------------------
+ void SAL_CALL OComposedPropertySet::addVetoableChangeListener( const ::rtl::OUString&, const Reference< XVetoableChangeListener >& ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+ {
+ OSL_FAIL("OComposedPropertySet::addVetoableChangeListener: no implemented (yet)!");
+ }
+
+ //------------------------------------------------------------------------------
+ void SAL_CALL OComposedPropertySet::removeVetoableChangeListener( const ::rtl::OUString&, const Reference< XVetoableChangeListener >& ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+ {
+ OSL_FAIL("OComposedPropertySet::removeVetoableChangeListener: no implemented (yet)!");
+ }
+
+ //------------------------------------------------------------------------------
+ OComposedPropertySetInfo::OComposedPropertySetInfo(const Sequence< Property>& rSeq)
+ :m_aProperties(rSeq)
+ {
+ }
+
+ //------------------------------------------------------------------------------
+ Sequence< Property> SAL_CALL OComposedPropertySetInfo::getProperties() throw(RuntimeException)
+ {
+ return m_aProperties;
+ }
+
+ //------------------------------------------------------------------------------
+ Property SAL_CALL OComposedPropertySetInfo::getPropertyByName( const ::rtl::OUString& _rName ) throw(UnknownPropertyException, RuntimeException)
+ {
+ sal_Int32 nLength = m_aProperties.getLength();
+ const Property* pProps = m_aProperties.getConstArray();
+ // TODO TODO TODO: this O(n) search really sucks ...
+ for (sal_Int32 i=0; i<nLength; ++i, ++pProps)
+ {
+ if (pProps->Name == _rName)
+ return *pProps;
+ }
+
+ throw UnknownPropertyException( _rName, *this );
+ }
+
+ //------------------------------------------------------------------------------
+ sal_Bool SAL_CALL OComposedPropertySetInfo::hasPropertyByName( const ::rtl::OUString& _rName ) throw(RuntimeException)
+ {
+ sal_Int32 nLength = m_aProperties.getLength();
+ const Property* pProps = m_aProperties.getConstArray();
+ // TODO TODO TODO: this O(n) search really sucks ...
+ for( sal_Int32 i=0; i<nLength; ++i,++pProps )
+ {
+ if(pProps->Name == _rName)
+ return sal_True;
+ }
+
+ return sal_False;
+ }
+
+//.........................................................................
+} // namespace comphelper
+//.........................................................................
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */