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