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