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