xref: /AOO41X/main/toolkit/source/controls/geometrycontrolmodel.cxx (revision b0724fc6948542b2496e16ea247f985ee5987cfe)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_toolkit.hxx"
26 #include "toolkit/controls/geometrycontrolmodel.hxx"
27 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
28 #include <com/sun/star/beans/PropertyAttribute.hpp>
29 #include <osl/diagnose.h>
30 #include <rtl/instance.hxx>
31 #include <comphelper/property.hxx>
32 #include <comphelper/sequence.hxx>
33 #ifndef _COM_SUN_STAR_XNAMECONTAINER_HPP_
34 #include <toolkit/controls/eventcontainer.hxx>
35 #endif
36 #include <toolkit/helper/property.hxx>
37 #include <tools/debug.hxx>
38 #include <algorithm>
39 #include <functional>
40 #include <comphelper/sequence.hxx>
41 
42 
43 #define GCM_PROPERTY_ID_POS_X               1
44 #define GCM_PROPERTY_ID_POS_Y               2
45 #define GCM_PROPERTY_ID_WIDTH               3
46 #define GCM_PROPERTY_ID_HEIGHT              4
47 #define GCM_PROPERTY_ID_NAME                5
48 #define GCM_PROPERTY_ID_TABINDEX            6
49 #define GCM_PROPERTY_ID_STEP                7
50 #define GCM_PROPERTY_ID_TAG                 8
51 #define GCM_PROPERTY_ID_RESOURCERESOLVER    9
52 
53 #define GCM_PROPERTY_POS_X              ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("PositionX"))
54 #define GCM_PROPERTY_POS_Y              ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("PositionY"))
55 #define GCM_PROPERTY_WIDTH              ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Width"))
56 #define GCM_PROPERTY_HEIGHT             ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Height"))
57 #define GCM_PROPERTY_NAME               ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Name"))
58 #define GCM_PROPERTY_TABINDEX           ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("TabIndex"))
59 #define GCM_PROPERTY_STEP               ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Step"))
60 #define GCM_PROPERTY_TAG                ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Tag"))
61 #define GCM_PROPERTY_RESOURCERESOLVER   ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ResourceResolver"))
62 
63 #define DEFAULT_ATTRIBS()       PropertyAttribute::BOUND | PropertyAttribute::TRANSIENT
64 
65 //........................................................................
66 // namespace toolkit
67 // {
68 //........................................................................
69 
70     using namespace ::com::sun::star;
71     using namespace ::com::sun::star::uno;
72     using namespace ::com::sun::star::lang;
73     using namespace ::com::sun::star::beans;
74     using namespace ::com::sun::star::util;
75     using namespace ::com::sun::star::container;
76     using namespace ::comphelper;
77 
78     //====================================================================
79     //= OGeometryControlModel_Base
80     //====================================================================
81     //--------------------------------------------------------------------
OGeometryControlModel_Base(::com::sun::star::uno::XAggregation * _pAggregateInstance)82     OGeometryControlModel_Base::OGeometryControlModel_Base(::com::sun::star::uno::XAggregation* _pAggregateInstance)
83         :OPropertySetAggregationHelper( m_aBHelper )
84         ,OPropertyContainer( m_aBHelper )
85         ,OGCM_Base( m_aMutex )
86         ,m_nPosX(0)
87         ,m_nPosY(0)
88         ,m_nWidth(0)
89         ,m_nHeight(0)
90         ,m_nTabIndex(-1)
91         ,m_nStep(0)
92         ,m_bCloneable(sal_False)
93     {
94         OSL_ENSURE(NULL != _pAggregateInstance, "OGeometryControlModel_Base::OGeometryControlModel_Base: invalid aggregate!");
95 
96         increment(m_refCount);
97         {
98             m_xAggregate = _pAggregateInstance;
99 
100             {   // check if the aggregat is cloneable
101                 Reference< XCloneable > xCloneAccess(m_xAggregate, UNO_QUERY);
102                 m_bCloneable = xCloneAccess.is();
103             }
104 
105             setAggregation(m_xAggregate);
106             m_xAggregate->setDelegator(static_cast< XWeak* >(this));
107         }
108         decrement(m_refCount);
109 
110         registerProperties();
111     }
112 
113     //--------------------------------------------------------------------
OGeometryControlModel_Base(Reference<XCloneable> & _rxAggregateInstance)114     OGeometryControlModel_Base::OGeometryControlModel_Base(Reference< XCloneable >& _rxAggregateInstance)
115         :OPropertySetAggregationHelper( m_aBHelper )
116         ,OPropertyContainer( m_aBHelper )
117         ,OGCM_Base( m_aMutex )
118         ,m_nPosX(0)
119         ,m_nPosY(0)
120         ,m_nWidth(0)
121         ,m_nHeight(0)
122         ,m_nTabIndex(-1)
123         ,m_nStep(0)
124         ,m_bCloneable(_rxAggregateInstance.is())
125     {
126         increment(m_refCount);
127         {
128             {
129                 // ensure that the temporary gets destructed NOW
130                 m_xAggregate = Reference< XAggregation >(_rxAggregateInstance, UNO_QUERY);
131             }
132             OSL_ENSURE(m_xAggregate.is(), "OGeometryControlModel_Base::OGeometryControlModel_Base: invalid object given!");
133 
134             // now the aggregate has a ref count of 2, but before setting the delegator it must be 1
135             _rxAggregateInstance.clear();
136             // now it should be the 1 we need here ...
137 
138             setAggregation(m_xAggregate);
139             m_xAggregate->setDelegator(static_cast< XWeak* >(this));
140         }
141         decrement(m_refCount);
142 
143         registerProperties();
144     }
145 
146     //--------------------------------------------------------------------
getTypes()147     Sequence< Type > SAL_CALL OGeometryControlModel_Base::getTypes(  ) throw (RuntimeException)
148     {
149         // our own types
150         Sequence< Type > aTypes = ::comphelper::concatSequences(
151             OPropertySetAggregationHelper::getTypes(),
152             OPropertyContainer::getTypes(),
153             OGCM_Base::getTypes()
154         );
155 
156         if ( m_xAggregate.is() )
157         {
158             // retrieve the types of the aggregate
159             Reference< XTypeProvider > xAggregateTypeProv;
160             m_xAggregate->queryAggregation( ::getCppuType( &xAggregateTypeProv ) ) >>= xAggregateTypeProv;
161             OSL_ENSURE( xAggregateTypeProv.is(), "OGeometryControlModel_Base::getTypes: aggregate should be a type provider!" );
162             Sequence< Type > aAggTypes;
163             if ( xAggregateTypeProv.is() )
164                 aAggTypes = xAggregateTypeProv->getTypes();
165 
166             // concat the sequences
167             sal_Int32 nOldSize = aTypes.getLength();
168             aTypes.realloc( nOldSize + aAggTypes.getLength() );
169             ::std::copy(
170                 aAggTypes.getConstArray(),
171                 aAggTypes.getConstArray() + aAggTypes.getLength(),
172                 aTypes.getArray() + nOldSize
173             );
174         }
175 
176         return aTypes;
177     }
178 
179     //--------------------------------------------------------------------
registerProperties()180     void OGeometryControlModel_Base::registerProperties()
181     {
182         // register our members for the property handling of the OPropertyContainer
183         registerProperty(GCM_PROPERTY_POS_X,    GCM_PROPERTY_ID_POS_X,      DEFAULT_ATTRIBS(), &m_nPosX, ::getCppuType(&m_nPosX));
184         registerProperty(GCM_PROPERTY_POS_Y,    GCM_PROPERTY_ID_POS_Y,      DEFAULT_ATTRIBS(), &m_nPosY, ::getCppuType(&m_nPosY));
185         registerProperty(GCM_PROPERTY_WIDTH,    GCM_PROPERTY_ID_WIDTH,      DEFAULT_ATTRIBS(), &m_nWidth, ::getCppuType(&m_nWidth));
186         registerProperty(GCM_PROPERTY_HEIGHT,   GCM_PROPERTY_ID_HEIGHT,     DEFAULT_ATTRIBS(), &m_nHeight, ::getCppuType(&m_nHeight));
187         registerProperty(GCM_PROPERTY_NAME,     GCM_PROPERTY_ID_NAME,       DEFAULT_ATTRIBS(), &m_aName, ::getCppuType(&m_aName));
188         registerProperty(GCM_PROPERTY_TABINDEX, GCM_PROPERTY_ID_TABINDEX,   DEFAULT_ATTRIBS(), &m_nTabIndex, ::getCppuType(&m_nTabIndex));
189         registerProperty(GCM_PROPERTY_STEP,     GCM_PROPERTY_ID_STEP,       DEFAULT_ATTRIBS(), &m_nStep, ::getCppuType(&m_nStep));
190         registerProperty(GCM_PROPERTY_TAG,      GCM_PROPERTY_ID_TAG,        DEFAULT_ATTRIBS(), &m_aTag, ::getCppuType(&m_aTag));
191         registerProperty(GCM_PROPERTY_RESOURCERESOLVER, GCM_PROPERTY_ID_RESOURCERESOLVER, DEFAULT_ATTRIBS(), &m_xStrResolver, ::getCppuType(&m_xStrResolver));
192     }
193 
194     //--------------------------------------------------------------------
ImplGetDefaultValueByHandle(sal_Int32 nHandle) const195     ::com::sun::star::uno::Any OGeometryControlModel_Base::ImplGetDefaultValueByHandle(sal_Int32 nHandle) const
196     {
197         ::com::sun::star::uno::Any aDefault;
198 
199         switch ( nHandle )
200         {
201             case GCM_PROPERTY_ID_POS_X:             aDefault <<= (sal_Int32) 0; break;
202             case GCM_PROPERTY_ID_POS_Y:             aDefault <<= (sal_Int32) 0; break;
203             case GCM_PROPERTY_ID_WIDTH:             aDefault <<= (sal_Int32) 0; break;
204             case GCM_PROPERTY_ID_HEIGHT:            aDefault <<= (sal_Int32) 0; break;
205             case GCM_PROPERTY_ID_NAME:              aDefault <<= ::rtl::OUString(); break;
206             case GCM_PROPERTY_ID_TABINDEX:          aDefault <<= (sal_Int16) -1; break;
207             case GCM_PROPERTY_ID_STEP:              aDefault <<= (sal_Int32) 0; break;
208             case GCM_PROPERTY_ID_TAG:               aDefault <<= ::rtl::OUString(); break;
209             case GCM_PROPERTY_ID_RESOURCERESOLVER:  aDefault <<= Reference< resource::XStringResourceResolver >(); break;
210             default:                            DBG_ERROR( "ImplGetDefaultValueByHandle - unknown Property" );
211         }
212 
213         return aDefault;
214     }
215 
216     //--------------------------------------------------------------------
ImplGetPropertyValueByHandle(sal_Int32 nHandle) const217     ::com::sun::star::uno::Any OGeometryControlModel_Base::ImplGetPropertyValueByHandle(sal_Int32 nHandle) const
218     {
219         ::com::sun::star::uno::Any aValue;
220 
221         switch ( nHandle )
222         {
223             case GCM_PROPERTY_ID_POS_X:         aValue <<= m_nPosX; break;
224             case GCM_PROPERTY_ID_POS_Y:         aValue <<= m_nPosY; break;
225             case GCM_PROPERTY_ID_WIDTH:         aValue <<= m_nWidth; break;
226             case GCM_PROPERTY_ID_HEIGHT:        aValue <<= m_nHeight; break;
227             case GCM_PROPERTY_ID_NAME:          aValue <<= m_aName; break;
228             case GCM_PROPERTY_ID_TABINDEX:      aValue <<= m_nTabIndex; break;
229             case GCM_PROPERTY_ID_STEP:          aValue <<= m_nStep; break;
230             case GCM_PROPERTY_ID_TAG:           aValue <<= m_aTag; break;
231             case GCM_PROPERTY_ID_RESOURCERESOLVER: aValue <<= m_xStrResolver; break;
232             default:                            DBG_ERROR( "ImplGetPropertyValueByHandle - unknown Property" );
233         }
234 
235         return aValue;
236     }
237 
238     //--------------------------------------------------------------------
ImplSetPropertyValueByHandle(sal_Int32 nHandle,const::com::sun::star::uno::Any & aValue)239     void OGeometryControlModel_Base::ImplSetPropertyValueByHandle(sal_Int32 nHandle, const :: com::sun::star::uno::Any& aValue)
240     {
241         switch ( nHandle )
242         {
243             case GCM_PROPERTY_ID_POS_X:         aValue >>= m_nPosX; break;
244             case GCM_PROPERTY_ID_POS_Y:         aValue >>= m_nPosY; break;
245             case GCM_PROPERTY_ID_WIDTH:         aValue >>= m_nWidth; break;
246             case GCM_PROPERTY_ID_HEIGHT:        aValue >>= m_nHeight; break;
247             case GCM_PROPERTY_ID_NAME:          aValue >>= m_aName; break;
248             case GCM_PROPERTY_ID_TABINDEX:      aValue >>= m_nTabIndex; break;
249             case GCM_PROPERTY_ID_STEP:          aValue >>= m_nStep; break;
250             case GCM_PROPERTY_ID_TAG:           aValue >>= m_aTag; break;
251             case GCM_PROPERTY_ID_RESOURCERESOLVER: aValue >>= m_xStrResolver; break;
252             default:                            DBG_ERROR( "ImplSetPropertyValueByHandle - unknown Property" );
253         }
254     }
255 
256     //--------------------------------------------------------------------
queryAggregation(const Type & _rType)257     Any SAL_CALL OGeometryControlModel_Base::queryAggregation( const Type& _rType ) throw(RuntimeException)
258     {
259         Any aReturn;
260         if (_rType.equals(::getCppuType(static_cast< Reference< XCloneable>* >(NULL))) && !m_bCloneable)
261             // somebody is asking for the XCloneable interface, but our aggregate does not support it
262             // -> outta here
263             // (need this extra check, cause OGCM_Base::queryAggregation would return this interface
264             // in every case)
265             return aReturn;
266 
267         aReturn = OGCM_Base::queryAggregation(_rType);
268             // the basic interfaces (XInterface, XAggregation etc)
269 
270         if (!aReturn.hasValue())
271             aReturn = OPropertySetAggregationHelper::queryInterface(_rType);
272             // the property set related interfaces
273 
274         if (!aReturn.hasValue() && m_xAggregate.is())
275             aReturn = m_xAggregate->queryAggregation(_rType);
276             // the interfaces our aggregate can provide
277 
278         return aReturn;
279     }
280 
281     //--------------------------------------------------------------------
queryInterface(const Type & _rType)282     Any SAL_CALL OGeometryControlModel_Base::queryInterface( const Type& _rType ) throw(RuntimeException)
283     {
284         return OGCM_Base::queryInterface(_rType);
285     }
286 
287     //--------------------------------------------------------------------
acquire()288     void SAL_CALL OGeometryControlModel_Base::acquire(  ) throw()
289     {
290         OGCM_Base::acquire();
291     }
292 
293     //--------------------------------------------------------------------
release()294     void SAL_CALL OGeometryControlModel_Base::release(  ) throw()
295     {
296         OGCM_Base::release();
297     }
298 
299     //--------------------------------------------------------------------
releaseAggregation()300     void OGeometryControlModel_Base::releaseAggregation()
301     {
302         // release the aggregate (_before_ clearing m_xAggregate)
303         if (m_xAggregate.is())
304             m_xAggregate->setDelegator(NULL);
305         setAggregation(NULL);
306     }
307 
308     //--------------------------------------------------------------------
~OGeometryControlModel_Base()309     OGeometryControlModel_Base::~OGeometryControlModel_Base()
310     {
311         releaseAggregation();
312     }
313 
314     //--------------------------------------------------------------------
convertFastPropertyValue(Any & _rConvertedValue,Any & _rOldValue,sal_Int32 _nHandle,const Any & _rValue)315     sal_Bool SAL_CALL OGeometryControlModel_Base::convertFastPropertyValue(Any& _rConvertedValue, Any& _rOldValue,
316             sal_Int32 _nHandle, const Any& _rValue) throw (IllegalArgumentException)
317     {
318         return OPropertyContainer::convertFastPropertyValue(_rConvertedValue, _rOldValue, _nHandle, _rValue);
319     }
320 
321     //--------------------------------------------------------------------
setFastPropertyValue_NoBroadcast(sal_Int32 _nHandle,const Any & _rValue)322     void SAL_CALL OGeometryControlModel_Base::setFastPropertyValue_NoBroadcast(sal_Int32 _nHandle, const Any& _rValue) throw (Exception)
323     {
324         OPropertyContainer::setFastPropertyValue_NoBroadcast(_nHandle, _rValue);
325     }
326 
327     //--------------------------------------------------------------------
getFastPropertyValue(Any & _rValue,sal_Int32 _nHandle) const328     void SAL_CALL OGeometryControlModel_Base::getFastPropertyValue(Any& _rValue, sal_Int32 _nHandle) const
329     {
330         OPropertyArrayAggregationHelper& rPH = static_cast<OPropertyArrayAggregationHelper&>(const_cast<OGeometryControlModel_Base*>(this)->getInfoHelper());
331         ::rtl::OUString sPropName;
332         sal_Int32   nOriginalHandle = -1;
333 
334         if (rPH.fillAggregatePropertyInfoByHandle(&sPropName, &nOriginalHandle, _nHandle))
335             OPropertySetAggregationHelper::getFastPropertyValue(_rValue, _nHandle);
336         else
337             OPropertyContainer::getFastPropertyValue(_rValue, _nHandle);
338     }
339 
340     //--------------------------------------------------------------------
getPropertyStateByHandle(sal_Int32 nHandle)341     ::com::sun::star::beans::PropertyState OGeometryControlModel_Base::getPropertyStateByHandle(sal_Int32 nHandle)
342     {
343         ::com::sun::star::uno::Any aValue = ImplGetPropertyValueByHandle( nHandle );
344         ::com::sun::star::uno::Any aDefault = ImplGetDefaultValueByHandle( nHandle );
345 
346         return CompareProperties( aValue, aDefault ) ? ::com::sun::star::beans::PropertyState_DEFAULT_VALUE : ::com::sun::star::beans::PropertyState_DIRECT_VALUE;
347     }
348 
349     //--------------------------------------------------------------------
setPropertyToDefaultByHandle(sal_Int32 nHandle)350     void OGeometryControlModel_Base::setPropertyToDefaultByHandle(sal_Int32 nHandle)
351     {
352         ImplSetPropertyValueByHandle( nHandle , ImplGetDefaultValueByHandle( nHandle ) );
353     }
354 
355     //--------------------------------------------------------------------
getPropertyDefaultByHandle(sal_Int32 nHandle) const356     ::com::sun::star::uno::Any OGeometryControlModel_Base::getPropertyDefaultByHandle( sal_Int32 nHandle ) const
357     {
358         return ImplGetDefaultValueByHandle( nHandle );
359     }
360 
361     //--------------------------------------------------------------------
getPropertySetInfo()362     Reference< XPropertySetInfo> SAL_CALL OGeometryControlModel_Base::getPropertySetInfo() throw(RuntimeException)
363     {
364         return OPropertySetAggregationHelper::createPropertySetInfo(getInfoHelper());
365     }
366 
367     //--------------------------------------------------------------------
createClone()368     Reference< XCloneable > SAL_CALL OGeometryControlModel_Base::createClone(  ) throw(RuntimeException)
369     {
370         OSL_ENSURE(m_bCloneable, "OGeometryControlModel_Base::createClone: invalid call!");
371         if (!m_bCloneable)
372             return Reference< XCloneable >();
373 
374         // let the aggregate create it's own clone
375         // the interface
376         Reference< XCloneable > xCloneAccess;
377         m_xAggregate->queryAggregation(::getCppuType(&xCloneAccess)) >>= xCloneAccess;
378         OSL_ENSURE(xCloneAccess.is(), "OGeometryControlModel_Base::createClone: suspicious aggregate!");
379         if (!xCloneAccess.is())
380             return Reference< XCloneable >();
381         // the aggregate's clone
382         Reference< XCloneable > xAggregateClone = xCloneAccess->createClone();
383         OSL_ENSURE(xAggregateClone.is(), "OGeometryControlModel_Base::createClone: suspicious return of the aggregate!");
384 
385         // create a new wrapper aggregating this return value
386         OGeometryControlModel_Base* pOwnClone = createClone_Impl(xAggregateClone);
387         OSL_ENSURE(pOwnClone, "OGeometryControlModel_Base::createClone: invalid derivee behaviour!");
388         OSL_ENSURE(!xAggregateClone.is(), "OGeometryControlModel_Base::createClone: invalid ctor behaviour!");
389             // should have been reset
390 
391         // set properties
392         pOwnClone->m_nPosX      = m_nPosX;
393         pOwnClone->m_nPosY      = m_nPosY;
394         pOwnClone->m_nWidth     = m_nWidth;
395         pOwnClone->m_nHeight    = m_nHeight;
396         pOwnClone->m_aName      = m_aName;
397         pOwnClone->m_nTabIndex  = m_nTabIndex;
398         pOwnClone->m_nStep      = m_nStep;
399         pOwnClone->m_aTag       = m_aTag;
400 
401 
402         // Clone event container
403         Reference< ::com::sun::star::script::XScriptEventsSupplier > xEventsSupplier =
404             static_cast< ::com::sun::star::script::XScriptEventsSupplier* >( this );
405         Reference< ::com::sun::star::script::XScriptEventsSupplier > xCloneEventsSupplier =
406             static_cast< ::com::sun::star::script::XScriptEventsSupplier* >( pOwnClone );
407 
408         if( xEventsSupplier.is() && xCloneEventsSupplier.is() )
409         {
410             Reference< XNameContainer > xEventCont = xEventsSupplier->getEvents();
411             Reference< XNameContainer > xCloneEventCont = xCloneEventsSupplier->getEvents();
412 
413             ::com::sun::star::uno::Sequence< ::rtl::OUString > aNames =
414                 xEventCont->getElementNames();
415             const ::rtl::OUString* pNames = aNames.getConstArray();
416             sal_Int32 i, nNameCount = aNames.getLength();
417 
418             for( i = 0 ; i < nNameCount ; i++ )
419             {
420                 ::rtl::OUString aName = pNames[ i ];
421                 ::com::sun::star::uno::Any aElement = xEventCont->getByName( aName );
422                 xCloneEventCont->insertByName( aName, aElement );
423             }
424         }
425 
426         return pOwnClone;
427     }
428 
429     //--------------------------------------------------------------------
getEvents()430     Reference< XNameContainer > SAL_CALL OGeometryControlModel_Base::getEvents() throw(RuntimeException)
431     {
432         if( !mxEventContainer.is() )
433             mxEventContainer = (XNameContainer*)new toolkit::ScriptEventContainer();
434         return mxEventContainer;
435     }
436 
437     //--------------------------------------------------------------------
disposing()438     void SAL_CALL OGeometryControlModel_Base::disposing()
439     {
440         OGCM_Base::disposing();
441         OPropertySetAggregationHelper::disposing();
442 
443         Reference<XComponent>  xComp;
444         if ( query_aggregation( m_xAggregate, xComp ) )
445             xComp->dispose();
446     }
447 
448     //====================================================================
449     //= OCommonGeometryControlModel
450     //====================================================================
451     //--------------------------------------------------------------------
452 
453     typedef ::std::hash_map< ::rtl::OUString, sal_Int32, ::comphelper::UStringHash > HashMapString2Int;
454     typedef ::std::vector< ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property > >   PropSeqArray;
455     typedef ::std::vector< ::std::vector< sal_Int32 > > IntArrayArray;
456 
457     // for creating class-unique PropertySetInfo's, we need some info:
458     namespace { struct ServiceSpecifierMap : public rtl::Static< HashMapString2Int, ServiceSpecifierMap > {}; }
459     // this one maps from a String, which is the service specifier for our
460     // aggregate, to a unique id
461 
462     namespace { struct AggregateProperties : public rtl::Static< PropSeqArray, AggregateProperties > {}; }
463     // this one contains the properties which belong to all the unique ids
464     // in ServiceSpecifierMap
465 
466     namespace { struct AmbiguousPropertyIds : public rtl::Static< IntArrayArray, AmbiguousPropertyIds > {}; }
467     // the ids of the properties which we as well as our aggregate supply
468     // For such props, we let our base class handle them, and whenever such
469     // a prop is set, we forward this to our aggregate.
470 
471     // With this, we can ensure that two instances of this class share the
472     // same PropertySetInfo if and only if both aggregates have the same
473     // service specifier.
474 
475 
476     //--------------------------------------------------------------------
OCommonGeometryControlModel(Reference<XCloneable> & _rxAgg,const::rtl::OUString & _rServiceSpecifier)477     OCommonGeometryControlModel::OCommonGeometryControlModel( Reference< XCloneable >& _rxAgg, const ::rtl::OUString& _rServiceSpecifier )
478         :OGeometryControlModel_Base( _rxAgg )
479         ,m_sServiceSpecifier( _rServiceSpecifier )
480         ,m_nPropertyMapId( 0 )
481     {
482         Reference< XPropertySetInfo > xPI;
483         if ( m_xAggregateSet.is() )
484             xPI = m_xAggregateSet->getPropertySetInfo();
485         if ( !xPI.is() )
486         {
487             releaseAggregation();
488             throw IllegalArgumentException();
489         }
490 
491             HashMapString2Int &rMap = ServiceSpecifierMap::get();
492         HashMapString2Int::iterator aPropMapIdPos = rMap.find( m_sServiceSpecifier );
493         if ( rMap.end() == aPropMapIdPos )
494         {
495             PropSeqArray &rAggProperties = AggregateProperties::get();
496             m_nPropertyMapId = rAggProperties.size();
497             rAggProperties.push_back( xPI->getProperties() );
498             AmbiguousPropertyIds::get().push_back( IntArrayArray::value_type() );
499 
500             rMap[ m_sServiceSpecifier ] = m_nPropertyMapId;
501         }
502         else
503             m_nPropertyMapId = aPropMapIdPos->second;
504     }
505 
506     //--------------------------------------------------------------------
507     struct PropertyNameLess : public ::std::binary_function< Property, Property, bool >
508     {
operator ()PropertyNameLess509         bool operator()( const Property& _rLHS, const Property& _rRHS )
510         {
511             return _rLHS.Name < _rRHS.Name ? true : false;
512         }
513     };
514 
515     //--------------------------------------------------------------------
516     struct PropertyNameEqual : public ::std::unary_function< Property, bool >
517     {
518         const ::rtl::OUString&  m_rCompare;
PropertyNameEqualPropertyNameEqual519         PropertyNameEqual( const ::rtl::OUString& _rCompare ) : m_rCompare( _rCompare ) { }
520 
operator ()PropertyNameEqual521         bool operator()( const Property& _rLHS )
522         {
523             return _rLHS.Name == m_rCompare ? true : false;
524         }
525     };
526 
527     //--------------------------------------------------------------------
createArrayHelper(sal_Int32 _nId) const528     ::cppu::IPropertyArrayHelper* OCommonGeometryControlModel::createArrayHelper( sal_Int32 _nId ) const
529     {
530         OSL_ENSURE( _nId == m_nPropertyMapId, "OCommonGeometryControlModel::createArrayHelper: invalid argument!" );
531         OSL_ENSURE( _nId < (sal_Int32)AggregateProperties::get().size(), "OCommonGeometryControlModel::createArrayHelper: invalid status info (1)!" );
532         OSL_ENSURE( _nId < (sal_Int32)AmbiguousPropertyIds::get().size(), "OCommonGeometryControlModel::createArrayHelper: invalid status info (2)!" );
533 
534         // our own properties
535         Sequence< Property > aProps;
536         OPropertyContainer::describeProperties( aProps );
537 
538         // the aggregate properties
539         Sequence< Property > aAggregateProps;
540         aAggregateProps = AggregateProperties::get()[ _nId ];
541 
542         // look for duplicates, and remember them
543         IntArrayArray::value_type& rDuplicateIds = AmbiguousPropertyIds::get()[ _nId ];
544         // for this, sort the aggregate properties
545         ::std::sort(
546             aAggregateProps.getArray(),
547             aAggregateProps.getArray() + aAggregateProps.getLength(),
548             PropertyNameLess()
549         );
550         const Property* pAggProps = aAggregateProps.getConstArray();
551         const Property* pAggPropsEnd = aAggregateProps.getConstArray() + aAggregateProps.getLength();
552 
553         // now loop through our own props
554         const Property* pProp = aProps.getConstArray();
555         const Property* pPropEnd = aProps.getConstArray() + aProps.getLength();
556         while ( pProp < pPropEnd )
557         {
558             // look for the current property in the properties of our aggregate
559             const Property* pAggPropPos = ::std::find_if( pAggProps, pAggPropsEnd, PropertyNameEqual( pProp->Name ) );
560             if ( pAggPropPos != pAggPropsEnd )
561             {   // found a duplicate
562                 // -> remove from the aggregate property sequence
563                 ::comphelper::removeElementAt( aAggregateProps, pAggPropPos - pAggProps );
564                 // which means we have to adjust the pointers
565                 pAggProps = aAggregateProps.getConstArray(),
566                 pAggPropsEnd = aAggregateProps.getConstArray() + aAggregateProps.getLength(),
567 
568                 // and additionally, remember the id of this property
569                 rDuplicateIds.push_back( pProp->Handle );
570             }
571 
572             ++pProp;
573         }
574 
575         // now, finally, sort the duplicates
576         ::std::sort( rDuplicateIds.begin(), rDuplicateIds.end(), ::std::less< sal_Int32 >() );
577 
578         return new OPropertyArrayAggregationHelper(aProps, aAggregateProps);
579     }
580 
581     //--------------------------------------------------------------------
getInfoHelper()582     ::cppu::IPropertyArrayHelper& SAL_CALL OCommonGeometryControlModel::getInfoHelper()
583     {
584         return *getArrayHelper( m_nPropertyMapId );
585     }
586 
587     //--------------------------------------------------------------------
createClone_Impl(Reference<XCloneable> & _rxAggregateInstance)588     OGeometryControlModel_Base* OCommonGeometryControlModel::createClone_Impl( Reference< XCloneable >& _rxAggregateInstance )
589     {
590         return new OCommonGeometryControlModel( _rxAggregateInstance, m_sServiceSpecifier );
591     }
592 
593     //--------------------------------------------------------------------
getImplementationId()594     Sequence< sal_Int8 > SAL_CALL OCommonGeometryControlModel::getImplementationId(  ) throw (RuntimeException)
595     {
596         static ::cppu::OImplementationId * pId = NULL;
597         if ( !pId )
598         {
599             ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
600             if ( !pId )
601             {
602                 static ::cppu::OImplementationId s_aId;
603                 pId = &s_aId;
604             }
605         }
606         return pId->getImplementationId();
607     }
608 
609     //--------------------------------------------------------------------
610     struct Int32Equal : public ::std::unary_function< sal_Int32, bool >
611     {
612         sal_Int32   m_nCompare;
Int32EqualInt32Equal613         Int32Equal( sal_Int32 _nCompare ) : m_nCompare( _nCompare ) { }
614 
operator ()Int32Equal615         bool operator()( sal_Int32 _nLHS )
616         {
617             return _nLHS == m_nCompare ? true  : false;
618         }
619     };
620 
621     //--------------------------------------------------------------------
setFastPropertyValue_NoBroadcast(sal_Int32 _nHandle,const Any & _rValue)622     void SAL_CALL OCommonGeometryControlModel::setFastPropertyValue_NoBroadcast( sal_Int32 _nHandle, const Any& _rValue ) throw ( Exception )
623     {
624         OGeometryControlModel_Base::setFastPropertyValue_NoBroadcast( _nHandle, _rValue );
625 
626         // look if this id is one we recognized as duplicate
627         IntArrayArray::value_type& rDuplicateIds = AmbiguousPropertyIds::get()[ m_nPropertyMapId ];
628 
629         IntArrayArray::value_type::const_iterator aPos = ::std::find_if(
630             rDuplicateIds.begin(),
631             rDuplicateIds.end(),
632             Int32Equal( _nHandle )
633         );
634 
635         if ( rDuplicateIds.end() != aPos )
636         {
637             // yes, it is such a property
638             ::rtl::OUString sPropName;
639             sal_Int16 nAttributes(0);
640             static_cast< OPropertyArrayAggregationHelper* >( getArrayHelper( m_nPropertyMapId ) )->fillPropertyMembersByHandle( &sPropName, &nAttributes, _nHandle );
641 
642             if ( m_xAggregateSet.is() && sPropName.getLength() )
643                 m_xAggregateSet->setPropertyValue( sPropName, _rValue );
644         }
645     }
646 
647 //........................................................................
648 // }    // namespace toolkit
649 //........................................................................
650