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