xref: /trunk/main/editeng/source/uno/unoipset.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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