Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <com/sun/star/beans/XPropertySet.hpp>
21 : #include <svl/eitem.hxx>
22 :
23 : #include <boost/unordered_map.hpp>
24 : #include <svl/itemprop.hxx>
25 :
26 : #include <editeng/unoipset.hxx>
27 : #include <editeng/editids.hrc>
28 : #include <editeng/editeng.hxx>
29 : #include <svl/itempool.hxx>
30 : #include <algorithm>
31 :
32 : using namespace ::com::sun::star;
33 : using namespace ::rtl;
34 :
35 : using ::std::vector;
36 :
37 : //----------------------------------------------------------------------
38 :
39 : struct SfxItemPropertyMapEntryHash
40 : {
41 : size_t operator()(const SfxItemPropertyMapEntry* pMap) const { return (size_t)pMap; }
42 : };
43 :
44 : //----------------------------------------------------------------------
45 :
46 76 : struct SvxIDPropertyCombine
47 : {
48 : sal_uInt16 nWID;
49 : uno::Any aAny;
50 : };
51 :
52 :
53 80 : SvxItemPropertySet::SvxItemPropertySet( const SfxItemPropertyMapEntry* pMap, SfxItemPool& rItemPool, sal_Bool bConvertTwips )
54 : : m_aPropertyMap( pMap ),
55 80 : _pMap(pMap), mbConvertTwips(bConvertTwips), mrItemPool( rItemPool )
56 : {
57 80 : }
58 :
59 : //----------------------------------------------------------------------
60 160 : SvxItemPropertySet::~SvxItemPropertySet()
61 : {
62 80 : ClearAllUsrAny();
63 80 : }
64 :
65 : //----------------------------------------------------------------------
66 2176 : uno::Any* SvxItemPropertySet::GetUsrAnyForID(sal_uInt16 nWID) const
67 : {
68 8188 : for ( size_t i = 0, n = aCombineList.size(); i < n; ++i )
69 : {
70 6055 : SvxIDPropertyCombine* pActual = aCombineList[ i ];
71 6055 : if( pActual->nWID == nWID )
72 43 : return &pActual->aAny;
73 : }
74 2133 : return NULL;
75 : }
76 :
77 : //----------------------------------------------------------------------
78 38 : void SvxItemPropertySet::AddUsrAnyForID(const uno::Any& rAny, sal_uInt16 nWID)
79 : {
80 38 : SvxIDPropertyCombine* pNew = new SvxIDPropertyCombine;
81 38 : pNew->nWID = nWID;
82 38 : pNew->aAny = rAny;
83 38 : aCombineList.push_back( pNew );
84 38 : }
85 :
86 : //----------------------------------------------------------------------
87 :
88 93 : void SvxItemPropertySet::ClearAllUsrAny()
89 : {
90 131 : for ( size_t i = 0, n = aCombineList.size(); i < n; ++i )
91 38 : delete aCombineList[ i ];
92 93 : aCombineList.clear();
93 93 : }
94 :
95 : //----------------------------------------------------------------------
96 :
97 0 : sal_Bool SvxUnoCheckForPositiveValue( const uno::Any& rVal )
98 : {
99 0 : sal_Bool bConvert = sal_True; // the default is that all metric items must be converted
100 0 : sal_Int32 nValue = 0;
101 0 : if( rVal >>= nValue )
102 0 : bConvert = (nValue > 0);
103 0 : return bConvert;
104 : }
105 :
106 :
107 : //----------------------------------------------------------------------
108 4803 : uno::Any SvxItemPropertySet::getPropertyValue( const SfxItemPropertySimpleEntry* pMap, const SfxItemSet& rSet, bool bSearchInParent, bool bDontConvertNegativeValues ) const
109 : {
110 4803 : uno::Any aVal;
111 4803 : if(!pMap || !pMap->nWID)
112 : return aVal;
113 :
114 4803 : const SfxPoolItem* pItem = 0;
115 4803 : SfxItemPool* pPool = rSet.GetPool();
116 4803 : rSet.GetItemState( pMap->nWID, bSearchInParent, &pItem );
117 4803 : if( NULL == pItem && pPool )
118 0 : pItem = &(pPool->GetDefaultItem( pMap->nWID ));
119 :
120 4803 : const SfxMapUnit eMapUnit = pPool ? pPool->GetMetric((sal_uInt16)pMap->nWID) : SFX_MAPUNIT_100TH_MM;
121 4803 : sal_uInt8 nMemberId = pMap->nMemberId & (~SFX_METRIC_ITEM);
122 4803 : if( eMapUnit == SFX_MAPUNIT_100TH_MM )
123 4736 : nMemberId &= (~CONVERT_TWIPS);
124 :
125 4803 : if(pItem)
126 : {
127 4803 : pItem->QueryValue( aVal, nMemberId );
128 4803 : if( pMap->nMemberId & SFX_METRIC_ITEM )
129 : {
130 1025 : if( eMapUnit != SFX_MAPUNIT_100TH_MM )
131 : {
132 13 : if ( !bDontConvertNegativeValues || SvxUnoCheckForPositiveValue( aVal ) )
133 13 : SvxUnoConvertToMM( eMapUnit, aVal );
134 : }
135 : }
136 4530 : else if ( pMap->pType->getTypeClass() == uno::TypeClass_ENUM &&
137 752 : aVal.getValueType() == ::getCppuType((const sal_Int32*)0) )
138 : {
139 : // convert typeless SfxEnumItem to enum type
140 : sal_Int32 nEnum;
141 72 : aVal >>= nEnum;
142 72 : aVal.setValue( &nEnum, *pMap->pType );
143 : }
144 : }
145 : else
146 : {
147 : OSL_FAIL( "No SfxPoolItem found for property!" );
148 : }
149 :
150 0 : return aVal;
151 : }
152 :
153 : //----------------------------------------------------------------------
154 66115 : void SvxItemPropertySet::setPropertyValue( const SfxItemPropertySimpleEntry* pMap, const uno::Any& rVal, SfxItemSet& rSet, bool bDontConvertNegativeValues ) const
155 : {
156 66115 : if(!pMap || !pMap->nWID)
157 : return;
158 :
159 : // Get item
160 66115 : const SfxPoolItem* pItem = 0;
161 66115 : SfxItemState eState = rSet.GetItemState( pMap->nWID, sal_True, &pItem );
162 66115 : SfxItemPool* pPool = rSet.GetPool();
163 :
164 : // Put UnoAny in the item value
165 66115 : if(eState < SFX_ITEM_DEFAULT || pItem == NULL)
166 : {
167 2 : if( pPool == NULL )
168 : {
169 : OSL_FAIL( "No default item and no pool?" );
170 : return;
171 : }
172 :
173 2 : pItem = &pPool->GetDefaultItem( pMap->nWID );
174 : }
175 :
176 : DBG_ASSERT( pItem, "Got no default for item!" );
177 66115 : if( pItem )
178 : {
179 66115 : uno::Any aValue( rVal );
180 :
181 66115 : const SfxMapUnit eMapUnit = pPool ? pPool->GetMetric((sal_uInt16)pMap->nWID) : SFX_MAPUNIT_100TH_MM;
182 :
183 : // check for needed metric translation
184 66115 : if( (pMap->nMemberId & SFX_METRIC_ITEM) && eMapUnit != SFX_MAPUNIT_100TH_MM )
185 : {
186 126 : if ( !bDontConvertNegativeValues || SvxUnoCheckForPositiveValue( aValue ) )
187 126 : SvxUnoConvertFromMM( eMapUnit, aValue );
188 : }
189 :
190 66115 : SfxPoolItem *pNewItem = pItem->Clone();
191 :
192 66115 : sal_uInt8 nMemberId = pMap->nMemberId & (~SFX_METRIC_ITEM);
193 66115 : if( eMapUnit == SFX_MAPUNIT_100TH_MM )
194 64925 : nMemberId &= (~CONVERT_TWIPS);
195 :
196 66115 : if( pNewItem->PutValue( aValue, nMemberId ) )
197 : {
198 : // Set new item in item set
199 66114 : rSet.Put( *pNewItem, pMap->nWID );
200 : }
201 66115 : delete pNewItem;
202 : }
203 : }
204 :
205 : //----------------------------------------------------------------------
206 0 : uno::Any SvxItemPropertySet::getPropertyValue( const SfxItemPropertySimpleEntry* pMap ) const
207 : {
208 : // Already entered a value? Then finish quickly
209 0 : uno::Any* pUsrAny = GetUsrAnyForID(pMap->nWID);
210 0 : if(pUsrAny)
211 0 : return *pUsrAny;
212 :
213 : // No UsrAny detected yet, generate Default entry and return this
214 0 : const SfxMapUnit eMapUnit = mrItemPool.GetMetric((sal_uInt16)pMap->nWID);
215 0 : sal_uInt8 nMemberId = pMap->nMemberId & (~SFX_METRIC_ITEM);
216 0 : if( eMapUnit == SFX_MAPUNIT_100TH_MM )
217 0 : nMemberId &= (~CONVERT_TWIPS);
218 0 : uno::Any aVal;
219 0 : SfxItemSet aSet( mrItemPool, pMap->nWID, pMap->nWID);
220 :
221 0 : if( (pMap->nWID < OWN_ATTR_VALUE_START) && (pMap->nWID > OWN_ATTR_VALUE_END ) )
222 : {
223 : // Get Default from ItemPool
224 0 : if(mrItemPool.IsWhich(pMap->nWID))
225 0 : aSet.Put(mrItemPool.GetDefaultItem(pMap->nWID));
226 : }
227 :
228 0 : if(aSet.Count())
229 : {
230 0 : const SfxPoolItem* pItem = NULL;
231 0 : SfxItemState eState = aSet.GetItemState( pMap->nWID, sal_True, &pItem );
232 0 : if(eState >= SFX_ITEM_DEFAULT && pItem)
233 : {
234 0 : pItem->QueryValue( aVal, nMemberId );
235 0 : ((SvxItemPropertySet*)this)->AddUsrAnyForID(aVal, pMap->nWID);
236 : }
237 : }
238 :
239 0 : if( pMap->nMemberId & SFX_METRIC_ITEM )
240 : {
241 : // check for needed metric translation
242 0 : if(pMap->nMemberId & SFX_METRIC_ITEM && eMapUnit != SFX_MAPUNIT_100TH_MM)
243 : {
244 0 : SvxUnoConvertToMM( eMapUnit, aVal );
245 : }
246 : }
247 :
248 0 : if ( pMap->pType->getTypeClass() == uno::TypeClass_ENUM &&
249 0 : aVal.getValueType() == ::getCppuType((const sal_Int32*)0) )
250 : {
251 : sal_Int32 nEnum;
252 0 : aVal >>= nEnum;
253 :
254 0 : aVal.setValue( &nEnum, *pMap->pType );
255 : }
256 :
257 0 : return aVal;
258 : }
259 :
260 : //----------------------------------------------------------------------
261 :
262 44 : void SvxItemPropertySet::setPropertyValue( const SfxItemPropertySimpleEntry* pMap, const uno::Any& rVal ) const
263 : {
264 44 : uno::Any* pUsrAny = GetUsrAnyForID(pMap->nWID);
265 44 : if(!pUsrAny)
266 38 : ((SvxItemPropertySet*)this)->AddUsrAnyForID(rVal, pMap->nWID);
267 : else
268 6 : *pUsrAny = rVal;
269 44 : }
270 :
271 : //----------------------------------------------------------------------
272 :
273 102304 : const SfxItemPropertySimpleEntry* SvxItemPropertySet::getPropertyMapEntry(const OUString &rName) const
274 : {
275 102304 : return m_aPropertyMap.getByName( rName );
276 : }
277 :
278 : //----------------------------------------------------------------------
279 :
280 1181 : uno::Reference< beans::XPropertySetInfo > SvxItemPropertySet::getPropertySetInfo() const
281 : {
282 1181 : if( !m_xInfo.is() )
283 50 : m_xInfo = new SfxItemPropertySetInfo( m_aPropertyMap );
284 1181 : return m_xInfo;
285 : }
286 :
287 : //----------------------------------------------------------------------
288 :
289 : #ifndef TWIPS_TO_MM
290 : #define TWIPS_TO_MM(val) ((val * 127 + 36) / 72)
291 : #endif
292 : #ifndef MM_TO_TWIPS
293 : #define MM_TO_TWIPS(val) ((val * 72 + 63) / 127)
294 : #endif
295 :
296 : /** converts the given any with a metric to 100th/mm if needed */
297 17 : void SvxUnoConvertToMM( const SfxMapUnit eSourceMapUnit, uno::Any & rMetric ) throw()
298 : {
299 : // map the metric of the itempool to 100th mm
300 17 : switch(eSourceMapUnit)
301 : {
302 : case SFX_MAPUNIT_TWIP :
303 : {
304 17 : switch( rMetric.getValueTypeClass() )
305 : {
306 : case uno::TypeClass_BYTE:
307 0 : rMetric <<= (sal_Int8)(TWIPS_TO_MM(*(sal_Int8*)rMetric.getValue()));
308 0 : break;
309 : case uno::TypeClass_SHORT:
310 0 : rMetric <<= (sal_Int16)(TWIPS_TO_MM(*(sal_Int16*)rMetric.getValue()));
311 0 : break;
312 : case uno::TypeClass_UNSIGNED_SHORT:
313 0 : rMetric <<= (sal_uInt16)(TWIPS_TO_MM(*(sal_uInt16*)rMetric.getValue()));
314 0 : break;
315 : case uno::TypeClass_LONG:
316 17 : rMetric <<= (sal_Int32)(TWIPS_TO_MM(*(sal_Int32*)rMetric.getValue()));
317 17 : break;
318 : case uno::TypeClass_UNSIGNED_LONG:
319 0 : rMetric <<= (sal_uInt32)(TWIPS_TO_MM(*(sal_uInt32*)rMetric.getValue()));
320 0 : break;
321 : default:
322 : OSL_FAIL("AW: Missing unit translation to 100th mm!");
323 : }
324 17 : break;
325 : }
326 : default:
327 : {
328 : OSL_FAIL("AW: Missing unit translation to 100th mm!");
329 : }
330 : }
331 17 : }
332 :
333 : //----------------------------------------------------------------------
334 :
335 : /** converts the given any with a metric from 100th/mm to the given metric if needed */
336 160 : void SvxUnoConvertFromMM( const SfxMapUnit eDestinationMapUnit, uno::Any & rMetric ) throw()
337 : {
338 160 : switch(eDestinationMapUnit)
339 : {
340 : case SFX_MAPUNIT_TWIP :
341 : {
342 160 : switch( rMetric.getValueTypeClass() )
343 : {
344 : case uno::TypeClass_BYTE:
345 0 : rMetric <<= (sal_Int8)(MM_TO_TWIPS(*(sal_Int8*)rMetric.getValue()));
346 0 : break;
347 : case uno::TypeClass_SHORT:
348 0 : rMetric <<= (sal_Int16)(MM_TO_TWIPS(*(sal_Int16*)rMetric.getValue()));
349 0 : break;
350 : case uno::TypeClass_UNSIGNED_SHORT:
351 0 : rMetric <<= (sal_uInt16)(MM_TO_TWIPS(*(sal_uInt16*)rMetric.getValue()));
352 0 : break;
353 : case uno::TypeClass_LONG:
354 160 : rMetric <<= (sal_Int32)(MM_TO_TWIPS(*(sal_Int32*)rMetric.getValue()));
355 160 : break;
356 : case uno::TypeClass_UNSIGNED_LONG:
357 0 : rMetric <<= (sal_uInt32)(MM_TO_TWIPS(*(sal_uInt32*)rMetric.getValue()));
358 0 : break;
359 : default:
360 : OSL_FAIL("AW: Missing unit translation to 100th mm!");
361 : }
362 160 : break;
363 : }
364 : default:
365 : {
366 : OSL_FAIL("AW: Missing unit translation to PoolMetrics!");
367 : }
368 : }
369 160 : }
370 :
371 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|