office-gobmx/chart2/source/tools/AxisHelper.cxx

1175 lines
45 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright 2000, 2010 Oracle and/or its affiliates.
*
* OpenOffice.org - a multi-platform office productivity suite
*
* This file is part of OpenOffice.org.
*
* OpenOffice.org is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3
* only, as published by the Free Software Foundation.
*
* OpenOffice.org is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License version 3 for more details
* (a copy is included in the LICENSE file that accompanied this code).
*
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with OpenOffice.org. If not, see
* <http://www.openoffice.org/license.html>
* for a copy of the LGPLv3 License.
*
************************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_chart2.hxx"
#include "AxisHelper.hxx"
#include "DiagramHelper.hxx"
#include "ChartTypeHelper.hxx"
#include "macros.hxx"
#include "AxisIndexDefines.hxx"
#include "LineProperties.hxx"
#include "ContainerHelper.hxx"
#include "servicenames_coosystems.hxx"
#include "DataSeriesHelper.hxx"
#include "Scaling.hxx"
#include "ChartModelHelper.hxx"
#include "DataSourceHelper.hxx"
#include <tools/debug.hxx>
#include <unotools/saveopt.hxx>
#include <com/sun/star/chart/ChartAxisPosition.hpp>
#include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
#include <com/sun/star/chart2/XChartTypeContainer.hpp>
#include <com/sun/star/chart2/XDataSeriesContainer.hpp>
#include <com/sun/star/chart2/data/XDataSource.hpp>
// header for class OUStringBuffer
#include <rtl/ustrbuf.hxx>
#include <rtl/math.hxx>
#include <com/sun/star/util/XCloneable.hpp>
#include <com/sun/star/lang/XServiceName.hpp>
#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;//this is adapted in the view code currently
Sequence< SubIncrement > aSubIncrements(1);
aSubIncrements[0] = SubIncrement();
aScaleData.IncrementData.SubIncrements = aSubIncrements;
return aScaleData;
}
void AxisHelper::removeExplicitScaling( ScaleData& rScaleData )
{
uno::Any aEmpty;
rScaleData.Minimum = rScaleData.Maximum = rScaleData.Origin = aEmpty;
rScaleData.Scaling = 0;
ScaleData aDefaultScale( createDefaultScale() );
rScaleData.IncrementData = aDefaultScale.IncrementData;
rScaleData.TimeIncrement = aDefaultScale.TimeIncrement;
}
bool AxisHelper::isLogarithmic( const Reference< XScaling >& xScaling )
{
bool bReturn = false;
Reference< lang::XServiceName > xServiceName( xScaling, uno::UNO_QUERY );
bReturn =( xServiceName.is() && (xServiceName->getServiceName()).equals(
C2U( "com.sun.star.chart2.LogarithmicScaling" )));
return bReturn;
}
chart2::ScaleData AxisHelper::getDateCheckedScale( const Reference< chart2::XAxis >& xAxis, const Reference< frame::XModel >& xChartModel )
{
DBG_ASSERT(xChartModel.is(),"missing chart model");
ScaleData aScale = xAxis->getScaleData();
Reference< chart2::XCoordinateSystem > xCooSys( ChartModelHelper::getFirstCoordinateSystem( xChartModel ) );
if( aScale.AutoDateAxis && aScale.AxisType == AxisType::CATEGORY )
{
sal_Int32 nDimensionIndex=0; sal_Int32 nAxisIndex=0;
AxisHelper::getIndicesForAxis(xAxis, xCooSys, nDimensionIndex, nAxisIndex );
bool bChartTypeAllowsDateAxis = ChartTypeHelper::isSupportingDateAxis( AxisHelper::getChartTypeByIndex( xCooSys, 0 ), 2, nDimensionIndex );
if( bChartTypeAllowsDateAxis )
aScale.AxisType = AxisType::DATE;
}
if( aScale.AxisType == AxisType::DATE )
{
ExplicitCategoriesProvider aExplicitCategoriesProvider( xCooSys,xChartModel );
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 Reference< chart2::XAxis >& xAxis
, const Reference< chart2::XCoordinateSystem > & xCorrespondingCoordinateSystem
, const Reference< util::XNumberFormatsSupplier >& xNumberFormatsSupplier
, bool bSearchForParallelAxisIfNothingIsFound )
{
sal_Int32 nNumberFormatKey(0);
bool bNumberFormatKeyFoundViaAttachedData = false;
sal_Int32 nAxisIndex = 0;
sal_Int32 nDimensionIndex = 1;
AxisHelper::getIndicesForAxis( xAxis, xCorrespondingCoordinateSystem, nDimensionIndex, nAxisIndex );
Reference< chart2::XChartDocument > xChartDoc( xNumberFormatsSupplier, uno::UNO_QUERY );
Reference< beans::XPropertySet > xProp( xAxis, uno::UNO_QUERY );
if( xProp.is() && !( xProp->getPropertyValue( C2U( "NumberFormat" ) ) >>= nNumberFormatKey ) )
{
bool bFormatSet = false;
//check wether we have a percent scale -> use percent format
if( xNumberFormatsSupplier.is() )
{
ScaleData aData = AxisHelper::getDateCheckedScale( xAxis, Reference< frame::XModel >( xNumberFormatsSupplier, uno::UNO_QUERY ) );
if( aData.AxisType==AxisType::PERCENT )
{
sal_Int32 nPercentFormat = DiagramHelper::getPercentNumberFormat( xNumberFormatsSupplier );
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( xNumberFormatsSupplier );
bFormatSet = true;
}
}
else if( xChartDoc.is() && xChartDoc->hasInternalDataProvider() && nDimensionIndex == 0 ) //maybe date axis
{
Reference< chart2::XDiagram > xDiagram( xChartDoc->getFirstDiagram() );
if( DiagramHelper::isSupportingDateAxis( xDiagram ) )
{
nNumberFormatKey = DiagramHelper::getDateNumberFormat( xNumberFormatsSupplier );
}
else
{
Reference< data::XDataSource > xSource( DataSourceHelper::getUsedData( xChartDoc ) );
if( xSource.is() )
{
::std::vector< Reference< chart2::data::XLabeledDataSequence > > aXValues(
DataSeriesHelper::getAllDataSequencesByRole( xSource->getDataSequences(), C2U("values-x"), true ) );
if( aXValues.empty() )
{
Reference< data::XLabeledDataSequence > xCategories( DiagramHelper::getCategoriesFromDiagram( xDiagram ) );
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) && !::rtl::math::isNan(fTest) )
{
bHasValidDoubles=true;
break;
}
}
if( bHasValidDoubles )
nNumberFormatKey = DiagramHelper::getDateNumberFormat( xNumberFormatsSupplier );
}
}
}
}
}
bFormatSet = true;
}
}
if( !bFormatSet )
{
typedef ::std::map< sal_Int32, sal_Int32 > tNumberformatFrequency;
tNumberformatFrequency aKeyMap;
try
{
Reference< XChartTypeContainer > xCTCnt( xCorrespondingCoordinateSystem, uno::UNO_QUERY_THROW );
if( xCTCnt.is() )
{
::rtl::OUString aRoleToMatch;
if( nDimensionIndex == 0 )
aRoleToMatch = C2U("values-x");
Sequence< Reference< XChartType > > aChartTypes( xCTCnt->getChartTypes());
for( sal_Int32 nCTIdx=0; nCTIdx<aChartTypes.getLength(); ++nCTIdx )
{
if( nDimensionIndex != 0 )
aRoleToMatch = ChartTypeHelper::getRoleOfSequenceForYAxisNumberFormatDetection( aChartTypes[nCTIdx] );
Reference< XDataSeriesContainer > xDSCnt( aChartTypes[nCTIdx], uno::UNO_QUERY_THROW );
Sequence< Reference< XDataSeries > > aDataSeriesSeq( xDSCnt->getDataSeries());
for( sal_Int32 nSeriesIdx=0; nSeriesIdx<aDataSeriesSeq.getLength(); ++nSeriesIdx )
{
Reference< chart2::XDataSeries > xDataSeries(aDataSeriesSeq[nSeriesIdx]);
Reference< data::XDataSource > xSource( xDataSeries, uno::UNO_QUERY_THROW );
if( nDimensionIndex == 1 )
{
//only take those series into accoutn that are attached to this axis
sal_Int32 nAttachedAxisIndex = DataSeriesHelper::getAttachedAxisIndex(xDataSeries);
if( nAttachedAxisIndex != nAxisIndex )
continue;
}
Reference< data::XLabeledDataSequence > xLabeledSeq(
DataSeriesHelper::getDataSequenceByRole( xSource, 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 );
// initialize the value
if( aKeyMap.find( nKey ) == aKeyMap.end())
aKeyMap[ nKey ] = 0;
// increase frequency
aKeyMap[ nKey ] = (aKeyMap[ nKey ] + 1);
}
}
}
}
}
}
catch( const uno::Exception & ex )
{
ASSERT_EXCEPTION( ex );
}
if( ! aKeyMap.empty())
{
sal_Int32 nMaxFreq = 0;
// find most frequent key
for( tNumberformatFrequency::const_iterator aIt = aKeyMap.begin();
aIt != aKeyMap.end(); ++aIt )
{
OSL_TRACE( "NumberFormatKey %d appears %d times", (*aIt).first, (*aIt).second );
// all values must at least be 1
if( (*aIt).second > nMaxFreq )
{
nNumberFormatKey = (*aIt).first;
bNumberFormatKeyFoundViaAttachedData = true;
nMaxFreq = (*aIt).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;
Reference< XAxis > xParallelAxis( AxisHelper::getAxis( 1, nParallelAxisIndex, xCorrespondingCoordinateSystem ) );
nNumberFormatKey = AxisHelper::getExplicitNumberFormatKeyForAxis( xParallelAxis, xCorrespondingCoordinateSystem, xNumberFormatsSupplier, false );
}
}
}
}
return nNumberFormatKey;
}
Reference< XAxis > AxisHelper::createAxis(
sal_Int32 nDimensionIndex
, sal_Int32 nAxisIndex // 0==main or 1==secondary axis
, const Reference< XCoordinateSystem >& xCooSys
, const Reference< uno::XComponentContext > & xContext
, ReferenceSizeProvider * pRefSizeProvider )
{
if( !xContext.is() || !xCooSys.is() )
return NULL;
if( nDimensionIndex >= xCooSys->getDimension() )
return NULL;
Reference< XAxis > xAxis( xContext->getServiceManager()->createInstanceWithContext(
C2U( "com.sun.star.chart2.Axis" ), xContext ), uno::UNO_QUERY );
OSL_ASSERT( xAxis.is());
if( xAxis.is())
{
xCooSys->setAxisByDimension( nDimensionIndex, xAxis, nAxisIndex );
if( nAxisIndex>0 )//when inserting secondary axes copy some things from the main axis
{
::com::sun::star::chart::ChartAxisPosition eNewAxisPos( ::com::sun::star::chart::ChartAxisPosition_END );
Reference< XAxis > xMainAxis( xCooSys->getAxisByDimension( 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;
xAxis->setScaleData( aScale );
//ensure that the second axis is not placed on the main axis
Reference< beans::XPropertySet > xMainProp( xMainAxis, uno::UNO_QUERY );
if( xMainProp.is() )
{
::com::sun::star::chart::ChartAxisPosition eMainAxisPos( ::com::sun::star::chart::ChartAxisPosition_ZERO );
xMainProp->getPropertyValue(C2U( "CrossoverPosition" )) >>= eMainAxisPos;
if( ::com::sun::star::chart::ChartAxisPosition_END == eMainAxisPos )
eNewAxisPos = ::com::sun::star::chart::ChartAxisPosition_START;
}
}
Reference< beans::XPropertySet > xProp( xAxis, uno::UNO_QUERY );
if( xProp.is() )
xProp->setPropertyValue(C2U( "CrossoverPosition" ), uno::makeAny(eNewAxisPos) );
}
Reference< beans::XPropertySet > xProp( xAxis, uno::UNO_QUERY );
if( xProp.is() ) try
{
// set correct initial AutoScale
if( pRefSizeProvider )
pRefSizeProvider->setValuesAtPropertySet( xProp );
}
catch( uno::Exception& e )
{
ASSERT_EXCEPTION( e );
}
}
return xAxis;
}
Reference< XAxis > AxisHelper::createAxis( sal_Int32 nDimensionIndex, bool bMainAxis
, const Reference< chart2::XDiagram >& xDiagram
, const Reference< uno::XComponentContext >& xContext
, ReferenceSizeProvider * pRefSizeProvider )
{
OSL_ENSURE( xContext.is(), "need a context to create an axis" );
if( !xContext.is() )
return NULL;
sal_Int32 nAxisIndex = bMainAxis ? MAIN_AXIS_INDEX : SECONDARY_AXIS_INDEX;
sal_Int32 nCooSysIndex = 0;
Reference< XCoordinateSystem > xCooSys = AxisHelper::getCoordinateSystemByIndex( xDiagram, nCooSysIndex );
// create axis
return AxisHelper::createAxis(
nDimensionIndex, nAxisIndex, xCooSys, xContext, pRefSizeProvider );
}
void AxisHelper::showAxis( sal_Int32 nDimensionIndex, bool bMainAxis
, const Reference< chart2::XDiagram >& xDiagram
, const Reference< uno::XComponentContext >& xContext
, ReferenceSizeProvider * pRefSizeProvider )
{
if( !xDiagram.is() )
return;
bool bNewAxisCreated = false;
Reference< XAxis > xAxis( AxisHelper::getAxis( nDimensionIndex, bMainAxis, xDiagram ) );
if( !xAxis.is() && xContext.is() )
{
// create axis
bNewAxisCreated = true;
xAxis.set( 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 Reference< XDiagram >& xDiagram
, const Reference< uno::XComponentContext >& /*xContext*/ )
{
if( !xDiagram.is() )
return;
Reference< XCoordinateSystem > xCooSys = AxisHelper::getCoordinateSystemByIndex( xDiagram, nCooSysIndex );
if(!xCooSys.is())
return;
Reference< XAxis > xAxis( AxisHelper::getAxis( nDimensionIndex, MAIN_AXIS_INDEX, xCooSys ) );
if(!xAxis.is())
{
//hhhh todo create axis without axis visibility
}
if(!xAxis.is())
return;
if( bMainGrid )
AxisHelper::makeGridVisible( xAxis->getGridProperties() );
else
{
Sequence< Reference< beans::XPropertySet > > aSubGrids( xAxis->getSubGridProperties() );
for( sal_Int32 nN=0; nN<aSubGrids.getLength(); nN++)
AxisHelper::makeGridVisible( aSubGrids[nN] );
}
}
void AxisHelper::makeAxisVisible( const Reference< XAxis >& xAxis )
{
Reference< beans::XPropertySet > xProps( xAxis, uno::UNO_QUERY );
if( xProps.is() )
{
xProps->setPropertyValue( C2U( "Show" ), uno::makeAny( sal_True ) );
LineProperties::SetLineVisible( xProps );
xProps->setPropertyValue( C2U( "DisplayLabels" ), uno::makeAny( sal_True ) );
}
}
void AxisHelper::makeGridVisible( const Reference< beans::XPropertySet >& xGridProperties )
{
if( xGridProperties.is() )
{
xGridProperties->setPropertyValue( C2U( "Show" ), uno::makeAny( sal_True ) );
LineProperties::SetLineVisible( xGridProperties );
}
}
void AxisHelper::hideAxis( sal_Int32 nDimensionIndex, bool bMainAxis
, const Reference< XDiagram >& xDiagram )
{
AxisHelper::makeAxisInvisible( AxisHelper::getAxis( nDimensionIndex, bMainAxis, xDiagram ) );
}
void AxisHelper::makeAxisInvisible( const Reference< XAxis >& xAxis )
{
Reference< beans::XPropertySet > xProps( xAxis, uno::UNO_QUERY );
if( xProps.is() )
{
xProps->setPropertyValue( C2U( "Show" ), uno::makeAny( sal_False ) );
}
}
void AxisHelper::hideAxisIfNoDataIsAttached( const Reference< XAxis >& xAxis, const Reference< XDiagram >& xDiagram )
{
//axis is hidden if no data is attached anymore but data is available
bool bOtherSeriesAttachedToThisAxis = false;
::std::vector< Reference< chart2::XDataSeries > > aSeriesVector( DiagramHelper::getDataSeriesFromDiagram( xDiagram ) );
::std::vector< Reference< chart2::XDataSeries > >::const_iterator aIt = aSeriesVector.begin();
for( ; aIt != aSeriesVector.end(); ++aIt)
{
uno::Reference< chart2::XAxis > xCurrentAxis( DiagramHelper::getAttachedAxis( *aIt, xDiagram ), uno::UNO_QUERY );
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 Reference< XDiagram >& xDiagram )
{
if( !xDiagram.is() )
return;
Reference< XCoordinateSystem > xCooSys = AxisHelper::getCoordinateSystemByIndex( xDiagram, nCooSysIndex );
if(!xCooSys.is())
return;
Reference< XAxis > xAxis( AxisHelper::getAxis( nDimensionIndex, MAIN_AXIS_INDEX, xCooSys ) );
if(!xAxis.is())
return;
if( bMainGrid )
AxisHelper::makeGridInvisible( xAxis->getGridProperties() );
else
{
Sequence< Reference< beans::XPropertySet > > aSubGrids( xAxis->getSubGridProperties() );
for( sal_Int32 nN=0; nN<aSubGrids.getLength(); nN++)
AxisHelper::makeGridInvisible( aSubGrids[nN] );
}
}
void AxisHelper::makeGridInvisible( const Reference< beans::XPropertySet >& xGridProperties )
{
if( xGridProperties.is() )
{
xGridProperties->setPropertyValue( C2U( "Show" ), uno::makeAny( sal_False ) );
}
}
sal_Bool AxisHelper::isGridShown( sal_Int32 nDimensionIndex, sal_Int32 nCooSysIndex, bool bMainGrid
, const Reference< ::com::sun::star::chart2::XDiagram >& xDiagram )
{
sal_Bool bRet = false;
Reference< XCoordinateSystem > xCooSys = AxisHelper::getCoordinateSystemByIndex( xDiagram, nCooSysIndex );
if(!xCooSys.is())
return bRet;
Reference< XAxis > xAxis( AxisHelper::getAxis( nDimensionIndex, MAIN_AXIS_INDEX, xCooSys ) );
if(!xAxis.is())
return bRet;
if( bMainGrid )
bRet = AxisHelper::isGridVisible( xAxis->getGridProperties() );
else
{
Sequence< Reference< beans::XPropertySet > > aSubGrids( xAxis->getSubGridProperties() );
if( aSubGrids.getLength() )
bRet = AxisHelper::isGridVisible( aSubGrids[0] );
}
return bRet;
}
Reference< XCoordinateSystem > AxisHelper::getCoordinateSystemByIndex(
const Reference< XDiagram >& xDiagram, sal_Int32 nIndex )
{
Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY );
if(!xCooSysContainer.is())
return NULL;
Sequence< Reference< XCoordinateSystem > > aCooSysList = xCooSysContainer->getCoordinateSystems();
if(0<=nIndex && nIndex<aCooSysList.getLength())
return aCooSysList[nIndex];
return NULL;
}
Reference< XAxis > AxisHelper::getAxis( sal_Int32 nDimensionIndex, bool bMainAxis
, const Reference< XDiagram >& xDiagram )
{
Reference< XAxis > xRet;
try
{
Reference< XCoordinateSystem > xCooSys = AxisHelper::getCoordinateSystemByIndex( xDiagram, 0 );
xRet.set( AxisHelper::getAxis( nDimensionIndex, bMainAxis ? 0 : 1, xCooSys ) );
}
catch( const uno::Exception & )
{
}
return xRet;
}
Reference< XAxis > AxisHelper::getAxis( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex
, const Reference< XCoordinateSystem >& xCooSys )
{
Reference< XAxis > xRet;
try
{
if( xCooSys.is() )
xRet.set( xCooSys->getAxisByDimension( nDimensionIndex, nAxisIndex ) );
}
catch( const uno::Exception & )
{
}
return xRet;
}
Reference< XAxis > AxisHelper::getCrossingMainAxis( const Reference< XAxis >& xAxis
, const Reference< XCoordinateSystem >& xCooSys )
{
sal_Int32 nDimensionIndex = 0;
sal_Int32 nAxisIndex = 0;
AxisHelper::getIndicesForAxis( xAxis, xCooSys, nDimensionIndex, nAxisIndex );
if( 2==nDimensionIndex )
{
nDimensionIndex=1;
bool bSwapXY = false;
Reference< beans::XPropertySet > xCooSysProp( xCooSys, uno::UNO_QUERY );
if( xCooSysProp.is() && (xCooSysProp->getPropertyValue( C2U("SwapXAndYAxis") ) >>= bSwapXY) && bSwapXY )
nDimensionIndex=0;
}
else if( 1==nDimensionIndex )
nDimensionIndex=0;
else
nDimensionIndex=1;
return AxisHelper::getAxis( nDimensionIndex, 0, xCooSys );
}
Reference< XAxis > AxisHelper::getParallelAxis( const Reference< XAxis >& xAxis
, const Reference< XDiagram >& 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( uno::RuntimeException& )
{
}
return 0;
}
sal_Bool AxisHelper::isAxisShown( sal_Int32 nDimensionIndex, bool bMainAxis
, const Reference< XDiagram >& xDiagram )
{
return AxisHelper::isAxisVisible( AxisHelper::getAxis( nDimensionIndex, bMainAxis, xDiagram ) );
}
sal_Bool AxisHelper::isAxisVisible( const Reference< XAxis >& xAxis )
{
sal_Bool bRet = false;
Reference< beans::XPropertySet > xProps( xAxis, uno::UNO_QUERY );
if( xProps.is() )
{
xProps->getPropertyValue( C2U( "Show" ) ) >>= bRet;
bRet = bRet && ( LineProperties::IsLineVisible( xProps )
|| areAxisLabelsVisible( xProps ) );
}
return bRet;
}
sal_Bool AxisHelper::areAxisLabelsVisible( const Reference< beans::XPropertySet >& xAxisProperties )
{
sal_Bool bRet = false;
if( xAxisProperties.is() )
{
xAxisProperties->getPropertyValue( C2U( "DisplayLabels" ) ) >>= bRet;
}
return bRet;
}
sal_Bool AxisHelper::isGridVisible( const Reference< beans::XPropertySet >& xGridProperies )
{
sal_Bool bRet = false;
if( xGridProperies.is() )
{
xGridProperies->getPropertyValue( C2U( "Show" ) ) >>= bRet;
bRet = bRet && LineProperties::IsLineVisible( xGridProperies );
}
return bRet;
}
Reference< beans::XPropertySet > AxisHelper::getGridProperties(
const Reference< XCoordinateSystem >& xCooSys
, sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex, sal_Int32 nSubGridIndex )
{
Reference< beans::XPropertySet > xRet;
Reference< XAxis > xAxis( AxisHelper::getAxis( nDimensionIndex, nAxisIndex, xCooSys ) );
if( xAxis.is() )
{
if( nSubGridIndex<0 )
xRet.set( xAxis->getGridProperties() );
else
{
Sequence< Reference< beans::XPropertySet > > aSubGrids( xAxis->getSubGridProperties() );
if( nSubGridIndex >= 0 && nSubGridIndex < aSubGrids.getLength() )
xRet.set( aSubGrids[nSubGridIndex] );
}
}
return xRet;
}
sal_Int32 AxisHelper::getDimensionIndexOfAxis(
const Reference< XAxis >& xAxis
, const Reference< XDiagram >& 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 Reference< XAxis >& xAxis
, const Reference< XCoordinateSystem >& xCooSys
, sal_Int32& rOutDimensionIndex, sal_Int32& rOutAxisIndex )
{
//returns true if indices are found
rOutDimensionIndex = -1;
rOutAxisIndex = -1;
if( xCooSys.is() && xAxis.is() )
{
Reference< XAxis > 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->getAxisByDimension(nDimensionIndex,nAxisIndex);
if( xCurrentAxis == xAxis )
{
rOutDimensionIndex = nDimensionIndex;
rOutAxisIndex = nAxisIndex;
return true;
}
}
}
}
return false;
}
bool AxisHelper::getIndicesForAxis( const Reference< XAxis >& xAxis, const Reference< XDiagram >& xDiagram
, sal_Int32& rOutCooSysIndex, sal_Int32& rOutDimensionIndex, sal_Int32& rOutAxisIndex )
{
//returns true if indices are found
rOutCooSysIndex = -1;
rOutDimensionIndex = -1;
rOutAxisIndex = -1;
Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY );
if(xCooSysContainer.is())
{
Sequence< Reference< XCoordinateSystem > > aCooSysList = xCooSysContainer->getCoordinateSystems();
for( sal_Int32 nC=0; nC<aCooSysList.getLength(); ++nC )
{
if( AxisHelper::getIndicesForAxis( xAxis, aCooSysList[nC], rOutDimensionIndex, rOutAxisIndex ) )
{
rOutCooSysIndex = nC;
return true;
}
}
}
return false;
}
std::vector< Reference< XAxis > > AxisHelper::getAllAxesOfCoordinateSystem(
const Reference< XCoordinateSystem >& xCooSys
, bool bOnlyVisible /* = false */ )
{
std::vector< Reference< XAxis > > 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
{
Reference< XAxis > xAxis( xCooSys->getAxisByDimension( nDimensionIndex, nAxisIndex ) );
bool bAddAxis = true;
if( xAxis.is() )
{
if( bOnlyVisible )
{
Reference< beans::XPropertySet > xAxisProp( xAxis, uno::UNO_QUERY );
if( !xAxisProp.is() ||
!(xAxisProp->getPropertyValue( C2U("Show")) >>= bAddAxis) )
bAddAxis = false;
}
if( bAddAxis )
aAxisVector.push_back( xAxis );
}
}
catch( const uno::Exception & ex )
{
ASSERT_EXCEPTION( ex );
}
}
}
}
}
return aAxisVector;
}
Sequence< Reference< XAxis > > AxisHelper::getAllAxesOfDiagram(
const Reference< XDiagram >& xDiagram
, bool bOnlyVisible )
{
std::vector< Reference< XAxis > > aAxisVector;
Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY );
if(xCooSysContainer.is())
{
Sequence< Reference< XCoordinateSystem > > aCooSysList = xCooSysContainer->getCoordinateSystems();
sal_Int32 nC = 0;
for( nC=0; nC<aCooSysList.getLength(); ++nC )
{
std::vector< Reference< XAxis > > aAxesPerCooSys( AxisHelper::getAllAxesOfCoordinateSystem( aCooSysList[nC], bOnlyVisible ) );
aAxisVector.insert( aAxisVector.end(), aAxesPerCooSys.begin(), aAxesPerCooSys.end() );
}
}
return ContainerHelper::ContainerToSequence( aAxisVector );
}
Sequence< Reference< beans::XPropertySet > > AxisHelper::getAllGrids( const Reference< XDiagram >& xDiagram )
{
Sequence< Reference< XAxis > > aAllAxes( AxisHelper::getAllAxesOfDiagram( xDiagram ) );
std::vector< Reference< beans::XPropertySet > > aGridVector;
sal_Int32 nA = 0;
for( nA=0; nA<aAllAxes.getLength(); ++nA )
{
Reference< XAxis > xAxis( aAllAxes[nA] );
if(!xAxis.is())
continue;
Reference< beans::XPropertySet > xGridProperties( xAxis->getGridProperties() );
if( xGridProperties.is() )
aGridVector.push_back( xGridProperties );
Sequence< Reference< beans::XPropertySet > > aSubGrids( xAxis->getSubGridProperties() );;
sal_Int32 nSubGrid = 0;
for( nSubGrid = 0; nSubGrid < aSubGrids.getLength(); ++nSubGrid )
{
Reference< beans::XPropertySet > xSubGrid( aSubGrids[nSubGrid] );
if( xSubGrid.is() )
aGridVector.push_back( xSubGrid );
}
}
return ContainerHelper::ContainerToSequence( aGridVector );
}
void AxisHelper::getAxisOrGridPossibilities( Sequence< sal_Bool >& rPossibilityList
, const Reference< XDiagram>& xDiagram, sal_Bool bAxis )
{
rPossibilityList.realloc(6);
sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram );
//set possibilities:
sal_Int32 nIndex=0;
Reference< XChartType > xChartType = DiagramHelper::getChartTypeByIndex( xDiagram, 0 );
for(nIndex=0;nIndex<3;nIndex++)
rPossibilityList[nIndex]=ChartTypeHelper::isSupportingMainAxis(xChartType,nDimensionCount,nIndex);
for(nIndex=3;nIndex<6;nIndex++)
if( bAxis )
rPossibilityList[nIndex]=ChartTypeHelper::isSupportingSecondaryAxis(xChartType,nDimensionCount,nIndex-3);
else
rPossibilityList[nIndex] = rPossibilityList[nIndex-3];
}
bool AxisHelper::isSecondaryYAxisNeeded( const Reference< XCoordinateSystem >& xCooSys )
{
Reference< chart2::XChartTypeContainer > xCTCnt( xCooSys, uno::UNO_QUERY );
if( xCTCnt.is() )
{
Sequence< Reference< chart2::XChartType > > aChartTypes( xCTCnt->getChartTypes() );
for( sal_Int32 i=0; i<aChartTypes.getLength(); ++i )
{
Reference< XDataSeriesContainer > xSeriesContainer( aChartTypes[i] , uno::UNO_QUERY );
if( !xSeriesContainer.is() )
continue;
Sequence< Reference< XDataSeries > > aSeriesList( xSeriesContainer->getDataSeries() );
for( sal_Int32 nS = aSeriesList.getLength(); nS-- ; )
{
Reference< beans::XPropertySet > xProp( aSeriesList[nS], uno::UNO_QUERY );
if(xProp.is())
{
sal_Int32 nAttachedAxisIndex = 0;
if( ( xProp->getPropertyValue( C2U( "AttachedAxisIndex" ) ) >>= nAttachedAxisIndex ) && nAttachedAxisIndex>0 )
return true;
}
}
}
}
return false;
}
bool AxisHelper::shouldAxisBeDisplayed( const Reference< XAxis >& xAxis
, const Reference< XCoordinateSystem >& 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();
Reference< XChartType > xChartType( AxisHelper::getChartTypeByIndex( xCooSys, 0 ) );
bool bMainAxis = (nAxisIndex==MAIN_AXIS_INDEX);
if( bMainAxis )
bRet = ChartTypeHelper::isSupportingMainAxis(xChartType,nDimensionCount,nDimensionIndex);
else
bRet = ChartTypeHelper::isSupportingSecondaryAxis(xChartType,nDimensionCount,nDimensionIndex);
}
}
return bRet;
}
void AxisHelper::getAxisOrGridExcistence( Sequence< sal_Bool >& rExistenceList
, const Reference< XDiagram>& xDiagram, sal_Bool bAxis )
{
rExistenceList.realloc(6);
if(bAxis)
{
sal_Int32 nN;
Reference< XAxis > xAxis;
for(nN=0;nN<3;nN++)
rExistenceList[nN] = AxisHelper::isAxisShown( nN, true, xDiagram );
for(nN=3;nN<6;nN++)
rExistenceList[nN] = AxisHelper::isAxisShown( nN%3, false, xDiagram );
}
else
{
sal_Int32 nN;
for(nN=0;nN<3;nN++)
rExistenceList[nN] = AxisHelper::isGridShown( nN, 0, true, xDiagram );
for(nN=3;nN<6;nN++)
rExistenceList[nN] = AxisHelper::isGridShown( nN%3, 0, false, xDiagram );
}
}
bool AxisHelper::changeVisibilityOfAxes( const Reference< XDiagram >& 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 Reference< XDiagram >& xDiagram
, const Sequence< sal_Bool >& rOldExistenceList
, const Sequence< sal_Bool >& rNewExistenceList
, const Reference< uno::XComponentContext >& xContext )
{
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, xContext );
else
AxisHelper::hideGrid( nN%3, 0, nN<3, xDiagram );
}
}
return bChanged;
}
Reference< XCoordinateSystem > AxisHelper::getCoordinateSystemOfAxis(
const Reference< XAxis >& xAxis
, const Reference< XDiagram >& xDiagram )
{
Reference< XCoordinateSystem > xRet;
Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY );
if( xCooSysContainer.is() )
{
Reference< XCoordinateSystem > xCooSys;
Sequence< Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() );
for( sal_Int32 nCooSysIndex = 0; nCooSysIndex < aCooSysList.getLength(); ++nCooSysIndex )
{
xCooSys = aCooSysList[nCooSysIndex];
std::vector< Reference< XAxis > > aAllAxis( AxisHelper::getAllAxesOfCoordinateSystem( xCooSys ) );
::std::vector< Reference< XAxis > >::iterator aFound =
::std::find( aAllAxis.begin(), aAllAxis.end(), xAxis );
if( aFound != aAllAxis.end())
{
xRet.set( xCooSys );
break;
}
}
}
return xRet;
}
Reference< XChartType > AxisHelper::getChartTypeByIndex( const Reference< XCoordinateSystem >& xCooSys, sal_Int32 nIndex )
{
Reference< XChartType > xChartType;
Reference< XChartTypeContainer > xChartTypeContainer( xCooSys, uno::UNO_QUERY );
if( xChartTypeContainer.is() )
{
Sequence< Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() );
if( nIndex >= 0 && nIndex < aChartTypeList.getLength() )
xChartType.set( aChartTypeList[nIndex] );
}
return xChartType;
}
void AxisHelper::setRTLAxisLayout( const Reference< XCoordinateSystem >& xCooSys )
{
if( xCooSys.is() )
{
bool bCartesian = xCooSys->getViewServiceName().equals( CHART2_COOSYSTEM_CARTESIAN_VIEW_SERVICE_NAME );
if( bCartesian )
{
bool bVertical = false;
Reference< beans::XPropertySet > xCooSysProp( xCooSys, uno::UNO_QUERY );
if( xCooSysProp.is() )
xCooSysProp->getPropertyValue( C2U("SwapXAndYAxis") ) >>= bVertical;
sal_Int32 nHorizontalAxisDimension = bVertical ? 1 : 0;
sal_Int32 nVerticalAxisDimension = bVertical ? 0 : 1;
try
{
//reverse direction for horizontal main axis
Reference< chart2::XAxis > 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
Reference< chart2::XAxis > 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( uno::Exception & ex )
{
ASSERT_EXCEPTION( ex );
}
try
{
//reverse direction for horizontal secondary axis
Reference< chart2::XAxis > 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
Reference< chart2::XAxis > 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( uno::Exception & ex )
{
ASSERT_EXCEPTION( ex );
}
}
}
}
Reference< XChartType > AxisHelper::getFirstChartTypeWithSeriesAttachedToAxisIndex( const Reference< chart2::XDiagram >& xDiagram, const sal_Int32 nAttachedAxisIndex )
{
Reference< XChartType > xChartType;
::std::vector< Reference< XDataSeries > > aSeriesVector( DiagramHelper::getDataSeriesFromDiagram( xDiagram ) );
::std::vector< Reference< XDataSeries > >::const_iterator aIter = aSeriesVector.begin();
for( ; aIter != aSeriesVector.end(); aIter++ )
{
sal_Int32 nCurrentIndex = DataSeriesHelper::getAttachedAxisIndex( *aIter );
if( nAttachedAxisIndex == nCurrentIndex )
{
xChartType = DiagramHelper::getChartTypeOfSeries( xDiagram, *aIter );
if(xChartType.is())
break;
}
}
return xChartType;
}
bool AxisHelper::isAxisPositioningEnabled()
{
const SvtSaveOptions::ODFDefaultVersion nCurrentVersion( SvtSaveOptions().GetODFDefaultVersion() );
return nCurrentVersion >= SvtSaveOptions::ODFVER_012;
}
//.............................................................................
} //namespace chart
//.............................................................................
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */