1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <com/sun/star/beans/XPropertySet.hpp>
21 #include <svl/itemprop.hxx>
22 #include <tools/helpers.hxx>
23 #include <editeng/unoipset.hxx>
24 #include <svl/itempool.hxx>
25 #include <svl/solar.hrc>
26 #include <o3tl/any.hxx>
27 #include <osl/diagnose.h>
28 #include <sal/log.hxx>
31 using namespace ::com::sun::star
;
34 struct SvxIDPropertyCombine
42 SvxItemPropertySet::SvxItemPropertySet( const SfxItemPropertyMapEntry
* pMap
, SfxItemPool
& rItemPool
)
43 : m_aPropertyMap( pMap
),
44 mrItemPool( rItemPool
)
49 SvxItemPropertySet::~SvxItemPropertySet()
55 uno::Any
* SvxItemPropertySet::GetUsrAnyForID(SfxItemPropertySimpleEntry
const & entry
) const
57 for (auto const & pActual
: aCombineList
)
59 if( pActual
->nWID
== entry
.nWID
&& pActual
->memberId
== entry
.nMemberId
)
60 return &pActual
->aAny
;
66 void SvxItemPropertySet::AddUsrAnyForID(
67 const uno::Any
& rAny
, SfxItemPropertySimpleEntry
const & entry
)
69 std::unique_ptr
<SvxIDPropertyCombine
> pNew(new SvxIDPropertyCombine
);
70 pNew
->nWID
= entry
.nWID
;
71 pNew
->memberId
= entry
.nMemberId
;
73 aCombineList
.push_back( std::move(pNew
) );
77 void SvxItemPropertySet::ClearAllUsrAny()
83 static bool SvxUnoCheckForPositiveValue( const uno::Any
& rVal
)
85 bool bConvert
= true; // the default is that all metric items must be converted
88 bConvert
= (nValue
> 0);
93 uno::Any
SvxItemPropertySet::getPropertyValue( const SfxItemPropertySimpleEntry
* pMap
, const SfxItemSet
& rSet
, bool bSearchInParent
, bool bDontConvertNegativeValues
)
96 if(!pMap
|| !pMap
->nWID
)
99 const SfxPoolItem
* pItem
= nullptr;
100 SfxItemPool
* pPool
= rSet
.GetPool();
101 (void)rSet
.GetItemState( pMap
->nWID
, bSearchInParent
, &pItem
);
102 if( nullptr == pItem
&& pPool
)
103 pItem
= &(pPool
->GetDefaultItem( pMap
->nWID
));
105 const MapUnit eMapUnit
= pPool
? pPool
->GetMetric(pMap
->nWID
) : MapUnit::Map100thMM
;
106 sal_uInt8 nMemberId
= pMap
->nMemberId
;
107 if( eMapUnit
== MapUnit::Map100thMM
)
108 nMemberId
&= (~CONVERT_TWIPS
);
112 pItem
->QueryValue( aVal
, nMemberId
);
113 if( pMap
->nMoreFlags
& PropertyMoreFlags::METRIC_ITEM
)
115 if( eMapUnit
!= MapUnit::Map100thMM
)
117 if ( !bDontConvertNegativeValues
|| SvxUnoCheckForPositiveValue( aVal
) )
118 SvxUnoConvertToMM( eMapUnit
, aVal
);
121 else if ( pMap
->aType
.getTypeClass() == uno::TypeClass_ENUM
&&
122 aVal
.getValueType() == ::cppu::UnoType
<sal_Int32
>::get() )
124 // convert typeless SfxEnumItem to enum type
127 aVal
.setValue( &nEnum
, pMap
->aType
);
132 OSL_FAIL( "No SfxPoolItem found for property!" );
139 void SvxItemPropertySet::setPropertyValue( const SfxItemPropertySimpleEntry
* pMap
, const uno::Any
& rVal
, SfxItemSet
& rSet
, bool bDontConvertNegativeValues
)
141 if(!pMap
|| !pMap
->nWID
)
145 const SfxPoolItem
* pItem
= nullptr;
146 SfxItemState eState
= rSet
.GetItemState( pMap
->nWID
, true, &pItem
);
147 SfxItemPool
* pPool
= rSet
.GetPool();
149 // Put UnoAny in the item value
150 if(eState
< SfxItemState::DEFAULT
|| pItem
== nullptr)
152 if( pPool
== nullptr )
154 OSL_FAIL( "No default item and no pool?" );
158 pItem
= &pPool
->GetDefaultItem( pMap
->nWID
);
161 uno::Any
aValue(rVal
);
163 const MapUnit eMapUnit
= pPool
? pPool
->GetMetric(pMap
->nWID
) : MapUnit::Map100thMM
;
165 // check for needed metric translation
166 if ((pMap
->nMoreFlags
& PropertyMoreFlags::METRIC_ITEM
) && eMapUnit
!= MapUnit::Map100thMM
)
168 if (!bDontConvertNegativeValues
|| SvxUnoCheckForPositiveValue(aValue
))
169 SvxUnoConvertFromMM(eMapUnit
, aValue
);
172 std::unique_ptr
<SfxPoolItem
> pNewItem(pItem
->Clone());
174 sal_uInt8 nMemberId
= pMap
->nMemberId
;
175 if (eMapUnit
== MapUnit::Map100thMM
)
176 nMemberId
&= (~CONVERT_TWIPS
);
178 if (pNewItem
->PutValue(aValue
, nMemberId
))
180 // Set new item in item set
181 pNewItem
->SetWhich(pMap
->nWID
);
187 uno::Any
SvxItemPropertySet::getPropertyValue( const SfxItemPropertySimpleEntry
* pMap
) const
189 // Already entered a value? Then finish quickly
190 uno::Any
* pUsrAny
= GetUsrAnyForID(*pMap
);
194 // No UsrAny detected yet, generate Default entry and return this
195 const MapUnit eMapUnit
= mrItemPool
.GetMetric(pMap
->nWID
);
196 sal_uInt8 nMemberId
= pMap
->nMemberId
;
197 if( eMapUnit
== MapUnit::Map100thMM
)
198 nMemberId
&= (~CONVERT_TWIPS
);
200 SfxItemSet
aSet( mrItemPool
, {{pMap
->nWID
, pMap
->nWID
}});
202 if( (pMap
->nWID
< OWN_ATTR_VALUE_START
) || (pMap
->nWID
> OWN_ATTR_VALUE_END
) )
204 // Get Default from ItemPool
205 if(SfxItemPool::IsWhich(pMap
->nWID
))
206 aSet
.Put(mrItemPool
.GetDefaultItem(pMap
->nWID
));
211 const SfxPoolItem
* pItem
= nullptr;
212 SfxItemState eState
= aSet
.GetItemState( pMap
->nWID
, true, &pItem
);
213 if(eState
>= SfxItemState::DEFAULT
&& pItem
)
215 pItem
->QueryValue( aVal
, nMemberId
);
216 const_cast<SvxItemPropertySet
*>(this)->AddUsrAnyForID(aVal
, *pMap
);
220 // check for needed metric translation
221 if(pMap
->nMoreFlags
& PropertyMoreFlags::METRIC_ITEM
&& eMapUnit
!= MapUnit::Map100thMM
)
223 SvxUnoConvertToMM( eMapUnit
, aVal
);
226 if ( pMap
->aType
.getTypeClass() == uno::TypeClass_ENUM
&&
227 aVal
.getValueType() == ::cppu::UnoType
<sal_Int32
>::get() )
232 aVal
.setValue( &nEnum
, pMap
->aType
);
239 void SvxItemPropertySet::setPropertyValue( const SfxItemPropertySimpleEntry
* pMap
, const uno::Any
& rVal
) const
241 uno::Any
* pUsrAny
= GetUsrAnyForID(*pMap
);
243 const_cast<SvxItemPropertySet
*>(this)->AddUsrAnyForID(rVal
, *pMap
);
249 const SfxItemPropertySimpleEntry
* SvxItemPropertySet::getPropertyMapEntry(const OUString
&rName
) const
251 return m_aPropertyMap
.getByName( rName
);
255 uno::Reference
< beans::XPropertySetInfo
> const & SvxItemPropertySet::getPropertySetInfo() const
258 m_xInfo
= new SfxItemPropertySetInfo( m_aPropertyMap
);
264 #define TWIPS_TO_MM(val) ((val * 127 + 36) / 72)
267 /** converts the given any with a metric to 100th/mm if needed */
268 void SvxUnoConvertToMM( const MapUnit eSourceMapUnit
, uno::Any
& rMetric
) throw()
270 // map the metric of the itempool to 100th mm
271 switch(eSourceMapUnit
)
273 case MapUnit::MapTwip
:
275 switch( rMetric
.getValueTypeClass() )
277 case uno::TypeClass_BYTE
:
278 rMetric
<<= static_cast<sal_Int8
>(TWIPS_TO_MM(*o3tl::forceAccess
<sal_Int8
>(rMetric
)));
280 case uno::TypeClass_SHORT
:
281 rMetric
<<= static_cast<sal_Int16
>(TWIPS_TO_MM(*o3tl::forceAccess
<sal_Int16
>(rMetric
)));
283 case uno::TypeClass_UNSIGNED_SHORT
:
284 rMetric
<<= static_cast<sal_uInt16
>(TWIPS_TO_MM(*o3tl::forceAccess
<sal_uInt16
>(rMetric
)));
286 case uno::TypeClass_LONG
:
287 rMetric
<<= static_cast<sal_Int32
>(TWIPS_TO_MM(*o3tl::forceAccess
<sal_Int32
>(rMetric
)));
289 case uno::TypeClass_UNSIGNED_LONG
:
290 rMetric
<<= static_cast<sal_uInt32
>(TWIPS_TO_MM(*o3tl::forceAccess
<sal_uInt32
>(rMetric
)));
293 SAL_WARN("editeng", "AW: Missing unit translation to 100th mm, " << OString::number(static_cast<sal_Int32
>(rMetric
.getValueTypeClass())));
300 OSL_FAIL("AW: Missing unit translation to 100th mm!");
306 /** converts the given any with a metric from 100th/mm to the given metric if needed */
307 void SvxUnoConvertFromMM( const MapUnit eDestinationMapUnit
, uno::Any
& rMetric
) throw()
309 switch(eDestinationMapUnit
)
311 case MapUnit::MapTwip
:
313 switch( rMetric
.getValueTypeClass() )
315 case uno::TypeClass_BYTE
:
316 rMetric
<<= static_cast<sal_Int8
>(sanitiseMm100ToTwip(*o3tl::forceAccess
<sal_Int8
>(rMetric
)));
318 case uno::TypeClass_SHORT
:
319 rMetric
<<= static_cast<sal_Int16
>(sanitiseMm100ToTwip(*o3tl::forceAccess
<sal_Int16
>(rMetric
)));
321 case uno::TypeClass_UNSIGNED_SHORT
:
322 rMetric
<<= static_cast<sal_uInt16
>(sanitiseMm100ToTwip(*o3tl::forceAccess
<sal_uInt16
>(rMetric
)));
324 case uno::TypeClass_LONG
:
325 rMetric
<<= static_cast<sal_Int32
>(sanitiseMm100ToTwip(*o3tl::forceAccess
<sal_Int32
>(rMetric
)));
327 case uno::TypeClass_UNSIGNED_LONG
:
328 rMetric
<<= static_cast<sal_uInt32
>(sanitiseMm100ToTwip(*o3tl::forceAccess
<sal_uInt32
>(rMetric
)));
331 OSL_FAIL("AW: Missing unit translation to 100th mm!");
337 OSL_FAIL("AW: Missing unit translation to PoolMetrics!");
342 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */