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 }
551}
552
554{
555 if( m_aCurrentAxis.aTitle.isEmpty() )
556 return;
557
559 if( !xAxis.is() )
560 return;
561
562 Reference< beans::XPropertySet > xTitleProp( xAxis->getAxisTitle() );
563 if( xTitleProp.is() )
564 {
565 try
566 {
567 xTitleProp->setPropertyValue("String", uno::Any(m_aCurrentAxis.aTitle) );
568 }
569 catch( beans::UnknownPropertyException & )
570 {
571 SAL_INFO("xmloff.chart", "Property String for Title not available" );
572 }
573 }
574}
575
576css::uno::Reference< css::xml::sax::XFastContextHandler > SchXMLAxisContext::createFastChildContext(
577 sal_Int32 nElement,
578 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
579{
580 switch( nElement )
581 {
583 {
587 xTitleShape );
588 }
589 break;
590
593 return new SchXMLCategoriesContext( GetImport(),
595 break;
596
598 case XML_ELEMENT(CHART_EXT, XML_DATE_SCALE):
600 return new DateScaleContext( GetImport(), m_xAxisProps );
601
603 {
604 bool bIsMajor = true; // default value for class is "major"
605 OUString sAutoStyleName;
606
607 for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
608 {
609 switch (aIter.getToken())
610 {
612 if( IsXMLToken( aIter, XML_MINOR ) )
613 bIsMajor = false;
614 break;
616 sAutoStyleName = aIter.toString();
617 break;
618 default:
619 XMLOFF_WARN_UNKNOWN("xmloff", aIter);
620 }
621 }
622
623 CreateGrid( sAutoStyleName, bIsMajor );
624
625 // don't create a context => use default context. grid elements are empty
626 }
627 break;
628
629 default:
630 XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
631 break;
632 }
633
634 return nullptr;
635}
636
638{
639 if( !m_bDateScaleImported && m_nAxisType==chart::ChartAxisType::AUTOMATIC )
640 {
642 if( xAxis.is() )
643 {
644 chart2::ScaleData aScaleData( xAxis->getScaleData());
645 aScaleData.AutoDateAxis = false;//different default for older documents
646 xAxis->setScaleData( aScaleData );
647 }
648 }
649
650 SetAxisTitle();
651}
652
653namespace
654{
655
656Reference< chart2::XAxis > lcl_getAxis( const Reference< chart2::XCoordinateSystem >& rCooSys, sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex )
657{
659 try
660 {
661 xAxis = rCooSys->getAxisByDimension( nDimensionIndex, nAxisIndex );
662 }
663 catch( uno::Exception & )
664 {
665 }
666 return xAxis;
667}
668
669} // anonymous namespace
670
672 std::u16string_view rChartTypeServiceName,
673 std::u16string_view rODFVersionOfFile,
674 bool bAxisPositionAttributeImported )
675{
676 if( !(rODFVersionOfFile.empty() || rODFVersionOfFile == u"1.0" || rODFVersionOfFile == u"1.1"
677 || ( rODFVersionOfFile == u"1.2" && !bAxisPositionAttributeImported )) )
678 return;
679
680 try
681 {
682 Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xNewDoc->getFirstDiagram(), uno::UNO_QUERY_THROW );
683 uno::Sequence< Reference< chart2::XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems());
684 if( aCooSysSeq.hasElements() )
685 {
686 Reference< chart2::XCoordinateSystem > xCooSys( aCooSysSeq[0] );
687 if( xCooSys.is() )
688 {
689 Reference< chart2::XAxis > xMainXAxis = lcl_getAxis( xCooSys, 0, 0 );
690 Reference< chart2::XAxis > xMainYAxis = lcl_getAxis( xCooSys, 1, 0 );
691 //Reference< chart2::XAxis > xMajorZAxis = lcl_getAxis( xCooSys, 2, 0 );
692 Reference< chart2::XAxis > xSecondaryXAxis = lcl_getAxis( xCooSys, 0, 1 );
693 Reference< chart2::XAxis > xSecondaryYAxis = lcl_getAxis( xCooSys, 1, 1 );
694
695 Reference< beans::XPropertySet > xMainXAxisProp( xMainXAxis, uno::UNO_QUERY );
696 Reference< beans::XPropertySet > xMainYAxisProp( xMainYAxis, uno::UNO_QUERY );
697 Reference< beans::XPropertySet > xSecondaryXAxisProp( xSecondaryXAxis, uno::UNO_QUERY );
698 Reference< beans::XPropertySet > xSecondaryYAxisProp( xSecondaryYAxis, uno::UNO_QUERY );
699
700 if( xMainXAxisProp.is() && xMainYAxisProp.is() )
701 {
702 chart2::ScaleData aMainXScale = xMainXAxis->getScaleData();
703 if( rChartTypeServiceName == u"com.sun.star.chart2.ScatterChartType" )
704 {
705 xMainYAxisProp->setPropertyValue("CrossoverPosition"
706 , uno::Any( css::chart::ChartAxisPosition_VALUE) );
707 double fCrossoverValue = 0.0;
708 aMainXScale.Origin >>= fCrossoverValue;
709 xMainYAxisProp->setPropertyValue("CrossoverValue"
710 , uno::Any( fCrossoverValue ) );
711
712 if( aMainXScale.Orientation == chart2::AxisOrientation_REVERSE )
713 {
714 xMainYAxisProp->setPropertyValue("LabelPosition"
715 , uno::Any( css::chart::ChartAxisLabelPosition_OUTSIDE_END) );
716 xMainYAxisProp->setPropertyValue("MarkPosition"
717 , uno::Any( css::chart::ChartAxisMarkPosition_AT_LABELS) );
718 if( xSecondaryYAxisProp.is() )
719 xSecondaryYAxisProp->setPropertyValue("CrossoverPosition"
720 , uno::Any( css::chart::ChartAxisPosition_START) );
721 }
722 else
723 {
724 xMainYAxisProp->setPropertyValue("LabelPosition"
725 , uno::Any( css::chart::ChartAxisLabelPosition_OUTSIDE_START) );
726 xMainYAxisProp->setPropertyValue("MarkPosition"
727 , uno::Any( css::chart::ChartAxisMarkPosition_AT_LABELS) );
728 if( xSecondaryYAxisProp.is() )
729 xSecondaryYAxisProp->setPropertyValue("CrossoverPosition"
730 , uno::Any( css::chart::ChartAxisPosition_END) );
731 }
732 }
733 else
734 {
735 if( aMainXScale.Orientation == chart2::AxisOrientation_REVERSE )
736 {
737 xMainYAxisProp->setPropertyValue("CrossoverPosition"
738 , uno::Any( css::chart::ChartAxisPosition_END) );
739 if( xSecondaryYAxisProp.is() )
740 xSecondaryYAxisProp->setPropertyValue("CrossoverPosition"
741 , uno::Any( css::chart::ChartAxisPosition_START) );
742 }
743 else
744 {
745 xMainYAxisProp->setPropertyValue("CrossoverPosition"
746 , uno::Any( css::chart::ChartAxisPosition_START) );
747 if( xSecondaryYAxisProp.is() )
748 xSecondaryYAxisProp->setPropertyValue("CrossoverPosition"
749 , uno::Any( css::chart::ChartAxisPosition_END) );
750 }
751 }
752
753 chart2::ScaleData aMainYScale = xMainYAxis->getScaleData();
754 xMainXAxisProp->setPropertyValue("CrossoverPosition"
755 , uno::Any( css::chart::ChartAxisPosition_VALUE) );
756 double fCrossoverValue = 0.0;
757 aMainYScale.Origin >>= fCrossoverValue;
758 xMainXAxisProp->setPropertyValue("CrossoverValue"
759 , uno::Any( fCrossoverValue ) );
760
761 if( aMainYScale.Orientation == chart2::AxisOrientation_REVERSE )
762 {
763 xMainXAxisProp->setPropertyValue("LabelPosition"
764 , uno::Any( css::chart::ChartAxisLabelPosition_OUTSIDE_END) );
765 xMainXAxisProp->setPropertyValue("MarkPosition"
766 , uno::Any( css::chart::ChartAxisMarkPosition_AT_LABELS) );
767 if( xSecondaryXAxisProp.is() )
768 xSecondaryXAxisProp->setPropertyValue("CrossoverPosition"
769 , uno::Any( css::chart::ChartAxisPosition_START) );
770 }
771 else
772 {
773 xMainXAxisProp->setPropertyValue("LabelPosition"
774 , uno::Any( css::chart::ChartAxisLabelPosition_OUTSIDE_START) );
775 xMainXAxisProp->setPropertyValue("MarkPosition"
776 , uno::Any( css::chart::ChartAxisMarkPosition_AT_LABELS) );
777 if( xSecondaryXAxisProp.is() )
778 xSecondaryXAxisProp->setPropertyValue("CrossoverPosition"
779 , uno::Any( css::chart::ChartAxisPosition_END) );
780 }
781 }
782 }
783 }
784 }
785 catch( uno::Exception & )
786 {
787 }
788}
789
790SchXMLCategoriesContext::SchXMLCategoriesContext(
791 SvXMLImport& rImport,
792 OUString& rAddress ) :
793 SvXMLImportContext( rImport ),
794 mrAddress( rAddress )
795{
796}
797
798void SchXMLCategoriesContext::startFastElement( sal_Int32 /*nElement*/,
799 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
800{
801 for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
802 {
803 if( aIter.getToken() == XML_ELEMENT(TABLE, XML_CELL_RANGE_ADDRESS) )
804 mrAddress = aIter.toString();
805 else
806 XMLOFF_WARN_UNKNOWN("xmloff", aIter);
807 }
808}
809
810DateScaleContext::DateScaleContext(
811 SvXMLImport& rImport,
812 const Reference< beans::XPropertySet >& rAxisProps ) :
813 SvXMLImportContext( rImport ),
814 m_xAxisProps( rAxisProps )
815{
816}
817
818namespace
819{
820sal_Int32 lcl_getTimeUnit( const sax_fastparser::FastAttributeList::FastAttributeIter& rValue )
821{
822 sal_Int32 nTimeUnit = css::chart::TimeUnit::DAY;
823 if( IsXMLToken( rValue, XML_DAYS ) )
824 nTimeUnit = css::chart::TimeUnit::DAY;
825 else if( IsXMLToken( rValue, XML_MONTHS ) )
826 nTimeUnit = css::chart::TimeUnit::MONTH;
827 else if( IsXMLToken( rValue, XML_YEARS ) )
828 nTimeUnit = css::chart::TimeUnit::YEAR;
829 return nTimeUnit;
830}
831
832}
833
834void DateScaleContext::startFastElement( sal_Int32 /*nElement*/,
835 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
836{
837 if( !m_xAxisProps.is() )
838 return;
839
840 // parse attributes
841 bool bSetNewIncrement=false;
842 chart::TimeIncrement aIncrement;
843 m_xAxisProps->getPropertyValue("TimeIncrement") >>= aIncrement;
844
845 for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
846 {
847 switch( aIter.getToken() )
848 {
849 case XML_ELEMENT(CHART, XML_BASE_TIME_UNIT):
850 {
851 aIncrement.TimeResolution <<= lcl_getTimeUnit(aIter);
852 bSetNewIncrement = true;
853 }
854 break;
856 {
857 chart::TimeInterval aInterval(1,0);
858 aIncrement.MajorTimeInterval >>= aInterval;
859 ::sax::Converter::convertNumber( aInterval.Number, aIter.toView() );
860 aIncrement.MajorTimeInterval <<= aInterval;
861 bSetNewIncrement = true;
862 }
863 break;
865 {
866 chart::TimeInterval aInterval(1,0);
867 aIncrement.MajorTimeInterval >>= aInterval;
868 aInterval.TimeUnit = lcl_getTimeUnit(aIter);
869 aIncrement.MajorTimeInterval <<= aInterval;
870 bSetNewIncrement = true;
871 }
872 break;
874 {
875 chart::TimeInterval aInterval(1,0);
876 aIncrement.MinorTimeInterval >>= aInterval;
877 ::sax::Converter::convertNumber( aInterval.Number, aIter.toView() );
878 aIncrement.MinorTimeInterval <<= aInterval;
879 bSetNewIncrement = true;
880 }
881 break;
883 {
884 chart::TimeInterval aInterval(1,0);
885 aIncrement.MinorTimeInterval >>= aInterval;
886 aInterval.TimeUnit = lcl_getTimeUnit(aIter);
887 aIncrement.MinorTimeInterval <<= aInterval;
888 bSetNewIncrement = true;
889 }
890 break;
891 default:
892 XMLOFF_WARN_UNKNOWN("xmloff", aIter);
893 }
894 }
895
896 if( bSetNewIncrement )
897 m_xAxisProps->setPropertyValue("TimeIncrement", uno::Any( aIncrement ) );
898}
899
900/* 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
static const sal_uInt16 ProductVersionUnknown
Definition: xmlimp.hxx:563
const SvXMLStyleContext * FindStyleChildContext(XmlStyleFamily nFamily, const OUString &rName, bool bCreateIndex=false) const
Definition: xmlstyle.cxx:799
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:3371
@ XML_MAJOR_INTERVAL_UNIT
Definition: xmltoken.hxx:3372
@ XML_CELL_RANGE_ADDRESS
Definition: xmltoken.hxx:410
@ XML_MAJOR_INTERVAL_VALUE
Definition: xmltoken.hxx:3370
@ XML_MINOR_INTERVAL_UNIT
Definition: xmltoken.hxx:3373
bool IsXMLToken(std::u16string_view rString, enum XMLTokenEnum eToken)
compare eToken to the string
Definition: xmltoken.cxx:3581
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:98