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 "drawingml/chart/typegroupconverter.hxx"
21 :
22 : #include <com/sun/star/chart/DataLabelPlacement.hpp>
23 : #include <com/sun/star/chart2/CartesianCoordinateSystem2d.hpp>
24 : #include <com/sun/star/chart2/CartesianCoordinateSystem3d.hpp>
25 : #include <com/sun/star/chart2/PolarCoordinateSystem2d.hpp>
26 : #include <com/sun/star/chart2/PolarCoordinateSystem3d.hpp>
27 : #include <com/sun/star/chart2/CurveStyle.hpp>
28 : #include <com/sun/star/chart2/DataPointGeometry3D.hpp>
29 : #include <com/sun/star/chart2/StackingDirection.hpp>
30 : #include <com/sun/star/chart2/Symbol.hpp>
31 : #include <com/sun/star/chart2/XChartTypeContainer.hpp>
32 : #include <com/sun/star/chart2/XCoordinateSystem.hpp>
33 : #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
34 : #include <com/sun/star/chart2/data/XDataSink.hpp>
35 : #include <com/sun/star/drawing/LineStyle.hpp>
36 : #include "oox/drawingml/lineproperties.hxx"
37 : #include "drawingml/chart/seriesconverter.hxx"
38 : #include "drawingml/chart/typegroupmodel.hxx"
39 : #include "oox/helper/containerhelper.hxx"
40 :
41 : namespace oox {
42 : namespace drawingml {
43 : namespace chart {
44 :
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;
49 :
50 : namespace {
51 :
52 : // chart type service names
53 : const sal_Char SERVICE_CHART2_AREA[] = "com.sun.star.chart2.AreaChartType";
54 : const sal_Char SERVICE_CHART2_CANDLE[] = "com.sun.star.chart2.CandleStickChartType";
55 : const sal_Char SERVICE_CHART2_COLUMN[] = "com.sun.star.chart2.ColumnChartType";
56 : const sal_Char SERVICE_CHART2_LINE[] = "com.sun.star.chart2.LineChartType";
57 : const sal_Char SERVICE_CHART2_NET[] = "com.sun.star.chart2.NetChartType";
58 : const sal_Char SERVICE_CHART2_FILLEDNET[] = "com.sun.star.chart2.FilledNetChartType";
59 : const sal_Char SERVICE_CHART2_PIE[] = "com.sun.star.chart2.PieChartType";
60 : const sal_Char SERVICE_CHART2_SCATTER[] = "com.sun.star.chart2.ScatterChartType";
61 : const sal_Char SERVICE_CHART2_BUBBLE[] = "com.sun.star.chart2.BubbleChartType";
62 : const sal_Char SERVICE_CHART2_SURFACE[] = "com.sun.star.chart2.ColumnChartType"; // Todo
63 :
64 : namespace csscd = ::com::sun::star::chart::DataLabelPlacement;
65 :
66 : static const TypeGroupInfo spTypeInfos[] =
67 : {
68 : // type-id type-category service varied-point-color default label pos comb2d supp3d polar area2d 1stvis xcateg swap stack revers betw picopt
69 : { TYPEID_BAR, TYPECATEGORY_BAR, SERVICE_CHART2_COLUMN, VARPOINTMODE_SINGLE, csscd::OUTSIDE, true, true, false, true, false, true, false, true, false, true, true },
70 : { TYPEID_HORBAR, TYPECATEGORY_BAR, SERVICE_CHART2_COLUMN, VARPOINTMODE_SINGLE, csscd::OUTSIDE, false, true, false, true, false, true, true, true, false, true, true },
71 : { TYPEID_LINE, TYPECATEGORY_LINE, SERVICE_CHART2_LINE, VARPOINTMODE_SINGLE, csscd::RIGHT, true, true, false, false, false, true, false, true, false, true, false },
72 : { TYPEID_AREA, TYPECATEGORY_LINE, SERVICE_CHART2_AREA, VARPOINTMODE_NONE, csscd::CENTER, true, true, false, true, false, true, false, true, true, false, false },
73 : { TYPEID_STOCK, TYPECATEGORY_LINE, SERVICE_CHART2_CANDLE, VARPOINTMODE_NONE, csscd::RIGHT, true, false, false, false, false, true, false, true, false, true, false },
74 : { TYPEID_RADARLINE, TYPECATEGORY_RADAR, SERVICE_CHART2_NET, VARPOINTMODE_SINGLE, csscd::TOP, false, false, true, false, false, true, false, false, false, false, false },
75 : { TYPEID_RADARAREA, TYPECATEGORY_RADAR, SERVICE_CHART2_FILLEDNET, VARPOINTMODE_NONE, csscd::TOP, false, false, true, true, false, true, false, false, true, false, false },
76 : { TYPEID_PIE, TYPECATEGORY_PIE, SERVICE_CHART2_PIE, VARPOINTMODE_MULTI, csscd::AVOID_OVERLAP, false, true, true, true, true, true, false, false, false, false, false },
77 : { TYPEID_DOUGHNUT, TYPECATEGORY_PIE, SERVICE_CHART2_PIE, VARPOINTMODE_MULTI, csscd::AVOID_OVERLAP, false, true, true, true, false, true, false, false, false, false, false },
78 : { TYPEID_OFPIE, TYPECATEGORY_PIE, SERVICE_CHART2_PIE, VARPOINTMODE_MULTI, csscd::AVOID_OVERLAP, false, true, true, true, true, true, false, false, false, false, false },
79 : { TYPEID_SCATTER, TYPECATEGORY_SCATTER, SERVICE_CHART2_SCATTER, VARPOINTMODE_SINGLE, csscd::RIGHT, true, true, false, false, false, false, false, false, false, false, false },
80 : { TYPEID_BUBBLE, TYPECATEGORY_SCATTER, SERVICE_CHART2_BUBBLE, VARPOINTMODE_SINGLE, csscd::RIGHT, false, false, false, true, false, false, false, false, false, false, false },
81 : { TYPEID_SURFACE, TYPECATEGORY_SURFACE, SERVICE_CHART2_SURFACE, VARPOINTMODE_NONE, csscd::RIGHT, false, true, false, true, false, true, false, false, false, false, false }
82 : };
83 :
84 : static const TypeGroupInfo saUnknownTypeInfo =
85 : { TYPEID_UNKNOWN, TYPECATEGORY_BAR, SERVICE_CHART2_COLUMN, VARPOINTMODE_SINGLE, csscd::OUTSIDE, true, true, false, true, false, true, false, true, false, true, true };
86 :
87 410 : const TypeGroupInfo& lclGetTypeInfoFromTypeId( TypeId eTypeId )
88 : {
89 410 : const TypeGroupInfo* pEnd = STATIC_ARRAY_END( spTypeInfos );
90 1274 : for( const TypeGroupInfo* pIt = spTypeInfos; pIt != pEnd; ++pIt )
91 1274 : if( pIt->meTypeId == eTypeId )
92 410 : return *pIt;
93 : OSL_ENSURE( eTypeId == TYPEID_UNKNOWN, "lclGetTypeInfoFromTypeId - unexpected chart type identifier" );
94 0 : return saUnknownTypeInfo;
95 : }
96 :
97 : } // namespace
98 :
99 168 : const TypeGroupInfo& GetTypeGroupInfo( TypeId eType )
100 : {
101 168 : return lclGetTypeInfoFromTypeId(eType);
102 : }
103 :
104 4 : UpDownBarsConverter::UpDownBarsConverter( const ConverterRoot& rParent, UpDownBarsModel& rModel ) :
105 4 : ConverterBase< UpDownBarsModel >( rParent, rModel )
106 : {
107 4 : }
108 :
109 4 : UpDownBarsConverter::~UpDownBarsConverter()
110 : {
111 4 : }
112 :
113 4 : void UpDownBarsConverter::convertFromModel( const Reference< XChartType >& rxChartType )
114 : {
115 4 : PropertySet aTypeProp( rxChartType );
116 :
117 : // upbar format
118 8 : Reference< XPropertySet > xWhitePropSet;
119 4 : if( aTypeProp.getProperty( xWhitePropSet, PROP_WhiteDay ) )
120 : {
121 4 : PropertySet aPropSet( xWhitePropSet );
122 4 : getFormatter().convertFrameFormatting( aPropSet, mrModel.mxUpBars, OBJECTTYPE_UPBAR );
123 : }
124 :
125 : // downbar format
126 8 : Reference< XPropertySet > xBlackPropSet;
127 4 : if( aTypeProp.getProperty( xBlackPropSet, PROP_BlackDay ) )
128 : {
129 4 : PropertySet aPropSet( xBlackPropSet );
130 4 : getFormatter().convertFrameFormatting( aPropSet, mrModel.mxDownBars, OBJECTTYPE_DOWNBAR );
131 4 : }
132 4 : }
133 :
134 242 : TypeGroupConverter::TypeGroupConverter( const ConverterRoot& rParent, TypeGroupModel& rModel ) :
135 : ConverterBase< TypeGroupModel >( rParent, rModel ),
136 242 : mb3dChart( false )
137 : {
138 242 : TypeId eTypeId = TYPEID_UNKNOWN;
139 242 : switch( mrModel.mnTypeId )
140 : {
141 : #define ENSURE_AXESCOUNT( min, max ) OSL_ENSURE( (min <= (int)mrModel.maAxisIds.size()) && ((int)mrModel.maAxisIds.size() <= max), "TypeGroupConverter::TypeGroupConverter - invalid axes count" )
142 0 : case C_TOKEN( area3DChart ): ENSURE_AXESCOUNT( 2, 3 ); eTypeId = TYPEID_AREA; mb3dChart = true; break;
143 10 : case C_TOKEN( areaChart ): ENSURE_AXESCOUNT( 2, 2 ); eTypeId = TYPEID_AREA; mb3dChart = false; break;
144 58 : case C_TOKEN( bar3DChart ): ENSURE_AXESCOUNT( 2, 3 ); eTypeId = TYPEID_BAR; mb3dChart = true; break;
145 78 : case C_TOKEN( barChart ): ENSURE_AXESCOUNT( 2, 2 ); eTypeId = TYPEID_BAR; mb3dChart = false; break;
146 0 : case C_TOKEN( bubbleChart ): ENSURE_AXESCOUNT( 2, 2 ); eTypeId = TYPEID_BUBBLE; mb3dChart = false; break;
147 8 : case C_TOKEN( doughnutChart ): ENSURE_AXESCOUNT( 0, 0 ); eTypeId = TYPEID_DOUGHNUT; mb3dChart = false; break;
148 0 : case C_TOKEN( line3DChart ): ENSURE_AXESCOUNT( 3, 3 ); eTypeId = TYPEID_LINE; mb3dChart = true; break;
149 26 : case C_TOKEN( lineChart ): ENSURE_AXESCOUNT( 2, 2 ); eTypeId = TYPEID_LINE; mb3dChart = false; break;
150 2 : case C_TOKEN( ofPieChart ): ENSURE_AXESCOUNT( 0, 0 ); eTypeId = TYPEID_OFPIE; mb3dChart = false; break;
151 12 : case C_TOKEN( pie3DChart ): ENSURE_AXESCOUNT( 0, 0 ); eTypeId = TYPEID_PIE; mb3dChart = true; break;
152 20 : case C_TOKEN( pieChart ): ENSURE_AXESCOUNT( 0, 0 ); eTypeId = TYPEID_PIE; mb3dChart = false; break;
153 4 : case C_TOKEN( radarChart ): ENSURE_AXESCOUNT( 2, 2 ); eTypeId = TYPEID_RADARLINE; mb3dChart = false; break;
154 20 : case C_TOKEN( scatterChart ): ENSURE_AXESCOUNT( 2, 2 ); eTypeId = TYPEID_SCATTER; mb3dChart = false; break;
155 4 : case C_TOKEN( stockChart ): ENSURE_AXESCOUNT( 2, 2 ); eTypeId = TYPEID_STOCK; mb3dChart = false; break;
156 0 : case C_TOKEN( surface3DChart ): ENSURE_AXESCOUNT( 3, 3 ); eTypeId = TYPEID_SURFACE; mb3dChart = true; break;
157 0 : case C_TOKEN( surfaceChart ): ENSURE_AXESCOUNT( 2, 3 ); eTypeId = TYPEID_SURFACE; mb3dChart = true; break; // 3D bar chart from all surface charts
158 : default: OSL_FAIL( "TypeGroupConverter::TypeGroupConverter - unknown chart type" );
159 : #undef ENSURE_AXESCOUNT
160 : }
161 :
162 : // special handling for some chart types
163 242 : switch( eTypeId )
164 : {
165 : case TYPEID_BAR:
166 136 : if( mrModel.mnBarDir == XML_bar )
167 36 : eTypeId = TYPEID_HORBAR;
168 136 : break;
169 : case TYPEID_RADARLINE:
170 4 : if( mrModel.mnRadarStyle == XML_filled )
171 4 : eTypeId = TYPEID_RADARAREA;
172 4 : break;
173 : case TYPEID_SURFACE:
174 : // create a deep 3D bar chart from surface charts
175 0 : mrModel.mnGrouping = XML_standard;
176 0 : break;
177 : default:;
178 : }
179 :
180 : // set the chart type info struct for the current chart type
181 242 : maTypeInfo = lclGetTypeInfoFromTypeId( eTypeId );
182 242 : }
183 :
184 484 : TypeGroupConverter::~TypeGroupConverter()
185 : {
186 484 : }
187 :
188 524 : bool TypeGroupConverter::isStacked() const
189 : {
190 524 : return maTypeInfo.mbSupportsStacking && (mrModel.mnGrouping == XML_stacked);
191 : }
192 :
193 690 : bool TypeGroupConverter::isPercent() const
194 : {
195 690 : return maTypeInfo.mbSupportsStacking && (mrModel.mnGrouping == XML_percentStacked);
196 : }
197 :
198 852 : bool TypeGroupConverter::isWall3dChart() const
199 : {
200 852 : return mb3dChart && (maTypeInfo.meTypeCategory != TYPECATEGORY_PIE);
201 : }
202 :
203 614 : bool TypeGroupConverter::isDeep3dChart() const
204 : {
205 614 : return isWall3dChart() && (mrModel.mnGrouping == XML_standard);
206 : }
207 :
208 506 : bool TypeGroupConverter::isSeriesFrameFormat() const
209 : {
210 506 : return mb3dChart || maTypeInfo.mbSeriesIsFrame2d;
211 : }
212 :
213 690 : ObjectType TypeGroupConverter::getSeriesObjectType() const
214 : {
215 : return mb3dChart ? OBJECTTYPE_FILLEDSERIES3D :
216 690 : (maTypeInfo.mbSeriesIsFrame2d ? OBJECTTYPE_FILLEDSERIES2D : OBJECTTYPE_LINEARSERIES2D);
217 : }
218 :
219 242 : bool TypeGroupConverter::isReverseSeries() const
220 : {
221 242 : return maTypeInfo.mbReverseSeries && !mb3dChart && !isStacked() && !isPercent();
222 : }
223 :
224 234 : OUString TypeGroupConverter::getSingleSeriesTitle() const
225 : {
226 234 : OUString aSeriesTitle;
227 234 : if( !mrModel.maSeries.empty() && (maTypeInfo.mbSingleSeriesVis || (mrModel.maSeries.size() == 1)) )
228 110 : if( const TextModel* pText = mrModel.maSeries.front()->mxText.get() )
229 94 : if( const DataSequenceModel* pDataSeq = pText->mxDataSeq.get() )
230 94 : if( !pDataSeq->maData.empty() )
231 92 : pDataSeq->maData.begin()->second >>= aSeriesTitle;
232 234 : return aSeriesTitle;
233 : }
234 :
235 224 : Reference< XCoordinateSystem > TypeGroupConverter::createCoordinateSystem()
236 : {
237 : // create the coordinate system object
238 224 : Reference< css::uno::XComponentContext > xContext = getComponentContext();
239 224 : Reference< XCoordinateSystem > xCoordSystem;
240 224 : if( maTypeInfo.mbPolarCoordSystem )
241 : {
242 46 : if( mb3dChart )
243 12 : xCoordSystem = css::chart2::PolarCoordinateSystem3d::create(xContext);
244 : else
245 34 : xCoordSystem = css::chart2::PolarCoordinateSystem2d::create(xContext);
246 : }
247 : else
248 : {
249 178 : if( mb3dChart )
250 58 : xCoordSystem = css::chart2::CartesianCoordinateSystem3d::create(xContext);
251 : else
252 120 : xCoordSystem = css::chart2::CartesianCoordinateSystem2d::create(xContext);
253 : }
254 :
255 : // swap X and Y axis
256 224 : if( maTypeInfo.mbSwappedAxesSet )
257 : {
258 36 : PropertySet aPropSet( xCoordSystem );
259 36 : aPropSet.setProperty( PROP_SwapXAndYAxis, true );
260 : }
261 :
262 224 : return xCoordSystem;
263 : }
264 :
265 218 : Reference< XLabeledDataSequence > TypeGroupConverter::createCategorySequence()
266 : {
267 218 : sal_Int32 nMaxValues = 0;
268 218 : Reference< XLabeledDataSequence > xLabeledSeq;
269 : /* Find first existing category sequence. The bahaviour of Excel 2007 is
270 : different to Excel 2003, which always used the category sequence of the
271 : first series, even if it was empty. */
272 456 : for( TypeGroupModel::SeriesVector::iterator aIt = mrModel.maSeries.begin(), aEnd = mrModel.maSeries.end(); !xLabeledSeq.is() && (aIt != aEnd); ++aIt )
273 : {
274 238 : if( (*aIt)->maSources.has( SeriesModel::CATEGORIES ) )
275 : {
276 194 : SeriesConverter aSeriesConv( *this, **aIt );
277 194 : xLabeledSeq = aSeriesConv.createCategorySequence( "categories" );
278 : }
279 44 : else if( nMaxValues <= 0 && (*aIt)->maSources.has( SeriesModel::VALUES ) )
280 : {
281 24 : DataSourceModel *pValues = (*aIt)->maSources.get( SeriesModel::VALUES ).get();
282 24 : if( pValues->mxDataSeq.is() )
283 24 : nMaxValues = pValues->mxDataSeq.get()->maData.size();
284 : }
285 : }
286 : /* n#839727 Create Category Sequence when none are found */
287 218 : if( !xLabeledSeq.is() && mrModel.maSeries.size() > 0 ) {
288 24 : if( nMaxValues < 0 )
289 0 : nMaxValues = 2;
290 24 : SeriesModel &aModel = mrModel.maSeries.create();
291 24 : DataSourceModel &aSrc = aModel.maSources.create( SeriesModel::CATEGORIES );
292 24 : DataSequenceModel &aSeq = aSrc.mxDataSeq.create();
293 114 : for( sal_Int32 i = 0; i < nMaxValues; i++ )
294 90 : aSeq.maData[ i ] <<= OUString::number( i + 1 );
295 24 : SeriesConverter aSeriesConv( *this, aModel );
296 24 : xLabeledSeq = aSeriesConv.createCategorySequence( "categories" );
297 : }
298 218 : return xLabeledSeq;
299 : }
300 :
301 242 : void TypeGroupConverter::convertFromModel( const Reference< XDiagram >& rxDiagram,
302 : const Reference< XCoordinateSystem >& rxCoordSystem,
303 : sal_Int32 nAxesSetIdx, bool bSupportsVaryColorsByPoint )
304 : {
305 : try
306 : {
307 : // create the chart type object
308 242 : OUString aService = OUString::createFromAscii( maTypeInfo.mpcServiceName );
309 484 : Reference< XChartType > xChartType( createInstance( aService ), UNO_QUERY_THROW );
310 :
311 : // additional properties
312 484 : PropertySet aDiaProp( rxDiagram );
313 484 : PropertySet aTypeProp( xChartType );
314 242 : switch( maTypeInfo.meTypeCategory )
315 : {
316 : case TYPECATEGORY_BAR:
317 : {
318 136 : Sequence< sal_Int32 > aInt32Seq( 2 );
319 136 : aInt32Seq[ 0 ] = aInt32Seq[ 1 ] = mrModel.mnOverlap;
320 136 : aTypeProp.setProperty( PROP_OverlapSequence, aInt32Seq );
321 136 : aInt32Seq[ 0 ] = aInt32Seq[ 1 ] = mrModel.mnGapWidth;
322 136 : aTypeProp.setProperty( PROP_GapwidthSequence, aInt32Seq );
323 : }
324 136 : break;
325 : case TYPECATEGORY_PIE:
326 : {
327 42 : aTypeProp.setProperty( PROP_UseRings, maTypeInfo.meTypeId == TYPEID_DOUGHNUT );
328 : /* #i85166# starting angle of first pie slice. 3D pie charts
329 : use Y rotation setting in view3D element. Of-pie charts do
330 : not support pie rotation. */
331 42 : if( !is3dChart() && (maTypeInfo.meTypeId != TYPEID_OFPIE) )
332 28 : convertPieRotation( aDiaProp, mrModel.mnFirstAngle );
333 : }
334 42 : break;
335 : default:;
336 : }
337 :
338 : // create converter objects for all series models
339 : typedef RefVector< SeriesConverter > SeriesConvVector;
340 242 : SeriesConvVector aSeries;
341 764 : for( TypeGroupModel::SeriesVector::iterator aIt = mrModel.maSeries.begin(), aEnd = mrModel.maSeries.end(); aIt != aEnd; ++aIt )
342 522 : aSeries.push_back( SeriesConvVector::value_type( new SeriesConverter( *this, **aIt ) ) );
343 :
344 : // reverse series order for some unstacked 2D chart types
345 242 : if( isReverseSeries() )
346 4 : ::std::reverse( aSeries.begin(), aSeries.end() );
347 :
348 : // decide whether to use varying colors for each data point
349 242 : bool bVaryColorsByPoint = bSupportsVaryColorsByPoint && mrModel.mbVaryColors;
350 242 : switch( maTypeInfo.meVarPointMode )
351 : {
352 18 : case VARPOINTMODE_NONE: bVaryColorsByPoint = false; break;
353 182 : case VARPOINTMODE_SINGLE: bVaryColorsByPoint &= (mrModel.maSeries.size() == 1); break;
354 42 : case VARPOINTMODE_MULTI: break;
355 : }
356 :
357 : /* Stock chart needs special processing. Create one 'big' series with
358 : data sequences of different roles. */
359 242 : if( maTypeInfo.meTypeId == TYPEID_STOCK )
360 : {
361 : // create the data series object
362 4 : Reference< XDataSeries > xDataSeries( createInstance( "com.sun.star.chart2.DataSeries" ), UNO_QUERY );
363 8 : Reference< XDataSink > xDataSink( xDataSeries, UNO_QUERY );
364 4 : if( xDataSink.is() )
365 : {
366 : // create a list of data sequences from all series
367 4 : ::std::vector< Reference< XLabeledDataSequence > > aLabeledSeqVec;
368 : OSL_ENSURE( aSeries.size() >= 3, "TypeGroupConverter::convertFromModel - too few stock chart series" );
369 4 : int nRoleIdx = (aSeries.size() == 3) ? 1 : 0;
370 20 : for( SeriesConvVector::iterator aIt = aSeries.begin(), aEnd = aSeries.end(); (nRoleIdx < 4) && (aIt != aEnd); ++nRoleIdx, ++aIt )
371 : {
372 : // create a data sequence with a specific role
373 16 : OUString aRole;
374 16 : switch( nRoleIdx )
375 : {
376 4 : case 0: aRole = "values-first"; break;
377 4 : case 1: aRole = "values-max"; break;
378 4 : case 2: aRole = "values-min"; break;
379 4 : case 3: aRole = "values-last"; break;
380 : }
381 16 : Reference< XLabeledDataSequence > xDataSeq = (*aIt)->createValueSequence( aRole );
382 16 : if( xDataSeq.is() )
383 16 : aLabeledSeqVec.push_back( xDataSeq );
384 16 : }
385 :
386 : // attach labeled data sequences to series and insert series into chart type
387 4 : xDataSink->setData( ContainerHelper::vectorToSequence( aLabeledSeqVec ) );
388 :
389 : // formatting of high/low lines
390 4 : aTypeProp.setProperty( PROP_ShowHighLow, true );
391 4 : PropertySet aSeriesProp( xDataSeries );
392 4 : if( mrModel.mxHiLowLines.is() )
393 4 : getFormatter().convertFrameFormatting( aSeriesProp, mrModel.mxHiLowLines, OBJECTTYPE_HILOLINE );
394 : else
395 : // hi/low-lines cannot be switched off via "ShowHighLow" property (?)
396 0 : aSeriesProp.setProperty( PROP_LineStyle, ::com::sun::star::drawing::LineStyle_NONE );
397 :
398 : // formatting of up/down bars
399 4 : bool bUpDownBars = mrModel.mxUpDownBars.is();
400 4 : aTypeProp.setProperty( PROP_Japanese, bUpDownBars );
401 4 : aTypeProp.setProperty( PROP_ShowFirst, bUpDownBars );
402 4 : if( bUpDownBars )
403 : {
404 4 : UpDownBarsConverter aUpDownConv( *this, *mrModel.mxUpDownBars );
405 4 : aUpDownConv.convertFromModel( xChartType );
406 : }
407 :
408 : // insert the series into the chart type object
409 4 : insertDataSeries( xChartType, xDataSeries, nAxesSetIdx );
410 4 : }
411 : }
412 : else
413 : {
414 744 : for( SeriesConvVector::iterator aIt = aSeries.begin(), aEnd = aSeries.end(); aIt != aEnd; ++aIt )
415 : {
416 506 : SeriesConverter& rSeriesConv = **aIt;
417 506 : Reference< XDataSeries > xDataSeries = rSeriesConv.createDataSeries( *this, bVaryColorsByPoint );
418 506 : insertDataSeries( xChartType, xDataSeries, nAxesSetIdx );
419 :
420 : /* Excel does not use the value of the c:smooth element of the
421 : chart type to set a default line smoothing for the data
422 : series. Line smoothing is always controlled by the c:smooth
423 : element of the respective data series. If the element in the
424 : data series is missing, line smoothing is off, regardless of
425 : the c:smooth element of the chart type. */
426 : #if !OOX_CHART_SMOOTHED_PER_SERIES
427 506 : if( rSeriesConv.getModel().mbSmooth )
428 0 : convertLineSmooth( aTypeProp, true );
429 : #endif
430 506 : }
431 : }
432 :
433 : // add chart type object to coordinate system
434 242 : Reference< XChartTypeContainer > xChartTypeCont( rxCoordSystem, UNO_QUERY_THROW );
435 242 : xChartTypeCont->addChartType( xChartType );
436 :
437 : // set existence of bar connector lines at diagram (only in stacked 2D bar charts)
438 242 : if( mrModel.mxSerLines.is() && !mb3dChart && (maTypeInfo.meTypeCategory == TYPECATEGORY_BAR) && (isStacked() || isPercent()) )
439 242 : aDiaProp.setProperty( PROP_ConnectBars, true );
440 : }
441 0 : catch( Exception& )
442 : {
443 : OSL_FAIL( "TypeGroupConverter::convertFromModel - cannot add chart type" );
444 : }
445 242 : }
446 :
447 506 : void TypeGroupConverter::convertMarker( PropertySet& rPropSet, sal_Int32 nOoxSymbol, sal_Int32 nOoxSize,
448 : ModelRef< Shape > xShapeProps ) const
449 : {
450 506 : if( !isSeriesFrameFormat() )
451 : {
452 : namespace cssc = ::com::sun::star::chart2;
453 :
454 : // symbol style
455 86 : cssc::Symbol aSymbol;
456 86 : aSymbol.Style = cssc::SymbolStyle_STANDARD;
457 86 : switch( nOoxSymbol ) // compare with XclChPropSetHelper::WriteMarkerProperties in xlchart.cxx
458 : {
459 32 : case XML_auto: aSymbol.Style = cssc::SymbolStyle_AUTO; break;
460 20 : case XML_none: aSymbol.Style = cssc::SymbolStyle_NONE; break;
461 18 : case XML_square: aSymbol.StandardSymbol = 0; break; // square
462 2 : case XML_diamond: aSymbol.StandardSymbol = 1; break; // diamond
463 0 : case XML_triangle: aSymbol.StandardSymbol = 3; break; // arrow up
464 12 : case XML_x: aSymbol.StandardSymbol = 10; break; // X, legacy bow tie
465 0 : case XML_star: aSymbol.StandardSymbol = 12; break; // asterisk, legacy sand glass
466 0 : case XML_dot: aSymbol.StandardSymbol = 4; break; // arrow right
467 0 : case XML_dash: aSymbol.StandardSymbol = 13; break; // horizontal bar, legacy arrow down
468 2 : case XML_circle: aSymbol.StandardSymbol = 8; break; // circle, legacy arrow right
469 0 : case XML_plus: aSymbol.StandardSymbol = 11; break; // plus, legacy arrow left
470 : }
471 :
472 : // symbol size (points in OOXML, 1/100 mm in Chart2)
473 86 : sal_Int32 nSize = static_cast< sal_Int32 >( nOoxSize * (2540.0 / 72.0) + 0.5 );
474 86 : aSymbol.Size.Width = aSymbol.Size.Height = nSize;
475 :
476 86 : if(xShapeProps.is())
477 : {
478 26 : Color aFillColor = xShapeProps->getFillProperties().maFillColor;
479 26 : aSymbol.FillColor = aFillColor.getColor(getFilter().getGraphicHelper());
480 : }
481 :
482 : // set the property
483 86 : rPropSet.setProperty( PROP_Symbol, aSymbol );
484 : }
485 506 : }
486 :
487 0 : void TypeGroupConverter::convertLineSmooth( PropertySet& rPropSet, bool bOoxSmooth ) const
488 : {
489 0 : if( !isSeriesFrameFormat() && (maTypeInfo.meTypeCategory != TYPECATEGORY_RADAR) )
490 : {
491 : namespace cssc = ::com::sun::star::chart2;
492 0 : cssc::CurveStyle eCurveStyle = bOoxSmooth ? cssc::CurveStyle_CUBIC_SPLINES : cssc::CurveStyle_LINES;
493 0 : rPropSet.setProperty( PROP_CurveStyle, eCurveStyle );
494 : }
495 0 : }
496 :
497 506 : void TypeGroupConverter::convertBarGeometry( PropertySet& rPropSet, sal_Int32 nOoxShape ) const
498 : {
499 506 : if( mb3dChart && (maTypeInfo.meTypeCategory == TYPECATEGORY_BAR) )
500 : {
501 : namespace cssc = ::com::sun::star::chart2;
502 :
503 180 : sal_Int32 nGeom3d = cssc::DataPointGeometry3D::CUBOID;
504 180 : switch( nOoxShape )
505 : {
506 78 : case XML_box: nGeom3d = cssc::DataPointGeometry3D::CUBOID; break;
507 60 : case XML_cone: nGeom3d = cssc::DataPointGeometry3D::CONE; break;
508 0 : case XML_coneToMax: nGeom3d = cssc::DataPointGeometry3D::CONE; break;
509 42 : case XML_cylinder: nGeom3d = cssc::DataPointGeometry3D::CYLINDER; break;
510 0 : case XML_pyramid: nGeom3d = cssc::DataPointGeometry3D::PYRAMID; break;
511 0 : case XML_pyramidToMax: nGeom3d = cssc::DataPointGeometry3D::PYRAMID; break;
512 : default: OSL_FAIL( "TypeGroupConverter::convertBarGeometry - unknown 3D bar shape type" );
513 : }
514 180 : rPropSet.setProperty( PROP_Geometry3D, nGeom3d );
515 : }
516 506 : }
517 :
518 40 : void TypeGroupConverter::convertPieRotation( PropertySet& rPropSet, sal_Int32 nOoxAngle ) const
519 : {
520 40 : if( maTypeInfo.meTypeCategory == TYPECATEGORY_PIE )
521 : {
522 : // map OOXML [0,360] clockwise (0deg top) to Chart2 counterclockwise (0deg left)
523 40 : sal_Int32 nAngle = (450 - nOoxAngle) % 360;
524 40 : rPropSet.setProperty( PROP_StartingAngle, nAngle );
525 : }
526 40 : }
527 :
528 510 : void TypeGroupConverter::convertPieExplosion( PropertySet& rPropSet, sal_Int32 nOoxExplosion ) const
529 : {
530 510 : if( maTypeInfo.meTypeCategory == TYPECATEGORY_PIE )
531 : {
532 : // pie explosion restricted to 100% in Chart2, set as double in range [0,1]
533 52 : double fOffset = getLimitedValue< double >( nOoxExplosion / 100.0, 0.0, 1.0 );
534 52 : rPropSet.setProperty( PROP_Offset, fOffset );
535 : }
536 510 : }
537 :
538 : // private --------------------------------------------------------------------
539 :
540 510 : void TypeGroupConverter::insertDataSeries( const Reference< XChartType >& rxChartType, const Reference< XDataSeries >& rxSeries, sal_Int32 nAxesSetIdx )
541 : {
542 510 : if( rxSeries.is() )
543 : {
544 510 : PropertySet aSeriesProp( rxSeries );
545 :
546 : // series stacking mode
547 : namespace cssc = ::com::sun::star::chart2;
548 510 : cssc::StackingDirection eStacking = cssc::StackingDirection_NO_STACKING;
549 : // stacked overrides deep-3d
550 510 : if( isStacked() || isPercent() )
551 134 : eStacking = cssc::StackingDirection_Y_STACKING;
552 376 : else if( isDeep3dChart() )
553 0 : eStacking = cssc::StackingDirection_Z_STACKING;
554 510 : aSeriesProp.setProperty( PROP_StackingDirection, eStacking );
555 :
556 : // additional series properties
557 510 : aSeriesProp.setProperty( PROP_AttachedAxisIndex, nAxesSetIdx );
558 :
559 : // insert series into container
560 : try
561 : {
562 510 : Reference< XDataSeriesContainer > xSeriesCont( rxChartType, UNO_QUERY_THROW );
563 510 : xSeriesCont->addDataSeries( rxSeries );
564 : }
565 0 : catch( Exception& )
566 : {
567 : OSL_FAIL( "TypeGroupConverter::insertDataSeries - cannot add data series" );
568 510 : }
569 : }
570 510 : }
571 :
572 : } // namespace chart
573 : } // namespace drawingml
574 408 : } // namespace oox
575 :
576 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|