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