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