Teach symstore more duplicated DLLs
[LibreOffice.git] / xmloff / source / chart / SchXMLAxisContext.cxx
blob931983bc8c01268589555e8cb71e628ded90b1a7
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/xmlnmspe.hxx>
27 #include <xmloff/xmlement.hxx>
28 #include <xmloff/xmlstyle.hxx>
29 #include <xmloff/prstylei.hxx>
30 #include <xmloff/nmspmap.hxx>
31 #include <xmloff/xmluconv.hxx>
33 #include <tools/color.hxx>
34 #include <sal/log.hxx>
36 #include <com/sun/star/chart/ChartAxisLabelPosition.hpp>
37 #include <com/sun/star/chart/ChartAxisMarkPosition.hpp>
38 #include <com/sun/star/chart/ChartAxisPosition.hpp>
39 #include <com/sun/star/chart/ChartAxisType.hpp>
40 #include <com/sun/star/chart/TimeIncrement.hpp>
41 #include <com/sun/star/chart/TimeInterval.hpp>
42 #include <com/sun/star/chart/TimeUnit.hpp>
43 #include <com/sun/star/chart/XAxis.hpp>
44 #include <com/sun/star/chart/XAxisSupplier.hpp>
45 #include <com/sun/star/chart/XChartDocument.hpp>
46 #include <com/sun/star/chart2/AxisType.hpp>
47 #include <com/sun/star/chart2/XChartDocument.hpp>
48 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
50 #include <com/sun/star/drawing/LineStyle.hpp>
52 using namespace ::xmloff::token;
53 using namespace com::sun::star;
55 using com::sun::star::uno::Reference;
57 static const SvXMLEnumMapEntry<SchXMLAxisDimension> aXMLAxisDimensionMap[] =
59 { XML_X, SCH_XML_AXIS_X },
60 { XML_Y, SCH_XML_AXIS_Y },
61 { XML_Z, SCH_XML_AXIS_Z },
62 { XML_TOKEN_INVALID, SchXMLAxisDimension(0) }
65 static const SvXMLEnumMapEntry<sal_uInt16> aXMLAxisTypeMap[] =
67 { XML_AUTO, css::chart::ChartAxisType::AUTOMATIC },
68 { XML_TEXT, css::chart::ChartAxisType::CATEGORY },
69 { XML_DATE, css::chart::ChartAxisType::DATE },
70 { XML_TOKEN_INVALID, 0 }
73 class SchXMLCategoriesContext : public SvXMLImportContext
75 private:
76 OUString& mrAddress;
78 public:
79 SchXMLCategoriesContext( SvXMLImport& rImport,
80 sal_uInt16 nPrefix,
81 const OUString& rLocalName,
82 OUString& rAddress );
83 virtual void StartElement( const Reference< css::xml::sax::XAttributeList >& xAttrList ) override;
86 class DateScaleContext : public SvXMLImportContext
88 public:
89 DateScaleContext( SvXMLImport& rImport,
90 sal_uInt16 nPrefix, const OUString& rLocalName,
91 const Reference< beans::XPropertySet >& rAxisProps );
93 virtual void StartElement( const Reference< css::xml::sax::XAttributeList >& xAttrList ) override;
95 private:
96 Reference< beans::XPropertySet > m_xAxisProps;
99 SchXMLAxisContext::SchXMLAxisContext( SchXMLImportHelper& rImpHelper,
100 SvXMLImport& rImport, const OUString& rLocalName,
101 Reference< chart::XDiagram > const & xDiagram,
102 std::vector< SchXMLAxis >& rAxes,
103 OUString & rCategoriesAddress,
104 bool bAddMissingXAxisForNetCharts,
105 bool bAdaptWrongPercentScaleValues,
106 bool bAdaptXAxisOrientationForOld2DBarCharts,
107 bool& rbAxisPositionAttributeImported ) :
108 SvXMLImportContext( rImport, XML_NAMESPACE_CHART, rLocalName ),
109 m_rImportHelper( rImpHelper ),
110 m_xDiagram( xDiagram ),
111 m_rAxes( rAxes ),
112 m_rCategoriesAddress( rCategoriesAddress ),
113 m_nAxisType(chart::ChartAxisType::AUTOMATIC),
114 m_bAxisTypeImported(false),
115 m_bDateScaleImported(false),
116 m_bAddMissingXAxisForNetCharts( bAddMissingXAxisForNetCharts ),
117 m_bAdaptWrongPercentScaleValues( bAdaptWrongPercentScaleValues ),
118 m_bAdaptXAxisOrientationForOld2DBarCharts( bAdaptXAxisOrientationForOld2DBarCharts ),
119 m_rbAxisPositionAttributeImported( rbAxisPositionAttributeImported )
123 SchXMLAxisContext::~SchXMLAxisContext()
126 static Reference< chart::XAxis > lcl_getChartAxis(const SchXMLAxis& rCurrentAxis, const Reference< chart::XDiagram >& rDiagram )
128 Reference< chart::XAxis > xAxis;
129 Reference< chart::XAxisSupplier > xAxisSuppl( rDiagram, uno::UNO_QUERY );
130 if( !xAxisSuppl.is() )
131 return xAxis;
132 if( rCurrentAxis.nAxisIndex == 0 )
133 xAxis = xAxisSuppl->getAxis(rCurrentAxis.eDimension);
134 else
135 xAxis = xAxisSuppl->getSecondaryAxis(rCurrentAxis.eDimension);
136 return xAxis;
139 /* returns a shape for the current axis's title. The property
140 "Has...AxisTitle" is set to "True" to get the shape
142 Reference< drawing::XShape > SchXMLAxisContext::getTitleShape() const
144 Reference< drawing::XShape > xResult;
145 Reference< beans::XPropertySet > xDiaProp( m_rImportHelper.GetChartDocument()->getDiagram(), uno::UNO_QUERY );
146 Reference< chart::XAxis > xAxis( lcl_getChartAxis( m_aCurrentAxis, m_xDiagram ) );
147 if( !xDiaProp.is() || !xAxis.is() )
148 return xResult;
150 OUString aPropName;
151 switch( m_aCurrentAxis.eDimension )
153 case SCH_XML_AXIS_X:
154 if( m_aCurrentAxis.nAxisIndex == 0 )
155 aPropName = "HasXAxisTitle";
156 else
157 aPropName = "HasSecondaryXAxisTitle";
158 break;
159 case SCH_XML_AXIS_Y:
160 if( m_aCurrentAxis.nAxisIndex == 0 )
161 aPropName = "HasYAxisTitle";
162 else
163 aPropName = "HasSecondaryYAxisTitle";
164 break;
165 case SCH_XML_AXIS_Z:
166 aPropName = "HasZAxisTitle";
167 break;
168 case SCH_XML_AXIS_UNDEF:
169 SAL_INFO("xmloff.chart", "Invalid axis" );
170 break;
172 xDiaProp->setPropertyValue( aPropName, uno::makeAny(true) );
173 xResult.set( xAxis->getAxisTitle(), uno::UNO_QUERY );
174 return xResult;
177 void SchXMLAxisContext::CreateGrid( const OUString& sAutoStyleName, bool bIsMajor )
179 Reference< beans::XPropertySet > xDiaProp( m_rImportHelper.GetChartDocument()->getDiagram(), uno::UNO_QUERY );
180 Reference< chart::XAxis > xAxis( lcl_getChartAxis( m_aCurrentAxis, m_xDiagram ) );
181 if( !xDiaProp.is() || !xAxis.is() )
182 return;
184 OUString aPropName;
185 switch( m_aCurrentAxis.eDimension )
187 case SCH_XML_AXIS_X:
188 if( bIsMajor )
189 aPropName = "HasXAxisGrid";
190 else
191 aPropName = "HasXAxisHelpGrid";
192 break;
193 case SCH_XML_AXIS_Y:
194 if( bIsMajor )
195 aPropName = "HasYAxisGrid";
196 else
197 aPropName = "HasYAxisHelpGrid";
198 break;
199 case SCH_XML_AXIS_Z:
200 if( bIsMajor )
201 aPropName = "HasZAxisGrid";
202 else
203 aPropName = "HasZAxisHelpGrid";
204 break;
205 case SCH_XML_AXIS_UNDEF:
206 SAL_INFO("xmloff.chart", "Invalid axis" );
207 break;
209 xDiaProp->setPropertyValue( aPropName, uno::makeAny(true) );
211 Reference< beans::XPropertySet > xGridProp;
212 if( bIsMajor )
213 xGridProp = xAxis->getMajorGrid();
214 else
215 xGridProp = xAxis->getMinorGrid();
217 // set properties
218 if( xGridProp.is())
220 // the line color is black as default, in the model it is a light gray
221 xGridProp->setPropertyValue("LineColor",
222 uno::makeAny( COL_BLACK ));
223 if (!sAutoStyleName.isEmpty())
224 m_rImportHelper.FillAutoStyle(sAutoStyleName, xGridProp);
228 namespace
230 enum AxisAttributeTokens
232 XML_TOK_AXIS_DIMENSION,
233 XML_TOK_AXIS_NAME,
234 XML_TOK_AXIS_STYLE_NAME,
235 XML_TOK_AXIS_TYPE,
236 XML_TOK_AXIS_TYPE_EXT
239 const SvXMLTokenMapEntry aAxisAttributeTokenMap[] =
241 { XML_NAMESPACE_CHART, XML_DIMENSION, XML_TOK_AXIS_DIMENSION },
242 { XML_NAMESPACE_CHART, XML_NAME, XML_TOK_AXIS_NAME },
243 { XML_NAMESPACE_CHART, XML_STYLE_NAME, XML_TOK_AXIS_STYLE_NAME },
244 { XML_NAMESPACE_CHART, XML_AXIS_TYPE, XML_TOK_AXIS_TYPE },
245 { XML_NAMESPACE_CHART_EXT, XML_AXIS_TYPE, XML_TOK_AXIS_TYPE_EXT },
246 XML_TOKEN_MAP_END
249 class AxisAttributeTokenMap : public SvXMLTokenMap
251 public:
252 AxisAttributeTokenMap(): SvXMLTokenMap( aAxisAttributeTokenMap ) {}
253 virtual ~AxisAttributeTokenMap() {}
256 //a AxisAttributeTokenMap Singleton
257 struct theAxisAttributeTokenMap : public rtl::Static< AxisAttributeTokenMap, theAxisAttributeTokenMap > {};
260 void SchXMLAxisContext::StartElement( const Reference< xml::sax::XAttributeList >& xAttrList )
262 // parse attributes
263 sal_Int16 nAttrCount = xAttrList.is()? xAttrList->getLength(): 0;
264 const SvXMLTokenMap& rAttrTokenMap = theAxisAttributeTokenMap::get();
266 for( sal_Int16 i = 0; i < nAttrCount; i++ )
268 OUString sAttrName = xAttrList->getNameByIndex( i );
269 OUString aLocalName;
270 OUString aValue = xAttrList->getValueByIndex( i );
271 sal_uInt16 nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
273 switch( rAttrTokenMap.Get( nPrefix, aLocalName ))
275 case XML_TOK_AXIS_DIMENSION:
277 SchXMLAxisDimension nEnumVal;
278 if( SvXMLUnitConverter::convertEnum( nEnumVal, aValue, aXMLAxisDimensionMap ))
279 m_aCurrentAxis.eDimension = nEnumVal;
281 break;
282 case XML_TOK_AXIS_NAME:
283 m_aCurrentAxis.aName = aValue;
284 break;
285 case XML_TOK_AXIS_TYPE:
286 case XML_TOK_AXIS_TYPE_EXT:
287 sal_uInt16 nEnumVal;
288 if( SvXMLUnitConverter::convertEnum( nEnumVal, aValue, aXMLAxisTypeMap ))
290 m_nAxisType = nEnumVal;
291 m_bAxisTypeImported = true;
293 break;
294 case XML_TOK_AXIS_STYLE_NAME:
295 m_aAutoStyleName = aValue;
296 break;
300 // check for number of axes with same dimension
301 m_aCurrentAxis.nAxisIndex = 0;
302 sal_Int32 nNumOfAxes = m_rAxes.size();
303 for( sal_Int32 nCurrent = 0; nCurrent < nNumOfAxes; nCurrent++ )
305 if( m_rAxes[ nCurrent ].eDimension == m_aCurrentAxis.eDimension )
306 m_aCurrentAxis.nAxisIndex++;
308 CreateAxis();
310 namespace
313 Reference< chart2::XAxis > lcl_getAxis( const Reference< frame::XModel >& xChartModel,
314 sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex )
316 Reference< chart2::XAxis > xAxis;
320 Reference< chart2::XChartDocument > xChart2Document( xChartModel, uno::UNO_QUERY );
321 if( xChart2Document.is() )
323 Reference< chart2::XDiagram > xDiagram( xChart2Document->getFirstDiagram());
324 Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xDiagram, uno::UNO_QUERY_THROW );
325 uno::Sequence< Reference< chart2::XCoordinateSystem > >
326 aCooSysSeq( xCooSysCnt->getCoordinateSystems());
327 sal_Int32 nCooSysIndex = 0;
328 if( nCooSysIndex < aCooSysSeq.getLength() )
330 Reference< chart2::XCoordinateSystem > xCooSys( aCooSysSeq[nCooSysIndex] );
331 if( xCooSys.is() && nDimensionIndex < xCooSys->getDimension() )
333 const sal_Int32 nMaxAxisIndex = xCooSys->getMaximumAxisIndexByDimension(nDimensionIndex);
334 if( nAxisIndex <= nMaxAxisIndex )
335 xAxis = xCooSys->getAxisByDimension( nDimensionIndex, nAxisIndex );
340 catch( uno::Exception & )
342 SAL_INFO("xmloff.chart", "Couldn't get axis" );
345 return xAxis;
348 bool lcl_divideBy100( uno::Any& rDoubleAny )
350 bool bChanged = false;
351 double fValue=0.0;
352 if( (rDoubleAny>>=fValue) && (fValue!=0.0) )
354 fValue/=100.0;
355 rDoubleAny <<= fValue;
356 bChanged = true;
358 return bChanged;
361 bool lcl_AdaptWrongPercentScaleValues(chart2::ScaleData& rScaleData)
363 bool bChanged = lcl_divideBy100( rScaleData.Minimum );
364 bChanged = lcl_divideBy100( rScaleData.Maximum ) || bChanged;
365 bChanged = lcl_divideBy100( rScaleData.Origin ) || bChanged;
366 bChanged = lcl_divideBy100( rScaleData.IncrementData.Distance ) || bChanged;
367 return bChanged;
370 }//end anonymous namespace
372 void SchXMLAxisContext::CreateAxis()
374 m_rAxes.push_back( m_aCurrentAxis );
376 Reference< beans::XPropertySet > xDiaProp( m_rImportHelper.GetChartDocument()->getDiagram(), uno::UNO_QUERY );
377 if( !xDiaProp.is() )
378 return;
379 OUString aPropName;
380 switch( m_aCurrentAxis.eDimension )
382 case SCH_XML_AXIS_X:
383 if( m_aCurrentAxis.nAxisIndex == 0 )
384 aPropName = "HasXAxis";
385 else
386 aPropName = "HasSecondaryXAxis";
387 break;
388 case SCH_XML_AXIS_Y:
389 if( m_aCurrentAxis.nAxisIndex == 0 )
390 aPropName = "HasYAxis";
391 else
392 aPropName = "HasSecondaryYAxis";
393 break;
394 case SCH_XML_AXIS_Z:
395 if( m_aCurrentAxis.nAxisIndex == 0 )
396 aPropName = "HasZAxis";
397 break;
398 case SCH_XML_AXIS_UNDEF:
399 SAL_INFO("xmloff.chart", "Invalid axis" );
400 break;
404 xDiaProp->setPropertyValue( aPropName, uno::makeAny(true) );
406 catch( beans::UnknownPropertyException & )
408 SAL_INFO("xmloff.chart", "Couldn't turn on axis" );
410 if( m_aCurrentAxis.eDimension==SCH_XML_AXIS_Z )
412 bool bSettingZAxisSuccedded = false;
415 xDiaProp->getPropertyValue( aPropName ) >>= bSettingZAxisSuccedded;
417 catch( beans::UnknownPropertyException & )
419 SAL_INFO("xmloff.chart", "Couldn't turn on z axis" );
421 if( !bSettingZAxisSuccedded )
422 return;
425 m_xAxisProps.set( lcl_getChartAxis( m_aCurrentAxis, m_xDiagram ), uno::UNO_QUERY );
427 if( m_bAddMissingXAxisForNetCharts && m_aCurrentAxis.eDimension==SCH_XML_AXIS_Y && m_aCurrentAxis.nAxisIndex==0 )
431 xDiaProp->setPropertyValue("HasXAxis", uno::makeAny(true) );
433 catch( beans::UnknownPropertyException & )
435 SAL_INFO("xmloff.chart", "Couldn't turn on x axis" );
439 // set properties
440 if( m_xAxisProps.is())
442 uno::Any aTrueBool( uno::makeAny( true ));
443 uno::Any aFalseBool( uno::makeAny( false ));
445 // #i109879# the line color is black as default, in the model it is a light gray
446 m_xAxisProps->setPropertyValue("LineColor",
447 uno::makeAny( COL_BLACK ));
449 m_xAxisProps->setPropertyValue("DisplayLabels", aFalseBool );
451 // Compatibility option: starting from LibreOffice 5.1 the rotated
452 // layout is preferred to staggering for axis labels.
453 // So the import default value for having compatibility with ODF
454 // documents created with earlier LibreOffice versions is `true`.
455 if( GetImport().getGeneratorVersion() != SvXMLImport::ProductVersionUnknown )
456 m_xAxisProps->setPropertyValue("TryStaggeringFirst", aTrueBool );
458 // #88077# AutoOrigin 'on' is default
459 m_xAxisProps->setPropertyValue("AutoOrigin", aTrueBool );
461 if( m_bAxisTypeImported )
462 m_xAxisProps->setPropertyValue("AxisType", uno::makeAny(m_nAxisType) );
464 if( m_aCurrentAxis.eDimension == SCH_XML_AXIS_X )
466 bool bIs3DChart = false;
467 if( (xDiaProp->getPropertyValue("Dim3D") >>= bIs3DChart) && bIs3DChart )
469 OUString sChartType = m_xDiagram->getDiagramType();
470 if( sChartType == "com.sun.star.chart.BarDiagram" || sChartType == "com.sun.star.chart.StockDiagram" )
472 Reference< chart2::XAxis > xAxis(lcl_getAxis(GetImport().GetModel(), m_aCurrentAxis.eDimension, m_aCurrentAxis.nAxisIndex));
473 if( xAxis.is() )
475 chart2::ScaleData aScaleData(xAxis->getScaleData());
476 aScaleData.ShiftedCategoryPosition = true;
477 xAxis->setScaleData(aScaleData);
483 if( !m_aAutoStyleName.isEmpty())
485 const SvXMLStylesContext* pStylesCtxt = m_rImportHelper.GetAutoStylesContext();
486 if (pStylesCtxt)
488 SvXMLStyleContext* pStyle = const_cast<SvXMLStyleContext*>(pStylesCtxt->FindStyleChildContext(SchXMLImportHelper::GetChartFamilyID(), m_aAutoStyleName));
490 if (XMLPropStyleContext * pPropStyleContext = dynamic_cast<XMLPropStyleContext*>(pStyle))
492 pPropStyleContext->FillPropertySet(m_xAxisProps);
494 if( m_bAdaptWrongPercentScaleValues && m_aCurrentAxis.eDimension==SCH_XML_AXIS_Y )
496 //set scale data of added x axis back to default
497 Reference< chart2::XAxis > xAxis( lcl_getAxis( GetImport().GetModel(),
498 m_aCurrentAxis.eDimension, m_aCurrentAxis.nAxisIndex ) );
499 if( xAxis.is() )
501 chart2::ScaleData aScaleData( xAxis->getScaleData());
502 if( lcl_AdaptWrongPercentScaleValues(aScaleData) )
503 xAxis->setScaleData( aScaleData );
507 if( m_bAddMissingXAxisForNetCharts )
509 //copy style from y axis to added x axis:
511 Reference< chart::XAxisSupplier > xAxisSuppl( xDiaProp, uno::UNO_QUERY );
512 if( xAxisSuppl.is() )
514 Reference< beans::XPropertySet > xXAxisProp( xAxisSuppl->getAxis(0), uno::UNO_QUERY );
515 pPropStyleContext->FillPropertySet(xXAxisProp);
518 //set scale data of added x axis back to default
519 Reference< chart2::XAxis > xAxis( lcl_getAxis( GetImport().GetModel(),
520 0 /*nDimensionIndex*/, 0 /*nAxisIndex*/ ) );
521 if( xAxis.is() )
523 chart2::ScaleData aScaleData;
524 aScaleData.AxisType = chart2::AxisType::CATEGORY;
525 aScaleData.Orientation = chart2::AxisOrientation_MATHEMATICAL;
526 xAxis->setScaleData( aScaleData );
529 //set line style of added x axis to invisible
530 Reference< beans::XPropertySet > xNewAxisProp( xAxis, uno::UNO_QUERY );
531 if( xNewAxisProp.is() )
533 xNewAxisProp->setPropertyValue("LineStyle"
534 , uno::makeAny(drawing::LineStyle_NONE));
538 if( m_bAdaptXAxisOrientationForOld2DBarCharts && m_aCurrentAxis.eDimension == SCH_XML_AXIS_X )
540 bool bIs3DChart = false;
541 if( xDiaProp.is() && ( xDiaProp->getPropertyValue("Dim3D") >>= bIs3DChart )
542 && !bIs3DChart )
544 Reference< chart2::XChartDocument > xChart2Document( GetImport().GetModel(), uno::UNO_QUERY );
545 if( xChart2Document.is() )
547 Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xChart2Document->getFirstDiagram(), uno::UNO_QUERY );
548 if( xCooSysCnt.is() )
550 uno::Sequence< Reference< chart2::XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems() );
551 if( aCooSysSeq.hasElements() )
553 bool bSwapXandYAxis = false;
554 Reference< chart2::XCoordinateSystem > xCooSys( aCooSysSeq[0] );
555 Reference< beans::XPropertySet > xCooSysProp( xCooSys, uno::UNO_QUERY );
556 if( xCooSysProp.is() && ( xCooSysProp->getPropertyValue("SwapXAndYAxis") >>= bSwapXandYAxis )
557 && bSwapXandYAxis )
559 Reference< chart2::XAxis > xAxis = xCooSys->getAxisByDimension( 0, m_aCurrentAxis.nAxisIndex );
560 if( xAxis.is() )
562 chart2::ScaleData aScaleData = xAxis->getScaleData();
563 aScaleData.Orientation = chart2::AxisOrientation_REVERSE;
564 xAxis->setScaleData( aScaleData );
573 m_rbAxisPositionAttributeImported = m_rbAxisPositionAttributeImported || SchXMLTools::getPropertyFromContext(
574 "CrossoverPosition", pPropStyleContext, pStylesCtxt ).hasValue();
581 void SchXMLAxisContext::SetAxisTitle()
583 if( m_aCurrentAxis.aTitle.isEmpty() )
584 return;
586 Reference< chart::XAxis > xAxis( lcl_getChartAxis( m_aCurrentAxis, m_xDiagram ) );
587 if( !xAxis.is() )
588 return;
590 Reference< beans::XPropertySet > xTitleProp( xAxis->getAxisTitle() );
591 if( xTitleProp.is() )
595 xTitleProp->setPropertyValue("String", uno::makeAny(m_aCurrentAxis.aTitle) );
597 catch( beans::UnknownPropertyException & )
599 SAL_INFO("xmloff.chart", "Property String for Title not available" );
604 namespace
606 enum AxisChildTokens
608 XML_TOK_AXIS_TITLE,
609 XML_TOK_AXIS_CATEGORIES,
610 XML_TOK_AXIS_GRID,
611 XML_TOK_AXIS_DATE_SCALE,
612 XML_TOK_AXIS_DATE_SCALE_EXT
615 const SvXMLTokenMapEntry aAxisChildTokenMap[] =
617 { XML_NAMESPACE_CHART, XML_TITLE, XML_TOK_AXIS_TITLE },
618 { XML_NAMESPACE_CHART, XML_CATEGORIES, XML_TOK_AXIS_CATEGORIES },
619 { XML_NAMESPACE_CHART, XML_GRID, XML_TOK_AXIS_GRID },
620 { XML_NAMESPACE_CHART, XML_DATE_SCALE, XML_TOK_AXIS_DATE_SCALE },
621 { XML_NAMESPACE_CHART_EXT, XML_DATE_SCALE, XML_TOK_AXIS_DATE_SCALE_EXT },
622 XML_TOKEN_MAP_END
625 class AxisChildTokenMap : public SvXMLTokenMap
627 public:
628 AxisChildTokenMap(): SvXMLTokenMap( aAxisChildTokenMap ) {}
629 virtual ~AxisChildTokenMap() {}
632 //a AxisChildTokenMap Singleton
633 struct theAxisChildTokenMap : public rtl::Static< AxisChildTokenMap, theAxisChildTokenMap > {};
636 SvXMLImportContextRef SchXMLAxisContext::CreateChildContext(
637 sal_uInt16 p_nPrefix,
638 const OUString& rLocalName,
639 const Reference< xml::sax::XAttributeList >& xAttrList )
641 SvXMLImportContext* pContext = nullptr;
642 const SvXMLTokenMap& rTokenMap = theAxisChildTokenMap::get();
644 switch( rTokenMap.Get( p_nPrefix, rLocalName ))
646 case XML_TOK_AXIS_TITLE:
648 Reference< drawing::XShape > xTitleShape = getTitleShape();
649 pContext = new SchXMLTitleContext( m_rImportHelper, GetImport(), rLocalName,
650 m_aCurrentAxis.aTitle,
651 xTitleShape );
653 break;
655 case XML_TOK_AXIS_CATEGORIES:
656 pContext = new SchXMLCategoriesContext( GetImport(),
657 p_nPrefix, rLocalName,
658 m_rCategoriesAddress );
659 m_aCurrentAxis.bHasCategories = true;
660 break;
662 case XML_TOK_AXIS_DATE_SCALE:
663 case XML_TOK_AXIS_DATE_SCALE_EXT:
664 pContext = new DateScaleContext( GetImport(),
665 p_nPrefix, rLocalName, m_xAxisProps );
666 m_bDateScaleImported = true;
667 break;
669 case XML_TOK_AXIS_GRID:
671 sal_Int16 nAttrCount = xAttrList.is()? xAttrList->getLength(): 0;
672 bool bIsMajor = true; // default value for class is "major"
673 OUString sAutoStyleName;
675 for( sal_Int16 i = 0; i < nAttrCount; i++ )
677 OUString sAttrName = xAttrList->getNameByIndex( i );
678 OUString aLocalName;
679 sal_uInt16 nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
681 if( nPrefix == XML_NAMESPACE_CHART )
683 if( IsXMLToken( aLocalName, XML_CLASS ) )
685 if( IsXMLToken( xAttrList->getValueByIndex( i ), XML_MINOR ) )
686 bIsMajor = false;
688 else if( IsXMLToken( aLocalName, XML_STYLE_NAME ) )
689 sAutoStyleName = xAttrList->getValueByIndex( i );
693 CreateGrid( sAutoStyleName, bIsMajor );
695 // don't create a context => use default context. grid elements are empty
696 pContext = new SvXMLImportContext( GetImport(), p_nPrefix, rLocalName );
698 break;
700 default:
701 pContext = new SvXMLImportContext( GetImport(), p_nPrefix, rLocalName );
702 break;
705 return pContext;
708 void SchXMLAxisContext::EndElement()
710 if( !m_bDateScaleImported && m_nAxisType==chart::ChartAxisType::AUTOMATIC )
712 Reference< chart2::XAxis > xAxis( lcl_getAxis( GetImport().GetModel(), m_aCurrentAxis.eDimension, m_aCurrentAxis.nAxisIndex ) );
713 if( xAxis.is() )
715 chart2::ScaleData aScaleData( xAxis->getScaleData());
716 aScaleData.AutoDateAxis = false;//different default for older documents
717 xAxis->setScaleData( aScaleData );
721 SetAxisTitle();
724 namespace
727 Reference< chart2::XAxis > lcl_getAxis( const Reference< chart2::XCoordinateSystem >& rCooSys, sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex )
729 Reference< chart2::XAxis > xAxis;
732 xAxis = rCooSys->getAxisByDimension( nDimensionIndex, nAxisIndex );
734 catch( uno::Exception & )
737 return xAxis;
740 } // anonymous namespace
742 void SchXMLAxisContext::CorrectAxisPositions( const Reference< chart2::XChartDocument >& xNewDoc,
743 const OUString& rChartTypeServiceName,
744 const OUString& rODFVersionOfFile,
745 bool bAxisPositionAttributeImported )
747 if( rODFVersionOfFile.isEmpty() || rODFVersionOfFile == "1.0" || rODFVersionOfFile == "1.1"
748 || ( rODFVersionOfFile == "1.2" && !bAxisPositionAttributeImported ) )
752 Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xNewDoc->getFirstDiagram(), uno::UNO_QUERY_THROW );
753 uno::Sequence< Reference< chart2::XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems());
754 if( aCooSysSeq.hasElements() )
756 Reference< chart2::XCoordinateSystem > xCooSys( aCooSysSeq[0] );
757 if( xCooSys.is() )
759 Reference< chart2::XAxis > xMainXAxis = lcl_getAxis( xCooSys, 0, 0 );
760 Reference< chart2::XAxis > xMainYAxis = lcl_getAxis( xCooSys, 1, 0 );
761 //Reference< chart2::XAxis > xMajorZAxis = lcl_getAxis( xCooSys, 2, 0 );
762 Reference< chart2::XAxis > xSecondaryXAxis = lcl_getAxis( xCooSys, 0, 1 );
763 Reference< chart2::XAxis > xSecondaryYAxis = lcl_getAxis( xCooSys, 1, 1 );
765 Reference< beans::XPropertySet > xMainXAxisProp( xMainXAxis, uno::UNO_QUERY );
766 Reference< beans::XPropertySet > xMainYAxisProp( xMainYAxis, uno::UNO_QUERY );
767 Reference< beans::XPropertySet > xSecondaryXAxisProp( xSecondaryXAxis, uno::UNO_QUERY );
768 Reference< beans::XPropertySet > xSecondaryYAxisProp( xSecondaryYAxis, uno::UNO_QUERY );
770 if( xMainXAxisProp.is() && xMainYAxisProp.is() )
772 chart2::ScaleData aMainXScale = xMainXAxis->getScaleData();
773 if( rChartTypeServiceName == "com.sun.star.chart2.ScatterChartType" )
775 xMainYAxisProp->setPropertyValue("CrossoverPosition"
776 , uno::makeAny( css::chart::ChartAxisPosition_VALUE) );
777 double fCrossoverValue = 0.0;
778 aMainXScale.Origin >>= fCrossoverValue;
779 xMainYAxisProp->setPropertyValue("CrossoverValue"
780 , uno::makeAny( fCrossoverValue ) );
782 if( aMainXScale.Orientation == chart2::AxisOrientation_REVERSE )
784 xMainYAxisProp->setPropertyValue("LabelPosition"
785 , uno::makeAny( css::chart::ChartAxisLabelPosition_OUTSIDE_END) );
786 xMainYAxisProp->setPropertyValue("MarkPosition"
787 , uno::makeAny( css::chart::ChartAxisMarkPosition_AT_LABELS) );
788 if( xSecondaryYAxisProp.is() )
789 xSecondaryYAxisProp->setPropertyValue("CrossoverPosition"
790 , uno::makeAny( css::chart::ChartAxisPosition_START) );
792 else
794 xMainYAxisProp->setPropertyValue("LabelPosition"
795 , uno::makeAny( css::chart::ChartAxisLabelPosition_OUTSIDE_START) );
796 xMainYAxisProp->setPropertyValue("MarkPosition"
797 , uno::makeAny( css::chart::ChartAxisMarkPosition_AT_LABELS) );
798 if( xSecondaryYAxisProp.is() )
799 xSecondaryYAxisProp->setPropertyValue("CrossoverPosition"
800 , uno::makeAny( css::chart::ChartAxisPosition_END) );
803 else
805 if( aMainXScale.Orientation == chart2::AxisOrientation_REVERSE )
807 xMainYAxisProp->setPropertyValue("CrossoverPosition"
808 , uno::makeAny( css::chart::ChartAxisPosition_END) );
809 if( xSecondaryYAxisProp.is() )
810 xSecondaryYAxisProp->setPropertyValue("CrossoverPosition"
811 , uno::makeAny( css::chart::ChartAxisPosition_START) );
813 else
815 xMainYAxisProp->setPropertyValue("CrossoverPosition"
816 , uno::makeAny( css::chart::ChartAxisPosition_START) );
817 if( xSecondaryYAxisProp.is() )
818 xSecondaryYAxisProp->setPropertyValue("CrossoverPosition"
819 , uno::makeAny( css::chart::ChartAxisPosition_END) );
823 chart2::ScaleData aMainYScale = xMainYAxis->getScaleData();
824 xMainXAxisProp->setPropertyValue("CrossoverPosition"
825 , uno::makeAny( css::chart::ChartAxisPosition_VALUE) );
826 double fCrossoverValue = 0.0;
827 aMainYScale.Origin >>= fCrossoverValue;
828 xMainXAxisProp->setPropertyValue("CrossoverValue"
829 , uno::makeAny( fCrossoverValue ) );
831 if( aMainYScale.Orientation == chart2::AxisOrientation_REVERSE )
833 xMainXAxisProp->setPropertyValue("LabelPosition"
834 , uno::makeAny( css::chart::ChartAxisLabelPosition_OUTSIDE_END) );
835 xMainXAxisProp->setPropertyValue("MarkPosition"
836 , uno::makeAny( css::chart::ChartAxisMarkPosition_AT_LABELS) );
837 if( xSecondaryXAxisProp.is() )
838 xSecondaryXAxisProp->setPropertyValue("CrossoverPosition"
839 , uno::makeAny( css::chart::ChartAxisPosition_START) );
841 else
843 xMainXAxisProp->setPropertyValue("LabelPosition"
844 , uno::makeAny( css::chart::ChartAxisLabelPosition_OUTSIDE_START) );
845 xMainXAxisProp->setPropertyValue("MarkPosition"
846 , uno::makeAny( css::chart::ChartAxisMarkPosition_AT_LABELS) );
847 if( xSecondaryXAxisProp.is() )
848 xSecondaryXAxisProp->setPropertyValue("CrossoverPosition"
849 , uno::makeAny( css::chart::ChartAxisPosition_END) );
855 catch( uno::Exception & )
861 SchXMLCategoriesContext::SchXMLCategoriesContext(
862 SvXMLImport& rImport,
863 sal_uInt16 nPrefix,
864 const OUString& rLocalName,
865 OUString& rAddress ) :
866 SvXMLImportContext( rImport, nPrefix, rLocalName ),
867 mrAddress( rAddress )
871 void SchXMLCategoriesContext::StartElement( const Reference< xml::sax::XAttributeList >& xAttrList )
873 sal_Int16 nAttrCount = xAttrList.is()? xAttrList->getLength(): 0;
875 for( sal_Int16 i = 0; i < nAttrCount; i++ )
877 OUString sAttrName = xAttrList->getNameByIndex( i );
878 OUString aLocalName;
879 sal_uInt16 nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
881 if( nPrefix == XML_NAMESPACE_TABLE &&
882 IsXMLToken( aLocalName, XML_CELL_RANGE_ADDRESS ) )
884 mrAddress = xAttrList->getValueByIndex( i );
889 DateScaleContext::DateScaleContext(
890 SvXMLImport& rImport,
891 sal_uInt16 nPrefix,
892 const OUString& rLocalName,
893 const Reference< beans::XPropertySet >& rAxisProps ) :
894 SvXMLImportContext( rImport, nPrefix, rLocalName ),
895 m_xAxisProps( rAxisProps )
899 namespace
901 enum DateScaleAttributeTokens
903 XML_TOK_DATESCALE_BASE_TIME_UNIT,
904 XML_TOK_DATESCALE_MAJOR_INTERVAL_VALUE,
905 XML_TOK_DATESCALE_MAJOR_INTERVAL_UNIT,
906 XML_TOK_DATESCALE_MINOR_INTERVAL_VALUE,
907 XML_TOK_DATESCALE_MINOR_INTERVAL_UNIT
910 const SvXMLTokenMapEntry aDateScaleAttributeTokenMap[] =
912 { XML_NAMESPACE_CHART, XML_BASE_TIME_UNIT, XML_TOK_DATESCALE_BASE_TIME_UNIT },
913 { XML_NAMESPACE_CHART, XML_MAJOR_INTERVAL_VALUE, XML_TOK_DATESCALE_MAJOR_INTERVAL_VALUE },
914 { XML_NAMESPACE_CHART, XML_MAJOR_INTERVAL_UNIT, XML_TOK_DATESCALE_MAJOR_INTERVAL_UNIT },
915 { XML_NAMESPACE_CHART, XML_MINOR_INTERVAL_VALUE, XML_TOK_DATESCALE_MINOR_INTERVAL_VALUE },
916 { XML_NAMESPACE_CHART, XML_MINOR_INTERVAL_UNIT, XML_TOK_DATESCALE_MINOR_INTERVAL_UNIT },
917 XML_TOKEN_MAP_END
920 class DateScaleAttributeTokenMap : public SvXMLTokenMap
922 public:
923 DateScaleAttributeTokenMap(): SvXMLTokenMap( aDateScaleAttributeTokenMap ) {}
924 virtual ~DateScaleAttributeTokenMap() {}
927 struct theDateScaleAttributeTokenMap : public rtl::Static< DateScaleAttributeTokenMap, theDateScaleAttributeTokenMap > {};
929 sal_Int32 lcl_getTimeUnit( const OUString& rValue )
931 sal_Int32 nTimeUnit = css::chart::TimeUnit::DAY;
932 if( IsXMLToken( rValue, XML_DAYS ) )
933 nTimeUnit = css::chart::TimeUnit::DAY;
934 else if( IsXMLToken( rValue, XML_MONTHS ) )
935 nTimeUnit = css::chart::TimeUnit::MONTH;
936 else if( IsXMLToken( rValue, XML_YEARS ) )
937 nTimeUnit = css::chart::TimeUnit::YEAR;
938 return nTimeUnit;
943 void DateScaleContext::StartElement( const Reference< xml::sax::XAttributeList >& xAttrList )
945 if( !m_xAxisProps.is() )
946 return;
948 // parse attributes
949 sal_Int16 nAttrCount = xAttrList.is()? xAttrList->getLength(): 0;
950 const SvXMLTokenMap& rAttrTokenMap = theDateScaleAttributeTokenMap::get();
952 bool bSetNewIncrement=false;
953 chart::TimeIncrement aIncrement;
954 m_xAxisProps->getPropertyValue("TimeIncrement") >>= aIncrement;
956 for( sal_Int16 i = 0; i < nAttrCount; i++ )
958 OUString sAttrName = xAttrList->getNameByIndex( i );
959 OUString aLocalName;
960 OUString aValue = xAttrList->getValueByIndex( i );
961 sal_uInt16 nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
963 switch( rAttrTokenMap.Get( nPrefix, aLocalName ))
965 case XML_TOK_DATESCALE_BASE_TIME_UNIT:
967 aIncrement.TimeResolution <<= lcl_getTimeUnit(aValue);
968 bSetNewIncrement = true;
970 break;
971 case XML_TOK_DATESCALE_MAJOR_INTERVAL_VALUE:
973 chart::TimeInterval aInterval(1,0);
974 aIncrement.MajorTimeInterval >>= aInterval;
975 ::sax::Converter::convertNumber( aInterval.Number, aValue );
976 aIncrement.MajorTimeInterval <<= aInterval;
977 bSetNewIncrement = true;
979 break;
980 case XML_TOK_DATESCALE_MAJOR_INTERVAL_UNIT:
982 chart::TimeInterval aInterval(1,0);
983 aIncrement.MajorTimeInterval >>= aInterval;
984 aInterval.TimeUnit = lcl_getTimeUnit(aValue);
985 aIncrement.MajorTimeInterval <<= aInterval;
986 bSetNewIncrement = true;
988 break;
989 case XML_TOK_DATESCALE_MINOR_INTERVAL_VALUE:
991 chart::TimeInterval aInterval(1,0);
992 aIncrement.MinorTimeInterval >>= aInterval;
993 ::sax::Converter::convertNumber( aInterval.Number, aValue );
994 aIncrement.MinorTimeInterval <<= aInterval;
995 bSetNewIncrement = true;
997 break;
998 case XML_TOK_DATESCALE_MINOR_INTERVAL_UNIT:
1000 chart::TimeInterval aInterval(1,0);
1001 aIncrement.MinorTimeInterval >>= aInterval;
1002 aInterval.TimeUnit = lcl_getTimeUnit(aValue);
1003 aIncrement.MinorTimeInterval <<= aInterval;
1004 bSetNewIncrement = true;
1006 break;
1010 if( bSetNewIncrement )
1011 m_xAxisProps->setPropertyValue("TimeIncrement", uno::makeAny( aIncrement ) );
1014 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */