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