1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <AxisHelper.hxx>
21 #include <DiagramHelper.hxx>
22 #include <Diagram.hxx>
23 #include <ChartTypeHelper.hxx>
24 #include <ChartType.hxx>
26 #include <AxisIndexDefines.hxx>
27 #include <DataSource.hxx>
28 #include <LinePropertiesHelper.hxx>
29 #include <servicenames_coosystems.hxx>
30 #include <DataSeries.hxx>
31 #include <DataSeriesHelper.hxx>
32 #include <Scaling.hxx>
33 #include <ChartModel.hxx>
34 #include <ChartModelHelper.hxx>
35 #include <DataSourceHelper.hxx>
36 #include <ReferenceSizeProvider.hxx>
37 #include <ExplicitCategoriesProvider.hxx>
38 #include <unonames.hxx>
39 #include <BaseCoordinateSystem.hxx>
40 #include <GridProperties.hxx>
42 #include <o3tl/safeint.hxx>
43 #include <unotools/saveopt.hxx>
45 #include <com/sun/star/chart/ChartAxisPosition.hpp>
46 #include <com/sun/star/chart2/AxisType.hpp>
48 #include <sal/log.hxx>
50 #include <com/sun/star/lang/XServiceName.hpp>
51 #include <com/sun/star/uno/XComponentContext.hpp>
52 #include <comphelper/diagnose_ex.hxx>
59 using namespace ::com::sun::star
;
60 using namespace ::com::sun::star::chart2
;
61 using ::com::sun::star::uno::Reference
;
62 using ::com::sun::star::uno::Sequence
;
64 Reference
< chart2::XScaling
> AxisHelper::createLinearScaling()
66 return new LinearScaling( 1.0, 0.0 );
69 Reference
< chart2::XScaling
> AxisHelper::createLogarithmicScaling( double fBase
)
71 return new LogarithmicScaling( fBase
);
74 ScaleData
AxisHelper::createDefaultScale()
77 aScaleData
.AxisType
= chart2::AxisType::REALNUMBER
;
78 aScaleData
.AutoDateAxis
= true;
79 aScaleData
.ShiftedCategoryPosition
= false;
80 aScaleData
.IncrementData
.SubIncrements
= { SubIncrement() };
84 void AxisHelper::removeExplicitScaling( ScaleData
& rScaleData
)
86 rScaleData
.Minimum
= rScaleData
.Maximum
= rScaleData
.Origin
= uno::Any();
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 rtl::Reference
< Axis
>& xAxis
, ChartModel
& rModel
)
102 ScaleData aScale
= xAxis
->getScaleData();
103 rtl::Reference
< BaseCoordinateSystem
> 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
;
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 rtl::Reference
< Axis
>& xAxis
137 , const rtl::Reference
< BaseCoordinateSystem
> & xCorrespondingCoordinateSystem
138 , const rtl::Reference
<ChartModel
>& 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
);
149 bool bLinkToSource
= true;
150 xAxis
->getPropertyValue(CHART_UNONAME_LINK_TO_SRC_NUMFMT
) >>= bLinkToSource
;
151 xAxis
->getPropertyValue(CHART_UNONAME_NUMFMT
) >>= nNumberFormatKey
;
155 bool bFormatSet
= false;
156 //check whether we have a percent scale -> use percent format
159 ScaleData aData
= AxisHelper::getDateCheckedScale( xAxis
, *xChartDoc
);
160 if( aData
.AxisType
==AxisType::PERCENT
)
162 sal_Int32 nPercentFormat
= DiagramHelper::getPercentNumberFormat( xChartDoc
);
163 if( nPercentFormat
!= -1 )
165 nNumberFormatKey
= nPercentFormat
;
169 else if( aData
.AxisType
==AxisType::DATE
)
171 if( aData
.Categories
.is() )
173 Reference
< data::XDataSequence
> xSeq( aData
.Categories
->getValues());
174 if( xSeq
.is() && !( xChartDoc
.is() && xChartDoc
->hasInternalDataProvider()) )
175 nNumberFormatKey
= xSeq
->getNumberFormatKeyByIndex( -1 );
177 nNumberFormatKey
= DiagramHelper::getDateNumberFormat( xChartDoc
);
181 else if( xChartDoc
.is() && xChartDoc
->hasInternalDataProvider() && nDimensionIndex
== 0 ) //maybe date axis
183 rtl::Reference
< Diagram
> xDiagram( xChartDoc
->getFirstChartDiagram() );
184 if( xDiagram
->isSupportingDateAxis() )
186 nNumberFormatKey
= DiagramHelper::getDateNumberFormat( xChartDoc
);
190 rtl::Reference
< DataSource
> xSource
= DataSourceHelper::getUsedData( *xChartDoc
);
193 std::vector
< uno::Reference
< chart2::data::XLabeledDataSequence
> > aXValues(
194 DataSeriesHelper::getAllDataSequencesByRole( xSource
->getDataSequences(), u
"values-x"_ustr
) );
195 if( aXValues
.empty() )
197 uno::Reference
< chart2::data::XLabeledDataSequence
> xCategories( xDiagram
->getCategories() );
198 if( xCategories
.is() )
200 Reference
< data::XDataSequence
> xSeq( xCategories
->getValues());
203 bool bHasValidDoubles
= false;
205 Sequence
< uno::Any
> aCats( xSeq
->getData() );
206 sal_Int32 nCount
= aCats
.getLength();
207 for( sal_Int32 i
= 0; i
< nCount
; ++i
)
209 if( (aCats
[i
]>>=fTest
) && !std::isnan(fTest
) )
211 bHasValidDoubles
=true;
215 if( bHasValidDoubles
)
216 nNumberFormatKey
= DiagramHelper::getDateNumberFormat( xChartDoc
);
228 std::map
< sal_Int32
, sal_Int32
> aKeyMap
;
229 bool bNumberFormatKeyFoundViaAttachedData
= false;
233 OUString aRoleToMatch
;
234 if( nDimensionIndex
== 0 )
235 aRoleToMatch
= "values-x";
236 const std::vector
< rtl::Reference
< ChartType
> > & aChartTypes( xCorrespondingCoordinateSystem
->getChartTypes2());
237 for( rtl::Reference
< ChartType
> const & chartType
: aChartTypes
)
239 if( nDimensionIndex
!= 0 )
240 aRoleToMatch
= ChartTypeHelper::getRoleOfSequenceForYAxisNumberFormatDetection( chartType
);
241 for( rtl::Reference
< DataSeries
> const & xDataSeries
: chartType
->getDataSeries2() )
243 if( nDimensionIndex
== 1 )
245 //only take those series into account that are attached to this axis
246 sal_Int32 nAttachedAxisIndex
= DataSeriesHelper::getAttachedAxisIndex(xDataSeries
);
247 if( nAttachedAxisIndex
!= nAxisIndex
)
251 Reference
< data::XLabeledDataSequence
> xLabeledSeq(
252 DataSeriesHelper::getDataSequenceByRole( xDataSeries
, aRoleToMatch
) );
254 if( !xLabeledSeq
.is() && nDimensionIndex
==0 )
256 ScaleData aData
= xAxis
->getScaleData();
257 xLabeledSeq
= aData
.Categories
;
260 if( xLabeledSeq
.is() )
262 Reference
< data::XDataSequence
> xSeq( xLabeledSeq
->getValues());
265 sal_Int32 nKey
= xSeq
->getNumberFormatKeyByIndex( -1 );
266 // increase frequency
273 catch( const uno::Exception
& )
275 DBG_UNHANDLED_EXCEPTION("chart2");
278 if( ! aKeyMap
.empty())
280 sal_Int32 nMaxFreq
= 0;
281 // find most frequent key
282 for (auto const& elem
: aKeyMap
)
286 "NumberFormatKey " << elem
.first
<< " appears "
287 << elem
.second
<< " times");
288 // all values must at least be 1
289 if( elem
.second
> nMaxFreq
)
291 nNumberFormatKey
= elem
.first
;
292 bNumberFormatKeyFoundViaAttachedData
= true;
293 nMaxFreq
= elem
.second
;
298 if( bSearchForParallelAxisIfNothingIsFound
)
300 //no format is set to this axis and no data is set to this axis
301 //--> try to obtain the format from the parallel y-axis
302 if( !bNumberFormatKeyFoundViaAttachedData
&& nDimensionIndex
== 1 )
304 sal_Int32 nParallelAxisIndex
= (nAxisIndex
==1) ?0 :1;
305 rtl::Reference
< Axis
> xParallelAxis
= AxisHelper::getAxis( 1, nParallelAxisIndex
, xCorrespondingCoordinateSystem
);
306 nNumberFormatKey
= AxisHelper::getExplicitNumberFormatKeyForAxis(xParallelAxis
, xCorrespondingCoordinateSystem
, xChartDoc
, false);
312 return nNumberFormatKey
;
315 rtl::Reference
< Axis
> AxisHelper::createAxis(
316 sal_Int32 nDimensionIndex
317 , sal_Int32 nAxisIndex
// 0==main or 1==secondary axis
318 , const rtl::Reference
< BaseCoordinateSystem
>& xCooSys
319 , const Reference
< uno::XComponentContext
> & xContext
320 , ReferenceSizeProvider
* pRefSizeProvider
)
322 if( !xContext
.is() || !xCooSys
.is() )
324 if( nDimensionIndex
>= xCooSys
->getDimension() )
327 rtl::Reference
< Axis
> xAxis
= new Axis();
329 xCooSys
->setAxisByDimension( nDimensionIndex
, xAxis
, nAxisIndex
);
331 if( nAxisIndex
>0 )//when inserting secondary axes copy some things from the main axis
333 css::chart::ChartAxisPosition
eNewAxisPos( css::chart::ChartAxisPosition_END
);
335 rtl::Reference
< Axis
> xMainAxis
= xCooSys
->getAxisByDimension2( nDimensionIndex
, 0 );
338 ScaleData aScale
= xAxis
->getScaleData();
339 ScaleData aMainScale
= xMainAxis
->getScaleData();
341 aScale
.AxisType
= aMainScale
.AxisType
;
342 aScale
.AutoDateAxis
= aMainScale
.AutoDateAxis
;
343 aScale
.Categories
= aMainScale
.Categories
;
344 aScale
.Orientation
= aMainScale
.Orientation
;
345 aScale
.ShiftedCategoryPosition
= aMainScale
.ShiftedCategoryPosition
;
347 xAxis
->setScaleData( aScale
);
349 //ensure that the second axis is not placed on the main axis
350 css::chart::ChartAxisPosition
eMainAxisPos( css::chart::ChartAxisPosition_ZERO
);
351 xMainAxis
->getPropertyValue(u
"CrossoverPosition"_ustr
) >>= eMainAxisPos
;
352 if( eMainAxisPos
== css::chart::ChartAxisPosition_END
)
353 eNewAxisPos
= css::chart::ChartAxisPosition_START
;
356 xAxis
->setPropertyValue(u
"CrossoverPosition"_ustr
, uno::Any(eNewAxisPos
) );
361 // set correct initial AutoScale
362 if( pRefSizeProvider
)
363 pRefSizeProvider
->setValuesAtPropertySet( xAxis
);
365 catch( const uno::Exception
& )
367 TOOLS_WARN_EXCEPTION("chart2", "" );
372 rtl::Reference
< Axis
> AxisHelper::createAxis( sal_Int32 nDimensionIndex
, bool bMainAxis
373 , const rtl::Reference
< Diagram
>& xDiagram
374 , const Reference
< uno::XComponentContext
>& xContext
375 , ReferenceSizeProvider
* pRefSizeProvider
)
377 OSL_ENSURE( xContext
.is(), "need a context to create an axis" );
381 sal_Int32 nAxisIndex
= bMainAxis
? MAIN_AXIS_INDEX
: SECONDARY_AXIS_INDEX
;
382 rtl::Reference
< BaseCoordinateSystem
> xCooSys
= AxisHelper::getCoordinateSystemByIndex( xDiagram
, 0 );
385 return AxisHelper::createAxis(
386 nDimensionIndex
, nAxisIndex
, xCooSys
, xContext
, pRefSizeProvider
);
389 void AxisHelper::showAxis( sal_Int32 nDimensionIndex
, bool bMainAxis
390 , const rtl::Reference
< Diagram
>& xDiagram
391 , const Reference
< uno::XComponentContext
>& xContext
392 , ReferenceSizeProvider
* pRefSizeProvider
)
397 bool bNewAxisCreated
= false;
398 rtl::Reference
< Axis
> xAxis
= AxisHelper::getAxis( nDimensionIndex
, bMainAxis
, xDiagram
);
399 if( !xAxis
.is() && xContext
.is() )
402 bNewAxisCreated
= true;
403 xAxis
= AxisHelper::createAxis( nDimensionIndex
, bMainAxis
, xDiagram
, xContext
, pRefSizeProvider
);
406 OSL_ASSERT( xAxis
.is());
407 if( !bNewAxisCreated
) //default is true already if created
408 AxisHelper::makeAxisVisible( xAxis
);
411 void AxisHelper::showGrid( sal_Int32 nDimensionIndex
, sal_Int32 nCooSysIndex
, bool bMainGrid
412 , const rtl::Reference
< Diagram
>& xDiagram
)
417 rtl::Reference
< BaseCoordinateSystem
> xCooSys
= AxisHelper::getCoordinateSystemByIndex( xDiagram
, nCooSysIndex
);
421 rtl::Reference
< Axis
> xAxis
= AxisHelper::getAxis( nDimensionIndex
, MAIN_AXIS_INDEX
, xCooSys
);
424 //hhhh todo create axis without axis visibility
429 AxisHelper::makeGridVisible( xAxis
->getGridProperties2() );
432 std::vector
< rtl::Reference
< GridProperties
> > aSubGrids( xAxis
->getSubGridProperties2() );
433 for( auto const & i
: aSubGrids
)
434 AxisHelper::makeGridVisible( i
);
438 void AxisHelper::makeAxisVisible( const rtl::Reference
< Axis
>& xAxis
)
442 xAxis
->setPropertyValue( u
"Show"_ustr
, uno::Any( true ) );
443 LinePropertiesHelper::SetLineVisible( xAxis
);
444 xAxis
->setPropertyValue( u
"DisplayLabels"_ustr
, uno::Any( true ) );
448 void AxisHelper::makeGridVisible( const rtl::Reference
< GridProperties
>& xGridProperties
)
450 if( xGridProperties
.is() )
452 xGridProperties
->setPropertyValue( u
"Show"_ustr
, uno::Any( true ) );
453 LinePropertiesHelper::SetLineVisible( xGridProperties
);
457 void AxisHelper::hideAxis( sal_Int32 nDimensionIndex
, bool bMainAxis
458 , const rtl::Reference
< Diagram
>& xDiagram
)
460 AxisHelper::makeAxisInvisible( AxisHelper::getAxis( nDimensionIndex
, bMainAxis
, xDiagram
) );
463 void AxisHelper::makeAxisInvisible( const rtl::Reference
< Axis
>& xAxis
)
467 xAxis
->setPropertyValue( u
"Show"_ustr
, uno::Any( false ) );
471 void AxisHelper::hideAxisIfNoDataIsAttached( const rtl::Reference
< Axis
>& xAxis
, const rtl::Reference
< Diagram
>& xDiagram
)
473 //axis is hidden if no data is attached anymore but data is available
474 bool bOtherSeriesAttachedToThisAxis
= false;
475 std::vector
< rtl::Reference
< DataSeries
> > aSeriesVector
= xDiagram
->getDataSeries();
476 for (auto const& series
: aSeriesVector
)
478 rtl::Reference
< Axis
> xCurrentAxis
= xDiagram
->getAttachedAxis(series
);
479 if( xCurrentAxis
==xAxis
)
481 bOtherSeriesAttachedToThisAxis
= true;
485 if(!bOtherSeriesAttachedToThisAxis
&& !aSeriesVector
.empty() )
486 AxisHelper::makeAxisInvisible( xAxis
);
489 void AxisHelper::hideGrid( sal_Int32 nDimensionIndex
, sal_Int32 nCooSysIndex
, bool bMainGrid
490 , const rtl::Reference
< Diagram
>& xDiagram
)
495 rtl::Reference
< BaseCoordinateSystem
> xCooSys
= AxisHelper::getCoordinateSystemByIndex( xDiagram
, nCooSysIndex
);
499 rtl::Reference
< Axis
> xAxis
= AxisHelper::getAxis( nDimensionIndex
, MAIN_AXIS_INDEX
, xCooSys
);
504 AxisHelper::makeGridInvisible( xAxis
->getGridProperties2() );
507 std::vector
< rtl::Reference
< ::chart::GridProperties
> > aSubGrids( xAxis
->getSubGridProperties2() );
508 for( auto const & i
: aSubGrids
)
509 AxisHelper::makeGridInvisible( i
);
513 void AxisHelper::makeGridInvisible( const rtl::Reference
< ::chart::GridProperties
>& xGridProperties
)
515 if( xGridProperties
.is() )
517 xGridProperties
->setPropertyValue( u
"Show"_ustr
, uno::Any( false ) );
521 bool AxisHelper::isGridShown( sal_Int32 nDimensionIndex
, sal_Int32 nCooSysIndex
, bool bMainGrid
522 , const rtl::Reference
< Diagram
>& xDiagram
)
526 rtl::Reference
< BaseCoordinateSystem
> xCooSys
= AxisHelper::getCoordinateSystemByIndex( xDiagram
, nCooSysIndex
);
530 rtl::Reference
< Axis
> xAxis
= AxisHelper::getAxis( nDimensionIndex
, MAIN_AXIS_INDEX
, xCooSys
);
535 bRet
= AxisHelper::isGridVisible( xAxis
->getGridProperties2() );
538 std::vector
< rtl::Reference
< ::chart::GridProperties
> > aSubGrids( xAxis
->getSubGridProperties2() );
539 if( !aSubGrids
.empty() )
540 bRet
= AxisHelper::isGridVisible( aSubGrids
[0] );
546 rtl::Reference
< ::chart::BaseCoordinateSystem
> AxisHelper::getCoordinateSystemByIndex(
547 const rtl::Reference
< Diagram
>& xDiagram
, sal_Int32 nIndex
)
551 auto aCooSysList
= xDiagram
->getBaseCoordinateSystems();
552 if(0<=nIndex
&& o3tl::make_unsigned(nIndex
) < aCooSysList
.size())
553 return aCooSysList
[nIndex
];
557 rtl::Reference
< Axis
> AxisHelper::getAxis( sal_Int32 nDimensionIndex
, bool bMainAxis
558 , const rtl::Reference
< Diagram
>& xDiagram
)
560 rtl::Reference
< Axis
> xRet
;
563 rtl::Reference
< BaseCoordinateSystem
> xCooSys
= AxisHelper::getCoordinateSystemByIndex( xDiagram
, 0 );
564 xRet
= AxisHelper::getAxis( nDimensionIndex
, bMainAxis
? 0 : 1, xCooSys
);
566 catch( const uno::Exception
& )
572 rtl::Reference
< Axis
> AxisHelper::getAxis( sal_Int32 nDimensionIndex
, sal_Int32 nAxisIndex
573 , const rtl::Reference
< BaseCoordinateSystem
>& xCooSys
)
575 rtl::Reference
< Axis
> xRet
;
579 if(nDimensionIndex
>= xCooSys
->getDimension())
582 if(nAxisIndex
> xCooSys
->getMaximumAxisIndexByDimension(nDimensionIndex
))
585 assert(nAxisIndex
>= 0);
586 assert(nDimensionIndex
>= 0);
587 xRet
= xCooSys
->getAxisByDimension2( nDimensionIndex
, nAxisIndex
);
591 rtl::Reference
< Axis
> AxisHelper::getCrossingMainAxis( const rtl::Reference
< Axis
>& xAxis
592 , const rtl::Reference
< BaseCoordinateSystem
>& xCooSys
)
594 sal_Int32 nDimensionIndex
= 0;
595 sal_Int32 nAxisIndex
= 0;
596 AxisHelper::getIndicesForAxis( xAxis
, xCooSys
, nDimensionIndex
, nAxisIndex
);
597 if( nDimensionIndex
==2 )
600 bool bSwapXY
= false;
601 if( (xCooSys
->getPropertyValue( u
"SwapXAndYAxis"_ustr
) >>= bSwapXY
) && bSwapXY
)
604 else if( nDimensionIndex
==1 )
608 return AxisHelper::getAxis( nDimensionIndex
, 0, xCooSys
);
611 rtl::Reference
< Axis
> AxisHelper::getParallelAxis( const rtl::Reference
< Axis
>& xAxis
612 , const rtl::Reference
< Diagram
>& xDiagram
)
616 sal_Int32 nCooSysIndex
=-1;
617 sal_Int32 nDimensionIndex
=-1;
618 sal_Int32 nAxisIndex
=-1;
619 if( getIndicesForAxis( xAxis
, xDiagram
, nCooSysIndex
, nDimensionIndex
, nAxisIndex
) )
621 sal_Int32 nParallelAxisIndex
= (nAxisIndex
==1) ?0 :1;
622 return getAxis( nDimensionIndex
, nParallelAxisIndex
, getCoordinateSystemByIndex( xDiagram
, nCooSysIndex
) );
625 catch( const uno::RuntimeException
& )
631 bool AxisHelper::isAxisShown( sal_Int32 nDimensionIndex
, bool bMainAxis
632 , const rtl::Reference
< Diagram
>& xDiagram
)
634 return AxisHelper::isAxisVisible( AxisHelper::getAxis( nDimensionIndex
, bMainAxis
, xDiagram
) );
637 bool AxisHelper::isAxisVisible( const rtl::Reference
< Axis
>& xAxis
)
643 xAxis
->getPropertyValue( u
"Show"_ustr
) >>= bRet
;
644 bRet
= bRet
&& ( LinePropertiesHelper::IsLineVisible( xAxis
)
645 || areAxisLabelsVisible( xAxis
) );
651 bool AxisHelper::areAxisLabelsVisible( const rtl::Reference
< Axis
>& xAxis
)
656 xAxis
->getPropertyValue( u
"DisplayLabels"_ustr
) >>= bRet
;
661 bool AxisHelper::isGridVisible( const rtl::Reference
< ::chart::GridProperties
>& xGridproperties
)
665 if( xGridproperties
.is() )
667 xGridproperties
->getPropertyValue( u
"Show"_ustr
) >>= bRet
;
668 bRet
= bRet
&& LinePropertiesHelper::IsLineVisible( xGridproperties
);
674 rtl::Reference
< GridProperties
> AxisHelper::getGridProperties(
675 const rtl::Reference
< BaseCoordinateSystem
>& xCooSys
676 , sal_Int32 nDimensionIndex
, sal_Int32 nAxisIndex
, sal_Int32 nSubGridIndex
)
678 rtl::Reference
< GridProperties
> xRet
;
680 rtl::Reference
< Axis
> xAxis( AxisHelper::getAxis( nDimensionIndex
, nAxisIndex
, xCooSys
) );
683 if( nSubGridIndex
<0 )
684 xRet
= xAxis
->getGridProperties2();
687 std::vector
< rtl::Reference
< GridProperties
> > aSubGrids( xAxis
->getSubGridProperties2() );
688 if (nSubGridIndex
< static_cast<sal_Int32
>(aSubGrids
.size()))
689 xRet
= aSubGrids
[nSubGridIndex
];
696 sal_Int32
AxisHelper::getDimensionIndexOfAxis(
697 const rtl::Reference
< Axis
>& xAxis
698 , const rtl::Reference
< Diagram
>& xDiagram
)
700 sal_Int32 nDimensionIndex
= -1;
701 sal_Int32 nCooSysIndex
= -1;
702 sal_Int32 nAxisIndex
= -1;
703 AxisHelper::getIndicesForAxis( xAxis
, xDiagram
, nCooSysIndex
, nDimensionIndex
, nAxisIndex
);
704 return nDimensionIndex
;
707 bool AxisHelper::getIndicesForAxis(
708 const rtl::Reference
< Axis
>& xAxis
709 , const rtl::Reference
< BaseCoordinateSystem
>& xCooSys
710 , sal_Int32
& rOutDimensionIndex
, sal_Int32
& rOutAxisIndex
)
712 //returns true if indices are found
714 rOutDimensionIndex
= -1;
717 if( !xCooSys
|| !xAxis
)
720 rtl::Reference
< Axis
> xCurrentAxis
;
721 sal_Int32
nDimensionCount( xCooSys
->getDimension() );
722 for( sal_Int32 nDimensionIndex
= 0; nDimensionIndex
< nDimensionCount
; nDimensionIndex
++ )
724 sal_Int32 nMaxAxisIndex
= xCooSys
->getMaximumAxisIndexByDimension(nDimensionIndex
);
725 for( sal_Int32 nAxisIndex
= 0; nAxisIndex
<= nMaxAxisIndex
; nAxisIndex
++ )
727 xCurrentAxis
= xCooSys
->getAxisByDimension2(nDimensionIndex
,nAxisIndex
);
728 if( xCurrentAxis
== xAxis
)
730 rOutDimensionIndex
= nDimensionIndex
;
731 rOutAxisIndex
= nAxisIndex
;
739 bool AxisHelper::getIndicesForAxis( const rtl::Reference
< Axis
>& xAxis
, const rtl::Reference
< Diagram
>& xDiagram
740 , sal_Int32
& rOutCooSysIndex
, sal_Int32
& rOutDimensionIndex
, sal_Int32
& rOutAxisIndex
)
742 //returns true if indices are found
744 rOutCooSysIndex
= -1;
745 rOutDimensionIndex
= -1;
748 const std::vector
< rtl::Reference
< BaseCoordinateSystem
> > aCooSysList
= xDiagram
->getBaseCoordinateSystems();
749 for( std::size_t nC
=0; nC
< aCooSysList
.size(); ++nC
)
751 if( AxisHelper::getIndicesForAxis( xAxis
, aCooSysList
[nC
], rOutDimensionIndex
, rOutAxisIndex
) )
753 rOutCooSysIndex
= nC
;
761 std::vector
< rtl::Reference
< Axis
> > AxisHelper::getAllAxesOfCoordinateSystem(
762 const rtl::Reference
< BaseCoordinateSystem
>& xCooSys
763 , bool bOnlyVisible
/* = false */ )
765 std::vector
< rtl::Reference
< Axis
> > aAxisVector
;
769 sal_Int32 nMaxDimensionIndex
= xCooSys
->getDimension() -1;
770 if( nMaxDimensionIndex
>=0 )
772 sal_Int32 nDimensionIndex
= 0;
773 for(; nDimensionIndex
<=nMaxDimensionIndex
; ++nDimensionIndex
)
775 const sal_Int32 nMaximumAxisIndex
= xCooSys
->getMaximumAxisIndexByDimension(nDimensionIndex
);
776 for(sal_Int32 nAxisIndex
=0; nAxisIndex
<=nMaximumAxisIndex
; ++nAxisIndex
)
780 rtl::Reference
< Axis
> xAxis
= xCooSys
->getAxisByDimension2( nDimensionIndex
, nAxisIndex
);
783 bool bAddAxis
= true;
786 if( !(xAxis
->getPropertyValue( u
"Show"_ustr
) >>= bAddAxis
) )
790 aAxisVector
.push_back( xAxis
);
793 catch( const uno::Exception
& )
795 DBG_UNHANDLED_EXCEPTION("chart2");
805 std::vector
< rtl::Reference
< Axis
> > AxisHelper::getAllAxesOfDiagram(
806 const rtl::Reference
< Diagram
>& xDiagram
807 , bool bOnlyVisible
)
809 std::vector
< rtl::Reference
< Axis
> > aAxisVector
;
811 for( rtl::Reference
< BaseCoordinateSystem
> const & coords
: xDiagram
->getBaseCoordinateSystems() )
813 std::vector
< rtl::Reference
< Axis
> > aAxesPerCooSys
= AxisHelper::getAllAxesOfCoordinateSystem( coords
, bOnlyVisible
);
814 aAxisVector
.insert( aAxisVector
.end(), aAxesPerCooSys
.begin(), aAxesPerCooSys
.end() );
820 std::vector
< rtl::Reference
< GridProperties
> > AxisHelper::getAllGrids( const rtl::Reference
< Diagram
>& xDiagram
)
822 const std::vector
< rtl::Reference
< Axis
> > aAllAxes
= AxisHelper::getAllAxesOfDiagram( xDiagram
);
823 std::vector
< rtl::Reference
< GridProperties
> > aGridVector
;
825 for( rtl::Reference
< Axis
> const & xAxis
: aAllAxes
)
827 rtl::Reference
< GridProperties
> xGridProperties( xAxis
->getGridProperties2() );
828 if( xGridProperties
.is() )
829 aGridVector
.push_back( xGridProperties
);
831 std::vector
< rtl::Reference
< GridProperties
> > aSubGrids( xAxis
->getSubGridProperties2() );
832 for( rtl::Reference
< GridProperties
> const & xSubGrid
: aSubGrids
)
835 aGridVector
.push_back( xSubGrid
);
842 void AxisHelper::getAxisOrGridPossibilities( Sequence
< sal_Bool
>& rPossibilityList
843 , const rtl::Reference
< Diagram
>& xDiagram
, bool bAxis
)
845 rPossibilityList
.realloc(6);
846 sal_Bool
* pPossibilityList
= rPossibilityList
.getArray();
848 sal_Int32 nDimensionCount
= -1;
850 nDimensionCount
= xDiagram
->getDimension();
854 rtl::Reference
< ChartType
> xChartType
;
856 xChartType
= xDiagram
->getChartTypeByIndex( 0 );
857 for(nIndex
=0;nIndex
<3;nIndex
++)
858 pPossibilityList
[nIndex
]=ChartTypeHelper::isSupportingMainAxis(xChartType
,nDimensionCount
,nIndex
);
859 for(nIndex
=3;nIndex
<6;nIndex
++)
861 pPossibilityList
[nIndex
]=ChartTypeHelper::isSupportingSecondaryAxis(xChartType
,nDimensionCount
);
863 pPossibilityList
[nIndex
] = rPossibilityList
[nIndex
-3];
866 bool AxisHelper::isSecondaryYAxisNeeded( const rtl::Reference
< BaseCoordinateSystem
>& xCooSys
)
871 const std::vector
< rtl::Reference
< ChartType
> > & aChartTypes( xCooSys
->getChartTypes2() );
872 for( rtl::Reference
< ChartType
> const & chartType
: aChartTypes
)
874 const std::vector
< rtl::Reference
< DataSeries
> > & aSeriesList
= chartType
->getDataSeries2();
875 for( sal_Int32 nS
= aSeriesList
.size(); nS
-- ; )
877 sal_Int32 nAttachedAxisIndex
= 0;
878 if( ( aSeriesList
[nS
]->getPropertyValue( u
"AttachedAxisIndex"_ustr
) >>= nAttachedAxisIndex
) &&
879 nAttachedAxisIndex
>0 )
886 bool AxisHelper::shouldAxisBeDisplayed( const rtl::Reference
< Axis
>& xAxis
887 , const rtl::Reference
< BaseCoordinateSystem
>& xCooSys
)
891 if( xAxis
.is() && xCooSys
.is() )
893 sal_Int32 nDimensionIndex
=-1;
894 sal_Int32 nAxisIndex
=-1;
895 if( AxisHelper::getIndicesForAxis( xAxis
, xCooSys
, nDimensionIndex
, nAxisIndex
) )
897 sal_Int32 nDimensionCount
= xCooSys
->getDimension();
898 rtl::Reference
< ChartType
> xChartType( AxisHelper::getChartTypeByIndex( xCooSys
, 0 ) );
900 bool bMainAxis
= (nAxisIndex
==MAIN_AXIS_INDEX
);
902 bRet
= ChartTypeHelper::isSupportingMainAxis(xChartType
,nDimensionCount
,nDimensionIndex
);
904 bRet
= ChartTypeHelper::isSupportingSecondaryAxis(xChartType
,nDimensionCount
);
911 void AxisHelper::getAxisOrGridExistence( Sequence
< sal_Bool
>& rExistenceList
912 , const rtl::Reference
< Diagram
>& xDiagram
, bool bAxis
)
914 rExistenceList
.realloc(6);
915 sal_Bool
* pExistenceList
= rExistenceList
.getArray();
921 pExistenceList
[nN
] = AxisHelper::isAxisShown( nN
, true, xDiagram
);
923 pExistenceList
[nN
] = AxisHelper::isAxisShown( nN
%3, false, xDiagram
);
930 pExistenceList
[nN
] = AxisHelper::isGridShown( nN
, 0, true, xDiagram
);
932 pExistenceList
[nN
] = AxisHelper::isGridShown( nN
%3, 0, false, xDiagram
);
936 bool AxisHelper::changeVisibilityOfAxes( const rtl::Reference
< Diagram
>& xDiagram
937 , const Sequence
< sal_Bool
>& rOldExistenceList
938 , const Sequence
< sal_Bool
>& rNewExistenceList
939 , const Reference
< uno::XComponentContext
>& xContext
940 , ReferenceSizeProvider
* pRefSizeProvider
)
942 bool bChanged
= false;
943 for(sal_Int32 nN
=0;nN
<6;nN
++)
945 if(rOldExistenceList
[nN
]!=rNewExistenceList
[nN
])
948 if(rNewExistenceList
[nN
])
950 AxisHelper::showAxis( nN
%3, nN
<3, xDiagram
, xContext
, pRefSizeProvider
);
953 AxisHelper::hideAxis( nN
%3, nN
<3, xDiagram
);
959 bool AxisHelper::changeVisibilityOfGrids( const rtl::Reference
< Diagram
>& xDiagram
960 , const Sequence
< sal_Bool
>& rOldExistenceList
961 , const Sequence
< sal_Bool
>& rNewExistenceList
)
963 bool bChanged
= false;
964 for(sal_Int32 nN
=0;nN
<6;nN
++)
966 if(rOldExistenceList
[nN
]!=rNewExistenceList
[nN
])
969 if(rNewExistenceList
[nN
])
970 AxisHelper::showGrid( nN
%3, 0, nN
<3, xDiagram
);
972 AxisHelper::hideGrid( nN
%3, 0, nN
<3, xDiagram
);
978 rtl::Reference
< BaseCoordinateSystem
> AxisHelper::getCoordinateSystemOfAxis(
979 const rtl::Reference
< Axis
>& xAxis
980 , const rtl::Reference
< Diagram
>& xDiagram
)
985 rtl::Reference
< BaseCoordinateSystem
> xRet
;
986 for( rtl::Reference
< BaseCoordinateSystem
> const & xCooSys
: xDiagram
->getBaseCoordinateSystems() )
988 std::vector
< rtl::Reference
< Axis
> > aAllAxis
= AxisHelper::getAllAxesOfCoordinateSystem( xCooSys
);
990 auto aFound
= std::find( aAllAxis
.begin(), aAllAxis
.end(), xAxis
);
991 if( aFound
!= aAllAxis
.end())
1000 rtl::Reference
< ChartType
> AxisHelper::getChartTypeByIndex( const rtl::Reference
< BaseCoordinateSystem
>& xCooSys
, sal_Int32 nIndex
)
1002 rtl::Reference
< ChartType
> xChartType
;
1006 const std::vector
< rtl::Reference
< ChartType
> > aChartTypeList( xCooSys
->getChartTypes2() );
1007 if( nIndex
>= 0 && o3tl::make_unsigned(nIndex
) < aChartTypeList
.size() )
1008 xChartType
= aChartTypeList
[nIndex
];
1014 void AxisHelper::setRTLAxisLayout( const rtl::Reference
< BaseCoordinateSystem
>& xCooSys
)
1019 bool bCartesian
= xCooSys
->getViewServiceName() == CHART2_COOSYSTEM_CARTESIAN_VIEW_SERVICE_NAME
;
1023 bool bVertical
= false;
1024 xCooSys
->getPropertyValue( u
"SwapXAndYAxis"_ustr
) >>= bVertical
;
1026 sal_Int32 nHorizontalAxisDimension
= bVertical
? 1 : 0;
1027 sal_Int32 nVerticalAxisDimension
= bVertical
? 0 : 1;
1031 //reverse direction for horizontal main axis
1032 rtl::Reference
< Axis
> xHorizontalMainAxis
= AxisHelper::getAxis( nHorizontalAxisDimension
, MAIN_AXIS_INDEX
, xCooSys
);
1033 if( xHorizontalMainAxis
.is() )
1035 chart2::ScaleData aScale
= xHorizontalMainAxis
->getScaleData();
1036 aScale
.Orientation
= chart2::AxisOrientation_REVERSE
;
1037 xHorizontalMainAxis
->setScaleData(aScale
);
1040 //mathematical direction for vertical main axis
1041 rtl::Reference
< Axis
> xVerticalMainAxis
= AxisHelper::getAxis( nVerticalAxisDimension
, MAIN_AXIS_INDEX
, xCooSys
);
1042 if( xVerticalMainAxis
.is() )
1044 chart2::ScaleData aScale
= xVerticalMainAxis
->getScaleData();
1045 aScale
.Orientation
= chart2::AxisOrientation_MATHEMATICAL
;
1046 xVerticalMainAxis
->setScaleData(aScale
);
1049 catch( const uno::Exception
& )
1051 DBG_UNHANDLED_EXCEPTION("chart2" );
1056 //reverse direction for horizontal secondary axis
1057 rtl::Reference
< Axis
> xHorizontalSecondaryAxis
= AxisHelper::getAxis( nHorizontalAxisDimension
, SECONDARY_AXIS_INDEX
, xCooSys
);
1058 if( xHorizontalSecondaryAxis
.is() )
1060 chart2::ScaleData aScale
= xHorizontalSecondaryAxis
->getScaleData();
1061 aScale
.Orientation
= chart2::AxisOrientation_REVERSE
;
1062 xHorizontalSecondaryAxis
->setScaleData(aScale
);
1065 //mathematical direction for vertical secondary axis
1066 rtl::Reference
< Axis
> xVerticalSecondaryAxis
= AxisHelper::getAxis( nVerticalAxisDimension
, SECONDARY_AXIS_INDEX
, xCooSys
);
1067 if( xVerticalSecondaryAxis
.is() )
1069 chart2::ScaleData aScale
= xVerticalSecondaryAxis
->getScaleData();
1070 aScale
.Orientation
= chart2::AxisOrientation_MATHEMATICAL
;
1071 xVerticalSecondaryAxis
->setScaleData(aScale
);
1074 catch( const uno::Exception
& )
1076 DBG_UNHANDLED_EXCEPTION("chart2");
1080 rtl::Reference
< ChartType
> AxisHelper::getFirstChartTypeWithSeriesAttachedToAxisIndex( const rtl::Reference
< Diagram
>& xDiagram
, const sal_Int32 nAttachedAxisIndex
)
1082 rtl::Reference
< ChartType
> xChartType
;
1083 std::vector
< rtl::Reference
< DataSeries
> > aSeriesVector
= xDiagram
->getDataSeries();
1084 for (auto const& series
: aSeriesVector
)
1086 sal_Int32 nCurrentIndex
= DataSeriesHelper::getAttachedAxisIndex(series
);
1087 if( nAttachedAxisIndex
== nCurrentIndex
)
1089 xChartType
= xDiagram
->getChartTypeOfSeries(series
);
1097 bool AxisHelper::isAxisPositioningEnabled()
1099 const SvtSaveOptions::ODFSaneDefaultVersion
nCurrentVersion(GetODFSaneDefaultVersion());
1100 return nCurrentVersion
>= SvtSaveOptions::ODFSVER_012
;
1105 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */