merge the formfield patch from ooo-build
[ooovba.git] / comphelper / source / property / composedprops.cxx
blobb24bce6e8077feb1ff01b521ba8aab8d83753835
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: composedprops.cxx,v $
10 * $Revision: 1.7 $
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_comphelper.hxx"
33 #include <comphelper/composedprops.hxx>
34 #include <com/sun/star/container/XChild.hpp>
35 #include <com/sun/star/beans/XPropertySetInfo.hpp>
36 #include <cppuhelper/implbase1.hxx>
38 //.........................................................................
39 namespace comphelper
41 //.........................................................................
43 using namespace ::com::sun::star::uno;
44 using namespace ::com::sun::star::beans;
45 using namespace ::com::sun::star::lang;
47 //=====================================================================
48 //= OComposedPropertySetInfo
49 //=====================================================================
50 class OComposedPropertySetInfo : public ::cppu::WeakImplHelper1< XPropertySetInfo >
52 private:
53 Sequence< Property> m_aProperties;
55 public:
56 OComposedPropertySetInfo(const Sequence< Property>& _rProperties);
58 virtual Sequence< Property > SAL_CALL getProperties( ) throw(RuntimeException);
59 virtual Property SAL_CALL getPropertyByName( const ::rtl::OUString& _rName ) throw(UnknownPropertyException, RuntimeException);
60 virtual sal_Bool SAL_CALL hasPropertyByName( const ::rtl::OUString& _rName ) throw(RuntimeException);
63 //=====================================================================
64 //= OComposedPropertySet
65 //=====================================================================
66 //---------------------------------------------------------------------
67 OComposedPropertySet::OComposedPropertySet(
68 const Sequence< Reference< XPropertySet> > & _rElements,
69 const IPropertySetComposerCallback* _pPropertyMetaData)
70 :m_pInfo(NULL)
72 // copy the sequence
73 sal_Int32 nSingleSets = _rElements.getLength();
74 if (nSingleSets)
76 m_aSingleSets.resize(nSingleSets);
77 const Reference< XPropertySet >* pSingleSets = _rElements.getConstArray();
78 ::std::copy(pSingleSets, pSingleSets + nSingleSets, m_aSingleSets.begin());
81 // impl ctor
82 compose(_pPropertyMetaData);
85 //---------------------------------------------------------------------
86 OComposedPropertySet::~OComposedPropertySet()
88 if (m_pInfo)
89 m_pInfo->release();
92 //---------------------------------------------------------------------
93 void OComposedPropertySet::compose(const IPropertySetComposerCallback* _pMetaData)
95 sal_Int32 nSingleSets = m_aSingleSets.size();
97 if (nSingleSets>0)
99 // get the properties of the first set
100 Reference< XPropertySet > xMasterSet = m_aSingleSets[0];
101 Sequence< Property> aMasterProps;
102 if (xMasterSet.is())
103 aMasterProps = xMasterSet->getPropertySetInfo()->getProperties();
104 sal_Int32 nMasterPropsCount = aMasterProps.getLength();
105 const Property* pMasterProps = aMasterProps.getConstArray();
107 // check which of the master properties should be included
108 Sequence<sal_Bool> aInclusionFlags(nMasterPropsCount);
109 sal_Bool* pInclusionFlags = aInclusionFlags.getArray();
111 // the states of all these properties
112 Sequence< PropertyState > aPropertyStates(nMasterPropsCount);
114 for (sal_Int32 i=0; i<nMasterPropsCount; ++i)
115 pInclusionFlags[i] = sal_True;
117 Reference< XPropertySet > xSecondarySet;
118 sal_Int32 nSecondaryPropertyCount;
119 Sequence< Property > aSecondaryProperties;
120 const Property* pPrimaryProperty = aMasterProps.getConstArray();
121 for (sal_Int32 nPrimary=0; nPrimary<nMasterPropsCount; ++nPrimary, ++pPrimaryProperty)
123 if (_pMetaData && !_pMetaData->isComposeable(pPrimaryProperty->Name))
124 // do not include this property
125 pInclusionFlags[nPrimary] = sal_False;
126 else
128 // search the property in all secondary sets
129 for (sal_Int32 i=1; i<nSingleSets; ++i)
131 xSecondarySet = m_aSingleSets[i];
132 aSecondaryProperties = xSecondarySet->getPropertySetInfo()->getProperties();
133 nSecondaryPropertyCount = aSecondaryProperties.getLength();
134 const Property* pSecondaryProperties = aSecondaryProperties.getConstArray();
136 // search the current primary property in the secondary property sequence
137 sal_Int32 k=0;
138 while (k<nSecondaryPropertyCount && (pSecondaryProperties[k].Name != pPrimaryProperty->Name))
139 ++k;
141 if (k >= nSecondaryPropertyCount)
142 // not found -> do not include
143 pInclusionFlags[nPrimary] = sal_False;
148 // count what's left ....
149 sal_Int32 nOverallProperties = 0;
150 for (sal_Int32 nCounter=0; nCounter<nMasterPropsCount; ++nCounter)
152 if (pInclusionFlags[nCounter])
153 ++nOverallProperties;
156 // and finally construct our sequence
157 m_aProperties = Sequence< Property >(nOverallProperties);
158 Property* pProperties = m_aProperties.getArray();
159 const Property* pMasterProperties = pMasterProps;
160 sal_Int32 nOwnProperties = 0;
161 for (sal_Int32 nCopy = 0; nCopy < nMasterPropsCount; ++nCopy, ++pMasterProperties)
163 if (pInclusionFlags[nCopy])
164 pProperties[nOwnProperties++] = *pMasterProperties;
169 //------------------------------------------------------------------------------
170 Reference< XPropertySetInfo > SAL_CALL OComposedPropertySet::getPropertySetInfo( ) throw(RuntimeException)
172 ::osl::MutexGuard aGuard(m_aMutex);
173 if (!m_pInfo)
175 m_pInfo = new OComposedPropertySetInfo(m_aProperties);
176 m_pInfo->acquire();
178 return m_pInfo;
181 //------------------------------------------------------------------------------
182 PropertyState SAL_CALL OComposedPropertySet::getPropertyState( const ::rtl::OUString& _rPropertyName ) throw(UnknownPropertyException, RuntimeException)
184 // assume DIRECT for the moment
185 PropertyState eState = PropertyState_DIRECT_VALUE;
187 sal_Int32 nSingleSets = m_aSingleSets.size();
188 if (nSingleSets>0)
190 // check the master state
191 Reference< XPropertySet > xMasterSet(m_aSingleSets[0]);
192 Any aPrimaryValue;
193 if (xMasterSet.is())
195 Reference< XPropertyState > xMasterState(xMasterSet,UNO_QUERY);
196 aPrimaryValue = xMasterSet->getPropertyValue(_rPropertyName);
198 if (xMasterState.is())
199 eState = xMasterState->getPropertyState(_rPropertyName);
202 // loop through the secondary sets
203 PropertyState eSecondaryState;
204 for (sal_Int32 i=1; i<nSingleSets; ++i)
206 Reference< XPropertySet > xSecondary(m_aSingleSets[i]);
207 Reference< XPropertyState > xSecondaryState(xSecondary, UNO_QUERY);
209 // the secondary state
210 eSecondaryState = PropertyState_DIRECT_VALUE;
211 if(xSecondaryState.is())
212 eSecondaryState = xSecondaryState->getPropertyState(_rPropertyName);
214 // the secondary value
215 Any aSecondaryValue(xSecondary->getPropertyValue(_rPropertyName));
217 if ( (PropertyState_AMBIGUOUS_VALUE == eSecondaryState) // secondary is ambiguous
218 || !::comphelper::compare(aPrimaryValue, aSecondaryValue) // unequal values
221 eState = PropertyState_AMBIGUOUS_VALUE;
222 break;
226 else
228 throw UnknownPropertyException( _rPropertyName, *this );
231 return eState;
234 //---------------------------------------------------------------------
235 Sequence< PropertyState > SAL_CALL OComposedPropertySet::getPropertyStates( const Sequence< ::rtl::OUString >& _rPropertyName ) throw(UnknownPropertyException, RuntimeException)
237 sal_Int32 nCount = _rPropertyName.getLength();
238 Sequence< PropertyState > aReturn(nCount);
239 const ::rtl::OUString* pNames = _rPropertyName.getConstArray();
240 PropertyState* pStates = aReturn.getArray();
241 for (sal_Int32 i=0; i<nCount; ++i, ++pNames, ++pStates)
242 *pStates = getPropertyState(*pNames);
243 return aReturn;
246 //---------------------------------------------------------------------
247 void SAL_CALL OComposedPropertySet::setPropertyToDefault( const ::rtl::OUString& _rPropertyName ) throw(UnknownPropertyException, RuntimeException)
249 sal_Int32 nSingleSets = m_aSingleSets.size();
250 for (sal_Int32 i=0; i<nSingleSets; ++i)
252 Reference< XPropertyState > xState(m_aSingleSets[i], UNO_QUERY);
253 if(xState.is())
254 xState->setPropertyToDefault(_rPropertyName);
258 //---------------------------------------------------------------------
259 Any SAL_CALL OComposedPropertySet::getPropertyDefault( const ::rtl::OUString& ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
261 return Any();
264 //------------------------------------------------------------------------------
265 void SAL_CALL OComposedPropertySet::setPropertyValue( const ::rtl::OUString& _rPropertyName, const Any& _rValue ) throw(UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException)
267 sal_Int32 nSingleSets = m_aSingleSets.size();
268 for (sal_Int32 i=0; i<nSingleSets; ++i)
270 if (m_aSingleSets[i].is())
271 m_aSingleSets[i]->setPropertyValue(_rPropertyName, _rValue);
275 //------------------------------------------------------------------------------
276 Any SAL_CALL OComposedPropertySet::getPropertyValue( const ::rtl::OUString& _rPropertyName ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
278 sal_Int32 nSingleSets = m_aSingleSets.size();
280 if ((nSingleSets>0) && (m_aSingleSets[0].is()))
281 return m_aSingleSets[0]->getPropertyValue(_rPropertyName);
282 return Any();
285 //------------------------------------------------------------------------------
286 void SAL_CALL OComposedPropertySet::addPropertyChangeListener( const ::rtl::OUString&, const Reference< XPropertyChangeListener >& ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
288 // TODO:
289 // hold the single property sets weak
290 // be a property change listener on all single property sets (for all composed properties)
291 // upon property change
292 // determine the new state/value of the composed property
293 // broadcast the new composed property value
296 //------------------------------------------------------------------------------
297 void SAL_CALL OComposedPropertySet::removePropertyChangeListener( const ::rtl::OUString&, const Reference< XPropertyChangeListener >& ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
299 // TODO
302 //------------------------------------------------------------------------------
303 void SAL_CALL OComposedPropertySet::addVetoableChangeListener( const ::rtl::OUString&, const Reference< XVetoableChangeListener >& ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
305 OSL_ENSURE(sal_False, "OComposedPropertySet::addVetoableChangeListener: no implemented (yet)!");
308 //------------------------------------------------------------------------------
309 void SAL_CALL OComposedPropertySet::removeVetoableChangeListener( const ::rtl::OUString&, const Reference< XVetoableChangeListener >& ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
311 OSL_ENSURE(sal_False, "OComposedPropertySet::removeVetoableChangeListener: no implemented (yet)!");
314 //------------------------------------------------------------------------------
315 OComposedPropertySetInfo::OComposedPropertySetInfo(const Sequence< Property>& rSeq)
316 :m_aProperties(rSeq)
320 //------------------------------------------------------------------------------
321 Sequence< Property> SAL_CALL OComposedPropertySetInfo::getProperties() throw(RuntimeException)
323 return m_aProperties;
326 //------------------------------------------------------------------------------
327 Property SAL_CALL OComposedPropertySetInfo::getPropertyByName( const ::rtl::OUString& _rName ) throw(UnknownPropertyException, RuntimeException)
329 sal_Int32 nLength = m_aProperties.getLength();
330 const Property* pProps = m_aProperties.getConstArray();
331 // TODO TODO TODO: this O(n) search really sucks ...
332 for (sal_Int32 i=0; i<nLength; ++i, ++pProps)
334 if (pProps->Name == _rName)
335 return *pProps;
338 throw UnknownPropertyException( _rName, *this );
341 //------------------------------------------------------------------------------
342 sal_Bool SAL_CALL OComposedPropertySetInfo::hasPropertyByName( const ::rtl::OUString& _rName ) throw(RuntimeException)
344 sal_Int32 nLength = m_aProperties.getLength();
345 const Property* pProps = m_aProperties.getConstArray();
346 // TODO TODO TODO: this O(n) search really sucks ...
347 for( sal_Int32 i=0; i<nLength; ++i,++pProps )
349 if(pProps->Name == _rName)
350 return sal_True;
353 return sal_False;
356 //.........................................................................
357 } // namespace comphelper
358 //.........................................................................