Version 7.5.1.1, tag libreoffice-7.5.1.1
[LibreOffice.git] / xmloff / source / chart / SchXMLAxisContext.cxx
blobad8b187f88e267f07aa341b9e3566aaf633f1366
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 <sax/tools/converter.hxx>
22 #include "SchXMLAxisContext.hxx"
23 #include "SchXMLChartContext.hxx"
24 #include "SchXMLTools.hxx"
25 #include <xmloff/xmlimp.hxx>
26 #include <xmloff/xmlnamespace.hxx>
27 #include <xmloff/xmlement.hxx>
28 #include <xmloff/xmlstyle.hxx>
29 #include <xmloff/prstylei.hxx>
30 #include <xmloff/namespacemap.hxx>
31 #include <xmloff/xmluconv.hxx>
33 #include <rtl/math.hxx>
34 #include <tools/color.hxx>
35 #include <sal/log.hxx>
37 #include <com/sun/star/chart/ChartAxisLabelPosition.hpp>
38 #include <com/sun/star/chart/ChartAxisMarkPosition.hpp>
39 #include <com/sun/star/chart/ChartAxisPosition.hpp>
40 #include <com/sun/star/chart/ChartAxisType.hpp>
41 #include <com/sun/star/chart/TimeIncrement.hpp>
42 #include <com/sun/star/chart/TimeInterval.hpp>
43 #include <com/sun/star/chart/TimeUnit.hpp>
44 #include <com/sun/star/chart/XAxis.hpp>
45 #include <com/sun/star/chart/XAxisSupplier.hpp>
46 #include <com/sun/star/chart/XChartDocument.hpp>
47 #include <com/sun/star/chart2/AxisType.hpp>
48 #include <com/sun/star/chart2/XChartDocument.hpp>
49 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
51 #include <com/sun/star/drawing/LineStyle.hpp>
53 using namespace ::xmloff::token;
54 using namespace com::sun::star;
56 using com::sun::star::uno::Reference;
58 const SvXMLEnumMapEntry<SchXMLAxisDimension> aXMLAxisDimensionMap[] =
60 { XML_X, SCH_XML_AXIS_X },
61 { XML_Y, SCH_XML_AXIS_Y },
62 { XML_Z, SCH_XML_AXIS_Z },
63 { XML_TOKEN_INVALID, SchXMLAxisDimension(0) }
66 const SvXMLEnumMapEntry<sal_uInt16> aXMLAxisTypeMap[] =
68 { XML_AUTO, css::chart::ChartAxisType::AUTOMATIC },
69 { XML_TEXT, css::chart::ChartAxisType::CATEGORY },
70 { XML_DATE, css::chart::ChartAxisType::DATE },
71 { XML_TOKEN_INVALID, 0 }
74 namespace {
76 class SchXMLCategoriesContext : public SvXMLImportContext
78 private:
79 OUString& mrAddress;
81 public:
82 SchXMLCategoriesContext( SvXMLImport& rImport,
83 OUString& rAddress );
84 virtual void SAL_CALL startFastElement( sal_Int32 nElement,
85 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
88 class DateScaleContext : public SvXMLImportContext
90 public:
91 DateScaleContext( SvXMLImport& rImport,
92 const Reference< beans::XPropertySet >& rAxisProps );
94 virtual void SAL_CALL startFastElement( sal_Int32 nElement,
95 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
97 private:
98 Reference< beans::XPropertySet > m_xAxisProps;
103 SchXMLAxisContext::SchXMLAxisContext( SchXMLImportHelper& rImpHelper,
104 SvXMLImport& rImport,
105 Reference< chart::XDiagram > const & xDiagram,
106 std::vector< SchXMLAxis >& rAxes,
107 OUString & rCategoriesAddress,
108 bool bAddMissingXAxisForNetCharts,
109 bool bAdaptWrongPercentScaleValues,
110 bool bAdaptXAxisOrientationForOld2DBarCharts,
111 bool& rbAxisPositionAttributeImported ) :
112 SvXMLImportContext( rImport ),
113 m_rImportHelper( rImpHelper ),
114 m_xDiagram( xDiagram ),
115 m_rAxes( rAxes ),
116 m_rCategoriesAddress( rCategoriesAddress ),
117 m_nAxisType(chart::ChartAxisType::AUTOMATIC),
118 m_bAxisTypeImported(false),
119 m_bDateScaleImported(false),
120 m_bAddMissingXAxisForNetCharts( bAddMissingXAxisForNetCharts ),
121 m_bAdaptWrongPercentScaleValues( bAdaptWrongPercentScaleValues ),
122 m_bAdaptXAxisOrientationForOld2DBarCharts( bAdaptXAxisOrientationForOld2DBarCharts ),
123 m_rbAxisPositionAttributeImported( rbAxisPositionAttributeImported )
127 SchXMLAxisContext::~SchXMLAxisContext()
130 static Reference< chart::XAxis > lcl_getChartAxis(const SchXMLAxis& rCurrentAxis, const Reference< chart::XDiagram >& rDiagram )
132 Reference< chart::XAxis > xAxis;
133 Reference< chart::XAxisSupplier > xAxisSuppl( rDiagram, uno::UNO_QUERY );
134 if( !xAxisSuppl.is() )
135 return xAxis;
136 if( rCurrentAxis.nAxisIndex == 0 )
137 xAxis = xAxisSuppl->getAxis(rCurrentAxis.eDimension);
138 else
139 xAxis = xAxisSuppl->getSecondaryAxis(rCurrentAxis.eDimension);
140 return xAxis;
143 /* returns a shape for the current axis's title. The property
144 "Has...AxisTitle" is set to "True" to get the shape
146 Reference< drawing::XShape > SchXMLAxisContext::getTitleShape() const
148 Reference< drawing::XShape > xResult;
149 Reference< beans::XPropertySet > xDiaProp( m_rImportHelper.GetChartDocument()->getDiagram(), uno::UNO_QUERY );
150 Reference< chart::XAxis > xAxis( lcl_getChartAxis( m_aCurrentAxis, m_xDiagram ) );
151 if( !xDiaProp.is() || !xAxis.is() )
152 return xResult;
154 OUString aPropName;
155 switch( m_aCurrentAxis.eDimension )
157 case SCH_XML_AXIS_X:
158 if( m_aCurrentAxis.nAxisIndex == 0 )
159 aPropName = "HasXAxisTitle";
160 else
161 aPropName = "HasSecondaryXAxisTitle";
162 break;
163 case SCH_XML_AXIS_Y:
164 if( m_aCurrentAxis.nAxisIndex == 0 )
165 aPropName = "HasYAxisTitle";
166 else
167 aPropName = "HasSecondaryYAxisTitle";
168 break;
169 case SCH_XML_AXIS_Z:
170 aPropName = "HasZAxisTitle";
171 break;
172 case SCH_XML_AXIS_UNDEF:
173 SAL_INFO("xmloff.chart", "Invalid axis" );
174 break;
176 xDiaProp->setPropertyValue( aPropName, uno::Any(true) );
177 xResult.set( xAxis->getAxisTitle(), uno::UNO_QUERY );
178 return xResult;
181 void SchXMLAxisContext::CreateGrid( const OUString& sAutoStyleName, bool bIsMajor )
183 Reference< beans::XPropertySet > xDiaProp( m_rImportHelper.GetChartDocument()->getDiagram(), uno::UNO_QUERY );
184 Reference< chart::XAxis > xAxis( lcl_getChartAxis( m_aCurrentAxis, m_xDiagram ) );
185 if( !xDiaProp.is() || !xAxis.is() )
186 return;
188 OUString aPropName;
189 switch( m_aCurrentAxis.eDimension )
191 case SCH_XML_AXIS_X:
192 if( bIsMajor )
193 aPropName = "HasXAxisGrid";
194 else
195 aPropName = "HasXAxisHelpGrid";
196 break;
197 case SCH_XML_AXIS_Y:
198 if( bIsMajor )
199 aPropName = "HasYAxisGrid";
200 else
201 aPropName = "HasYAxisHelpGrid";
202 break;
203 case SCH_XML_AXIS_Z:
204 if( bIsMajor )
205 aPropName = "HasZAxisGrid";
206 else
207 aPropName = "HasZAxisHelpGrid";
208 break;
209 case SCH_XML_AXIS_UNDEF:
210 SAL_INFO("xmloff.chart", "Invalid axis" );
211 break;
213 xDiaProp->setPropertyValue( aPropName, uno::Any(true) );
215 Reference< beans::XPropertySet > xGridProp;
216 if( bIsMajor )
217 xGridProp = xAxis->getMajorGrid();
218 else
219 xGridProp = xAxis->getMinorGrid();
221 // set properties
222 if( xGridProp.is())
224 // the line color is black as default, in the model it is a light gray
225 xGridProp->setPropertyValue("LineColor",
226 uno::Any( COL_BLACK ));
227 if (!sAutoStyleName.isEmpty())
228 m_rImportHelper.FillAutoStyle(sAutoStyleName, xGridProp);
232 void SchXMLAxisContext::startFastElement( sal_Int32 /*nElement*/,
233 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
235 // parse attributes
236 for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
238 switch(aIter.getToken())
240 case XML_ELEMENT(CHART, XML_DIMENSION):
242 SchXMLAxisDimension nEnumVal;
243 if( SvXMLUnitConverter::convertEnum( nEnumVal, aIter.toView(), aXMLAxisDimensionMap ))
244 m_aCurrentAxis.eDimension = nEnumVal;
246 break;
247 case XML_ELEMENT(CHART, XML_NAME):
248 m_aCurrentAxis.aName = aIter.toString();
249 break;
250 case XML_ELEMENT(CHART, XML_AXIS_TYPE):
251 case XML_ELEMENT(CHART_EXT, XML_AXIS_TYPE):
252 sal_uInt16 nEnumVal;
253 if( SvXMLUnitConverter::convertEnum( nEnumVal, aIter.toView(), aXMLAxisTypeMap ))
255 m_nAxisType = nEnumVal;
256 m_bAxisTypeImported = true;
258 break;
259 case XML_ELEMENT(CHART, XML_STYLE_NAME):
260 m_aAutoStyleName = aIter.toString();
261 break;
262 default:
263 XMLOFF_WARN_UNKNOWN("xmloff", aIter);
267 // check for number of axes with same dimension
268 m_aCurrentAxis.nAxisIndex = 0;
269 sal_Int32 nNumOfAxes = m_rAxes.size();
270 for( sal_Int32 nCurrent = 0; nCurrent < nNumOfAxes; nCurrent++ )
272 if( m_rAxes[ nCurrent ].eDimension == m_aCurrentAxis.eDimension )
273 m_aCurrentAxis.nAxisIndex++;
275 CreateAxis();
277 namespace
280 Reference< chart2::XAxis > lcl_getAxis( const Reference< frame::XModel >& xChartModel,
281 sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex )
283 Reference< chart2::XAxis > xAxis;
287 Reference< chart2::XChartDocument > xChart2Document( xChartModel, uno::UNO_QUERY );
288 if( xChart2Document.is() )
290 Reference< chart2::XDiagram > xDiagram( xChart2Document->getFirstDiagram());
291 Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xDiagram, uno::UNO_QUERY_THROW );
292 uno::Sequence< Reference< chart2::XCoordinateSystem > >
293 aCooSysSeq( xCooSysCnt->getCoordinateSystems());
294 sal_Int32 nCooSysIndex = 0;
295 if( nCooSysIndex < aCooSysSeq.getLength() )
297 Reference< chart2::XCoordinateSystem > xCooSys( aCooSysSeq[nCooSysIndex] );
298 if( xCooSys.is() && nDimensionIndex < xCooSys->getDimension() )
300 const sal_Int32 nMaxAxisIndex = xCooSys->getMaximumAxisIndexByDimension(nDimensionIndex);
301 if( nAxisIndex <= nMaxAxisIndex )
302 xAxis = xCooSys->getAxisByDimension( nDimensionIndex, nAxisIndex );
307 catch( uno::Exception & )
309 SAL_INFO("xmloff.chart", "Couldn't get axis" );
312 return xAxis;
315 bool lcl_divideBy100( uno::Any& rDoubleAny )
317 bool bChanged = false;
318 double fValue=0.0;
319 if( (rDoubleAny>>=fValue) && (fValue!=0.0) )
321 fValue/=100.0;
322 rDoubleAny <<= fValue;
323 bChanged = true;
325 return bChanged;
328 bool lcl_AdaptWrongPercentScaleValues(chart2::ScaleData& rScaleData)
330 bool bChanged = lcl_divideBy100( rScaleData.Minimum );
331 bChanged = lcl_divideBy100( rScaleData.Maximum ) || bChanged;
332 bChanged = lcl_divideBy100( rScaleData.Origin ) || bChanged;
333 bChanged = lcl_divideBy100( rScaleData.IncrementData.Distance ) || bChanged;
334 return bChanged;
337 }//end anonymous namespace
339 void SchXMLAxisContext::CreateAxis()
341 m_rAxes.push_back( m_aCurrentAxis );
343 Reference< beans::XPropertySet > xDiaProp( m_rImportHelper.GetChartDocument()->getDiagram(), uno::UNO_QUERY );
344 if( !xDiaProp.is() )
345 return;
346 OUString aPropName;
347 switch( m_aCurrentAxis.eDimension )
349 case SCH_XML_AXIS_X:
350 if( m_aCurrentAxis.nAxisIndex == 0 )
351 aPropName = "HasXAxis";
352 else
353 aPropName = "HasSecondaryXAxis";
354 break;
355 case SCH_XML_AXIS_Y:
356 if( m_aCurrentAxis.nAxisIndex == 0 )
357 aPropName = "HasYAxis";
358 else
359 aPropName = "HasSecondaryYAxis";
360 break;
361 case SCH_XML_AXIS_Z:
362 if( m_aCurrentAxis.nAxisIndex == 0 )
363 aPropName = "HasZAxis";
364 break;
365 case SCH_XML_AXIS_UNDEF:
366 SAL_INFO("xmloff.chart", "Invalid axis" );
367 break;
371 xDiaProp->setPropertyValue( aPropName, uno::Any(true) );
373 catch( beans::UnknownPropertyException & )
375 SAL_INFO("xmloff.chart", "Couldn't turn on axis" );
377 if( m_aCurrentAxis.eDimension==SCH_XML_AXIS_Z )
379 bool bSettingZAxisSucceeded = false;
382 xDiaProp->getPropertyValue( aPropName ) >>= bSettingZAxisSucceeded;
384 catch( beans::UnknownPropertyException & )
386 SAL_INFO("xmloff.chart", "Couldn't turn on z axis" );
388 if( !bSettingZAxisSucceeded )
389 return;
392 m_xAxisProps.set( lcl_getChartAxis( m_aCurrentAxis, m_xDiagram ), uno::UNO_QUERY );
394 if( m_bAddMissingXAxisForNetCharts && m_aCurrentAxis.eDimension==SCH_XML_AXIS_Y && m_aCurrentAxis.nAxisIndex==0 )
398 xDiaProp->setPropertyValue("HasXAxis", uno::Any(true) );
400 catch( beans::UnknownPropertyException & )
402 SAL_INFO("xmloff.chart", "Couldn't turn on x axis" );
406 // set properties
407 if( !m_xAxisProps.is())
408 return;
410 uno::Any aTrueBool( uno::Any( true ));
411 uno::Any aFalseBool( uno::Any( false ));
413 // #i109879# the line color is black as default, in the model it is a light gray
414 m_xAxisProps->setPropertyValue("LineColor",
415 uno::Any( COL_BLACK ));
417 m_xAxisProps->setPropertyValue("DisplayLabels", aFalseBool );
419 // Compatibility option: starting from LibreOffice 5.1 the rotated
420 // layout is preferred to staggering for axis labels.
421 // So the import default value for having compatibility with ODF
422 // documents created with earlier LibreOffice versions is `true`.
423 if( GetImport().getGeneratorVersion() != SvXMLImport::ProductVersionUnknown )
424 m_xAxisProps->setPropertyValue("TryStaggeringFirst", aTrueBool );
426 // #88077# AutoOrigin 'on' is default
427 m_xAxisProps->setPropertyValue("AutoOrigin", aTrueBool );
429 if( m_bAxisTypeImported )
430 m_xAxisProps->setPropertyValue("AxisType", uno::Any(m_nAxisType) );
432 if( !m_aAutoStyleName.isEmpty())
434 const SvXMLStylesContext* pStylesCtxt = m_rImportHelper.GetAutoStylesContext();
435 if (pStylesCtxt)
437 SvXMLStyleContext* pStyle = const_cast<SvXMLStyleContext*>(pStylesCtxt->FindStyleChildContext(SchXMLImportHelper::GetChartFamilyID(), m_aAutoStyleName));
439 if (XMLPropStyleContext * pPropStyleContext = dynamic_cast<XMLPropStyleContext*>(pStyle))
441 pPropStyleContext->FillPropertySet(m_xAxisProps);
443 if( m_bAdaptWrongPercentScaleValues && m_aCurrentAxis.eDimension==SCH_XML_AXIS_Y )
445 //set scale data of added x axis back to default
446 Reference< chart2::XAxis > xAxis( lcl_getAxis( GetImport().GetModel(),
447 m_aCurrentAxis.eDimension, m_aCurrentAxis.nAxisIndex ) );
448 if( xAxis.is() )
450 chart2::ScaleData aScaleData( xAxis->getScaleData());
451 if( lcl_AdaptWrongPercentScaleValues(aScaleData) )
452 xAxis->setScaleData( aScaleData );
456 if( m_bAddMissingXAxisForNetCharts )
458 //copy style from y axis to added x axis:
460 Reference< chart::XAxisSupplier > xAxisSuppl( xDiaProp, uno::UNO_QUERY );
461 if( xAxisSuppl.is() )
463 Reference< beans::XPropertySet > xXAxisProp( xAxisSuppl->getAxis(0), uno::UNO_QUERY );
464 pPropStyleContext->FillPropertySet(xXAxisProp);
467 //set scale data of added x axis back to default
468 Reference< chart2::XAxis > xAxis( lcl_getAxis( GetImport().GetModel(),
469 0 /*nDimensionIndex*/, 0 /*nAxisIndex*/ ) );
470 if( xAxis.is() )
472 chart2::ScaleData aScaleData;
473 aScaleData.AxisType = chart2::AxisType::CATEGORY;
474 aScaleData.Orientation = chart2::AxisOrientation_MATHEMATICAL;
475 xAxis->setScaleData( aScaleData );
478 //set line style of added x axis to invisible
479 Reference< beans::XPropertySet > xNewAxisProp( xAxis, uno::UNO_QUERY );
480 if( xNewAxisProp.is() )
482 xNewAxisProp->setPropertyValue("LineStyle"
483 , uno::Any(drawing::LineStyle_NONE));
487 if( m_bAdaptXAxisOrientationForOld2DBarCharts && m_aCurrentAxis.eDimension == SCH_XML_AXIS_X )
489 bool bIs3DChart = false;
490 if( xDiaProp.is() && ( xDiaProp->getPropertyValue("Dim3D") >>= bIs3DChart )
491 && !bIs3DChart )
493 Reference< chart2::XChartDocument > xChart2Document( GetImport().GetModel(), uno::UNO_QUERY );
494 if( xChart2Document.is() )
496 Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xChart2Document->getFirstDiagram(), uno::UNO_QUERY );
497 if( xCooSysCnt.is() )
499 uno::Sequence< Reference< chart2::XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems() );
500 if( aCooSysSeq.hasElements() )
502 bool bSwapXandYAxis = false;
503 Reference< chart2::XCoordinateSystem > xCooSys( aCooSysSeq[0] );
504 Reference< beans::XPropertySet > xCooSysProp( xCooSys, uno::UNO_QUERY );
505 if( xCooSysProp.is() && ( xCooSysProp->getPropertyValue("SwapXAndYAxis") >>= bSwapXandYAxis )
506 && bSwapXandYAxis )
508 Reference< chart2::XAxis > xAxis = xCooSys->getAxisByDimension( 0, m_aCurrentAxis.nAxisIndex );
509 if( xAxis.is() )
511 chart2::ScaleData aScaleData = xAxis->getScaleData();
512 aScaleData.Orientation = chart2::AxisOrientation_REVERSE;
513 xAxis->setScaleData( aScaleData );
522 m_rbAxisPositionAttributeImported = m_rbAxisPositionAttributeImported || SchXMLTools::getPropertyFromContext(
523 u"CrossoverPosition", pPropStyleContext, pStylesCtxt ).hasValue();
528 if (m_aCurrentAxis.eDimension != SCH_XML_AXIS_X)
529 return;
531 Reference<chart2::XAxis> xAxis(lcl_getAxis(GetImport().GetModel(), m_aCurrentAxis.eDimension, m_aCurrentAxis.nAxisIndex));
532 if (!xAxis.is())
533 return;
535 chart2::ScaleData aScaleData(xAxis->getScaleData());
536 bool bIs3DChart = false;
537 double fMajorOrigin = -1;
538 OUString sChartType = m_xDiagram->getDiagramType();
539 if ((xDiaProp->getPropertyValue("Dim3D") >>= bIs3DChart) && bIs3DChart
540 && (sChartType == "com.sun.star.chart.BarDiagram" || sChartType == "com.sun.star.chart.StockDiagram"))
542 aScaleData.ShiftedCategoryPosition = true;
543 xAxis->setScaleData(aScaleData);
545 else if ((m_xAxisProps->getPropertyValue("MajorOrigin") >>= fMajorOrigin)
546 && (rtl::math::approxEqual(fMajorOrigin, 0.0) || rtl::math::approxEqual(fMajorOrigin, 0.5)))
548 aScaleData.ShiftedCategoryPosition = rtl::math::approxEqual(fMajorOrigin, 0.5);
549 xAxis->setScaleData(aScaleData);
553 void SchXMLAxisContext::SetAxisTitle()
555 if( m_aCurrentAxis.aTitle.isEmpty() )
556 return;
558 Reference< chart::XAxis > xAxis( lcl_getChartAxis( m_aCurrentAxis, m_xDiagram ) );
559 if( !xAxis.is() )
560 return;
562 Reference< beans::XPropertySet > xTitleProp( xAxis->getAxisTitle() );
563 if( xTitleProp.is() )
567 xTitleProp->setPropertyValue("String", uno::Any(m_aCurrentAxis.aTitle) );
569 catch( beans::UnknownPropertyException & )
571 SAL_INFO("xmloff.chart", "Property String for Title not available" );
576 css::uno::Reference< css::xml::sax::XFastContextHandler > SchXMLAxisContext::createFastChildContext(
577 sal_Int32 nElement,
578 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
580 switch( nElement )
582 case XML_ELEMENT(CHART, XML_TITLE):
584 Reference< drawing::XShape > xTitleShape = getTitleShape();
585 return new SchXMLTitleContext( m_rImportHelper, GetImport(),
586 m_aCurrentAxis.aTitle,
587 xTitleShape );
589 break;
591 case XML_ELEMENT(CHART, XML_CATEGORIES):
592 m_aCurrentAxis.bHasCategories = true;
593 return new SchXMLCategoriesContext( GetImport(),
594 m_rCategoriesAddress );
595 break;
597 case XML_ELEMENT(CHART, XML_DATE_SCALE):
598 case XML_ELEMENT(CHART_EXT, XML_DATE_SCALE):
599 m_bDateScaleImported = true;
600 return new DateScaleContext( GetImport(), m_xAxisProps );
602 case XML_ELEMENT(CHART, XML_GRID):
604 bool bIsMajor = true; // default value for class is "major"
605 OUString sAutoStyleName;
607 for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
609 switch (aIter.getToken())
611 case XML_ELEMENT(CHART, XML_CLASS):
612 if( IsXMLToken( aIter, XML_MINOR ) )
613 bIsMajor = false;
614 break;
615 case XML_ELEMENT(CHART, XML_STYLE_NAME):
616 sAutoStyleName = aIter.toString();
617 break;
618 default:
619 XMLOFF_WARN_UNKNOWN("xmloff", aIter);
623 CreateGrid( sAutoStyleName, bIsMajor );
625 // don't create a context => use default context. grid elements are empty
627 break;
629 default:
630 XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
631 break;
634 return nullptr;
637 void SchXMLAxisContext::endFastElement(sal_Int32 )
639 if( !m_bDateScaleImported && m_nAxisType==chart::ChartAxisType::AUTOMATIC )
641 Reference< chart2::XAxis > xAxis( lcl_getAxis( GetImport().GetModel(), m_aCurrentAxis.eDimension, m_aCurrentAxis.nAxisIndex ) );
642 if( xAxis.is() )
644 chart2::ScaleData aScaleData( xAxis->getScaleData());
645 aScaleData.AutoDateAxis = false;//different default for older documents
646 xAxis->setScaleData( aScaleData );
650 SetAxisTitle();
653 namespace
656 Reference< chart2::XAxis > lcl_getAxis( const Reference< chart2::XCoordinateSystem >& rCooSys, sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex )
658 Reference< chart2::XAxis > xAxis;
661 xAxis = rCooSys->getAxisByDimension( nDimensionIndex, nAxisIndex );
663 catch( uno::Exception & )
666 return xAxis;
669 } // anonymous namespace
671 void SchXMLAxisContext::CorrectAxisPositions( const Reference< chart2::XChartDocument >& xNewDoc,
672 std::u16string_view rChartTypeServiceName,
673 std::u16string_view rODFVersionOfFile,
674 bool bAxisPositionAttributeImported )
676 if( !(rODFVersionOfFile.empty() || rODFVersionOfFile == u"1.0" || rODFVersionOfFile == u"1.1"
677 || ( rODFVersionOfFile == u"1.2" && !bAxisPositionAttributeImported )) )
678 return;
682 Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xNewDoc->getFirstDiagram(), uno::UNO_QUERY_THROW );
683 uno::Sequence< Reference< chart2::XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems());
684 if( aCooSysSeq.hasElements() )
686 Reference< chart2::XCoordinateSystem > xCooSys( aCooSysSeq[0] );
687 if( xCooSys.is() )
689 Reference< chart2::XAxis > xMainXAxis = lcl_getAxis( xCooSys, 0, 0 );
690 Reference< chart2::XAxis > xMainYAxis = lcl_getAxis( xCooSys, 1, 0 );
691 //Reference< chart2::XAxis > xMajorZAxis = lcl_getAxis( xCooSys, 2, 0 );
692 Reference< chart2::XAxis > xSecondaryXAxis = lcl_getAxis( xCooSys, 0, 1 );
693 Reference< chart2::XAxis > xSecondaryYAxis = lcl_getAxis( xCooSys, 1, 1 );
695 Reference< beans::XPropertySet > xMainXAxisProp( xMainXAxis, uno::UNO_QUERY );
696 Reference< beans::XPropertySet > xMainYAxisProp( xMainYAxis, uno::UNO_QUERY );
697 Reference< beans::XPropertySet > xSecondaryXAxisProp( xSecondaryXAxis, uno::UNO_QUERY );
698 Reference< beans::XPropertySet > xSecondaryYAxisProp( xSecondaryYAxis, uno::UNO_QUERY );
700 if( xMainXAxisProp.is() && xMainYAxisProp.is() )
702 chart2::ScaleData aMainXScale = xMainXAxis->getScaleData();
703 if( rChartTypeServiceName == u"com.sun.star.chart2.ScatterChartType" )
705 xMainYAxisProp->setPropertyValue("CrossoverPosition"
706 , uno::Any( css::chart::ChartAxisPosition_VALUE) );
707 double fCrossoverValue = 0.0;
708 aMainXScale.Origin >>= fCrossoverValue;
709 xMainYAxisProp->setPropertyValue("CrossoverValue"
710 , uno::Any( fCrossoverValue ) );
712 if( aMainXScale.Orientation == chart2::AxisOrientation_REVERSE )
714 xMainYAxisProp->setPropertyValue("LabelPosition"
715 , uno::Any( css::chart::ChartAxisLabelPosition_OUTSIDE_END) );
716 xMainYAxisProp->setPropertyValue("MarkPosition"
717 , uno::Any( css::chart::ChartAxisMarkPosition_AT_LABELS) );
718 if( xSecondaryYAxisProp.is() )
719 xSecondaryYAxisProp->setPropertyValue("CrossoverPosition"
720 , uno::Any( css::chart::ChartAxisPosition_START) );
722 else
724 xMainYAxisProp->setPropertyValue("LabelPosition"
725 , uno::Any( css::chart::ChartAxisLabelPosition_OUTSIDE_START) );
726 xMainYAxisProp->setPropertyValue("MarkPosition"
727 , uno::Any( css::chart::ChartAxisMarkPosition_AT_LABELS) );
728 if( xSecondaryYAxisProp.is() )
729 xSecondaryYAxisProp->setPropertyValue("CrossoverPosition"
730 , uno::Any( css::chart::ChartAxisPosition_END) );
733 else
735 if( aMainXScale.Orientation == chart2::AxisOrientation_REVERSE )
737 xMainYAxisProp->setPropertyValue("CrossoverPosition"
738 , uno::Any( css::chart::ChartAxisPosition_END) );
739 if( xSecondaryYAxisProp.is() )
740 xSecondaryYAxisProp->setPropertyValue("CrossoverPosition"
741 , uno::Any( css::chart::ChartAxisPosition_START) );
743 else
745 xMainYAxisProp->setPropertyValue("CrossoverPosition"
746 , uno::Any( css::chart::ChartAxisPosition_START) );
747 if( xSecondaryYAxisProp.is() )
748 xSecondaryYAxisProp->setPropertyValue("CrossoverPosition"
749 , uno::Any( css::chart::ChartAxisPosition_END) );
753 chart2::ScaleData aMainYScale = xMainYAxis->getScaleData();
754 xMainXAxisProp->setPropertyValue("CrossoverPosition"
755 , uno::Any( css::chart::ChartAxisPosition_VALUE) );
756 double fCrossoverValue = 0.0;
757 aMainYScale.Origin >>= fCrossoverValue;
758 xMainXAxisProp->setPropertyValue("CrossoverValue"
759 , uno::Any( fCrossoverValue ) );
761 if( aMainYScale.Orientation == chart2::AxisOrientation_REVERSE )
763 xMainXAxisProp->setPropertyValue("LabelPosition"
764 , uno::Any( css::chart::ChartAxisLabelPosition_OUTSIDE_END) );
765 xMainXAxisProp->setPropertyValue("MarkPosition"
766 , uno::Any( css::chart::ChartAxisMarkPosition_AT_LABELS) );
767 if( xSecondaryXAxisProp.is() )
768 xSecondaryXAxisProp->setPropertyValue("CrossoverPosition"
769 , uno::Any( css::chart::ChartAxisPosition_START) );
771 else
773 xMainXAxisProp->setPropertyValue("LabelPosition"
774 , uno::Any( css::chart::ChartAxisLabelPosition_OUTSIDE_START) );
775 xMainXAxisProp->setPropertyValue("MarkPosition"
776 , uno::Any( css::chart::ChartAxisMarkPosition_AT_LABELS) );
777 if( xSecondaryXAxisProp.is() )
778 xSecondaryXAxisProp->setPropertyValue("CrossoverPosition"
779 , uno::Any( css::chart::ChartAxisPosition_END) );
785 catch( uno::Exception & )
790 SchXMLCategoriesContext::SchXMLCategoriesContext(
791 SvXMLImport& rImport,
792 OUString& rAddress ) :
793 SvXMLImportContext( rImport ),
794 mrAddress( rAddress )
798 void SchXMLCategoriesContext::startFastElement( sal_Int32 /*nElement*/,
799 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
801 for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
803 if( aIter.getToken() == XML_ELEMENT(TABLE, XML_CELL_RANGE_ADDRESS) )
804 mrAddress = aIter.toString();
805 else
806 XMLOFF_WARN_UNKNOWN("xmloff", aIter);
810 DateScaleContext::DateScaleContext(
811 SvXMLImport& rImport,
812 const Reference< beans::XPropertySet >& rAxisProps ) :
813 SvXMLImportContext( rImport ),
814 m_xAxisProps( rAxisProps )
818 namespace
820 sal_Int32 lcl_getTimeUnit( const sax_fastparser::FastAttributeList::FastAttributeIter& rValue )
822 sal_Int32 nTimeUnit = css::chart::TimeUnit::DAY;
823 if( IsXMLToken( rValue, XML_DAYS ) )
824 nTimeUnit = css::chart::TimeUnit::DAY;
825 else if( IsXMLToken( rValue, XML_MONTHS ) )
826 nTimeUnit = css::chart::TimeUnit::MONTH;
827 else if( IsXMLToken( rValue, XML_YEARS ) )
828 nTimeUnit = css::chart::TimeUnit::YEAR;
829 return nTimeUnit;
834 void DateScaleContext::startFastElement( sal_Int32 /*nElement*/,
835 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
837 if( !m_xAxisProps.is() )
838 return;
840 // parse attributes
841 bool bSetNewIncrement=false;
842 chart::TimeIncrement aIncrement;
843 m_xAxisProps->getPropertyValue("TimeIncrement") >>= aIncrement;
845 for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
847 switch( aIter.getToken() )
849 case XML_ELEMENT(CHART, XML_BASE_TIME_UNIT):
851 aIncrement.TimeResolution <<= lcl_getTimeUnit(aIter);
852 bSetNewIncrement = true;
854 break;
855 case XML_ELEMENT(CHART, XML_MAJOR_INTERVAL_VALUE):
857 chart::TimeInterval aInterval(1,0);
858 aIncrement.MajorTimeInterval >>= aInterval;
859 ::sax::Converter::convertNumber( aInterval.Number, aIter.toView() );
860 aIncrement.MajorTimeInterval <<= aInterval;
861 bSetNewIncrement = true;
863 break;
864 case XML_ELEMENT(CHART, XML_MAJOR_INTERVAL_UNIT):
866 chart::TimeInterval aInterval(1,0);
867 aIncrement.MajorTimeInterval >>= aInterval;
868 aInterval.TimeUnit = lcl_getTimeUnit(aIter);
869 aIncrement.MajorTimeInterval <<= aInterval;
870 bSetNewIncrement = true;
872 break;
873 case XML_ELEMENT(CHART, XML_MINOR_INTERVAL_VALUE):
875 chart::TimeInterval aInterval(1,0);
876 aIncrement.MinorTimeInterval >>= aInterval;
877 ::sax::Converter::convertNumber( aInterval.Number, aIter.toView() );
878 aIncrement.MinorTimeInterval <<= aInterval;
879 bSetNewIncrement = true;
881 break;
882 case XML_ELEMENT(CHART, XML_MINOR_INTERVAL_UNIT):
884 chart::TimeInterval aInterval(1,0);
885 aIncrement.MinorTimeInterval >>= aInterval;
886 aInterval.TimeUnit = lcl_getTimeUnit(aIter);
887 aIncrement.MinorTimeInterval <<= aInterval;
888 bSetNewIncrement = true;
890 break;
891 default:
892 XMLOFF_WARN_UNKNOWN("xmloff", aIter);
896 if( bSetNewIncrement )
897 m_xAxisProps->setPropertyValue("TimeIncrement", uno::Any( aIncrement ) );
900 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */