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