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 { 45 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 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 //---------------------------------------------------------------------- 66 SvxItemPropertySet::~SvxItemPropertySet() 67 { 68 ClearAllUsrAny(); 69 } 70 71 //---------------------------------------------------------------------- 72 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 //---------------------------------------------------------------------- 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 102 void SvxItemPropertySet::ClearAllUsrAny() 103 { 104 if(pCombiList) 105 delete pCombiList; 106 pCombiList = NULL; 107 } 108 109 //---------------------------------------------------------------------- 110 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 //---------------------------------------------------------------------- 122 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 //---------------------------------------------------------------------- 168 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 //---------------------------------------------------------------------- 221 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 280 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 291 const SfxItemPropertySimpleEntry* SvxItemPropertySet::getPropertyMapEntry(const OUString &rName) const 292 { 293 return m_aPropertyMap.getByName( rName ); 294 } 295 296 //---------------------------------------------------------------------- 297 298 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 */ 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 */ 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