1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <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
79 SchXMLCategoriesContext( SvXMLImport
& rImport
,
81 const OUString
& rLocalName
,
83 virtual void StartElement( const Reference
< css::xml::sax::XAttributeList
>& xAttrList
) override
;
86 class DateScaleContext
: public SvXMLImportContext
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
;
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
),
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() )
132 if( rCurrentAxis
.nAxisIndex
== 0 )
133 xAxis
= xAxisSuppl
->getAxis(rCurrentAxis
.eDimension
);
135 xAxis
= xAxisSuppl
->getSecondaryAxis(rCurrentAxis
.eDimension
);
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() )
151 switch( m_aCurrentAxis
.eDimension
)
154 if( m_aCurrentAxis
.nAxisIndex
== 0 )
155 aPropName
= "HasXAxisTitle";
157 aPropName
= "HasSecondaryXAxisTitle";
160 if( m_aCurrentAxis
.nAxisIndex
== 0 )
161 aPropName
= "HasYAxisTitle";
163 aPropName
= "HasSecondaryYAxisTitle";
166 aPropName
= "HasZAxisTitle";
168 case SCH_XML_AXIS_UNDEF
:
169 SAL_INFO("xmloff.chart", "Invalid axis" );
172 xDiaProp
->setPropertyValue( aPropName
, uno::makeAny(true) );
173 xResult
.set( xAxis
->getAxisTitle(), uno::UNO_QUERY
);
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() )
185 switch( m_aCurrentAxis
.eDimension
)
189 aPropName
= "HasXAxisGrid";
191 aPropName
= "HasXAxisHelpGrid";
195 aPropName
= "HasYAxisGrid";
197 aPropName
= "HasYAxisHelpGrid";
201 aPropName
= "HasZAxisGrid";
203 aPropName
= "HasZAxisHelpGrid";
205 case SCH_XML_AXIS_UNDEF
:
206 SAL_INFO("xmloff.chart", "Invalid axis" );
209 xDiaProp
->setPropertyValue( aPropName
, uno::makeAny(true) );
211 Reference
< beans::XPropertySet
> xGridProp
;
213 xGridProp
= xAxis
->getMajorGrid();
215 xGridProp
= xAxis
->getMinorGrid();
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
);
230 enum AxisAttributeTokens
232 XML_TOK_AXIS_DIMENSION
,
234 XML_TOK_AXIS_STYLE_NAME
,
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
},
249 class AxisAttributeTokenMap
: public SvXMLTokenMap
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
)
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
);
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
;
282 case XML_TOK_AXIS_NAME
:
283 m_aCurrentAxis
.aName
= aValue
;
285 case XML_TOK_AXIS_TYPE
:
286 case XML_TOK_AXIS_TYPE_EXT
:
288 if( SvXMLUnitConverter::convertEnum( nEnumVal
, aValue
, aXMLAxisTypeMap
))
290 m_nAxisType
= nEnumVal
;
291 m_bAxisTypeImported
= true;
294 case XML_TOK_AXIS_STYLE_NAME
:
295 m_aAutoStyleName
= aValue
;
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
++;
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" );
348 bool lcl_divideBy100( uno::Any
& rDoubleAny
)
350 bool bChanged
= false;
352 if( (rDoubleAny
>>=fValue
) && (fValue
!=0.0) )
355 rDoubleAny
<<= fValue
;
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
;
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
);
380 switch( m_aCurrentAxis
.eDimension
)
383 if( m_aCurrentAxis
.nAxisIndex
== 0 )
384 aPropName
= "HasXAxis";
386 aPropName
= "HasSecondaryXAxis";
389 if( m_aCurrentAxis
.nAxisIndex
== 0 )
390 aPropName
= "HasYAxis";
392 aPropName
= "HasSecondaryYAxis";
395 if( m_aCurrentAxis
.nAxisIndex
== 0 )
396 aPropName
= "HasZAxis";
398 case SCH_XML_AXIS_UNDEF
:
399 SAL_INFO("xmloff.chart", "Invalid axis" );
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
)
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" );
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
));
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();
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
) );
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*/ ) );
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
)
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
)
559 Reference
< chart2::XAxis
> xAxis
= xCooSys
->getAxisByDimension( 0, m_aCurrentAxis
.nAxisIndex
);
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() )
586 Reference
< chart::XAxis
> xAxis( lcl_getChartAxis( m_aCurrentAxis
, m_xDiagram
) );
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" );
609 XML_TOK_AXIS_CATEGORIES
,
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
},
625 class AxisChildTokenMap
: public SvXMLTokenMap
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
,
655 case XML_TOK_AXIS_CATEGORIES
:
656 pContext
= new SchXMLCategoriesContext( GetImport(),
657 p_nPrefix
, rLocalName
,
658 m_rCategoriesAddress
);
659 m_aCurrentAxis
.bHasCategories
= true;
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;
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
);
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
) )
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
);
701 pContext
= new SvXMLImportContext( GetImport(), p_nPrefix
, rLocalName
);
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
) );
715 chart2::ScaleData
aScaleData( xAxis
->getScaleData());
716 aScaleData
.AutoDateAxis
= false;//different default for older documents
717 xAxis
->setScaleData( aScaleData
);
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
& )
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] );
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
) );
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
) );
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
) );
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
) );
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
,
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
);
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
,
892 const OUString
& rLocalName
,
893 const Reference
< beans::XPropertySet
>& rAxisProps
) :
894 SvXMLImportContext( rImport
, nPrefix
, rLocalName
),
895 m_xAxisProps( rAxisProps
)
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
},
920 class DateScaleAttributeTokenMap
: public SvXMLTokenMap
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
;
943 void DateScaleContext::StartElement( const Reference
< xml::sax::XAttributeList
>& xAttrList
)
945 if( !m_xAxisProps
.is() )
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
);
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;
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;
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;
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;
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;
1010 if( bSetNewIncrement
)
1011 m_xAxisProps
->setPropertyValue("TimeIncrement", uno::makeAny( aIncrement
) );
1014 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */