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