xref: /aoo42x/main/editeng/source/uno/unoipset.cxx (revision 190118d0)
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_editeng.hxx"
26 #include <com/sun/star/beans/XPropertySet.hpp>
27 #include <svl/eitem.hxx>
28 #include <tools/list.hxx>
29 
30 #include <hash_map>
31 #include <vector>
32 #include <svl/itemprop.hxx>
33 
34 #include <editeng/unoipset.hxx>
35 #include <editeng/editids.hrc>
36 #include <editeng/editeng.hxx>
37 #include <svl/itempool.hxx>
38 #include <algorithm>
39 
40 using namespace ::com::sun::star;
41 using namespace ::rtl;
42 
43 //----------------------------------------------------------------------
44 
45 struct SfxItemPropertyMapEntryHash
46 {
47     size_t operator()(const SfxItemPropertyMapEntry* pMap) const { return (size_t)pMap; }
48 };
49 
50 //----------------------------------------------------------------------
51 
52 struct SvxIDPropertyCombine
53 {
54 	sal_uInt16	nWID;
55 	uno::Any	aAny;
56 };
57 
58 DECLARE_LIST( SvxIDPropertyCombineList, SvxIDPropertyCombine * )
59 
60 SvxItemPropertySet::SvxItemPropertySet( const SfxItemPropertyMapEntry* pMap, SfxItemPool& rItemPool, sal_Bool bConvertTwips )
61 :   m_aPropertyMap( pMap ),
62     _pMap(pMap), mbConvertTwips(bConvertTwips), mrItemPool( rItemPool )
63 {
64 	pCombiList = NULL;
65 }
66 
67 //----------------------------------------------------------------------
68 SvxItemPropertySet::~SvxItemPropertySet()
69 {
70 	ClearAllUsrAny();
71 }
72 
73 //----------------------------------------------------------------------
74 uno::Any* SvxItemPropertySet::GetUsrAnyForID(sal_uInt16 nWID) const
75 {
76 	if(pCombiList && pCombiList->Count())
77 	{
78 		SvxIDPropertyCombine* pActual = pCombiList->First();
79 		while(pActual)
80 		{
81 			if(pActual->nWID == nWID)
82 				return &pActual->aAny;
83 			pActual = pCombiList->Next();
84 
85 		}
86 	}
87 	return NULL;
88 }
89 
90 //----------------------------------------------------------------------
91 void SvxItemPropertySet::AddUsrAnyForID(const uno::Any& rAny, sal_uInt16 nWID)
92 {
93 	if(!pCombiList)
94 		pCombiList = new SvxIDPropertyCombineList();
95 
96 	SvxIDPropertyCombine* pNew = new SvxIDPropertyCombine;
97 	pNew->nWID = nWID;
98 	pNew->aAny = rAny;
99 	pCombiList->Insert(pNew);
100 }
101 
102 //----------------------------------------------------------------------
103 
104 void SvxItemPropertySet::ClearAllUsrAny()
105 {
106 	if(pCombiList)
107 		delete pCombiList;
108 	pCombiList = NULL;
109 }
110 
111 //----------------------------------------------------------------------
112 
113 sal_Bool SvxUnoCheckForPositiveValue( const uno::Any& rVal )
114 {
115 	sal_Bool bConvert = sal_True; // the default is that all metric items must be converted
116 	sal_Int32 nValue = 0;
117 	if( rVal >>= nValue )
118 		bConvert = (nValue > 0);
119 	return bConvert;
120 }
121 
122 
123 //----------------------------------------------------------------------
124 uno::Any SvxItemPropertySet::getPropertyValue( const SfxItemPropertySimpleEntry* pMap, const SfxItemSet& rSet, bool bSearchInParent, bool bDontConvertNegativeValues ) const
125 {
126 	uno::Any aVal;
127 	if(!pMap || !pMap->nWID)
128 		return aVal;
129 
130 	const SfxPoolItem* pItem = 0;
131 	SfxItemPool* pPool = rSet.GetPool();
132 	rSet.GetItemState( pMap->nWID, bSearchInParent, &pItem );
133 	if( NULL == pItem && pPool )
134 		pItem = &(pPool->GetDefaultItem( pMap->nWID ));
135 
136 	const SfxMapUnit eMapUnit = pPool ? pPool->GetMetric((sal_uInt16)pMap->nWID) : SFX_MAPUNIT_100TH_MM;
137 	sal_uInt8 nMemberId = pMap->nMemberId & (~SFX_METRIC_ITEM);
138 	if( eMapUnit == SFX_MAPUNIT_100TH_MM )
139 		nMemberId &= (~CONVERT_TWIPS);
140 
141 	if(pItem)
142 	{
143 		pItem->QueryValue( aVal, nMemberId );
144 		if( pMap->nMemberId & SFX_METRIC_ITEM )
145 		{
146 			if( eMapUnit != SFX_MAPUNIT_100TH_MM )
147 			{
148 		        if ( !bDontConvertNegativeValues || SvxUnoCheckForPositiveValue( aVal ) )
149 					SvxUnoConvertToMM( eMapUnit, aVal );
150 			}
151 		}
152 		else if ( pMap->pType->getTypeClass() == uno::TypeClass_ENUM &&
153 			  aVal.getValueType() == ::getCppuType((const sal_Int32*)0) )
154 		{
155     		// convert typeless SfxEnumItem to enum type
156 			sal_Int32 nEnum;
157 			aVal >>= nEnum;
158 			aVal.setValue( &nEnum, *pMap->pType );
159 		}
160 	}
161 	else
162 	{
163 		DBG_ERROR( "No SfxPoolItem found for property!" );
164 	}
165 
166 	return aVal;
167 }
168 
169 //----------------------------------------------------------------------
170 void SvxItemPropertySet::setPropertyValue( const SfxItemPropertySimpleEntry* pMap, const uno::Any& rVal, SfxItemSet& rSet, bool bDontConvertNegativeValues ) const
171 {
172 	if(!pMap || !pMap->nWID)
173 		return;
174 
175 	// item holen
176 	const SfxPoolItem* pItem = 0;
177 	SfxPoolItem *pNewItem = 0;
178 	SfxItemState eState = rSet.GetItemState( pMap->nWID, sal_True, &pItem );
179 	SfxItemPool* pPool = rSet.GetPool();
180 
181 	// UnoAny in item-Wert stecken
182 	if(eState < SFX_ITEM_DEFAULT || pItem == NULL)
183 	{
184 		if( pPool == NULL )
185 		{
186 			DBG_ERROR( "No default item and no pool?" );
187 			return;
188 		}
189 
190 		pItem = &pPool->GetDefaultItem( pMap->nWID );
191 	}
192 
193 	DBG_ASSERT( pItem, "Got no default for item!" );
194 	if( pItem )
195 	{
196 		uno::Any aValue( rVal );
197 
198 		const SfxMapUnit eMapUnit = pPool ? pPool->GetMetric((sal_uInt16)pMap->nWID) : SFX_MAPUNIT_100TH_MM;
199 
200 		// check for needed metric translation
201 		if( (pMap->nMemberId & SFX_METRIC_ITEM) && eMapUnit != SFX_MAPUNIT_100TH_MM )
202 		{
203 		    if ( !bDontConvertNegativeValues || SvxUnoCheckForPositiveValue( aValue ) )
204 			    SvxUnoConvertFromMM( eMapUnit, aValue );
205 	    }
206 
207 		pNewItem = pItem->Clone();
208 
209 		sal_uInt8 nMemberId = pMap->nMemberId & (~SFX_METRIC_ITEM);
210 		if( eMapUnit == SFX_MAPUNIT_100TH_MM )
211 			nMemberId &= (~CONVERT_TWIPS);
212 
213 		if( pNewItem->PutValue( aValue, nMemberId ) )
214 		{
215 			// neues item in itemset setzen
216 			rSet.Put( *pNewItem, pMap->nWID );
217 		}
218 		delete pNewItem;
219 	}
220 }
221 
222 //----------------------------------------------------------------------
223 uno::Any SvxItemPropertySet::getPropertyValue( const SfxItemPropertySimpleEntry* pMap ) const
224 {
225 	// Schon ein Wert eingetragen? Dann schnell fertig
226 	uno::Any* pUsrAny = GetUsrAnyForID(pMap->nWID);
227 	if(pUsrAny)
228 		return *pUsrAny;
229 
230 	// Noch kein UsrAny gemerkt, generiere Default-Eintrag und gib
231 	// diesen zurueck
232 
233 	const SfxMapUnit eMapUnit = mrItemPool.GetMetric((sal_uInt16)pMap->nWID);
234 	sal_uInt8 nMemberId = pMap->nMemberId & (~SFX_METRIC_ITEM);
235 	if( eMapUnit == SFX_MAPUNIT_100TH_MM )
236 		nMemberId &= (~CONVERT_TWIPS);
237 
238 	uno::Any aVal;
239 	SfxItemSet aSet( mrItemPool, pMap->nWID, pMap->nWID);
240 
241 	if( (pMap->nWID < OWN_ATTR_VALUE_START) && (pMap->nWID > OWN_ATTR_VALUE_END ) )
242 	{
243 		// Default aus ItemPool holen
244 		if(mrItemPool.IsWhich(pMap->nWID))
245 			aSet.Put(mrItemPool.GetDefaultItem(pMap->nWID));
246 	}
247 
248 	if(aSet.Count())
249 	{
250 		const SfxPoolItem* pItem = NULL;
251 		SfxItemState eState = aSet.GetItemState( pMap->nWID, sal_True, &pItem );
252 		if(eState >= SFX_ITEM_DEFAULT && pItem)
253 		{
254 			pItem->QueryValue( aVal, nMemberId );
255 			((SvxItemPropertySet*)this)->AddUsrAnyForID(aVal, pMap->nWID);
256 		}
257 	}
258 
259 	if( pMap->nMemberId & SFX_METRIC_ITEM )
260 	{
261 		// check for needed metric translation
262 		if(pMap->nMemberId & SFX_METRIC_ITEM && eMapUnit != SFX_MAPUNIT_100TH_MM)
263 		{
264 			SvxUnoConvertToMM( eMapUnit, aVal );
265 		}
266 	}
267 
268 	if ( pMap->pType->getTypeClass() == uno::TypeClass_ENUM &&
269 		  aVal.getValueType() == ::getCppuType((const sal_Int32*)0) )
270 	{
271 		sal_Int32 nEnum;
272 		aVal >>= nEnum;
273 
274 		aVal.setValue( &nEnum, *pMap->pType );
275 	}
276 
277 	return aVal;
278 }
279 
280 //----------------------------------------------------------------------
281 
282 void SvxItemPropertySet::setPropertyValue( const SfxItemPropertySimpleEntry* pMap, const uno::Any& rVal ) const
283 {
284 	uno::Any* pUsrAny = GetUsrAnyForID(pMap->nWID);
285 	if(!pUsrAny)
286 		((SvxItemPropertySet*)this)->AddUsrAnyForID(rVal, pMap->nWID);
287 	else
288 		*pUsrAny = rVal;
289 }
290 
291 //----------------------------------------------------------------------
292 
293 const SfxItemPropertySimpleEntry* SvxItemPropertySet::getPropertyMapEntry(const OUString &rName) const
294 {
295     return m_aPropertyMap.getByName( rName );
296  }
297 
298 //----------------------------------------------------------------------
299 
300 uno::Reference< beans::XPropertySetInfo >  SvxItemPropertySet::getPropertySetInfo() const
301 {
302     if( !m_xInfo.is() )
303         m_xInfo = new SfxItemPropertySetInfo( &m_aPropertyMap );
304     return m_xInfo;
305 }
306 
307 //----------------------------------------------------------------------
308 
309 #ifndef TWIPS_TO_MM
310 #define	TWIPS_TO_MM(val) ((val * 127 + 36) / 72)
311 #endif
312 #ifndef MM_TO_TWIPS
313 #define	MM_TO_TWIPS(val) ((val * 72 + 63) / 127)
314 #endif
315 
316 /** converts the given any with a metric to 100th/mm if needed */
317 void SvxUnoConvertToMM( const SfxMapUnit eSourceMapUnit, uno::Any & rMetric ) throw()
318 {
319 	// map the metric of the itempool to 100th mm
320 	switch(eSourceMapUnit)
321 	{
322 		case SFX_MAPUNIT_TWIP :
323 		{
324 			switch( rMetric.getValueTypeClass() )
325 			{
326 			case uno::TypeClass_BYTE:
327 				rMetric <<= (sal_Int8)(TWIPS_TO_MM(*(sal_Int8*)rMetric.getValue()));
328 				break;
329 			case uno::TypeClass_SHORT:
330 				rMetric <<= (sal_Int16)(TWIPS_TO_MM(*(sal_Int16*)rMetric.getValue()));
331 				break;
332 			case uno::TypeClass_UNSIGNED_SHORT:
333 				rMetric <<= (sal_uInt16)(TWIPS_TO_MM(*(sal_uInt16*)rMetric.getValue()));
334 				break;
335 			case uno::TypeClass_LONG:
336 				rMetric <<= (sal_Int32)(TWIPS_TO_MM(*(sal_Int32*)rMetric.getValue()));
337 				break;
338 			case uno::TypeClass_UNSIGNED_LONG:
339 				rMetric <<= (sal_uInt32)(TWIPS_TO_MM(*(sal_uInt32*)rMetric.getValue()));
340 				break;
341 			default:
342 				DBG_ERROR("AW: Missing unit translation to 100th mm!");
343 			}
344 			break;
345 		}
346 		default:
347 		{
348 			DBG_ERROR("AW: Missing unit translation to 100th mm!");
349 		}
350 	}
351 }
352 
353 //----------------------------------------------------------------------
354 
355 /** converts the given any with a metric from 100th/mm to the given metric if needed */
356 void SvxUnoConvertFromMM( const SfxMapUnit eDestinationMapUnit, uno::Any & rMetric ) throw()
357 {
358 	switch(eDestinationMapUnit)
359 	{
360 		case SFX_MAPUNIT_TWIP :
361 		{
362 			switch( rMetric.getValueTypeClass() )
363 			{
364 				case uno::TypeClass_BYTE:
365 					rMetric <<= (sal_Int8)(MM_TO_TWIPS(*(sal_Int8*)rMetric.getValue()));
366 					break;
367 				case uno::TypeClass_SHORT:
368 					rMetric <<= (sal_Int16)(MM_TO_TWIPS(*(sal_Int16*)rMetric.getValue()));
369 					break;
370 				case uno::TypeClass_UNSIGNED_SHORT:
371 					rMetric <<= (sal_uInt16)(MM_TO_TWIPS(*(sal_uInt16*)rMetric.getValue()));
372 					break;
373 				case uno::TypeClass_LONG:
374 					rMetric <<= (sal_Int32)(MM_TO_TWIPS(*(sal_Int32*)rMetric.getValue()));
375 					break;
376 				case uno::TypeClass_UNSIGNED_LONG:
377 					rMetric <<= (sal_uInt32)(MM_TO_TWIPS(*(sal_uInt32*)rMetric.getValue()));
378 					break;
379 				default:
380 					DBG_ERROR("AW: Missing unit translation to 100th mm!");
381 			}
382 			break;
383 		}
384 		default:
385 		{
386 			DBG_ERROR("AW: Missing unit translation to PoolMetrics!");
387 		}
388 	}
389 }
390 
391