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/xmlnmspe.hxx>
26 #include <xmloff/xmlement.hxx>
27 #include <xmloff/xmlstyle.hxx>
28 #include <xmloff/prstylei.hxx>
29 #include <xmloff/nmspmap.hxx>
30 #include <xmloff/xmluconv.hxx>
32 #include <tools/color.hxx>
34 #include <com/sun/star/chart/ChartAxisLabelPosition.hpp>
35 #include <com/sun/star/chart/ChartAxisMarkPosition.hpp>
36 #include <com/sun/star/chart/ChartAxisPosition.hpp>
37 #include <com/sun/star/chart/ChartAxisType.hpp>
38 #include <com/sun/star/chart/TimeIncrement.hpp>
39 #include <com/sun/star/chart/TimeInterval.hpp>
40 #include <com/sun/star/chart/TimeUnit.hpp>
41 #include <com/sun/star/chart/XAxis.hpp>
42 #include <com/sun/star/chart/XAxisSupplier.hpp>
43 #include <com/sun/star/chart2/AxisType.hpp>
44 #include <com/sun/star/chart2/XChartDocument.hpp>
45 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
47 #include <com/sun/star/drawing/LineStyle.hpp>
49 using namespace ::xmloff::token
;
50 using namespace com::sun::star
;
52 using com::sun::star::uno::Reference
;
54 static const SvXMLEnumMapEntry aXMLAxisDimensionMap
[] =
56 { XML_X
, SCH_XML_AXIS_X
},
57 { XML_Y
, SCH_XML_AXIS_Y
},
58 { XML_Z
, SCH_XML_AXIS_Z
},
59 { XML_TOKEN_INVALID
, 0 }
62 static const SvXMLEnumMapEntry aXMLAxisTypeMap
[] =
64 { XML_AUTO
, css::chart::ChartAxisType::AUTOMATIC
},
65 { XML_TEXT
, css::chart::ChartAxisType::CATEGORY
},
66 { XML_DATE
, css::chart::ChartAxisType::DATE
},
67 { XML_TOKEN_INVALID
, 0 }
70 class SchXMLCategoriesContext
: public SvXMLImportContext
76 SchXMLCategoriesContext( SvXMLImport
& rImport
,
78 const OUString
& rLocalName
,
80 virtual ~SchXMLCategoriesContext();
81 virtual void StartElement( const Reference
< css::xml::sax::XAttributeList
>& xAttrList
) override
;
84 class DateScaleContext
: public SvXMLImportContext
87 DateScaleContext( SvXMLImport
& rImport
,
88 sal_uInt16 nPrefix
, const OUString
& rLocalName
,
89 const Reference
< beans::XPropertySet
>& rAxisProps
);
91 virtual ~DateScaleContext();
92 virtual void StartElement( const Reference
< css::xml::sax::XAttributeList
>& xAttrList
) override
;
95 Reference
< beans::XPropertySet
> m_xAxisProps
;
98 SchXMLAxisContext::SchXMLAxisContext( SchXMLImportHelper
& rImpHelper
,
99 SvXMLImport
& rImport
, const OUString
& rLocalName
,
100 Reference
< chart::XDiagram
> xDiagram
,
101 std::vector
< SchXMLAxis
>& rAxes
,
102 OUString
& rCategoriesAddress
,
103 bool bAddMissingXAxisForNetCharts
,
104 bool bAdaptWrongPercentScaleValues
,
105 bool bAdaptXAxisOrientationForOld2DBarCharts
,
106 bool& rbAxisPositionAttributeImported
) :
107 SvXMLImportContext( rImport
, XML_NAMESPACE_CHART
, rLocalName
),
108 m_rImportHelper( rImpHelper
),
109 m_xDiagram( xDiagram
),
111 m_rCategoriesAddress( rCategoriesAddress
),
112 m_nAxisType(chart::ChartAxisType::AUTOMATIC
),
113 m_bAxisTypeImported(false),
114 m_bDateScaleImported(false),
115 m_bAddMissingXAxisForNetCharts( bAddMissingXAxisForNetCharts
),
116 m_bAdaptWrongPercentScaleValues( bAdaptWrongPercentScaleValues
),
117 m_bAdaptXAxisOrientationForOld2DBarCharts( bAdaptXAxisOrientationForOld2DBarCharts
),
118 m_rbAxisPositionAttributeImported( rbAxisPositionAttributeImported
)
122 SchXMLAxisContext::~SchXMLAxisContext()
125 static Reference
< chart::XAxis
> lcl_getChartAxis(const SchXMLAxis
& rCurrentAxis
, const Reference
< chart::XDiagram
>& rDiagram
)
127 Reference
< chart::XAxis
> xAxis
;
128 Reference
< chart::XAxisSupplier
> xAxisSuppl( rDiagram
, uno::UNO_QUERY
);
129 if( !xAxisSuppl
.is() )
131 if( rCurrentAxis
.nAxisIndex
== 0 )
132 xAxis
= xAxisSuppl
->getAxis(rCurrentAxis
.eDimension
);
134 xAxis
= xAxisSuppl
->getSecondaryAxis(rCurrentAxis
.eDimension
);
138 /* returns a shape for the current axis's title. The property
139 "Has...AxisTitle" is set to "True" to get the shape
141 Reference
< drawing::XShape
> SchXMLAxisContext::getTitleShape()
143 Reference
< drawing::XShape
> xResult
;
144 Reference
< beans::XPropertySet
> xDiaProp( m_rImportHelper
.GetChartDocument()->getDiagram(), uno::UNO_QUERY
);
145 Reference
< chart::XAxis
> xAxis( lcl_getChartAxis( m_aCurrentAxis
, m_xDiagram
) );
146 if( !xDiaProp
.is() || !xAxis
.is() )
150 switch( m_aCurrentAxis
.eDimension
)
153 if( m_aCurrentAxis
.nAxisIndex
== 0 )
154 aPropName
= "HasXAxisTitle";
156 aPropName
= "HasSecondaryXAxisTitle";
159 if( m_aCurrentAxis
.nAxisIndex
== 0 )
160 aPropName
= "HasYAxisTitle";
162 aPropName
= "HasSecondaryYAxisTitle";
165 aPropName
= "HasZAxisTitle";
167 case SCH_XML_AXIS_UNDEF
:
168 SAL_INFO("xmloff.chart", "Invalid axis" );
171 xDiaProp
->setPropertyValue( aPropName
, uno::makeAny(true) );
172 xResult
.set( xAxis
->getAxisTitle(), uno::UNO_QUERY
);
176 void SchXMLAxisContext::CreateGrid( const OUString
& sAutoStyleName
, bool bIsMajor
)
178 Reference
< beans::XPropertySet
> xDiaProp( m_rImportHelper
.GetChartDocument()->getDiagram(), uno::UNO_QUERY
);
179 Reference
< chart::XAxis
> xAxis( lcl_getChartAxis( m_aCurrentAxis
, m_xDiagram
) );
180 if( !xDiaProp
.is() || !xAxis
.is() )
184 switch( m_aCurrentAxis
.eDimension
)
188 aPropName
= "HasXAxisGrid";
190 aPropName
= "HasXAxisHelpGrid";
194 aPropName
= "HasYAxisGrid";
196 aPropName
= "HasYAxisHelpGrid";
200 aPropName
= "HasZAxisGrid";
202 aPropName
= "HasZAxisHelpGrid";
204 case SCH_XML_AXIS_UNDEF
:
205 SAL_INFO("xmloff.chart", "Invalid axis" );
208 xDiaProp
->setPropertyValue( aPropName
, uno::makeAny(true) );
210 Reference
< beans::XPropertySet
> xGridProp
;
212 xGridProp
= xAxis
->getMajorGrid();
214 xGridProp
= xAxis
->getMinorGrid();
219 // the line color is black as default, in the model it is a light gray
220 xGridProp
->setPropertyValue("LineColor",
221 uno::makeAny( COL_BLACK
));
222 if( !sAutoStyleName
.isEmpty())
224 const SvXMLStylesContext
* pStylesCtxt
= m_rImportHelper
.GetAutoStylesContext();
227 const SvXMLStyleContext
* pStyle
= pStylesCtxt
->FindStyleChildContext(
228 SchXMLImportHelper::GetChartFamilyID(), sAutoStyleName
);
230 if( pStyle
&& dynamic_cast<const XMLPropStyleContext
*>( pStyle
) != nullptr)
231 const_cast<XMLPropStyleContext
*>( static_cast< const XMLPropStyleContext
* >( pStyle
))->FillPropertySet( xGridProp
);
239 enum AxisAttributeTokens
241 XML_TOK_AXIS_DIMENSION
,
243 XML_TOK_AXIS_STYLE_NAME
,
245 XML_TOK_AXIS_TYPE_EXT
248 const SvXMLTokenMapEntry aAxisAttributeTokenMap
[] =
250 { XML_NAMESPACE_CHART
, XML_DIMENSION
, XML_TOK_AXIS_DIMENSION
},
251 { XML_NAMESPACE_CHART
, XML_NAME
, XML_TOK_AXIS_NAME
},
252 { XML_NAMESPACE_CHART
, XML_STYLE_NAME
, XML_TOK_AXIS_STYLE_NAME
},
253 { XML_NAMESPACE_CHART
, XML_AXIS_TYPE
, XML_TOK_AXIS_TYPE
},
254 { XML_NAMESPACE_CHART_EXT
, XML_AXIS_TYPE
, XML_TOK_AXIS_TYPE_EXT
},
258 class AxisAttributeTokenMap
: public SvXMLTokenMap
261 AxisAttributeTokenMap(): SvXMLTokenMap( aAxisAttributeTokenMap
) {}
262 virtual ~AxisAttributeTokenMap() {}
265 //a AxisAttributeTokenMap Singleton
266 struct theAxisAttributeTokenMap
: public rtl::Static
< AxisAttributeTokenMap
, theAxisAttributeTokenMap
> {};
269 void SchXMLAxisContext::StartElement( const Reference
< xml::sax::XAttributeList
>& xAttrList
)
272 sal_Int16 nAttrCount
= xAttrList
.is()? xAttrList
->getLength(): 0;
273 const SvXMLTokenMap
& rAttrTokenMap
= theAxisAttributeTokenMap::get();
275 for( sal_Int16 i
= 0; i
< nAttrCount
; i
++ )
277 OUString sAttrName
= xAttrList
->getNameByIndex( i
);
279 OUString aValue
= xAttrList
->getValueByIndex( i
);
280 sal_uInt16 nPrefix
= GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName
, &aLocalName
);
282 switch( rAttrTokenMap
.Get( nPrefix
, aLocalName
))
284 case XML_TOK_AXIS_DIMENSION
:
287 if( SvXMLUnitConverter::convertEnum( nEnumVal
, aValue
, aXMLAxisDimensionMap
))
288 m_aCurrentAxis
.eDimension
= ( SchXMLAxisDimension
)nEnumVal
;
291 case XML_TOK_AXIS_NAME
:
292 m_aCurrentAxis
.aName
= aValue
;
294 case XML_TOK_AXIS_TYPE
:
295 case XML_TOK_AXIS_TYPE_EXT
:
297 if( SvXMLUnitConverter::convertEnum( nEnumVal
, aValue
, aXMLAxisTypeMap
))
299 m_nAxisType
= nEnumVal
;
300 m_bAxisTypeImported
= true;
303 case XML_TOK_AXIS_STYLE_NAME
:
304 m_aAutoStyleName
= aValue
;
309 // check for number of axes with same dimension
310 m_aCurrentAxis
.nAxisIndex
= 0;
311 sal_Int32 nNumOfAxes
= m_rAxes
.size();
312 for( sal_Int32 nCurrent
= 0; nCurrent
< nNumOfAxes
; nCurrent
++ )
314 if( m_rAxes
[ nCurrent
].eDimension
== m_aCurrentAxis
.eDimension
)
315 m_aCurrentAxis
.nAxisIndex
++;
322 Reference
< chart2::XAxis
> lcl_getAxis( const Reference
< frame::XModel
>& xChartModel
,
323 sal_Int32 nDimensionIndex
, sal_Int32 nAxisIndex
)
325 Reference
< chart2::XAxis
> xAxis
;
329 Reference
< chart2::XChartDocument
> xChart2Document( xChartModel
, uno::UNO_QUERY
);
330 if( xChart2Document
.is() )
332 Reference
< chart2::XDiagram
> xDiagram( xChart2Document
->getFirstDiagram());
333 Reference
< chart2::XCoordinateSystemContainer
> xCooSysCnt( xDiagram
, uno::UNO_QUERY_THROW
);
334 uno::Sequence
< Reference
< chart2::XCoordinateSystem
> >
335 aCooSysSeq( xCooSysCnt
->getCoordinateSystems());
336 sal_Int32 nCooSysIndex
= 0;
337 if( nCooSysIndex
< aCooSysSeq
.getLength() )
339 Reference
< chart2::XCoordinateSystem
> xCooSys( aCooSysSeq
[nCooSysIndex
] );
340 if( xCooSys
.is() && nDimensionIndex
< xCooSys
->getDimension() )
342 const sal_Int32 nMaxAxisIndex
= xCooSys
->getMaximumAxisIndexByDimension(nDimensionIndex
);
343 if( nAxisIndex
<= nMaxAxisIndex
)
344 xAxis
= xCooSys
->getAxisByDimension( nDimensionIndex
, nAxisIndex
);
349 catch( uno::Exception
& )
351 SAL_INFO("xmloff.chart", "Couldn't get axis" );
357 bool lcl_divideBy100( uno::Any
& rDoubleAny
)
359 bool bChanged
= false;
361 if( (rDoubleAny
>>=fValue
) && (fValue
!=0.0) )
364 rDoubleAny
= uno::makeAny(fValue
);
370 bool lcl_AdaptWrongPercentScaleValues(chart2::ScaleData
& rScaleData
)
372 bool bChanged
= lcl_divideBy100( rScaleData
.Minimum
);
373 bChanged
= lcl_divideBy100( rScaleData
.Maximum
) || bChanged
;
374 bChanged
= lcl_divideBy100( rScaleData
.Origin
) || bChanged
;
375 bChanged
= lcl_divideBy100( rScaleData
.IncrementData
.Distance
) || bChanged
;
379 }//end anonymous namespace
381 void SchXMLAxisContext::CreateAxis()
383 m_rAxes
.push_back( m_aCurrentAxis
);
385 Reference
< beans::XPropertySet
> xDiaProp( m_rImportHelper
.GetChartDocument()->getDiagram(), uno::UNO_QUERY
);
389 switch( m_aCurrentAxis
.eDimension
)
392 if( m_aCurrentAxis
.nAxisIndex
== 0 )
393 aPropName
= "HasXAxis";
395 aPropName
= "HasSecondaryXAxis";
398 if( m_aCurrentAxis
.nAxisIndex
== 0 )
399 aPropName
= "HasYAxis";
401 aPropName
= "HasSecondaryYAxis";
404 if( m_aCurrentAxis
.nAxisIndex
== 0 )
405 aPropName
= "HasXAxis";
407 aPropName
= "HasSecondaryXAxis";
409 case SCH_XML_AXIS_UNDEF
:
410 SAL_INFO("xmloff.chart", "Invalid axis" );
415 xDiaProp
->setPropertyValue( aPropName
, uno::makeAny(true) );
417 catch( beans::UnknownPropertyException
& )
419 SAL_INFO("xmloff.chart", "Couldn't turn on axis" );
421 if( m_aCurrentAxis
.eDimension
==SCH_XML_AXIS_Z
)
423 bool bSettingZAxisSuccedded
= false;
426 xDiaProp
->getPropertyValue( aPropName
) >>= bSettingZAxisSuccedded
;
428 catch( beans::UnknownPropertyException
& )
430 SAL_INFO("xmloff.chart", "Couldn't turn on z axis" );
432 if( !bSettingZAxisSuccedded
)
436 m_xAxisProps
.set( lcl_getChartAxis( m_aCurrentAxis
, m_xDiagram
), uno::UNO_QUERY
);
438 if( m_bAddMissingXAxisForNetCharts
&& m_aCurrentAxis
.eDimension
==SCH_XML_AXIS_Y
&& m_aCurrentAxis
.nAxisIndex
==0 )
442 xDiaProp
->setPropertyValue("HasXAxis", uno::makeAny(true) );
444 catch( beans::UnknownPropertyException
& )
446 SAL_INFO("xmloff.chart", "Couldn't turn on x axis" );
451 if( m_xAxisProps
.is())
453 uno::Any
aTrueBool( uno::makeAny( true ));
454 uno::Any
aFalseBool( uno::makeAny( false ));
456 // #i109879# the line color is black as default, in the model it is a light gray
457 m_xAxisProps
->setPropertyValue("LineColor",
458 uno::makeAny( COL_BLACK
));
460 m_xAxisProps
->setPropertyValue("DisplayLabels", aFalseBool
);
462 // Compatibility option: starting from LibreOffice 5.1 the rotated
463 // layout is preferred to staggering for axis labels.
464 // So the import default value for having compatibility with ODF
465 // documents created with earlier LibreOffice versions is `true`.
466 if( GetImport().getGeneratorVersion() != SvXMLImport::ProductVersionUnknown
)
467 m_xAxisProps
->setPropertyValue("TryStaggeringFirst", aTrueBool
);
469 // #88077# AutoOrigin 'on' is default
470 m_xAxisProps
->setPropertyValue("AutoOrigin", aTrueBool
);
472 if( m_bAxisTypeImported
)
473 m_xAxisProps
->setPropertyValue("AxisType", uno::makeAny(m_nAxisType
) );
475 if( !m_aAutoStyleName
.isEmpty())
477 const SvXMLStylesContext
* pStylesCtxt
= m_rImportHelper
.GetAutoStylesContext();
480 const SvXMLStyleContext
* pStyle
= pStylesCtxt
->FindStyleChildContext(
481 SchXMLImportHelper::GetChartFamilyID(), m_aAutoStyleName
);
483 if( pStyle
&& dynamic_cast<const XMLPropStyleContext
*>( pStyle
) != nullptr)
485 // note: SvXMLStyleContext::FillPropertySet is not const
486 XMLPropStyleContext
* pPropStyleContext
= const_cast< XMLPropStyleContext
* >( dynamic_cast< const XMLPropStyleContext
* >( pStyle
));
487 if( pPropStyleContext
)
488 pPropStyleContext
->FillPropertySet( m_xAxisProps
);
490 if( m_bAdaptWrongPercentScaleValues
&& m_aCurrentAxis
.eDimension
==SCH_XML_AXIS_Y
)
492 //set scale data of added x axis back to default
493 Reference
< chart2::XAxis
> xAxis( lcl_getAxis( GetImport().GetModel(),
494 m_aCurrentAxis
.eDimension
, m_aCurrentAxis
.nAxisIndex
) );
497 chart2::ScaleData
aScaleData( xAxis
->getScaleData());
498 if( lcl_AdaptWrongPercentScaleValues(aScaleData
) )
499 xAxis
->setScaleData( aScaleData
);
503 if( m_bAddMissingXAxisForNetCharts
)
505 //copy style from y axis to added x axis:
507 Reference
< chart::XAxisSupplier
> xAxisSuppl( xDiaProp
, uno::UNO_QUERY
);
508 if( xAxisSuppl
.is() )
510 Reference
< beans::XPropertySet
> xXAxisProp( xAxisSuppl
->getAxis(0), uno::UNO_QUERY
);
511 const_cast<XMLPropStyleContext
*>( static_cast< const XMLPropStyleContext
* >( pStyle
))->FillPropertySet( xXAxisProp
);
514 //set scale data of added x axis back to default
515 Reference
< chart2::XAxis
> xAxis( lcl_getAxis( GetImport().GetModel(),
516 0 /*nDimensionIndex*/, 0 /*nAxisIndex*/ ) );
519 chart2::ScaleData aScaleData
;
520 aScaleData
.AxisType
= chart2::AxisType::CATEGORY
;
521 aScaleData
.Orientation
= chart2::AxisOrientation_MATHEMATICAL
;
522 xAxis
->setScaleData( aScaleData
);
525 //set line style of added x axis to invisible
526 Reference
< beans::XPropertySet
> xNewAxisProp( xAxis
, uno::UNO_QUERY
);
527 if( xNewAxisProp
.is() )
529 xNewAxisProp
->setPropertyValue("LineStyle"
530 , uno::makeAny(drawing::LineStyle_NONE
));
534 if( m_bAdaptXAxisOrientationForOld2DBarCharts
&& m_aCurrentAxis
.eDimension
== SCH_XML_AXIS_X
)
536 bool bIs3DChart
= false;
537 if( xDiaProp
.is() && ( xDiaProp
->getPropertyValue("Dim3D") >>= bIs3DChart
)
540 Reference
< chart2::XChartDocument
> xChart2Document( GetImport().GetModel(), uno::UNO_QUERY
);
541 if( xChart2Document
.is() )
543 Reference
< chart2::XCoordinateSystemContainer
> xCooSysCnt( xChart2Document
->getFirstDiagram(), uno::UNO_QUERY
);
544 if( xCooSysCnt
.is() )
546 uno::Sequence
< Reference
< chart2::XCoordinateSystem
> > aCooSysSeq( xCooSysCnt
->getCoordinateSystems() );
547 if( aCooSysSeq
.getLength() )
549 bool bSwapXandYAxis
= false;
550 Reference
< chart2::XCoordinateSystem
> xCooSys( aCooSysSeq
[0] );
551 Reference
< beans::XPropertySet
> xCooSysProp( xCooSys
, uno::UNO_QUERY
);
552 if( xCooSysProp
.is() && ( xCooSysProp
->getPropertyValue("SwapXAndYAxis") >>= bSwapXandYAxis
)
555 Reference
< chart2::XAxis
> xAxis
= xCooSys
->getAxisByDimension( 0, m_aCurrentAxis
.nAxisIndex
);
558 chart2::ScaleData aScaleData
= xAxis
->getScaleData();
559 aScaleData
.Orientation
= chart2::AxisOrientation_REVERSE
;
560 xAxis
->setScaleData( aScaleData
);
569 m_rbAxisPositionAttributeImported
= m_rbAxisPositionAttributeImported
|| SchXMLTools::getPropertyFromContext(
570 "CrossoverPosition", pPropStyleContext
, pStylesCtxt
).hasValue();
577 void SchXMLAxisContext::SetAxisTitle()
579 if( m_aCurrentAxis
.aTitle
.isEmpty() )
582 Reference
< chart::XAxis
> xAxis( lcl_getChartAxis( m_aCurrentAxis
, m_xDiagram
) );
586 Reference
< beans::XPropertySet
> xTitleProp( xAxis
->getAxisTitle() );
587 if( xTitleProp
.is() )
591 xTitleProp
->setPropertyValue("String", uno::makeAny(m_aCurrentAxis
.aTitle
) );
593 catch( beans::UnknownPropertyException
& )
595 SAL_INFO("xmloff.chart", "Property String for Title not available" );
605 XML_TOK_AXIS_CATEGORIES
,
607 XML_TOK_AXIS_DATE_SCALE
,
608 XML_TOK_AXIS_DATE_SCALE_EXT
611 const SvXMLTokenMapEntry aAxisChildTokenMap
[] =
613 { XML_NAMESPACE_CHART
, XML_TITLE
, XML_TOK_AXIS_TITLE
},
614 { XML_NAMESPACE_CHART
, XML_CATEGORIES
, XML_TOK_AXIS_CATEGORIES
},
615 { XML_NAMESPACE_CHART
, XML_GRID
, XML_TOK_AXIS_GRID
},
616 { XML_NAMESPACE_CHART
, XML_DATE_SCALE
, XML_TOK_AXIS_DATE_SCALE
},
617 { XML_NAMESPACE_CHART_EXT
, XML_DATE_SCALE
, XML_TOK_AXIS_DATE_SCALE_EXT
},
621 class AxisChildTokenMap
: public SvXMLTokenMap
624 AxisChildTokenMap(): SvXMLTokenMap( aAxisChildTokenMap
) {}
625 virtual ~AxisChildTokenMap() {}
628 //a AxisChildTokenMap Singleton
629 struct theAxisChildTokenMap
: public rtl::Static
< AxisChildTokenMap
, theAxisChildTokenMap
> {};
632 SvXMLImportContext
* SchXMLAxisContext::CreateChildContext(
633 sal_uInt16 p_nPrefix
,
634 const OUString
& rLocalName
,
635 const Reference
< xml::sax::XAttributeList
>& xAttrList
)
637 SvXMLImportContext
* pContext
= nullptr;
638 const SvXMLTokenMap
& rTokenMap
= theAxisChildTokenMap::get();
640 switch( rTokenMap
.Get( p_nPrefix
, rLocalName
))
642 case XML_TOK_AXIS_TITLE
:
644 Reference
< drawing::XShape
> xTitleShape
= getTitleShape();
645 pContext
= new SchXMLTitleContext( m_rImportHelper
, GetImport(), rLocalName
,
646 m_aCurrentAxis
.aTitle
,
651 case XML_TOK_AXIS_CATEGORIES
:
652 pContext
= new SchXMLCategoriesContext( GetImport(),
653 p_nPrefix
, rLocalName
,
654 m_rCategoriesAddress
);
655 m_aCurrentAxis
.bHasCategories
= true;
658 case XML_TOK_AXIS_DATE_SCALE
:
659 case XML_TOK_AXIS_DATE_SCALE_EXT
:
660 pContext
= new DateScaleContext( GetImport(),
661 p_nPrefix
, rLocalName
, m_xAxisProps
);
662 m_bDateScaleImported
= true;
665 case XML_TOK_AXIS_GRID
:
667 sal_Int16 nAttrCount
= xAttrList
.is()? xAttrList
->getLength(): 0;
668 bool bIsMajor
= true; // default value for class is "major"
669 OUString sAutoStyleName
;
671 for( sal_Int16 i
= 0; i
< nAttrCount
; i
++ )
673 OUString sAttrName
= xAttrList
->getNameByIndex( i
);
675 sal_uInt16 nPrefix
= GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName
, &aLocalName
);
677 if( nPrefix
== XML_NAMESPACE_CHART
)
679 if( IsXMLToken( aLocalName
, XML_CLASS
) )
681 if( IsXMLToken( xAttrList
->getValueByIndex( i
), XML_MINOR
) )
684 else if( IsXMLToken( aLocalName
, XML_STYLE_NAME
) )
685 sAutoStyleName
= xAttrList
->getValueByIndex( i
);
689 CreateGrid( sAutoStyleName
, bIsMajor
);
691 // don't create a context => use default context. grid elements are empty
692 pContext
= new SvXMLImportContext( GetImport(), p_nPrefix
, rLocalName
);
697 pContext
= new SvXMLImportContext( GetImport(), p_nPrefix
, rLocalName
);
704 void SchXMLAxisContext::EndElement()
706 if( !m_bDateScaleImported
&& m_nAxisType
==chart::ChartAxisType::AUTOMATIC
)
708 Reference
< chart2::XAxis
> xAxis( lcl_getAxis( GetImport().GetModel(), m_aCurrentAxis
.eDimension
, m_aCurrentAxis
.nAxisIndex
) );
711 chart2::ScaleData
aScaleData( xAxis
->getScaleData());
712 aScaleData
.AutoDateAxis
= false;//different default for older documents
713 xAxis
->setScaleData( aScaleData
);
723 Reference
< chart2::XAxis
> lcl_getAxis( const Reference
< chart2::XCoordinateSystem
>& rCooSys
, sal_Int32 nDimensionIndex
, sal_Int32 nAxisIndex
)
725 Reference
< chart2::XAxis
> xAxis
;
728 xAxis
= rCooSys
->getAxisByDimension( nDimensionIndex
, nAxisIndex
);
730 catch( uno::Exception
& )
736 } // anonymous namespace
738 void SchXMLAxisContext::CorrectAxisPositions( const Reference
< chart2::XChartDocument
>& xNewDoc
,
739 const OUString
& rChartTypeServiceName
,
740 const OUString
& rODFVersionOfFile
,
741 bool bAxisPositionAttributeImported
)
743 if( ( rODFVersionOfFile
.isEmpty() || rODFVersionOfFile
== "1.0" || rODFVersionOfFile
== "1.1"
744 || ( rODFVersionOfFile
== "1.2" && !bAxisPositionAttributeImported
) ) )
748 Reference
< chart2::XCoordinateSystemContainer
> xCooSysCnt( xNewDoc
->getFirstDiagram(), uno::UNO_QUERY_THROW
);
749 uno::Sequence
< Reference
< chart2::XCoordinateSystem
> > aCooSysSeq( xCooSysCnt
->getCoordinateSystems());
750 if( aCooSysSeq
.getLength() )
752 Reference
< chart2::XCoordinateSystem
> xCooSys( aCooSysSeq
[0] );
755 Reference
< chart2::XAxis
> xMainXAxis
= lcl_getAxis( xCooSys
, 0, 0 );
756 Reference
< chart2::XAxis
> xMainYAxis
= lcl_getAxis( xCooSys
, 1, 0 );
757 //Reference< chart2::XAxis > xMajorZAxis = lcl_getAxis( xCooSys, 2, 0 );
758 Reference
< chart2::XAxis
> xSecondaryXAxis
= lcl_getAxis( xCooSys
, 0, 1 );
759 Reference
< chart2::XAxis
> xSecondaryYAxis
= lcl_getAxis( xCooSys
, 1, 1 );
761 Reference
< beans::XPropertySet
> xMainXAxisProp( xMainXAxis
, uno::UNO_QUERY
);
762 Reference
< beans::XPropertySet
> xMainYAxisProp( xMainYAxis
, uno::UNO_QUERY
);
763 Reference
< beans::XPropertySet
> xSecondaryXAxisProp( xSecondaryXAxis
, uno::UNO_QUERY
);
764 Reference
< beans::XPropertySet
> xSecondaryYAxisProp( xSecondaryYAxis
, uno::UNO_QUERY
);
766 if( xMainXAxisProp
.is() && xMainYAxisProp
.is() )
768 chart2::ScaleData aMainXScale
= xMainXAxis
->getScaleData();
769 if( rChartTypeServiceName
== "com.sun.star.chart2.ScatterChartType" )
771 xMainYAxisProp
->setPropertyValue("CrossoverPosition"
772 , uno::makeAny( css::chart::ChartAxisPosition_VALUE
) );
773 double fCrossoverValue
= 0.0;
774 aMainXScale
.Origin
>>= fCrossoverValue
;
775 xMainYAxisProp
->setPropertyValue("CrossoverValue"
776 , uno::makeAny( fCrossoverValue
) );
778 if( aMainXScale
.Orientation
== chart2::AxisOrientation_REVERSE
)
780 xMainYAxisProp
->setPropertyValue("LabelPosition"
781 , uno::makeAny( css::chart::ChartAxisLabelPosition_OUTSIDE_END
) );
782 xMainYAxisProp
->setPropertyValue("MarkPosition"
783 , uno::makeAny( css::chart::ChartAxisMarkPosition_AT_LABELS
) );
784 if( xSecondaryYAxisProp
.is() )
785 xSecondaryYAxisProp
->setPropertyValue("CrossoverPosition"
786 , uno::makeAny( css::chart::ChartAxisPosition_START
) );
790 xMainYAxisProp
->setPropertyValue("LabelPosition"
791 , uno::makeAny( css::chart::ChartAxisLabelPosition_OUTSIDE_START
) );
792 xMainYAxisProp
->setPropertyValue("MarkPosition"
793 , uno::makeAny( css::chart::ChartAxisMarkPosition_AT_LABELS
) );
794 if( xSecondaryYAxisProp
.is() )
795 xSecondaryYAxisProp
->setPropertyValue("CrossoverPosition"
796 , uno::makeAny( css::chart::ChartAxisPosition_END
) );
801 if( aMainXScale
.Orientation
== chart2::AxisOrientation_REVERSE
)
803 xMainYAxisProp
->setPropertyValue("CrossoverPosition"
804 , uno::makeAny( css::chart::ChartAxisPosition_END
) );
805 if( xSecondaryYAxisProp
.is() )
806 xSecondaryYAxisProp
->setPropertyValue("CrossoverPosition"
807 , uno::makeAny( css::chart::ChartAxisPosition_START
) );
811 xMainYAxisProp
->setPropertyValue("CrossoverPosition"
812 , uno::makeAny( css::chart::ChartAxisPosition_START
) );
813 if( xSecondaryYAxisProp
.is() )
814 xSecondaryYAxisProp
->setPropertyValue("CrossoverPosition"
815 , uno::makeAny( css::chart::ChartAxisPosition_END
) );
819 chart2::ScaleData aMainYScale
= xMainYAxis
->getScaleData();
820 xMainXAxisProp
->setPropertyValue("CrossoverPosition"
821 , uno::makeAny( css::chart::ChartAxisPosition_VALUE
) );
822 double fCrossoverValue
= 0.0;
823 aMainYScale
.Origin
>>= fCrossoverValue
;
824 xMainXAxisProp
->setPropertyValue("CrossoverValue"
825 , uno::makeAny( fCrossoverValue
) );
827 if( aMainYScale
.Orientation
== chart2::AxisOrientation_REVERSE
)
829 xMainXAxisProp
->setPropertyValue("LabelPosition"
830 , uno::makeAny( css::chart::ChartAxisLabelPosition_OUTSIDE_END
) );
831 xMainXAxisProp
->setPropertyValue("MarkPosition"
832 , uno::makeAny( css::chart::ChartAxisMarkPosition_AT_LABELS
) );
833 if( xSecondaryXAxisProp
.is() )
834 xSecondaryXAxisProp
->setPropertyValue("CrossoverPosition"
835 , uno::makeAny( css::chart::ChartAxisPosition_START
) );
839 xMainXAxisProp
->setPropertyValue("LabelPosition"
840 , uno::makeAny( css::chart::ChartAxisLabelPosition_OUTSIDE_START
) );
841 xMainXAxisProp
->setPropertyValue("MarkPosition"
842 , uno::makeAny( css::chart::ChartAxisMarkPosition_AT_LABELS
) );
843 if( xSecondaryXAxisProp
.is() )
844 xSecondaryXAxisProp
->setPropertyValue("CrossoverPosition"
845 , uno::makeAny( css::chart::ChartAxisPosition_END
) );
851 catch( uno::Exception
& )
857 SchXMLCategoriesContext::SchXMLCategoriesContext(
858 SvXMLImport
& rImport
,
860 const OUString
& rLocalName
,
861 OUString
& rAddress
) :
862 SvXMLImportContext( rImport
, nPrefix
, rLocalName
),
863 mrAddress( rAddress
)
867 SchXMLCategoriesContext::~SchXMLCategoriesContext()
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 Reference
< chart2::XChartDocument
> xNewDoc( GetImport().GetModel(), uno::UNO_QUERY
);
885 mrAddress
= xAttrList
->getValueByIndex( i
);
890 DateScaleContext::DateScaleContext(
891 SvXMLImport
& rImport
,
893 const OUString
& rLocalName
,
894 const Reference
< beans::XPropertySet
>& rAxisProps
) :
895 SvXMLImportContext( rImport
, nPrefix
, rLocalName
),
896 m_xAxisProps( rAxisProps
)
900 DateScaleContext::~DateScaleContext()
906 enum DateScaleAttributeTokens
908 XML_TOK_DATESCALE_BASE_TIME_UNIT
,
909 XML_TOK_DATESCALE_MAJOR_INTERVAL_VALUE
,
910 XML_TOK_DATESCALE_MAJOR_INTERVAL_UNIT
,
911 XML_TOK_DATESCALE_MINOR_INTERVAL_VALUE
,
912 XML_TOK_DATESCALE_MINOR_INTERVAL_UNIT
915 const SvXMLTokenMapEntry aDateScaleAttributeTokenMap
[] =
917 { XML_NAMESPACE_CHART
, XML_BASE_TIME_UNIT
, XML_TOK_DATESCALE_BASE_TIME_UNIT
},
918 { XML_NAMESPACE_CHART
, XML_MAJOR_INTERVAL_VALUE
, XML_TOK_DATESCALE_MAJOR_INTERVAL_VALUE
},
919 { XML_NAMESPACE_CHART
, XML_MAJOR_INTERVAL_UNIT
, XML_TOK_DATESCALE_MAJOR_INTERVAL_UNIT
},
920 { XML_NAMESPACE_CHART
, XML_MINOR_INTERVAL_VALUE
, XML_TOK_DATESCALE_MINOR_INTERVAL_VALUE
},
921 { XML_NAMESPACE_CHART
, XML_MINOR_INTERVAL_UNIT
, XML_TOK_DATESCALE_MINOR_INTERVAL_UNIT
},
925 class DateScaleAttributeTokenMap
: public SvXMLTokenMap
928 DateScaleAttributeTokenMap(): SvXMLTokenMap( aDateScaleAttributeTokenMap
) {}
929 virtual ~DateScaleAttributeTokenMap() {}
932 struct theDateScaleAttributeTokenMap
: public rtl::Static
< DateScaleAttributeTokenMap
, theDateScaleAttributeTokenMap
> {};
934 sal_Int32
lcl_getTimeUnit( const OUString
& rValue
)
936 sal_Int32 nTimeUnit
= css::chart::TimeUnit::DAY
;
937 if( IsXMLToken( rValue
, XML_DAYS
) )
938 nTimeUnit
= css::chart::TimeUnit::DAY
;
939 else if( IsXMLToken( rValue
, XML_MONTHS
) )
940 nTimeUnit
= css::chart::TimeUnit::MONTH
;
941 else if( IsXMLToken( rValue
, XML_YEARS
) )
942 nTimeUnit
= css::chart::TimeUnit::YEAR
;
948 void DateScaleContext::StartElement( const Reference
< xml::sax::XAttributeList
>& xAttrList
)
950 if( !m_xAxisProps
.is() )
954 sal_Int16 nAttrCount
= xAttrList
.is()? xAttrList
->getLength(): 0;
955 const SvXMLTokenMap
& rAttrTokenMap
= theDateScaleAttributeTokenMap::get();
957 bool bSetNewIncrement
=false;
958 chart::TimeIncrement aIncrement
;
959 m_xAxisProps
->getPropertyValue("TimeIncrement") >>= aIncrement
;
961 for( sal_Int16 i
= 0; i
< nAttrCount
; i
++ )
963 OUString sAttrName
= xAttrList
->getNameByIndex( i
);
965 OUString aValue
= xAttrList
->getValueByIndex( i
);
966 sal_uInt16 nPrefix
= GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName
, &aLocalName
);
968 switch( rAttrTokenMap
.Get( nPrefix
, aLocalName
))
970 case XML_TOK_DATESCALE_BASE_TIME_UNIT
:
972 aIncrement
.TimeResolution
= uno::makeAny( lcl_getTimeUnit(aValue
) );
973 bSetNewIncrement
= true;
976 case XML_TOK_DATESCALE_MAJOR_INTERVAL_VALUE
:
978 chart::TimeInterval
aInterval(1,0);
979 aIncrement
.MajorTimeInterval
>>= aInterval
;
980 ::sax::Converter::convertNumber( aInterval
.Number
, aValue
);
981 aIncrement
.MajorTimeInterval
= uno::makeAny(aInterval
);
982 bSetNewIncrement
= true;
985 case XML_TOK_DATESCALE_MAJOR_INTERVAL_UNIT
:
987 chart::TimeInterval
aInterval(1,0);
988 aIncrement
.MajorTimeInterval
>>= aInterval
;
989 aInterval
.TimeUnit
= lcl_getTimeUnit(aValue
);
990 aIncrement
.MajorTimeInterval
= uno::makeAny(aInterval
);
991 bSetNewIncrement
= true;
994 case XML_TOK_DATESCALE_MINOR_INTERVAL_VALUE
:
996 chart::TimeInterval
aInterval(1,0);
997 aIncrement
.MinorTimeInterval
>>= aInterval
;
998 ::sax::Converter::convertNumber( aInterval
.Number
, aValue
);
999 aIncrement
.MinorTimeInterval
= uno::makeAny(aInterval
);
1000 bSetNewIncrement
= true;
1003 case XML_TOK_DATESCALE_MINOR_INTERVAL_UNIT
:
1005 chart::TimeInterval
aInterval(1,0);
1006 aIncrement
.MinorTimeInterval
>>= aInterval
;
1007 aInterval
.TimeUnit
= lcl_getTimeUnit(aValue
);
1008 aIncrement
.MinorTimeInterval
= uno::makeAny(aInterval
);
1009 bSetNewIncrement
= true;
1015 if( bSetNewIncrement
)
1016 m_xAxisProps
->setPropertyValue("TimeIncrement", uno::makeAny( aIncrement
) );
1019 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */