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