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_chartcontroller.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 { 148 bool bChanged = false; 149 uno::Any aValue; 150 151 switch( nWhichId ) 152 { 153 // Attention !!! This case must be passed before SCHATTR_STAT_PERCENT, 154 // SCHATTR_STAT_BIGERROR, SCHATTR_STAT_CONSTPLUS, 155 // SCHATTR_STAT_CONSTMINUS and SCHATTR_STAT_INDICATE 156 case SCHATTR_STAT_KIND_ERROR: 157 { 158 uno::Reference< beans::XPropertySet > xErrorBarProp( GetPropertySet()); 159 160 SvxChartKindError eErrorKind = 161 static_cast< const SvxChartKindErrorItem & >( 162 rItemSet.Get( nWhichId )).GetValue(); 163 164 if( !xErrorBarProp.is() && eErrorKind == CHERROR_NONE) 165 { 166 //nothing to do 167 } 168 else 169 { 170 sal_Int32 nStyle = ::com::sun::star::chart::ErrorBarStyle::NONE; 171 172 switch( eErrorKind ) 173 { 174 case CHERROR_NONE: 175 nStyle = ::com::sun::star::chart::ErrorBarStyle::NONE; break; 176 case CHERROR_VARIANT: 177 nStyle = ::com::sun::star::chart::ErrorBarStyle::VARIANCE; break; 178 case CHERROR_SIGMA: 179 nStyle = ::com::sun::star::chart::ErrorBarStyle::STANDARD_DEVIATION; break; 180 case CHERROR_PERCENT: 181 nStyle = ::com::sun::star::chart::ErrorBarStyle::RELATIVE; break; 182 case CHERROR_BIGERROR: 183 nStyle = ::com::sun::star::chart::ErrorBarStyle::ERROR_MARGIN; break; 184 case CHERROR_CONST: 185 nStyle = ::com::sun::star::chart::ErrorBarStyle::ABSOLUTE; break; 186 case CHERROR_STDERROR: 187 nStyle = ::com::sun::star::chart::ErrorBarStyle::STANDARD_ERROR; break; 188 case CHERROR_RANGE: 189 nStyle = ::com::sun::star::chart::ErrorBarStyle::FROM_DATA; break; 190 } 191 192 xErrorBarProp->setPropertyValue( C2U( "ErrorBarStyle" ), 193 uno::makeAny( nStyle )); 194 bChanged = true; 195 } 196 } 197 break; 198 199 case SCHATTR_STAT_PERCENT: 200 case SCHATTR_STAT_BIGERROR: 201 { 202 OSL_ENSURE( false, "Deprecated item" ); 203 uno::Reference< beans::XPropertySet > xErrorBarProp( GetPropertySet()); 204 205 double fValue = 206 static_cast< const SvxDoubleItem & >( 207 rItemSet.Get( nWhichId )).GetValue(); 208 double fPos, fNeg; 209 lcl_getErrorValues( xErrorBarProp, fPos, fNeg ); 210 211 if( ! ( ::rtl::math::approxEqual( fPos, fValue ) && 212 ::rtl::math::approxEqual( fNeg, fValue ))) 213 { 214 xErrorBarProp->setPropertyValue( C2U( "PositiveError" ), 215 uno::makeAny( fValue )); 216 xErrorBarProp->setPropertyValue( C2U( "NegativeError" ), 217 uno::makeAny( fValue )); 218 bChanged = true; 219 } 220 } 221 break; 222 223 case SCHATTR_STAT_CONSTPLUS: 224 { 225 double fValue = 226 static_cast< const SvxDoubleItem & >( 227 rItemSet.Get( nWhichId )).GetValue(); 228 double fPos, fNeg; 229 lcl_getErrorValues( GetPropertySet(), fPos, fNeg ); 230 231 if( ! ::rtl::math::approxEqual( fPos, fValue )) 232 { 233 GetPropertySet()->setPropertyValue( C2U( "PositiveError" ), uno::makeAny( fValue )); 234 bChanged = true; 235 } 236 } 237 break; 238 239 case SCHATTR_STAT_CONSTMINUS: 240 { 241 uno::Reference< beans::XPropertySet > xErrorBarProp( GetPropertySet()); 242 243 double fValue = 244 static_cast< const SvxDoubleItem & >( 245 rItemSet.Get( nWhichId )).GetValue(); 246 double fPos, fNeg; 247 lcl_getErrorValues( xErrorBarProp, fPos, fNeg ); 248 249 if( ! ::rtl::math::approxEqual( fNeg, fValue )) 250 { 251 xErrorBarProp->setPropertyValue( C2U( "NegativeError" ), uno::makeAny( fValue )); 252 bChanged = true; 253 } 254 } 255 break; 256 257 case SCHATTR_STAT_INDICATE: 258 { 259 uno::Reference< beans::XPropertySet > xErrorBarProp( GetPropertySet()); 260 261 SvxChartIndicate eIndicate = 262 static_cast< const SvxChartIndicateItem & >( 263 rItemSet.Get( nWhichId )).GetValue(); 264 265 bool bNewIndPos = (eIndicate == CHINDICATE_BOTH || eIndicate == CHINDICATE_UP ); 266 bool bNewIndNeg = (eIndicate == CHINDICATE_BOTH || eIndicate == CHINDICATE_DOWN ); 267 268 bool bShowPos, bShowNeg; 269 lcl_getErrorIndicatorValues( xErrorBarProp, bShowPos, bShowNeg ); 270 271 if( ( bShowPos != bNewIndPos || 272 bShowNeg != bNewIndNeg )) 273 { 274 xErrorBarProp->setPropertyValue( C2U( "ShowPositiveError" ), uno::makeAny( bNewIndPos )); 275 xErrorBarProp->setPropertyValue( C2U( "ShowNegativeError" ), uno::makeAny( bNewIndNeg )); 276 bChanged = true; 277 } 278 } 279 break; 280 281 case SCHATTR_STAT_RANGE_POS: 282 case SCHATTR_STAT_RANGE_NEG: 283 { 284 // @todo: also be able to deal with x-error bars 285 const bool bYError = true; 286 uno::Reference< chart2::data::XDataSource > xErrorBarSource( GetPropertySet(), uno::UNO_QUERY ); 287 uno::Reference< chart2::XChartDocument > xChartDoc( m_xModel, uno::UNO_QUERY ); 288 uno::Reference< chart2::data::XDataProvider > xDataProvider; 289 290 if( xChartDoc.is()) 291 xDataProvider.set( xChartDoc->getDataProvider()); 292 if( xErrorBarSource.is() && xDataProvider.is()) 293 { 294 ::rtl::OUString aNewRange( static_cast< const SfxStringItem & >( rItemSet.Get( nWhichId )).GetValue()); 295 bool bApplyNewRange = false; 296 297 bool bIsPositiveValue( nWhichId == SCHATTR_STAT_RANGE_POS ); 298 if( xChartDoc->hasInternalDataProvider()) 299 { 300 if( !aNewRange.isEmpty() ) 301 { 302 uno::Reference< chart2::data::XDataSequence > xSeq( 303 StatisticsHelper::getErrorDataSequenceFromDataSource( 304 xErrorBarSource, bIsPositiveValue, bYError )); 305 if( ! xSeq.is()) 306 { 307 // no data range for error bars yet => create 308 uno::Reference< chart2::XInternalDataProvider > xIntDataProvider( xDataProvider, uno::UNO_QUERY ); 309 OSL_ASSERT( xIntDataProvider.is()); 310 if( xIntDataProvider.is()) 311 { 312 xIntDataProvider->appendSequence(); 313 aNewRange = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("last")); 314 bApplyNewRange = true; 315 } 316 } 317 } 318 } 319 else 320 { 321 uno::Reference< chart2::data::XDataSequence > xSeq( 322 StatisticsHelper::getErrorDataSequenceFromDataSource( 323 xErrorBarSource, bIsPositiveValue, bYError )); 324 bApplyNewRange = 325 ! ( xSeq.is() && aNewRange.equals( xSeq->getSourceRangeRepresentation())); 326 } 327 328 if( bApplyNewRange ) 329 StatisticsHelper::setErrorDataSequence( 330 xErrorBarSource, xDataProvider, aNewRange, bIsPositiveValue, bYError ); 331 } 332 } 333 break; 334 } 335 336 return bChanged; 337 } 338 339 void ErrorBarItemConverter::FillSpecialItem( 340 sal_uInt16 nWhichId, SfxItemSet & rOutItemSet ) const 341 { 342 switch( nWhichId ) 343 { 344 case SCHATTR_STAT_KIND_ERROR: 345 { 346 SvxChartKindError eErrorKind = CHERROR_NONE; 347 uno::Reference< beans::XPropertySet > xErrorBarProp( GetPropertySet()); 348 349 sal_Int32 nStyle = 0; 350 if( xErrorBarProp->getPropertyValue( C2U( "ErrorBarStyle" )) >>= nStyle ) 351 { 352 switch( nStyle ) 353 { 354 case ::com::sun::star::chart::ErrorBarStyle::NONE: 355 break; 356 case ::com::sun::star::chart::ErrorBarStyle::VARIANCE: 357 eErrorKind = CHERROR_VARIANT; break; 358 case ::com::sun::star::chart::ErrorBarStyle::STANDARD_DEVIATION: 359 eErrorKind = CHERROR_SIGMA; break; 360 case ::com::sun::star::chart::ErrorBarStyle::ABSOLUTE: 361 eErrorKind = CHERROR_CONST; break; 362 case ::com::sun::star::chart::ErrorBarStyle::RELATIVE: 363 eErrorKind = CHERROR_PERCENT; break; 364 case ::com::sun::star::chart::ErrorBarStyle::ERROR_MARGIN: 365 eErrorKind = CHERROR_BIGERROR; break; 366 case ::com::sun::star::chart::ErrorBarStyle::STANDARD_ERROR: 367 eErrorKind = CHERROR_STDERROR; break; 368 case ::com::sun::star::chart::ErrorBarStyle::FROM_DATA: 369 eErrorKind = CHERROR_RANGE; break; 370 } 371 } 372 rOutItemSet.Put( SvxChartKindErrorItem( eErrorKind, SCHATTR_STAT_KIND_ERROR )); 373 } 374 break; 375 376 case SCHATTR_STAT_PERCENT: 377 { 378 double fPos, fNeg; 379 lcl_getErrorValues( GetPropertySet(), fPos, fNeg ); 380 rOutItemSet.Put( SvxDoubleItem( ( fPos + fNeg ) / 2.0, nWhichId )); 381 } 382 break; 383 384 case SCHATTR_STAT_BIGERROR: 385 { 386 double fPos, fNeg; 387 lcl_getErrorValues( GetPropertySet(), fPos, fNeg ); 388 rOutItemSet.Put( SvxDoubleItem( ( fPos + fNeg ) / 2.0, nWhichId )); 389 } 390 break; 391 392 case SCHATTR_STAT_CONSTPLUS: 393 { 394 double fPos, fNeg; 395 lcl_getErrorValues( GetPropertySet(), fPos, fNeg ); 396 rOutItemSet.Put( SvxDoubleItem( fPos, nWhichId )); 397 } 398 break; 399 400 case SCHATTR_STAT_CONSTMINUS: 401 { 402 double fPos, fNeg; 403 lcl_getErrorValues( GetPropertySet(), fPos, fNeg ); 404 rOutItemSet.Put( SvxDoubleItem( fNeg, nWhichId )); 405 } 406 break; 407 408 case SCHATTR_STAT_INDICATE: 409 { 410 SvxChartIndicate eIndicate = CHINDICATE_BOTH; 411 bool bShowPos, bShowNeg; 412 lcl_getErrorIndicatorValues( GetPropertySet(), bShowPos, bShowNeg ); 413 414 if( bShowPos ) 415 { 416 if( bShowNeg ) 417 eIndicate = CHINDICATE_BOTH; 418 else 419 eIndicate = CHINDICATE_UP; 420 } 421 else 422 { 423 if( bShowNeg ) 424 eIndicate = CHINDICATE_DOWN; 425 else 426 eIndicate = CHINDICATE_NONE; 427 } 428 rOutItemSet.Put( SvxChartIndicateItem( eIndicate, SCHATTR_STAT_INDICATE )); 429 } 430 break; 431 432 case SCHATTR_STAT_RANGE_POS: 433 case SCHATTR_STAT_RANGE_NEG: 434 { 435 uno::Reference< chart2::data::XDataSource > xErrorBarSource( GetPropertySet(), uno::UNO_QUERY ); 436 if( xErrorBarSource.is()) 437 { 438 uno::Reference< chart2::data::XDataSequence > xSeq( 439 StatisticsHelper::getErrorDataSequenceFromDataSource( 440 xErrorBarSource, (nWhichId == SCHATTR_STAT_RANGE_POS) /*, true */ /* y */ )); 441 if( xSeq.is()) 442 rOutItemSet.Put( SfxStringItem( nWhichId, String( xSeq->getSourceRangeRepresentation()))); 443 } 444 } 445 break; 446 } 447 } 448 449 } // namespace wrapper 450 } // namespace chart 451