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 "SchXMLPlotAreaContext.hxx"
21 #include <SchXMLImport.hxx>
22 #include "SchXMLAxisContext.hxx"
23 #include "SchXMLSeries2Context.hxx"
24 #include "SchXMLTools.hxx"
25
26 #include <comphelper/processfactory.hxx>
27 #include <sal/log.hxx>
28 #include <tools/diagnose_ex.h>
29 #include <xmloff/xmlnamespace.hxx>
30 #include <xmloff/namespacemap.hxx>
31 #include <xmloff/xmluconv.hxx>
32 #include <xmloff/prstylei.hxx>
33 #include <xmloff/xmlstyle.hxx>
34 #include <oox/helper/containerhelper.hxx>
35
36 #include <com/sun/star/awt/Point.hpp>
37 #include <com/sun/star/awt/Size.hpp>
38 #include <com/sun/star/chart/ErrorBarStyle.hpp>
39 #include <com/sun/star/chart/X3DDisplay.hpp>
40 #include <com/sun/star/chart/XStatisticDisplay.hpp>
41 #include <com/sun/star/chart/XDiagramPositioning.hpp>
42 #include <com/sun/star/chart/XChartDocument.hpp>
43 #include <com/sun/star/chart2/XChartDocument.hpp>
44 #include <com/sun/star/chart2/data/XDataSink.hpp>
45 #include <com/sun/star/chart2/data/XRangeXMLConversion.hpp>
46 #include <com/sun/star/chart2/data/LabeledDataSequence.hpp>
47 #include <com/sun/star/drawing/CameraGeometry.hpp>
48 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
49 #include <com/sun/star/lang/XServiceInfo.hpp>
50 #include <com/sun/star/xml/sax/XAttributeList.hpp>
51
52 using namespace com::sun::star;
53 using namespace ::xmloff::token;
54
55 using com::sun::star::uno::Reference;
56
57 namespace
58 {
59
60 struct lcl_AxisHasCategories
61 {
operator ()__anon361f00960111::lcl_AxisHasCategories62 bool operator() ( const SchXMLAxis & rAxis )
63 {
64 return rAxis.bHasCategories;
65 }
66 };
67
lcl_ConvertRange(const OUString & rRange,const uno::Reference<chart2::XChartDocument> & xDoc)68 OUString lcl_ConvertRange( const OUString & rRange, const uno::Reference< chart2::XChartDocument > & xDoc )
69 {
70 OUString aResult = rRange;
71 if(!xDoc.is())
72 return aResult;
73 uno::Reference< chart2::data::XRangeXMLConversion > xConversion(
74 xDoc->getDataProvider(), uno::UNO_QUERY );
75 if( xConversion.is())
76 aResult = xConversion->convertRangeFromXML( rRange );
77 return aResult;
78 }
79
80 } // anonymous namespace
81
SchXML3DSceneAttributesHelper(SvXMLImport & rImporter)82 SchXML3DSceneAttributesHelper::SchXML3DSceneAttributesHelper( SvXMLImport& rImporter )
83 : SdXML3DSceneAttributesHelper( rImporter )
84 {
85 }
86
getCameraDefaultFromDiagram(const uno::Reference<chart::XDiagram> & xDiagram)87 void SchXML3DSceneAttributesHelper::getCameraDefaultFromDiagram( const uno::Reference< chart::XDiagram >& xDiagram )
88 {
89 //different defaults for camera geometry necessary to workaround wrong behaviour in old chart
90 //in future make this version dependent if we have versioning (metastream) for ole objects
91
92 try
93 {
94 uno::Reference< beans::XPropertySet > xProp( xDiagram, uno::UNO_QUERY );
95 if( xProp.is() )
96 {
97 drawing::CameraGeometry aCamGeo;
98 xProp->getPropertyValue("D3DCameraGeometry") >>= aCamGeo;
99 maVRP.setX( aCamGeo.vrp.PositionX );
100 maVRP.setY( aCamGeo.vrp.PositionY );
101 maVRP.setZ( aCamGeo.vrp.PositionZ );
102 maVPN.setX( aCamGeo.vpn.DirectionX );
103 maVPN.setY( aCamGeo.vpn.DirectionY );
104 maVPN.setZ( aCamGeo.vpn.DirectionZ );
105 maVUP.setX( aCamGeo.vup.DirectionX );
106 maVUP.setY( aCamGeo.vup.DirectionY );
107 maVUP.setZ( aCamGeo.vup.DirectionZ );
108 }
109 }
110 catch( const uno::Exception & )
111 {
112 TOOLS_INFO_EXCEPTION("xmloff.chart", "Exception caught for property NumberOfLines");
113 }
114 }
115
~SchXML3DSceneAttributesHelper()116 SchXML3DSceneAttributesHelper::~SchXML3DSceneAttributesHelper()
117 {
118 }
119
SchXMLPlotAreaContext(SchXMLImportHelper & rImpHelper,SvXMLImport & rImport,const OUString & rXLinkHRefAttributeToIndicateDataProvider,OUString & rCategoriesAddress,OUString & rChartAddress,bool & rbHasRangeAtPlotArea,bool & rAllRangeAddressesAvailable,bool & rColHasLabels,bool & rRowHasLabels,chart::ChartDataRowSource & rDataRowSource,SeriesDefaultsAndStyles & rSeriesDefaultsAndStyles,const OUString & aChartTypeServiceName,tSchXMLLSequencesPerIndex & rLSequencesPerIndex,const awt::Size & rChartSize)120 SchXMLPlotAreaContext::SchXMLPlotAreaContext(
121 SchXMLImportHelper& rImpHelper,
122 SvXMLImport& rImport,
123 const OUString& rXLinkHRefAttributeToIndicateDataProvider,
124 OUString& rCategoriesAddress,
125 OUString& rChartAddress,
126 bool & rbHasRangeAtPlotArea,
127 bool & rAllRangeAddressesAvailable,
128 bool & rColHasLabels,
129 bool & rRowHasLabels,
130 chart::ChartDataRowSource & rDataRowSource,
131 SeriesDefaultsAndStyles& rSeriesDefaultsAndStyles,
132 const OUString& aChartTypeServiceName,
133 tSchXMLLSequencesPerIndex & rLSequencesPerIndex,
134 const awt::Size & rChartSize ) :
135 SvXMLImportContext( rImport ),
136 mrImportHelper( rImpHelper ),
137 mrCategoriesAddress( rCategoriesAddress ),
138 mrSeriesDefaultsAndStyles( rSeriesDefaultsAndStyles ),
139 mnNumOfLinesProp( 0 ),
140 mbStockHasVolume( false ),
141 mnSeries( 0 ),
142 m_aGlobalSeriesImportInfo( rAllRangeAddressesAvailable ),
143 maSceneImportHelper( rImport ),
144 m_aOuterPositioning( rImport ),
145 m_aInnerPositioning( rImport ),
146 mbPercentStacked(false),
147 m_bAxisPositionAttributeImported(false),
148 m_rXLinkHRefAttributeToIndicateDataProvider(rXLinkHRefAttributeToIndicateDataProvider),
149 mrChartAddress( rChartAddress ),
150 m_rbHasRangeAtPlotArea( rbHasRangeAtPlotArea ),
151 mrColHasLabels( rColHasLabels ),
152 mrRowHasLabels( rRowHasLabels ),
153 mrDataRowSource( rDataRowSource ),
154 maChartTypeServiceName( aChartTypeServiceName ),
155 mrLSequencesPerIndex( rLSequencesPerIndex ),
156 mbGlobalChartTypeUsedBySeries( false ),
157 maChartSize( rChartSize )
158 {
159 m_rbHasRangeAtPlotArea = false;
160
161 // get Diagram
162 uno::Reference< chart::XChartDocument > xDoc = rImpHelper.GetChartDocument();
163 if( xDoc.is())
164 {
165 mxDiagram = xDoc->getDiagram();
166 mxNewDoc.set( xDoc, uno::UNO_QUERY );
167
168 maSceneImportHelper.getCameraDefaultFromDiagram( mxDiagram );
169 }
170 SAL_WARN_IF( !mxDiagram.is(),"xmloff.chart", "Couldn't get XDiagram" );
171
172 // turn off all axes initially
173 uno::Any aFalseBool;
174 aFalseBool <<= false;
175
176 uno::Reference< lang::XServiceInfo > xInfo( mxDiagram, uno::UNO_QUERY );
177 uno::Reference< beans::XPropertySet > xProp( mxDiagram, uno::UNO_QUERY );
178 if( !xInfo.is() || !xProp.is() )
179 return;
180
181 try
182 {
183 xProp->setPropertyValue("HasXAxis", aFalseBool );
184 xProp->setPropertyValue("HasXAxisGrid", aFalseBool );
185 xProp->setPropertyValue("HasXAxisDescription", aFalseBool );
186 xProp->setPropertyValue("HasSecondaryXAxis", aFalseBool );
187 xProp->setPropertyValue("HasSecondaryXAxisDescription", aFalseBool );
188
189 xProp->setPropertyValue("HasYAxis", aFalseBool );
190 xProp->setPropertyValue("HasYAxisGrid", aFalseBool );
191 xProp->setPropertyValue("HasYAxisDescription", aFalseBool );
192 xProp->setPropertyValue("HasSecondaryYAxis", aFalseBool );
193 xProp->setPropertyValue("HasSecondaryYAxisDescription", aFalseBool );
194
195 xProp->setPropertyValue("HasZAxis", aFalseBool );
196 xProp->setPropertyValue("HasZAxisDescription", aFalseBool );
197
198 xProp->setPropertyValue("DataRowSource", uno::Any(chart::ChartDataRowSource_COLUMNS) );
199 }
200 catch( const beans::UnknownPropertyException & )
201 {
202 SAL_WARN("xmloff.chart", "Property required by service not supported" );
203 }
204 }
205
~SchXMLPlotAreaContext()206 SchXMLPlotAreaContext::~SchXMLPlotAreaContext()
207 {}
208
startFastElement(sal_Int32,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList)209 void SchXMLPlotAreaContext::startFastElement (sal_Int32 /*nElement*/,
210 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
211 {
212 // parse attributes
213 uno::Reference< chart2::XChartDocument > xNewDoc( GetImport().GetModel(), uno::UNO_QUERY );
214
215 for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
216 {
217 switch( aIter.getToken() )
218 {
219 case XML_ELEMENT(SVG, XML_X):
220 case XML_ELEMENT(SVG_COMPAT, XML_X):
221 case XML_ELEMENT(SVG, XML_Y):
222 case XML_ELEMENT(SVG_COMPAT, XML_Y):
223 case XML_ELEMENT(SVG, XML_WIDTH):
224 case XML_ELEMENT(SVG_COMPAT, XML_WIDTH):
225 case XML_ELEMENT(SVG, XML_HEIGHT):
226 case XML_ELEMENT(SVG_COMPAT, XML_HEIGHT):
227 m_aOuterPositioning.readPositioningAttribute( aIter.getToken(), aIter.toView() );
228 break;
229 case XML_ELEMENT(CHART, XML_STYLE_NAME):
230 msAutoStyleName = aIter.toString();
231 break;
232 case XML_ELEMENT(TABLE, XML_CELL_RANGE_ADDRESS):
233 mrChartAddress = lcl_ConvertRange( aIter.toString(), xNewDoc );
234 // indicator for getting data from the outside
235 m_rbHasRangeAtPlotArea = true;
236 break;
237 case XML_ELEMENT(CHART, XML_DATA_SOURCE_HAS_LABELS):
238 {
239 if( IsXMLToken(aIter, XML_BOTH) )
240 mrColHasLabels = mrRowHasLabels = true;
241 else if( IsXMLToken(aIter, XML_ROW) )
242 mrRowHasLabels = true;
243 else if( IsXMLToken(aIter, XML_COLUMN) )
244 mrColHasLabels = true;
245 }
246 break;
247 case XML_ELEMENT(DR3D, XML_TRANSFORM):
248 case XML_ELEMENT(DR3D, XML_VRP):
249 case XML_ELEMENT(DR3D, XML_VPN):
250 case XML_ELEMENT(DR3D, XML_VUP):
251 case XML_ELEMENT(DR3D, XML_PROJECTION):
252 case XML_ELEMENT(DR3D, XML_DISTANCE):
253 case XML_ELEMENT(DR3D, XML_FOCAL_LENGTH):
254 case XML_ELEMENT(DR3D, XML_SHADOW_SLANT):
255 case XML_ELEMENT(DR3D, XML_SHADE_MODE):
256 case XML_ELEMENT(DR3D, XML_AMBIENT_COLOR):
257 case XML_ELEMENT(DR3D, XML_LIGHTING_MODE):
258 maSceneImportHelper.processSceneAttribute( aIter );
259 break;
260 default:
261 XMLOFF_WARN_UNKNOWN("xmloff", aIter);
262 }
263 }
264
265 if( ! mxNewDoc.is())
266 {
267 uno::Reference< beans::XPropertySet > xDocProp( mrImportHelper.GetChartDocument(), uno::UNO_QUERY );
268 if( xDocProp.is())
269 {
270 try
271 {
272 xDocProp->setPropertyValue("DataSourceLabelsInFirstColumn", uno::Any(mrColHasLabels) );
273 xDocProp->setPropertyValue("DataSourceLabelsInFirstRow", uno::Any(mrRowHasLabels) );
274 }
275 catch( const beans::UnknownPropertyException & )
276 {
277 SAL_WARN("xmloff.chart", "Properties missing" );
278 }
279 }
280 }
281
282 // set properties
283 uno::Reference< beans::XPropertySet > xProp( mxDiagram, uno::UNO_QUERY );
284 if( !msAutoStyleName.isEmpty())
285 {
286 if( xProp.is())
287 {
288 const SvXMLStylesContext* pStylesCtxt = mrImportHelper.GetAutoStylesContext();
289 if( pStylesCtxt )
290 {
291 const SvXMLStyleContext* pStyle = pStylesCtxt->FindStyleChildContext(
292 SchXMLImportHelper::GetChartFamilyID(), msAutoStyleName );
293
294 XMLPropStyleContext* pPropStyleContext =
295 const_cast< XMLPropStyleContext * >(
296 dynamic_cast< const XMLPropStyleContext * >( pStyle ) );
297 if( pPropStyleContext )
298 {
299 pPropStyleContext->FillPropertySet( xProp );
300
301 // get the data row source that was set without having data
302 xProp->getPropertyValue("DataRowSource")
303 >>= mrDataRowSource;
304
305 //lines on/off
306 //this old property is not supported fully anymore with the new chart, so we need to get the information a little bit different from similar properties
307 mrSeriesDefaultsAndStyles.maLinesOnProperty = SchXMLTools::getPropertyFromContext(
308 u"Lines", pPropStyleContext, pStylesCtxt );
309
310 //handle automatic position and size
311 m_aOuterPositioning.readAutomaticPositioningProperties( pPropStyleContext, pStylesCtxt );
312
313 //correct default starting angle for old 3D pies
314 if( SchXMLTools::isDocumentGeneratedWithOpenOfficeOlderThan3_0( GetImport().GetModel() ) )
315 {
316 bool bIs3d = false;
317 if( xProp.is() && ( xProp->getPropertyValue("Dim3D") >>= bIs3d ) &&
318 bIs3d )
319 {
320 if( maChartTypeServiceName == "com.sun.star.chart2.PieChartType" || maChartTypeServiceName == "com.sun.star.chart2.DonutChartType" )
321 {
322 OUString aPropName( "StartingAngle" );
323 uno::Any aAStartingAngle( SchXMLTools::getPropertyFromContext( aPropName, pPropStyleContext, pStylesCtxt ) );
324 if( !aAStartingAngle.hasValue() )
325 xProp->setPropertyValue( aPropName, uno::makeAny(sal_Int32(0)) ) ;
326 }
327 }
328 }
329 }
330 }
331 }
332 }
333
334 //remember default values for dataseries
335 if(xProp.is())
336 {
337 try
338 {
339 mrSeriesDefaultsAndStyles.maSymbolTypeDefault = xProp->getPropertyValue("SymbolType");
340 mrSeriesDefaultsAndStyles.maDataCaptionDefault = xProp->getPropertyValue("DataCaption");
341
342 mrSeriesDefaultsAndStyles.maMeanValueDefault = xProp->getPropertyValue("MeanValue");
343 mrSeriesDefaultsAndStyles.maRegressionCurvesDefault = xProp->getPropertyValue("RegressionCurves");
344
345 bool bStacked = false;
346 mrSeriesDefaultsAndStyles.maStackedDefault = xProp->getPropertyValue("Stacked");
347 mrSeriesDefaultsAndStyles.maStackedDefault >>= bStacked;
348 mrSeriesDefaultsAndStyles.maPercentDefault = xProp->getPropertyValue("Percent");
349 mrSeriesDefaultsAndStyles.maPercentDefault >>= mbPercentStacked;
350 mrSeriesDefaultsAndStyles.maStackedBarsConnectedDefault = xProp->getPropertyValue("StackedBarsConnected");
351
352 // deep
353 uno::Any aDeepProperty( xProp->getPropertyValue("Deep"));
354 // #124488# old versions store a 3d area and 3D line deep chart with Deep==false => workaround for this
355 if( ! (bStacked || mbPercentStacked ))
356 {
357 if( SchXMLTools::isDocumentGeneratedWithOpenOfficeOlderThan2_3( GetImport().GetModel() ) )
358 {
359 bool bIs3d = false;
360 if( ( xProp->getPropertyValue("Dim3D") >>= bIs3d ) &&
361 bIs3d )
362 {
363 if( maChartTypeServiceName == "com.sun.star.chart2.AreaChartType" || maChartTypeServiceName == "com.sun.star.chart2.LineChartType" )
364 {
365 aDeepProperty <<= true;
366 }
367 }
368 }
369 }
370 mrSeriesDefaultsAndStyles.maDeepDefault = aDeepProperty;
371
372 xProp->getPropertyValue("NumberOfLines") >>= mnNumOfLinesProp;
373 xProp->getPropertyValue("Volume") >>= mbStockHasVolume;
374 }
375 catch( const uno::Exception & )
376 {
377 TOOLS_INFO_EXCEPTION("xmloff.chart", "PlotAreaContext:EndElement(): Exception caught");
378 }
379 } // if
380
381 bool bCreateInternalDataProvider = false;
382 if( m_rXLinkHRefAttributeToIndicateDataProvider == "." ) //data comes from the chart itself
383 bCreateInternalDataProvider = true;
384 else if( m_rXLinkHRefAttributeToIndicateDataProvider == ".." ) //data comes from the parent application
385 bCreateInternalDataProvider = false;
386 else if( !m_rXLinkHRefAttributeToIndicateDataProvider.isEmpty() ) //not supported so far to get the data by sibling objects -> fall back to chart itself
387 bCreateInternalDataProvider = true;
388 else if( !m_rbHasRangeAtPlotArea )
389 bCreateInternalDataProvider = true;
390
391 if( bCreateInternalDataProvider && mxNewDoc.is() )
392 {
393 // we have no complete range => we have own data, so switch the data
394 // provider to internal. Clone is not necessary, as we don't have any
395 // data yet.
396 mxNewDoc->createInternalDataProvider( false /* bCloneExistingData */ );
397 if( xProp.is() && mrDataRowSource!=chart::ChartDataRowSource_COLUMNS )
398 xProp->setPropertyValue("DataRowSource", uno::makeAny(mrDataRowSource) );
399 }
400 }
401
createFastChildContext(sal_Int32 nElement,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList)402 css::uno::Reference< css::xml::sax::XFastContextHandler > SchXMLPlotAreaContext::createFastChildContext(
403 sal_Int32 nElement,
404 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
405 {
406 SvXMLImportContext* pContext = nullptr;
407
408 switch(nElement)
409 {
410 case XML_ELEMENT(CHART_EXT, XML_COORDINATE_REGION):
411 case XML_ELEMENT(CHART, XML_COORDINATE_REGION):
412 {
413 pContext = new SchXMLCoordinateRegionContext( GetImport(), m_aInnerPositioning );
414 }
415 break;
416
417 case XML_ELEMENT(CHART, XML_AXIS):
418 {
419 bool bAddMissingXAxisForNetCharts = false;
420 bool bAdaptWrongPercentScaleValues = false;
421 if( SchXMLTools::isDocumentGeneratedWithOpenOfficeOlderThan2_3( GetImport().GetModel() ) )
422 {
423 //correct errors from older versions
424
425 // for NetCharts there were no xAxis exported to older files
426 // so we need to add the x axis here for those old NetChart files
427 if ( maChartTypeServiceName == "com.sun.star.chart2.NetChartType" )
428 bAddMissingXAxisForNetCharts = true;
429
430 //Issue 59288
431 if( mbPercentStacked )
432 bAdaptWrongPercentScaleValues = true;
433 }
434
435 bool bAdaptXAxisOrientationForOld2DBarCharts = false;
436 if( SchXMLTools::isDocumentGeneratedWithOpenOfficeOlderThan2_4( GetImport().GetModel() ) )
437 {
438 //issue74660
439 if ( maChartTypeServiceName == "com.sun.star.chart2.ColumnChartType" )
440 bAdaptXAxisOrientationForOld2DBarCharts = true;
441 }
442
443 pContext = new SchXMLAxisContext( mrImportHelper, GetImport(), mxDiagram, maAxes, mrCategoriesAddress,
444 bAddMissingXAxisForNetCharts, bAdaptWrongPercentScaleValues, bAdaptXAxisOrientationForOld2DBarCharts, m_bAxisPositionAttributeImported );
445 }
446 break;
447
448 case XML_ELEMENT(CHART, XML_SERIES):
449 {
450 if( mxNewDoc.is())
451 {
452 pContext = new SchXMLSeries2Context(
453 mrImportHelper, GetImport(),
454 mxNewDoc, maAxes,
455 mrSeriesDefaultsAndStyles.maSeriesStyleVector,
456 mrSeriesDefaultsAndStyles.maRegressionStyleVector,
457 mnSeries,
458 mbStockHasVolume,
459 m_aGlobalSeriesImportInfo,
460 maChartTypeServiceName,
461 mrLSequencesPerIndex,
462 mbGlobalChartTypeUsedBySeries, maChartSize );
463 }
464 mnSeries++;
465 }
466 break;
467
468 case XML_ELEMENT(CHART, XML_WALL):
469 pContext = new SchXMLWallFloorContext( mrImportHelper, GetImport(), mxDiagram,
470 SchXMLWallFloorContext::CONTEXT_TYPE_WALL );
471 break;
472 case XML_ELEMENT(CHART, XML_FLOOR):
473 pContext = new SchXMLWallFloorContext( mrImportHelper, GetImport(), mxDiagram,
474 SchXMLWallFloorContext::CONTEXT_TYPE_FLOOR );
475 break;
476
477 case XML_ELEMENT(DR3D, XML_LIGHT):
478 pContext = maSceneImportHelper.create3DLightContext( xAttrList );
479 break;
480
481 // elements for stock charts
482 case XML_ELEMENT(CHART, XML_STOCK_GAIN_MARKER):
483 pContext = new SchXMLStockContext( mrImportHelper, GetImport(), mxDiagram,
484 SchXMLStockContext::CONTEXT_TYPE_GAIN );
485 break;
486 case XML_ELEMENT(CHART, XML_STOCK_LOSS_MARKER):
487 pContext = new SchXMLStockContext( mrImportHelper, GetImport(), mxDiagram,
488 SchXMLStockContext::CONTEXT_TYPE_LOSS );
489 break;
490 case XML_ELEMENT(CHART, XML_STOCK_RANGE_LINE):
491 pContext = new SchXMLStockContext( mrImportHelper, GetImport(), mxDiagram,
492 SchXMLStockContext::CONTEXT_TYPE_RANGE );
493 break;
494 default:
495 XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
496 }
497
498 return pContext;
499 }
500
endFastElement(sal_Int32)501 void SchXMLPlotAreaContext::endFastElement(sal_Int32 )
502 {
503 // set categories
504 if( !mrCategoriesAddress.isEmpty() && mxNewDoc.is())
505 {
506 uno::Reference< chart2::data::XDataProvider > xDataProvider(
507 mxNewDoc->getDataProvider() );
508 // @todo: correct coordinate system index
509 sal_Int32 nDimension( 0 );
510 ::std::vector< SchXMLAxis >::const_iterator aIt(
511 ::std::find_if( maAxes.begin(), maAxes.end(), lcl_AxisHasCategories()));
512 if( aIt != maAxes.end())
513 nDimension = static_cast< sal_Int32 >( (*aIt).eDimension );
514 SchXMLTools::CreateCategories(
515 xDataProvider, mxNewDoc, mrCategoriesAddress,
516 0 /* nCooSysIndex */,
517 nDimension, &mrLSequencesPerIndex );
518 }
519
520 uno::Reference< beans::XPropertySet > xDiaProp( mxDiagram, uno::UNO_QUERY );
521 if( xDiaProp.is())
522 {
523 bool bIsThreeDim = false;
524 uno::Any aAny = xDiaProp->getPropertyValue("Dim3D");
525 aAny >>= bIsThreeDim;
526
527 // set 3d scene attributes
528 if( bIsThreeDim )
529 {
530 // set scene attributes at diagram
531 maSceneImportHelper.setSceneAttributes( xDiaProp );
532 }
533
534 // set correct number of lines at series
535 if( ! m_aGlobalSeriesImportInfo.rbAllRangeAddressesAvailable && mnNumOfLinesProp > 0 && maChartTypeServiceName == "com.sun.star.chart2.ColumnChartType" )
536 {
537 try
538 {
539 xDiaProp->setPropertyValue("NumberOfLines",
540 uno::makeAny( mnNumOfLinesProp ));
541 }
542 catch( const uno::Exception & )
543 {
544 TOOLS_INFO_EXCEPTION("xmloff.chart", "Exception caught for property NumberOfLines");
545 }
546 }
547
548 // #i32366# stock has volume
549 if( mxDiagram->getDiagramType() == "com.sun.star.chart.StockDiagram" &&
550 mbStockHasVolume )
551 {
552 try
553 {
554 xDiaProp->setPropertyValue("Volume",
555 uno::makeAny( true ));
556 }
557 catch( const uno::Exception & )
558 {
559 TOOLS_INFO_EXCEPTION("xmloff.chart", "Exception caught for property Volume");
560 }
561 }
562 }
563
564 // set changed size and position after properties (esp. 3d)
565
566 uno::Reference< chart::XDiagramPositioning > xDiaPos( mxDiagram, uno::UNO_QUERY );
567 if( xDiaPos.is())
568 {
569 if( !m_aOuterPositioning.isAutomatic() )
570 {
571 if( m_aInnerPositioning.hasPosSize() )
572 xDiaPos->setDiagramPositionExcludingAxes( m_aInnerPositioning.getRectangle() );
573 else if( m_aOuterPositioning.hasPosSize() )
574 {
575 if( SchXMLTools::isDocumentGeneratedWithOpenOfficeOlderThan3_3( GetImport().GetModel() ) ) //old version of OOo did write a wrong rectangle for the diagram size
576 xDiaPos->setDiagramPositionIncludingAxesAndAxisTitles( m_aOuterPositioning.getRectangle() );
577 else
578 xDiaPos->setDiagramPositionIncludingAxes( m_aOuterPositioning.getRectangle() );
579 }
580 }
581 }
582
583 SchXMLAxisContext::CorrectAxisPositions( uno::Reference< chart2::XChartDocument >( mrImportHelper.GetChartDocument(), uno::UNO_QUERY ), maChartTypeServiceName, GetImport().GetODFVersion(), m_bAxisPositionAttributeImported );
584 }
585
SchXMLDataLabelSpanContext(SvXMLImport & rImport,::std::vector<OUString> & rLabels)586 SchXMLDataLabelSpanContext::SchXMLDataLabelSpanContext( SvXMLImport& rImport, ::std::vector<OUString>& rLabels):
587 SvXMLImportContext( rImport ),
588 mrLabels(rLabels)
589 {
590 }
591
characters(const OUString & rChars)592 void SchXMLDataLabelSpanContext::characters(const OUString& rChars)
593 {
594 maCharBuffer.append(rChars);
595 }
596
endFastElement(sal_Int32)597 void SchXMLDataLabelSpanContext::endFastElement(sal_Int32 )
598 {
599 mrLabels.push_back(maCharBuffer.makeStringAndClear());
600 }
601
SchXMLDataLabelParaContext(SvXMLImport & rImport,::std::vector<OUString> & rLabels)602 SchXMLDataLabelParaContext::SchXMLDataLabelParaContext( SvXMLImport& rImport, ::std::vector<OUString>& rLabels):
603 SvXMLImportContext( rImport ),
604 mrLabels(rLabels)
605 {
606 }
607
createFastChildContext(sal_Int32 nElement,const css::uno::Reference<css::xml::sax::XFastAttributeList> &)608 css::uno::Reference< css::xml::sax::XFastContextHandler > SchXMLDataLabelParaContext::createFastChildContext(
609 sal_Int32 nElement,
610 const css::uno::Reference< css::xml::sax::XFastAttributeList >& )
611 {
612 if ( nElement == XML_ELEMENT(TEXT, XML_SPAN) )
613 return new SchXMLDataLabelSpanContext(GetImport(), mrLabels);
614 else
615 XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
616 return nullptr;
617 }
618
SchXMLDataLabelContext(SvXMLImport & rImport,::std::vector<OUString> & rLabels,DataRowPointStyle & rDataLabelStyle)619 SchXMLDataLabelContext::SchXMLDataLabelContext(SvXMLImport& rImport,
620 ::std::vector<OUString>& rLabels,
621 DataRowPointStyle& rDataLabelStyle)
622 : SvXMLImportContext(rImport)
623 , mrLabels(rLabels)
624 , mrDataLabelStyle(rDataLabelStyle)
625 {
626 }
627
createFastChildContext(sal_Int32 nElement,const css::uno::Reference<css::xml::sax::XFastAttributeList> &)628 css::uno::Reference< css::xml::sax::XFastContextHandler > SchXMLDataLabelContext::createFastChildContext(
629 sal_Int32 nElement,
630 const css::uno::Reference< css::xml::sax::XFastAttributeList >& )
631 {
632 if ( nElement == XML_ELEMENT(TEXT, XML_P) )
633 return new SchXMLDataLabelParaContext(GetImport(), mrLabels);
634 else
635 XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
636 return nullptr;
637 }
638
startFastElement(sal_Int32,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList)639 void SchXMLDataLabelContext::startFastElement(
640 sal_Int32 /*nElement*/,
641 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
642 {
643 for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
644 {
645 switch(aIter.getToken())
646 {
647 case XML_ELEMENT(SVG, XML_X):
648 case XML_ELEMENT(SVG_COMPAT, XML_X):
649 {
650 sal_Int32 nResultValue;
651 GetImport().GetMM100UnitConverter().convertMeasureToCore(nResultValue, aIter.toView());
652 mrDataLabelStyle.mo_nLabelAbsolutePosX = nResultValue;
653 break;
654 }
655 case XML_ELEMENT(SVG, XML_Y):
656 case XML_ELEMENT(SVG_COMPAT, XML_Y):
657 {
658 sal_Int32 nResultValue;
659 GetImport().GetMM100UnitConverter().convertMeasureToCore(nResultValue, aIter.toView());
660 mrDataLabelStyle.mo_nLabelAbsolutePosY = nResultValue;
661 break;
662 }
663 case XML_ELEMENT(CHART, XML_STYLE_NAME):
664 mrDataLabelStyle.msStyleName = aIter.toString();
665 break;
666 default:
667 XMLOFF_WARN_UNKNOWN("xmloff", aIter);
668 }
669 }
670 }
671
672
SchXMLDataPointContext(SvXMLImport & rImport,::std::vector<DataRowPointStyle> & rStyleVector,const css::uno::Reference<css::chart2::XDataSeries> & xSeries,sal_Int32 & rIndex,bool bSymbolSizeForSeriesIsMissingInFile)673 SchXMLDataPointContext::SchXMLDataPointContext( SvXMLImport& rImport,
674 ::std::vector< DataRowPointStyle >& rStyleVector,
675 const css::uno::Reference< css::chart2::XDataSeries >& xSeries,
676 sal_Int32& rIndex,
677 bool bSymbolSizeForSeriesIsMissingInFile ) :
678 SvXMLImportContext( rImport ),
679 mrStyleVector( rStyleVector ),
680 mrIndex( rIndex ),
681 mDataPoint(DataRowPointStyle::DATA_POINT, xSeries, rIndex, 1, OUString{}),
682 mDataLabel(DataRowPointStyle::DATA_LABEL_POINT, xSeries, rIndex, 1, OUString{})
683 {
684 mDataPoint.mbSymbolSizeForSeriesIsMissingInFile = bSymbolSizeForSeriesIsMissingInFile;
685 }
686
createFastChildContext(sal_Int32 nElement,const css::uno::Reference<css::xml::sax::XFastAttributeList> &)687 css::uno::Reference< css::xml::sax::XFastContextHandler > SchXMLDataPointContext::createFastChildContext(
688 sal_Int32 nElement,
689 const css::uno::Reference< css::xml::sax::XFastAttributeList >& )
690 {
691 SvXMLImportContext* pContext = nullptr;
692 switch(nElement)
693 {
694 case XML_ELEMENT(CHART, XML_DATA_LABEL):
695 mbHasLabelParagraph = true;
696 pContext = new SchXMLDataLabelContext(GetImport(), mDataPoint.mCustomLabels,
697 mDataLabel);
698 break;
699 default:
700 XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
701 }
702 return pContext;
703 }
704
~SchXMLDataPointContext()705 SchXMLDataPointContext::~SchXMLDataPointContext()
706 {
707 }
708
startFastElement(sal_Int32,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList)709 void SchXMLDataPointContext::startFastElement (sal_Int32 /*Element*/,
710 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
711 {
712 OUString sAutoStyleName;
713 sal_Int32 nRepeat = 1;
714 OUString sCustomLabelField;
715
716 for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
717 {
718 switch (aIter.getToken())
719 {
720 case XML_ELEMENT(CHART, XML_STYLE_NAME):
721 {
722 sAutoStyleName = aIter.toString();
723 mDataPoint.msStyleName = sAutoStyleName;
724 mDataLabel.msStyleNameOfParent = sAutoStyleName;
725 break;
726 }
727 case XML_ELEMENT(CHART, XML_REPEATED):
728 {
729 nRepeat = aIter.toInt32();
730 mDataPoint.m_nPointRepeat = nRepeat;
731 mDataLabel.m_nPointRepeat = nRepeat;
732 break;
733 }
734 // Deprecated. New documents use the chart:data-label element
735 // instead in order to store custom label text.
736 case XML_ELEMENT(LO_EXT, XML_CUSTOM_LABEL_FIELD):
737 if (!mbHasLabelParagraph)
738 {
739 sCustomLabelField = aIter.toString();
740 mDataPoint.mCustomLabels.push_back(sCustomLabelField);
741 }
742 break;
743 case XML_ELEMENT(LO_EXT, XML_HIDE_LEGEND):
744 {
745 bool bHideLegend = aIter.toBoolean();
746 if (bHideLegend)
747 {
748 uno::Sequence<sal_Int32> deletedLegendEntriesSeq;
749 Reference<beans::XPropertySet> xSeriesProp(mDataPoint.m_xSeries, uno::UNO_QUERY);
750 xSeriesProp->getPropertyValue("DeletedLegendEntries") >>= deletedLegendEntriesSeq;
751 std::vector<sal_Int32> deletedLegendEntries;
752 for (auto& deletedLegendEntry : deletedLegendEntriesSeq)
753 {
754 deletedLegendEntries.push_back(deletedLegendEntry);
755 }
756 deletedLegendEntries.push_back(mDataPoint.m_nPointIndex);
757 xSeriesProp->setPropertyValue("DeletedLegendEntries", uno::makeAny(::oox::ContainerHelper::vectorToSequence(deletedLegendEntries)));
758 }
759 break;
760 }
761 case XML_ELEMENT(LO_EXT, XML_CUSTOM_LABEL_POS_X):
762 {
763 mDataPoint.mCustomLabelPos[0] = aIter.toDouble();
764 break;
765 }
766 case XML_ELEMENT(LO_EXT, XML_CUSTOM_LABEL_POS_Y):
767 {
768 mDataPoint.mCustomLabelPos[1] = aIter.toDouble();
769 break;
770 }
771 default:
772 XMLOFF_WARN_UNKNOWN("xmloff", aIter);
773 }
774 }
775
776 mrIndex += nRepeat;
777 }
778
endFastElement(sal_Int32)779 void SchXMLDataPointContext::endFastElement(sal_Int32 )
780 {
781 if(!mDataPoint.msStyleName.isEmpty() || mDataPoint.mCustomLabels.size() > 0)
782 {
783 mrStyleVector.push_back(mDataPoint);
784 }
785 if (!mDataLabel.msStyleName.isEmpty() || mDataLabel.mo_nLabelAbsolutePosX.has_value()
786 || mDataLabel.mo_nLabelAbsolutePosY.has_value())
787 {
788 mrStyleVector.push_back(mDataLabel);
789 }
790 }
791
SchXMLPositionAttributesHelper(SvXMLImport & rImporter)792 SchXMLPositionAttributesHelper::SchXMLPositionAttributesHelper( SvXMLImport& rImporter )
793 : m_rImport( rImporter )
794 , m_aPosition(0,0)
795 , m_aSize(0,0)
796 , m_bHasSizeWidth( false )
797 , m_bHasSizeHeight( false )
798 , m_bHasPositionX( false )
799 , m_bHasPositionY( false )
800 , m_bAutoSize( false )
801 , m_bAutoPosition( false )
802 {
803 }
804
~SchXMLPositionAttributesHelper()805 SchXMLPositionAttributesHelper::~SchXMLPositionAttributesHelper()
806 {
807 }
808
hasPosSize() const809 bool SchXMLPositionAttributesHelper::hasPosSize() const
810 {
811 return (m_bHasPositionX && m_bHasPositionY) && (m_bHasSizeWidth && m_bHasSizeHeight);
812 }
813
isAutomatic() const814 bool SchXMLPositionAttributesHelper::isAutomatic() const
815 {
816 return m_bAutoSize || m_bAutoPosition;
817 }
818
readPositioningAttribute(sal_Int32 nAttributeToken,std::string_view rValue)819 void SchXMLPositionAttributesHelper::readPositioningAttribute( sal_Int32 nAttributeToken, std::string_view rValue )
820 {
821 if( !IsTokenInNamespace(nAttributeToken, XML_NAMESPACE_SVG) && !IsTokenInNamespace(nAttributeToken, XML_NAMESPACE_SVG_COMPAT) )
822 return;
823
824 switch (nAttributeToken & TOKEN_MASK)
825 {
826 case XML_X:
827 {
828 m_rImport.GetMM100UnitConverter().convertMeasureToCore(
829 m_aPosition.X, rValue );
830 m_bHasPositionX = true;
831 break;
832 }
833 case XML_Y:
834 {
835 m_rImport.GetMM100UnitConverter().convertMeasureToCore(
836 m_aPosition.Y, rValue );
837 m_bHasPositionY = true;
838 break;
839 }
840 case XML_WIDTH:
841 {
842 m_rImport.GetMM100UnitConverter().convertMeasureToCore(
843 m_aSize.Width, rValue );
844 m_bHasSizeWidth = true;
845 break;
846 }
847 case XML_HEIGHT:
848 {
849 m_rImport.GetMM100UnitConverter().convertMeasureToCore(
850 m_aSize.Height, rValue );
851 m_bHasSizeHeight = true;
852 break;
853 }
854 default:
855 XMLOFF_WARN_UNKNOWN_ATTR("xmloff", nAttributeToken, OUString::fromUtf8(rValue));
856 }
857 }
858
readAutomaticPositioningProperties(XMLPropStyleContext const * pPropStyleContext,const SvXMLStylesContext * pStylesCtxt)859 void SchXMLPositionAttributesHelper::readAutomaticPositioningProperties( XMLPropStyleContext const * pPropStyleContext, const SvXMLStylesContext* pStylesCtxt )
860 {
861 if( pPropStyleContext && pStylesCtxt )
862 {
863 //handle automatic position and size
864 SchXMLTools::getPropertyFromContext(
865 u"AutomaticSize", pPropStyleContext, pStylesCtxt ) >>= m_bAutoSize;
866 SchXMLTools::getPropertyFromContext(
867 u"AutomaticPosition", pPropStyleContext, pStylesCtxt ) >>= m_bAutoPosition;
868 }
869 }
870
SchXMLCoordinateRegionContext(SvXMLImport & rImport,SchXMLPositionAttributesHelper & rPositioning)871 SchXMLCoordinateRegionContext::SchXMLCoordinateRegionContext(
872 SvXMLImport& rImport
873 , SchXMLPositionAttributesHelper& rPositioning )
874 : SvXMLImportContext( rImport )
875 , m_rPositioning( rPositioning )
876 {
877 }
878
~SchXMLCoordinateRegionContext()879 SchXMLCoordinateRegionContext::~SchXMLCoordinateRegionContext()
880 {
881 }
882
startFastElement(sal_Int32,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList)883 void SchXMLCoordinateRegionContext::startFastElement (sal_Int32 /*Element*/,
884 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
885 {
886 // parse attributes
887 for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
888 m_rPositioning.readPositioningAttribute( aIter.getToken(), aIter.toView() );
889 }
890
SchXMLWallFloorContext(SchXMLImportHelper & rImpHelper,SvXMLImport & rImport,uno::Reference<chart::XDiagram> const & xDiagram,ContextType eContextType)891 SchXMLWallFloorContext::SchXMLWallFloorContext(
892 SchXMLImportHelper& rImpHelper,
893 SvXMLImport& rImport,
894 uno::Reference< chart::XDiagram > const & xDiagram,
895 ContextType eContextType ) :
896 SvXMLImportContext( rImport ),
897 mrImportHelper( rImpHelper ),
898 mxWallFloorSupplier( xDiagram, uno::UNO_QUERY ),
899 meContextType( eContextType )
900 {
901 }
902
~SchXMLWallFloorContext()903 SchXMLWallFloorContext::~SchXMLWallFloorContext()
904 {
905 }
906
startFastElement(sal_Int32,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList)907 void SchXMLWallFloorContext::startFastElement (sal_Int32 /*Element*/,
908 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
909 {
910 if( !mxWallFloorSupplier.is())
911 return;
912
913 OUString sAutoStyleName;
914
915 for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
916 {
917 if( aIter.getToken() == XML_ELEMENT(CHART, XML_STYLE_NAME) )
918 sAutoStyleName = aIter.toString();
919 else
920 XMLOFF_WARN_UNKNOWN("xmloff", aIter);
921 }
922
923 // set properties
924 uno::Reference< beans::XPropertySet > xProp = ( meContextType == CONTEXT_TYPE_WALL )
925 ? mxWallFloorSupplier->getWall()
926 : mxWallFloorSupplier->getFloor();
927
928 if (!sAutoStyleName.isEmpty())
929 mrImportHelper.FillAutoStyle(sAutoStyleName, xProp);
930 }
931
SchXMLStockContext(SchXMLImportHelper & rImpHelper,SvXMLImport & rImport,uno::Reference<chart::XDiagram> const & xDiagram,ContextType eContextType)932 SchXMLStockContext::SchXMLStockContext(
933 SchXMLImportHelper& rImpHelper,
934 SvXMLImport& rImport,
935 uno::Reference< chart::XDiagram > const & xDiagram,
936 ContextType eContextType ) :
937 SvXMLImportContext( rImport ),
938 mrImportHelper( rImpHelper ),
939 mxStockPropProvider( xDiagram, uno::UNO_QUERY ),
940 meContextType( eContextType )
941 {
942 }
943
~SchXMLStockContext()944 SchXMLStockContext::~SchXMLStockContext()
945 {
946 }
947
startFastElement(sal_Int32,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList)948 void SchXMLStockContext::startFastElement (sal_Int32 /*Element*/,
949 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
950 {
951 if( !mxStockPropProvider.is())
952 return;
953
954 OUString sAutoStyleName;
955
956 for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
957 {
958 if( aIter.getToken() == XML_ELEMENT(CHART, XML_STYLE_NAME) )
959 sAutoStyleName = aIter.toString();
960 else
961 XMLOFF_WARN_UNKNOWN("xmloff", aIter);
962 }
963
964 if( sAutoStyleName.isEmpty())
965 return;
966
967 // set properties
968 uno::Reference< beans::XPropertySet > xProp;
969 switch( meContextType )
970 {
971 case CONTEXT_TYPE_GAIN:
972 xProp = mxStockPropProvider->getUpBar();
973 break;
974 case CONTEXT_TYPE_LOSS:
975 xProp = mxStockPropProvider->getDownBar();
976 break;
977 case CONTEXT_TYPE_RANGE:
978 xProp = mxStockPropProvider->getMinMaxLine();
979 break;
980 }
981
982 mrImportHelper.FillAutoStyle(sAutoStyleName, xProp);
983 }
984
lcl_setErrorBarSequence(const uno::Reference<chart2::XChartDocument> & xDoc,const uno::Reference<beans::XPropertySet> & xBarProp,const OUString & aXMLRange,bool bPositiveValue,bool bYError,tSchXMLLSequencesPerIndex & rSequences)985 static void lcl_setErrorBarSequence ( const uno::Reference< chart2::XChartDocument > &xDoc,
986 const uno::Reference< beans::XPropertySet > &xBarProp,
987 const OUString &aXMLRange,
988 bool bPositiveValue, bool bYError,
989 tSchXMLLSequencesPerIndex& rSequences)
990 {
991 uno::Reference< css::chart2::data::XDataProvider > xDataProvider(xDoc->getDataProvider());
992 uno::Reference< css::chart2::data::XDataSource > xDataSource( xBarProp, uno::UNO_QUERY );
993 uno::Reference< css::chart2::data::XDataSink > xDataSink( xDataSource, uno::UNO_QUERY );
994
995 assert( xDataSink.is() && xDataSource.is() && xDataProvider.is() );
996
997 OUString aRange(lcl_ConvertRange(aXMLRange,xDoc));
998
999 uno::Reference< chart2::data::XDataSequence > xNewSequence(
1000 xDataProvider->createDataSequenceByRangeRepresentation( aRange ));
1001
1002 if( !xNewSequence.is())
1003 return;
1004
1005 SchXMLTools::setXMLRangePropertyAtDataSequence(xNewSequence,aXMLRange);
1006
1007 OUStringBuffer aRoleBuffer("error-bars-");
1008 if( bYError )
1009 aRoleBuffer.append( 'y' );
1010 else
1011 aRoleBuffer.append( 'x');
1012
1013 aRoleBuffer.append( '-' );
1014
1015 if( bPositiveValue )
1016 aRoleBuffer = aRoleBuffer.append( "positive" );
1017 else
1018 aRoleBuffer = aRoleBuffer.append( "negative" );
1019
1020 OUString aRole = aRoleBuffer.makeStringAndClear();
1021
1022 Reference< beans::XPropertySet > xSeqProp( xNewSequence, uno::UNO_QUERY );
1023
1024 xSeqProp->setPropertyValue("Role", uno::makeAny( aRole ));
1025
1026 Reference< uno::XComponentContext > xContext = comphelper::getProcessComponentContext();
1027
1028 Reference< chart2::data::XLabeledDataSequence > xLabelSeq( chart2::data::LabeledDataSequence::create(xContext),
1029 uno::UNO_QUERY_THROW );
1030
1031 rSequences.emplace( tSchXMLIndexWithPart( -2, SCH_XML_PART_ERROR_BARS ), xLabelSeq );
1032
1033 xLabelSeq->setValues( xNewSequence );
1034
1035 uno::Sequence< Reference< chart2::data::XLabeledDataSequence > > aSequences(
1036 xDataSource->getDataSequences());
1037
1038 aSequences.realloc( aSequences.getLength() + 1 );
1039 aSequences[ aSequences.getLength() - 1 ] = xLabelSeq;
1040 xDataSink->setData( aSequences );
1041
1042 }
1043
SchXMLStatisticsObjectContext(SchXMLImportHelper & rImpHelper,SvXMLImport & rImport,const OUString & rSeriesStyleName,::std::vector<DataRowPointStyle> & rStyleVector,const css::uno::Reference<css::chart2::XDataSeries> & xSeries,ContextType eContextType,tSchXMLLSequencesPerIndex & rLSequencesPerIndex)1044 SchXMLStatisticsObjectContext::SchXMLStatisticsObjectContext(
1045 SchXMLImportHelper& rImpHelper,
1046 SvXMLImport& rImport,
1047 const OUString &rSeriesStyleName,
1048 ::std::vector< DataRowPointStyle >& rStyleVector,
1049 const css::uno::Reference< css::chart2::XDataSeries >& xSeries,
1050 ContextType eContextType,
1051 tSchXMLLSequencesPerIndex & rLSequencesPerIndex) :
1052
1053 SvXMLImportContext( rImport ),
1054 mrImportHelper( rImpHelper ),
1055 mrStyleVector( rStyleVector ),
1056 m_xSeries( xSeries ),
1057 meContextType( eContextType ),
1058 maSeriesStyleName( rSeriesStyleName),
1059 mrLSequencesPerIndex(rLSequencesPerIndex)
1060 {}
1061
~SchXMLStatisticsObjectContext()1062 SchXMLStatisticsObjectContext::~SchXMLStatisticsObjectContext()
1063 {
1064 }
1065
1066 namespace {
1067
SetErrorBarStyleProperties(const OUString & rStyleName,const uno::Reference<beans::XPropertySet> & xBarProp,SchXMLImportHelper const & rImportHelper)1068 void SetErrorBarStyleProperties( const OUString& rStyleName, const uno::Reference< beans::XPropertySet >& xBarProp,
1069 SchXMLImportHelper const & rImportHelper )
1070 {
1071 const SvXMLStylesContext* pStylesCtxt = rImportHelper.GetAutoStylesContext();
1072 const SvXMLStyleContext* pStyle = pStylesCtxt->FindStyleChildContext(SchXMLImportHelper::GetChartFamilyID(),
1073 rStyleName);
1074
1075 XMLPropStyleContext &rSeriesStyleContext =
1076 const_cast< XMLPropStyleContext& >( dynamic_cast< const XMLPropStyleContext& >( *pStyle ));
1077
1078 rSeriesStyleContext.FillPropertySet( xBarProp );
1079 }
1080
SetErrorBarPropertiesFromStyleName(const OUString & aStyleName,const uno::Reference<beans::XPropertySet> & xBarProp,SchXMLImportHelper const & rImportHelper,OUString & aPosRange,OUString & aNegRange)1081 void SetErrorBarPropertiesFromStyleName( const OUString& aStyleName, const uno::Reference< beans::XPropertySet>& xBarProp,
1082 SchXMLImportHelper const & rImportHelper, OUString& aPosRange, OUString& aNegRange)
1083 {
1084 const SvXMLStylesContext* pStylesCtxt = rImportHelper.GetAutoStylesContext();
1085 const SvXMLStyleContext* pStyle = pStylesCtxt->FindStyleChildContext(SchXMLImportHelper::GetChartFamilyID(),
1086 aStyleName);
1087
1088 XMLPropStyleContext * pSeriesStyleContext =
1089 const_cast< XMLPropStyleContext * >( dynamic_cast< const XMLPropStyleContext * >( pStyle ));
1090
1091 uno::Any aAny = SchXMLTools::getPropertyFromContext(u"ErrorBarStyle",
1092 pSeriesStyleContext,pStylesCtxt);
1093
1094 if ( !aAny.hasValue() )
1095 return;
1096
1097 sal_Int32 aBarStyle = css::chart::ErrorBarStyle::NONE;
1098 aAny >>= aBarStyle;
1099 xBarProp->setPropertyValue("ErrorBarStyle", aAny);
1100
1101 aAny = SchXMLTools::getPropertyFromContext(u"ShowPositiveError",
1102 pSeriesStyleContext,pStylesCtxt);
1103
1104 if(aAny.hasValue())
1105 xBarProp->setPropertyValue("ShowPositiveError",aAny);
1106
1107 aAny = SchXMLTools::getPropertyFromContext(u"ShowNegativeError",
1108 pSeriesStyleContext,pStylesCtxt);
1109
1110 if(aAny.hasValue())
1111 xBarProp->setPropertyValue("ShowNegativeError",aAny);
1112
1113 aAny = SchXMLTools::getPropertyFromContext(u"PositiveError",
1114 pSeriesStyleContext, pStylesCtxt);
1115
1116 if(aAny.hasValue())
1117 xBarProp->setPropertyValue("PositiveError", aAny);
1118 else
1119 {
1120 aAny = SchXMLTools::getPropertyFromContext(u"ConstantErrorHigh",
1121 pSeriesStyleContext, pStylesCtxt);
1122
1123 if(aAny.hasValue())
1124 xBarProp->setPropertyValue("PositiveError", aAny);
1125 }
1126
1127 aAny = SchXMLTools::getPropertyFromContext(u"NegativeError",
1128 pSeriesStyleContext, pStylesCtxt);
1129
1130 if(aAny.hasValue())
1131 xBarProp->setPropertyValue("NegativeError", aAny);
1132 else
1133 {
1134 aAny = SchXMLTools::getPropertyFromContext(u"ConstantErrorLow",
1135 pSeriesStyleContext, pStylesCtxt);
1136
1137 if(aAny.hasValue())
1138 xBarProp->setPropertyValue("NegativeError", aAny);
1139 }
1140
1141 aAny = SchXMLTools::getPropertyFromContext(u"ErrorBarRangePositive",
1142 pSeriesStyleContext, pStylesCtxt);
1143 if( aAny.hasValue() )
1144 {
1145 aAny >>= aPosRange;
1146 }
1147
1148 aAny = SchXMLTools::getPropertyFromContext(u"ErrorBarRangeNegative",
1149 pSeriesStyleContext, pStylesCtxt);
1150 if( aAny.hasValue() )
1151 {
1152 aAny >>= aNegRange;
1153 }
1154
1155 aAny = SchXMLTools::getPropertyFromContext(u"Weight",
1156 pSeriesStyleContext, pStylesCtxt);
1157 if( aAny.hasValue() )
1158 {
1159 xBarProp->setPropertyValue("Weight", aAny);
1160 }
1161
1162 aAny = SchXMLTools::getPropertyFromContext(u"PercentageError",
1163 pSeriesStyleContext, pStylesCtxt);
1164 if( aAny.hasValue() && aBarStyle == css::chart::ErrorBarStyle::RELATIVE )
1165 {
1166 xBarProp->setPropertyValue("PositiveError", aAny);
1167 xBarProp->setPropertyValue("NegativeError", aAny);
1168 }
1169
1170 switch(aBarStyle)
1171 {
1172 case css::chart::ErrorBarStyle::ERROR_MARGIN:
1173 {
1174 aAny = SchXMLTools::getPropertyFromContext(u"NegativeError",
1175 pSeriesStyleContext,pStylesCtxt);
1176
1177 xBarProp->setPropertyValue("NegativeError",aAny);
1178
1179 aAny = SchXMLTools::getPropertyFromContext(u"PositiveError",
1180 pSeriesStyleContext,pStylesCtxt);
1181
1182 xBarProp->setPropertyValue("PositiveError",aAny);
1183 }
1184 break;
1185 default:
1186 break;
1187 }
1188
1189 }
1190
1191 }
1192
startFastElement(sal_Int32,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList)1193 void SchXMLStatisticsObjectContext::startFastElement (sal_Int32 /*Element*/,
1194 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
1195 {
1196 OUString sAutoStyleName;
1197 OUString aPosRange;
1198 OUString aNegRange;
1199 bool bYError = true; /// Default errorbar, to be backward compatible with older files!
1200
1201 for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
1202 {
1203 switch (aIter.getToken())
1204 {
1205 case XML_ELEMENT(CHART, XML_STYLE_NAME):
1206 sAutoStyleName = aIter.toString();
1207 break;
1208 case XML_ELEMENT(CHART, XML_DIMENSION):
1209 bYError = aIter.toString() == "y";
1210 break;
1211 case XML_ELEMENT(CHART, XML_ERROR_UPPER_RANGE):
1212 aPosRange = aIter.toString();
1213 break;
1214 case XML_ELEMENT(CHART, XML_ERROR_LOWER_RANGE):
1215 aNegRange = aIter.toString();
1216 break;
1217 }
1218 }
1219
1220 if( sAutoStyleName.isEmpty() )
1221 return;
1222
1223 DataRowPointStyle aStyle( DataRowPointStyle::MEAN_VALUE, m_xSeries, -1, 1, sAutoStyleName );
1224
1225 switch( meContextType )
1226 {
1227 case CONTEXT_TYPE_MEAN_VALUE_LINE:
1228 aStyle.meType = DataRowPointStyle::MEAN_VALUE;
1229 break;
1230 case CONTEXT_TYPE_ERROR_INDICATOR:
1231 {
1232 aStyle.meType = DataRowPointStyle::ERROR_INDICATOR;
1233
1234 uno::Reference< lang::XMultiServiceFactory > xFact = comphelper::getProcessServiceFactory();
1235
1236 uno::Reference< beans::XPropertySet > xBarProp( xFact->createInstance("com.sun.star.chart2.ErrorBar" ),
1237 uno::UNO_QUERY );
1238
1239 xBarProp->setPropertyValue("ErrorBarStyle",uno::makeAny(css::chart::ErrorBarStyle::NONE));
1240 xBarProp->setPropertyValue("PositiveError",uno::makeAny(0.0));
1241 xBarProp->setPropertyValue("NegativeError",uno::makeAny(0.0));
1242 xBarProp->setPropertyValue("Weight",uno::makeAny(1.0));
1243 xBarProp->setPropertyValue("ShowPositiveError",uno::makeAny(true));
1244 xBarProp->setPropertyValue("ShowNegativeError",uno::makeAny(true));
1245
1246 // first import defaults from parent style
1247 SetErrorBarStyleProperties( maSeriesStyleName, xBarProp, mrImportHelper );
1248 SetErrorBarStyleProperties( sAutoStyleName, xBarProp, mrImportHelper );
1249 SetErrorBarPropertiesFromStyleName( maSeriesStyleName, xBarProp, mrImportHelper, aPosRange, aNegRange );
1250 SetErrorBarPropertiesFromStyleName( sAutoStyleName, xBarProp, mrImportHelper, aPosRange, aNegRange );
1251
1252 uno::Reference< chart2::XChartDocument > xDoc(GetImport().GetModel(),uno::UNO_QUERY);
1253
1254 if (!aPosRange.isEmpty())
1255 lcl_setErrorBarSequence(xDoc,xBarProp,aPosRange,true,bYError, mrLSequencesPerIndex);
1256
1257 if (!aNegRange.isEmpty())
1258 lcl_setErrorBarSequence(xDoc,xBarProp,aNegRange,false,bYError, mrLSequencesPerIndex);
1259
1260 if ( !bYError )
1261 {
1262 aStyle.m_xErrorXProperties.set( xBarProp );
1263 }
1264 else
1265 {
1266 aStyle.m_xErrorYProperties.set( xBarProp );
1267 }
1268 }
1269 break;
1270 }
1271
1272 mrStyleVector.push_back( aStyle );
1273 }
1274
1275 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1276