1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_editeng.hxx" 30 #include <com/sun/star/beans/XPropertySet.hpp> 31 #include <svl/eitem.hxx> 32 #include <tools/list.hxx> 33 34 #include <hash_map> 35 #include <vector> 36 #include <svl/itemprop.hxx> 37 38 #include <editeng/unoipset.hxx> 39 #include <editeng/editids.hrc> 40 #include <editeng/editeng.hxx> 41 #include <svl/itempool.hxx> 42 #include <algorithm> 43 44 using namespace ::com::sun::star; 45 using namespace ::rtl; 46 47 //---------------------------------------------------------------------- 48 49 struct SfxItemPropertyMapEntryHash 50 { 51 size_t operator()(const SfxItemPropertyMapEntry* pMap) const { return (size_t)pMap; } 52 }; 53 54 //---------------------------------------------------------------------- 55 56 struct SvxIDPropertyCombine 57 { 58 sal_uInt16 nWID; 59 uno::Any aAny; 60 }; 61 62 DECLARE_LIST( SvxIDPropertyCombineList, SvxIDPropertyCombine * ) 63 64 SvxItemPropertySet::SvxItemPropertySet( const SfxItemPropertyMapEntry* pMap, SfxItemPool& rItemPool, sal_Bool bConvertTwips ) 65 : m_aPropertyMap( pMap ), 66 _pMap(pMap), mbConvertTwips(bConvertTwips), mrItemPool( rItemPool ) 67 { 68 pCombiList = NULL; 69 } 70 71 //---------------------------------------------------------------------- 72 SvxItemPropertySet::~SvxItemPropertySet() 73 { 74 ClearAllUsrAny(); 75 } 76 77 //---------------------------------------------------------------------- 78 uno::Any* SvxItemPropertySet::GetUsrAnyForID(sal_uInt16 nWID) const 79 { 80 if(pCombiList && pCombiList->Count()) 81 { 82 SvxIDPropertyCombine* pActual = pCombiList->First(); 83 while(pActual) 84 { 85 if(pActual->nWID == nWID) 86 return &pActual->aAny; 87 pActual = pCombiList->Next(); 88 89 } 90 } 91 return NULL; 92 } 93 94 //---------------------------------------------------------------------- 95 void SvxItemPropertySet::AddUsrAnyForID(const uno::Any& rAny, sal_uInt16 nWID) 96 { 97 if(!pCombiList) 98 pCombiList = new SvxIDPropertyCombineList(); 99 100 SvxIDPropertyCombine* pNew = new SvxIDPropertyCombine; 101 pNew->nWID = nWID; 102 pNew->aAny = rAny; 103 pCombiList->Insert(pNew); 104 } 105 106 //---------------------------------------------------------------------- 107 108 void SvxItemPropertySet::ClearAllUsrAny() 109 { 110 if(pCombiList) 111 delete pCombiList; 112 pCombiList = NULL; 113 } 114 115 //---------------------------------------------------------------------- 116 117 sal_Bool SvxUnoCheckForPositiveValue( const uno::Any& rVal ) 118 { 119 sal_Bool bConvert = sal_True; // the default is that all metric items must be converted 120 sal_Int32 nValue = 0; 121 if( rVal >>= nValue ) 122 bConvert = (nValue > 0); 123 return bConvert; 124 } 125 126 127 //---------------------------------------------------------------------- 128 uno::Any SvxItemPropertySet::getPropertyValue( const SfxItemPropertySimpleEntry* pMap, const SfxItemSet& rSet, bool bSearchInParent, bool bDontConvertNegativeValues ) const 129 { 130 uno::Any aVal; 131 if(!pMap || !pMap->nWID) 132 return aVal; 133 134 const SfxPoolItem* pItem = 0; 135 SfxItemPool* pPool = rSet.GetPool(); 136 rSet.GetItemState( pMap->nWID, bSearchInParent, &pItem ); 137 if( NULL == pItem && pPool ) 138 pItem = &(pPool->GetDefaultItem( pMap->nWID )); 139 140 const SfxMapUnit eMapUnit = pPool ? pPool->GetMetric((sal_uInt16)pMap->nWID) : SFX_MAPUNIT_100TH_MM; 141 sal_uInt8 nMemberId = pMap->nMemberId & (~SFX_METRIC_ITEM); 142 if( eMapUnit == SFX_MAPUNIT_100TH_MM ) 143 nMemberId &= (~CONVERT_TWIPS); 144 145 if(pItem) 146 { 147 pItem->QueryValue( aVal, nMemberId ); 148 if( pMap->nMemberId & SFX_METRIC_ITEM ) 149 { 150 if( eMapUnit != SFX_MAPUNIT_100TH_MM ) 151 { 152 if ( !bDontConvertNegativeValues || SvxUnoCheckForPositiveValue( aVal ) ) 153 SvxUnoConvertToMM( eMapUnit, aVal ); 154 } 155 } 156 else if ( pMap->pType->getTypeClass() == uno::TypeClass_ENUM && 157 aVal.getValueType() == ::getCppuType((const sal_Int32*)0) ) 158 { 159 // convert typeless SfxEnumItem to enum type 160 sal_Int32 nEnum; 161 aVal >>= nEnum; 162 aVal.setValue( &nEnum, *pMap->pType ); 163 } 164 } 165 else 166 { 167 DBG_ERROR( "No SfxPoolItem found for property!" ); 168 } 169 170 return aVal; 171 } 172 173 //---------------------------------------------------------------------- 174 void SvxItemPropertySet::setPropertyValue( const SfxItemPropertySimpleEntry* pMap, const uno::Any& rVal, SfxItemSet& rSet, bool bDontConvertNegativeValues ) const 175 { 176 if(!pMap || !pMap->nWID) 177 return; 178 179 // item holen 180 const SfxPoolItem* pItem = 0; 181 SfxPoolItem *pNewItem = 0; 182 SfxItemState eState = rSet.GetItemState( pMap->nWID, sal_True, &pItem ); 183 SfxItemPool* pPool = rSet.GetPool(); 184 185 // UnoAny in item-Wert stecken 186 if(eState < SFX_ITEM_DEFAULT || pItem == NULL) 187 { 188 if( pPool == NULL ) 189 { 190 DBG_ERROR( "No default item and no pool?" ); 191 return; 192 } 193 194 pItem = &pPool->GetDefaultItem( pMap->nWID ); 195 } 196 197 DBG_ASSERT( pItem, "Got no default for item!" ); 198 if( pItem ) 199 { 200 uno::Any aValue( rVal ); 201 202 const SfxMapUnit eMapUnit = pPool ? pPool->GetMetric((sal_uInt16)pMap->nWID) : SFX_MAPUNIT_100TH_MM; 203 204 // check for needed metric translation 205 if( (pMap->nMemberId & SFX_METRIC_ITEM) && eMapUnit != SFX_MAPUNIT_100TH_MM ) 206 { 207 if ( !bDontConvertNegativeValues || SvxUnoCheckForPositiveValue( aValue ) ) 208 SvxUnoConvertFromMM( eMapUnit, aValue ); 209 } 210 211 pNewItem = pItem->Clone(); 212 213 sal_uInt8 nMemberId = pMap->nMemberId & (~SFX_METRIC_ITEM); 214 if( eMapUnit == SFX_MAPUNIT_100TH_MM ) 215 nMemberId &= (~CONVERT_TWIPS); 216 217 if( pNewItem->PutValue( aValue, nMemberId ) ) 218 { 219 // neues item in itemset setzen 220 rSet.Put( *pNewItem, pMap->nWID ); 221 } 222 delete pNewItem; 223 } 224 } 225 226 //---------------------------------------------------------------------- 227 uno::Any SvxItemPropertySet::getPropertyValue( const SfxItemPropertySimpleEntry* pMap ) const 228 { 229 // Schon ein Wert eingetragen? Dann schnell fertig 230 uno::Any* pUsrAny = GetUsrAnyForID(pMap->nWID); 231 if(pUsrAny) 232 return *pUsrAny; 233 234 // Noch kein UsrAny gemerkt, generiere Default-Eintrag und gib 235 // diesen zurueck 236 237 const SfxMapUnit eMapUnit = mrItemPool.GetMetric((sal_uInt16)pMap->nWID); 238 sal_uInt8 nMemberId = pMap->nMemberId & (~SFX_METRIC_ITEM); 239 if( eMapUnit == SFX_MAPUNIT_100TH_MM ) 240 nMemberId &= (~CONVERT_TWIPS); 241 242 uno::Any aVal; 243 SfxItemSet aSet( mrItemPool, pMap->nWID, pMap->nWID); 244 245 if( (pMap->nWID < OWN_ATTR_VALUE_START) && (pMap->nWID > OWN_ATTR_VALUE_END ) ) 246 { 247 // Default aus ItemPool holen 248 if(mrItemPool.IsWhich(pMap->nWID)) 249 aSet.Put(mrItemPool.GetDefaultItem(pMap->nWID)); 250 } 251 252 if(aSet.Count()) 253 { 254 const SfxPoolItem* pItem = NULL; 255 SfxItemState eState = aSet.GetItemState( pMap->nWID, sal_True, &pItem ); 256 if(eState >= SFX_ITEM_DEFAULT && pItem) 257 { 258 pItem->QueryValue( aVal, nMemberId ); 259 ((SvxItemPropertySet*)this)->AddUsrAnyForID(aVal, pMap->nWID); 260 } 261 } 262 263 if( pMap->nMemberId & SFX_METRIC_ITEM ) 264 { 265 // check for needed metric translation 266 if(pMap->nMemberId & SFX_METRIC_ITEM && eMapUnit != SFX_MAPUNIT_100TH_MM) 267 { 268 SvxUnoConvertToMM( eMapUnit, aVal ); 269 } 270 } 271 272 if ( pMap->pType->getTypeClass() == uno::TypeClass_ENUM && 273 aVal.getValueType() == ::getCppuType((const sal_Int32*)0) ) 274 { 275 sal_Int32 nEnum; 276 aVal >>= nEnum; 277 278 aVal.setValue( &nEnum, *pMap->pType ); 279 } 280 281 return aVal; 282 } 283 284 //---------------------------------------------------------------------- 285 286 void SvxItemPropertySet::setPropertyValue( const SfxItemPropertySimpleEntry* pMap, const uno::Any& rVal ) const 287 { 288 uno::Any* pUsrAny = GetUsrAnyForID(pMap->nWID); 289 if(!pUsrAny) 290 ((SvxItemPropertySet*)this)->AddUsrAnyForID(rVal, pMap->nWID); 291 else 292 *pUsrAny = rVal; 293 } 294 295 //---------------------------------------------------------------------- 296 297 const SfxItemPropertySimpleEntry* SvxItemPropertySet::getPropertyMapEntry(const OUString &rName) const 298 { 299 return m_aPropertyMap.getByName( rName ); 300 } 301 302 //---------------------------------------------------------------------- 303 304 uno::Reference< beans::XPropertySetInfo > SvxItemPropertySet::getPropertySetInfo() const 305 { 306 if( !m_xInfo.is() ) 307 m_xInfo = new SfxItemPropertySetInfo( &m_aPropertyMap ); 308 return m_xInfo; 309 } 310 311 //---------------------------------------------------------------------- 312 313 #ifndef TWIPS_TO_MM 314 #define TWIPS_TO_MM(val) ((val * 127 + 36) / 72) 315 #endif 316 #ifndef MM_TO_TWIPS 317 #define MM_TO_TWIPS(val) ((val * 72 + 63) / 127) 318 #endif 319 320 /** converts the given any with a metric to 100th/mm if needed */ 321 void SvxUnoConvertToMM( const SfxMapUnit eSourceMapUnit, uno::Any & rMetric ) throw() 322 { 323 // map the metric of the itempool to 100th mm 324 switch(eSourceMapUnit) 325 { 326 case SFX_MAPUNIT_TWIP : 327 { 328 switch( rMetric.getValueTypeClass() ) 329 { 330 case uno::TypeClass_BYTE: 331 rMetric <<= (sal_Int8)(TWIPS_TO_MM(*(sal_Int8*)rMetric.getValue())); 332 break; 333 case uno::TypeClass_SHORT: 334 rMetric <<= (sal_Int16)(TWIPS_TO_MM(*(sal_Int16*)rMetric.getValue())); 335 break; 336 case uno::TypeClass_UNSIGNED_SHORT: 337 rMetric <<= (sal_uInt16)(TWIPS_TO_MM(*(sal_uInt16*)rMetric.getValue())); 338 break; 339 case uno::TypeClass_LONG: 340 rMetric <<= (sal_Int32)(TWIPS_TO_MM(*(sal_Int32*)rMetric.getValue())); 341 break; 342 case uno::TypeClass_UNSIGNED_LONG: 343 rMetric <<= (sal_uInt32)(TWIPS_TO_MM(*(sal_uInt32*)rMetric.getValue())); 344 break; 345 default: 346 DBG_ERROR("AW: Missing unit translation to 100th mm!"); 347 } 348 break; 349 } 350 default: 351 { 352 DBG_ERROR("AW: Missing unit translation to 100th mm!"); 353 } 354 } 355 } 356 357 //---------------------------------------------------------------------- 358 359 /** converts the given any with a metric from 100th/mm to the given metric if needed */ 360 void SvxUnoConvertFromMM( const SfxMapUnit eDestinationMapUnit, uno::Any & rMetric ) throw() 361 { 362 switch(eDestinationMapUnit) 363 { 364 case SFX_MAPUNIT_TWIP : 365 { 366 switch( rMetric.getValueTypeClass() ) 367 { 368 case uno::TypeClass_BYTE: 369 rMetric <<= (sal_Int8)(MM_TO_TWIPS(*(sal_Int8*)rMetric.getValue())); 370 break; 371 case uno::TypeClass_SHORT: 372 rMetric <<= (sal_Int16)(MM_TO_TWIPS(*(sal_Int16*)rMetric.getValue())); 373 break; 374 case uno::TypeClass_UNSIGNED_SHORT: 375 rMetric <<= (sal_uInt16)(MM_TO_TWIPS(*(sal_uInt16*)rMetric.getValue())); 376 break; 377 case uno::TypeClass_LONG: 378 rMetric <<= (sal_Int32)(MM_TO_TWIPS(*(sal_Int32*)rMetric.getValue())); 379 break; 380 case uno::TypeClass_UNSIGNED_LONG: 381 rMetric <<= (sal_uInt32)(MM_TO_TWIPS(*(sal_uInt32*)rMetric.getValue())); 382 break; 383 default: 384 DBG_ERROR("AW: Missing unit translation to 100th mm!"); 385 } 386 break; 387 } 388 default: 389 { 390 DBG_ERROR("AW: Missing unit translation to PoolMetrics!"); 391 } 392 } 393 } 394 395