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 0 : struct SvxIDPropertyCombine
38 : {
39 : sal_uInt16 nWID;
40 : uno::Any aAny;
41 : };
42 :
43 :
44 0 : SvxItemPropertySet::SvxItemPropertySet( const SfxItemPropertyMapEntry* pMap, SfxItemPool& rItemPool, bool bConvertTwips )
45 : : m_aPropertyMap( pMap ),
46 0 : _pMap(pMap), mbConvertTwips(bConvertTwips), mrItemPool( rItemPool )
47 : {
48 0 : }
49 :
50 :
51 0 : SvxItemPropertySet::~SvxItemPropertySet()
52 : {
53 0 : ClearAllUsrAny();
54 0 : }
55 :
56 :
57 0 : uno::Any* SvxItemPropertySet::GetUsrAnyForID(sal_uInt16 nWID) const
58 : {
59 0 : for ( size_t i = 0, n = aCombineList.size(); i < n; ++i )
60 : {
61 0 : SvxIDPropertyCombine* pActual = aCombineList[ i ];
62 0 : if( pActual->nWID == nWID )
63 0 : return &pActual->aAny;
64 : }
65 0 : return NULL;
66 : }
67 :
68 :
69 0 : void SvxItemPropertySet::AddUsrAnyForID(const uno::Any& rAny, sal_uInt16 nWID)
70 : {
71 0 : SvxIDPropertyCombine* pNew = new SvxIDPropertyCombine;
72 0 : pNew->nWID = nWID;
73 0 : pNew->aAny = rAny;
74 0 : aCombineList.push_back( pNew );
75 0 : }
76 :
77 :
78 :
79 0 : void SvxItemPropertySet::ClearAllUsrAny()
80 : {
81 0 : for ( size_t i = 0, n = aCombineList.size(); i < n; ++i )
82 0 : delete aCombineList[ i ];
83 0 : aCombineList.clear();
84 0 : }
85 :
86 :
87 :
88 0 : sal_Bool SvxUnoCheckForPositiveValue( const uno::Any& rVal )
89 : {
90 0 : sal_Bool bConvert = sal_True; // the default is that all metric items must be converted
91 0 : sal_Int32 nValue = 0;
92 0 : if( rVal >>= nValue )
93 0 : bConvert = (nValue > 0);
94 0 : return bConvert;
95 : }
96 :
97 :
98 :
99 0 : uno::Any SvxItemPropertySet::getPropertyValue( const SfxItemPropertySimpleEntry* pMap, const SfxItemSet& rSet, bool bSearchInParent, bool bDontConvertNegativeValues ) const
100 : {
101 0 : uno::Any aVal;
102 0 : if(!pMap || !pMap->nWID)
103 0 : return aVal;
104 :
105 0 : const SfxPoolItem* pItem = 0;
106 0 : SfxItemPool* pPool = rSet.GetPool();
107 0 : rSet.GetItemState( pMap->nWID, bSearchInParent, &pItem );
108 0 : if( NULL == pItem && pPool )
109 0 : pItem = &(pPool->GetDefaultItem( pMap->nWID ));
110 :
111 0 : const SfxMapUnit eMapUnit = pPool ? pPool->GetMetric((sal_uInt16)pMap->nWID) : SFX_MAPUNIT_100TH_MM;
112 0 : sal_uInt8 nMemberId = pMap->nMemberId & (~SFX_METRIC_ITEM);
113 0 : if( eMapUnit == SFX_MAPUNIT_100TH_MM )
114 0 : nMemberId &= (~CONVERT_TWIPS);
115 :
116 0 : if(pItem)
117 : {
118 0 : pItem->QueryValue( aVal, nMemberId );
119 0 : if( pMap->nMemberId & SFX_METRIC_ITEM )
120 : {
121 0 : if( eMapUnit != SFX_MAPUNIT_100TH_MM )
122 : {
123 0 : if ( !bDontConvertNegativeValues || SvxUnoCheckForPositiveValue( aVal ) )
124 0 : SvxUnoConvertToMM( eMapUnit, aVal );
125 : }
126 : }
127 0 : else if ( pMap->aType.getTypeClass() == uno::TypeClass_ENUM &&
128 0 : aVal.getValueType() == ::getCppuType((const sal_Int32*)0) )
129 : {
130 : // convert typeless SfxEnumItem to enum type
131 : sal_Int32 nEnum;
132 0 : aVal >>= nEnum;
133 0 : aVal.setValue( &nEnum, pMap->aType );
134 : }
135 : }
136 : else
137 : {
138 : OSL_FAIL( "No SfxPoolItem found for property!" );
139 : }
140 :
141 0 : return aVal;
142 : }
143 :
144 :
145 0 : void SvxItemPropertySet::setPropertyValue( const SfxItemPropertySimpleEntry* pMap, const uno::Any& rVal, SfxItemSet& rSet, bool bDontConvertNegativeValues ) const
146 : {
147 0 : if(!pMap || !pMap->nWID)
148 0 : return;
149 :
150 : // Get item
151 0 : const SfxPoolItem* pItem = 0;
152 0 : SfxItemState eState = rSet.GetItemState( pMap->nWID, true, &pItem );
153 0 : SfxItemPool* pPool = rSet.GetPool();
154 :
155 : // Put UnoAny in the item value
156 0 : if(eState < SFX_ITEM_DEFAULT || pItem == NULL)
157 : {
158 0 : if( pPool == NULL )
159 : {
160 : OSL_FAIL( "No default item and no pool?" );
161 0 : return;
162 : }
163 :
164 0 : pItem = &pPool->GetDefaultItem( pMap->nWID );
165 : }
166 :
167 : DBG_ASSERT( pItem, "Got no default for item!" );
168 0 : if( pItem )
169 : {
170 0 : uno::Any aValue( rVal );
171 :
172 0 : const SfxMapUnit eMapUnit = pPool ? pPool->GetMetric((sal_uInt16)pMap->nWID) : SFX_MAPUNIT_100TH_MM;
173 :
174 : // check for needed metric translation
175 0 : if( (pMap->nMemberId & SFX_METRIC_ITEM) && eMapUnit != SFX_MAPUNIT_100TH_MM )
176 : {
177 0 : if ( !bDontConvertNegativeValues || SvxUnoCheckForPositiveValue( aValue ) )
178 0 : SvxUnoConvertFromMM( eMapUnit, aValue );
179 : }
180 :
181 0 : SfxPoolItem *pNewItem = pItem->Clone();
182 :
183 0 : sal_uInt8 nMemberId = pMap->nMemberId & (~SFX_METRIC_ITEM);
184 0 : if( eMapUnit == SFX_MAPUNIT_100TH_MM )
185 0 : nMemberId &= (~CONVERT_TWIPS);
186 :
187 0 : if( pNewItem->PutValue( aValue, nMemberId ) )
188 : {
189 : // Set new item in item set
190 0 : rSet.Put( *pNewItem, pMap->nWID );
191 : }
192 0 : delete pNewItem;
193 : }
194 : }
195 :
196 :
197 0 : uno::Any SvxItemPropertySet::getPropertyValue( const SfxItemPropertySimpleEntry* pMap ) const
198 : {
199 : // Already entered a value? Then finish quickly
200 0 : uno::Any* pUsrAny = GetUsrAnyForID(pMap->nWID);
201 0 : if(pUsrAny)
202 0 : return *pUsrAny;
203 :
204 : // No UsrAny detected yet, generate Default entry and return this
205 0 : const SfxMapUnit eMapUnit = mrItemPool.GetMetric((sal_uInt16)pMap->nWID);
206 0 : sal_uInt8 nMemberId = pMap->nMemberId & (~SFX_METRIC_ITEM);
207 0 : if( eMapUnit == SFX_MAPUNIT_100TH_MM )
208 0 : nMemberId &= (~CONVERT_TWIPS);
209 0 : uno::Any aVal;
210 0 : SfxItemSet aSet( mrItemPool, pMap->nWID, pMap->nWID);
211 :
212 0 : if( (pMap->nWID < OWN_ATTR_VALUE_START) && (pMap->nWID > OWN_ATTR_VALUE_END ) )
213 : {
214 : // Get Default from ItemPool
215 0 : if(mrItemPool.IsWhich(pMap->nWID))
216 0 : aSet.Put(mrItemPool.GetDefaultItem(pMap->nWID));
217 : }
218 :
219 0 : if(aSet.Count())
220 : {
221 0 : const SfxPoolItem* pItem = NULL;
222 0 : SfxItemState eState = aSet.GetItemState( pMap->nWID, true, &pItem );
223 0 : if(eState >= SFX_ITEM_DEFAULT && pItem)
224 : {
225 0 : pItem->QueryValue( aVal, nMemberId );
226 0 : ((SvxItemPropertySet*)this)->AddUsrAnyForID(aVal, pMap->nWID);
227 : }
228 : }
229 :
230 0 : if( pMap->nMemberId & SFX_METRIC_ITEM )
231 : {
232 : // check for needed metric translation
233 0 : if(pMap->nMemberId & SFX_METRIC_ITEM && eMapUnit != SFX_MAPUNIT_100TH_MM)
234 : {
235 0 : SvxUnoConvertToMM( eMapUnit, aVal );
236 : }
237 : }
238 :
239 0 : if ( pMap->aType.getTypeClass() == uno::TypeClass_ENUM &&
240 0 : aVal.getValueType() == ::getCppuType((const sal_Int32*)0) )
241 : {
242 : sal_Int32 nEnum;
243 0 : aVal >>= nEnum;
244 :
245 0 : aVal.setValue( &nEnum, pMap->aType );
246 : }
247 :
248 0 : return aVal;
249 : }
250 :
251 :
252 :
253 0 : void SvxItemPropertySet::setPropertyValue( const SfxItemPropertySimpleEntry* pMap, const uno::Any& rVal ) const
254 : {
255 0 : uno::Any* pUsrAny = GetUsrAnyForID(pMap->nWID);
256 0 : if(!pUsrAny)
257 0 : ((SvxItemPropertySet*)this)->AddUsrAnyForID(rVal, pMap->nWID);
258 : else
259 0 : *pUsrAny = rVal;
260 0 : }
261 :
262 :
263 :
264 0 : const SfxItemPropertySimpleEntry* SvxItemPropertySet::getPropertyMapEntry(const OUString &rName) const
265 : {
266 0 : return m_aPropertyMap.getByName( rName );
267 : }
268 :
269 :
270 :
271 0 : uno::Reference< beans::XPropertySetInfo > SvxItemPropertySet::getPropertySetInfo() const
272 : {
273 0 : if( !m_xInfo.is() )
274 0 : m_xInfo = new SfxItemPropertySetInfo( m_aPropertyMap );
275 0 : return m_xInfo;
276 : }
277 :
278 :
279 :
280 : #ifndef TWIPS_TO_MM
281 : #define TWIPS_TO_MM(val) ((val * 127 + 36) / 72)
282 : #endif
283 : #ifndef MM_TO_TWIPS
284 : #define MM_TO_TWIPS(val) ((val * 72 + 63) / 127)
285 : #endif
286 :
287 : /** converts the given any with a metric to 100th/mm if needed */
288 0 : void SvxUnoConvertToMM( const SfxMapUnit eSourceMapUnit, uno::Any & rMetric ) throw()
289 : {
290 : // map the metric of the itempool to 100th mm
291 0 : switch(eSourceMapUnit)
292 : {
293 : case SFX_MAPUNIT_TWIP :
294 : {
295 0 : switch( rMetric.getValueTypeClass() )
296 : {
297 : case uno::TypeClass_BYTE:
298 0 : rMetric <<= (sal_Int8)(TWIPS_TO_MM(*(sal_Int8*)rMetric.getValue()));
299 0 : break;
300 : case uno::TypeClass_SHORT:
301 0 : rMetric <<= (sal_Int16)(TWIPS_TO_MM(*(sal_Int16*)rMetric.getValue()));
302 0 : break;
303 : case uno::TypeClass_UNSIGNED_SHORT:
304 0 : rMetric <<= (sal_uInt16)(TWIPS_TO_MM(*(sal_uInt16*)rMetric.getValue()));
305 0 : break;
306 : case uno::TypeClass_LONG:
307 0 : rMetric <<= (sal_Int32)(TWIPS_TO_MM(*(sal_Int32*)rMetric.getValue()));
308 0 : break;
309 : case uno::TypeClass_UNSIGNED_LONG:
310 0 : rMetric <<= (sal_uInt32)(TWIPS_TO_MM(*(sal_uInt32*)rMetric.getValue()));
311 0 : break;
312 : default:
313 : OSL_FAIL("AW: Missing unit translation to 100th mm!");
314 : }
315 0 : break;
316 : }
317 : default:
318 : {
319 : OSL_FAIL("AW: Missing unit translation to 100th mm!");
320 : }
321 : }
322 0 : }
323 :
324 :
325 :
326 : /** converts the given any with a metric from 100th/mm to the given metric if needed */
327 0 : void SvxUnoConvertFromMM( const SfxMapUnit eDestinationMapUnit, uno::Any & rMetric ) throw()
328 : {
329 0 : switch(eDestinationMapUnit)
330 : {
331 : case SFX_MAPUNIT_TWIP :
332 : {
333 0 : switch( rMetric.getValueTypeClass() )
334 : {
335 : case uno::TypeClass_BYTE:
336 0 : rMetric <<= (sal_Int8)(MM_TO_TWIPS(*(sal_Int8*)rMetric.getValue()));
337 0 : break;
338 : case uno::TypeClass_SHORT:
339 0 : rMetric <<= (sal_Int16)(MM_TO_TWIPS(*(sal_Int16*)rMetric.getValue()));
340 0 : break;
341 : case uno::TypeClass_UNSIGNED_SHORT:
342 0 : rMetric <<= (sal_uInt16)(MM_TO_TWIPS(*(sal_uInt16*)rMetric.getValue()));
343 0 : break;
344 : case uno::TypeClass_LONG:
345 0 : rMetric <<= (sal_Int32)(MM_TO_TWIPS(*(sal_Int32*)rMetric.getValue()));
346 0 : break;
347 : case uno::TypeClass_UNSIGNED_LONG:
348 0 : rMetric <<= (sal_uInt32)(MM_TO_TWIPS(*(sal_uInt32*)rMetric.getValue()));
349 0 : break;
350 : default:
351 : OSL_FAIL("AW: Missing unit translation to 100th mm!");
352 : }
353 0 : break;
354 : }
355 : default:
356 : {
357 : OSL_FAIL("AW: Missing unit translation to PoolMetrics!");
358 : }
359 : }
360 0 : }
361 :
362 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|