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
lclCreateLabeledDataSequence(const ConverterRoot & rParent,DataSourceModel * pValues,const OUString & rRole,TextModel * pTitle=0)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
lclConvertLabelFormatting(PropertySet & rPropSet,ObjectFormatter & rFormatter,const DataLabelModelBase & rDataLabel,const TypeGroupConverter & rTypeGroup,bool bDataSeriesLabel)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
DataLabelConverter(const ConverterRoot & rParent,DataLabelModel & rModel)161 DataLabelConverter::DataLabelConverter( const ConverterRoot& rParent, DataLabelModel& rModel ) :
162 ConverterBase< DataLabelModel >( rParent, rModel )
163 {
164 }
165
~DataLabelConverter()166 DataLabelConverter::~DataLabelConverter()
167 {
168 }
169
convertFromModel(const Reference<XDataSeries> & rxDataSeries,const TypeGroupConverter & rTypeGroup)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
DataLabelsConverter(const ConverterRoot & rParent,DataLabelsModel & rModel)184 DataLabelsConverter::DataLabelsConverter( const ConverterRoot& rParent, DataLabelsModel& rModel ) :
185 ConverterBase< DataLabelsModel >( rParent, rModel )
186 {
187 }
188
~DataLabelsConverter()189 DataLabelsConverter::~DataLabelsConverter()
190 {
191 }
192
convertFromModel(const Reference<XDataSeries> & rxDataSeries,const TypeGroupConverter & rTypeGroup)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
ErrorBarConverter(const ConverterRoot & rParent,ErrorBarModel & rModel)211 ErrorBarConverter::ErrorBarConverter( const ConverterRoot& rParent, ErrorBarModel& rModel ) :
212 ConverterBase< ErrorBarModel >( rParent, rModel )
213 {
214 }
215
~ErrorBarConverter()216 ErrorBarConverter::~ErrorBarConverter()
217 {
218 }
219
convertFromModel(const Reference<XDataSeries> & rxDataSeries)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
createLabeledDataSequence(ErrorBarModel::SourceType eSourceType)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
TrendlineLabelConverter(const ConverterRoot & rParent,TrendlineLabelModel & rModel)339 TrendlineLabelConverter::TrendlineLabelConverter( const ConverterRoot& rParent, TrendlineLabelModel& rModel ) :
340 ConverterBase< TrendlineLabelModel >( rParent, rModel )
341 {
342 }
343
~TrendlineLabelConverter()344 TrendlineLabelConverter::~TrendlineLabelConverter()
345 {
346 }
347
convertFromModel(PropertySet & rPropSet)348 void TrendlineLabelConverter::convertFromModel( PropertySet& rPropSet )
349 {
350 // formatting
351 getFormatter().convertFormatting( rPropSet, mrModel.mxShapeProp, mrModel.mxTextProp, OBJECTTYPE_TRENDLINELABEL );
352 }
353
354 // ============================================================================
355
TrendlineConverter(const ConverterRoot & rParent,TrendlineModel & rModel)356 TrendlineConverter::TrendlineConverter( const ConverterRoot& rParent, TrendlineModel& rModel ) :
357 ConverterBase< TrendlineModel >( rParent, rModel )
358 {
359 }
360
~TrendlineConverter()361 TrendlineConverter::~TrendlineConverter()
362 {
363 }
364
convertFromModel(const Reference<XDataSeries> & rxDataSeries)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
DataPointConverter(const ConverterRoot & rParent,DataPointModel & rModel)416 DataPointConverter::DataPointConverter( const ConverterRoot& rParent, DataPointModel& rModel ) :
417 ConverterBase< DataPointModel >( rParent, rModel )
418 {
419 }
420
~DataPointConverter()421 DataPointConverter::~DataPointConverter()
422 {
423 }
424
convertFromModel(const Reference<XDataSeries> & rxDataSeries,const TypeGroupConverter & rTypeGroup,const SeriesModel & rSeries)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
SeriesConverter(const ConverterRoot & rParent,SeriesModel & rModel)456 SeriesConverter::SeriesConverter( const ConverterRoot& rParent, SeriesModel& rModel ) :
457 ConverterBase< SeriesModel >( rParent, rModel )
458 {
459 }
460
~SeriesConverter()461 SeriesConverter::~SeriesConverter()
462 {
463 }
464
createCategorySequence(const OUString & rRole)465 Reference< XLabeledDataSequence > SeriesConverter::createCategorySequence( const OUString& rRole )
466 {
467 return createLabeledDataSequence( SeriesModel::CATEGORIES, rRole, false );
468 }
469
createValueSequence(const OUString & rRole)470 Reference< XLabeledDataSequence > SeriesConverter::createValueSequence( const OUString& rRole )
471 {
472 return createLabeledDataSequence( SeriesModel::VALUES, rRole, true );
473 }
474
createDataSeries(const TypeGroupConverter & rTypeGroup,bool bVaryColorsByPoint)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
createLabeledDataSequence(SeriesModel::SourceType eSourceType,const OUString & rRole,bool bUseTextLabel)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