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 
20 #include <sax/tools/converter.hxx>
21 
22 #include "SchXMLAxisContext.hxx"
23 #include "SchXMLChartContext.hxx"
24 #include "SchXMLTools.hxx"
25 #include <xmloff/xmlimp.hxx>
26 #include <xmloff/xmlnamespace.hxx>
27 #include <xmloff/xmlement.hxx>
28 #include <xmloff/xmlstyle.hxx>
29 #include <xmloff/prstylei.hxx>
30 #include <xmloff/namespacemap.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 
53 using namespace ::xmloff::token;
54 using namespace com::sun::star;
55 
57 
59 {
60  { XML_X, SCH_XML_AXIS_X },
61  { XML_Y, SCH_XML_AXIS_Y },
62  { XML_Z, SCH_XML_AXIS_Z },
64 };
65 
67 {
68  { XML_AUTO, css::chart::ChartAxisType::AUTOMATIC },
69  { XML_TEXT, css::chart::ChartAxisType::CATEGORY },
70  { XML_DATE, css::chart::ChartAxisType::DATE },
71  { XML_TOKEN_INVALID, 0 }
72 };
73 
74 namespace {
75 
76 class SchXMLCategoriesContext : public SvXMLImportContext
77 {
78 private:
79  OUString& mrAddress;
80 
81 public:
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 
88 class DateScaleContext : public SvXMLImportContext
89 {
90 public:
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 
97 private:
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;
172  case SCH_XML_AXIS_UNDEF:
173  SAL_INFO("xmloff.chart", "Invalid axis" );
174  break;
175  }
176  xDiaProp->setPropertyValue( aPropName, uno::makeAny(true) );
177  xResult.set( xAxis->getAxisTitle(), uno::UNO_QUERY );
178  return xResult;
179 }
180 
181 void 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;
209  case SCH_XML_AXIS_UNDEF:
210  SAL_INFO("xmloff.chart", "Invalid axis" );
211  break;
212  }
213  xDiaProp->setPropertyValue( aPropName, uno::makeAny(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",
226  uno::makeAny( COL_BLACK ));
227  if (!sAutoStyleName.isEmpty())
228  m_rImportHelper.FillAutoStyle(sAutoStyleName, xGridProp);
229  }
230 }
231 
232 void 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;
247  case XML_ELEMENT(CHART, XML_NAME):
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 }
277 namespace
278 {
279 
280 Reference< 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 
315 bool 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 
328 bool 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;
365  case SCH_XML_AXIS_UNDEF:
366  SAL_INFO("xmloff.chart", "Invalid axis" );
367  break;
368  }
369  try
370  {
371  xDiaProp->setPropertyValue( aPropName, uno::makeAny(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::makeAny(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::makeAny( true ));
411  uno::Any aFalseBool( uno::makeAny( false ));
412 
413  // #i109879# the line color is black as default, in the model it is a light gray
414  m_xAxisProps->setPropertyValue("LineColor",
415  uno::makeAny( COL_BLACK ));
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 
429  if( m_bAxisTypeImported )
430  m_xAxisProps->setPropertyValue("AxisType", uno::makeAny(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::makeAny(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::makeAny(m_aCurrentAxis.aTitle) );
568  }
569  catch( beans::UnknownPropertyException & )
570  {
571  SAL_INFO("xmloff.chart", "Property String for Title not available" );
572  }
573  }
574 }
575 
576 css::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  {
582  case XML_ELEMENT(CHART, XML_TITLE):
583  {
587  xTitleShape );
588  }
589  break;
590 
593  return new SchXMLCategoriesContext( GetImport(),
595  break;
596 
598  case XML_ELEMENT(CHART_EXT, XML_DATE_SCALE):
599  m_bDateScaleImported = true;
600  return new DateScaleContext( GetImport(), m_xAxisProps );
601  break;
602 
603  case XML_ELEMENT(CHART, XML_GRID):
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  {
612  case XML_ELEMENT(CHART, XML_CLASS):
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 
654 namespace
655 {
656 
657 Reference< 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::makeAny( css::chart::ChartAxisPosition_VALUE) );
708  double fCrossoverValue = 0.0;
709  aMainXScale.Origin >>= fCrossoverValue;
710  xMainYAxisProp->setPropertyValue("CrossoverValue"
711  , uno::makeAny( fCrossoverValue ) );
712 
713  if( aMainXScale.Orientation == chart2::AxisOrientation_REVERSE )
714  {
715  xMainYAxisProp->setPropertyValue("LabelPosition"
716  , uno::makeAny( css::chart::ChartAxisLabelPosition_OUTSIDE_END) );
717  xMainYAxisProp->setPropertyValue("MarkPosition"
718  , uno::makeAny( css::chart::ChartAxisMarkPosition_AT_LABELS) );
719  if( xSecondaryYAxisProp.is() )
720  xSecondaryYAxisProp->setPropertyValue("CrossoverPosition"
721  , uno::makeAny( css::chart::ChartAxisPosition_START) );
722  }
723  else
724  {
725  xMainYAxisProp->setPropertyValue("LabelPosition"
726  , uno::makeAny( css::chart::ChartAxisLabelPosition_OUTSIDE_START) );
727  xMainYAxisProp->setPropertyValue("MarkPosition"
728  , uno::makeAny( css::chart::ChartAxisMarkPosition_AT_LABELS) );
729  if( xSecondaryYAxisProp.is() )
730  xSecondaryYAxisProp->setPropertyValue("CrossoverPosition"
731  , uno::makeAny( css::chart::ChartAxisPosition_END) );
732  }
733  }
734  else
735  {
736  if( aMainXScale.Orientation == chart2::AxisOrientation_REVERSE )
737  {
738  xMainYAxisProp->setPropertyValue("CrossoverPosition"
739  , uno::makeAny( css::chart::ChartAxisPosition_END) );
740  if( xSecondaryYAxisProp.is() )
741  xSecondaryYAxisProp->setPropertyValue("CrossoverPosition"
742  , uno::makeAny( css::chart::ChartAxisPosition_START) );
743  }
744  else
745  {
746  xMainYAxisProp->setPropertyValue("CrossoverPosition"
747  , uno::makeAny( css::chart::ChartAxisPosition_START) );
748  if( xSecondaryYAxisProp.is() )
749  xSecondaryYAxisProp->setPropertyValue("CrossoverPosition"
750  , uno::makeAny( css::chart::ChartAxisPosition_END) );
751  }
752  }
753 
754  chart2::ScaleData aMainYScale = xMainYAxis->getScaleData();
755  xMainXAxisProp->setPropertyValue("CrossoverPosition"
756  , uno::makeAny( css::chart::ChartAxisPosition_VALUE) );
757  double fCrossoverValue = 0.0;
758  aMainYScale.Origin >>= fCrossoverValue;
759  xMainXAxisProp->setPropertyValue("CrossoverValue"
760  , uno::makeAny( fCrossoverValue ) );
761 
762  if( aMainYScale.Orientation == chart2::AxisOrientation_REVERSE )
763  {
764  xMainXAxisProp->setPropertyValue("LabelPosition"
765  , uno::makeAny( css::chart::ChartAxisLabelPosition_OUTSIDE_END) );
766  xMainXAxisProp->setPropertyValue("MarkPosition"
767  , uno::makeAny( css::chart::ChartAxisMarkPosition_AT_LABELS) );
768  if( xSecondaryXAxisProp.is() )
769  xSecondaryXAxisProp->setPropertyValue("CrossoverPosition"
770  , uno::makeAny( css::chart::ChartAxisPosition_START) );
771  }
772  else
773  {
774  xMainXAxisProp->setPropertyValue("LabelPosition"
775  , uno::makeAny( css::chart::ChartAxisLabelPosition_OUTSIDE_START) );
776  xMainXAxisProp->setPropertyValue("MarkPosition"
777  , uno::makeAny( css::chart::ChartAxisMarkPosition_AT_LABELS) );
778  if( xSecondaryXAxisProp.is() )
779  xSecondaryXAxisProp->setPropertyValue("CrossoverPosition"
780  , uno::makeAny( css::chart::ChartAxisPosition_END) );
781  }
782  }
783  }
784  }
785  }
786  catch( uno::Exception & )
787  {
788  }
789 }
790 
791 SchXMLCategoriesContext::SchXMLCategoriesContext(
792  SvXMLImport& rImport,
793  OUString& rAddress ) :
794  SvXMLImportContext( rImport ),
795  mrAddress( rAddress )
796 {
797 }
798 
799 void 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 
811 DateScaleContext::DateScaleContext(
812  SvXMLImport& rImport,
813  const Reference< beans::XPropertySet >& rAxisProps ) :
814  SvXMLImportContext( rImport ),
815  m_xAxisProps( rAxisProps )
816 {
817 }
818 
819 namespace
820 {
821 sal_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 
835 void 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::makeAny( aIncrement ) );
899 }
900 
901 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList > &AttrList) override
const SvXMLEnumMapEntry< sal_uInt16 > aXMLAxisTypeMap[]
bool hasValue()
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)
SvXMLStylesContext * GetAutoStylesContext() const
uno::Any getPropertyFromContext(std::u16string_view rPropertyName, const XMLPropStyleContext *pPropStyleContext, const SvXMLStylesContext *pStylesCtxt)
SvXMLImport & GetImport()
Definition: xmlictxt.hxx:56
sal_Int8 nAxisIndex
SchXMLAxisDimension
css::uno::Reference< css::drawing::XShape > getTitleShape() const
css::uno::Reference< css::chart::XDiagram > m_xDiagram
bool IsXMLToken(std::u16string_view rString, enum XMLTokenEnum eToken)
compare eToken to the string
Definition: xmltoken.cxx:3462
FastAttributeList & castToFastAttributeList(const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList)
void FillAutoStyle(const OUString &rAutoStyleName, const css::uno::Reference< css::beans::XPropertySet > &rProp)
Fill in the autostyle.
bool & m_rbAxisPositionAttributeImported
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 ...
css::uno::Any const & rValue
Definition: ImageStyle.hxx:38
static void CorrectAxisPositions(const css::uno::Reference< css::chart2::XChartDocument > &xNewDoc, std::u16string_view rChartTypeServiceName, std::u16string_view rODFVersionOfFile, bool bAxisPositionAttributeImported)
#define XMLOFF_WARN_UNKNOWN(area, rIter)
Definition: xmlictxt.hxx:110
static const sal_uInt16 ProductVersionUnknown
Definition: xmlimp.hxx:556
std::vector< SchXMLAxis > & m_rAxes
OUString aTitle
bool m_bAdaptXAxisOrientationForOld2DBarCharts
enum SchXMLAxisDimension eDimension
static Reference< chart::XAxis > lcl_getChartAxis(const SchXMLAxis &rCurrentAxis, const Reference< chart::XDiagram > &rDiagram)
float u
OUString & m_rCategoriesAddress
static XmlStyleFamily GetChartFamilyID()
css::uno::Reference< css::beans::XPropertySet > m_xAxisProps
OUString aName
With this class you can import a element containing its data as element o...
virtual void SAL_CALL startFastElement(sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList) override
This class deliberately does not support XWeak, to improve performance when loading large documents...
Definition: xmlictxt.hxx:45
Map an XMLTokenEnum to an enum value.
Definition: ximpshap.hxx:40
const css::uno::Reference< css::chart::XChartDocument > & GetChartDocument() const
Handling of tokens in XML:
#define SAL_INFO(area, stream)
#define XML_ELEMENT(prefix, name)
Definition: xmlimp.hxx:96
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:138
const ::std::vector< Color > ImpSvNumberformatScan::StandardColor COL_BLACK
const SvXMLStyleContext * FindStyleChildContext(XmlStyleFamily nFamily, const OUString &rName, bool bCreateIndex=false) const
Definition: xmlstyle.cxx:788
#define XMLOFF_WARN_UNKNOWN_ELEMENT(area, token)
Definition: xmlictxt.hxx:116
SchXMLImportHelper & m_rImportHelper
virtual ~SchXMLAxisContext() override
const SvXMLEnumMapEntry< SchXMLAxisDimension > aXMLAxisDimensionMap[]
AUTOMATIC
static bool convertNumber(sal_Int32 &rValue, std::u16string_view aString, sal_Int32 nMin=SAL_MIN_INT32, sal_Int32 nMax=SAL_MAX_INT32)
void CreateGrid(const OUString &sAutoStyleName, bool bIsMajor)