vcl: allow for overriding the default PDF rendering resolution
[LibreOffice.git] / chart2 / source / tools / AxisHelper.cxx
blobf3ededdaef347f2d1802c73cb5889b06ef5af70f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <AxisHelper.hxx>
21 #include <DiagramHelper.hxx>
22 #include <ChartTypeHelper.hxx>
23 #include <AxisIndexDefines.hxx>
24 #include <LinePropertiesHelper.hxx>
25 #include <servicenames_coosystems.hxx>
26 #include <DataSeriesHelper.hxx>
27 #include <Scaling.hxx>
28 #include <ChartModel.hxx>
29 #include <ChartModelHelper.hxx>
30 #include <DataSourceHelper.hxx>
31 #include <ReferenceSizeProvider.hxx>
32 #include <ExplicitCategoriesProvider.hxx>
33 #include <unonames.hxx>
35 #include <unotools/saveopt.hxx>
37 #include <com/sun/star/chart/ChartAxisPosition.hpp>
38 #include <com/sun/star/chart2/AxisType.hpp>
39 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
40 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
41 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
42 #include <com/sun/star/chart2/data/XDataSource.hpp>
44 #include <rtl/math.hxx>
45 #include <sal/log.hxx>
47 #include <com/sun/star/lang/XServiceName.hpp>
48 #include <com/sun/star/uno/XComponentContext.hpp>
49 #include <comphelper/sequence.hxx>
50 #include <tools/diagnose_ex.h>
52 #include <map>
54 namespace chart
56 using namespace ::com::sun::star;
57 using namespace ::com::sun::star::chart2;
58 using ::com::sun::star::uno::Reference;
59 using ::com::sun::star::uno::Sequence;
61 Reference< chart2::XScaling > AxisHelper::createLinearScaling()
63 return new LinearScaling( 1.0, 0.0 );
66 Reference< chart2::XScaling > AxisHelper::createLogarithmicScaling( double fBase )
68 return new LogarithmicScaling( fBase );
71 ScaleData AxisHelper::createDefaultScale()
73 ScaleData aScaleData;
74 aScaleData.AxisType = chart2::AxisType::REALNUMBER;
75 aScaleData.AutoDateAxis = true;
76 aScaleData.ShiftedCategoryPosition = false;//this is adapted in the view code currently
77 Sequence< SubIncrement > aSubIncrements(1);
78 aSubIncrements[0] = SubIncrement();
79 aScaleData.IncrementData.SubIncrements = aSubIncrements;
80 return aScaleData;
83 void AxisHelper::removeExplicitScaling( ScaleData& rScaleData )
85 uno::Any aEmpty;
86 rScaleData.Minimum = rScaleData.Maximum = rScaleData.Origin = aEmpty;
87 rScaleData.Scaling = nullptr;
88 ScaleData aDefaultScale( createDefaultScale() );
89 rScaleData.IncrementData = aDefaultScale.IncrementData;
90 rScaleData.TimeIncrement = aDefaultScale.TimeIncrement;
93 bool AxisHelper::isLogarithmic( const Reference< XScaling >& xScaling )
95 Reference< lang::XServiceName > xServiceName( xScaling, uno::UNO_QUERY );
96 return xServiceName.is()
97 && xServiceName->getServiceName() == "com.sun.star.chart2.LogarithmicScaling";
100 chart2::ScaleData AxisHelper::getDateCheckedScale( const Reference< chart2::XAxis >& xAxis, ChartModel& rModel )
102 ScaleData aScale = xAxis->getScaleData();
103 Reference< chart2::XCoordinateSystem > xCooSys( ChartModelHelper::getFirstCoordinateSystem( rModel ) );
104 if( aScale.AutoDateAxis && aScale.AxisType == AxisType::CATEGORY )
106 sal_Int32 nDimensionIndex=0; sal_Int32 nAxisIndex=0;
107 AxisHelper::getIndicesForAxis(xAxis, xCooSys, nDimensionIndex, nAxisIndex );
108 bool bChartTypeAllowsDateAxis = ChartTypeHelper::isSupportingDateAxis( AxisHelper::getChartTypeByIndex( xCooSys, 0 ), nDimensionIndex );
109 if( bChartTypeAllowsDateAxis )
110 aScale.AxisType = AxisType::DATE;
112 if( aScale.AxisType == AxisType::DATE )
114 ExplicitCategoriesProvider aExplicitCategoriesProvider( xCooSys, rModel );
115 if( !aExplicitCategoriesProvider.isDateAxis() )
116 aScale.AxisType = AxisType::CATEGORY;
118 return aScale;
121 void AxisHelper::checkDateAxis( chart2::ScaleData& rScale, ExplicitCategoriesProvider* pExplicitCategoriesProvider, bool bChartTypeAllowsDateAxis )
123 if( rScale.AutoDateAxis && rScale.AxisType == AxisType::CATEGORY && bChartTypeAllowsDateAxis )
125 rScale.AxisType = AxisType::DATE;
126 removeExplicitScaling( rScale );
128 if( rScale.AxisType == AxisType::DATE && (!pExplicitCategoriesProvider || !pExplicitCategoriesProvider->isDateAxis()) )
130 rScale.AxisType = AxisType::CATEGORY;
131 removeExplicitScaling( rScale );
135 sal_Int32 AxisHelper::getExplicitNumberFormatKeyForAxis(
136 const Reference< chart2::XAxis >& xAxis
137 , const Reference< chart2::XCoordinateSystem > & xCorrespondingCoordinateSystem
138 , const Reference<chart2::XChartDocument>& xChartDoc
139 , bool bSearchForParallelAxisIfNothingIsFound )
141 sal_Int32 nNumberFormatKey(0);
142 sal_Int32 nAxisIndex = 0;
143 sal_Int32 nDimensionIndex = 1;
144 AxisHelper::getIndicesForAxis( xAxis, xCorrespondingCoordinateSystem, nDimensionIndex, nAxisIndex );
145 Reference<util::XNumberFormatsSupplier> const xNumberFormatsSupplier(xChartDoc, uno::UNO_QUERY);
147 Reference< beans::XPropertySet > xProp( xAxis, uno::UNO_QUERY );
148 if (!xProp.is())
149 return 0;
151 bool bLinkToSource = true;
152 xProp->getPropertyValue(CHART_UNONAME_LINK_TO_SRC_NUMFMT) >>= bLinkToSource;
153 xProp->getPropertyValue(CHART_UNONAME_NUMFMT) >>= nNumberFormatKey;
155 if (bLinkToSource)
157 bool bFormatSet = false;
158 //check whether we have a percent scale -> use percent format
159 ChartModel* pModel = nullptr;
160 if( xNumberFormatsSupplier.is() )
162 pModel = dynamic_cast<ChartModel*>( xChartDoc.get() );
163 assert(pModel);
165 if (pModel)
167 ScaleData aData = AxisHelper::getDateCheckedScale( xAxis, *pModel );
168 if( aData.AxisType==AxisType::PERCENT )
170 sal_Int32 nPercentFormat = DiagramHelper::getPercentNumberFormat( xNumberFormatsSupplier );
171 if( nPercentFormat != -1 )
173 nNumberFormatKey = nPercentFormat;
174 bFormatSet = true;
177 else if( aData.AxisType==AxisType::DATE )
179 if( aData.Categories.is() )
181 Reference< data::XDataSequence > xSeq( aData.Categories->getValues());
182 if( xSeq.is() && !( xChartDoc.is() && xChartDoc->hasInternalDataProvider()) )
183 nNumberFormatKey = xSeq->getNumberFormatKeyByIndex( -1 );
184 else
185 nNumberFormatKey = DiagramHelper::getDateNumberFormat( xNumberFormatsSupplier );
186 bFormatSet = true;
189 else if( xChartDoc.is() && xChartDoc->hasInternalDataProvider() && nDimensionIndex == 0 ) //maybe date axis
191 Reference< chart2::XDiagram > xDiagram( xChartDoc->getFirstDiagram() );
192 if( DiagramHelper::isSupportingDateAxis( xDiagram ) )
194 nNumberFormatKey = DiagramHelper::getDateNumberFormat( xNumberFormatsSupplier );
196 else
198 Reference< data::XDataSource > xSource( DataSourceHelper::getUsedData( xChartDoc ) );
199 if( xSource.is() )
201 std::vector< Reference< chart2::data::XLabeledDataSequence > > aXValues(
202 DataSeriesHelper::getAllDataSequencesByRole( xSource->getDataSequences(), "values-x" ) );
203 if( aXValues.empty() )
205 Reference< data::XLabeledDataSequence > xCategories( DiagramHelper::getCategoriesFromDiagram( xDiagram ) );
206 if( xCategories.is() )
208 Reference< data::XDataSequence > xSeq( xCategories->getValues());
209 if( xSeq.is() )
211 bool bHasValidDoubles = false;
212 double fTest=0.0;
213 Sequence< uno::Any > aCats( xSeq->getData() );
214 sal_Int32 nCount = aCats.getLength();
215 for( sal_Int32 i = 0; i < nCount; ++i )
217 if( (aCats[i]>>=fTest) && !::rtl::math::isNan(fTest) )
219 bHasValidDoubles=true;
220 break;
223 if( bHasValidDoubles )
224 nNumberFormatKey = DiagramHelper::getDateNumberFormat( xNumberFormatsSupplier );
230 bFormatSet = true;
234 if( !bFormatSet )
236 typedef std::map< sal_Int32, sal_Int32 > tNumberformatFrequency;
237 tNumberformatFrequency aKeyMap;
238 bool bNumberFormatKeyFoundViaAttachedData = false;
242 Reference< XChartTypeContainer > xCTCnt( xCorrespondingCoordinateSystem, uno::UNO_QUERY_THROW );
243 OUString aRoleToMatch;
244 if( nDimensionIndex == 0 )
245 aRoleToMatch = "values-x";
246 Sequence< Reference< XChartType > > aChartTypes( xCTCnt->getChartTypes());
247 for( sal_Int32 nCTIdx=0; nCTIdx<aChartTypes.getLength(); ++nCTIdx )
249 if( nDimensionIndex != 0 )
250 aRoleToMatch = ChartTypeHelper::getRoleOfSequenceForYAxisNumberFormatDetection( aChartTypes[nCTIdx] );
251 Reference< XDataSeriesContainer > xDSCnt( aChartTypes[nCTIdx], uno::UNO_QUERY_THROW );
252 Sequence< Reference< XDataSeries > > aDataSeriesSeq( xDSCnt->getDataSeries());
253 for( sal_Int32 nSeriesIdx=0; nSeriesIdx<aDataSeriesSeq.getLength(); ++nSeriesIdx )
255 Reference< chart2::XDataSeries > xDataSeries(aDataSeriesSeq[nSeriesIdx]);
256 Reference< data::XDataSource > xSource( xDataSeries, uno::UNO_QUERY_THROW );
258 if( nDimensionIndex == 1 )
260 //only take those series into account that are attached to this axis
261 sal_Int32 nAttachedAxisIndex = DataSeriesHelper::getAttachedAxisIndex(xDataSeries);
262 if( nAttachedAxisIndex != nAxisIndex )
263 continue;
266 Reference< data::XLabeledDataSequence > xLabeledSeq(
267 DataSeriesHelper::getDataSequenceByRole( xSource, aRoleToMatch ) );
269 if( !xLabeledSeq.is() && nDimensionIndex==0 )
271 ScaleData aData = xAxis->getScaleData();
272 xLabeledSeq = aData.Categories;
275 if( xLabeledSeq.is() )
277 Reference< data::XDataSequence > xSeq( xLabeledSeq->getValues());
278 if( xSeq.is() )
280 sal_Int32 nKey = xSeq->getNumberFormatKeyByIndex( -1 );
281 // initialize the value
282 if( aKeyMap.find( nKey ) == aKeyMap.end())
283 aKeyMap[ nKey ] = 0;
284 // increase frequency
285 aKeyMap[ nKey ] = (aKeyMap[ nKey ] + 1);
291 catch( const uno::Exception & )
293 DBG_UNHANDLED_EXCEPTION("chart2");
296 if( ! aKeyMap.empty())
298 sal_Int32 nMaxFreq = 0;
299 // find most frequent key
300 for (auto const& elem : aKeyMap)
302 SAL_INFO(
303 "chart2.tools",
304 "NumberFormatKey " << elem.first << " appears "
305 << elem.second << " times");
306 // all values must at least be 1
307 if( elem.second > nMaxFreq )
309 nNumberFormatKey = elem.first;
310 bNumberFormatKeyFoundViaAttachedData = true;
311 nMaxFreq = elem.second;
316 if( bSearchForParallelAxisIfNothingIsFound )
318 //no format is set to this axis and no data is set to this axis
319 //--> try to obtain the format from the parallel y-axis
320 if( !bNumberFormatKeyFoundViaAttachedData && nDimensionIndex == 1 )
322 sal_Int32 nParallelAxisIndex = (nAxisIndex==1) ?0 :1;
323 Reference< XAxis > xParallelAxis( AxisHelper::getAxis( 1, nParallelAxisIndex, xCorrespondingCoordinateSystem ) );
324 nNumberFormatKey = AxisHelper::getExplicitNumberFormatKeyForAxis(xParallelAxis, xCorrespondingCoordinateSystem, xChartDoc, false);
330 return nNumberFormatKey;
333 Reference< XAxis > AxisHelper::createAxis(
334 sal_Int32 nDimensionIndex
335 , sal_Int32 nAxisIndex // 0==main or 1==secondary axis
336 , const Reference< XCoordinateSystem >& xCooSys
337 , const Reference< uno::XComponentContext > & xContext
338 , ReferenceSizeProvider * pRefSizeProvider )
340 if( !xContext.is() || !xCooSys.is() )
341 return nullptr;
342 if( nDimensionIndex >= xCooSys->getDimension() )
343 return nullptr;
345 Reference< XAxis > xAxis( xContext->getServiceManager()->createInstanceWithContext(
346 "com.sun.star.chart2.Axis", xContext ), uno::UNO_QUERY );
348 OSL_ASSERT( xAxis.is());
349 if( xAxis.is())
351 xCooSys->setAxisByDimension( nDimensionIndex, xAxis, nAxisIndex );
353 if( nAxisIndex>0 )//when inserting secondary axes copy some things from the main axis
355 css::chart::ChartAxisPosition eNewAxisPos( css::chart::ChartAxisPosition_END );
357 Reference< XAxis > xMainAxis( xCooSys->getAxisByDimension( nDimensionIndex, 0 ) );
358 if( xMainAxis.is() )
360 ScaleData aScale = xAxis->getScaleData();
361 ScaleData aMainScale = xMainAxis->getScaleData();
363 aScale.AxisType = aMainScale.AxisType;
364 aScale.AutoDateAxis = aMainScale.AutoDateAxis;
365 aScale.Categories = aMainScale.Categories;
366 aScale.Orientation = aMainScale.Orientation;
368 xAxis->setScaleData( aScale );
370 //ensure that the second axis is not placed on the main axis
371 Reference< beans::XPropertySet > xMainProp( xMainAxis, uno::UNO_QUERY );
372 if( xMainProp.is() )
374 css::chart::ChartAxisPosition eMainAxisPos( css::chart::ChartAxisPosition_ZERO );
375 xMainProp->getPropertyValue("CrossoverPosition") >>= eMainAxisPos;
376 if( eMainAxisPos == css::chart::ChartAxisPosition_END )
377 eNewAxisPos = css::chart::ChartAxisPosition_START;
381 Reference< beans::XPropertySet > xProp( xAxis, uno::UNO_QUERY );
382 if( xProp.is() )
383 xProp->setPropertyValue("CrossoverPosition", uno::Any(eNewAxisPos) );
386 Reference< beans::XPropertySet > xProp( xAxis, uno::UNO_QUERY );
387 if( xProp.is() ) try
389 // set correct initial AutoScale
390 if( pRefSizeProvider )
391 pRefSizeProvider->setValuesAtPropertySet( xProp );
393 catch( const uno::Exception& )
395 TOOLS_WARN_EXCEPTION("chart2", "" );
398 return xAxis;
401 Reference< XAxis > AxisHelper::createAxis( sal_Int32 nDimensionIndex, bool bMainAxis
402 , const Reference< chart2::XDiagram >& xDiagram
403 , const Reference< uno::XComponentContext >& xContext
404 , ReferenceSizeProvider * pRefSizeProvider )
406 OSL_ENSURE( xContext.is(), "need a context to create an axis" );
407 if( !xContext.is() )
408 return nullptr;
410 sal_Int32 nAxisIndex = bMainAxis ? MAIN_AXIS_INDEX : SECONDARY_AXIS_INDEX;
411 Reference< XCoordinateSystem > xCooSys = AxisHelper::getCoordinateSystemByIndex( xDiagram, 0 );
413 // create axis
414 return AxisHelper::createAxis(
415 nDimensionIndex, nAxisIndex, xCooSys, xContext, pRefSizeProvider );
418 void AxisHelper::showAxis( sal_Int32 nDimensionIndex, bool bMainAxis
419 , const Reference< chart2::XDiagram >& xDiagram
420 , const Reference< uno::XComponentContext >& xContext
421 , ReferenceSizeProvider * pRefSizeProvider )
423 if( !xDiagram.is() )
424 return;
426 bool bNewAxisCreated = false;
427 Reference< XAxis > xAxis( AxisHelper::getAxis( nDimensionIndex, bMainAxis, xDiagram ) );
428 if( !xAxis.is() && xContext.is() )
430 // create axis
431 bNewAxisCreated = true;
432 xAxis.set( AxisHelper::createAxis( nDimensionIndex, bMainAxis, xDiagram, xContext, pRefSizeProvider ) );
435 OSL_ASSERT( xAxis.is());
436 if( !bNewAxisCreated ) //default is true already if created
437 AxisHelper::makeAxisVisible( xAxis );
440 void AxisHelper::showGrid( sal_Int32 nDimensionIndex, sal_Int32 nCooSysIndex, bool bMainGrid
441 , const Reference< XDiagram >& xDiagram )
443 if( !xDiagram.is() )
444 return;
446 Reference< XCoordinateSystem > xCooSys = AxisHelper::getCoordinateSystemByIndex( xDiagram, nCooSysIndex );
447 if(!xCooSys.is())
448 return;
450 Reference< XAxis > xAxis( AxisHelper::getAxis( nDimensionIndex, MAIN_AXIS_INDEX, xCooSys ) );
451 if(!xAxis.is())
453 //hhhh todo create axis without axis visibility
455 if(!xAxis.is())
456 return;
458 if( bMainGrid )
459 AxisHelper::makeGridVisible( xAxis->getGridProperties() );
460 else
462 Sequence< Reference< beans::XPropertySet > > aSubGrids( xAxis->getSubGridProperties() );
463 for( sal_Int32 nN=0; nN<aSubGrids.getLength(); nN++)
464 AxisHelper::makeGridVisible( aSubGrids[nN] );
468 void AxisHelper::makeAxisVisible( const Reference< XAxis >& xAxis )
470 Reference< beans::XPropertySet > xProps( xAxis, uno::UNO_QUERY );
471 if( xProps.is() )
473 xProps->setPropertyValue( "Show", uno::Any( true ) );
474 LinePropertiesHelper::SetLineVisible( xProps );
475 xProps->setPropertyValue( "DisplayLabels", uno::Any( true ) );
479 void AxisHelper::makeGridVisible( const Reference< beans::XPropertySet >& xGridProperties )
481 if( xGridProperties.is() )
483 xGridProperties->setPropertyValue( "Show", uno::Any( true ) );
484 LinePropertiesHelper::SetLineVisible( xGridProperties );
488 void AxisHelper::hideAxis( sal_Int32 nDimensionIndex, bool bMainAxis
489 , const Reference< XDiagram >& xDiagram )
491 AxisHelper::makeAxisInvisible( AxisHelper::getAxis( nDimensionIndex, bMainAxis, xDiagram ) );
494 void AxisHelper::makeAxisInvisible( const Reference< XAxis >& xAxis )
496 Reference< beans::XPropertySet > xProps( xAxis, uno::UNO_QUERY );
497 if( xProps.is() )
499 xProps->setPropertyValue( "Show", uno::Any( false ) );
503 void AxisHelper::hideAxisIfNoDataIsAttached( const Reference< XAxis >& xAxis, const Reference< XDiagram >& xDiagram )
505 //axis is hidden if no data is attached anymore but data is available
506 bool bOtherSeriesAttachedToThisAxis = false;
507 std::vector< Reference< chart2::XDataSeries > > aSeriesVector( DiagramHelper::getDataSeriesFromDiagram( xDiagram ) );
508 for (auto const& series : aSeriesVector)
510 uno::Reference< chart2::XAxis > xCurrentAxis = DiagramHelper::getAttachedAxis(series, xDiagram );
511 if( xCurrentAxis==xAxis )
513 bOtherSeriesAttachedToThisAxis = true;
514 break;
517 if(!bOtherSeriesAttachedToThisAxis && !aSeriesVector.empty() )
518 AxisHelper::makeAxisInvisible( xAxis );
521 void AxisHelper::hideGrid( sal_Int32 nDimensionIndex, sal_Int32 nCooSysIndex, bool bMainGrid
522 , const Reference< XDiagram >& xDiagram )
524 if( !xDiagram.is() )
525 return;
527 Reference< XCoordinateSystem > xCooSys = AxisHelper::getCoordinateSystemByIndex( xDiagram, nCooSysIndex );
528 if(!xCooSys.is())
529 return;
531 Reference< XAxis > xAxis( AxisHelper::getAxis( nDimensionIndex, MAIN_AXIS_INDEX, xCooSys ) );
532 if(!xAxis.is())
533 return;
535 if( bMainGrid )
536 AxisHelper::makeGridInvisible( xAxis->getGridProperties() );
537 else
539 Sequence< Reference< beans::XPropertySet > > aSubGrids( xAxis->getSubGridProperties() );
540 for( sal_Int32 nN=0; nN<aSubGrids.getLength(); nN++)
541 AxisHelper::makeGridInvisible( aSubGrids[nN] );
545 void AxisHelper::makeGridInvisible( const Reference< beans::XPropertySet >& xGridProperties )
547 if( xGridProperties.is() )
549 xGridProperties->setPropertyValue( "Show", uno::Any( false ) );
553 bool AxisHelper::isGridShown( sal_Int32 nDimensionIndex, sal_Int32 nCooSysIndex, bool bMainGrid
554 , const Reference< css::chart2::XDiagram >& xDiagram )
556 bool bRet = false;
558 Reference< XCoordinateSystem > xCooSys = AxisHelper::getCoordinateSystemByIndex( xDiagram, nCooSysIndex );
559 if(!xCooSys.is())
560 return bRet;
562 Reference< XAxis > xAxis( AxisHelper::getAxis( nDimensionIndex, MAIN_AXIS_INDEX, xCooSys ) );
563 if(!xAxis.is())
564 return bRet;
566 if( bMainGrid )
567 bRet = AxisHelper::isGridVisible( xAxis->getGridProperties() );
568 else
570 Sequence< Reference< beans::XPropertySet > > aSubGrids( xAxis->getSubGridProperties() );
571 if( aSubGrids.hasElements() )
572 bRet = AxisHelper::isGridVisible( aSubGrids[0] );
575 return bRet;
578 Reference< XCoordinateSystem > AxisHelper::getCoordinateSystemByIndex(
579 const Reference< XDiagram >& xDiagram, sal_Int32 nIndex )
581 Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY );
582 if(!xCooSysContainer.is())
583 return nullptr;
584 Sequence< Reference< XCoordinateSystem > > aCooSysList = xCooSysContainer->getCoordinateSystems();
585 if(0<=nIndex && nIndex<aCooSysList.getLength())
586 return aCooSysList[nIndex];
587 return nullptr;
590 Reference< XAxis > AxisHelper::getAxis( sal_Int32 nDimensionIndex, bool bMainAxis
591 , const Reference< XDiagram >& xDiagram )
593 Reference< XAxis > xRet;
596 Reference< XCoordinateSystem > xCooSys = AxisHelper::getCoordinateSystemByIndex( xDiagram, 0 );
597 xRet.set( AxisHelper::getAxis( nDimensionIndex, bMainAxis ? 0 : 1, xCooSys ) );
599 catch( const uno::Exception & )
602 return xRet;
605 Reference< XAxis > AxisHelper::getAxis( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex
606 , const Reference< XCoordinateSystem >& xCooSys )
608 Reference< XAxis > xRet;
609 if(!xCooSys.is())
610 return xRet;
612 if(nDimensionIndex >= xCooSys->getDimension())
613 return xRet;
615 if(nAxisIndex > xCooSys->getMaximumAxisIndexByDimension(nDimensionIndex))
616 return xRet;
618 assert(nAxisIndex >= 0);
619 assert(nDimensionIndex >= 0);
620 xRet.set( xCooSys->getAxisByDimension( nDimensionIndex, nAxisIndex ) );
621 return xRet;
624 Reference< XAxis > AxisHelper::getCrossingMainAxis( const Reference< XAxis >& xAxis
625 , const Reference< XCoordinateSystem >& xCooSys )
627 sal_Int32 nDimensionIndex = 0;
628 sal_Int32 nAxisIndex = 0;
629 AxisHelper::getIndicesForAxis( xAxis, xCooSys, nDimensionIndex, nAxisIndex );
630 if( nDimensionIndex==2 )
632 nDimensionIndex=1;
633 bool bSwapXY = false;
634 Reference< beans::XPropertySet > xCooSysProp( xCooSys, uno::UNO_QUERY );
635 if( xCooSysProp.is() && (xCooSysProp->getPropertyValue( "SwapXAndYAxis" ) >>= bSwapXY) && bSwapXY )
636 nDimensionIndex=0;
638 else if( nDimensionIndex==1 )
639 nDimensionIndex=0;
640 else
641 nDimensionIndex=1;
642 return AxisHelper::getAxis( nDimensionIndex, 0, xCooSys );
645 Reference< XAxis > AxisHelper::getParallelAxis( const Reference< XAxis >& xAxis
646 , const Reference< XDiagram >& xDiagram )
650 sal_Int32 nCooSysIndex=-1;
651 sal_Int32 nDimensionIndex=-1;
652 sal_Int32 nAxisIndex=-1;
653 if( getIndicesForAxis( xAxis, xDiagram, nCooSysIndex, nDimensionIndex, nAxisIndex ) )
655 sal_Int32 nParallelAxisIndex = (nAxisIndex==1) ?0 :1;
656 return getAxis( nDimensionIndex, nParallelAxisIndex, getCoordinateSystemByIndex( xDiagram, nCooSysIndex ) );
659 catch( const uno::RuntimeException& )
662 return nullptr;
665 bool AxisHelper::isAxisShown( sal_Int32 nDimensionIndex, bool bMainAxis
666 , const Reference< XDiagram >& xDiagram )
668 return AxisHelper::isAxisVisible( AxisHelper::getAxis( nDimensionIndex, bMainAxis, xDiagram ) );
671 bool AxisHelper::isAxisVisible( const Reference< XAxis >& xAxis )
673 bool bRet = false;
675 Reference< beans::XPropertySet > xProps( xAxis, uno::UNO_QUERY );
676 if( xProps.is() )
678 xProps->getPropertyValue( "Show" ) >>= bRet;
679 bRet = bRet && ( LinePropertiesHelper::IsLineVisible( xProps )
680 || areAxisLabelsVisible( xProps ) );
683 return bRet;
686 bool AxisHelper::areAxisLabelsVisible( const Reference< beans::XPropertySet >& xAxisProperties )
688 bool bRet = false;
689 if( xAxisProperties.is() )
691 xAxisProperties->getPropertyValue( "DisplayLabels" ) >>= bRet;
693 return bRet;
696 bool AxisHelper::isGridVisible( const Reference< beans::XPropertySet >& xGridProperies )
698 bool bRet = false;
700 if( xGridProperies.is() )
702 xGridProperies->getPropertyValue( "Show" ) >>= bRet;
703 bRet = bRet && LinePropertiesHelper::IsLineVisible( xGridProperies );
706 return bRet;
709 Reference< beans::XPropertySet > AxisHelper::getGridProperties(
710 const Reference< XCoordinateSystem >& xCooSys
711 , sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex, sal_Int32 nSubGridIndex )
713 Reference< beans::XPropertySet > xRet;
715 Reference< XAxis > xAxis( AxisHelper::getAxis( nDimensionIndex, nAxisIndex, xCooSys ) );
716 if( xAxis.is() )
718 if( nSubGridIndex<0 )
719 xRet.set( xAxis->getGridProperties() );
720 else
722 Sequence< Reference< beans::XPropertySet > > aSubGrids( xAxis->getSubGridProperties() );
723 if (nSubGridIndex < aSubGrids.getLength())
724 xRet.set( aSubGrids[nSubGridIndex] );
728 return xRet;
731 sal_Int32 AxisHelper::getDimensionIndexOfAxis(
732 const Reference< XAxis >& xAxis
733 , const Reference< XDiagram >& xDiagram )
735 sal_Int32 nDimensionIndex = -1;
736 sal_Int32 nCooSysIndex = -1;
737 sal_Int32 nAxisIndex = -1;
738 AxisHelper::getIndicesForAxis( xAxis, xDiagram, nCooSysIndex , nDimensionIndex, nAxisIndex );
739 return nDimensionIndex;
742 bool AxisHelper::getIndicesForAxis(
743 const Reference< XAxis >& xAxis
744 , const Reference< XCoordinateSystem >& xCooSys
745 , sal_Int32& rOutDimensionIndex, sal_Int32& rOutAxisIndex )
747 //returns true if indices are found
749 rOutDimensionIndex = -1;
750 rOutAxisIndex = -1;
752 if( xCooSys.is() && xAxis.is() )
754 Reference< XAxis > xCurrentAxis;
755 sal_Int32 nDimensionCount( xCooSys->getDimension() );
756 for( sal_Int32 nDimensionIndex = 0; nDimensionIndex < nDimensionCount; nDimensionIndex++ )
758 sal_Int32 nMaxAxisIndex = xCooSys->getMaximumAxisIndexByDimension(nDimensionIndex);
759 for( sal_Int32 nAxisIndex = 0; nAxisIndex <= nMaxAxisIndex; nAxisIndex++ )
761 xCurrentAxis = xCooSys->getAxisByDimension(nDimensionIndex,nAxisIndex);
762 if( xCurrentAxis == xAxis )
764 rOutDimensionIndex = nDimensionIndex;
765 rOutAxisIndex = nAxisIndex;
766 return true;
771 return false;
774 bool AxisHelper::getIndicesForAxis( const Reference< XAxis >& xAxis, const Reference< XDiagram >& xDiagram
775 , sal_Int32& rOutCooSysIndex, sal_Int32& rOutDimensionIndex, sal_Int32& rOutAxisIndex )
777 //returns true if indices are found
779 rOutCooSysIndex = -1;
780 rOutDimensionIndex = -1;
781 rOutAxisIndex = -1;
783 Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY );
784 if(xCooSysContainer.is())
786 Sequence< Reference< XCoordinateSystem > > aCooSysList = xCooSysContainer->getCoordinateSystems();
787 for( sal_Int32 nC=0; nC<aCooSysList.getLength(); ++nC )
789 if( AxisHelper::getIndicesForAxis( xAxis, aCooSysList[nC], rOutDimensionIndex, rOutAxisIndex ) )
791 rOutCooSysIndex = nC;
792 return true;
797 return false;
800 std::vector< Reference< XAxis > > AxisHelper::getAllAxesOfCoordinateSystem(
801 const Reference< XCoordinateSystem >& xCooSys
802 , bool bOnlyVisible /* = false */ )
804 std::vector< Reference< XAxis > > aAxisVector;
806 if(xCooSys.is())
808 sal_Int32 nMaxDimensionIndex = xCooSys->getDimension() -1;
809 if( nMaxDimensionIndex>=0 )
811 sal_Int32 nDimensionIndex = 0;
812 for(; nDimensionIndex<=nMaxDimensionIndex; ++nDimensionIndex)
814 const sal_Int32 nMaximumAxisIndex = xCooSys->getMaximumAxisIndexByDimension(nDimensionIndex);
815 for(sal_Int32 nAxisIndex=0; nAxisIndex<=nMaximumAxisIndex; ++nAxisIndex)
819 Reference< XAxis > xAxis( xCooSys->getAxisByDimension( nDimensionIndex, nAxisIndex ) );
820 if( xAxis.is() )
822 bool bAddAxis = true;
823 if( bOnlyVisible )
825 Reference< beans::XPropertySet > xAxisProp( xAxis, uno::UNO_QUERY );
826 if( !xAxisProp.is() ||
827 !(xAxisProp->getPropertyValue( "Show") >>= bAddAxis) )
828 bAddAxis = false;
830 if( bAddAxis )
831 aAxisVector.push_back( xAxis );
834 catch( const uno::Exception & )
836 DBG_UNHANDLED_EXCEPTION("chart2");
843 return aAxisVector;
846 Sequence< Reference< XAxis > > AxisHelper::getAllAxesOfDiagram(
847 const Reference< XDiagram >& xDiagram
848 , bool bOnlyVisible )
850 std::vector< Reference< XAxis > > aAxisVector;
852 Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY );
853 if(xCooSysContainer.is())
855 Sequence< Reference< XCoordinateSystem > > aCooSysList = xCooSysContainer->getCoordinateSystems();
856 sal_Int32 nC = 0;
857 for( nC=0; nC<aCooSysList.getLength(); ++nC )
859 std::vector< Reference< XAxis > > aAxesPerCooSys( AxisHelper::getAllAxesOfCoordinateSystem( aCooSysList[nC], bOnlyVisible ) );
860 aAxisVector.insert( aAxisVector.end(), aAxesPerCooSys.begin(), aAxesPerCooSys.end() );
864 return comphelper::containerToSequence( aAxisVector );
867 Sequence< Reference< beans::XPropertySet > > AxisHelper::getAllGrids( const Reference< XDiagram >& xDiagram )
869 Sequence< Reference< XAxis > > aAllAxes( AxisHelper::getAllAxesOfDiagram( xDiagram ) );
870 std::vector< Reference< beans::XPropertySet > > aGridVector;
872 sal_Int32 nA = 0;
873 for( nA=0; nA<aAllAxes.getLength(); ++nA )
875 Reference< XAxis > xAxis( aAllAxes[nA] );
876 if(!xAxis.is())
877 continue;
878 Reference< beans::XPropertySet > xGridProperties( xAxis->getGridProperties() );
879 if( xGridProperties.is() )
880 aGridVector.push_back( xGridProperties );
882 Sequence< Reference< beans::XPropertySet > > aSubGrids( xAxis->getSubGridProperties() );
883 sal_Int32 nSubGrid = 0;
884 for( nSubGrid = 0; nSubGrid < aSubGrids.getLength(); ++nSubGrid )
886 Reference< beans::XPropertySet > xSubGrid( aSubGrids[nSubGrid] );
887 if( xSubGrid.is() )
888 aGridVector.push_back( xSubGrid );
892 return comphelper::containerToSequence( aGridVector );
895 void AxisHelper::getAxisOrGridPossibilities( Sequence< sal_Bool >& rPossibilityList
896 , const Reference< XDiagram>& xDiagram, bool bAxis )
898 rPossibilityList.realloc(6);
900 sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram );
902 //set possibilities:
903 sal_Int32 nIndex=0;
904 Reference< XChartType > xChartType = DiagramHelper::getChartTypeByIndex( xDiagram, 0 );
905 for(nIndex=0;nIndex<3;nIndex++)
906 rPossibilityList[nIndex]=ChartTypeHelper::isSupportingMainAxis(xChartType,nDimensionCount,nIndex);
907 for(nIndex=3;nIndex<6;nIndex++)
908 if( bAxis )
909 rPossibilityList[nIndex]=ChartTypeHelper::isSupportingSecondaryAxis(xChartType,nDimensionCount);
910 else
911 rPossibilityList[nIndex] = rPossibilityList[nIndex-3];
914 bool AxisHelper::isSecondaryYAxisNeeded( const Reference< XCoordinateSystem >& xCooSys )
916 Reference< chart2::XChartTypeContainer > xCTCnt( xCooSys, uno::UNO_QUERY );
917 if( xCTCnt.is() )
919 Sequence< Reference< chart2::XChartType > > aChartTypes( xCTCnt->getChartTypes() );
920 for( sal_Int32 i=0; i<aChartTypes.getLength(); ++i )
922 Reference< XDataSeriesContainer > xSeriesContainer( aChartTypes[i] , uno::UNO_QUERY );
923 if( !xSeriesContainer.is() )
924 continue;
926 Sequence< Reference< XDataSeries > > aSeriesList( xSeriesContainer->getDataSeries() );
927 for( sal_Int32 nS = aSeriesList.getLength(); nS-- ; )
929 Reference< beans::XPropertySet > xProp( aSeriesList[nS], uno::UNO_QUERY );
930 if(xProp.is())
932 sal_Int32 nAttachedAxisIndex = 0;
933 if( ( xProp->getPropertyValue( "AttachedAxisIndex" ) >>= nAttachedAxisIndex ) && nAttachedAxisIndex>0 )
934 return true;
939 return false;
942 bool AxisHelper::shouldAxisBeDisplayed( const Reference< XAxis >& xAxis
943 , const Reference< XCoordinateSystem >& xCooSys )
945 bool bRet = false;
947 if( xAxis.is() && xCooSys.is() )
949 sal_Int32 nDimensionIndex=-1;
950 sal_Int32 nAxisIndex=-1;
951 if( AxisHelper::getIndicesForAxis( xAxis, xCooSys, nDimensionIndex, nAxisIndex ) )
953 sal_Int32 nDimensionCount = xCooSys->getDimension();
954 Reference< XChartType > xChartType( AxisHelper::getChartTypeByIndex( xCooSys, 0 ) );
956 bool bMainAxis = (nAxisIndex==MAIN_AXIS_INDEX);
957 if( bMainAxis )
958 bRet = ChartTypeHelper::isSupportingMainAxis(xChartType,nDimensionCount,nDimensionIndex);
959 else
960 bRet = ChartTypeHelper::isSupportingSecondaryAxis(xChartType,nDimensionCount);
964 return bRet;
967 void AxisHelper::getAxisOrGridExcistence( Sequence< sal_Bool >& rExistenceList
968 , const Reference< XDiagram>& xDiagram, bool bAxis )
970 rExistenceList.realloc(6);
972 if(bAxis)
974 sal_Int32 nN;
975 for(nN=0;nN<3;nN++)
976 rExistenceList[nN] = AxisHelper::isAxisShown( nN, true, xDiagram );
977 for(nN=3;nN<6;nN++)
978 rExistenceList[nN] = AxisHelper::isAxisShown( nN%3, false, xDiagram );
980 else
982 sal_Int32 nN;
984 for(nN=0;nN<3;nN++)
985 rExistenceList[nN] = AxisHelper::isGridShown( nN, 0, true, xDiagram );
986 for(nN=3;nN<6;nN++)
987 rExistenceList[nN] = AxisHelper::isGridShown( nN%3, 0, false, xDiagram );
991 bool AxisHelper::changeVisibilityOfAxes( const Reference< XDiagram >& xDiagram
992 , const Sequence< sal_Bool >& rOldExistenceList
993 , const Sequence< sal_Bool >& rNewExistenceList
994 , const Reference< uno::XComponentContext >& xContext
995 , ReferenceSizeProvider * pRefSizeProvider )
997 bool bChanged = false;
998 for(sal_Int32 nN=0;nN<6;nN++)
1000 if(rOldExistenceList[nN]!=rNewExistenceList[nN])
1002 bChanged = true;
1003 if(rNewExistenceList[nN])
1005 AxisHelper::showAxis( nN%3, nN<3, xDiagram, xContext, pRefSizeProvider );
1007 else
1008 AxisHelper::hideAxis( nN%3, nN<3, xDiagram );
1011 return bChanged;
1014 bool AxisHelper::changeVisibilityOfGrids( const Reference< XDiagram >& xDiagram
1015 , const Sequence< sal_Bool >& rOldExistenceList
1016 , const Sequence< sal_Bool >& rNewExistenceList )
1018 bool bChanged = false;
1019 for(sal_Int32 nN=0;nN<6;nN++)
1021 if(rOldExistenceList[nN]!=rNewExistenceList[nN])
1023 bChanged = true;
1024 if(rNewExistenceList[nN])
1025 AxisHelper::showGrid( nN%3, 0, nN<3, xDiagram );
1026 else
1027 AxisHelper::hideGrid( nN%3, 0, nN<3, xDiagram );
1030 return bChanged;
1033 Reference< XCoordinateSystem > AxisHelper::getCoordinateSystemOfAxis(
1034 const Reference< XAxis >& xAxis
1035 , const Reference< XDiagram >& xDiagram )
1037 Reference< XCoordinateSystem > xRet;
1039 Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY );
1040 if( xCooSysContainer.is() )
1042 Reference< XCoordinateSystem > xCooSys;
1043 Sequence< Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() );
1044 for( sal_Int32 nCooSysIndex = 0; nCooSysIndex < aCooSysList.getLength(); ++nCooSysIndex )
1046 xCooSys = aCooSysList[nCooSysIndex];
1047 std::vector< Reference< XAxis > > aAllAxis( AxisHelper::getAllAxesOfCoordinateSystem( xCooSys ) );
1049 std::vector< Reference< XAxis > >::iterator aFound =
1050 std::find( aAllAxis.begin(), aAllAxis.end(), xAxis );
1051 if( aFound != aAllAxis.end())
1053 xRet.set( xCooSys );
1054 break;
1058 return xRet;
1061 Reference< XChartType > AxisHelper::getChartTypeByIndex( const Reference< XCoordinateSystem >& xCooSys, sal_Int32 nIndex )
1063 Reference< XChartType > xChartType;
1065 Reference< XChartTypeContainer > xChartTypeContainer( xCooSys, uno::UNO_QUERY );
1066 if( xChartTypeContainer.is() )
1068 Sequence< Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() );
1069 if( nIndex >= 0 && nIndex < aChartTypeList.getLength() )
1070 xChartType.set( aChartTypeList[nIndex] );
1073 return xChartType;
1076 void AxisHelper::setRTLAxisLayout( const Reference< XCoordinateSystem >& xCooSys )
1078 if( xCooSys.is() )
1080 bool bCartesian = xCooSys->getViewServiceName() == CHART2_COOSYSTEM_CARTESIAN_VIEW_SERVICE_NAME;
1081 if( bCartesian )
1083 bool bVertical = false;
1084 Reference< beans::XPropertySet > xCooSysProp( xCooSys, uno::UNO_QUERY );
1085 if( xCooSysProp.is() )
1086 xCooSysProp->getPropertyValue( "SwapXAndYAxis" ) >>= bVertical;
1088 sal_Int32 nHorizontalAxisDimension = bVertical ? 1 : 0;
1089 sal_Int32 nVerticalAxisDimension = bVertical ? 0 : 1;
1093 //reverse direction for horizontal main axis
1094 Reference< chart2::XAxis > xHorizontalMainAxis( AxisHelper::getAxis( nHorizontalAxisDimension, MAIN_AXIS_INDEX, xCooSys ) );
1095 if( xHorizontalMainAxis.is() )
1097 chart2::ScaleData aScale = xHorizontalMainAxis->getScaleData();
1098 aScale.Orientation = chart2::AxisOrientation_REVERSE;
1099 xHorizontalMainAxis->setScaleData(aScale);
1102 //mathematical direction for vertical main axis
1103 Reference< chart2::XAxis > xVerticalMainAxis( AxisHelper::getAxis( nVerticalAxisDimension, MAIN_AXIS_INDEX, xCooSys ) );
1104 if( xVerticalMainAxis.is() )
1106 chart2::ScaleData aScale = xVerticalMainAxis->getScaleData();
1107 aScale.Orientation = chart2::AxisOrientation_MATHEMATICAL;
1108 xVerticalMainAxis->setScaleData(aScale);
1111 catch( const uno::Exception & )
1113 DBG_UNHANDLED_EXCEPTION("chart2" );
1118 //reverse direction for horizontal secondary axis
1119 Reference< chart2::XAxis > xHorizontalSecondaryAxis( AxisHelper::getAxis( nHorizontalAxisDimension, SECONDARY_AXIS_INDEX, xCooSys ) );
1120 if( xHorizontalSecondaryAxis.is() )
1122 chart2::ScaleData aScale = xHorizontalSecondaryAxis->getScaleData();
1123 aScale.Orientation = chart2::AxisOrientation_REVERSE;
1124 xHorizontalSecondaryAxis->setScaleData(aScale);
1127 //mathematical direction for vertical secondary axis
1128 Reference< chart2::XAxis > xVerticalSecondaryAxis( AxisHelper::getAxis( nVerticalAxisDimension, SECONDARY_AXIS_INDEX, xCooSys ) );
1129 if( xVerticalSecondaryAxis.is() )
1131 chart2::ScaleData aScale = xVerticalSecondaryAxis->getScaleData();
1132 aScale.Orientation = chart2::AxisOrientation_MATHEMATICAL;
1133 xVerticalSecondaryAxis->setScaleData(aScale);
1136 catch( const uno::Exception & )
1138 DBG_UNHANDLED_EXCEPTION("chart2");
1144 Reference< XChartType > AxisHelper::getFirstChartTypeWithSeriesAttachedToAxisIndex( const Reference< chart2::XDiagram >& xDiagram, const sal_Int32 nAttachedAxisIndex )
1146 Reference< XChartType > xChartType;
1147 std::vector< Reference< XDataSeries > > aSeriesVector( DiagramHelper::getDataSeriesFromDiagram( xDiagram ) );
1148 for (auto const& series : aSeriesVector)
1150 sal_Int32 nCurrentIndex = DataSeriesHelper::getAttachedAxisIndex(series);
1151 if( nAttachedAxisIndex == nCurrentIndex )
1153 xChartType = DiagramHelper::getChartTypeOfSeries(xDiagram, series);
1154 if(xChartType.is())
1155 break;
1158 return xChartType;
1161 bool AxisHelper::isAxisPositioningEnabled()
1163 const SvtSaveOptions::ODFSaneDefaultVersion nCurrentVersion(SvtSaveOptions().GetODFSaneDefaultVersion());
1164 return nCurrentVersion >= SvtSaveOptions::ODFSVER_012;
1167 } //namespace chart
1169 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */