1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 "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 <osl/diagnose.h>
31 #include <basegfx/numeric/ftools.hxx>
32 #include "drawingml/chart/datasourceconverter.hxx"
33 #include "drawingml/chart/seriesmodel.hxx"
34 #include "drawingml/chart/titleconverter.hxx"
35 #include "drawingml/chart/typegroupconverter.hxx"
36 #include "drawingml/chart/typegroupmodel.hxx"
37 #include "oox/helper/containerhelper.hxx"
38 #include <oox/drawingml/lineproperties.hxx>
44 using namespace com::sun::star
;
45 using namespace ::com::sun::star::beans
;
46 using namespace ::com::sun::star::chart2
;
47 using namespace ::com::sun::star::chart2::data
;
48 using namespace ::com::sun::star::uno
;
52 /** nastied-up sgn function - employs some gratuity around 0 - values
53 smaller than 0.33 are clamped to 0
55 int lclSgn( double nVal
)
57 const int intVal
=nVal
*3;
58 return intVal
== 0 ? 0 : (intVal
< 0 ? -1 : 1);
61 Reference
< XLabeledDataSequence
> lclCreateLabeledDataSequence(
62 const ConverterRoot
& rParent
,
63 DataSourceModel
* pValues
, const OUString
& rRole
,
64 TextModel
* pTitle
= 0 )
66 // create data sequence for values
67 Reference
< XDataSequence
> xValueSeq
;
70 DataSourceConverter
aSourceConv( rParent
, *pValues
);
71 xValueSeq
= aSourceConv
.createDataSequence( rRole
);
74 // create data sequence for title
75 Reference
< XDataSequence
> xTitleSeq
;
78 TextConverter
aTextConv( rParent
, *pTitle
);
79 xTitleSeq
= aTextConv
.createDataSequence( "label" );
82 // create the labeled data sequence, if values or title are present
83 Reference
< XLabeledDataSequence
> xLabeledSeq
;
84 if( xValueSeq
.is() || xTitleSeq
.is() )
86 xLabeledSeq
.set( LabeledDataSequence::create(rParent
.getComponentContext()), UNO_QUERY
);
87 if( xLabeledSeq
.is() )
89 xLabeledSeq
->setValues( xValueSeq
);
90 xLabeledSeq
->setLabel( xTitleSeq
);
96 void lclConvertLabelFormatting( PropertySet
& rPropSet
, ObjectFormatter
& rFormatter
,
97 const DataLabelModelBase
& rDataLabel
, const TypeGroupConverter
& rTypeGroup
, bool bDataSeriesLabel
, bool bMSO2007Doc
)
99 const TypeGroupInfo
& rTypeInfo
= rTypeGroup
.getTypeInfo();
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
= true;
111 bHasAnyElement
= rDataLabel
.moaSeparator
.has() || rDataLabel
.monLabelPos
.has() ||
112 rDataLabel
.mobShowCatName
.has() || rDataLabel
.mobShowLegendKey
.has() ||
113 rDataLabel
.mobShowPercent
.has() || rDataLabel
.mobShowSerName
.has() ||
114 rDataLabel
.mobShowVal
.has();
117 bool bShowValue
= !rDataLabel
.mbDeleted
&& rDataLabel
.mobShowVal
.get( !bMSO2007Doc
);
118 bool bShowPercent
= !rDataLabel
.mbDeleted
&& rDataLabel
.mobShowPercent
.get( !bMSO2007Doc
) && (rTypeInfo
.meTypeCategory
== TYPECATEGORY_PIE
);
120 !bShowPercent
&& rTypeInfo
.meTypeCategory
== TYPECATEGORY_PIE
&&
121 rDataLabel
.maNumberFormat
.maFormatCode
.indexOf('%') >= 0 )
126 bool bShowCateg
= !rDataLabel
.mbDeleted
&& rDataLabel
.mobShowCatName
.get( !bMSO2007Doc
);
127 bool bShowSymbol
= !rDataLabel
.mbDeleted
&& rDataLabel
.mobShowLegendKey
.get( !bMSO2007Doc
);
129 // type of attached label
130 if( bHasAnyElement
|| rDataLabel
.mbDeleted
)
132 DataPointLabel
aPointLabel( bShowValue
, bShowPercent
, bShowCateg
, bShowSymbol
);
133 rPropSet
.setProperty( PROP_Label
, aPointLabel
);
136 if( !rDataLabel
.mbDeleted
)
138 // data label number format (percentage format wins over value format)
139 rFormatter
.convertNumberFormat( rPropSet
, rDataLabel
.maNumberFormat
, false, bShowPercent
);
141 // data label text formatting (frame formatting not supported by Chart2)
142 rFormatter
.convertTextFormatting( rPropSet
, rDataLabel
.mxTextProp
, OBJECTTYPE_DATALABEL
);
143 ObjectFormatter::convertTextRotation( rPropSet
, rDataLabel
.mxTextProp
, false );
145 // data label separator (do not overwrite series separator, if no explicit point separator is present)
146 if( bDataSeriesLabel
|| rDataLabel
.moaSeparator
.has() )
147 rPropSet
.setProperty( PROP_LabelSeparator
, rDataLabel
.moaSeparator
.get( "; " ) );
149 // data label placement (do not overwrite series placement, if no explicit point placement is present)
150 if( bDataSeriesLabel
|| rDataLabel
.monLabelPos
.has() )
152 namespace csscd
= ::com::sun::star::chart::DataLabelPlacement
;
153 sal_Int32 nPlacement
= rTypeInfo
.mnDefLabelPos
;
154 switch( rDataLabel
.monLabelPos
.get( XML_TOKEN_INVALID
) )
156 case XML_outEnd
: nPlacement
= csscd::OUTSIDE
; break;
157 case XML_inEnd
: nPlacement
= csscd::INSIDE
; break;
158 case XML_ctr
: nPlacement
= csscd::CENTER
; break;
159 case XML_inBase
: nPlacement
= csscd::NEAR_ORIGIN
; break;
160 case XML_t
: nPlacement
= csscd::TOP
; break;
161 case XML_b
: nPlacement
= csscd::BOTTOM
; break;
162 case XML_l
: nPlacement
= csscd::LEFT
; break;
163 case XML_r
: nPlacement
= csscd::RIGHT
; break;
164 case XML_bestFit
: nPlacement
= csscd::AVOID_OVERLAP
; break;
166 rPropSet
.setProperty( PROP_LabelPlacement
, nPlacement
);
171 void importBorderProperties( PropertySet
& rPropSet
, Shape
& rShape
, const GraphicHelper
& rGraphicHelper
)
173 LineProperties
& rLP
= rShape
.getLineProperties();
174 // no fill has the same effect as no border so skip it
175 if (rLP
.maLineFill
.moFillType
.get() == XML_noFill
)
178 if (rLP
.moLineWidth
.has())
180 sal_Int32 nWidth
= convertEmuToHmm(rLP
.moLineWidth
.get());
181 rPropSet
.setProperty(PROP_LabelBorderWidth
, uno::makeAny(nWidth
));
182 rPropSet
.setProperty(PROP_LabelBorderStyle
, uno::makeAny(drawing::LineStyle_SOLID
));
184 const Color
& aColor
= rLP
.maLineFill
.maFillColor
;
185 sal_Int32 nColor
= aColor
.getColor(rGraphicHelper
);
186 rPropSet
.setProperty(PROP_LabelBorderColor
, uno::makeAny(nColor
));
191 DataLabelConverter::DataLabelConverter( const ConverterRoot
& rParent
, DataLabelModel
& rModel
) :
192 ConverterBase
< DataLabelModel
>( rParent
, rModel
)
196 DataLabelConverter::~DataLabelConverter()
200 void DataLabelConverter::convertFromModel( const Reference
< XDataSeries
>& rxDataSeries
, const TypeGroupConverter
& rTypeGroup
)
202 if (!rxDataSeries
.is())
207 bool bMSO2007Doc
= getFilter().isMSO2007Document();
208 PropertySet
aPropSet( rxDataSeries
->getDataPointByIndex( mrModel
.mnIndex
) );
209 lclConvertLabelFormatting( aPropSet
, getFormatter(), mrModel
, rTypeGroup
, false, bMSO2007Doc
);
210 const TypeGroupInfo
& rTypeInfo
= rTypeGroup
.getTypeInfo();
211 bool bIsPie
= rTypeInfo
.meTypeCategory
== TYPECATEGORY_PIE
;
212 if( mrModel
.mxLayout
&& !mrModel
.mxLayout
->mbAutoLayout
&& !bIsPie
)
214 // bnc#694340 - nasty hack - chart2 cannot individually
215 // place data labels, let's try to find a useful
216 // compromise instead
217 namespace csscd
= ::com::sun::star::chart::DataLabelPlacement
;
218 const sal_Int32 aPositionsLookupTable
[] =
220 csscd::TOP_LEFT
, csscd::TOP
, csscd::TOP_RIGHT
,
221 csscd::LEFT
, csscd::CENTER
, csscd::RIGHT
,
222 csscd::BOTTOM_LEFT
, csscd::BOTTOM
, csscd::BOTTOM_RIGHT
224 const double nMax
=std::max(
225 fabs(mrModel
.mxLayout
->mfX
),
226 fabs(mrModel
.mxLayout
->mfY
));
227 const int simplifiedX
=lclSgn(mrModel
.mxLayout
->mfX
/nMax
);
228 const int simplifiedY
=lclSgn(mrModel
.mxLayout
->mfY
/nMax
);
229 aPropSet
.setProperty( PROP_LabelPlacement
,
230 aPositionsLookupTable
[ simplifiedX
+1 + 3*(simplifiedY
+1) ] );
233 if (mrModel
.mxShapeProp
)
234 importBorderProperties(aPropSet
, *mrModel
.mxShapeProp
, getFilter().getGraphicHelper());
241 DataLabelsConverter::DataLabelsConverter( const ConverterRoot
& rParent
, DataLabelsModel
& rModel
) :
242 ConverterBase
< DataLabelsModel
>( rParent
, rModel
)
246 DataLabelsConverter::~DataLabelsConverter()
250 void DataLabelsConverter::convertFromModel( const Reference
< XDataSeries
>& rxDataSeries
, const TypeGroupConverter
& rTypeGroup
)
252 if( !mrModel
.mbDeleted
)
254 bool bMSO2007Doc
= getFilter().isMSO2007Document();
255 PropertySet
aPropSet( rxDataSeries
);
256 lclConvertLabelFormatting( aPropSet
, getFormatter(), mrModel
, rTypeGroup
, true, bMSO2007Doc
);
258 if (mrModel
.mxShapeProp
)
259 // Import baseline border properties for these data labels.
260 importBorderProperties(aPropSet
, *mrModel
.mxShapeProp
, getFilter().getGraphicHelper());
263 // data point label settings
264 for( DataLabelsModel::DataLabelVector::iterator aIt
= mrModel
.maPointLabels
.begin(), aEnd
= mrModel
.maPointLabels
.end(); aIt
!= aEnd
; ++aIt
)
266 if ((*aIt
)->maNumberFormat
.maFormatCode
.isEmpty())
267 (*aIt
)->maNumberFormat
= mrModel
.maNumberFormat
;
269 DataLabelConverter
aLabelConv( *this, **aIt
);
270 aLabelConv
.convertFromModel( rxDataSeries
, rTypeGroup
);
274 ErrorBarConverter::ErrorBarConverter( const ConverterRoot
& rParent
, ErrorBarModel
& rModel
) :
275 ConverterBase
< ErrorBarModel
>( rParent
, rModel
)
279 ErrorBarConverter::~ErrorBarConverter()
283 void ErrorBarConverter::convertFromModel( const Reference
< XDataSeries
>& rxDataSeries
)
285 bool bShowPos
= (mrModel
.mnTypeId
== XML_plus
) || (mrModel
.mnTypeId
== XML_both
);
286 bool bShowNeg
= (mrModel
.mnTypeId
== XML_minus
) || (mrModel
.mnTypeId
== XML_both
);
287 if( bShowPos
|| bShowNeg
) try
289 Reference
< XPropertySet
> xErrorBar( createInstance( "com.sun.star.chart2.ErrorBar" ), UNO_QUERY_THROW
);
290 PropertySet
aBarProp( xErrorBar
);
293 aBarProp
.setProperty( PROP_ShowPositiveError
, bShowPos
);
294 aBarProp
.setProperty( PROP_ShowNegativeError
, bShowNeg
);
296 // type of displayed error
297 namespace cssc
= ::com::sun::star::chart
;
298 switch( mrModel
.mnValueType
)
302 // #i87806# manual error bars
303 aBarProp
.setProperty( PROP_ErrorBarStyle
, cssc::ErrorBarStyle::FROM_DATA
);
304 // attach data sequences to erorr bar
305 Reference
< XDataSink
> xDataSink( xErrorBar
, UNO_QUERY
);
308 // create vector of all value sequences
309 ::std::vector
< Reference
< XLabeledDataSequence
> > aLabeledSeqVec
;
310 // add positive values
313 Reference
< XLabeledDataSequence
> xValueSeq
= createLabeledDataSequence( ErrorBarModel::PLUS
);
315 aLabeledSeqVec
.push_back( xValueSeq
);
317 // add negative values
320 Reference
< XLabeledDataSequence
> xValueSeq
= createLabeledDataSequence( ErrorBarModel::MINUS
);
322 aLabeledSeqVec
.push_back( xValueSeq
);
324 // attach labeled data sequences to series
325 if( aLabeledSeqVec
.empty() )
328 xDataSink
->setData( ContainerHelper::vectorToSequence( aLabeledSeqVec
) );
333 aBarProp
.setProperty( PROP_ErrorBarStyle
, cssc::ErrorBarStyle::ABSOLUTE
);
334 aBarProp
.setProperty( PROP_PositiveError
, mrModel
.mfValue
);
335 aBarProp
.setProperty( PROP_NegativeError
, mrModel
.mfValue
);
338 aBarProp
.setProperty( PROP_ErrorBarStyle
, cssc::ErrorBarStyle::RELATIVE
);
339 aBarProp
.setProperty( PROP_PositiveError
, mrModel
.mfValue
);
340 aBarProp
.setProperty( PROP_NegativeError
, mrModel
.mfValue
);
343 aBarProp
.setProperty( PROP_ErrorBarStyle
, cssc::ErrorBarStyle::STANDARD_DEVIATION
);
344 aBarProp
.setProperty( PROP_Weight
, mrModel
.mfValue
);
347 aBarProp
.setProperty( PROP_ErrorBarStyle
, cssc::ErrorBarStyle::STANDARD_ERROR
);
350 OSL_FAIL( "ErrorBarConverter::convertFromModel - unknown error bar type" );
354 // error bar formatting
355 getFormatter().convertFrameFormatting( aBarProp
, mrModel
.mxShapeProp
, OBJECTTYPE_ERRORBAR
);
359 PropertySet
aSeriesProp( rxDataSeries
);
360 switch( mrModel
.mnDirection
)
362 case XML_x
: aSeriesProp
.setProperty( PROP_ErrorBarX
, xErrorBar
); break;
363 case XML_y
: aSeriesProp
.setProperty( PROP_ErrorBarY
, xErrorBar
); break;
364 default: OSL_FAIL( "ErrorBarConverter::convertFromModel - invalid error bar direction" );
370 OSL_FAIL( "ErrorBarConverter::convertFromModel - error while creating error bars" );
374 Reference
< XLabeledDataSequence
> ErrorBarConverter::createLabeledDataSequence( ErrorBarModel::SourceType eSourceType
)
377 switch( eSourceType
)
379 case ErrorBarModel::PLUS
:
380 switch( mrModel
.mnDirection
)
382 case XML_x
: aRole
= "error-bars-x-positive"; break;
383 case XML_y
: aRole
= "error-bars-y-positive"; break;
386 case ErrorBarModel::MINUS
:
387 switch( mrModel
.mnDirection
)
389 case XML_x
: aRole
= "error-bars-x-negative"; break;
390 case XML_y
: aRole
= "error-bars-y-negative"; break;
394 OSL_ENSURE( !aRole
.isEmpty(), "ErrorBarConverter::createLabeledDataSequence - invalid error bar direction" );
395 return lclCreateLabeledDataSequence( *this, mrModel
.maSources
.get( eSourceType
).get(), aRole
);
398 TrendlineLabelConverter::TrendlineLabelConverter( const ConverterRoot
& rParent
, TrendlineLabelModel
& rModel
) :
399 ConverterBase
< TrendlineLabelModel
>( rParent
, rModel
)
403 TrendlineLabelConverter::~TrendlineLabelConverter()
407 void TrendlineLabelConverter::convertFromModel( PropertySet
& rPropSet
)
410 getFormatter().convertFormatting( rPropSet
, mrModel
.mxShapeProp
, mrModel
.mxTextProp
, OBJECTTYPE_TRENDLINELABEL
);
413 TrendlineConverter::TrendlineConverter( const ConverterRoot
& rParent
, TrendlineModel
& rModel
) :
414 ConverterBase
< TrendlineModel
>( rParent
, rModel
)
418 TrendlineConverter::~TrendlineConverter()
422 void TrendlineConverter::convertFromModel( const Reference
< XDataSeries
>& rxDataSeries
)
427 OUString aServiceName
;
428 switch( mrModel
.mnTypeId
)
431 aServiceName
= "com.sun.star.chart2.ExponentialRegressionCurve";
434 aServiceName
= "com.sun.star.chart2.LinearRegressionCurve";
437 aServiceName
= "com.sun.star.chart2.LogarithmicRegressionCurve";
440 aServiceName
= "com.sun.star.chart2.MovingAverageRegressionCurve";
443 aServiceName
= "com.sun.star.chart2.PolynomialRegressionCurve";
446 aServiceName
= "com.sun.star.chart2.PotentialRegressionCurve";
449 OSL_FAIL( "TrendlineConverter::convertFromModel - unknown trendline type" );
451 if( !aServiceName
.isEmpty() )
453 Reference
< XRegressionCurve
> xRegCurve( createInstance( aServiceName
), UNO_QUERY_THROW
);
454 PropertySet
aPropSet( xRegCurve
);
457 aPropSet
.setProperty( PROP_CurveName
, mrModel
.maName
);
458 aPropSet
.setProperty( PROP_PolynomialDegree
, mrModel
.mnOrder
);
459 aPropSet
.setProperty( PROP_MovingAveragePeriod
, mrModel
.mnPeriod
);
462 bool hasIntercept
= mrModel
.mfIntercept
.has();
463 aPropSet
.setProperty( PROP_ForceIntercept
, hasIntercept
);
465 aPropSet
.setProperty( PROP_InterceptValue
, mrModel
.mfIntercept
.get());
468 if (mrModel
.mfForward
.has())
469 aPropSet
.setProperty( PROP_ExtrapolateForward
, mrModel
.mfForward
.get() );
470 if (mrModel
.mfBackward
.has())
471 aPropSet
.setProperty( PROP_ExtrapolateBackward
, mrModel
.mfBackward
.get() );
473 // trendline formatting
474 getFormatter().convertFrameFormatting( aPropSet
, mrModel
.mxShapeProp
, OBJECTTYPE_TRENDLINE
);
476 // #i83100# show equation and correlation coefficient
477 PropertySet
aLabelProp( xRegCurve
->getEquationProperties() );
478 aLabelProp
.setProperty( PROP_ShowEquation
, mrModel
.mbDispEquation
);
479 aLabelProp
.setProperty( PROP_ShowCorrelationCoefficient
, mrModel
.mbDispRSquared
);
481 // #i83100# formatting of the equation text box
482 if( mrModel
.mbDispEquation
|| mrModel
.mbDispRSquared
)
484 TrendlineLabelConverter
aLabelConv( *this, mrModel
.mxLabel
.getOrCreate() );
485 aLabelConv
.convertFromModel( aLabelProp
);
488 // unsupported: #i5085# manual trendline size
489 // unsupported: #i34093# manual crossing point
491 Reference
< XRegressionCurveContainer
> xRegCurveCont( rxDataSeries
, UNO_QUERY_THROW
);
492 xRegCurveCont
->addRegressionCurve( xRegCurve
);
497 OSL_FAIL( "TrendlineConverter::convertFromModel - error while creating trendline" );
501 DataPointConverter::DataPointConverter( const ConverterRoot
& rParent
, DataPointModel
& rModel
) :
502 ConverterBase
< DataPointModel
>( rParent
, rModel
)
506 DataPointConverter::~DataPointConverter()
510 void DataPointConverter::convertFromModel( const Reference
< XDataSeries
>& rxDataSeries
,
511 const TypeGroupConverter
& rTypeGroup
, const SeriesModel
& rSeries
)
513 bool bMSO2007Doc
= getFilter().isMSO2007Document();
516 PropertySet
aPropSet( rxDataSeries
->getDataPointByIndex( mrModel
.mnIndex
) );
519 if( mrModel
.monMarkerSymbol
.differsFrom( rSeries
.mnMarkerSymbol
) || mrModel
.monMarkerSize
.differsFrom( rSeries
.mnMarkerSize
) )
520 rTypeGroup
.convertMarker( aPropSet
, mrModel
.monMarkerSymbol
.get( rSeries
.mnMarkerSymbol
),
521 mrModel
.monMarkerSize
.get( rSeries
.mnMarkerSize
), mrModel
.mxMarkerProp
);
523 // data point pie explosion
524 if( mrModel
.monExplosion
.differsFrom( rSeries
.mnExplosion
) )
525 rTypeGroup
.convertPieExplosion( aPropSet
, mrModel
.monExplosion
.get() );
528 if( mrModel
.mxShapeProp
.is() )
530 if( rTypeGroup
.getTypeInfo().mbPictureOptions
)
531 getFormatter().convertFrameFormatting( aPropSet
, mrModel
.mxShapeProp
, mrModel
.mxPicOptions
.getOrCreate(bMSO2007Doc
), rTypeGroup
.getSeriesObjectType(), rSeries
.mnIndex
);
533 getFormatter().convertFrameFormatting( aPropSet
, mrModel
.mxShapeProp
, rTypeGroup
.getSeriesObjectType(), rSeries
.mnIndex
);
541 SeriesConverter::SeriesConverter( const ConverterRoot
& rParent
, SeriesModel
& rModel
) :
542 ConverterBase
< SeriesModel
>( rParent
, rModel
)
546 SeriesConverter::~SeriesConverter()
550 Reference
< XLabeledDataSequence
> SeriesConverter::createCategorySequence( const OUString
& rRole
)
552 return createLabeledDataSequence(SeriesModel::CATEGORIES
, rRole
, false);
555 Reference
< XLabeledDataSequence
> SeriesConverter::createValueSequence( const OUString
& rRole
)
557 return createLabeledDataSequence( SeriesModel::VALUES
, rRole
, true );
560 Reference
< XDataSeries
> SeriesConverter::createDataSeries( const TypeGroupConverter
& rTypeGroup
, bool bVaryColorsByPoint
)
562 const TypeGroupInfo
& rTypeInfo
= rTypeGroup
.getTypeInfo();
564 // create the data series object
565 Reference
< XDataSeries
> xDataSeries( createInstance( "com.sun.star.chart2.DataSeries" ), UNO_QUERY
);
566 PropertySet
aSeriesProp( xDataSeries
);
568 // attach data and title sequences to series
569 sal_Int32 nDataPointCount
= 0;
570 Reference
< XDataSink
> xDataSink( xDataSeries
, UNO_QUERY
);
573 // create vector of all value sequences
574 ::std::vector
< Reference
< XLabeledDataSequence
> > aLabeledSeqVec
;
576 Reference
< XLabeledDataSequence
> xYValueSeq
= createValueSequence( "values-y" );
577 if( xYValueSeq
.is() )
579 aLabeledSeqVec
.push_back( xYValueSeq
);
580 Reference
< XDataSequence
> xValues
= xYValueSeq
->getValues();
582 nDataPointCount
= xValues
->getData().getLength();
584 if (!nDataPointCount
)
585 // No values present. Don't create a data series.
586 return Reference
<XDataSeries
>();
588 // add X values of scatter and bubble charts
589 if( !rTypeInfo
.mbCategoryAxis
)
591 Reference
< XLabeledDataSequence
> xXValueSeq
= createCategorySequence( "values-x" );
592 if( xXValueSeq
.is() )
593 aLabeledSeqVec
.push_back( xXValueSeq
);
594 // add size values of bubble charts
595 if( rTypeInfo
.meTypeId
== TYPEID_BUBBLE
)
597 Reference
< XLabeledDataSequence
> xSizeValueSeq
= createLabeledDataSequence( SeriesModel::POINTS
, "values-size", true );
598 if( xSizeValueSeq
.is() )
599 aLabeledSeqVec
.push_back( xSizeValueSeq
);
602 // attach labeled data sequences to series
603 if( !aLabeledSeqVec
.empty() )
604 xDataSink
->setData( ContainerHelper::vectorToSequence( aLabeledSeqVec
) );
608 for( SeriesModel::ErrorBarVector::iterator aIt
= mrModel
.maErrorBars
.begin(), aEnd
= mrModel
.maErrorBars
.end(); aIt
!= aEnd
; ++aIt
)
610 ErrorBarConverter
aErrorBarConv( *this, **aIt
);
611 aErrorBarConv
.convertFromModel( xDataSeries
);
615 for( SeriesModel::TrendlineVector::iterator aIt
= mrModel
.maTrendlines
.begin(), aEnd
= mrModel
.maTrendlines
.end(); aIt
!= aEnd
; ++aIt
)
617 TrendlineConverter
aTrendlineConv( *this, **aIt
);
618 aTrendlineConv
.convertFromModel( xDataSeries
);
621 // data point markers
622 rTypeGroup
.convertMarker( aSeriesProp
, mrModel
.mnMarkerSymbol
, mrModel
.mnMarkerSize
, mrModel
.mxMarkerProp
);
623 #if OOX_CHART_SMOOTHED_PER_SERIES
624 // #i66858# smoothed series lines
625 rTypeGroup
.convertLineSmooth( aSeriesProp
, mrModel
.mbSmooth
);
627 // 3D bar style (not possible to set at chart type -> set at all series)
628 rTypeGroup
.convertBarGeometry( aSeriesProp
, mrModel
.monShape
.get( rTypeGroup
.getModel().mnShape
) );
629 // pie explosion (restricted to [0%,100%] in Chart2)
630 rTypeGroup
.convertPieExplosion( aSeriesProp
, mrModel
.mnExplosion
);
633 ObjectFormatter
& rFormatter
= getFormatter();
634 ObjectType eObjType
= rTypeGroup
.getSeriesObjectType();
635 bool bMSO2007Doc
= getFilter().isMSO2007Document();
636 if( rTypeInfo
.mbPictureOptions
)
637 rFormatter
.convertFrameFormatting( aSeriesProp
, mrModel
.mxShapeProp
, mrModel
.mxPicOptions
.getOrCreate(bMSO2007Doc
), eObjType
, mrModel
.mnIndex
);
639 rFormatter
.convertFrameFormatting( aSeriesProp
, mrModel
.mxShapeProp
, eObjType
, mrModel
.mnIndex
);
641 // set the (unused) property default value used by the Chart2 templates (true for pie/doughnut charts)
642 bool bIsPie
= rTypeInfo
.meTypeCategory
== TYPECATEGORY_PIE
;
643 aSeriesProp
.setProperty( PROP_VaryColorsByPoint
, bVaryColorsByPoint
);
645 // own area formatting for every data point (TODO: varying line color not supported)
646 // #i91271# always set area formatting for every point in pie/doughnut charts to override their automatic point formatting
647 if( bIsPie
|| (bVaryColorsByPoint
&& rTypeGroup
.isSeriesFrameFormat() && ObjectFormatter::isAutomaticFill( mrModel
.mxShapeProp
)) )
649 /* Set the series point number as color cycle size at the object
650 formatter to get correct start-shade/end-tint. TODO: in doughnut
651 charts, the sizes of the series may vary, need to use the maximum
652 point count of all series. */
653 sal_Int32 nOldMax
= rFormatter
.getMaxSeriesIndex();
654 if( bVaryColorsByPoint
)
655 rFormatter
.setMaxSeriesIndex( nDataPointCount
- 1 );
656 for( sal_Int32 nIndex
= 0; nIndex
< nDataPointCount
; ++nIndex
)
660 PropertySet
aPointProp( xDataSeries
->getDataPointByIndex( nIndex
) );
661 rFormatter
.convertAutomaticFill( aPointProp
, eObjType
, bVaryColorsByPoint
? nIndex
: mrModel
.mnIndex
);
667 rFormatter
.setMaxSeriesIndex( nOldMax
);
670 // data point settings
671 for( SeriesModel::DataPointVector::iterator aIt
= mrModel
.maPoints
.begin(), aEnd
= mrModel
.maPoints
.end(); aIt
!= aEnd
; ++aIt
)
673 DataPointConverter
aPointConv( *this, **aIt
);
674 aPointConv
.convertFromModel( xDataSeries
, rTypeGroup
, mrModel
);
677 /* Series data label settings. If and only if the series does not contain
678 a c:dLbls element, then the c:dLbls element of the parent chart type is
679 used (data label settings of the parent chart type are *not* merged
680 into own existing data label settings). */
681 ModelRef
< DataLabelsModel
> xLabels
= mrModel
.mxLabels
.is() ? mrModel
.mxLabels
: rTypeGroup
.getModel().mxLabels
;
684 if( xLabels
->maNumberFormat
.maFormatCode
.isEmpty() )
686 // Use number format code from Value series
687 DataSourceModel
* pValues
= mrModel
.maSources
.get( SeriesModel::VALUES
).get();
689 xLabels
->maNumberFormat
.maFormatCode
= pValues
->mxDataSeq
->maFormatCode
;
691 DataLabelsConverter
aLabelsConv( *this, *xLabels
);
692 aLabelsConv
.convertFromModel( xDataSeries
, rTypeGroup
);
698 // private --------------------------------------------------------------------
700 Reference
< XLabeledDataSequence
> SeriesConverter::createLabeledDataSequence(
701 SeriesModel::SourceType eSourceType
, const OUString
& rRole
, bool bUseTextLabel
)
703 DataSourceModel
* pValues
= mrModel
.maSources
.get( eSourceType
).get();
704 TextModel
* pTitle
= bUseTextLabel
? mrModel
.mxText
.get() : 0;
705 return lclCreateLabeledDataSequence( *this, pValues
, rRole
, pTitle
);
709 } // namespace drawingml
712 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */