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_chart2.hxx" 30 #include "ErrorBarItemConverter.hxx" 31 #include "SchWhichPairs.hxx" 32 #include "macros.hxx" 33 #include "ItemPropertyMap.hxx" 34 #include "ErrorBar.hxx" 35 #include "PropertyHelper.hxx" 36 #include "ChartModelHelper.hxx" 37 #include "ChartTypeHelper.hxx" 38 #include "StatisticsHelper.hxx" 39 40 #include "GraphicPropertyItemConverter.hxx" 41 42 #include <svl/stritem.hxx> 43 #include <svx/chrtitem.hxx> 44 #include <svl/intitem.hxx> 45 #include <rtl/math.hxx> 46 47 #include <com/sun/star/chart2/DataPointLabel.hpp> 48 #include <com/sun/star/chart2/XInternalDataProvider.hpp> 49 #include <com/sun/star/chart/ErrorBarStyle.hpp> 50 #include <com/sun/star/lang/XServiceName.hpp> 51 52 #include <functional> 53 #include <algorithm> 54 #include <vector> 55 56 using namespace ::com::sun::star; 57 58 namespace 59 { 60 61 void lcl_getErrorValues( const uno::Reference< beans::XPropertySet > & xErrorBarProp, 62 double & rOutPosError, double & rOutNegError ) 63 { 64 if( ! xErrorBarProp.is()) 65 return; 66 67 try 68 { 69 xErrorBarProp->getPropertyValue( C2U( "PositiveError" )) >>= rOutPosError; 70 xErrorBarProp->getPropertyValue( C2U( "NegativeError" )) >>= rOutNegError; 71 } 72 catch( uno::Exception & ex ) 73 { 74 ASSERT_EXCEPTION( ex ); 75 } 76 } 77 78 void lcl_getErrorIndicatorValues( 79 const uno::Reference< beans::XPropertySet > & xErrorBarProp, 80 bool & rOutShowPosError, bool & rOutShowNegError ) 81 { 82 if( ! xErrorBarProp.is()) 83 return; 84 85 try 86 { 87 xErrorBarProp->getPropertyValue( C2U( "ShowPositiveError" )) >>= rOutShowPosError; 88 xErrorBarProp->getPropertyValue( C2U( "ShowNegativeError" )) >>= rOutShowNegError; 89 } 90 catch( uno::Exception & ex ) 91 { 92 ASSERT_EXCEPTION( ex ); 93 } 94 } 95 96 } // anonymous namespace 97 98 namespace chart 99 { 100 namespace wrapper 101 { 102 103 ErrorBarItemConverter::ErrorBarItemConverter( 104 const uno::Reference< frame::XModel > & xModel, 105 const uno::Reference< beans::XPropertySet > & rPropertySet, 106 SfxItemPool& rItemPool, 107 SdrModel& rDrawModel, 108 const uno::Reference< lang::XMultiServiceFactory > & xNamedPropertyContainerFactory ) : 109 ItemConverter( rPropertySet, rItemPool ), 110 m_spGraphicConverter( new GraphicPropertyItemConverter( 111 rPropertySet, rItemPool, rDrawModel, 112 xNamedPropertyContainerFactory, 113 GraphicPropertyItemConverter::LINE_PROPERTIES )), 114 m_xModel( xModel ) 115 {} 116 117 ErrorBarItemConverter::~ErrorBarItemConverter() 118 {} 119 120 void ErrorBarItemConverter::FillItemSet( SfxItemSet & rOutItemSet ) const 121 { 122 m_spGraphicConverter->FillItemSet( rOutItemSet ); 123 124 // own items 125 ItemConverter::FillItemSet( rOutItemSet ); 126 } 127 128 bool ErrorBarItemConverter::ApplyItemSet( const SfxItemSet & rItemSet ) 129 { 130 bool bResult = m_spGraphicConverter->ApplyItemSet( rItemSet ); 131 132 // own items 133 return ItemConverter::ApplyItemSet( rItemSet ) || bResult; 134 } 135 136 const sal_uInt16 * ErrorBarItemConverter::GetWhichPairs() const 137 { 138 // must span all used items! 139 return nErrorBarWhichPairs; 140 } 141 142 bool ErrorBarItemConverter::GetItemProperty( 143 tWhichIdType /* nWhichId */, 144 tPropertyNameWithMemberId & /* rOutProperty */ ) const 145 { 146 return false; 147 } 148 149 bool ErrorBarItemConverter::ApplySpecialItem( 150 sal_uInt16 nWhichId, const SfxItemSet & rItemSet ) 151 throw( uno::Exception ) 152 { 153 bool bChanged = false; 154 uno::Any aValue; 155 156 switch( nWhichId ) 157 { 158 // Attention !!! This case must be passed before SCHATTR_STAT_PERCENT, 159 // SCHATTR_STAT_BIGERROR, SCHATTR_STAT_CONSTPLUS, 160 // SCHATTR_STAT_CONSTMINUS and SCHATTR_STAT_INDICATE 161 case SCHATTR_STAT_KIND_ERROR: 162 { 163 uno::Reference< beans::XPropertySet > xErrorBarProp( GetPropertySet()); 164 165 SvxChartKindError eErrorKind = 166 static_cast< const SvxChartKindErrorItem & >( 167 rItemSet.Get( nWhichId )).GetValue(); 168 169 if( !xErrorBarProp.is() && eErrorKind == CHERROR_NONE) 170 { 171 //nothing to do 172 } 173 else 174 { 175 sal_Int32 nStyle = ::com::sun::star::chart::ErrorBarStyle::NONE; 176 177 switch( eErrorKind ) 178 { 179 case CHERROR_NONE: 180 nStyle = ::com::sun::star::chart::ErrorBarStyle::NONE; break; 181 case CHERROR_VARIANT: 182 nStyle = ::com::sun::star::chart::ErrorBarStyle::VARIANCE; break; 183 case CHERROR_SIGMA: 184 nStyle = ::com::sun::star::chart::ErrorBarStyle::STANDARD_DEVIATION; break; 185 case CHERROR_PERCENT: 186 nStyle = ::com::sun::star::chart::ErrorBarStyle::RELATIVE; break; 187 case CHERROR_BIGERROR: 188 nStyle = ::com::sun::star::chart::ErrorBarStyle::ERROR_MARGIN; break; 189 case CHERROR_CONST: 190 nStyle = ::com::sun::star::chart::ErrorBarStyle::ABSOLUTE; break; 191 case CHERROR_STDERROR: 192 nStyle = ::com::sun::star::chart::ErrorBarStyle::STANDARD_ERROR; break; 193 case CHERROR_RANGE: 194 nStyle = ::com::sun::star::chart::ErrorBarStyle::FROM_DATA; break; 195 } 196 197 xErrorBarProp->setPropertyValue( C2U( "ErrorBarStyle" ), 198 uno::makeAny( nStyle )); 199 bChanged = true; 200 } 201 } 202 break; 203 204 case SCHATTR_STAT_PERCENT: 205 case SCHATTR_STAT_BIGERROR: 206 { 207 OSL_ENSURE( false, "Deprectaed item" ); 208 uno::Reference< beans::XPropertySet > xErrorBarProp( GetPropertySet()); 209 210 double fValue = 211 static_cast< const SvxDoubleItem & >( 212 rItemSet.Get( nWhichId )).GetValue(); 213 double fPos, fNeg; 214 lcl_getErrorValues( xErrorBarProp, fPos, fNeg ); 215 216 if( ! ( ::rtl::math::approxEqual( fPos, fValue ) && 217 ::rtl::math::approxEqual( fNeg, fValue ))) 218 { 219 xErrorBarProp->setPropertyValue( C2U( "PositiveError" ), 220 uno::makeAny( fValue )); 221 xErrorBarProp->setPropertyValue( C2U( "NegativeError" ), 222 uno::makeAny( fValue )); 223 bChanged = true; 224 } 225 } 226 break; 227 228 case SCHATTR_STAT_CONSTPLUS: 229 { 230 double fValue = 231 static_cast< const SvxDoubleItem & >( 232 rItemSet.Get( nWhichId )).GetValue(); 233 double fPos, fNeg; 234 lcl_getErrorValues( GetPropertySet(), fPos, fNeg ); 235 236 if( ! ::rtl::math::approxEqual( fPos, fValue )) 237 { 238 GetPropertySet()->setPropertyValue( C2U( "PositiveError" ), uno::makeAny( fValue )); 239 bChanged = true; 240 } 241 } 242 break; 243 244 case SCHATTR_STAT_CONSTMINUS: 245 { 246 uno::Reference< beans::XPropertySet > xErrorBarProp( GetPropertySet()); 247 248 double fValue = 249 static_cast< const SvxDoubleItem & >( 250 rItemSet.Get( nWhichId )).GetValue(); 251 double fPos, fNeg; 252 lcl_getErrorValues( xErrorBarProp, fPos, fNeg ); 253 254 if( ! ::rtl::math::approxEqual( fNeg, fValue )) 255 { 256 xErrorBarProp->setPropertyValue( C2U( "NegativeError" ), uno::makeAny( fValue )); 257 bChanged = true; 258 } 259 } 260 break; 261 262 case SCHATTR_STAT_INDICATE: 263 { 264 uno::Reference< beans::XPropertySet > xErrorBarProp( GetPropertySet()); 265 266 SvxChartIndicate eIndicate = 267 static_cast< const SvxChartIndicateItem & >( 268 rItemSet.Get( nWhichId )).GetValue(); 269 270 bool bNewIndPos = (eIndicate == CHINDICATE_BOTH || eIndicate == CHINDICATE_UP ); 271 bool bNewIndNeg = (eIndicate == CHINDICATE_BOTH || eIndicate == CHINDICATE_DOWN ); 272 273 bool bShowPos, bShowNeg; 274 lcl_getErrorIndicatorValues( xErrorBarProp, bShowPos, bShowNeg ); 275 276 if( ( bShowPos != bNewIndPos || 277 bShowNeg != bNewIndNeg )) 278 { 279 xErrorBarProp->setPropertyValue( C2U( "ShowPositiveError" ), uno::makeAny( bNewIndPos )); 280 xErrorBarProp->setPropertyValue( C2U( "ShowNegativeError" ), uno::makeAny( bNewIndNeg )); 281 bChanged = true; 282 } 283 } 284 break; 285 286 case SCHATTR_STAT_RANGE_POS: 287 case SCHATTR_STAT_RANGE_NEG: 288 { 289 // @todo: also be able to deal with x-error bars 290 const bool bYError = true; 291 uno::Reference< chart2::data::XDataSource > xErrorBarSource( GetPropertySet(), uno::UNO_QUERY ); 292 uno::Reference< chart2::XChartDocument > xChartDoc( m_xModel, uno::UNO_QUERY ); 293 uno::Reference< chart2::data::XDataProvider > xDataProvider; 294 295 if( xChartDoc.is()) 296 xDataProvider.set( xChartDoc->getDataProvider()); 297 if( xErrorBarSource.is() && xDataProvider.is()) 298 { 299 ::rtl::OUString aNewRange( static_cast< const SfxStringItem & >( rItemSet.Get( nWhichId )).GetValue()); 300 bool bApplyNewRange = false; 301 302 bool bIsPositiveValue( nWhichId == SCHATTR_STAT_RANGE_POS ); 303 if( xChartDoc->hasInternalDataProvider()) 304 { 305 if( aNewRange.getLength()) 306 { 307 uno::Reference< chart2::data::XDataSequence > xSeq( 308 StatisticsHelper::getErrorDataSequenceFromDataSource( 309 xErrorBarSource, bIsPositiveValue, bYError )); 310 if( ! xSeq.is()) 311 { 312 // no data range for error bars yet => create 313 uno::Reference< chart2::XInternalDataProvider > xIntDataProvider( xDataProvider, uno::UNO_QUERY ); 314 OSL_ASSERT( xIntDataProvider.is()); 315 if( xIntDataProvider.is()) 316 { 317 xIntDataProvider->appendSequence(); 318 aNewRange = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("last")); 319 bApplyNewRange = true; 320 } 321 } 322 } 323 } 324 else 325 { 326 uno::Reference< chart2::data::XDataSequence > xSeq( 327 StatisticsHelper::getErrorDataSequenceFromDataSource( 328 xErrorBarSource, bIsPositiveValue, bYError )); 329 bApplyNewRange = 330 ! ( xSeq.is() && aNewRange.equals( xSeq->getSourceRangeRepresentation())); 331 } 332 333 if( bApplyNewRange ) 334 StatisticsHelper::setErrorDataSequence( 335 xErrorBarSource, xDataProvider, aNewRange, bIsPositiveValue, bYError ); 336 } 337 } 338 break; 339 } 340 341 return bChanged; 342 } 343 344 void ErrorBarItemConverter::FillSpecialItem( 345 sal_uInt16 nWhichId, SfxItemSet & rOutItemSet ) const 346 throw( uno::Exception ) 347 { 348 switch( nWhichId ) 349 { 350 case SCHATTR_STAT_KIND_ERROR: 351 { 352 SvxChartKindError eErrorKind = CHERROR_NONE; 353 uno::Reference< beans::XPropertySet > xErrorBarProp( GetPropertySet()); 354 355 sal_Int32 nStyle = 0; 356 if( xErrorBarProp->getPropertyValue( C2U( "ErrorBarStyle" )) >>= nStyle ) 357 { 358 switch( nStyle ) 359 { 360 case ::com::sun::star::chart::ErrorBarStyle::NONE: 361 break; 362 case ::com::sun::star::chart::ErrorBarStyle::VARIANCE: 363 eErrorKind = CHERROR_VARIANT; break; 364 case ::com::sun::star::chart::ErrorBarStyle::STANDARD_DEVIATION: 365 eErrorKind = CHERROR_SIGMA; break; 366 case ::com::sun::star::chart::ErrorBarStyle::ABSOLUTE: 367 eErrorKind = CHERROR_CONST; break; 368 case ::com::sun::star::chart::ErrorBarStyle::RELATIVE: 369 eErrorKind = CHERROR_PERCENT; break; 370 case ::com::sun::star::chart::ErrorBarStyle::ERROR_MARGIN: 371 eErrorKind = CHERROR_BIGERROR; break; 372 case ::com::sun::star::chart::ErrorBarStyle::STANDARD_ERROR: 373 eErrorKind = CHERROR_STDERROR; break; 374 case ::com::sun::star::chart::ErrorBarStyle::FROM_DATA: 375 eErrorKind = CHERROR_RANGE; break; 376 } 377 } 378 rOutItemSet.Put( SvxChartKindErrorItem( eErrorKind, SCHATTR_STAT_KIND_ERROR )); 379 } 380 break; 381 382 case SCHATTR_STAT_PERCENT: 383 { 384 double fPos, fNeg; 385 lcl_getErrorValues( GetPropertySet(), fPos, fNeg ); 386 rOutItemSet.Put( SvxDoubleItem( ( fPos + fNeg ) / 2.0, nWhichId )); 387 } 388 break; 389 390 case SCHATTR_STAT_BIGERROR: 391 { 392 double fPos, fNeg; 393 lcl_getErrorValues( GetPropertySet(), fPos, fNeg ); 394 rOutItemSet.Put( SvxDoubleItem( ( fPos + fNeg ) / 2.0, nWhichId )); 395 } 396 break; 397 398 case SCHATTR_STAT_CONSTPLUS: 399 { 400 double fPos, fNeg; 401 lcl_getErrorValues( GetPropertySet(), fPos, fNeg ); 402 rOutItemSet.Put( SvxDoubleItem( fPos, nWhichId )); 403 } 404 break; 405 406 case SCHATTR_STAT_CONSTMINUS: 407 { 408 double fPos, fNeg; 409 lcl_getErrorValues( GetPropertySet(), fPos, fNeg ); 410 rOutItemSet.Put( SvxDoubleItem( fNeg, nWhichId )); 411 } 412 break; 413 414 case SCHATTR_STAT_INDICATE: 415 { 416 SvxChartIndicate eIndicate = CHINDICATE_BOTH; 417 bool bShowPos, bShowNeg; 418 lcl_getErrorIndicatorValues( GetPropertySet(), bShowPos, bShowNeg ); 419 420 if( bShowPos ) 421 { 422 if( bShowNeg ) 423 eIndicate = CHINDICATE_BOTH; 424 else 425 eIndicate = CHINDICATE_UP; 426 } 427 else 428 { 429 if( bShowNeg ) 430 eIndicate = CHINDICATE_DOWN; 431 else 432 eIndicate = CHINDICATE_NONE; 433 } 434 rOutItemSet.Put( SvxChartIndicateItem( eIndicate, SCHATTR_STAT_INDICATE )); 435 } 436 break; 437 438 case SCHATTR_STAT_RANGE_POS: 439 case SCHATTR_STAT_RANGE_NEG: 440 { 441 uno::Reference< chart2::data::XDataSource > xErrorBarSource( GetPropertySet(), uno::UNO_QUERY ); 442 if( xErrorBarSource.is()) 443 { 444 uno::Reference< chart2::data::XDataSequence > xSeq( 445 StatisticsHelper::getErrorDataSequenceFromDataSource( 446 xErrorBarSource, (nWhichId == SCHATTR_STAT_RANGE_POS) /*, true */ /* y */ )); 447 if( xSeq.is()) 448 rOutItemSet.Put( SfxStringItem( nWhichId, String( xSeq->getSourceRangeRepresentation()))); 449 } 450 } 451 break; 452 } 453 } 454 455 } // namespace wrapper 456 } // namespace chart 457