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 #include "oox/drawingml/chart/seriesconverter.hxx" 29 30 #include <com/sun/star/chart/DataLabelPlacement.hpp> 31 #include <com/sun/star/chart/ErrorBarStyle.hpp> 32 #include <com/sun/star/chart2/DataPointLabel.hpp> 33 #include <com/sun/star/chart2/XDataSeries.hpp> 34 #include <com/sun/star/chart2/XRegressionCurve.hpp> 35 #include <com/sun/star/chart2/XRegressionCurveContainer.hpp> 36 #include <com/sun/star/chart2/data/XDataSink.hpp> 37 #include "oox/drawingml/chart/datasourceconverter.hxx" 38 #include "oox/drawingml/chart/seriesmodel.hxx" 39 #include "oox/drawingml/chart/titleconverter.hxx" 40 #include "oox/drawingml/chart/typegroupconverter.hxx" 41 #include "oox/drawingml/chart/typegroupmodel.hxx" 42 #include "oox/helper/containerhelper.hxx" 43 44 namespace oox { 45 namespace drawingml { 46 namespace chart { 47 48 // ============================================================================ 49 50 using namespace ::com::sun::star::beans; 51 using namespace ::com::sun::star::chart2; 52 using namespace ::com::sun::star::chart2::data; 53 using namespace ::com::sun::star::uno; 54 55 using ::rtl::OUString; 56 57 // ============================================================================ 58 59 namespace { 60 61 Reference< XLabeledDataSequence > lclCreateLabeledDataSequence( 62 const ConverterRoot& rParent, 63 DataSourceModel* pValues, const OUString& rRole, 64 TextModel* pTitle = 0 ) 65 { 66 // create data sequence for values 67 Reference< XDataSequence > xValueSeq; 68 if( pValues ) 69 { 70 DataSourceConverter aSourceConv( rParent, *pValues ); 71 xValueSeq = aSourceConv.createDataSequence( rRole ); 72 } 73 74 // create data sequence for title 75 Reference< XDataSequence > xTitleSeq; 76 if( pTitle ) 77 { 78 TextConverter aTextConv( rParent, *pTitle ); 79 xTitleSeq = aTextConv.createDataSequence( CREATE_OUSTRING( "label" ) ); 80 } 81 82 // create the labeled data sequence, if values or title are present 83 Reference< XLabeledDataSequence > xLabeledSeq; 84 if( xValueSeq.is() || xTitleSeq.is() ) 85 { 86 xLabeledSeq.set( rParent.createInstance( CREATE_OUSTRING( "com.sun.star.chart2.data.LabeledDataSequence" ) ), UNO_QUERY ); 87 if( xLabeledSeq.is() ) 88 { 89 xLabeledSeq->setValues( xValueSeq ); 90 xLabeledSeq->setLabel( xTitleSeq ); 91 } 92 } 93 return xLabeledSeq; 94 } 95 96 void lclConvertLabelFormatting( PropertySet& rPropSet, ObjectFormatter& rFormatter, 97 const DataLabelModelBase& rDataLabel, const TypeGroupConverter& rTypeGroup, bool bDataSeriesLabel ) 98 { 99 const TypeGroupInfo& rTypeInfo = rTypeGroup.getTypeInfo(); 100 101 /* Excel 2007 does not change the series setting for a single data point, 102 if none of some specific elements occur. But only one existing element 103 in a data point will reset most other of these elements from the series 104 (e.g.: series has <c:showVal>, data point has <c:showCatName>, this 105 will reset <c:showVal> for this point, unless <c:showVal> is repeated 106 in the data point). The elements <c:layout>, <c:numberFormat>, 107 <c:spPr>, <c:tx>, and <c:txPr> are not affected at all. */ 108 bool bHasAnyElement = 109 rDataLabel.moaSeparator.has() || rDataLabel.monLabelPos.has() || 110 rDataLabel.mobShowCatName.has() || rDataLabel.mobShowLegendKey.has() || 111 rDataLabel.mobShowPercent.has() || rDataLabel.mobShowSerName.has() || 112 rDataLabel.mobShowVal.has(); 113 114 bool bShowValue = !rDataLabel.mbDeleted && rDataLabel.mobShowVal.get( false ); 115 bool bShowPercent = !rDataLabel.mbDeleted && rDataLabel.mobShowPercent.get( false ) && (rTypeInfo.meTypeCategory == TYPECATEGORY_PIE); 116 bool bShowCateg = !rDataLabel.mbDeleted && rDataLabel.mobShowCatName.get( false ); 117 bool bShowSymbol = !rDataLabel.mbDeleted && rDataLabel.mobShowLegendKey.get( false ); 118 119 // type of attached label 120 if( bHasAnyElement || rDataLabel.mbDeleted ) 121 { 122 DataPointLabel aPointLabel( bShowValue, bShowPercent, bShowCateg, bShowSymbol ); 123 rPropSet.setProperty( PROP_Label, aPointLabel ); 124 } 125 126 if( !rDataLabel.mbDeleted ) 127 { 128 // data label number format (percentage format wins over value format) 129 rFormatter.convertNumberFormat( rPropSet, rDataLabel.maNumberFormat, bShowPercent ); 130 131 // data label text formatting (frame formatting not supported by Chart2) 132 rFormatter.convertTextFormatting( rPropSet, rDataLabel.mxTextProp, OBJECTTYPE_DATALABEL ); 133 rFormatter.convertTextRotation( rPropSet, rDataLabel.mxTextProp, false ); 134 135 // data label separator (do not overwrite series separator, if no explicit point separator is present) 136 if( bDataSeriesLabel || rDataLabel.moaSeparator.has() ) 137 rPropSet.setProperty( PROP_LabelSeparator, rDataLabel.moaSeparator.get( CREATE_OUSTRING( "; " ) ) ); 138 139 // data label placement (do not overwrite series placement, if no explicit point placement is present) 140 if( bDataSeriesLabel || rDataLabel.monLabelPos.has() ) 141 { 142 namespace csscd = ::com::sun::star::chart::DataLabelPlacement; 143 sal_Int32 nPlacement = rTypeInfo.mnDefLabelPos; 144 switch( rDataLabel.monLabelPos.get( XML_TOKEN_INVALID ) ) 145 { 146 case XML_outEnd: nPlacement = csscd::OUTSIDE; break; 147 case XML_inEnd: nPlacement = csscd::INSIDE; break; 148 case XML_ctr: nPlacement = csscd::CENTER; break; 149 case XML_inBase: nPlacement = csscd::NEAR_ORIGIN; break; 150 case XML_t: nPlacement = csscd::TOP; break; 151 case XML_b: nPlacement = csscd::BOTTOM; break; 152 case XML_l: nPlacement = csscd::LEFT; break; 153 case XML_r: nPlacement = csscd::RIGHT; break; 154 case XML_bestFit: nPlacement = csscd::AVOID_OVERLAP; break; 155 } 156 rPropSet.setProperty( PROP_LabelPlacement, nPlacement ); 157 } 158 } 159 } 160 161 } // namespace 162 163 // ============================================================================ 164 165 DataLabelConverter::DataLabelConverter( const ConverterRoot& rParent, DataLabelModel& rModel ) : 166 ConverterBase< DataLabelModel >( rParent, rModel ) 167 { 168 } 169 170 DataLabelConverter::~DataLabelConverter() 171 { 172 } 173 174 void DataLabelConverter::convertFromModel( const Reference< XDataSeries >& rxDataSeries, const TypeGroupConverter& rTypeGroup ) 175 { 176 if( rxDataSeries.is() ) try 177 { 178 PropertySet aPropSet( rxDataSeries->getDataPointByIndex( mrModel.mnIndex ) ); 179 lclConvertLabelFormatting( aPropSet, getFormatter(), mrModel, rTypeGroup, false ); 180 } 181 catch( Exception& ) 182 { 183 } 184 } 185 186 // ============================================================================ 187 188 DataLabelsConverter::DataLabelsConverter( const ConverterRoot& rParent, DataLabelsModel& rModel ) : 189 ConverterBase< DataLabelsModel >( rParent, rModel ) 190 { 191 } 192 193 DataLabelsConverter::~DataLabelsConverter() 194 { 195 } 196 197 void DataLabelsConverter::convertFromModel( const Reference< XDataSeries >& rxDataSeries, const TypeGroupConverter& rTypeGroup ) 198 { 199 if( !mrModel.mbDeleted ) 200 { 201 PropertySet aPropSet( rxDataSeries ); 202 lclConvertLabelFormatting( aPropSet, getFormatter(), mrModel, rTypeGroup, true ); 203 } 204 205 // data point label settings 206 for( DataLabelsModel::DataLabelVector::iterator aIt = mrModel.maPointLabels.begin(), aEnd = mrModel.maPointLabels.end(); aIt != aEnd; ++aIt ) 207 { 208 DataLabelConverter aLabelConv( *this, **aIt ); 209 aLabelConv.convertFromModel( rxDataSeries, rTypeGroup ); 210 } 211 } 212 213 // ============================================================================ 214 215 ErrorBarConverter::ErrorBarConverter( const ConverterRoot& rParent, ErrorBarModel& rModel ) : 216 ConverterBase< ErrorBarModel >( rParent, rModel ) 217 { 218 } 219 220 ErrorBarConverter::~ErrorBarConverter() 221 { 222 } 223 224 void ErrorBarConverter::convertFromModel( const Reference< XDataSeries >& rxDataSeries ) 225 { 226 bool bShowPos = (mrModel.mnTypeId == XML_plus) || (mrModel.mnTypeId == XML_both); 227 bool bShowNeg = (mrModel.mnTypeId == XML_minus) || (mrModel.mnTypeId == XML_both); 228 if( bShowPos || bShowNeg ) try 229 { 230 Reference< XPropertySet > xErrorBar( createInstance( CREATE_OUSTRING( "com.sun.star.chart2.ErrorBar" ) ), UNO_QUERY_THROW ); 231 PropertySet aBarProp( xErrorBar ); 232 233 // plus/minus bars 234 aBarProp.setProperty( PROP_ShowPositiveError, bShowPos ); 235 aBarProp.setProperty( PROP_ShowNegativeError, bShowNeg ); 236 237 // type of displayed error 238 namespace cssc = ::com::sun::star::chart; 239 switch( mrModel.mnValueType ) 240 { 241 case XML_cust: 242 { 243 // #i87806# manual error bars 244 aBarProp.setProperty( PROP_ErrorBarStyle, cssc::ErrorBarStyle::FROM_DATA ); 245 // attach data sequences to erorr bar 246 Reference< XDataSink > xDataSink( xErrorBar, UNO_QUERY ); 247 if( xDataSink.is() ) 248 { 249 // create vector of all value sequences 250 ::std::vector< Reference< XLabeledDataSequence > > aLabeledSeqVec; 251 // add positive values 252 if( bShowPos ) 253 { 254 Reference< XLabeledDataSequence > xValueSeq = createLabeledDataSequence( ErrorBarModel::PLUS ); 255 if( xValueSeq.is() ) 256 aLabeledSeqVec.push_back( xValueSeq ); 257 } 258 // add negative values 259 if( bShowNeg ) 260 { 261 Reference< XLabeledDataSequence > xValueSeq = createLabeledDataSequence( ErrorBarModel::MINUS ); 262 if( xValueSeq.is() ) 263 aLabeledSeqVec.push_back( xValueSeq ); 264 } 265 // attach labeled data sequences to series 266 if( aLabeledSeqVec.empty() ) 267 xErrorBar.clear(); 268 else 269 xDataSink->setData( ContainerHelper::vectorToSequence( aLabeledSeqVec ) ); 270 } 271 } 272 break; 273 case XML_fixedVal: 274 aBarProp.setProperty( PROP_ErrorBarStyle, cssc::ErrorBarStyle::ABSOLUTE ); 275 aBarProp.setProperty( PROP_PositiveError, mrModel.mfValue ); 276 aBarProp.setProperty( PROP_NegativeError, mrModel.mfValue ); 277 break; 278 case XML_percentage: 279 aBarProp.setProperty( PROP_ErrorBarStyle, cssc::ErrorBarStyle::RELATIVE ); 280 aBarProp.setProperty( PROP_PositiveError, mrModel.mfValue ); 281 aBarProp.setProperty( PROP_NegativeError, mrModel.mfValue ); 282 break; 283 case XML_stdDev: 284 aBarProp.setProperty( PROP_ErrorBarStyle, cssc::ErrorBarStyle::STANDARD_DEVIATION ); 285 aBarProp.setProperty( PROP_Weight, mrModel.mfValue ); 286 break; 287 case XML_stdErr: 288 aBarProp.setProperty( PROP_ErrorBarStyle, cssc::ErrorBarStyle::STANDARD_ERROR ); 289 break; 290 default: 291 OSL_ENSURE( false, "ErrorBarConverter::convertFromModel - unknown error bar type" ); 292 xErrorBar.clear(); 293 } 294 295 // error bar formatting 296 getFormatter().convertFrameFormatting( aBarProp, mrModel.mxShapeProp, OBJECTTYPE_ERRORBAR ); 297 298 if( xErrorBar.is() ) 299 { 300 PropertySet aSeriesProp( rxDataSeries ); 301 switch( mrModel.mnDirection ) 302 { 303 case XML_x: aSeriesProp.setProperty( PROP_ErrorBarX, xErrorBar ); break; 304 case XML_y: aSeriesProp.setProperty( PROP_ErrorBarY, xErrorBar ); break; 305 default: OSL_ENSURE( false, "ErrorBarConverter::convertFromModel - invalid error bar direction" ); 306 } 307 } 308 } 309 catch( Exception& ) 310 { 311 OSL_ENSURE( false, "ErrorBarConverter::convertFromModel - error while creating error bars" ); 312 } 313 } 314 315 // private -------------------------------------------------------------------- 316 317 Reference< XLabeledDataSequence > ErrorBarConverter::createLabeledDataSequence( ErrorBarModel::SourceType eSourceType ) 318 { 319 OUString aRole; 320 switch( eSourceType ) 321 { 322 case ErrorBarModel::PLUS: 323 switch( mrModel.mnDirection ) 324 { 325 case XML_x: aRole = CREATE_OUSTRING( "error-bars-x-positive" ); break; 326 case XML_y: aRole = CREATE_OUSTRING( "error-bars-y-positive" ); break; 327 } 328 break; 329 case ErrorBarModel::MINUS: 330 switch( mrModel.mnDirection ) 331 { 332 case XML_x: aRole = CREATE_OUSTRING( "error-bars-x-negative" ); break; 333 case XML_y: aRole = CREATE_OUSTRING( "error-bars-y-negative" ); break; 334 } 335 break; 336 } 337 OSL_ENSURE( aRole.getLength() > 0, "ErrorBarConverter::createLabeledDataSequence - invalid error bar direction" ); 338 return lclCreateLabeledDataSequence( *this, mrModel.maSources.get( eSourceType ).get(), aRole ); 339 } 340 341 // ============================================================================ 342 343 TrendlineLabelConverter::TrendlineLabelConverter( const ConverterRoot& rParent, TrendlineLabelModel& rModel ) : 344 ConverterBase< TrendlineLabelModel >( rParent, rModel ) 345 { 346 } 347 348 TrendlineLabelConverter::~TrendlineLabelConverter() 349 { 350 } 351 352 void TrendlineLabelConverter::convertFromModel( PropertySet& rPropSet ) 353 { 354 // formatting 355 getFormatter().convertFormatting( rPropSet, mrModel.mxShapeProp, mrModel.mxTextProp, OBJECTTYPE_TRENDLINELABEL ); 356 } 357 358 // ============================================================================ 359 360 TrendlineConverter::TrendlineConverter( const ConverterRoot& rParent, TrendlineModel& rModel ) : 361 ConverterBase< TrendlineModel >( rParent, rModel ) 362 { 363 } 364 365 TrendlineConverter::~TrendlineConverter() 366 { 367 } 368 369 void TrendlineConverter::convertFromModel( const Reference< XDataSeries >& rxDataSeries ) 370 { 371 try 372 { 373 // trend line type 374 OUString aServiceName; 375 switch( mrModel.mnTypeId ) 376 { 377 case XML_exp: aServiceName = CREATE_OUSTRING( "com.sun.star.chart2.ExponentialRegressionCurve" ); break; 378 case XML_linear: aServiceName = CREATE_OUSTRING( "com.sun.star.chart2.LinearRegressionCurve" ); break; 379 case XML_log: aServiceName = CREATE_OUSTRING( "com.sun.star.chart2.LogarithmicRegressionCurve" ); break; 380 case XML_movingAvg: /* #i66819# moving average trendlines not supported */ break; 381 case XML_poly: /* #i20819# polynomial trendlines not supported */ break; 382 case XML_power: aServiceName = CREATE_OUSTRING( "com.sun.star.chart2.PotentialRegressionCurve" ); break; 383 default: OSL_ENSURE( false, "TrendlineConverter::convertFromModel - unknown trendline type" ); 384 } 385 if( aServiceName.getLength() > 0 ) 386 { 387 Reference< XRegressionCurve > xRegCurve( createInstance( aServiceName ), UNO_QUERY_THROW ); 388 PropertySet aPropSet( xRegCurve ); 389 390 // trendline formatting 391 getFormatter().convertFrameFormatting( aPropSet, mrModel.mxShapeProp, OBJECTTYPE_TRENDLINE ); 392 393 // #i83100# show equation and correlation coefficient 394 PropertySet aLabelProp( xRegCurve->getEquationProperties() ); 395 aLabelProp.setProperty( PROP_ShowEquation, mrModel.mbDispEquation ); 396 aLabelProp.setProperty( PROP_ShowCorrelationCoefficient, mrModel.mbDispRSquared ); 397 398 // #i83100# formatting of the equation text box 399 if( mrModel.mbDispEquation || mrModel.mbDispRSquared ) 400 { 401 TrendlineLabelConverter aLabelConv( *this, mrModel.mxLabel.getOrCreate() ); 402 aLabelConv.convertFromModel( aLabelProp ); 403 } 404 405 // unsupported: #i5085# manual trendline size 406 // unsupported: #i34093# manual crossing point 407 408 Reference< XRegressionCurveContainer > xRegCurveCont( rxDataSeries, UNO_QUERY_THROW ); 409 xRegCurveCont->addRegressionCurve( xRegCurve ); 410 } 411 } 412 catch( Exception& ) 413 { 414 OSL_ENSURE( false, "TrendlineConverter::convertFromModel - error while creating trendline" ); 415 } 416 } 417 418 // ============================================================================ 419 420 DataPointConverter::DataPointConverter( const ConverterRoot& rParent, DataPointModel& rModel ) : 421 ConverterBase< DataPointModel >( rParent, rModel ) 422 { 423 } 424 425 DataPointConverter::~DataPointConverter() 426 { 427 } 428 429 void DataPointConverter::convertFromModel( const Reference< XDataSeries >& rxDataSeries, 430 const TypeGroupConverter& rTypeGroup, const SeriesModel& rSeries ) 431 { 432 try 433 { 434 PropertySet aPropSet( rxDataSeries->getDataPointByIndex( mrModel.mnIndex ) ); 435 436 // data point marker 437 if( mrModel.monMarkerSymbol.differsFrom( rSeries.mnMarkerSymbol ) || mrModel.monMarkerSize.differsFrom( rSeries.mnMarkerSize ) ) 438 rTypeGroup.convertMarker( aPropSet, mrModel.monMarkerSymbol.get( rSeries.mnMarkerSymbol ), mrModel.monMarkerSize.get( rSeries.mnMarkerSize ) ); 439 440 // data point pie explosion 441 if( mrModel.monExplosion.differsFrom( rSeries.mnExplosion ) ) 442 rTypeGroup.convertPieExplosion( aPropSet, mrModel.monExplosion.get() ); 443 444 // point formatting 445 if( mrModel.mxShapeProp.is() ) 446 { 447 if( rTypeGroup.getTypeInfo().mbPictureOptions ) 448 getFormatter().convertFrameFormatting( aPropSet, mrModel.mxShapeProp, mrModel.mxPicOptions.getOrCreate(), rTypeGroup.getSeriesObjectType(), rSeries.mnIndex ); 449 else 450 getFormatter().convertFrameFormatting( aPropSet, mrModel.mxShapeProp, rTypeGroup.getSeriesObjectType(), rSeries.mnIndex ); 451 } 452 } 453 catch( Exception& ) 454 { 455 } 456 } 457 458 // ============================================================================ 459 460 SeriesConverter::SeriesConverter( const ConverterRoot& rParent, SeriesModel& rModel ) : 461 ConverterBase< SeriesModel >( rParent, rModel ) 462 { 463 } 464 465 SeriesConverter::~SeriesConverter() 466 { 467 } 468 469 Reference< XLabeledDataSequence > SeriesConverter::createCategorySequence( const OUString& rRole ) 470 { 471 return createLabeledDataSequence( SeriesModel::CATEGORIES, rRole, false ); 472 } 473 474 Reference< XLabeledDataSequence > SeriesConverter::createValueSequence( const OUString& rRole ) 475 { 476 return createLabeledDataSequence( SeriesModel::VALUES, rRole, true ); 477 } 478 479 Reference< XDataSeries > SeriesConverter::createDataSeries( const TypeGroupConverter& rTypeGroup, bool bVaryColorsByPoint ) 480 { 481 const TypeGroupInfo& rTypeInfo = rTypeGroup.getTypeInfo(); 482 483 // create the data series object 484 Reference< XDataSeries > xDataSeries( createInstance( CREATE_OUSTRING( "com.sun.star.chart2.DataSeries" ) ), UNO_QUERY ); 485 PropertySet aSeriesProp( xDataSeries ); 486 487 // attach data and title sequences to series 488 sal_Int32 nDataPointCount = 0; 489 Reference< XDataSink > xDataSink( xDataSeries, UNO_QUERY ); 490 if( xDataSink.is() ) 491 { 492 // create vector of all value sequences 493 ::std::vector< Reference< XLabeledDataSequence > > aLabeledSeqVec; 494 // add Y values 495 Reference< XLabeledDataSequence > xYValueSeq = createValueSequence( CREATE_OUSTRING( "values-y" ) ); 496 if( xYValueSeq.is() ) 497 { 498 aLabeledSeqVec.push_back( xYValueSeq ); 499 Reference< XDataSequence > xValues = xYValueSeq->getValues(); 500 if( xValues.is() ) 501 nDataPointCount = xValues->getData().getLength(); 502 } 503 // add X values of scatter and bubble charts 504 if( !rTypeInfo.mbCategoryAxis ) 505 { 506 Reference< XLabeledDataSequence > xXValueSeq = createCategorySequence( CREATE_OUSTRING( "values-x" ) ); 507 if( xXValueSeq.is() ) 508 aLabeledSeqVec.push_back( xXValueSeq ); 509 // add size values of bubble charts 510 if( rTypeInfo.meTypeId == TYPEID_BUBBLE ) 511 { 512 Reference< XLabeledDataSequence > xSizeValueSeq = createLabeledDataSequence( SeriesModel::POINTS, CREATE_OUSTRING( "values-size" ), true ); 513 if( xSizeValueSeq.is() ) 514 aLabeledSeqVec.push_back( xSizeValueSeq ); 515 } 516 } 517 // attach labeled data sequences to series 518 if( !aLabeledSeqVec.empty() ) 519 xDataSink->setData( ContainerHelper::vectorToSequence( aLabeledSeqVec ) ); 520 } 521 522 // error bars 523 for( SeriesModel::ErrorBarVector::iterator aIt = mrModel.maErrorBars.begin(), aEnd = mrModel.maErrorBars.end(); aIt != aEnd; ++aIt ) 524 { 525 ErrorBarConverter aErrorBarConv( *this, **aIt ); 526 aErrorBarConv.convertFromModel( xDataSeries ); 527 } 528 529 // trendlines 530 for( SeriesModel::TrendlineVector::iterator aIt = mrModel.maTrendlines.begin(), aEnd = mrModel.maTrendlines.end(); aIt != aEnd; ++aIt ) 531 { 532 TrendlineConverter aTrendlineConv( *this, **aIt ); 533 aTrendlineConv.convertFromModel( xDataSeries ); 534 } 535 536 // data point markers 537 rTypeGroup.convertMarker( aSeriesProp, mrModel.mnMarkerSymbol, mrModel.mnMarkerSize ); 538 #if OOX_CHART_SMOOTHED_PER_SERIES 539 // #i66858# smoothed series lines 540 rTypeGroup.convertLineSmooth( aSeriesProp, mrModel.mbSmooth ); 541 #endif 542 // 3D bar style (not possible to set at chart type -> set at all series) 543 rTypeGroup.convertBarGeometry( aSeriesProp, mrModel.monShape.get( rTypeGroup.getModel().mnShape ) ); 544 // pie explosion (restricted to [0%,100%] in Chart2) 545 rTypeGroup.convertPieExplosion( aSeriesProp, mrModel.mnExplosion ); 546 547 // series formatting 548 ObjectFormatter& rFormatter = getFormatter(); 549 ObjectType eObjType = rTypeGroup.getSeriesObjectType(); 550 if( rTypeInfo.mbPictureOptions ) 551 rFormatter.convertFrameFormatting( aSeriesProp, mrModel.mxShapeProp, mrModel.mxPicOptions.getOrCreate(), eObjType, mrModel.mnIndex ); 552 else 553 rFormatter.convertFrameFormatting( aSeriesProp, mrModel.mxShapeProp, eObjType, mrModel.mnIndex ); 554 555 // set the (unused) property default value used by the Chart2 templates (true for pie/doughnut charts) 556 bool bIsPie = rTypeInfo.meTypeCategory == TYPECATEGORY_PIE; 557 aSeriesProp.setProperty( PROP_VaryColorsByPoint, bIsPie ); 558 559 // own area formatting for every data point (TODO: varying line color not supported) 560 // #i91271# always set area formatting for every point in pie/doughnut charts to override their automatic point formatting 561 if( bIsPie || (bVaryColorsByPoint && rTypeGroup.isSeriesFrameFormat() && ObjectFormatter::isAutomaticFill( mrModel.mxShapeProp )) ) 562 { 563 /* Set the series point number as color cycle size at the object 564 formatter to get correct start-shade/end-tint. TODO: in doughnut 565 charts, the sizes of the series may vary, need to use the maximum 566 point count of all series. */ 567 sal_Int32 nOldMax = rFormatter.getMaxSeriesIndex(); 568 if( bVaryColorsByPoint ) 569 rFormatter.setMaxSeriesIndex( nDataPointCount - 1 ); 570 for( sal_Int32 nIndex = 0; nIndex < nDataPointCount; ++nIndex ) 571 { 572 try 573 { 574 PropertySet aPointProp( xDataSeries->getDataPointByIndex( nIndex ) ); 575 rFormatter.convertAutomaticFill( aPointProp, eObjType, bVaryColorsByPoint ? nIndex : mrModel.mnIndex ); 576 } 577 catch( Exception& ) 578 { 579 } 580 } 581 rFormatter.setMaxSeriesIndex( nOldMax ); 582 } 583 584 // data point settings 585 for( SeriesModel::DataPointVector::iterator aIt = mrModel.maPoints.begin(), aEnd = mrModel.maPoints.end(); aIt != aEnd; ++aIt ) 586 { 587 DataPointConverter aPointConv( *this, **aIt ); 588 aPointConv.convertFromModel( xDataSeries, rTypeGroup, mrModel ); 589 } 590 591 /* Series data label settings. If and only if the series does not contain 592 a c:dLbls element, then the c:dLbls element of the parent chart type is 593 used (data label settings of the parent chart type are *not* merged 594 into own existing data label settings). */ 595 ModelRef< DataLabelsModel > xLabels = mrModel.mxLabels.is() ? mrModel.mxLabels : rTypeGroup.getModel().mxLabels; 596 if( xLabels.is() ) 597 { 598 DataLabelsConverter aLabelsConv( *this, *xLabels ); 599 aLabelsConv.convertFromModel( xDataSeries, rTypeGroup ); 600 } 601 602 return xDataSeries; 603 } 604 605 // private -------------------------------------------------------------------- 606 607 Reference< XLabeledDataSequence > SeriesConverter::createLabeledDataSequence( 608 SeriesModel::SourceType eSourceType, const OUString& rRole, bool bUseTextLabel ) 609 { 610 DataSourceModel* pValues = mrModel.maSources.get( eSourceType ).get(); 611 TextModel* pTitle = bUseTextLabel ? mrModel.mxText.get() : 0; 612 return lclCreateLabeledDataSequence( *this, pValues, rRole, pTitle ); 613 } 614 615 // ============================================================================ 616 617 } // namespace chart 618 } // namespace drawingml 619 } // namespace oox 620