xref: /AOO41X/main/editeng/source/uno/unoipset.cxx (revision 8809db7a87f97847b57a57f4cd2b0104b2b83182)
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