/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include <AxisHelper.hxx>
#include <DiagramHelper.hxx>
#include <Diagram.hxx>
#include <ChartTypeHelper.hxx>
#include <ChartType.hxx>
#include <Axis.hxx>
#include <AxisIndexDefines.hxx>
#include <DataSource.hxx>
#include <LinePropertiesHelper.hxx>
#include <servicenames_coosystems.hxx>
#include <DataSeries.hxx>
#include <DataSeriesHelper.hxx>
#include <Scaling.hxx>
#include <ChartModel.hxx>
#include <DataSourceHelper.hxx>
#include <ReferenceSizeProvider.hxx>
#include <ExplicitCategoriesProvider.hxx>
#include <unonames.hxx>
#include <BaseCoordinateSystem.hxx>
#include <GridProperties.hxx>
#include <o3tl/safeint.hxx>
#include <unotools/saveopt.hxx>
#include <com/sun/star/chart/ChartAxisPosition.hpp>
#include <com/sun/star/chart2/AxisType.hpp>
#include <sal/log.hxx>
#include <com/sun/star/lang/XServiceName.hpp>
#include <com/sun/star/uno/XComponentContext.hpp>
#include <comphelper/diagnose_ex.hxx>
#include <cstddef>
#include <map>
namespace chart
{
using namespace ::com::sun::star;
using namespace ::com::sun::star::chart2;
using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::Sequence;
Reference< chart2::XScaling > AxisHelper::createLinearScaling()
{
return new LinearScaling( 1.0, 0.0 );
}
Reference< chart2::XScaling > AxisHelper::createLogarithmicScaling(
double fBase )
{
return new LogarithmicScaling( fBase );
}
ScaleData AxisHelper::createDefaultScale()
{
ScaleData aScaleData;
aScaleData.AxisType = chart2::AxisType::REALNUMBER;
aScaleData.AutoDateAxis =
true ;
aScaleData.ShiftedCategoryPosition =
false ;
aScaleData.IncrementData.SubIncrements = { SubIncrement() };
return aScaleData;
}
void AxisHelper::removeExplicitScaling( ScaleData& rScaleData )
{
rScaleData.Minimum = rScaleData.Maximum = rScaleData.Origin = uno::Any();
rScaleData.Scaling = nullptr;
ScaleData aDefaultScale( createDefaultScale() );
rScaleData.IncrementData = aDefaultScale.IncrementData;
rScaleData.TimeIncrement = aDefaultScale.TimeIncrement;
}
bool AxisHelper::isLogarithmic(
const Reference< XScaling >& xScaling )
{
Reference< lang::XServiceName > xServiceName( xScaling, uno::UNO_QUERY );
return xServiceName.is()
&& xServiceName->getServiceName() ==
"com.sun.star.chart2.LogarithmicScaling" ;
}
chart2::ScaleData AxisHelper::getDateCheckedScale(
const rtl::Reference< Axis >& xAx
is, ChartModel& rModel )
{
ScaleData aScale = xAxis->getScaleData();
rtl::Reference< BaseCoordinateSystem > xCooSys( rModel.getFirstCoordinateSystem() );
if ( aScale.AutoDateAxis && aScale.AxisType == AxisType::CATEGORY )
{
sal_Int32 nDimensionIndex=0; sal_Int32 nAxisIndex=0;
AxisHelper::getIndicesForAxis(xAxis, xCooSys, nDimensionIndex, nAxisIndex );
auto xChartType = AxisHelper::getChartTypeByIndex(xCooSys, 0);
bool bChartTypeAllowsDateAxis = xChartType.is() ? xChartType->isSupportingDateAxis(nDimensionIndex) : true ;
if ( bChartTypeAllowsDateAxis )
aScale.AxisType = AxisType::DATE;
}
if ( aScale.AxisType == AxisType::DATE )
{
ExplicitCategoriesProvider aExplicitCategoriesProvider( xCooSys, rModel );
if ( !aExplicitCategoriesProvider.isDateAxis() )
aScale.AxisType = AxisType::CATEGORY;
}
return aScale;
}
void AxisHelper::checkDateAxis( chart2::ScaleData& rScale, ExplicitCategoriesProvider* pExplicitCategoriesProvider, bool bChartTypeAllowsDateAxis )
{
if ( rScale.AutoDateAxis && rScale.AxisType == AxisType::CATEGORY && bChartTypeAllowsDateAxis )
{
rScale.AxisType = AxisType::DATE;
removeExplicitScaling( rScale );
}
if ( rScale.AxisType == AxisType::DATE && (!pExplicitCategoriesProvider || !pExplicitCategoriesProvider->isDateAxis()) )
{
rScale.AxisType = AxisType::CATEGORY;
removeExplicitScaling( rScale );
}
}
sal_Int32 AxisHelper::getExplicitNumberFormatKeyForAxis(
const rtl::Reference< Axis >& xAxis
, const rtl::Reference< BaseCoordinateSystem > & xCorrespondingCoordinateSystem
, const rtl::Reference<ChartModel>& xChartDoc
, bool bSearchForParallelAxisIfNothingIsFound )
{
sal_Int32 nNumberFormatKey(0);
sal_Int32 nAxisIndex = 0;
sal_Int32 nDimensionIndex = 1;
AxisHelper::getIndicesForAxis( xAxis, xCorrespondingCoordinateSystem, nDimensionIndex, nAxisIndex );
if (!xAxis.is())
return 0;
bool bLinkToSource = true ;
xAxis->getPropertyValue(CHART_UNONAME_LINK_TO_SRC_NUMFMT) >>= bLinkToSource;
xAxis->getPropertyValue(CHART_UNONAME_NUMFMT) >>= nNumberFormatKey;
if (bLinkToSource)
{
bool bFormatSet = false ;
//check whether we have a percent scale -> use percent format
if (xChartDoc)
{
ScaleData aData = AxisHelper::getDateCheckedScale( xAxis, *xChartDoc );
if ( aData.AxisType==AxisType::PERCENT )
{
sal_Int32 nPercentFormat = DiagramHelper::getPercentNumberFormat( xChartDoc );
if ( nPercentFormat != -1 )
{
nNumberFormatKey = nPercentFormat;
bFormatSet = true ;
}
}
else if ( aData.AxisType==AxisType::DATE )
{
if ( aData.Categories.is() )
{
Reference< data::XDataSequence > xSeq( aData.Categories->getValues());
if ( xSeq.is() && !( xChartDoc.is() && xChartDoc->hasInternalDataProvider()) )
nNumberFormatKey = xSeq->getNumberFormatKeyByIndex( -1 );
else
nNumberFormatKey = DiagramHelper::getDateNumberFormat( xChartDoc );
bFormatSet = true ;
}
}
else if ( xChartDoc.is() && xChartDoc->hasInternalDataProvider() && nDimensionIndex == 0 ) //maybe date axis
{
rtl::Reference< Diagram > xDiagram( xChartDoc->getFirstChartDiagram() );
if ( xDiagram->isSupportingDateAxis() )
{
nNumberFormatKey = DiagramHelper::getDateNumberFormat( xChartDoc );
}
else
{
rtl::Reference< DataSource > xSource = DataSourceHelper::getUsedData( *xChartDoc );
if ( xSource.is() )
{
std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > aXValues(
DataSeriesHelper::getAllDataSequencesByRole( xSource->getDataSequences(), u"values-x" _ustr ) );
if ( aXValues.empty() )
{
uno::Reference< chart2::data::XLabeledDataSequence > xCategories( xDiagram->getCategories() );
if ( xCategories.is() )
{
Reference< data::XDataSequence > xSeq( xCategories->getValues());
if ( xSeq.is() )
{
bool bHasValidDoubles = false ;
double fTest=0.0;
Sequence< uno::Any > aCats( xSeq->getData() );
sal_Int32 nCount = aCats.getLength();
for ( sal_Int32 i = 0; i < nCount; ++i )
{
if ( (aCats[i]>>=fTest) && !std::isnan(fTest) )
{
bHasValidDoubles=true ;
break ;
}
}
if ( bHasValidDoubles )
nNumberFormatKey = DiagramHelper::getDateNumberFormat( xChartDoc );
}
}
}
}
}
bFormatSet = true ;
}
}
if ( !bFormatSet )
{
std::map< sal_Int32, sal_Int32 > aKeyMap;
bool bNumberFormatKeyFoundViaAttachedData = false ;
try
{
OUString aRoleToMatch;
if ( nDimensionIndex == 0 )
aRoleToMatch = "values-x" ;
const std::vector< rtl::Reference< ChartType > > & aChartTypes( xCorrespondingCoordinateSystem->getChartTypes2());
for ( rtl::Reference< ChartType > const & chartType : aChartTypes )
{
if ( nDimensionIndex != 0 )
aRoleToMatch = ChartTypeHelper::getRoleOfSequenceForYAxisNumberFormatDetection( chartType );
for ( rtl::Reference< DataSeries > const & xDataSeries : chartType->getDataSeries2() )
{
if ( nDimensionIndex == 1 )
{
//only take those series into account that are attached to this axis
sal_Int32 nAttachedAxisIndex = xDataSeries->getAttachedAxisIndex();
if ( nAttachedAxisIndex != nAxisIndex )
continue ;
}
Reference< data::XLabeledDataSequence > xLabeledSeq(
DataSeriesHelper::getDataSequenceByRole( xDataSeries, aRoleToMatch ) );
if ( !xLabeledSeq.is() && nDimensionIndex==0 )
{
ScaleData aData = xAxis->getScaleData();
xLabeledSeq = aData.Categories;
}
if ( xLabeledSeq.is() )
{
Reference< data::XDataSequence > xSeq( xLabeledSeq->getValues());
if ( xSeq.is() )
{
sal_Int32 nKey = xSeq->getNumberFormatKeyByIndex( -1 );
// increase frequency
aKeyMap[ nKey ] ++;
}
}
}
}
}
catch ( const uno::Exception & )
{
DBG_UNHANDLED_EXCEPTION("chart2" );
}
if ( ! aKeyMap.empty())
{
sal_Int32 nMaxFreq = 0;
// find most frequent key
for (auto const & elem : aKeyMap)
{
SAL_INFO(
"chart2.tools" ,
"NumberFormatKey " << elem.first << " appears "
<< elem.second << " times" );
// all values must at least be 1
if ( elem.second > nMaxFreq )
{
nNumberFormatKey = elem.first;
bNumberFormatKeyFoundViaAttachedData = true ;
nMaxFreq = elem.second;
}
}
}
if ( bSearchForParallelAxisIfNothingIsFound )
{
//no format is set to this axis and no data is set to this axis
//--> try to obtain the format from the parallel y-axis
if ( !bNumberFormatKeyFoundViaAttachedData && nDimensionIndex == 1 )
{
sal_Int32 nParallelAxisIndex = (nAxisIndex==1) ?0 :1;
rtl::Reference< Axis > xParallelAxis = AxisHelper::getAxis( 1, nParallelAxisIndex, xCorrespondingCoordinateSystem );
nNumberFormatKey = AxisHelper::getExplicitNumberFormatKeyForAxis(xParallelAxis, xCorrespondingCoordinateSystem, xChartDoc, false );
}
}
}
}
return nNumberFormatKey;
}
rtl::Reference< Axis > AxisHelper::createAxis(
sal_Int32 nDimensionIndex
, sal_Int32 nAxisIndex // 0==main or 1==secondary axis
, const rtl::Reference< BaseCoordinateSystem >& xCooSys
, const Reference< uno::XComponentContext > & xContext
, ReferenceSizeProvider * pRefSizeProvider )
{
if ( !xContext.is() || !xCooSys.is() )
return nullptr;
if ( nDimensionIndex >= xCooSys->getDimension() )
return nullptr;
rtl::Reference< Axis > xAxis = new Axis();
xCooSys->setAxisByDimension( nDimensionIndex, xAxis, nAxisIndex );
if ( nAxisIndex>0 )//when inserting secondary axes copy some things from the main axis
{
css::chart::ChartAxisPosition eNewAxisPos( css::chart::ChartAxisPosition_END );
rtl::Reference< Axis > xMainAxis = xCooSys->getAxisByDimension2( nDimensionIndex, 0 );
if ( xMainAxis.is() )
{
ScaleData aScale = xAxis->getScaleData();
ScaleData aMainScale = xMainAxis->getScaleData();
aScale.AxisType = aMainScale.AxisType;
aScale.AutoDateAxis = aMainScale.AutoDateAxis;
aScale.Categories = aMainScale.Categories;
aScale.Orientation = aMainScale.Orientation;
aScale.ShiftedCategoryPosition = aMainScale.ShiftedCategoryPosition;
xAxis->setScaleData( aScale );
//ensure that the second axis is not placed on the main axis
css::chart::ChartAxisPosition eMainAxisPos( css::chart::ChartAxisPosition_ZERO );
xMainAxis->getPropertyValue(u"CrossoverPosition" _ustr) >>= eMainAxisPos;
if ( eMainAxisPos == css::chart::ChartAxisPosition_END )
eNewAxisPos = css::chart::ChartAxisPosition_START;
}
xAxis->setPropertyValue(u"CrossoverPosition" _ustr, uno::Any(eNewAxisPos) );
}
try
{
// set correct initial AutoScale
if ( pRefSizeProvider )
pRefSizeProvider->setValuesAtPropertySet( xAxis );
}
catch ( const uno::Exception& )
{
TOOLS_WARN_EXCEPTION("chart2" , "" );
}
return xAxis;
}
rtl::Reference< Axis > AxisHelper::createAxis( sal_Int32 nDimensionIndex, bool bMainAxis
, const rtl::Reference< Diagram >& xDiagram
, const Reference< uno::XComponentContext >& xContext
, ReferenceSizeProvider * pRefSizeProvider )
{
OSL_ENSURE( xContext.is(), "need a context to create an axis" );
if ( !xContext.is() )
return nullptr;
sal_Int32 nAxisIndex = bMainAxis ? MAIN_AXIS_INDEX : SECONDARY_AXIS_INDEX;
rtl::Reference< BaseCoordinateSystem > xCooSys = AxisHelper::getCoordinateSystemByIndex( xDiagram, 0 );
// create axis
return AxisHelper::createAxis(
nDimensionIndex, nAxisIndex, xCooSys, xContext, pRefSizeProvider );
}
void AxisHelper::showAxis( sal_Int32 nDimensionIndex, bool bMainAxis
, const rtl::Reference< Diagram >& xDiagram
, const Reference< uno::XComponentContext >& xContext
, ReferenceSizeProvider * pRefSizeProvider )
{
if ( !xDiagram.is() )
return ;
bool bNewAxisCreated = false ;
rtl::Reference< Axis > xAxis = AxisHelper::getAxis( nDimensionIndex, bMainAxis, xDiagram );
if ( !xAxis.is() && xContext.is() )
{
// create axis
bNewAxisCreated = true ;
xAxis = AxisHelper::createAxis( nDimensionIndex, bMainAxis, xDiagram, xContext, pRefSizeProvider );
}
OSL_ASSERT( xAxis.is());
if ( !bNewAxisCreated ) //default is true already if created
AxisHelper::makeAxisVisible( xAxis );
}
void AxisHelper::showGrid( sal_Int32 nDimensionIndex, sal_Int32 nCooSysIndex, bool bMainGrid
, const rtl::Reference< Diagram >& xDiagram )
{
if ( !xDiagram.is() )
return ;
rtl::Reference< BaseCoordinateSystem > xCooSys = AxisHelper::getCoordinateSystemByIndex( xDiagram, nCooSysIndex );
if (!xCooSys.is())
return ;
rtl::Reference< Axis > xAxis = AxisHelper::getAxis( nDimensionIndex, MAIN_AXIS_INDEX, xCooSys );
if (!xAxis.is())
{
//hhhh todo create axis without axis visibility
return ;
}
if ( bMainGrid )
AxisHelper::makeGridVisible( xAxis->getGridProperties2() );
else
{
std::vector< rtl::Reference< GridProperties > > aSubGrids( xAxis->getSubGridProperties2() );
for ( auto const & i : aSubGrids )
AxisHelper::makeGridVisible( i );
}
}
void AxisHelper::makeAxisVisible( const rtl::Reference< Axis >& xAxis )
{
if ( xAxis.is() )
{
xAxis->setPropertyValue( u"Show" _ustr, uno::Any( true ) );
LinePropertiesHelper::SetLineVisible( xAxis );
xAxis->setPropertyValue( u"DisplayLabels" _ustr, uno::Any( true ) );
}
}
void AxisHelper::makeGridVisible( const rtl::Reference< GridProperties >& xGridProperties )
{
if ( xGridProperties.is() )
{
xGridProperties->setPropertyValue( u"Show" _ustr, uno::Any( true ) );
LinePropertiesHelper::SetLineVisible( xGridProperties );
}
}
void AxisHelper::hideAxis( sal_Int32 nDimensionIndex, bool bMainAxis
, const rtl::Reference< Diagram >& xDiagram )
{
AxisHelper::makeAxisInvisible( AxisHelper::getAxis( nDimensionIndex, bMainAxis, xDiagram ) );
}
void AxisHelper::makeAxisInvisible( const rtl::Reference< Axis >& xAxis )
{
if ( xAxis.is() )
{
xAxis->setPropertyValue( u"Show" _ustr, uno::Any( false ) );
}
}
void AxisHelper::hideAxisIfNoDataIsAttached( const rtl::Reference< Axis >& xAxis, const rtl::Reference< Diagram >& xDiagram )
{
//axis is hidden if no data is attached anymore but data is available
bool bOtherSeriesAttachedToThisAxis = false ;
std::vector< rtl::Reference< DataSeries > > aSeriesVector = xDiagram->getDataSeries();
for (auto const & series : aSeriesVector)
{
rtl::Reference< Axis > xCurrentAxis = xDiagram->getAttachedAxis(series);
if ( xCurrentAxis==xAxis )
{
bOtherSeriesAttachedToThisAxis = true ;
break ;
}
}
if (!bOtherSeriesAttachedToThisAxis && !aSeriesVector.empty() )
AxisHelper::makeAxisInvisible( xAxis );
}
void AxisHelper::hideGrid( sal_Int32 nDimensionIndex, sal_Int32 nCooSysIndex, bool bMainGrid
, const rtl::Reference< Diagram >& xDiagram )
{
if ( !xDiagram.is() )
return ;
rtl::Reference< BaseCoordinateSystem > xCooSys = AxisHelper::getCoordinateSystemByIndex( xDiagram, nCooSysIndex );
if (!xCooSys.is())
return ;
rtl::Reference< Axis > xAxis = AxisHelper::getAxis( nDimensionIndex, MAIN_AXIS_INDEX, xCooSys );
if (!xAxis.is())
return ;
if ( bMainGrid )
AxisHelper::makeGridInvisible( xAxis->getGridProperties2() );
else
{
std::vector< rtl::Reference< ::chart::GridProperties > > aSubGrids( xAxis->getSubGridProperties2() );
for ( auto const & i : aSubGrids)
AxisHelper::makeGridInvisible( i );
}
}
void AxisHelper::makeGridInvisible( const rtl::Reference< ::chart::GridProperties >& xGridProperties )
{
if ( xGridProperties.is() )
{
xGridProperties->setPropertyValue( u"Show" _ustr, uno::Any( false ) );
}
}
bool AxisHelper::isGridShown( sal_Int32 nDimensionIndex, sal_Int32 nCooSysIndex, bool bMainGrid
, const rtl::Reference< Diagram >& xDiagram )
{
bool bRet = false ;
rtl::Reference< BaseCoordinateSystem > xCooSys = AxisHelper::getCoordinateSystemByIndex( xDiagram, nCooSysIndex );
if (!xCooSys.is())
return bRet;
rtl::Reference< Axis > xAxis = AxisHelper::getAxis( nDimensionIndex, MAIN_AXIS_INDEX, xCooSys );
if (!xAxis.is())
return bRet;
if ( bMainGrid )
bRet = AxisHelper::isGridVisible( xAxis->getGridProperties2() );
else
{
std::vector< rtl::Reference< ::chart::GridProperties > > aSubGrids( xAxis->getSubGridProperties2() );
if ( !aSubGrids.empty() )
bRet = AxisHelper::isGridVisible( aSubGrids[0] );
}
return bRet;
}
rtl::Reference< ::chart::BaseCoordinateSystem > AxisHelper::getCoordinateSystemByIndex(
const rtl::Reference< Diagram >& xDiagram, sal_Int32 nIndex )
{
if (!xDiagram.is())
return nullptr;
auto aCooSysList = xDiagram->getBaseCoordinateSystems();
if (0<=nIndex && o3tl::make_unsigned(nIndex) < aCooSysList.size())
return aCooSysList[nIndex];
return nullptr;
}
rtl::Reference< Axis > AxisHelper::getAxis( sal_Int32 nDimensionIndex, bool bMainAxis
, const rtl::Reference< Diagram >& xDiagram )
{
rtl::Reference< Axis > xRet;
try
{
rtl::Reference< BaseCoordinateSystem > xCooSys = AxisHelper::getCoordinateSystemByIndex( xDiagram, 0 );
xRet = AxisHelper::getAxis( nDimensionIndex, bMainAxis ? 0 : 1, xCooSys );
}
catch ( const uno::Exception & )
{
}
return xRet;
}
rtl::Reference< Axis > AxisHelper::getAxis( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex
, const rtl::Reference< BaseCoordinateSystem >& xCooSys )
{
rtl::Reference< Axis > xRet;
if (!xCooSys.is())
return xRet;
if (nDimensionIndex >= xCooSys->getDimension())
return xRet;
if (nAxisIndex > xCooSys->getMaximumAxisIndexByDimension(nDimensionIndex))
return xRet;
assert(nAxisIndex >= 0);
assert(nDimensionIndex >= 0);
xRet = xCooSys->getAxisByDimension2( nDimensionIndex, nAxisIndex );
return xRet;
}
rtl::Reference< Axis > AxisHelper::getCrossingMainAxis( const rtl::Reference< Axis >& xAxis
, const rtl::Reference< BaseCoordinateSystem >& xCooSys )
{
sal_Int32 nDimensionIndex = 0;
sal_Int32 nAxisIndex = 0;
AxisHelper::getIndicesForAxis( xAxis, xCooSys, nDimensionIndex, nAxisIndex );
if ( nDimensionIndex==2 )
{
nDimensionIndex=1;
bool bSwapXY = false ;
if ( (xCooSys->getPropertyValue( u"SwapXAndYAxis" _ustr ) >>= bSwapXY) && bSwapXY )
nDimensionIndex=0;
}
else if ( nDimensionIndex==1 )
nDimensionIndex=0;
else
nDimensionIndex=1;
return AxisHelper::getAxis( nDimensionIndex, 0, xCooSys );
}
rtl::Reference< Axis > AxisHelper::getParallelAxis( const rtl::Reference< Axis >& xAxis
, const rtl::Reference< Diagram >& xDiagram )
{
try
{
sal_Int32 nCooSysIndex=-1;
sal_Int32 nDimensionIndex=-1;
sal_Int32 nAxisIndex=-1;
if ( getIndicesForAxis( xAxis, xDiagram, nCooSysIndex, nDimensionIndex, nAxisIndex ) )
{
sal_Int32 nParallelAxisIndex = (nAxisIndex==1) ?0 :1;
return getAxis( nDimensionIndex, nParallelAxisIndex, getCoordinateSystemByIndex( xDiagram, nCooSysIndex ) );
}
}
catch ( const uno::RuntimeException& )
{
}
return nullptr;
}
bool AxisHelper::isAxisShown( sal_Int32 nDimensionIndex, bool bMainAxis
, const rtl::Reference< Diagram >& xDiagram )
{
return AxisHelper::isAxisVisible( AxisHelper::getAxis( nDimensionIndex, bMainAxis, xDiagram ) );
}
bool AxisHelper::isAxisVisible( const rtl::Reference< Axis >& xAxis )
{
bool bRet = false ;
if ( xAxis.is() )
{
xAxis->getPropertyValue( u"Show" _ustr ) >>= bRet;
bRet = bRet && ( LinePropertiesHelper::IsLineVisible( xAxis )
|| areAxisLabelsVisible( xAxis ) );
}
return bRet;
}
bool AxisHelper::areAxisLabelsVisible( const rtl::Reference< Axis >& xAxis )
{
bool bRet = false ;
if ( xAxis.is() )
{
xAxis->getPropertyValue( u"DisplayLabels" _ustr ) >>= bRet;
}
return bRet;
}
bool AxisHelper::isGridVisible( const rtl::Reference< ::chart::GridProperties >& xGridproperties )
{
bool bRet = false ;
if ( xGridproperties.is() )
{
xGridproperties->getPropertyValue( u"Show" _ustr ) >>= bRet;
bRet = bRet && LinePropertiesHelper::IsLineVisible( xGridproperties );
}
return bRet;
}
rtl::Reference< GridProperties > AxisHelper::getGridProperties(
const rtl::Reference< BaseCoordinateSystem >& xCooSys
, sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex, sal_Int32 nSubGridIndex )
{
rtl::Reference< GridProperties > xRet;
rtl::Reference< Axis > xAxis( AxisHelper::getAxis( nDimensionIndex, nAxisIndex, xCooSys ) );
if ( xAxis.is() )
{
if ( nSubGridIndex<0 )
xRet = xAxis->getGridProperties2();
else
{
std::vector< rtl::Reference< GridProperties > > aSubGrids( xAxis->getSubGridProperties2() );
if (nSubGridIndex < static_cast <sal_Int32>(aSubGrids.size()))
xRet = aSubGrids[nSubGridIndex];
}
}
return xRet;
}
sal_Int32 AxisHelper::getDimensionIndexOfAxis(
const rtl::Reference< Axis >& xAxis
, const rtl::Reference< Diagram >& xDiagram )
{
sal_Int32 nDimensionIndex = -1;
sal_Int32 nCooSysIndex = -1;
sal_Int32 nAxisIndex = -1;
AxisHelper::getIndicesForAxis( xAxis, xDiagram, nCooSysIndex , nDimensionIndex, nAxisIndex );
return nDimensionIndex;
}
bool AxisHelper::getIndicesForAxis(
const rtl::Reference< Axis >& xAxis
, const rtl::Reference< BaseCoordinateSystem >& xCooSys
, sal_Int32& rOutDimensionIndex, sal_Int32& rOutAxisIndex )
{
//returns true if indices are found
rOutDimensionIndex = -1;
rOutAxisIndex = -1;
if ( !xCooSys || !xAxis )
return false ;
rtl::Reference< Axis > xCurrentAxis;
sal_Int32 nDimensionCount( xCooSys->getDimension() );
for ( sal_Int32 nDimensionIndex = 0; nDimensionIndex < nDimensionCount; nDimensionIndex++ )
{
sal_Int32 nMaxAxisIndex = xCooSys->getMaximumAxisIndexByDimension(nDimensionIndex);
for ( sal_Int32 nAxisIndex = 0; nAxisIndex <= nMaxAxisIndex; nAxisIndex++ )
{
xCurrentAxis = xCooSys->getAxisByDimension2(nDimensionIndex,nAxisIndex);
if ( xCurrentAxis == xAxis )
{
rOutDimensionIndex = nDimensionIndex;
rOutAxisIndex = nAxisIndex;
return true ;
}
}
}
return false ;
}
bool AxisHelper::getIndicesForAxis( const rtl::Reference< Axis >& xAxis, const rtl::Reference< Diagram >& xDiagram
, sal_Int32& rOutCooSysIndex, sal_Int32& rOutDimensionIndex, sal_Int32& rOutAxisIndex )
{
//returns true if indices are found
rOutCooSysIndex = -1;
rOutDimensionIndex = -1;
rOutAxisIndex = -1;
const std::vector< rtl::Reference< BaseCoordinateSystem > > aCooSysList = xDiagram->getBaseCoordinateSystems();
for ( std::size_t nC=0; nC < aCooSysList.size(); ++nC )
{
if ( AxisHelper::getIndicesForAxis( xAxis, aCooSysList[nC], rOutDimensionIndex, rOutAxisIndex ) )
{
rOutCooSysIndex = nC;
return true ;
}
}
return false ;
}
std::vector< rtl::Reference< Axis > > AxisHelper::getAllAxesOfCoordinateSystem(
const rtl::Reference< BaseCoordinateSystem >& xCooSys
, bool bOnlyVisible /* = false */ )
{
std::vector< rtl::Reference< Axis > > aAxisVector;
if (xCooSys.is())
{
sal_Int32 nMaxDimensionIndex = xCooSys->getDimension() -1;
if ( nMaxDimensionIndex>=0 )
{
sal_Int32 nDimensionIndex = 0;
for (; nDimensionIndex<=nMaxDimensionIndex; ++nDimensionIndex)
{
const sal_Int32 nMaximumAxisIndex = xCooSys->getMaximumAxisIndexByDimension(nDimensionIndex);
for (sal_Int32 nAxisIndex=0; nAxisIndex<=nMaximumAxisIndex; ++nAxisIndex)
{
try
{
rtl::Reference< Axis > xAxis = xCooSys->getAxisByDimension2( nDimensionIndex, nAxisIndex );
if ( xAxis.is() )
{
bool bAddAxis = true ;
if ( bOnlyVisible )
{
if ( !(xAxis->getPropertyValue( u"Show" _ustr) >>= bAddAxis) )
bAddAxis = false ;
}
if ( bAddAxis )
aAxisVector.push_back( xAxis );
}
}
catch ( const uno::Exception & )
{
DBG_UNHANDLED_EXCEPTION("chart2" );
}
}
}
}
}
return aAxisVector;
}
std::vector< rtl::Reference< Axis > > AxisHelper::getAllAxesOfDiagram(
const rtl::Reference< Diagram >& xDiagram
, bool bOnlyVisible )
{
std::vector< rtl::Reference< Axis > > aAxisVector;
for ( rtl::Reference< BaseCoordinateSystem > const & coords : xDiagram->getBaseCoordinateSystems() )
{
std::vector< rtl::Reference< Axis > > aAxesPerCooSys = AxisHelper::getAllAxesOfCoordinateSystem( coords, bOnlyVisible );
aAxisVector.insert( aAxisVector.end(), aAxesPerCooSys.begin(), aAxesPerCooSys.end() );
}
return aAxisVector;
}
std::vector< rtl::Reference< GridProperties > > AxisHelper::getAllGrids( const rtl::Reference< Diagram >& xDiagram )
{
const std::vector< rtl::Reference< Axis > > aAllAxes = AxisHelper::getAllAxesOfDiagram( xDiagram );
std::vector< rtl::Reference< GridProperties > > aGridVector;
for ( rtl::Reference< Axis > const & xAxis : aAllAxes )
{
rtl::Reference< GridProperties > xGridProperties( xAxis->getGridProperties2() );
if ( xGridProperties.is() )
aGridVector.push_back( xGridProperties );
std::vector< rtl::Reference< GridProperties > > aSubGrids( xAxis->getSubGridProperties2() );
for ( rtl::Reference< GridProperties > const & xSubGrid : aSubGrids )
{
if ( xSubGrid.is() )
aGridVector.push_back( xSubGrid );
}
}
return aGridVector;
}
void AxisHelper::getAxisOrGridPossibilities( Sequence< sal_Bool >& rPossibilityList
, const rtl::Reference< Diagram>& xDiagram, bool bAxis )
{
rPossibilityList.realloc(6);
sal_Bool* pPossibilityList = rPossibilityList.getArray();
sal_Int32 nDimensionCount = -1;
if (xDiagram)
nDimensionCount = xDiagram->getDimension();
//set possibilities:
sal_Int32 nIndex=0;
rtl::Reference< ChartType > xChartType;
if (xDiagram)
xChartType = xDiagram->getChartTypeByIndex( 0 );
for (nIndex=0;nIndex<3;nIndex++)
pPossibilityList[nIndex] = xChartType.is() ? xChartType->isSupportingMainAxis(nDimensionCount, nIndex) : true ;
for (nIndex=3;nIndex<6;nIndex++)
if ( bAxis )
pPossibilityList[nIndex] = xChartType.is() ? xChartType->isSupportingSecondaryAxis(nDimensionCount) : true ;
else
pPossibilityList[nIndex] = rPossibilityList[nIndex-3];
}
bool AxisHelper::isSecondaryYAxisNeeded( const rtl::Reference< BaseCoordinateSystem >& xCooSys )
{
if ( !xCooSys.is() )
return false ;
const std::vector< rtl::Reference< ChartType > > & aChartTypes( xCooSys->getChartTypes2() );
for ( rtl::Reference< ChartType > const & chartType : aChartTypes )
{
const std::vector< rtl::Reference< DataSeries > > & aSeriesList = chartType->getDataSeries2();
for ( sal_Int32 nS = aSeriesList.size(); nS-- ; )
{
sal_Int32 nAttachedAxisIndex = 0;
if ( ( aSeriesList[nS]->getPropertyValue( u"AttachedAxisIndex" _ustr ) >>= nAttachedAxisIndex ) &&
nAttachedAxisIndex>0 )
return true ;
}
}
return false ;
}
bool AxisHelper::shouldAxisBeDisplayed( const rtl::Reference< Axis >& xAxis
, const rtl::Reference< BaseCoordinateSystem >& xCooSys )
{
bool bRet = false ;
if ( xAxis.is() && xCooSys.is() )
{
sal_Int32 nDimensionIndex=-1;
sal_Int32 nAxisIndex=-1;
if ( AxisHelper::getIndicesForAxis( xAxis, xCooSys, nDimensionIndex, nAxisIndex ) )
{
sal_Int32 nDimensionCount = xCooSys->getDimension();
rtl::Reference< ChartType > xChartType( AxisHelper::getChartTypeByIndex( xCooSys, 0 ) );
bool bMainAxis = (nAxisIndex==MAIN_AXIS_INDEX);
if ( bMainAxis )
bRet = xChartType.is() ? xChartType->isSupportingMainAxis(nDimensionCount, nDimensionIndex) : true ;
else
bRet = xChartType.is() ? xChartType->isSupportingSecondaryAxis(nDimensionCount) : true ;
}
}
return bRet;
}
void AxisHelper::getAxisOrGridExistence( Sequence< sal_Bool >& rExistenceList
, const rtl::Reference< Diagram>& xDiagram, bool bAxis )
{
rExistenceList.realloc(6);
sal_Bool* pExistenceList = rExistenceList.getArray();
if (bAxis)
{
sal_Int32 nN;
for (nN=0;nN<3;nN++)
pExistenceList[nN] = AxisHelper::isAxisShown( nN, true , xDiagram );
for (nN=3;nN<6;nN++)
pExistenceList[nN] = AxisHelper::isAxisShown( nN%3, false , xDiagram );
}
else
{
sal_Int32 nN;
for (nN=0;nN<3;nN++)
pExistenceList[nN] = AxisHelper::isGridShown( nN, 0, true , xDiagram );
for (nN=3;nN<6;nN++)
pExistenceList[nN] = AxisHelper::isGridShown( nN%3, 0, false , xDiagram );
}
}
bool AxisHelper::changeVisibilityOfAxes( const rtl::Reference< Diagram >& xDiagram
, const Sequence< sal_Bool >& rOldExistenceList
, const Sequence< sal_Bool >& rNewExistenceList
, const Reference< uno::XComponentContext >& xContext
, ReferenceSizeProvider * pRefSizeProvider )
{
bool bChanged = false ;
for (sal_Int32 nN=0;nN<6;nN++)
{
if (rOldExistenceList[nN]!=rNewExistenceList[nN])
{
bChanged = true ;
if (rNewExistenceList[nN])
{
AxisHelper::showAxis( nN%3, nN<3, xDiagram, xContext, pRefSizeProvider );
}
else
AxisHelper::hideAxis( nN%3, nN<3, xDiagram );
}
}
return bChanged;
}
bool AxisHelper::changeVisibilityOfGrids( const rtl::Reference< Diagram >& xDiagram
, const Sequence< sal_Bool >& rOldExistenceList
, const Sequence< sal_Bool >& rNewExistenceList )
{
bool bChanged = false ;
for (sal_Int32 nN=0;nN<6;nN++)
{
if (rOldExistenceList[nN]!=rNewExistenceList[nN])
{
bChanged = true ;
if (rNewExistenceList[nN])
AxisHelper::showGrid( nN%3, 0, nN<3, xDiagram );
else
AxisHelper::hideGrid( nN%3, 0, nN<3, xDiagram );
}
}
return bChanged;
}
rtl::Reference< BaseCoordinateSystem > AxisHelper::getCoordinateSystemOfAxis(
const rtl::Reference< Axis >& xAxis
, const rtl::Reference< Diagram >& xDiagram )
{
if (!xDiagram)
return nullptr;
rtl::Reference< BaseCoordinateSystem > xRet;
for ( rtl::Reference< BaseCoordinateSystem > const & xCooSys : xDiagram->getBaseCoordinateSystems() )
{
std::vector< rtl::Reference< Axis > > aAllAxis = AxisHelper::getAllAxesOfCoordinateSystem( xCooSys );
auto aFound = std::find( aAllAxis.begin(), aAllAxis.end(), xAxis );
if ( aFound != aAllAxis.end())
{
xRet = xCooSys;
break ;
}
}
return xRet;
}
rtl::Reference< ChartType > AxisHelper::getChartTypeByIndex( const rtl::Reference< BaseCoordinateSystem >& xCooSys, sal_Int32 nIndex )
{
rtl::Reference< ChartType > xChartType;
if ( xCooSys.is() )
{
const std::vector< rtl::Reference< ChartType > > aChartTypeList( xCooSys->getChartTypes2() );
if ( nIndex >= 0 && o3tl::make_unsigned(nIndex) < aChartTypeList.size() )
xChartType = aChartTypeList[nIndex];
}
return xChartType;
}
void AxisHelper::setRTLAxisLayout( const rtl::Reference< BaseCoordinateSystem >& xCooSys )
{
if ( !xCooSys.is() )
return ;
bool bCartesian = xCooSys->getViewServiceName() == CHART2_COOSYSTEM_CARTESIAN_VIEW_SERVICE_NAME;
if ( !bCartesian )
return ;
bool bVertical = false ;
xCooSys->getPropertyValue( u"SwapXAndYAxis" _ustr ) >>= bVertical;
sal_Int32 nHorizontalAxisDimension = bVertical ? 1 : 0;
sal_Int32 nVerticalAxisDimension = bVertical ? 0 : 1;
try
{
//reverse direction for horizontal main axis
rtl::Reference< Axis > xHorizontalMainAxis = AxisHelper::getAxis( nHorizontalAxisDimension, MAIN_AXIS_INDEX, xCooSys );
if ( xHorizontalMainAxis.is() )
{
chart2::ScaleData aScale = xHorizontalMainAxis->getScaleData();
aScale.Orientation = chart2::AxisOrientation_REVERSE;
xHorizontalMainAxis->setScaleData(aScale);
}
//mathematical direction for vertical main axis
rtl::Reference< Axis > xVerticalMainAxis = AxisHelper::getAxis( nVerticalAxisDimension, MAIN_AXIS_INDEX, xCooSys );
if ( xVerticalMainAxis.is() )
{
chart2::ScaleData aScale = xVerticalMainAxis->getScaleData();
aScale.Orientation = chart2::AxisOrientation_MATHEMATICAL;
xVerticalMainAxis->setScaleData(aScale);
}
}
catch ( const uno::Exception & )
{
DBG_UNHANDLED_EXCEPTION("chart2" );
}
try
{
//reverse direction for horizontal secondary axis
rtl::Reference< Axis > xHorizontalSecondaryAxis = AxisHelper::getAxis( nHorizontalAxisDimension, SECONDARY_AXIS_INDEX, xCooSys );
if ( xHorizontalSecondaryAxis.is() )
{
chart2::ScaleData aScale = xHorizontalSecondaryAxis->getScaleData();
aScale.Orientation = chart2::AxisOrientation_REVERSE;
xHorizontalSecondaryAxis->setScaleData(aScale);
}
//mathematical direction for vertical secondary axis
rtl::Reference< Axis > xVerticalSecondaryAxis = AxisHelper::getAxis( nVerticalAxisDimension, SECONDARY_AXIS_INDEX, xCooSys );
if ( xVerticalSecondaryAxis.is() )
{
chart2::ScaleData aScale = xVerticalSecondaryAxis->getScaleData();
aScale.Orientation = chart2::AxisOrientation_MATHEMATICAL;
xVerticalSecondaryAxis->setScaleData(aScale);
}
}
catch ( const uno::Exception & )
{
DBG_UNHANDLED_EXCEPTION("chart2" );
}
}
rtl::Reference< ChartType > AxisHelper::getFirstChartTypeWithSeriesAttachedToAxisIndex( const rtl::Reference< Diagram >& xDiagram, const sal_Int32 nAttachedAxisIndex )
{
rtl::Reference< ChartType > xChartType;
std::vector< rtl::Reference< DataSeries > > aSeriesVector = xDiagram->getDataSeries();
for (auto const & series : aSeriesVector)
{
sal_Int32 nCurrentIndex = series->getAttachedAxisIndex();
if ( nAttachedAxisIndex == nCurrentIndex )
{
xChartType = xDiagram->getChartTypeOfSeries(series);
if (xChartType.is())
break ;
}
}
return xChartType;
}
bool AxisHelper::isAxisPositioningEnabled()
{
const SvtSaveOptions::ODFSaneDefaultVersion nCurrentVersion(GetODFSaneDefaultVersion());
return nCurrentVersion >= SvtSaveOptions::ODFSVER_012;
}
} //namespace chart
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Messung V0.5 C=76 H=97 G=86
¤ Dauer der Verarbeitung: 0.19 Sekunden
(vorverarbeitet)
¤
*© Formatika GbR, Deutschland