bump product version to 4.1.6.2
[LibreOffice.git] / oox / source / drawingml / chart / seriesconverter.cxx
blob020b1410fd77e1a178cbf6e9c32938cca8473235
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "oox/drawingml/chart/seriesconverter.hxx"
22 #include <com/sun/star/chart/DataLabelPlacement.hpp>
23 #include <com/sun/star/chart/ErrorBarStyle.hpp>
24 #include <com/sun/star/chart2/DataPointLabel.hpp>
25 #include <com/sun/star/chart2/XDataSeries.hpp>
26 #include <com/sun/star/chart2/XRegressionCurve.hpp>
27 #include <com/sun/star/chart2/XRegressionCurveContainer.hpp>
28 #include <com/sun/star/chart2/data/XDataSink.hpp>
29 #include <com/sun/star/chart2/data/LabeledDataSequence.hpp>
30 #include <basegfx/numeric/ftools.hxx>
31 #include "oox/drawingml/chart/datasourceconverter.hxx"
32 #include "oox/drawingml/chart/seriesmodel.hxx"
33 #include "oox/drawingml/chart/titleconverter.hxx"
34 #include "oox/drawingml/chart/typegroupconverter.hxx"
35 #include "oox/drawingml/chart/typegroupmodel.hxx"
36 #include "oox/helper/containerhelper.hxx"
38 namespace oox {
39 namespace drawingml {
40 namespace chart {
42 // ============================================================================
44 using namespace ::com::sun::star::beans;
45 using namespace ::com::sun::star::chart2;
46 using namespace ::com::sun::star::chart2::data;
47 using namespace ::com::sun::star::uno;
49 // ============================================================================
51 namespace {
53 /** nastied-up sgn function - employs some gratuity around 0 - values
54 smaller than 0.33 are clamped to 0
56 int lclSgn( double nVal )
58 const int intVal=nVal*3;
59 return intVal == 0 ? 0 : (intVal < 0 ? -1 : 1);
62 Reference< XLabeledDataSequence > lclCreateLabeledDataSequence(
63 const ConverterRoot& rParent,
64 DataSourceModel* pValues, const OUString& rRole,
65 TextModel* pTitle = 0 )
67 // create data sequence for values
68 Reference< XDataSequence > xValueSeq;
69 if( pValues )
71 DataSourceConverter aSourceConv( rParent, *pValues );
72 xValueSeq = aSourceConv.createDataSequence( rRole );
75 // create data sequence for title
76 Reference< XDataSequence > xTitleSeq;
77 if( pTitle )
79 TextConverter aTextConv( rParent, *pTitle );
80 xTitleSeq = aTextConv.createDataSequence( "label" );
83 // create the labeled data sequence, if values or title are present
84 Reference< XLabeledDataSequence > xLabeledSeq;
85 if( xValueSeq.is() || xTitleSeq.is() )
87 xLabeledSeq.set( LabeledDataSequence::create(rParent.getComponentContext()), UNO_QUERY );
88 if( xLabeledSeq.is() )
90 xLabeledSeq->setValues( xValueSeq );
91 xLabeledSeq->setLabel( xTitleSeq );
94 return xLabeledSeq;
97 void lclConvertLabelFormatting( PropertySet& rPropSet, ObjectFormatter& rFormatter,
98 const DataLabelModelBase& rDataLabel, const TypeGroupConverter& rTypeGroup, bool bDataSeriesLabel )
100 const TypeGroupInfo& rTypeInfo = rTypeGroup.getTypeInfo();
102 /* Excel 2007 does not change the series setting for a single data point,
103 if none of some specific elements occur. But only one existing element
104 in a data point will reset most other of these elements from the series
105 (e.g.: series has <c:showVal>, data point has <c:showCatName>, this
106 will reset <c:showVal> for this point, unless <c:showVal> is repeated
107 in the data point). The elements <c:layout>, <c:numberFormat>,
108 <c:spPr>, <c:tx>, and <c:txPr> are not affected at all. */
109 bool bHasAnyElement =
110 rDataLabel.moaSeparator.has() || rDataLabel.monLabelPos.has() ||
111 rDataLabel.mobShowCatName.has() || rDataLabel.mobShowLegendKey.has() ||
112 rDataLabel.mobShowPercent.has() || rDataLabel.mobShowSerName.has() ||
113 rDataLabel.mobShowVal.has();
115 bool bShowValue = !rDataLabel.mbDeleted && rDataLabel.mobShowVal.get( false );
116 bool bShowPercent = !rDataLabel.mbDeleted && rDataLabel.mobShowPercent.get( false ) && (rTypeInfo.meTypeCategory == TYPECATEGORY_PIE);
117 if( bShowValue &&
118 !bShowPercent && rTypeInfo.meTypeCategory == TYPECATEGORY_PIE &&
119 rDataLabel.maNumberFormat.maFormatCode.indexOf('%') >= 0 )
121 bShowValue = false;
122 bShowPercent = true;
124 bool bShowCateg = !rDataLabel.mbDeleted && rDataLabel.mobShowCatName.get( false );
125 bool bShowSymbol = !rDataLabel.mbDeleted && rDataLabel.mobShowLegendKey.get( false );
127 // type of attached label
128 if( bHasAnyElement || rDataLabel.mbDeleted )
130 DataPointLabel aPointLabel( bShowValue, bShowPercent, bShowCateg, bShowSymbol );
131 rPropSet.setProperty( PROP_Label, aPointLabel );
134 if( !rDataLabel.mbDeleted )
136 // data label number format (percentage format wins over value format)
137 rFormatter.convertNumberFormat( rPropSet, rDataLabel.maNumberFormat, bShowPercent );
139 // data label text formatting (frame formatting not supported by Chart2)
140 rFormatter.convertTextFormatting( rPropSet, rDataLabel.mxTextProp, OBJECTTYPE_DATALABEL );
141 rFormatter.convertTextRotation( rPropSet, rDataLabel.mxTextProp, false );
143 // data label separator (do not overwrite series separator, if no explicit point separator is present)
144 if( bDataSeriesLabel || rDataLabel.moaSeparator.has() )
145 rPropSet.setProperty( PROP_LabelSeparator, rDataLabel.moaSeparator.get( "; " ) );
147 // data label placement (do not overwrite series placement, if no explicit point placement is present)
148 if( bDataSeriesLabel || rDataLabel.monLabelPos.has() )
150 namespace csscd = ::com::sun::star::chart::DataLabelPlacement;
151 sal_Int32 nPlacement = rTypeInfo.mnDefLabelPos;
152 switch( rDataLabel.monLabelPos.get( XML_TOKEN_INVALID ) )
154 case XML_outEnd: nPlacement = csscd::OUTSIDE; break;
155 case XML_inEnd: nPlacement = csscd::INSIDE; break;
156 case XML_ctr: nPlacement = csscd::CENTER; break;
157 case XML_inBase: nPlacement = csscd::NEAR_ORIGIN; break;
158 case XML_t: nPlacement = csscd::TOP; break;
159 case XML_b: nPlacement = csscd::BOTTOM; break;
160 case XML_l: nPlacement = csscd::LEFT; break;
161 case XML_r: nPlacement = csscd::RIGHT; break;
162 case XML_bestFit: nPlacement = csscd::AVOID_OVERLAP; break;
164 rPropSet.setProperty( PROP_LabelPlacement, nPlacement );
169 } // namespace
171 // ============================================================================
173 DataLabelConverter::DataLabelConverter( const ConverterRoot& rParent, DataLabelModel& rModel ) :
174 ConverterBase< DataLabelModel >( rParent, rModel )
178 DataLabelConverter::~DataLabelConverter()
182 void DataLabelConverter::convertFromModel( const Reference< XDataSeries >& rxDataSeries, const TypeGroupConverter& rTypeGroup )
184 if( rxDataSeries.is() ) try
186 PropertySet aPropSet( rxDataSeries->getDataPointByIndex( mrModel.mnIndex ) );
187 lclConvertLabelFormatting( aPropSet, getFormatter(), mrModel, rTypeGroup, false );
189 if( mrModel.mxLayout && !mrModel.mxLayout->mbAutoLayout )
191 // bnc#694340 - nasty hack - chart2 cannot individually
192 // place data labels, let's try to find a useful
193 // compromise instead
194 namespace csscd = ::com::sun::star::chart::DataLabelPlacement;
195 const sal_Int32 aPositionsLookupTable[] =
197 csscd::TOP_LEFT, csscd::TOP, csscd::TOP_RIGHT,
198 csscd::LEFT, csscd::CENTER, csscd::RIGHT,
199 csscd::BOTTOM_LEFT, csscd::BOTTOM, csscd::BOTTOM_RIGHT
201 const double nMax=std::max(
202 fabs(mrModel.mxLayout->mfX),
203 fabs(mrModel.mxLayout->mfY));
204 const int simplifiedX=lclSgn(mrModel.mxLayout->mfX/nMax);
205 const int simplifiedY=lclSgn(mrModel.mxLayout->mfY/nMax);
206 aPropSet.setProperty( PROP_LabelPlacement,
207 aPositionsLookupTable[ simplifiedX+1 + 3*(simplifiedY+1) ] );
210 catch( Exception& )
215 // ============================================================================
217 DataLabelsConverter::DataLabelsConverter( const ConverterRoot& rParent, DataLabelsModel& rModel ) :
218 ConverterBase< DataLabelsModel >( rParent, rModel )
222 DataLabelsConverter::~DataLabelsConverter()
226 void DataLabelsConverter::convertFromModel( const Reference< XDataSeries >& rxDataSeries, const TypeGroupConverter& rTypeGroup )
228 if( !mrModel.mbDeleted )
230 PropertySet aPropSet( rxDataSeries );
231 lclConvertLabelFormatting( aPropSet, getFormatter(), mrModel, rTypeGroup, true );
234 // data point label settings
235 for( DataLabelsModel::DataLabelVector::iterator aIt = mrModel.maPointLabels.begin(), aEnd = mrModel.maPointLabels.end(); aIt != aEnd; ++aIt )
237 (*aIt)->maNumberFormat.maFormatCode = mrModel.maNumberFormat.maFormatCode;
238 if( !mrModel.maNumberFormat.maFormatCode.isEmpty() )
239 (*aIt)->maNumberFormat.mbSourceLinked = false;
241 DataLabelConverter aLabelConv( *this, **aIt );
242 aLabelConv.convertFromModel( rxDataSeries, rTypeGroup );
246 // ============================================================================
248 ErrorBarConverter::ErrorBarConverter( const ConverterRoot& rParent, ErrorBarModel& rModel ) :
249 ConverterBase< ErrorBarModel >( rParent, rModel )
253 ErrorBarConverter::~ErrorBarConverter()
257 void ErrorBarConverter::convertFromModel( const Reference< XDataSeries >& rxDataSeries )
259 bool bShowPos = (mrModel.mnTypeId == XML_plus) || (mrModel.mnTypeId == XML_both);
260 bool bShowNeg = (mrModel.mnTypeId == XML_minus) || (mrModel.mnTypeId == XML_both);
261 if( bShowPos || bShowNeg ) try
263 Reference< XPropertySet > xErrorBar( createInstance( "com.sun.star.chart2.ErrorBar" ), UNO_QUERY_THROW );
264 PropertySet aBarProp( xErrorBar );
266 // plus/minus bars
267 aBarProp.setProperty( PROP_ShowPositiveError, bShowPos );
268 aBarProp.setProperty( PROP_ShowNegativeError, bShowNeg );
270 // type of displayed error
271 namespace cssc = ::com::sun::star::chart;
272 switch( mrModel.mnValueType )
274 case XML_cust:
276 // #i87806# manual error bars
277 aBarProp.setProperty( PROP_ErrorBarStyle, cssc::ErrorBarStyle::FROM_DATA );
278 // attach data sequences to erorr bar
279 Reference< XDataSink > xDataSink( xErrorBar, UNO_QUERY );
280 if( xDataSink.is() )
282 // create vector of all value sequences
283 ::std::vector< Reference< XLabeledDataSequence > > aLabeledSeqVec;
284 // add positive values
285 if( bShowPos )
287 Reference< XLabeledDataSequence > xValueSeq = createLabeledDataSequence( ErrorBarModel::PLUS );
288 if( xValueSeq.is() )
289 aLabeledSeqVec.push_back( xValueSeq );
291 // add negative values
292 if( bShowNeg )
294 Reference< XLabeledDataSequence > xValueSeq = createLabeledDataSequence( ErrorBarModel::MINUS );
295 if( xValueSeq.is() )
296 aLabeledSeqVec.push_back( xValueSeq );
298 // attach labeled data sequences to series
299 if( aLabeledSeqVec.empty() )
300 xErrorBar.clear();
301 else
302 xDataSink->setData( ContainerHelper::vectorToSequence( aLabeledSeqVec ) );
305 break;
306 case XML_fixedVal:
307 aBarProp.setProperty( PROP_ErrorBarStyle, cssc::ErrorBarStyle::ABSOLUTE );
308 aBarProp.setProperty( PROP_PositiveError, mrModel.mfValue );
309 aBarProp.setProperty( PROP_NegativeError, mrModel.mfValue );
310 break;
311 case XML_percentage:
312 aBarProp.setProperty( PROP_ErrorBarStyle, cssc::ErrorBarStyle::RELATIVE );
313 aBarProp.setProperty( PROP_PositiveError, mrModel.mfValue );
314 aBarProp.setProperty( PROP_NegativeError, mrModel.mfValue );
315 break;
316 case XML_stdDev:
317 aBarProp.setProperty( PROP_ErrorBarStyle, cssc::ErrorBarStyle::STANDARD_DEVIATION );
318 aBarProp.setProperty( PROP_Weight, mrModel.mfValue );
319 break;
320 case XML_stdErr:
321 aBarProp.setProperty( PROP_ErrorBarStyle, cssc::ErrorBarStyle::STANDARD_ERROR );
322 break;
323 default:
324 OSL_FAIL( "ErrorBarConverter::convertFromModel - unknown error bar type" );
325 xErrorBar.clear();
328 // error bar formatting
329 getFormatter().convertFrameFormatting( aBarProp, mrModel.mxShapeProp, OBJECTTYPE_ERRORBAR );
331 if( xErrorBar.is() )
333 PropertySet aSeriesProp( rxDataSeries );
334 switch( mrModel.mnDirection )
336 case XML_x: aSeriesProp.setProperty( PROP_ErrorBarX, xErrorBar ); break;
337 case XML_y: aSeriesProp.setProperty( PROP_ErrorBarY, xErrorBar ); break;
338 default: OSL_FAIL( "ErrorBarConverter::convertFromModel - invalid error bar direction" );
342 catch( Exception& )
344 OSL_FAIL( "ErrorBarConverter::convertFromModel - error while creating error bars" );
348 // private --------------------------------------------------------------------
350 Reference< XLabeledDataSequence > ErrorBarConverter::createLabeledDataSequence( ErrorBarModel::SourceType eSourceType )
352 OUString aRole;
353 switch( eSourceType )
355 case ErrorBarModel::PLUS:
356 switch( mrModel.mnDirection )
358 case XML_x: aRole = "error-bars-x-positive"; break;
359 case XML_y: aRole = "error-bars-y-positive"; break;
361 break;
362 case ErrorBarModel::MINUS:
363 switch( mrModel.mnDirection )
365 case XML_x: aRole = "error-bars-x-negative"; break;
366 case XML_y: aRole = "error-bars-y-negative"; break;
368 break;
370 OSL_ENSURE( !aRole.isEmpty(), "ErrorBarConverter::createLabeledDataSequence - invalid error bar direction" );
371 return lclCreateLabeledDataSequence( *this, mrModel.maSources.get( eSourceType ).get(), aRole );
374 // ============================================================================
376 TrendlineLabelConverter::TrendlineLabelConverter( const ConverterRoot& rParent, TrendlineLabelModel& rModel ) :
377 ConverterBase< TrendlineLabelModel >( rParent, rModel )
381 TrendlineLabelConverter::~TrendlineLabelConverter()
385 void TrendlineLabelConverter::convertFromModel( PropertySet& rPropSet )
387 // formatting
388 getFormatter().convertFormatting( rPropSet, mrModel.mxShapeProp, mrModel.mxTextProp, OBJECTTYPE_TRENDLINELABEL );
391 // ============================================================================
393 TrendlineConverter::TrendlineConverter( const ConverterRoot& rParent, TrendlineModel& rModel ) :
394 ConverterBase< TrendlineModel >( rParent, rModel )
398 TrendlineConverter::~TrendlineConverter()
402 void TrendlineConverter::convertFromModel( const Reference< XDataSeries >& rxDataSeries )
406 // trend line type
407 OUString aServiceName;
408 switch( mrModel.mnTypeId )
410 case XML_exp: aServiceName = "com.sun.star.chart2.ExponentialRegressionCurve"; break;
411 case XML_linear: aServiceName = "com.sun.star.chart2.LinearRegressionCurve"; break;
412 case XML_log: aServiceName = "com.sun.star.chart2.LogarithmicRegressionCurve"; break;
413 case XML_movingAvg: /* #i66819# moving average trendlines not supported */ break;
414 case XML_poly: /* #i20819# polynomial trendlines not supported */ break;
415 case XML_power: aServiceName = "com.sun.star.chart2.PotentialRegressionCurve"; break;
416 default: OSL_FAIL( "TrendlineConverter::convertFromModel - unknown trendline type" );
418 if( !aServiceName.isEmpty() )
420 Reference< XRegressionCurve > xRegCurve( createInstance( aServiceName ), UNO_QUERY_THROW );
421 PropertySet aPropSet( xRegCurve );
423 // trendline formatting
424 getFormatter().convertFrameFormatting( aPropSet, mrModel.mxShapeProp, OBJECTTYPE_TRENDLINE );
426 // #i83100# show equation and correlation coefficient
427 PropertySet aLabelProp( xRegCurve->getEquationProperties() );
428 aLabelProp.setProperty( PROP_ShowEquation, mrModel.mbDispEquation );
429 aLabelProp.setProperty( PROP_ShowCorrelationCoefficient, mrModel.mbDispRSquared );
431 // #i83100# formatting of the equation text box
432 if( mrModel.mbDispEquation || mrModel.mbDispRSquared )
434 TrendlineLabelConverter aLabelConv( *this, mrModel.mxLabel.getOrCreate() );
435 aLabelConv.convertFromModel( aLabelProp );
438 // unsupported: #i5085# manual trendline size
439 // unsupported: #i34093# manual crossing point
441 Reference< XRegressionCurveContainer > xRegCurveCont( rxDataSeries, UNO_QUERY_THROW );
442 xRegCurveCont->addRegressionCurve( xRegCurve );
445 catch( Exception& )
447 OSL_FAIL( "TrendlineConverter::convertFromModel - error while creating trendline" );
451 // ============================================================================
453 DataPointConverter::DataPointConverter( const ConverterRoot& rParent, DataPointModel& rModel ) :
454 ConverterBase< DataPointModel >( rParent, rModel )
458 DataPointConverter::~DataPointConverter()
462 void DataPointConverter::convertFromModel( const Reference< XDataSeries >& rxDataSeries,
463 const TypeGroupConverter& rTypeGroup, const SeriesModel& rSeries )
467 PropertySet aPropSet( rxDataSeries->getDataPointByIndex( mrModel.mnIndex ) );
469 // data point marker
470 if( mrModel.monMarkerSymbol.differsFrom( rSeries.mnMarkerSymbol ) || mrModel.monMarkerSize.differsFrom( rSeries.mnMarkerSize ) )
471 rTypeGroup.convertMarker( aPropSet, mrModel.monMarkerSymbol.get( rSeries.mnMarkerSymbol ), mrModel.monMarkerSize.get( rSeries.mnMarkerSize ) );
473 // data point pie explosion
474 if( mrModel.monExplosion.differsFrom( rSeries.mnExplosion ) )
475 rTypeGroup.convertPieExplosion( aPropSet, mrModel.monExplosion.get() );
477 // point formatting
478 if( mrModel.mxShapeProp.is() )
480 if( rTypeGroup.getTypeInfo().mbPictureOptions )
481 getFormatter().convertFrameFormatting( aPropSet, mrModel.mxShapeProp, mrModel.mxPicOptions.getOrCreate(), rTypeGroup.getSeriesObjectType(), rSeries.mnIndex );
482 else
483 getFormatter().convertFrameFormatting( aPropSet, mrModel.mxShapeProp, rTypeGroup.getSeriesObjectType(), rSeries.mnIndex );
486 catch( Exception& )
491 // ============================================================================
493 SeriesConverter::SeriesConverter( const ConverterRoot& rParent, SeriesModel& rModel ) :
494 ConverterBase< SeriesModel >( rParent, rModel )
498 SeriesConverter::~SeriesConverter()
502 Reference< XLabeledDataSequence > SeriesConverter::createCategorySequence( const OUString& rRole )
504 return createLabeledDataSequence( SeriesModel::CATEGORIES, rRole, false );
507 Reference< XLabeledDataSequence > SeriesConverter::createValueSequence( const OUString& rRole )
509 return createLabeledDataSequence( SeriesModel::VALUES, rRole, true );
512 Reference< XDataSeries > SeriesConverter::createDataSeries( const TypeGroupConverter& rTypeGroup, bool bVaryColorsByPoint )
514 const TypeGroupInfo& rTypeInfo = rTypeGroup.getTypeInfo();
516 // create the data series object
517 Reference< XDataSeries > xDataSeries( createInstance( "com.sun.star.chart2.DataSeries" ), UNO_QUERY );
518 PropertySet aSeriesProp( xDataSeries );
520 // attach data and title sequences to series
521 sal_Int32 nDataPointCount = 0;
522 Reference< XDataSink > xDataSink( xDataSeries, UNO_QUERY );
523 if( xDataSink.is() )
525 // create vector of all value sequences
526 ::std::vector< Reference< XLabeledDataSequence > > aLabeledSeqVec;
527 // add Y values
528 Reference< XLabeledDataSequence > xYValueSeq = createValueSequence( "values-y" );
529 if( xYValueSeq.is() )
531 aLabeledSeqVec.push_back( xYValueSeq );
532 Reference< XDataSequence > xValues = xYValueSeq->getValues();
533 if( xValues.is() )
534 nDataPointCount = xValues->getData().getLength();
536 // add X values of scatter and bubble charts
537 if( !rTypeInfo.mbCategoryAxis )
539 Reference< XLabeledDataSequence > xXValueSeq = createCategorySequence( "values-x" );
540 if( xXValueSeq.is() )
541 aLabeledSeqVec.push_back( xXValueSeq );
542 // add size values of bubble charts
543 if( rTypeInfo.meTypeId == TYPEID_BUBBLE )
545 Reference< XLabeledDataSequence > xSizeValueSeq = createLabeledDataSequence( SeriesModel::POINTS, "values-size", true );
546 if( xSizeValueSeq.is() )
547 aLabeledSeqVec.push_back( xSizeValueSeq );
550 // attach labeled data sequences to series
551 if( !aLabeledSeqVec.empty() )
552 xDataSink->setData( ContainerHelper::vectorToSequence( aLabeledSeqVec ) );
555 // error bars
556 for( SeriesModel::ErrorBarVector::iterator aIt = mrModel.maErrorBars.begin(), aEnd = mrModel.maErrorBars.end(); aIt != aEnd; ++aIt )
558 ErrorBarConverter aErrorBarConv( *this, **aIt );
559 aErrorBarConv.convertFromModel( xDataSeries );
562 // trendlines
563 for( SeriesModel::TrendlineVector::iterator aIt = mrModel.maTrendlines.begin(), aEnd = mrModel.maTrendlines.end(); aIt != aEnd; ++aIt )
565 TrendlineConverter aTrendlineConv( *this, **aIt );
566 aTrendlineConv.convertFromModel( xDataSeries );
569 // data point markers
570 rTypeGroup.convertMarker( aSeriesProp, mrModel.mnMarkerSymbol, mrModel.mnMarkerSize );
571 #if OOX_CHART_SMOOTHED_PER_SERIES
572 // #i66858# smoothed series lines
573 rTypeGroup.convertLineSmooth( aSeriesProp, mrModel.mbSmooth );
574 #endif
575 // 3D bar style (not possible to set at chart type -> set at all series)
576 rTypeGroup.convertBarGeometry( aSeriesProp, mrModel.monShape.get( rTypeGroup.getModel().mnShape ) );
577 // pie explosion (restricted to [0%,100%] in Chart2)
578 rTypeGroup.convertPieExplosion( aSeriesProp, mrModel.mnExplosion );
580 // series formatting
581 ObjectFormatter& rFormatter = getFormatter();
582 ObjectType eObjType = rTypeGroup.getSeriesObjectType();
583 if( rTypeInfo.mbPictureOptions )
584 rFormatter.convertFrameFormatting( aSeriesProp, mrModel.mxShapeProp, mrModel.mxPicOptions.getOrCreate(), eObjType, mrModel.mnIndex );
585 else
586 rFormatter.convertFrameFormatting( aSeriesProp, mrModel.mxShapeProp, eObjType, mrModel.mnIndex );
588 // set the (unused) property default value used by the Chart2 templates (true for pie/doughnut charts)
589 bool bIsPie = rTypeInfo.meTypeCategory == TYPECATEGORY_PIE;
590 aSeriesProp.setProperty( PROP_VaryColorsByPoint, bIsPie );
592 // own area formatting for every data point (TODO: varying line color not supported)
593 // #i91271# always set area formatting for every point in pie/doughnut charts to override their automatic point formatting
594 if( bIsPie || (bVaryColorsByPoint && rTypeGroup.isSeriesFrameFormat() && ObjectFormatter::isAutomaticFill( mrModel.mxShapeProp )) )
596 /* Set the series point number as color cycle size at the object
597 formatter to get correct start-shade/end-tint. TODO: in doughnut
598 charts, the sizes of the series may vary, need to use the maximum
599 point count of all series. */
600 sal_Int32 nOldMax = rFormatter.getMaxSeriesIndex();
601 if( bVaryColorsByPoint )
602 rFormatter.setMaxSeriesIndex( nDataPointCount - 1 );
603 for( sal_Int32 nIndex = 0; nIndex < nDataPointCount; ++nIndex )
607 PropertySet aPointProp( xDataSeries->getDataPointByIndex( nIndex ) );
608 rFormatter.convertAutomaticFill( aPointProp, eObjType, bVaryColorsByPoint ? nIndex : mrModel.mnIndex );
610 catch( Exception& )
614 rFormatter.setMaxSeriesIndex( nOldMax );
617 // data point settings
618 for( SeriesModel::DataPointVector::iterator aIt = mrModel.maPoints.begin(), aEnd = mrModel.maPoints.end(); aIt != aEnd; ++aIt )
620 DataPointConverter aPointConv( *this, **aIt );
621 aPointConv.convertFromModel( xDataSeries, rTypeGroup, mrModel );
624 /* Series data label settings. If and only if the series does not contain
625 a c:dLbls element, then the c:dLbls element of the parent chart type is
626 used (data label settings of the parent chart type are *not* merged
627 into own existing data label settings). */
628 ModelRef< DataLabelsModel > xLabels = mrModel.mxLabels.is() ? mrModel.mxLabels : rTypeGroup.getModel().mxLabels;
629 if( xLabels.is() )
631 if( xLabels->maNumberFormat.maFormatCode.isEmpty() )
633 // Use number format code from Value series
634 DataSourceModel* pValues = mrModel.maSources.get( SeriesModel::VALUES ).get();
635 if( pValues )
636 xLabels->maNumberFormat.maFormatCode = pValues->mxDataSeq->maFormatCode;
638 DataLabelsConverter aLabelsConv( *this, *xLabels );
639 aLabelsConv.convertFromModel( xDataSeries, rTypeGroup );
642 return xDataSeries;
645 // private --------------------------------------------------------------------
647 Reference< XLabeledDataSequence > SeriesConverter::createLabeledDataSequence(
648 SeriesModel::SourceType eSourceType, const OUString& rRole, bool bUseTextLabel )
650 DataSourceModel* pValues = mrModel.maSources.get( eSourceType ).get();
651 TextModel* pTitle = bUseTextLabel ? mrModel.mxText.get() : 0;
652 return lclCreateLabeledDataSequence( *this, pValues, rRole, pTitle );
655 // ============================================================================
657 } // namespace chart
658 } // namespace drawingml
659 } // namespace oox
661 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */