1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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
;
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();
86 Reference
< chart2::XCoordinateSystemContainer
> xCooSysContainer( xDiagram
, UNO_QUERY_THROW
);
88 Sequence
< Reference
< chart2::XCoordinateSystem
> > xCooSysSequence( xCooSysContainer
->getCoordinateSystems());
89 if ( !xCooSysSequence
.hasElements() )
92 Reference
< chart2::XChartTypeContainer
> xChartTypeContainer( xCooSysSequence
[0], UNO_QUERY_THROW
);
94 Sequence
< Reference
< chart2::XChartType
> > xChartTypeSequence( xChartTypeContainer
->getChartTypes() );
95 if ( !xChartTypeSequence
.hasElements() )
98 const Reference
<chart2::XChartType
>& xCT
= xChartTypeSequence
[0];
100 if ( xCT
->getChartType() != "com.sun.star.chart2.LineChartType" )
103 Reference
<chart2::XDataSeriesContainer
> xDSCont(xCT
, uno::UNO_QUERY
);
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
);
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();
125 Reference
<beans::XPropertySet
> xPropSet(xValues
, uno::UNO_QUERY
);
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
)
140 else if (rVal
>>= sStr
)
141 bHasNoGapBlankValue
= true;
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
);
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
);
200 if( xDiagram
.is() && mrModel
.mxLegend
.is() )
202 LegendConverter
aLegendConv( *this, *mrModel
.mxLegend
);
203 aLegendConv
.convertFromModel( xDiagram
);
206 // treatment of missing values
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
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
;
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
) );
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
) );
296 } // namespace drawingml
299 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */