Version 6.4.0.0.beta1, tag libreoffice-6.4.0.0.beta1
[LibreOffice.git] / oox / source / drawingml / chart / chartspaceconverter.cxx
blob997aa4d41fbe579f80c49cf326f3f57bdc7f7007
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/chartspaceconverter.hxx>
22 #include <com/sun/star/chart/MissingValueTreatment.hpp>
23 #include <com/sun/star/chart/XChartDocument.hpp>
24 #include <com/sun/star/chart2/XChartDocument.hpp>
25 #include <com/sun/star/chart2/XChartType.hpp>
26 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
27 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
28 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
29 #include <com/sun/star/chart2/XTitled.hpp>
30 #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
31 #include <com/sun/star/drawing/FillStyle.hpp>
32 #include <oox/core/xmlfilterbase.hxx>
33 #include <oox/drawingml/chart/chartconverter.hxx>
34 #include <oox/token/namespaces.hxx>
35 #include <oox/token/properties.hxx>
36 #include <oox/token/tokens.hxx>
37 #include <oox/helper/graphichelper.hxx>
38 #include <drawingml/chart/chartdrawingfragment.hxx>
39 #include <drawingml/chart/chartspacemodel.hxx>
40 #include <drawingml/chart/plotareaconverter.hxx>
41 #include <drawingml/chart/titleconverter.hxx>
42 #include <ooxresid.hxx>
43 #include <strings.hrc>
45 using namespace ::com::sun::star;
46 using ::com::sun::star::uno::Reference;
47 using ::com::sun::star::uno::Exception;
48 using ::com::sun::star::uno::UNO_QUERY;
49 using ::com::sun::star::uno::UNO_QUERY_THROW;
50 using ::com::sun::star::uno::makeAny;
51 using ::com::sun::star::drawing::XDrawPageSupplier;
52 using ::com::sun::star::drawing::XShapes;
53 using ::com::sun::star::chart2::XDiagram;
54 using ::com::sun::star::chart2::XTitled;
56 namespace oox {
57 namespace drawingml {
58 namespace chart {
60 using namespace ::com::sun::star::awt;
61 using namespace ::com::sun::star::chart2;
62 using namespace ::com::sun::star::chart2::data;
63 using namespace ::com::sun::star::drawing;
64 using namespace ::com::sun::star::uno;
65 using namespace ::com::sun::star::util;
67 ChartSpaceConverter::ChartSpaceConverter( const ConverterRoot& rParent, ChartSpaceModel& rModel ) :
68 ConverterBase< ChartSpaceModel >( rParent, rModel )
72 ChartSpaceConverter::~ChartSpaceConverter()
76 // Formulas with no numeric values and strings are zeroes in OOXML line charts also in the mode DispBlanksAs=gap,
77 // unlike in OpenDocument LEAVE_GAP mode. As a workaround, we will use the OpenDocument mode USE_ZERO, if the OOXML
78 // line chart has got formulas with no numeric values and strings, but it doesn't have empty cells, showing the
79 // same chart as in MSO. (Empty cells need gaps, so in that case, we cannot use this workaround).
80 static bool lcl_useWorkaroundForNoGapInOOXML( Reference< chart2::XChartDocument > const & xChartDoc)
82 Reference <chart2::XDiagram > xDiagram = xChartDoc->getFirstDiagram();
83 if ( !xDiagram.is() )
84 return false;
86 Reference< chart2::XCoordinateSystemContainer > xCooSysContainer( xDiagram, UNO_QUERY_THROW );
88 Sequence< Reference< chart2::XCoordinateSystem > > xCooSysSequence( xCooSysContainer->getCoordinateSystems());
89 if ( !xCooSysSequence.hasElements() )
90 return false;
92 Reference< chart2::XChartTypeContainer > xChartTypeContainer( xCooSysSequence[0], UNO_QUERY_THROW );
94 Sequence< Reference< chart2::XChartType > > xChartTypeSequence( xChartTypeContainer->getChartTypes() );
95 if ( !xChartTypeSequence.hasElements() )
96 return false;
98 const Reference<chart2::XChartType>& xCT = xChartTypeSequence[0];
100 if ( xCT->getChartType() != "com.sun.star.chart2.LineChartType" )
101 return false;
103 Reference<chart2::XDataSeriesContainer> xDSCont(xCT, uno::UNO_QUERY);
105 if (!xDSCont.is())
106 return false;
108 const Sequence<uno::Reference<chart2::XDataSeries> > aDataSeriesSeq = xDSCont->getDataSeries();
110 bool bHasNoGapBlankValue = false;
111 bool bHasEmptyCell = false;
113 for (const auto& rDataSeries : aDataSeriesSeq)
115 uno::Reference<chart2::data::XDataSource> xDSrc(rDataSeries, uno::UNO_QUERY);
116 if (!xDSrc.is())
117 return false;
119 const uno::Sequence<Reference<chart2::data::XLabeledDataSequence> > aDataSeqs = xDSrc->getDataSequences();
120 for (const auto& rDataSeq : aDataSeqs)
122 Reference<chart2::data::XDataSequence> xValues = rDataSeq->getValues();
123 if(!xValues.is())
124 return false;
125 Reference<beans::XPropertySet> xPropSet(xValues, uno::UNO_QUERY);
126 if (!xPropSet.is())
127 continue;
129 OUString aRoleName;
130 xPropSet->getPropertyValue("Role") >>= aRoleName;
131 if (aRoleName == "values-y")
133 const uno::Sequence<uno::Any> aData = xValues->getData();
134 for (const auto& rVal : aData)
136 double fVal;
137 OUString sStr;
138 if (rVal >>= fVal)
139 continue;
140 else if (rVal >>= sStr)
141 bHasNoGapBlankValue = true;
142 else
143 bHasEmptyCell = true;
149 return bHasNoGapBlankValue && !bHasEmptyCell;
152 void ChartSpaceConverter::convertFromModel( const Reference< XShapes >& rxExternalPage, const awt::Point& rChartPos )
154 /* create data provider (virtual function in the ChartConverter class,
155 derived converters may create an external data provider) */
156 getChartConverter().createDataProvider( getChartDocument() );
158 // formatting of the chart background. The default fill style varies with applications.
159 PropertySet aBackPropSet( getChartDocument()->getPageBackground() );
160 getFormatter().convertFrameFormatting( aBackPropSet, mrModel.mxShapeProp, OBJECTTYPE_CHARTSPACE );
162 bool bMSO2007Doc = getFilter().isMSO2007Document();
163 // convert plot area (container of all chart type groups)
164 PlotAreaConverter aPlotAreaConv( *this, mrModel.mxPlotArea.getOrCreate() );
165 aPlotAreaConv.convertFromModel( mrModel.mxView3D.getOrCreate(bMSO2007Doc) );
167 // plot area converter has created the diagram object
168 Reference< XDiagram > xDiagram = getChartDocument()->getFirstDiagram();
170 // convert wall and floor formatting in 3D charts
171 if( xDiagram.is() && aPlotAreaConv.isWall3dChart() )
173 WallFloorConverter aFloorConv( *this, mrModel.mxFloor.getOrCreate() );
174 aFloorConv.convertFromModel( xDiagram, OBJECTTYPE_FLOOR );
176 WallFloorConverter aWallConv( *this, mrModel.mxBackWall.getOrCreate() );
177 aWallConv.convertFromModel( xDiagram, OBJECTTYPE_WALL );
180 // chart title
181 if( !mrModel.mbAutoTitleDel ) try
183 /* If the title model is missing, but the chart shows exactly one
184 series, the series title is shown as chart title. */
185 OUString aAutoTitle = aPlotAreaConv.getAutomaticTitle();
186 if( mrModel.mxTitle.is() || !aAutoTitle.isEmpty() )
188 if( aAutoTitle.isEmpty() )
189 aAutoTitle = OoxResId(STR_DIAGRAM_TITLE);
190 Reference< XTitled > xTitled( getChartDocument(), UNO_QUERY_THROW );
191 TitleConverter aTitleConv( *this, mrModel.mxTitle.getOrCreate() );
192 aTitleConv.convertFromModel( xTitled, aAutoTitle, OBJECTTYPE_CHARTTITLE );
195 catch( Exception& )
199 // legend
200 if( xDiagram.is() && mrModel.mxLegend.is() )
202 LegendConverter aLegendConv( *this, *mrModel.mxLegend );
203 aLegendConv.convertFromModel( xDiagram );
206 // treatment of missing values
207 if( xDiagram.is() )
209 using namespace ::com::sun::star::chart::MissingValueTreatment;
210 sal_Int32 nMissingValues = LEAVE_GAP;
211 switch( mrModel.mnDispBlanksAs )
213 case XML_gap: nMissingValues = LEAVE_GAP; break;
214 case XML_zero: nMissingValues = USE_ZERO; break;
215 case XML_span: nMissingValues = CONTINUE; break;
218 // use a workaround, if it's possible for the difference of OOXML and OpenDocument
219 if ( nMissingValues == LEAVE_GAP && lcl_useWorkaroundForNoGapInOOXML(getChartDocument()) )
220 nMissingValues = USE_ZERO;
222 PropertySet aDiaProp( xDiagram );
223 aDiaProp.setProperty( PROP_MissingValueTreatment, nMissingValues );
226 /* Following all conversions needing the old Chart1 API that involves full
227 initialization of the chart view. */
228 namespace cssc = ::com::sun::star::chart;
229 Reference< cssc::XChartDocument > xChart1Doc( getChartDocument(), UNO_QUERY );
230 if( xChart1Doc.is() )
232 /* Set the IncludeHiddenCells property via the old API as only this
233 ensures that the data provider and all created sequences get this
234 flag correctly. */
235 PropertySet aDiaProp( xChart1Doc->getDiagram() );
236 aDiaProp.setProperty( PROP_IncludeHiddenCells, !mrModel.mbPlotVisOnly );
238 // plot area position and size
239 aPlotAreaConv.convertPositionFromModel();
241 // positions of main title and all axis titles
242 convertTitlePositions();
245 // embedded drawing shapes
246 if( !mrModel.maDrawingPath.isEmpty() ) try
248 /* Get the internal draw page of the chart document, if no external
249 drawing page has been passed. */
250 Reference< XShapes > xShapes;
251 awt::Point aShapesOffset( 0, 0 );
252 if( rxExternalPage.is() )
254 xShapes = rxExternalPage;
255 // offset for embedded shapes to move them inside the chart area
256 aShapesOffset = rChartPos;
258 else
260 Reference< XDrawPageSupplier > xDrawPageSupp( getChartDocument(), UNO_QUERY_THROW );
261 xShapes.set( xDrawPageSupp->getDrawPage(), UNO_QUERY_THROW );
264 /* If an external drawing page is passed, all embedded shapes will be
265 inserted there (used e.g. with 'chart sheets' in spreadsheet
266 documents). In this case, all types of shapes including OLE objects
267 are supported. If the shapes are inserted into the internal chart
268 drawing page instead, it is not possible to embed OLE objects. */
269 bool bOleSupport = rxExternalPage.is();
271 // now, xShapes is not null anymore
272 getFilter().importFragment( new ChartDrawingFragment(
273 getFilter(), mrModel.maDrawingPath, xShapes, getChartSize(), aShapesOffset, bOleSupport ) );
275 catch( Exception& )
279 // pivot chart
280 if ( mrModel.mbPivotChart )
282 PropertySet aProps( getChartDocument() );
283 aProps.setProperty( PROP_DisableDataTableDialog , true );
284 aProps.setProperty( PROP_DisableComplexChartTypes , true );
287 if(!mrModel.maSheetPath.isEmpty() )
289 Reference< css::chart::XChartDocument > xChartDoc( getChartDocument(), UNO_QUERY );
290 PropertySet aProps( xChartDoc->getDiagram() );
291 aProps.setProperty( PROP_ExternalData , uno::makeAny(mrModel.maSheetPath) );
295 } // namespace chart
296 } // namespace drawingml
297 } // namespace oox
299 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */