Version 6.4.0.0.beta1, tag libreoffice-6.4.0.0.beta1
[LibreOffice.git] / oox / source / drawingml / chart / typegroupconverter.cxx
blob1b6b20865a4849c80d8c4aba6c98eda35a89e31b
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <drawingml/chart/typegroupconverter.hxx>
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 <osl/diagnose.h>
37 #include <drawingml/lineproperties.hxx>
38 #include <drawingml/chart/seriesconverter.hxx>
39 #include <drawingml/chart/typegroupmodel.hxx>
40 #include <oox/core/xmlfilterbase.hxx>
41 #include <oox/helper/containerhelper.hxx>
42 #include <oox/token/namespaces.hxx>
43 #include <oox/token/properties.hxx>
44 #include <oox/token/tokens.hxx>
46 namespace oox {
47 namespace drawingml {
48 namespace chart {
50 using namespace ::com::sun::star::beans;
51 using namespace ::com::sun::star::chart2;
52 using namespace ::com::sun::star::chart2::data;
53 using namespace ::com::sun::star::uno;
55 namespace {
57 // chart type service names
58 const sal_Char SERVICE_CHART2_AREA[] = "com.sun.star.chart2.AreaChartType";
59 const sal_Char SERVICE_CHART2_CANDLE[] = "com.sun.star.chart2.CandleStickChartType";
60 const sal_Char SERVICE_CHART2_COLUMN[] = "com.sun.star.chart2.ColumnChartType";
61 const sal_Char SERVICE_CHART2_LINE[] = "com.sun.star.chart2.LineChartType";
62 const sal_Char SERVICE_CHART2_NET[] = "com.sun.star.chart2.NetChartType";
63 const sal_Char SERVICE_CHART2_FILLEDNET[] = "com.sun.star.chart2.FilledNetChartType";
64 const sal_Char SERVICE_CHART2_PIE[] = "com.sun.star.chart2.PieChartType";
65 const sal_Char SERVICE_CHART2_SCATTER[] = "com.sun.star.chart2.ScatterChartType";
66 const sal_Char SERVICE_CHART2_BUBBLE[] = "com.sun.star.chart2.BubbleChartType";
67 const sal_Char SERVICE_CHART2_SURFACE[] = "com.sun.star.chart2.ColumnChartType"; // Todo
69 namespace csscd = ::com::sun::star::chart::DataLabelPlacement;
71 static const TypeGroupInfo spTypeInfos[] =
73 // type-id type-category service varied-point-color default label pos polar area2d 1stvis xcateg swap stack revers picopt
74 { TYPEID_BAR, TYPECATEGORY_BAR, SERVICE_CHART2_COLUMN, VARPOINTMODE_SINGLE, csscd::OUTSIDE, false, true, false, true, false, true, false, true },
75 { TYPEID_HORBAR, TYPECATEGORY_BAR, SERVICE_CHART2_COLUMN, VARPOINTMODE_SINGLE, csscd::OUTSIDE, false, true, false, true, true, true, false, true },
76 { TYPEID_LINE, TYPECATEGORY_LINE, SERVICE_CHART2_LINE, VARPOINTMODE_SINGLE, csscd::RIGHT, false, false, false, true, false, true, false, false },
77 { TYPEID_AREA, TYPECATEGORY_LINE, SERVICE_CHART2_AREA, VARPOINTMODE_NONE, csscd::CENTER, false, true, false, true, false, true, true, false },
78 { TYPEID_STOCK, TYPECATEGORY_LINE, SERVICE_CHART2_CANDLE, VARPOINTMODE_NONE, csscd::RIGHT, false, false, false, true, false, true, false, false },
79 { TYPEID_RADARLINE, TYPECATEGORY_RADAR, SERVICE_CHART2_NET, VARPOINTMODE_SINGLE, csscd::TOP, true, false, false, true, false, false, false, false },
80 { TYPEID_RADARAREA, TYPECATEGORY_RADAR, SERVICE_CHART2_FILLEDNET, VARPOINTMODE_NONE, csscd::TOP, true, true, false, true, false, false, true, false },
81 { TYPEID_PIE, TYPECATEGORY_PIE, SERVICE_CHART2_PIE, VARPOINTMODE_MULTI, csscd::AVOID_OVERLAP, true, true, true, true, false, false, false, false },
82 { TYPEID_DOUGHNUT, TYPECATEGORY_PIE, SERVICE_CHART2_PIE, VARPOINTMODE_MULTI, csscd::AVOID_OVERLAP, true, true, false, true, false, false, false, false },
83 { TYPEID_OFPIE, TYPECATEGORY_PIE, SERVICE_CHART2_PIE, VARPOINTMODE_MULTI, csscd::AVOID_OVERLAP, true, true, true, true, false, false, false, false },
84 { TYPEID_SCATTER, TYPECATEGORY_SCATTER, SERVICE_CHART2_SCATTER, VARPOINTMODE_SINGLE, csscd::RIGHT, false, false, false, false, false, false, false, false },
85 { TYPEID_BUBBLE, TYPECATEGORY_SCATTER, SERVICE_CHART2_BUBBLE, VARPOINTMODE_SINGLE, csscd::RIGHT, false, true, false, false, false, false, false, false },
86 { TYPEID_SURFACE, TYPECATEGORY_SURFACE, SERVICE_CHART2_SURFACE, VARPOINTMODE_NONE, csscd::RIGHT, false, true, false, true, false, false, false, false }
89 static const TypeGroupInfo saUnknownTypeInfo =
90 { TYPEID_UNKNOWN, TYPECATEGORY_BAR, SERVICE_CHART2_COLUMN, VARPOINTMODE_SINGLE, csscd::OUTSIDE, false, true, false, true, false, true, false, true };
92 const TypeGroupInfo& lclGetTypeInfoFromTypeId( TypeId eTypeId )
94 for( auto const &rIt : spTypeInfos)
96 if( rIt.meTypeId == eTypeId )
97 return rIt;
99 OSL_ENSURE( eTypeId == TYPEID_UNKNOWN, "lclGetTypeInfoFromTypeId - unexpected chart type identifier" );
100 return saUnknownTypeInfo;
103 } // namespace
105 const TypeGroupInfo& GetTypeGroupInfo( TypeId eType )
107 return lclGetTypeInfoFromTypeId(eType);
110 UpDownBarsConverter::UpDownBarsConverter( const ConverterRoot& rParent, UpDownBarsModel& rModel ) :
111 ConverterBase< UpDownBarsModel >( rParent, rModel )
115 UpDownBarsConverter::~UpDownBarsConverter()
119 void UpDownBarsConverter::convertFromModel( const Reference< XChartType >& rxChartType )
121 PropertySet aTypeProp( rxChartType );
123 // upbar format
124 Reference< XPropertySet > xWhitePropSet;
125 if( aTypeProp.getProperty( xWhitePropSet, PROP_WhiteDay ) )
127 PropertySet aPropSet( xWhitePropSet );
128 getFormatter().convertFrameFormatting( aPropSet, mrModel.mxUpBars, OBJECTTYPE_UPBAR );
131 // downbar format
132 Reference< XPropertySet > xBlackPropSet;
133 if( aTypeProp.getProperty( xBlackPropSet, PROP_BlackDay ) )
135 PropertySet aPropSet( xBlackPropSet );
136 getFormatter().convertFrameFormatting( aPropSet, mrModel.mxDownBars, OBJECTTYPE_DOWNBAR );
140 TypeGroupConverter::TypeGroupConverter( const ConverterRoot& rParent, TypeGroupModel& rModel ) :
141 ConverterBase< TypeGroupModel >( rParent, rModel ),
142 mb3dChart( false )
144 TypeId eTypeId = TYPEID_UNKNOWN;
145 switch( mrModel.mnTypeId )
147 #define ENSURE_AXESCOUNT( min, max ) OSL_ENSURE( (min <= static_cast<int>(mrModel.maAxisIds.size())) && (static_cast<int>(mrModel.maAxisIds.size()) <= max), "TypeGroupConverter::TypeGroupConverter - invalid axes count" )
148 case C_TOKEN( area3DChart ): ENSURE_AXESCOUNT( 2, 3 ); eTypeId = TYPEID_AREA; mb3dChart = true; break;
149 case C_TOKEN( areaChart ): ENSURE_AXESCOUNT( 2, 2 ); eTypeId = TYPEID_AREA; mb3dChart = false; break;
150 case C_TOKEN( bar3DChart ): ENSURE_AXESCOUNT( 2, 3 ); eTypeId = TYPEID_BAR; mb3dChart = true; break;
151 case C_TOKEN( barChart ): ENSURE_AXESCOUNT( 2, 2 ); eTypeId = TYPEID_BAR; mb3dChart = false; break;
152 case C_TOKEN( bubbleChart ): ENSURE_AXESCOUNT( 2, 2 ); eTypeId = TYPEID_BUBBLE; mb3dChart = false; break;
153 case C_TOKEN( doughnutChart ): ENSURE_AXESCOUNT( 0, 0 ); eTypeId = TYPEID_DOUGHNUT; mb3dChart = false; break;
154 case C_TOKEN( line3DChart ): ENSURE_AXESCOUNT( 3, 3 ); eTypeId = TYPEID_LINE; mb3dChart = true; break;
155 case C_TOKEN( lineChart ): ENSURE_AXESCOUNT( 2, 2 ); eTypeId = TYPEID_LINE; mb3dChart = false; break;
156 case C_TOKEN( ofPieChart ): ENSURE_AXESCOUNT( 0, 0 ); eTypeId = TYPEID_OFPIE; mb3dChart = false; break;
157 case C_TOKEN( pie3DChart ): ENSURE_AXESCOUNT( 0, 0 ); eTypeId = TYPEID_PIE; mb3dChart = true; break;
158 case C_TOKEN( pieChart ): ENSURE_AXESCOUNT( 0, 0 ); eTypeId = TYPEID_PIE; mb3dChart = false; break;
159 case C_TOKEN( radarChart ): ENSURE_AXESCOUNT( 2, 2 ); eTypeId = TYPEID_RADARLINE; mb3dChart = false; break;
160 case C_TOKEN( scatterChart ): ENSURE_AXESCOUNT( 2, 2 ); eTypeId = TYPEID_SCATTER; mb3dChart = false; break;
161 case C_TOKEN( stockChart ): ENSURE_AXESCOUNT( 2, 2 ); eTypeId = TYPEID_STOCK; mb3dChart = false; break;
162 case C_TOKEN( surface3DChart ): ENSURE_AXESCOUNT( 3, 3 ); eTypeId = TYPEID_SURFACE; mb3dChart = true; break;
163 case C_TOKEN( surfaceChart ): ENSURE_AXESCOUNT( 2, 3 ); eTypeId = TYPEID_SURFACE; mb3dChart = true; break; // 3D bar chart from all surface charts
164 default: OSL_FAIL( "TypeGroupConverter::TypeGroupConverter - unknown chart type" );
165 #undef ENSURE_AXESCOUNT
168 // special handling for some chart types
169 switch( eTypeId )
171 case TYPEID_BAR:
172 if( mrModel.mnBarDir == XML_bar )
173 eTypeId = TYPEID_HORBAR;
174 break;
175 case TYPEID_RADARLINE:
176 if( mrModel.mnRadarStyle == XML_filled )
177 eTypeId = TYPEID_RADARAREA;
178 break;
179 case TYPEID_SURFACE:
180 // create a deep 3D bar chart from surface charts
181 mrModel.mnGrouping = XML_standard;
182 break;
183 default:;
186 // set the chart type info struct for the current chart type
187 maTypeInfo = lclGetTypeInfoFromTypeId( eTypeId );
190 TypeGroupConverter::~TypeGroupConverter()
194 bool TypeGroupConverter::isStacked() const
196 return maTypeInfo.mbSupportsStacking && (mrModel.mnGrouping == XML_stacked);
199 bool TypeGroupConverter::isPercent() const
201 return maTypeInfo.mbSupportsStacking && (mrModel.mnGrouping == XML_percentStacked);
204 bool TypeGroupConverter::isWall3dChart() const
206 return mb3dChart && (maTypeInfo.meTypeCategory != TYPECATEGORY_PIE);
209 bool TypeGroupConverter::isDeep3dChart() const
211 return isWall3dChart() && (mrModel.mnGrouping == XML_standard);
214 bool TypeGroupConverter::isSeriesFrameFormat() const
216 return mb3dChart || maTypeInfo.mbSeriesIsFrame2d;
219 ObjectType TypeGroupConverter::getSeriesObjectType() const
221 return mb3dChart ? OBJECTTYPE_FILLEDSERIES3D :
222 (maTypeInfo.mbSeriesIsFrame2d ? OBJECTTYPE_FILLEDSERIES2D : OBJECTTYPE_LINEARSERIES2D);
225 OUString TypeGroupConverter::getSingleSeriesTitle() const
227 OUString aSeriesTitle;
228 if( !mrModel.maSeries.empty() && (maTypeInfo.mbSingleSeriesVis || (mrModel.maSeries.size() == 1)) )
229 if( const TextModel* pText = mrModel.maSeries.front()->mxText.get() )
230 if( const DataSequenceModel* pDataSeq = pText->mxDataSeq.get() )
231 if( !pDataSeq->maData.empty() )
232 pDataSeq->maData.begin()->second >>= aSeriesTitle;
233 return aSeriesTitle;
236 Reference< XCoordinateSystem > TypeGroupConverter::createCoordinateSystem()
238 // create the coordinate system object
239 Reference< css::uno::XComponentContext > xContext = getComponentContext();
240 Reference< XCoordinateSystem > xCoordSystem;
241 if( maTypeInfo.mbPolarCoordSystem )
243 if( mb3dChart )
244 xCoordSystem = css::chart2::PolarCoordinateSystem3d::create(xContext);
245 else
246 xCoordSystem = css::chart2::PolarCoordinateSystem2d::create(xContext);
248 else
250 if( mb3dChart )
251 xCoordSystem = css::chart2::CartesianCoordinateSystem3d::create(xContext);
252 else
253 xCoordSystem = css::chart2::CartesianCoordinateSystem2d::create(xContext);
256 // swap X and Y axis
257 if( maTypeInfo.mbSwappedAxesSet )
259 PropertySet aPropSet( xCoordSystem );
260 aPropSet.setProperty( PROP_SwapXAndYAxis, true );
263 return xCoordSystem;
266 Reference< XLabeledDataSequence > TypeGroupConverter::createCategorySequence()
268 sal_Int32 nMaxValues = 0;
269 Reference< XLabeledDataSequence > xLabeledSeq;
270 /* Find first existing category sequence. The behaviour of Excel 2007 is
271 different to Excel 2003, which always used the category sequence of the
272 first series, even if it was empty. */
273 for (auto const& elem : mrModel.maSeries)
275 if( elem->maSources.has( SeriesModel::CATEGORIES ) && mrModel.mbCatAxisVisible)
277 SeriesConverter aSeriesConv(*this, *elem);
278 xLabeledSeq = aSeriesConv.createCategorySequence( "categories" );
279 if (xLabeledSeq.is())
280 break;
282 else if( nMaxValues <= 0 && elem->maSources.has( SeriesModel::VALUES ) )
284 DataSourceModel *pValues = elem->maSources.get( SeriesModel::VALUES ).get();
285 if( pValues->mxDataSeq.is() )
286 nMaxValues = pValues->mxDataSeq->maData.size();
289 /* n#839727 Create Category Sequence when none are found */
290 if( !xLabeledSeq.is() && !mrModel.maSeries.empty() && mrModel.mbCatAxisVisible) {
291 if( nMaxValues < 0 )
292 nMaxValues = 2;
293 SeriesModel &aModel = *mrModel.maSeries.get(0);
294 DataSourceModel &aSrc = aModel.maSources.create( SeriesModel::CATEGORIES );
295 DataSequenceModel &aSeq = aSrc.mxDataSeq.create();
296 aSeq.mnPointCount = nMaxValues;
297 for( sal_Int32 i = 0; i < nMaxValues; i++ )
298 aSeq.maData[ i ] <<= OUString::number( i + 1 );
299 SeriesConverter aSeriesConv( *this, aModel );
300 xLabeledSeq = aSeriesConv.createCategorySequence( "categories" );
302 return xLabeledSeq;
305 void TypeGroupConverter::convertFromModel( const Reference< XDiagram >& rxDiagram,
306 const Reference< XCoordinateSystem >& rxCoordSystem,
307 sal_Int32 nAxesSetIdx, bool bSupportsVaryColorsByPoint )
311 // create the chart type object
312 OUString aService = OUString::createFromAscii( maTypeInfo.mpcServiceName );
313 Reference< XChartType > xChartType( createInstance( aService ), UNO_QUERY_THROW );
315 Reference< XChartTypeContainer > xChartTypeContOld( rxCoordSystem, UNO_QUERY_THROW );
316 Sequence< Reference< XChartType > > xOldChartTypes( xChartTypeContOld->getChartTypes() );
317 sal_Int32 nOldChartTypeIdx = -1;
319 // additional properties
320 PropertySet aDiaProp( rxDiagram );
321 PropertySet aTypeProp( xChartType );
322 switch( maTypeInfo.meTypeCategory )
324 case TYPECATEGORY_BAR:
326 Sequence< sal_Int32 > aInt32Seq( 2 );
327 aInt32Seq[ 0 ] = aInt32Seq[ 1 ] = mrModel.mnOverlap;
328 aTypeProp.setProperty( PROP_OverlapSequence, aInt32Seq );
329 aInt32Seq[ 0 ] = aInt32Seq[ 1 ] = mrModel.mnGapWidth;
330 aTypeProp.setProperty( PROP_GapwidthSequence, aInt32Seq );
332 break;
333 case TYPECATEGORY_PIE:
335 aTypeProp.setProperty( PROP_UseRings, maTypeInfo.meTypeId == TYPEID_DOUGHNUT );
336 /* #i85166# starting angle of first pie slice. 3D pie charts
337 use Y rotation setting in view3D element. Of-pie charts do
338 not support pie rotation. */
339 if( !is3dChart() && (maTypeInfo.meTypeId != TYPEID_OFPIE) )
340 convertPieRotation( aDiaProp, mrModel.mnFirstAngle );
342 break;
343 default:;
346 // create converter objects for all series models
347 typedef RefVector< SeriesConverter > SeriesConvVector;
348 SeriesConvVector aSeries;
349 for (auto const& elemSeries : mrModel.maSeries)
350 aSeries.push_back( std::make_shared<SeriesConverter>(*this, *elemSeries) );
352 // reverse series order for some unstacked 2D chart types
353 if( maTypeInfo.mbReverseSeries && !mb3dChart && !isStacked() && !isPercent() )
354 ::std::reverse( aSeries.begin(), aSeries.end() );
356 // decide whether to use varying colors for each data point
357 bool bVaryColorsByPoint = bSupportsVaryColorsByPoint && mrModel.mbVaryColors;
358 switch( maTypeInfo.meVarPointMode )
360 case VARPOINTMODE_NONE: bVaryColorsByPoint = false; break;
361 case VARPOINTMODE_SINGLE: bVaryColorsByPoint &= (mrModel.maSeries.size() == 1); break;
362 case VARPOINTMODE_MULTI: break;
365 /* Stock chart needs special processing. Create one 'big' series with
366 data sequences of different roles. */
367 if( maTypeInfo.meTypeId == TYPEID_STOCK )
369 // create the data series object
370 Reference< XDataSeries > xDataSeries( createInstance( "com.sun.star.chart2.DataSeries" ), UNO_QUERY );
371 Reference< XDataSink > xDataSink( xDataSeries, UNO_QUERY );
372 if( xDataSink.is() )
374 // create a list of data sequences from all series
375 ::std::vector< Reference< XLabeledDataSequence > > aLabeledSeqVec;
376 OSL_ENSURE( aSeries.size() >= 3, "TypeGroupConverter::convertFromModel - too few stock chart series" );
377 int nRoleIdx = (aSeries.size() == 3) ? 1 : 0;
378 for( auto& rxSeriesConv : aSeries )
380 // create a data sequence with a specific role
381 OUString aRole;
382 switch( nRoleIdx )
384 case 0: aRole = "values-first"; break;
385 case 1: aRole = "values-max"; break;
386 case 2: aRole = "values-min"; break;
387 case 3: aRole = "values-last"; break;
389 Reference< XLabeledDataSequence > xDataSeq = rxSeriesConv->createValueSequence( aRole );
390 if( xDataSeq.is() )
391 aLabeledSeqVec.push_back( xDataSeq );
393 ++nRoleIdx;
394 if (nRoleIdx >= 4)
395 break;
398 // attach labeled data sequences to series and insert series into chart type
399 xDataSink->setData( ContainerHelper::vectorToSequence( aLabeledSeqVec ) );
401 // formatting of high/low lines
402 aTypeProp.setProperty( PROP_ShowHighLow, true );
403 PropertySet aSeriesProp( xDataSeries );
404 if( mrModel.mxHiLowLines.is() )
405 getFormatter().convertFrameFormatting( aSeriesProp, mrModel.mxHiLowLines, OBJECTTYPE_HILOLINE );
406 else
407 // hi/low-lines cannot be switched off via "ShowHighLow" property (?)
408 aSeriesProp.setProperty( PROP_LineStyle, css::drawing::LineStyle_NONE );
410 // formatting of up/down bars
411 bool bUpDownBars = mrModel.mxUpDownBars.is();
412 aTypeProp.setProperty( PROP_Japanese, bUpDownBars );
413 aTypeProp.setProperty( PROP_ShowFirst, bUpDownBars );
414 if( bUpDownBars )
416 UpDownBarsConverter aUpDownConv( *this, *mrModel.mxUpDownBars );
417 aUpDownConv.convertFromModel( xChartType );
420 // insert the series into the chart type object
421 insertDataSeries( xChartType, xDataSeries, nAxesSetIdx );
424 else
426 for( sal_Int32 nCTIdx=0; nCTIdx<xOldChartTypes.getLength(); ++nCTIdx )
428 if ( xChartType->getChartType() == xOldChartTypes[nCTIdx]->getChartType() )
430 nOldChartTypeIdx = nCTIdx;
434 for (auto const& elem : aSeries)
436 SeriesConverter& rSeriesConv = *elem;
437 Reference< XDataSeries > xDataSeries = rSeriesConv.createDataSeries( *this, bVaryColorsByPoint );
438 insertDataSeries( nOldChartTypeIdx == -1 ? xChartType : xOldChartTypes[nOldChartTypeIdx], xDataSeries, nAxesSetIdx );
440 /* Excel does not use the value of the c:smooth element of the
441 chart type to set a default line smoothing for the data
442 series. Line smoothing is always controlled by the c:smooth
443 element of the respective data series. If the element in the
444 data series is missing, line smoothing is off, regardless of
445 the c:smooth element of the chart type. */
446 #if !OOX_CHART_SMOOTHED_PER_SERIES
447 if( rSeriesConv.getModel().mbSmooth )
448 convertLineSmooth( aTypeProp, true );
449 #endif
453 // add chart type object to coordinate system
454 Reference< XChartTypeContainer > xChartTypeCont( rxCoordSystem, UNO_QUERY_THROW );
455 if (nOldChartTypeIdx == -1)
457 xChartTypeCont->addChartType(xChartType);
460 // set existence of bar connector lines at diagram (only in stacked 2D bar charts)
461 if( mrModel.mxSerLines.is() && !mb3dChart && (maTypeInfo.meTypeCategory == TYPECATEGORY_BAR) && (isStacked() || isPercent()) )
462 aDiaProp.setProperty( PROP_ConnectBars, true );
464 catch( Exception& )
466 OSL_FAIL( "TypeGroupConverter::convertFromModel - cannot add chart type" );
470 void TypeGroupConverter::convertMarker( PropertySet& rPropSet, sal_Int32 nOoxSymbol, sal_Int32 nOoxSize,
471 const ModelRef< Shape >& xShapeProps ) const
473 if( !isSeriesFrameFormat() )
475 namespace cssc = ::com::sun::star::chart2;
477 // symbol style
478 cssc::Symbol aSymbol;
479 aSymbol.Style = cssc::SymbolStyle_STANDARD;
480 switch( nOoxSymbol ) // compare with XclChPropSetHelper::WriteMarkerProperties in xlchart.cxx
482 case XML_auto: aSymbol.Style = cssc::SymbolStyle_AUTO; break;
483 case XML_none: aSymbol.Style = cssc::SymbolStyle_NONE; break;
484 case XML_square: aSymbol.StandardSymbol = 0; break; // square
485 case XML_diamond: aSymbol.StandardSymbol = 1; break; // diamond
486 case XML_triangle: aSymbol.StandardSymbol = 3; break; // arrow up
487 case XML_x: aSymbol.StandardSymbol = 10; break; // X, legacy bow tie
488 case XML_star: aSymbol.StandardSymbol = 12; break; // asterisk, legacy sand glass
489 case XML_dot: aSymbol.StandardSymbol = 4; break; // arrow right
490 case XML_dash: aSymbol.StandardSymbol = 13; break; // horizontal bar, legacy arrow down
491 case XML_circle: aSymbol.StandardSymbol = 8; break; // circle, legacy arrow right
492 case XML_plus: aSymbol.StandardSymbol = 11; break; // plus, legacy arrow left
495 // symbol size (points in OOXML, 1/100 mm in Chart2)
496 sal_Int32 nSize = static_cast< sal_Int32 >( nOoxSize * (2540.0 / 72.0) + 0.5 );
497 aSymbol.Size.Width = aSymbol.Size.Height = nSize;
499 if(xShapeProps.is())
501 Color aFillColor = xShapeProps->getFillProperties().maFillColor;
502 aSymbol.FillColor = sal_Int32(aFillColor.getColor(getFilter().getGraphicHelper()));
503 // tdf#124817: if there is no fill color, use line color of the symbol
504 if( aSymbol.FillColor < 0 )
506 Color aLineColor = xShapeProps->getLineProperties().maLineFill.maFillColor;
507 aSymbol.BorderColor = sal_Int32(aLineColor.getColor(getFilter().getGraphicHelper()));
508 rPropSet.setProperty(PROP_Color, aSymbol.BorderColor);
510 else
511 rPropSet.setProperty(PROP_Color, aSymbol.FillColor);
514 // set the property
515 rPropSet.setProperty( PROP_Symbol, aSymbol );
519 void TypeGroupConverter::convertLineSmooth( PropertySet& rPropSet, bool bOoxSmooth ) const
521 if( !isSeriesFrameFormat() && (maTypeInfo.meTypeCategory != TYPECATEGORY_RADAR) )
523 namespace cssc = ::com::sun::star::chart2;
524 cssc::CurveStyle eCurveStyle = bOoxSmooth ? cssc::CurveStyle_CUBIC_SPLINES : cssc::CurveStyle_LINES;
525 rPropSet.setProperty( PROP_CurveStyle, eCurveStyle );
529 void TypeGroupConverter::convertBarGeometry( PropertySet& rPropSet, sal_Int32 nOoxShape ) const
531 if( mb3dChart && (maTypeInfo.meTypeCategory == TYPECATEGORY_BAR) )
533 namespace cssc = ::com::sun::star::chart2;
535 sal_Int32 nGeom3d = cssc::DataPointGeometry3D::CUBOID;
536 switch( nOoxShape )
538 case XML_box: nGeom3d = cssc::DataPointGeometry3D::CUBOID; break;
539 case XML_cone: nGeom3d = cssc::DataPointGeometry3D::CONE; break;
540 case XML_coneToMax: nGeom3d = cssc::DataPointGeometry3D::CONE; break;
541 case XML_cylinder: nGeom3d = cssc::DataPointGeometry3D::CYLINDER; break;
542 case XML_pyramid: nGeom3d = cssc::DataPointGeometry3D::PYRAMID; break;
543 case XML_pyramidToMax: nGeom3d = cssc::DataPointGeometry3D::PYRAMID; break;
544 default: OSL_FAIL( "TypeGroupConverter::convertBarGeometry - unknown 3D bar shape type" );
546 rPropSet.setProperty( PROP_Geometry3D, nGeom3d );
550 void TypeGroupConverter::convertPieRotation( PropertySet& rPropSet, sal_Int32 nOoxAngle ) const
552 if( maTypeInfo.meTypeCategory == TYPECATEGORY_PIE )
554 // map OOXML [0,360] clockwise (0deg top) to Chart2 counterclockwise (0deg left)
555 sal_Int32 nAngle = (450 - nOoxAngle) % 360;
556 rPropSet.setProperty( PROP_StartingAngle, nAngle );
560 void TypeGroupConverter::convertPieExplosion( PropertySet& rPropSet, sal_Int32 nOoxExplosion ) const
562 if( maTypeInfo.meTypeCategory == TYPECATEGORY_PIE )
564 // pie explosion restricted to 100% in Chart2, set as double in range [0,1]
565 double fOffset = getLimitedValue< double >( nOoxExplosion / 100.0, 0.0, 1.0 );
566 rPropSet.setProperty( PROP_Offset, fOffset );
570 // private --------------------------------------------------------------------
572 void TypeGroupConverter::insertDataSeries( const Reference< XChartType >& rxChartType, const Reference< XDataSeries >& rxSeries, sal_Int32 nAxesSetIdx )
574 if( rxSeries.is() )
576 PropertySet aSeriesProp( rxSeries );
578 // series stacking mode
579 namespace cssc = ::com::sun::star::chart2;
580 cssc::StackingDirection eStacking = cssc::StackingDirection_NO_STACKING;
581 // stacked overrides deep-3d
582 if( isStacked() || isPercent() )
583 eStacking = cssc::StackingDirection_Y_STACKING;
584 else if( isDeep3dChart() )
585 eStacking = cssc::StackingDirection_Z_STACKING;
586 aSeriesProp.setProperty( PROP_StackingDirection, eStacking );
588 // additional series properties
589 aSeriesProp.setProperty( PROP_AttachedAxisIndex, nAxesSetIdx );
591 // insert series into container
594 Reference< XDataSeriesContainer > xSeriesCont( rxChartType, UNO_QUERY_THROW );
595 xSeriesCont->addDataSeries( rxSeries );
597 catch( Exception& )
599 OSL_FAIL( "TypeGroupConverter::insertDataSeries - cannot add data series" );
604 } // namespace chart
605 } // namespace drawingml
606 } // namespace oox
608 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */