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