LibreOffice Module xmloff (master) 1
SchXMLAxisContext.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
21
22#include "SchXMLAxisContext.hxx"
24#include "SchXMLTools.hxx"
25#include <xmloff/xmlimp.hxx>
27#include <xmloff/xmlement.hxx>
28#include <xmloff/xmlstyle.hxx>
29#include <xmloff/prstylei.hxx>
31#include <xmloff/xmluconv.hxx>
32
33#include <rtl/math.hxx>
34#include <tools/color.hxx>
35#include <sal/log.hxx>
36
37#include <com/sun/star/chart/ChartAxisLabelPosition.hpp>
38#include <com/sun/star/chart/ChartAxisMarkPosition.hpp>
39#include <com/sun/star/chart/ChartAxisPosition.hpp>
40#include <com/sun/star/chart/ChartAxisType.hpp>
41#include <com/sun/star/chart/TimeIncrement.hpp>
42#include <com/sun/star/chart/TimeInterval.hpp>
43#include <com/sun/star/chart/TimeUnit.hpp>
44#include <com/sun/star/chart/XAxis.hpp>
45#include <com/sun/star/chart/XAxisSupplier.hpp>
46#include <com/sun/star/chart/XChartDocument.hpp>
47#include <com/sun/star/chart2/AxisType.hpp>
48#include <com/sun/star/chart2/XChartDocument.hpp>
49#include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
50
51#include <com/sun/star/drawing/LineStyle.hpp>
52
53using namespace ::xmloff::token;
54using namespace com::sun::star;
55
57
59{
64};
65
67{
68 { XML_AUTO, css::chart::ChartAxisType::AUTOMATIC },
69 { XML_TEXT, css::chart::ChartAxisType::CATEGORY },
70 { XML_DATE, css::chart::ChartAxisType::DATE },
72};
73
74namespace {
75
76class SchXMLCategoriesContext : public SvXMLImportContext
77{
78private:
79 OUString& mrAddress;
80
81public:
82 SchXMLCategoriesContext( SvXMLImport& rImport,
83 OUString& rAddress );
84 virtual void SAL_CALL startFastElement( sal_Int32 nElement,
85 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
86};
87
88class DateScaleContext : public SvXMLImportContext
89{
90public:
91 DateScaleContext( SvXMLImport& rImport,
92 const Reference< beans::XPropertySet >& rAxisProps );
93
94 virtual void SAL_CALL startFastElement( sal_Int32 nElement,
95 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
96
97private:
99};
100
101}
102
104 SvXMLImport& rImport,
105 Reference< chart::XDiagram > const & xDiagram,
106 std::vector< SchXMLAxis >& rAxes,
107 OUString & rCategoriesAddress,
108 bool bAddMissingXAxisForNetCharts,
109 bool bAdaptWrongPercentScaleValues,
110 bool bAdaptXAxisOrientationForOld2DBarCharts,
111 bool& rbAxisPositionAttributeImported ) :
112 SvXMLImportContext( rImport ),
113 m_rImportHelper( rImpHelper ),
114 m_xDiagram( xDiagram ),
115 m_rAxes( rAxes ),
116 m_rCategoriesAddress( rCategoriesAddress ),
117 m_nAxisType(chart::ChartAxisType::AUTOMATIC),
118 m_bAxisTypeImported(false),
119 m_bDateScaleImported(false),
120 m_bAddMissingXAxisForNetCharts( bAddMissingXAxisForNetCharts ),
121 m_bAdaptWrongPercentScaleValues( bAdaptWrongPercentScaleValues ),
122 m_bAdaptXAxisOrientationForOld2DBarCharts( bAdaptXAxisOrientationForOld2DBarCharts ),
123 m_rbAxisPositionAttributeImported( rbAxisPositionAttributeImported )
124{
125}
126
128{}
129
131{
133 Reference< chart::XAxisSupplier > xAxisSuppl( rDiagram, uno::UNO_QUERY );
134 if( !xAxisSuppl.is() )
135 return xAxis;
136 if( rCurrentAxis.nAxisIndex == 0 )
137 xAxis = xAxisSuppl->getAxis(rCurrentAxis.eDimension);
138 else
139 xAxis = xAxisSuppl->getSecondaryAxis(rCurrentAxis.eDimension);
140 return xAxis;
141}
142
143/* returns a shape for the current axis's title. The property
144 "Has...AxisTitle" is set to "True" to get the shape
145 */
147{
149 Reference< beans::XPropertySet > xDiaProp( m_rImportHelper.GetChartDocument()->getDiagram(), uno::UNO_QUERY );
151 if( !xDiaProp.is() || !xAxis.is() )
152 return xResult;
153
154 OUString aPropName;
155 switch( m_aCurrentAxis.eDimension )
156 {
157 case SCH_XML_AXIS_X:
158 if( m_aCurrentAxis.nAxisIndex == 0 )
159 aPropName = "HasXAxisTitle";
160 else
161 aPropName = "HasSecondaryXAxisTitle";
162 break;
163 case SCH_XML_AXIS_Y:
164 if( m_aCurrentAxis.nAxisIndex == 0 )
165 aPropName = "HasYAxisTitle";
166 else
167 aPropName = "HasSecondaryYAxisTitle";
168 break;
169 case SCH_XML_AXIS_Z:
170 aPropName = "HasZAxisTitle";
171 break;
173 SAL_INFO("xmloff.chart", "Invalid axis" );
174 break;
175 }
176 xDiaProp->setPropertyValue( aPropName, uno::Any(true) );
177 xResult.set( xAxis->getAxisTitle(), uno::UNO_QUERY );
178 return xResult;
179}
180
181void SchXMLAxisContext::CreateGrid( const OUString& sAutoStyleName, bool bIsMajor )
182{
183 Reference< beans::XPropertySet > xDiaProp( m_rImportHelper.GetChartDocument()->getDiagram(), uno::UNO_QUERY );
185 if( !xDiaProp.is() || !xAxis.is() )
186 return;
187
188 OUString aPropName;
189 switch( m_aCurrentAxis.eDimension )
190 {
191 case SCH_XML_AXIS_X:
192 if( bIsMajor )
193 aPropName = "HasXAxisGrid";
194 else
195 aPropName = "HasXAxisHelpGrid";
196 break;
197 case SCH_XML_AXIS_Y:
198 if( bIsMajor )
199 aPropName = "HasYAxisGrid";
200 else
201 aPropName = "HasYAxisHelpGrid";
202 break;
203 case SCH_XML_AXIS_Z:
204 if( bIsMajor )
205 aPropName = "HasZAxisGrid";
206 else
207 aPropName = "HasZAxisHelpGrid";
208 break;
210 SAL_INFO("xmloff.chart", "Invalid axis" );
211 break;
212 }
213 xDiaProp->setPropertyValue( aPropName, uno::Any(true) );
214
216 if( bIsMajor )
217 xGridProp = xAxis->getMajorGrid();
218 else
219 xGridProp = xAxis->getMinorGrid();
220
221 // set properties
222 if( xGridProp.is())
223 {
224 // the line color is black as default, in the model it is a light gray
225 xGridProp->setPropertyValue("LineColor",
227 if (!sAutoStyleName.isEmpty())
228 m_rImportHelper.FillAutoStyle(sAutoStyleName, xGridProp);
229 }
230}
231
232void SchXMLAxisContext::startFastElement( sal_Int32 /*nElement*/,
233 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
234{
235 // parse attributes
236 for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
237 {
238 switch(aIter.getToken())
239 {
241 {
242 SchXMLAxisDimension nEnumVal;
243 if( SvXMLUnitConverter::convertEnum( nEnumVal, aIter.toView(), aXMLAxisDimensionMap ))
244 m_aCurrentAxis.eDimension = nEnumVal;
245 }
246 break;
248 m_aCurrentAxis.aName = aIter.toString();
249 break;
251 case XML_ELEMENT(CHART_EXT, XML_AXIS_TYPE):
252 sal_uInt16 nEnumVal;
253 if( SvXMLUnitConverter::convertEnum( nEnumVal, aIter.toView(), aXMLAxisTypeMap ))
254 {
255 m_nAxisType = nEnumVal;
256 m_bAxisTypeImported = true;
257 }
258 break;
260 m_aAutoStyleName = aIter.toString();
261 break;
262 default:
263 XMLOFF_WARN_UNKNOWN("xmloff", aIter);
264 }
265 }
266
267 // check for number of axes with same dimension
269 sal_Int32 nNumOfAxes = m_rAxes.size();
270 for( sal_Int32 nCurrent = 0; nCurrent < nNumOfAxes; nCurrent++ )
271 {
272 if( m_rAxes[ nCurrent ].eDimension == m_aCurrentAxis.eDimension )
274 }
275 CreateAxis();
276}
277namespace
278{
279
280Reference< chart2::XAxis > lcl_getAxis( const Reference< frame::XModel >& xChartModel,
281 sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex )
282{
284
285 try
286 {
287 Reference< chart2::XChartDocument > xChart2Document( xChartModel, uno::UNO_QUERY );
288 if( xChart2Document.is() )
289 {
290 Reference< chart2::XDiagram > xDiagram( xChart2Document->getFirstDiagram());
291 Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xDiagram, uno::UNO_QUERY_THROW );
292 uno::Sequence< Reference< chart2::XCoordinateSystem > >
293 aCooSysSeq( xCooSysCnt->getCoordinateSystems());
294 sal_Int32 nCooSysIndex = 0;
295 if( nCooSysIndex < aCooSysSeq.getLength() )
296 {
297 Reference< chart2::XCoordinateSystem > xCooSys( aCooSysSeq[nCooSysIndex] );
298 if( xCooSys.is() && nDimensionIndex < xCooSys->getDimension() )
299 {
300 const sal_Int32 nMaxAxisIndex = xCooSys->getMaximumAxisIndexByDimension(nDimensionIndex);
301 if( nAxisIndex <= nMaxAxisIndex )
302 xAxis = xCooSys->getAxisByDimension( nDimensionIndex, nAxisIndex );
303 }
304 }
305 }
306 }
307 catch( uno::Exception & )
308 {
309 SAL_INFO("xmloff.chart", "Couldn't get axis" );
310 }
311
312 return xAxis;
313}
314
315bool lcl_divideBy100( uno::Any& rDoubleAny )
316{
317 bool bChanged = false;
318 double fValue=0.0;
319 if( (rDoubleAny>>=fValue) && (fValue!=0.0) )
320 {
321 fValue/=100.0;
322 rDoubleAny <<= fValue;
323 bChanged = true;
324 }
325 return bChanged;
326}
327
328bool lcl_AdaptWrongPercentScaleValues(chart2::ScaleData& rScaleData)
329{
330 bool bChanged = lcl_divideBy100( rScaleData.Minimum );
331 bChanged = lcl_divideBy100( rScaleData.Maximum ) || bChanged;
332 bChanged = lcl_divideBy100( rScaleData.Origin ) || bChanged;
333 bChanged = lcl_divideBy100( rScaleData.IncrementData.Distance ) || bChanged;
334 return bChanged;
335}
336
337}//end anonymous namespace
338
340{
341 m_rAxes.push_back( m_aCurrentAxis );
342
343 Reference< beans::XPropertySet > xDiaProp( m_rImportHelper.GetChartDocument()->getDiagram(), uno::UNO_QUERY );
344 if( !xDiaProp.is() )
345 return;
346 OUString aPropName;
347 switch( m_aCurrentAxis.eDimension )
348 {
349 case SCH_XML_AXIS_X:
350 if( m_aCurrentAxis.nAxisIndex == 0 )
351 aPropName = "HasXAxis";
352 else
353 aPropName = "HasSecondaryXAxis";
354 break;
355 case SCH_XML_AXIS_Y:
356 if( m_aCurrentAxis.nAxisIndex == 0 )
357 aPropName = "HasYAxis";
358 else
359 aPropName = "HasSecondaryYAxis";
360 break;
361 case SCH_XML_AXIS_Z:
362 if( m_aCurrentAxis.nAxisIndex == 0 )
363 aPropName = "HasZAxis";
364 break;
366 SAL_INFO("xmloff.chart", "Invalid axis" );
367 break;
368 }
369 try
370 {
371 xDiaProp->setPropertyValue( aPropName, uno::Any(true) );
372 }
373 catch( beans::UnknownPropertyException & )
374 {
375 SAL_INFO("xmloff.chart", "Couldn't turn on axis" );
376 }
378 {
379 bool bSettingZAxisSucceeded = false;
380 try
381 {
382 xDiaProp->getPropertyValue( aPropName ) >>= bSettingZAxisSucceeded;
383 }
384 catch( beans::UnknownPropertyException & )
385 {
386 SAL_INFO("xmloff.chart", "Couldn't turn on z axis" );
387 }
388 if( !bSettingZAxisSucceeded )
389 return;
390 }
391
392 m_xAxisProps.set( lcl_getChartAxis( m_aCurrentAxis, m_xDiagram ), uno::UNO_QUERY );
393
395 {
396 try
397 {
398 xDiaProp->setPropertyValue("HasXAxis", uno::Any(true) );
399 }
400 catch( beans::UnknownPropertyException & )
401 {
402 SAL_INFO("xmloff.chart", "Couldn't turn on x axis" );
403 }
404 }
405
406 // set properties
407 if( !m_xAxisProps.is())
408 return;
409
410 uno::Any aTrueBool( uno::Any( true ));
411 uno::Any aFalseBool( uno::Any( false ));
412
413 // #i109879# the line color is black as default, in the model it is a light gray
414 m_xAxisProps->setPropertyValue("LineColor",
416
417 m_xAxisProps->setPropertyValue("DisplayLabels", aFalseBool );
418
419 // Compatibility option: starting from LibreOffice 5.1 the rotated
420 // layout is preferred to staggering for axis labels.
421 // So the import default value for having compatibility with ODF
422 // documents created with earlier LibreOffice versions is `true`.
423 if( GetImport().getGeneratorVersion() != SvXMLImport::ProductVersionUnknown )
424 m_xAxisProps->setPropertyValue("TryStaggeringFirst", aTrueBool );
425
426 // #88077# AutoOrigin 'on' is default
427 m_xAxisProps->setPropertyValue("AutoOrigin", aTrueBool );
428
430 m_xAxisProps->setPropertyValue("AxisType", uno::Any(m_nAxisType) );
431
432 if( !m_aAutoStyleName.isEmpty())
433 {
435 if (pStylesCtxt)
436 {
438
439 if (XMLPropStyleContext * pPropStyleContext = dynamic_cast<XMLPropStyleContext*>(pStyle))
440 {
441 pPropStyleContext->FillPropertySet(m_xAxisProps);
442
444 {
445 //set scale data of added x axis back to default
446 Reference< chart2::XAxis > xAxis( lcl_getAxis( GetImport().GetModel(),
448 if( xAxis.is() )
449 {
450 chart2::ScaleData aScaleData( xAxis->getScaleData());
451 if( lcl_AdaptWrongPercentScaleValues(aScaleData) )
452 xAxis->setScaleData( aScaleData );
453 }
454 }
455
457 {
458 //copy style from y axis to added x axis:
459
460 Reference< chart::XAxisSupplier > xAxisSuppl( xDiaProp, uno::UNO_QUERY );
461 if( xAxisSuppl.is() )
462 {
463 Reference< beans::XPropertySet > xXAxisProp( xAxisSuppl->getAxis(0), uno::UNO_QUERY );
464 pPropStyleContext->FillPropertySet(xXAxisProp);
465 }
466
467 //set scale data of added x axis back to default
468 Reference< chart2::XAxis > xAxis( lcl_getAxis( GetImport().GetModel(),
469 0 /*nDimensionIndex*/, 0 /*nAxisIndex*/ ) );
470 if( xAxis.is() )
471 {
472 chart2::ScaleData aScaleData;
473 aScaleData.AxisType = chart2::AxisType::CATEGORY;
474 aScaleData.Orientation = chart2::AxisOrientation_MATHEMATICAL;
475 xAxis->setScaleData( aScaleData );
476 }
477
478 //set line style of added x axis to invisible
479 Reference< beans::XPropertySet > xNewAxisProp( xAxis, uno::UNO_QUERY );
480 if( xNewAxisProp.is() )
481 {
482 xNewAxisProp->setPropertyValue("LineStyle"
483 , uno::Any(drawing::LineStyle_NONE));
484 }
485 }
486
488 {
489 bool bIs3DChart = false;
490 if( xDiaProp.is() && ( xDiaProp->getPropertyValue("Dim3D") >>= bIs3DChart )
491 && !bIs3DChart )
492 {
493 Reference< chart2::XChartDocument > xChart2Document( GetImport().GetModel(), uno::UNO_QUERY );
494 if( xChart2Document.is() )
495 {
496 Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xChart2Document->getFirstDiagram(), uno::UNO_QUERY );
497 if( xCooSysCnt.is() )
498 {
499 uno::Sequence< Reference< chart2::XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems() );
500 if( aCooSysSeq.hasElements() )
501 {
502 bool bSwapXandYAxis = false;
503 Reference< chart2::XCoordinateSystem > xCooSys( aCooSysSeq[0] );
504 Reference< beans::XPropertySet > xCooSysProp( xCooSys, uno::UNO_QUERY );
505 if( xCooSysProp.is() && ( xCooSysProp->getPropertyValue("SwapXAndYAxis") >>= bSwapXandYAxis )
506 && bSwapXandYAxis )
507 {
508 Reference< chart2::XAxis > xAxis = xCooSys->getAxisByDimension( 0, m_aCurrentAxis.nAxisIndex );
509 if( xAxis.is() )
510 {
511 chart2::ScaleData aScaleData = xAxis->getScaleData();
512 aScaleData.Orientation = chart2::AxisOrientation_REVERSE;
513 xAxis->setScaleData( aScaleData );
514 }
515 }
516 }
517 }
518 }
519 }
520 }
521
523 u"CrossoverPosition", pPropStyleContext, pStylesCtxt ).hasValue();
524 }
525 }
526 }
527
529 return;
530
532 if (!xAxis.is())
533 return;
534
535 chart2::ScaleData aScaleData(xAxis->getScaleData());
536 bool bIs3DChart = false;
537 double fMajorOrigin = -1;
538 OUString sChartType = m_xDiagram->getDiagramType();
539 if ((xDiaProp->getPropertyValue("Dim3D") >>= bIs3DChart) && bIs3DChart
540 && (sChartType == "com.sun.star.chart.BarDiagram" || sChartType == "com.sun.star.chart.StockDiagram"))
541 {
542 aScaleData.ShiftedCategoryPosition = true;
543 xAxis->setScaleData(aScaleData);
544 }
545 else if ((m_xAxisProps->getPropertyValue("MajorOrigin") >>= fMajorOrigin)
546 && (rtl::math::approxEqual(fMajorOrigin, 0.0) || rtl::math::approxEqual(fMajorOrigin, 0.5)))
547 {
548 aScaleData.ShiftedCategoryPosition = rtl::math::approxEqual(fMajorOrigin, 0.5);
549 xAxis->setScaleData(aScaleData);
550 m_xAxisProps->setPropertyValue("MajorOrigin", uno::Any());
551 }
552}
553
555{
556 if( m_aCurrentAxis.aTitle.isEmpty() )
557 return;
558
560 if( !xAxis.is() )
561 return;
562
563 Reference< beans::XPropertySet > xTitleProp( xAxis->getAxisTitle() );
564 if( xTitleProp.is() )
565 {
566 try
567 {
568 xTitleProp->setPropertyValue("String", uno::Any(m_aCurrentAxis.aTitle) );
569 }
570 catch( beans::UnknownPropertyException & )
571 {
572 SAL_INFO("xmloff.chart", "Property String for Title not available" );
573 }
574 }
575}
576
577css::uno::Reference< css::xml::sax::XFastContextHandler > SchXMLAxisContext::createFastChildContext(
578 sal_Int32 nElement,
579 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
580{
581 switch( nElement )
582 {
584 {
588 xTitleShape );
589 }
590 break;
591
594 return new SchXMLCategoriesContext( GetImport(),
596 break;
597
599 case XML_ELEMENT(CHART_EXT, XML_DATE_SCALE):
601 return new DateScaleContext( GetImport(), m_xAxisProps );
602
604 {
605 bool bIsMajor = true; // default value for class is "major"
606 OUString sAutoStyleName;
607
608 for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
609 {
610 switch (aIter.getToken())
611 {
613 if( IsXMLToken( aIter, XML_MINOR ) )
614 bIsMajor = false;
615 break;
617 sAutoStyleName = aIter.toString();
618 break;
619 default:
620 XMLOFF_WARN_UNKNOWN("xmloff", aIter);
621 }
622 }
623
624 CreateGrid( sAutoStyleName, bIsMajor );
625
626 // don't create a context => use default context. grid elements are empty
627 }
628 break;
629
630 default:
631 XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
632 break;
633 }
634
635 return nullptr;
636}
637
639{
640 if( !m_bDateScaleImported && m_nAxisType==chart::ChartAxisType::AUTOMATIC )
641 {
643 if( xAxis.is() )
644 {
645 chart2::ScaleData aScaleData( xAxis->getScaleData());
646 aScaleData.AutoDateAxis = false;//different default for older documents
647 xAxis->setScaleData( aScaleData );
648 }
649 }
650
651 SetAxisTitle();
652}
653
654namespace
655{
656
657Reference< chart2::XAxis > lcl_getAxis( const Reference< chart2::XCoordinateSystem >& rCooSys, sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex )
658{
660 try
661 {
662 xAxis = rCooSys->getAxisByDimension( nDimensionIndex, nAxisIndex );
663 }
664 catch( uno::Exception & )
665 {
666 }
667 return xAxis;
668}
669
670} // anonymous namespace
671
673 std::u16string_view rChartTypeServiceName,
674 std::u16string_view rODFVersionOfFile,
675 bool bAxisPositionAttributeImported )
676{
677 if( !(rODFVersionOfFile.empty() || rODFVersionOfFile == u"1.0" || rODFVersionOfFile == u"1.1"
678 || ( rODFVersionOfFile == u"1.2" && !bAxisPositionAttributeImported )) )
679 return;
680
681 try
682 {
683 Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xNewDoc->getFirstDiagram(), uno::UNO_QUERY_THROW );
684 uno::Sequence< Reference< chart2::XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems());
685 if( aCooSysSeq.hasElements() )
686 {
687 Reference< chart2::XCoordinateSystem > xCooSys( aCooSysSeq[0] );
688 if( xCooSys.is() )
689 {
690 Reference< chart2::XAxis > xMainXAxis = lcl_getAxis( xCooSys, 0, 0 );
691 Reference< chart2::XAxis > xMainYAxis = lcl_getAxis( xCooSys, 1, 0 );
692 //Reference< chart2::XAxis > xMajorZAxis = lcl_getAxis( xCooSys, 2, 0 );
693 Reference< chart2::XAxis > xSecondaryXAxis = lcl_getAxis( xCooSys, 0, 1 );
694 Reference< chart2::XAxis > xSecondaryYAxis = lcl_getAxis( xCooSys, 1, 1 );
695
696 Reference< beans::XPropertySet > xMainXAxisProp( xMainXAxis, uno::UNO_QUERY );
697 Reference< beans::XPropertySet > xMainYAxisProp( xMainYAxis, uno::UNO_QUERY );
698 Reference< beans::XPropertySet > xSecondaryXAxisProp( xSecondaryXAxis, uno::UNO_QUERY );
699 Reference< beans::XPropertySet > xSecondaryYAxisProp( xSecondaryYAxis, uno::UNO_QUERY );
700
701 if( xMainXAxisProp.is() && xMainYAxisProp.is() )
702 {
703 chart2::ScaleData aMainXScale = xMainXAxis->getScaleData();
704 if( rChartTypeServiceName == u"com.sun.star.chart2.ScatterChartType" )
705 {
706 xMainYAxisProp->setPropertyValue("CrossoverPosition"
707 , uno::Any( css::chart::ChartAxisPosition_VALUE) );
708 double fCrossoverValue = 0.0;
709 aMainXScale.Origin >>= fCrossoverValue;
710 xMainYAxisProp->setPropertyValue("CrossoverValue"
711 , uno::Any( fCrossoverValue ) );
712
713 if( aMainXScale.Orientation == chart2::AxisOrientation_REVERSE )
714 {
715 xMainYAxisProp->setPropertyValue("LabelPosition"
716 , uno::Any( css::chart::ChartAxisLabelPosition_OUTSIDE_END) );
717 xMainYAxisProp->setPropertyValue("MarkPosition"
718 , uno::Any( css::chart::ChartAxisMarkPosition_AT_LABELS) );
719 if( xSecondaryYAxisProp.is() )
720 xSecondaryYAxisProp->setPropertyValue("CrossoverPosition"
721 , uno::Any( css::chart::ChartAxisPosition_START) );
722 }
723 else
724 {
725 xMainYAxisProp->setPropertyValue("LabelPosition"
726 , uno::Any( css::chart::ChartAxisLabelPosition_OUTSIDE_START) );
727 xMainYAxisProp->setPropertyValue("MarkPosition"
728 , uno::Any( css::chart::ChartAxisMarkPosition_AT_LABELS) );
729 if( xSecondaryYAxisProp.is() )
730 xSecondaryYAxisProp->setPropertyValue("CrossoverPosition"
731 , uno::Any( css::chart::ChartAxisPosition_END) );
732 }
733 }
734 else
735 {
736 if( aMainXScale.Orientation == chart2::AxisOrientation_REVERSE )
737 {
738 xMainYAxisProp->setPropertyValue("CrossoverPosition"
739 , uno::Any( css::chart::ChartAxisPosition_END) );
740 if( xSecondaryYAxisProp.is() )
741 xSecondaryYAxisProp->setPropertyValue("CrossoverPosition"
742 , uno::Any( css::chart::ChartAxisPosition_START) );
743 }
744 else
745 {
746 xMainYAxisProp->setPropertyValue("CrossoverPosition"
747 , uno::Any( css::chart::ChartAxisPosition_START) );
748 if( xSecondaryYAxisProp.is() )
749 xSecondaryYAxisProp->setPropertyValue("CrossoverPosition"
750 , uno::Any( css::chart::ChartAxisPosition_END) );
751 }
752 }
753
754 chart2::ScaleData aMainYScale = xMainYAxis->getScaleData();
755 xMainXAxisProp->setPropertyValue("CrossoverPosition"
756 , uno::Any( css::chart::ChartAxisPosition_VALUE) );
757 double fCrossoverValue = 0.0;
758 aMainYScale.Origin >>= fCrossoverValue;
759 xMainXAxisProp->setPropertyValue("CrossoverValue"
760 , uno::Any( fCrossoverValue ) );
761
762 if( aMainYScale.Orientation == chart2::AxisOrientation_REVERSE )
763 {
764 xMainXAxisProp->setPropertyValue("LabelPosition"
765 , uno::Any( css::chart::ChartAxisLabelPosition_OUTSIDE_END) );
766 xMainXAxisProp->setPropertyValue("MarkPosition"
767 , uno::Any( css::chart::ChartAxisMarkPosition_AT_LABELS) );
768 if( xSecondaryXAxisProp.is() )
769 xSecondaryXAxisProp->setPropertyValue("CrossoverPosition"
770 , uno::Any( css::chart::ChartAxisPosition_START) );
771 }
772 else
773 {
774 xMainXAxisProp->setPropertyValue("LabelPosition"
775 , uno::Any( css::chart::ChartAxisLabelPosition_OUTSIDE_START) );
776 xMainXAxisProp->setPropertyValue("MarkPosition"
777 , uno::Any( css::chart::ChartAxisMarkPosition_AT_LABELS) );
778 if( xSecondaryXAxisProp.is() )
779 xSecondaryXAxisProp->setPropertyValue("CrossoverPosition"
780 , uno::Any( css::chart::ChartAxisPosition_END) );
781 }
782 }
783 }
784 }
785 }
786 catch( uno::Exception & )
787 {
788 }
789}
790
791SchXMLCategoriesContext::SchXMLCategoriesContext(
792 SvXMLImport& rImport,
793 OUString& rAddress ) :
794 SvXMLImportContext( rImport ),
795 mrAddress( rAddress )
796{
797}
798
799void SchXMLCategoriesContext::startFastElement( sal_Int32 /*nElement*/,
800 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
801{
802 for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
803 {
804 if( aIter.getToken() == XML_ELEMENT(TABLE, XML_CELL_RANGE_ADDRESS) )
805 mrAddress = aIter.toString();
806 else
807 XMLOFF_WARN_UNKNOWN("xmloff", aIter);
808 }
809}
810
811DateScaleContext::DateScaleContext(
812 SvXMLImport& rImport,
813 const Reference< beans::XPropertySet >& rAxisProps ) :
814 SvXMLImportContext( rImport ),
815 m_xAxisProps( rAxisProps )
816{
817}
818
819namespace
820{
821sal_Int32 lcl_getTimeUnit( const sax_fastparser::FastAttributeList::FastAttributeIter& rValue )
822{
823 sal_Int32 nTimeUnit = css::chart::TimeUnit::DAY;
824 if( IsXMLToken( rValue, XML_DAYS ) )
825 nTimeUnit = css::chart::TimeUnit::DAY;
826 else if( IsXMLToken( rValue, XML_MONTHS ) )
827 nTimeUnit = css::chart::TimeUnit::MONTH;
828 else if( IsXMLToken( rValue, XML_YEARS ) )
829 nTimeUnit = css::chart::TimeUnit::YEAR;
830 return nTimeUnit;
831}
832
833}
834
835void DateScaleContext::startFastElement( sal_Int32 /*nElement*/,
836 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
837{
838 if( !m_xAxisProps.is() )
839 return;
840
841 // parse attributes
842 bool bSetNewIncrement=false;
843 chart::TimeIncrement aIncrement;
844 m_xAxisProps->getPropertyValue("TimeIncrement") >>= aIncrement;
845
846 for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
847 {
848 switch( aIter.getToken() )
849 {
850 case XML_ELEMENT(CHART, XML_BASE_TIME_UNIT):
851 {
852 aIncrement.TimeResolution <<= lcl_getTimeUnit(aIter);
853 bSetNewIncrement = true;
854 }
855 break;
857 {
858 chart::TimeInterval aInterval(1,0);
859 aIncrement.MajorTimeInterval >>= aInterval;
860 ::sax::Converter::convertNumber( aInterval.Number, aIter.toView() );
861 aIncrement.MajorTimeInterval <<= aInterval;
862 bSetNewIncrement = true;
863 }
864 break;
866 {
867 chart::TimeInterval aInterval(1,0);
868 aIncrement.MajorTimeInterval >>= aInterval;
869 aInterval.TimeUnit = lcl_getTimeUnit(aIter);
870 aIncrement.MajorTimeInterval <<= aInterval;
871 bSetNewIncrement = true;
872 }
873 break;
875 {
876 chart::TimeInterval aInterval(1,0);
877 aIncrement.MinorTimeInterval >>= aInterval;
878 ::sax::Converter::convertNumber( aInterval.Number, aIter.toView() );
879 aIncrement.MinorTimeInterval <<= aInterval;
880 bSetNewIncrement = true;
881 }
882 break;
884 {
885 chart::TimeInterval aInterval(1,0);
886 aIncrement.MinorTimeInterval >>= aInterval;
887 aInterval.TimeUnit = lcl_getTimeUnit(aIter);
888 aIncrement.MinorTimeInterval <<= aInterval;
889 bSetNewIncrement = true;
890 }
891 break;
892 default:
893 XMLOFF_WARN_UNKNOWN("xmloff", aIter);
894 }
895 }
896
897 if( bSetNewIncrement )
898 m_xAxisProps->setPropertyValue("TimeIncrement", uno::Any( aIncrement ) );
899}
900
901/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const SvXMLEnumMapEntry< SchXMLAxisDimension > aXMLAxisDimensionMap[]
static Reference< chart::XAxis > lcl_getChartAxis(const SchXMLAxis &rCurrentAxis, const Reference< chart::XDiagram > &rDiagram)
const SvXMLEnumMapEntry< sal_uInt16 > aXMLAxisTypeMap[]
static void CorrectAxisPositions(const css::uno::Reference< css::chart2::XChartDocument > &xNewDoc, std::u16string_view rChartTypeServiceName, std::u16string_view rODFVersionOfFile, bool bAxisPositionAttributeImported)
SchXMLAxisContext(SchXMLImportHelper &rImpHelper, SvXMLImport &rImport, css::uno::Reference< css::chart::XDiagram > const &xDiagram, std::vector< SchXMLAxis > &aAxes, OUString &rCategoriesAddress, bool bAddMissingXAxisForNetCharts, bool bAdaptWrongPercentScaleValues, bool bAdaptXAxisOrientationForOld2DBarCharts, bool &rbAxisPositionAttributeImported)
virtual void SAL_CALL startFastElement(sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList) override
css::uno::Reference< css::chart::XDiagram > m_xDiagram
SchXMLImportHelper & m_rImportHelper
virtual void SAL_CALL endFastElement(sal_Int32 nElement) override
endFastElement is called before a context will be destructed, but after an elements context has been ...
virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList > &AttrList) override
void CreateGrid(const OUString &sAutoStyleName, bool bIsMajor)
std::vector< SchXMLAxis > & m_rAxes
bool & m_rbAxisPositionAttributeImported
virtual ~SchXMLAxisContext() override
bool m_bAdaptXAxisOrientationForOld2DBarCharts
css::uno::Reference< css::drawing::XShape > getTitleShape() const
css::uno::Reference< css::beans::XPropertySet > m_xAxisProps
OUString & m_rCategoriesAddress
With this class you can import a <chart:chart> element containing its data as <table:table> element o...
const css::uno::Reference< css::chart::XChartDocument > & GetChartDocument() const
SvXMLStylesContext * GetAutoStylesContext() const
void FillAutoStyle(const OUString &rAutoStyleName, const css::uno::Reference< css::beans::XPropertySet > &rProp)
Fill in the autostyle.
static XmlStyleFamily GetChartFamilyID()
This class deliberately does not support XWeak, to improve performance when loading large documents.
Definition: xmlictxt.hxx:48
virtual void SAL_CALL startFastElement(sal_Int32 Element, const css::uno::Reference< css::xml::sax::XFastAttributeList > &Attribs) override
Definition: xmlictxt.cxx:45
SvXMLImport & GetImport()
Definition: xmlictxt.hxx:60
const SvXMLStyleContext * FindStyleChildContext(XmlStyleFamily nFamily, const OUString &rName, bool bCreateIndex=false) const
Definition: xmlstyle.cxx:783
static bool convertEnum(EnumT &rEnum, std::u16string_view rValue, const SvXMLEnumMapEntry< EnumT > *pMap)
convert string to enum using given enum map, if the enum is not found in the map, this method will re...
Definition: xmluconv.hxx:145
static bool convertNumber(sal_Int32 &rValue, std::u16string_view aString, sal_Int32 nMin=SAL_MIN_INT32, sal_Int32 nMax=SAL_MAX_INT32)
constexpr ::Color COL_BLACK(0x00, 0x00, 0x00)
float u
AUTOMATIC
#define SAL_INFO(area, stream)
uno::Any getPropertyFromContext(std::u16string_view rPropertyName, const XMLPropStyleContext *pPropStyleContext, const SvXMLStylesContext *pStylesCtxt)
OUString aPropName
FastAttributeList & castToFastAttributeList(const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList)
Handling of tokens in XML:
@ XML_MINOR_INTERVAL_VALUE
Definition: xmltoken.hxx:3379
@ XML_MAJOR_INTERVAL_UNIT
Definition: xmltoken.hxx:3380
@ XML_CELL_RANGE_ADDRESS
Definition: xmltoken.hxx:412
@ XML_MAJOR_INTERVAL_VALUE
Definition: xmltoken.hxx:3378
@ XML_MINOR_INTERVAL_UNIT
Definition: xmltoken.hxx:3381
bool IsXMLToken(std::u16string_view rString, enum XMLTokenEnum eToken)
compare eToken to the string
Definition: xmltoken.cxx:3597
OUString aName
sal_Int8 nAxisIndex
OUString aTitle
enum SchXMLAxisDimension eDimension
bool hasValue()
SchXMLAxisDimension
@ SCH_XML_AXIS_Z
@ SCH_XML_AXIS_X
@ SCH_XML_AXIS_Y
@ SCH_XML_AXIS_UNDEF
#define XMLOFF_WARN_UNKNOWN_ELEMENT(area, token)
Definition: xmlictxt.hxx:120
#define XMLOFF_WARN_UNKNOWN(area, rIter)
Definition: xmlictxt.hxx:114
#define XML_ELEMENT(prefix, name)
Definition: xmlimp.hxx:97