diff options
Diffstat (limited to 'chart2/source/tools')
75 files changed, 25248 insertions, 0 deletions
diff --git a/chart2/source/tools/AxisHelper.cxx b/chart2/source/tools/AxisHelper.cxx new file mode 100644 index 000000000000..8cdd24e4dc05 --- /dev/null +++ b/chart2/source/tools/AxisHelper.cxx @@ -0,0 +1,976 @@ +/************************************************************************* + * + * 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 <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 <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; + +//static +Reference< chart2::XScaling > AxisHelper::createLinearScaling() +{ + return new LinearScaling( 1.0, 0.0 ); +} + +//static +Reference< chart2::XScaling > AxisHelper::createLogarithmicScaling( double fBase ) +{ + return new LogarithmicScaling( fBase ); +} + +//static +ScaleData AxisHelper::createDefaultScale() +{ + ScaleData aScaleData; + aScaleData.AxisType = chart2::AxisType::REALNUMBER; + Sequence< SubIncrement > aSubIncrements(1); + aSubIncrements[0] = SubIncrement(); + aScaleData.IncrementData.SubIncrements = aSubIncrements; + return aScaleData; +} + +//static +void AxisHelper::removeExplicitScaling( ScaleData& rScaleData ) +{ + uno::Any aEmpty; + rScaleData.Minimum = rScaleData.Maximum = rScaleData.Origin = aEmpty; + rScaleData.Scaling = 0; +} + +//static +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; +} + +//static +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.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; +} + +//static +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 ); +} + +//static +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 ); +} + +//static +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] ); + } +} + +//static +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 ) ); + } +} + +//static +void AxisHelper::makeGridVisible( const Reference< beans::XPropertySet >& xGridProperties ) +{ + if( xGridProperties.is() ) + { + xGridProperties->setPropertyValue( C2U( "Show" ), uno::makeAny( sal_True ) ); + LineProperties::SetLineVisible( xGridProperties ); + } +} + +//static +void AxisHelper::hideAxis( sal_Int32 nDimensionIndex, bool bMainAxis + , const Reference< XDiagram >& xDiagram ) +{ + AxisHelper::makeAxisInvisible( AxisHelper::getAxis( nDimensionIndex, bMainAxis, xDiagram ) ); +} + +//static +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 ) ); + } +} + +//static +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] ); + } +} + +//static +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; +} + +//static +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; +} + +//static +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; +} + +//static +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; +} + +//static +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 ); +} + +//static +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 ) ); +} + +//static +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; +} + +//static +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; +} + +//static +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; +} + +//static +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; +} + +//static +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; +} + +//static +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; +} + +//static +std::vector< Reference< XAxis > > AxisHelper::getAllAxesOfCoordinateSystem( + const Reference< XCoordinateSystem >& xCooSys + , bool bOnlyVisible /* = false */ ) +{ + std::vector< Reference< XAxis > > aAxisVector; + + if(xCooSys.is()) + { + sal_Int32 nDimensionIndex = 0; + sal_Int32 nMaxDimensionIndex = xCooSys->getDimension() -1; + if( nMaxDimensionIndex>=0 ) + { + for(nDimensionIndex=0; 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; +} + +//static +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 ); +} + +//static +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 ); +} + +//static +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]; +} + +//static +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; +} + +//static +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; +} + +//static +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 ); + } +} + +//static +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; +} + +//static +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; +} + +//static +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 +//............................................................................. diff --git a/chart2/source/tools/BaseGFXHelper.cxx b/chart2/source/tools/BaseGFXHelper.cxx new file mode 100644 index 000000000000..0ec7df9b7d71 --- /dev/null +++ b/chart2/source/tools/BaseGFXHelper.cxx @@ -0,0 +1,222 @@ +/************************************************************************* + * + * 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 "BaseGFXHelper.hxx" +#include <com/sun/star/drawing/DoubleSequence.hpp> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::drawing; +using namespace ::basegfx; + +namespace chart +{ +namespace BaseGFXHelper +{ + +::basegfx::B3DRange getBoundVolume( const drawing::PolyPolygonShape3D& rPolyPoly ) +{ + ::basegfx::B3DRange aRet; + + bool bInited = false; + sal_Int32 nPolyCount = rPolyPoly.SequenceX.getLength(); + for(sal_Int32 nPoly = 0; nPoly < nPolyCount; nPoly++) + { + sal_Int32 nPointCount = rPolyPoly.SequenceX[nPoly].getLength(); + for( sal_Int32 nPoint = 0; nPoint < nPointCount; nPoint++) + { + if(!bInited) + { + aRet = ::basegfx::B3DRange(::basegfx::B3DTuple( + rPolyPoly.SequenceX[nPoly][nPoint] + , rPolyPoly.SequenceY[nPoly][nPoint] + , rPolyPoly.SequenceZ[nPoly][nPoint])); + bInited = true; + } + else + { + aRet.expand( ::basegfx::B3DTuple( + rPolyPoly.SequenceX[nPoly][nPoint] + , rPolyPoly.SequenceY[nPoly][nPoint] + , rPolyPoly.SequenceZ[nPoly][nPoint])); + } + } + } + + return aRet; +} + +B2IRectangle makeRectangle( const awt::Point& rPos, const awt::Size& rSize ) +{ + return B2IRectangle(rPos.X,rPos.Y,rPos.X+rSize.Width,rPos.Y+rSize.Height); +} + +awt::Point B2IRectangleToAWTPoint( const ::basegfx::B2IRectangle& rB2IRectangle ) +{ + return awt::Point( rB2IRectangle.getMinX(), rB2IRectangle.getMinY() ); +} + +awt::Size B2IRectangleToAWTSize( const ::basegfx::B2IRectangle& rB2IRectangle ) +{ + return awt::Size( static_cast< sal_Int32 >( rB2IRectangle.getWidth()), + static_cast< sal_Int32 >( rB2IRectangle.getHeight())); +} + +awt::Rectangle B2IRectangleToAWTRectangle( + const ::basegfx::B2IRectangle& rB2IRectangle ) +{ + return awt::Rectangle( rB2IRectangle.getMinX(), rB2IRectangle.getMinY(), + static_cast< sal_Int32 >( rB2IRectangle.getWidth()), + static_cast< sal_Int32 >( rB2IRectangle.getHeight())); +} + +B3DVector Direction3DToB3DVector( const Direction3D& rDirection ) +{ + return B3DVector( + rDirection.DirectionX + , rDirection.DirectionY + , rDirection.DirectionZ + ); +} + +Direction3D B3DVectorToDirection3D( const B3DVector& rB3DVector ) +{ + return Direction3D( + rB3DVector.getX() + , rB3DVector.getY() + , rB3DVector.getZ() + ); +} + +B3DVector Position3DToB3DVector( const Position3D& rPosition ) +{ + return B3DVector( + rPosition.PositionX + , rPosition.PositionY + , rPosition.PositionZ + ); +} + +Position3D B3DVectorToPosition3D( const B3DVector& rB3DVector ) +{ + return Position3D( + rB3DVector.getX() + , rB3DVector.getY() + , rB3DVector.getZ() + ); +} + +B3DHomMatrix HomogenMatrixToB3DHomMatrix( const HomogenMatrix & rHomogenMatrix ) +{ + B3DHomMatrix aResult; + + aResult.set( 0, 0, rHomogenMatrix.Line1.Column1 ); + aResult.set( 0, 1, rHomogenMatrix.Line1.Column2 ); + aResult.set( 0, 2, rHomogenMatrix.Line1.Column3 ); + aResult.set( 0, 3, rHomogenMatrix.Line1.Column4 ); + + aResult.set( 1, 0, rHomogenMatrix.Line2.Column1 ); + aResult.set( 1, 1, rHomogenMatrix.Line2.Column2 ); + aResult.set( 1, 2, rHomogenMatrix.Line2.Column3 ); + aResult.set( 1, 3, rHomogenMatrix.Line2.Column4 ); + + aResult.set( 2, 0, rHomogenMatrix.Line3.Column1 ); + aResult.set( 2, 1, rHomogenMatrix.Line3.Column2 ); + aResult.set( 2, 2, rHomogenMatrix.Line3.Column3 ); + aResult.set( 2, 3, rHomogenMatrix.Line3.Column4 ); + + aResult.set( 3, 0, rHomogenMatrix.Line4.Column1 ); + aResult.set( 3, 1, rHomogenMatrix.Line4.Column2 ); + aResult.set( 3, 2, rHomogenMatrix.Line4.Column3 ); + aResult.set( 3, 3, rHomogenMatrix.Line4.Column4 ); + + return aResult; +} + +HomogenMatrix B3DHomMatrixToHomogenMatrix( const B3DHomMatrix & rB3DMatrix ) +{ + HomogenMatrix aResult; + + aResult.Line1.Column1 = rB3DMatrix.get( 0, 0 ); + aResult.Line1.Column2 = rB3DMatrix.get( 0, 1 ); + aResult.Line1.Column3 = rB3DMatrix.get( 0, 2 ); + aResult.Line1.Column4 = rB3DMatrix.get( 0, 3 ); + + aResult.Line2.Column1 = rB3DMatrix.get( 1, 0 ); + aResult.Line2.Column2 = rB3DMatrix.get( 1, 1 ); + aResult.Line2.Column3 = rB3DMatrix.get( 1, 2 ); + aResult.Line2.Column4 = rB3DMatrix.get( 1, 3 ); + + aResult.Line3.Column1 = rB3DMatrix.get( 2, 0 ); + aResult.Line3.Column2 = rB3DMatrix.get( 2, 1 ); + aResult.Line3.Column3 = rB3DMatrix.get( 2, 2 ); + aResult.Line3.Column4 = rB3DMatrix.get( 2, 3 ); + + aResult.Line4.Column1 = rB3DMatrix.get( 3, 0 ); + aResult.Line4.Column2 = rB3DMatrix.get( 3, 1 ); + aResult.Line4.Column3 = rB3DMatrix.get( 3, 2 ); + aResult.Line4.Column4 = rB3DMatrix.get( 3, 3 ); + + return aResult; +} + +B3DTuple GetRotationFromMatrix( const B3DHomMatrix & rB3DMatrix ) +{ + B3DTuple aScale, aTranslation, aRotation, aShearing; + rB3DMatrix.decompose( aScale, aTranslation, aRotation, aShearing ); + return aRotation; +} + +B3DTuple GetScaleFromMatrix( const B3DHomMatrix & rB3DMatrix ) +{ + B3DTuple aScale, aTranslation, aRotation, aShearing; + rB3DMatrix.decompose( aScale, aTranslation, aRotation, aShearing ); + return aScale; +} + +void ReduceToRotationMatrix( ::basegfx::B3DHomMatrix & rB3DMatrix ) +{ + B3DTuple aR( GetRotationFromMatrix( rB3DMatrix ) ); + ::basegfx::B3DHomMatrix aRotationMatrix; + aRotationMatrix.rotate(aR.getX(),aR.getY(),aR.getZ()); + rB3DMatrix = aRotationMatrix; +} + +double Deg2Rad( double fDegrees ) +{ + return fDegrees * ( F_PI / 180.0 ); +} + +double Rad2Deg( double fRadians ) +{ + return fRadians * ( 180.0 / F_PI ); +} + +} // namespace BaseGFXHelper +} // namespace chart diff --git a/chart2/source/tools/CachedDataSequence.cxx b/chart2/source/tools/CachedDataSequence.cxx new file mode 100644 index 000000000000..678cd8ba8314 --- /dev/null +++ b/chart2/source/tools/CachedDataSequence.cxx @@ -0,0 +1,409 @@ +/************************************************************************* + * + * 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 "CachedDataSequence.hxx" +#include "macros.hxx" +#include "PropertyHelper.hxx" +#include "ContainerHelper.hxx" +#include "CommonFunctors.hxx" +#include "ModifyListenerHelper.hxx" + +#include <comphelper/sequenceashashmap.hxx> + +#include <algorithm> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <rtl/math.hxx> + +using namespace ::com::sun::star; +using namespace ::chart::ContainerHelper; + +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Any; +using ::rtl::OUString; +using ::osl::MutexGuard; + +// necessary for MS compiler +using ::comphelper::OPropertyContainer; +using ::comphelper::OMutexAndBroadcastHelper; +using ::comphelper::OPropertyArrayUsageHelper; +using ::chart::impl::CachedDataSequence_Base; + +namespace +{ +static const OUString lcl_aServiceName( + RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.chart.CachedDataSequence" )); + +enum +{ +// PROP_SOURCE_IDENTIFIER, + PROP_NUMBERFORMAT_KEY, + PROP_PROPOSED_ROLE +}; +} // anonymous namespace + + +// ____________________ +namespace chart +{ + +CachedDataSequence::CachedDataSequence() + : OPropertyContainer( GetBroadcastHelper()), + CachedDataSequence_Base( GetMutex()), + m_eCurrentDataType( NUMERICAL ), + m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()) +{ + registerProperties(); +} +CachedDataSequence::CachedDataSequence( const Reference< uno::XComponentContext > & /*xContext*/ ) + : OPropertyContainer( GetBroadcastHelper()), + CachedDataSequence_Base( GetMutex()), + m_eCurrentDataType( MIXED ), + m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder( )) +{ + registerProperties(); +} + +CachedDataSequence::CachedDataSequence( const OUString & rSingleText ) + : OPropertyContainer( GetBroadcastHelper()), + CachedDataSequence_Base( GetMutex()), + m_eCurrentDataType( TEXTUAL ), + m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()) +{ + m_aTextualSequence.realloc(1); + m_aTextualSequence[0] = rSingleText; + registerProperties(); +} + +CachedDataSequence::CachedDataSequence( const CachedDataSequence & rSource ) + : OMutexAndBroadcastHelper(), + OPropertyContainer( GetBroadcastHelper()), + OPropertyArrayUsageHelper< CachedDataSequence >(), + CachedDataSequence_Base( GetMutex()), + m_nNumberFormatKey( rSource.m_nNumberFormatKey ), + m_sRole( rSource.m_sRole ), + m_eCurrentDataType( rSource.m_eCurrentDataType ), + m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()) +{ + switch( m_eCurrentDataType ) + { + case TEXTUAL: + m_aTextualSequence = rSource.m_aTextualSequence; + break; + case NUMERICAL: + m_aNumericalSequence = rSource.m_aNumericalSequence; + break; + case MIXED: + m_aMixedSequence = rSource.m_aMixedSequence; + break; + } + + registerProperties(); +} + +CachedDataSequence::~CachedDataSequence() +{} + +void CachedDataSequence::registerProperties() +{ + registerProperty( C2U( "NumberFormatKey" ), + PROP_NUMBERFORMAT_KEY, + 0, // PropertyAttributes + & m_nNumberFormatKey, + ::getCppuType( & m_nNumberFormatKey ) ); + + registerProperty( C2U( "Role" ), + PROP_PROPOSED_ROLE, + 0, // PropertyAttributes + & m_sRole, + ::getCppuType( & m_sRole ) ); +} + +Sequence< double > CachedDataSequence::Impl_getNumericalData() const +{ + if( m_eCurrentDataType == NUMERICAL ) + return m_aNumericalSequence; + + sal_Int32 nSize = ( m_eCurrentDataType == TEXTUAL ) + ? m_aTextualSequence.getLength() + : m_aMixedSequence.getLength(); + + Sequence< double > aResult( nSize ); + double * pResultArray = aResult.getArray(); + + if( m_eCurrentDataType == TEXTUAL ) + { + const OUString * pTextArray = m_aTextualSequence.getConstArray(); + ::std::transform( pTextArray, pTextArray + nSize, + pResultArray, + CommonFunctors::OUStringToDouble() ); + } + else + { + OSL_ASSERT( m_eCurrentDataType == MIXED ); + const Any * pMixedArray = m_aMixedSequence.getConstArray(); + ::std::transform( pMixedArray, pMixedArray + nSize, + pResultArray, + CommonFunctors::AnyToDouble() ); + } + return aResult; +} + +Sequence< OUString > CachedDataSequence::Impl_getTextualData() const +{ + if( m_eCurrentDataType == TEXTUAL ) + return m_aTextualSequence; + + sal_Int32 nSize = ( m_eCurrentDataType == NUMERICAL ) + ? m_aNumericalSequence.getLength() + : m_aMixedSequence.getLength(); + + Sequence< OUString > aResult( nSize ); + OUString * pResultArray = aResult.getArray(); + + if( m_eCurrentDataType == NUMERICAL ) + { + const double * pTextArray = m_aNumericalSequence.getConstArray(); + ::std::transform( pTextArray, pTextArray + nSize, + pResultArray, + CommonFunctors::DoubleToOUString() ); + } + else + { + OSL_ASSERT( m_eCurrentDataType == MIXED ); + const Any * pMixedArray = m_aMixedSequence.getConstArray(); + ::std::transform( pMixedArray, pMixedArray + nSize, + pResultArray, + CommonFunctors::AnyToString() ); + } + + return aResult; +} + +Sequence< Any > CachedDataSequence::Impl_getMixedData() const +{ + if( m_eCurrentDataType == MIXED ) + return m_aMixedSequence; + + sal_Int32 nSize = ( m_eCurrentDataType == NUMERICAL ) + ? m_aNumericalSequence.getLength() + : m_aTextualSequence.getLength(); + + Sequence< Any > aResult( nSize ); + Any * pResultArray = aResult.getArray(); + + if( m_eCurrentDataType == NUMERICAL ) + { + const double * pTextArray = m_aNumericalSequence.getConstArray(); + ::std::transform( pTextArray, pTextArray + nSize, + pResultArray, + CommonFunctors::makeAny< double >() ); + } + else + { + OSL_ASSERT( m_eCurrentDataType == TEXTUAL ); + const OUString * pMixedArray = m_aTextualSequence.getConstArray(); + ::std::transform( pMixedArray, pMixedArray + nSize, + pResultArray, + CommonFunctors::makeAny< OUString >() ); + } + + return aResult; +} + +// ================================================================================ + +Sequence< OUString > CachedDataSequence::getSupportedServiceNames_Static() +{ + Sequence< OUString > aServices( 4 ); + aServices[ 0 ] = lcl_aServiceName; + aServices[ 1 ] = C2U( "com.sun.star.chart2.data.DataSequence" ); + aServices[ 2 ] = C2U( "com.sun.star.chart2.data.NumericalDataSequence" ); + aServices[ 3 ] = C2U( "com.sun.star.chart2.data.TextualDataSequence" ); + return aServices; +} + +IMPLEMENT_FORWARD_XINTERFACE2( CachedDataSequence, CachedDataSequence_Base, OPropertyContainer ) +IMPLEMENT_FORWARD_XTYPEPROVIDER2( CachedDataSequence, CachedDataSequence_Base, OPropertyContainer ) + +// ____ XPropertySet ____ +Reference< beans::XPropertySetInfo > SAL_CALL CachedDataSequence::getPropertySetInfo() + throw(uno::RuntimeException) +{ + return Reference< beans::XPropertySetInfo >( createPropertySetInfo( getInfoHelper() ) ); +} + +// ____ ::comphelper::OPropertySetHelper ____ +// __________________________________________ +::cppu::IPropertyArrayHelper& CachedDataSequence::getInfoHelper() +{ + return *getArrayHelper(); +} + +// ____ ::comphelper::OPropertyArrayHelper ____ +// ____________________________________________ +::cppu::IPropertyArrayHelper* CachedDataSequence::createArrayHelper() const +{ + Sequence< beans::Property > aProps; + // describes all properties which have been registered in the ctor + describeProperties( aProps ); + + return new ::cppu::OPropertyArrayHelper( aProps ); +} + +// implement XServiceInfo methods basing upon getSupportedServiceNames_Static +APPHELPER_XSERVICEINFO_IMPL( CachedDataSequence, lcl_aServiceName ) + +// ================================================================================ + +// ________ XNumericalDataSequence ________ +Sequence< double > SAL_CALL CachedDataSequence::getNumericalData() + throw (uno::RuntimeException) +{ + // /-- + MutexGuard aGuard( GetMutex() ); + + if( m_eCurrentDataType == NUMERICAL ) + return m_aNumericalSequence; + else + return Impl_getNumericalData(); + // \-- +} + +// ________ XTextualDataSequence ________ +Sequence< OUString > SAL_CALL CachedDataSequence::getTextualData() + throw (uno::RuntimeException) +{ + // /-- + MutexGuard aGuard( GetMutex() ); + + if( m_eCurrentDataType == TEXTUAL ) + return m_aTextualSequence; + else + return Impl_getTextualData(); + // \-- +} + +// void SAL_CALL CachedDataSequence::setTextualData( const Sequence< OUString >& aData ) +// throw (uno::RuntimeException) +// { +// // /-- +// MutexGuard aGuard( GetMutex() ); +// Impl_setTextualData( aData ); +// // \-- +// } + +// ________ XDataSequence ________ +Sequence< Any > SAL_CALL CachedDataSequence::getData() + throw (uno::RuntimeException) +{ + // /-- + MutexGuard aGuard( GetMutex() ); + return Impl_getMixedData(); + // \-- +} + +OUString SAL_CALL CachedDataSequence::getSourceRangeRepresentation() + throw (uno::RuntimeException) +{ + return m_sRole; +} + +Sequence< OUString > SAL_CALL CachedDataSequence::generateLabel( chart2::data::LabelOrigin /*eLabelOrigin*/ ) + throw (uno::RuntimeException) +{ + // return empty label, as we have no range representaions to determine something useful + return Sequence< OUString >(); +} + +::sal_Int32 SAL_CALL CachedDataSequence::getNumberFormatKeyByIndex( ::sal_Int32 /*nIndex*/ ) + throw (lang::IndexOutOfBoundsException, + uno::RuntimeException) +{ + return 0; +} + +Reference< util::XCloneable > SAL_CALL CachedDataSequence::createClone() + throw (uno::RuntimeException) +{ + CachedDataSequence * pNewSeq = new CachedDataSequence( *this ); + + return Reference< util::XCloneable >( pNewSeq ); +} + +void SAL_CALL CachedDataSequence::addModifyListener( const Reference< util::XModifyListener >& aListener ) + throw (uno::RuntimeException) +{ + try + { + Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW ); + xBroadcaster->addModifyListener( aListener ); + } + catch( const uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } +} + +void SAL_CALL CachedDataSequence::removeModifyListener( const Reference< util::XModifyListener >& aListener ) + throw (uno::RuntimeException) +{ + try + { + Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW ); + xBroadcaster->removeModifyListener( aListener ); + } + catch( const uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } +} + +// lang::XInitialization: +void SAL_CALL CachedDataSequence::initialize(const uno::Sequence< uno::Any > & _aArguments) throw (uno::RuntimeException, uno::Exception) +{ + ::comphelper::SequenceAsHashMap aMap(_aArguments); + m_aNumericalSequence = aMap.getUnpackedValueOrDefault(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DataSequence")),m_aNumericalSequence); + if ( m_aNumericalSequence.getLength() ) + m_eCurrentDataType = NUMERICAL; + else + { + m_aTextualSequence = aMap.getUnpackedValueOrDefault(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DataSequence")),m_aTextualSequence); + if ( m_aTextualSequence.getLength() ) + m_eCurrentDataType = TEXTUAL; + else + { + m_aMixedSequence = aMap.getUnpackedValueOrDefault(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DataSequence")),m_aMixedSequence); + if ( m_aMixedSequence.getLength() ) + m_eCurrentDataType = MIXED; + } + } +} +} // namespace chart diff --git a/chart2/source/tools/CharacterProperties.cxx b/chart2/source/tools/CharacterProperties.cxx new file mode 100644 index 000000000000..cca655780a79 --- /dev/null +++ b/chart2/source/tools/CharacterProperties.cxx @@ -0,0 +1,608 @@ +/************************************************************************* + * + * 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 "CharacterProperties.hxx" +#include "ContainerHelper.hxx" +#include "macros.hxx" + +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/style/XStyle.hpp> +#include <com/sun/star/awt/FontSlant.hpp> +#include <com/sun/star/lang/Locale.hpp> + +#include <com/sun/star/awt/FontFamily.hpp> +#include <com/sun/star/awt/CharSet.hpp> +#include <com/sun/star/awt/FontPitch.hpp> +#include <com/sun/star/awt/FontUnderline.hpp> +#include <com/sun/star/awt/FontWeight.hpp> +#include <com/sun/star/awt/FontSlant.hpp> +#include <com/sun/star/style/CaseMap.hpp> +#include <com/sun/star/text/FontRelief.hpp> +#include <com/sun/star/text/FontEmphasis.hpp> +#include <com/sun/star/text/RubyAdjust.hpp> +#include <com/sun/star/awt/FontStrikeout.hpp> +#include <com/sun/star/text/WritingMode2.hpp> +#include <com/sun/star/i18n/ScriptType.hpp> + +#include <comphelper/InlineContainer.hxx> + + +// header for struct SvtLinguConfig +#ifndef _SVTOOLS_LINGUCFG_HXX_ +#include <unotools/lingucfg.hxx> +#endif +#ifndef INCLUDED_I18NPOOL_MSLANGID_HXX +#include <i18npool/mslangid.hxx> +#endif +#ifndef _SV_OUTDEV_HXX +#include <vcl/outdev.hxx> +#endif + +using namespace ::com::sun::star; + +using ::com::sun::star::beans::Property; + +using ::rtl::OUString; + +namespace chart +{ + +void CharacterProperties::AddPropertiesToVector( + ::std::vector< Property > & rOutProperties ) +{ + // CharacterProperties + rOutProperties.push_back( + Property( C2U( "CharFontName" ), + PROP_CHAR_FONT_NAME, + ::getCppuType( reinterpret_cast< const OUString * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); + rOutProperties.push_back( + Property( C2U( "CharFontStyleName" ), + PROP_CHAR_FONT_STYLE_NAME, + ::getCppuType( reinterpret_cast< const OUString * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT + | beans::PropertyAttribute::MAYBEVOID )); + // CharFontFamily (see awt.FontFamily) + rOutProperties.push_back( + Property( C2U( "CharFontFamily" ), + PROP_CHAR_FONT_FAMILY, + ::getCppuType( reinterpret_cast< const sal_Int16 * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); + // CharFontCharSet (see awt.CharSet) + rOutProperties.push_back( + Property( C2U( "CharFontCharSet" ), + PROP_CHAR_FONT_CHAR_SET, + ::getCppuType( reinterpret_cast< const sal_Int16 * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); + // CharFontPitch (see awt.FontPitch) + rOutProperties.push_back( + Property( C2U( "CharFontPitch" ), + PROP_CHAR_FONT_PITCH, + ::getCppuType( reinterpret_cast< const sal_Int16 * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); + // CharColor + rOutProperties.push_back( + Property( C2U( "CharColor" ), + PROP_CHAR_COLOR, + ::getCppuType( reinterpret_cast< const sal_Int32 * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); + // CharBackColor +// rOutProperties.push_back( +// Property( C2U( "CharBackColor" ), +// PROP_CHAR_BACKGROUND_COLOR, +// ::getCppuType( reinterpret_cast< const sal_Int32 * >(0)), +// beans::PropertyAttribute::BOUND +// | beans::PropertyAttribute::MAYBEDEFAULT)); + // CharEscapement + rOutProperties.push_back( + Property( C2U( "CharEscapement" ), + PROP_CHAR_ESCAPEMENT, + ::getCppuType( reinterpret_cast< const sal_Int16 * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID )); + // CharHeight + rOutProperties.push_back( + Property( C2U( "CharHeight" ), + PROP_CHAR_CHAR_HEIGHT, + ::getCppuType( reinterpret_cast< const float * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); + // CharUnderline (see awt.FontUnderline) + rOutProperties.push_back( + Property( C2U( "CharUnderline" ), + PROP_CHAR_UNDERLINE, + ::getCppuType( reinterpret_cast< const sal_Int16 * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); + // CharUnderlineColor + rOutProperties.push_back( + Property( C2U( "CharUnderlineColor" ), + PROP_CHAR_UNDERLINE_COLOR, + ::getCppuType( reinterpret_cast< const sal_Int32 * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT + | beans::PropertyAttribute::MAYBEVOID )); + // CharUnderlineHasColor + rOutProperties.push_back( + Property( C2U( "CharUnderlineHasColor" ), + PROP_CHAR_UNDERLINE_HAS_COLOR, + ::getBooleanCppuType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); + // CharWeight (see awt.FontWeight) + rOutProperties.push_back( + Property( C2U( "CharWeight" ), + PROP_CHAR_WEIGHT, + ::getCppuType( reinterpret_cast< const float * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); + // CharPosture + rOutProperties.push_back( + Property( C2U( "CharPosture" ), + PROP_CHAR_POSTURE, + ::getCppuType( reinterpret_cast< const awt::FontSlant * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); + rOutProperties.push_back( + Property( C2U( "CharAutoKerning" ), + PROP_CHAR_AUTO_KERNING, + ::getBooleanCppuType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT + | beans::PropertyAttribute::MAYBEVOID )); + rOutProperties.push_back( + Property( C2U( "CharKerning" ), + PROP_CHAR_KERNING, + ::getCppuType( reinterpret_cast< const sal_Int16 * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT + | beans::PropertyAttribute::MAYBEVOID )); + // CharCaseMap (see style.CaseMap) +// rOutProperties.push_back( +// Property( C2U( "CharCaseMap" ), +// PROP_CHAR_CASE_MAPPING, +// ::getCppuType( reinterpret_cast< const sal_Int16 * >(0)), +// beans::PropertyAttribute::BOUND +// | beans::PropertyAttribute::MAYBEDEFAULT )); + + + // CharRotation +// rOutProperties.push_back( +// Property( C2U( "CharRotation" ), +// PROP_CHAR_ROTATION, +// ::getCppuType( reinterpret_cast< const sal_Int16 * >(0)), +// beans::PropertyAttribute::BOUND +// | beans::PropertyAttribute::MAYBEDEFAULT )); + +// // CharScaleWidth +// rOutProperties.push_back( +// Property( C2U( "CharScaleWidth" ), +// PROP_CHAR_SCALE_WIDTH, +// ::getCppuType( reinterpret_cast< const sal_Int16 * >(0)), +// beans::PropertyAttribute::BOUND +// | beans::PropertyAttribute::MAYBEDEFAULT )); + // CharEscapementHeight + rOutProperties.push_back( + Property( C2U( "CharEscapementHeight" ), + PROP_CHAR_ESCAPEMENT_HEIGHT, + ::getCppuType( reinterpret_cast< const sal_Int8 * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID )); + + // CharCrossedOut +// rOutProperties.push_back( +// Property( C2U( "CharCrossedOut" ), +// PROP_CHAR_CROSSED_OUT, +// ::getBooleanCppuType(), +// beans::PropertyAttribute::BOUND +// | beans::PropertyAttribute::MAYBEDEFAULT )); + // CharStrikeout (see awt.FontStrikeout) + rOutProperties.push_back( + Property( C2U( "CharStrikeout" ), + PROP_CHAR_STRIKE_OUT, + ::getCppuType( reinterpret_cast< const sal_Int16 * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); + // CharWordMode + rOutProperties.push_back( + Property( C2U( "CharWordMode" ), + PROP_CHAR_WORD_MODE, + ::getBooleanCppuType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); + // CharFlash +// rOutProperties.push_back( +// Property( C2U( "CharFlash" ), +// PROP_CHAR_FLASH, +// ::getBooleanCppuType(), +// beans::PropertyAttribute::BOUND +// | beans::PropertyAttribute::MAYBEDEFAULT )); + // CharLocale + rOutProperties.push_back( + Property( C2U( "CharLocale" ), + PROP_CHAR_LOCALE, + ::getCppuType( reinterpret_cast< const lang::Locale * >(0)), + //#i111967# no PropertyChangeEvent is fired on change so far + beans::PropertyAttribute::MAYBEDEFAULT )); + // CharShadowed + rOutProperties.push_back( + Property( C2U( "CharShadowed" ), + PROP_CHAR_SHADOWED, + ::getBooleanCppuType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); + // CharContoured + rOutProperties.push_back( + Property( C2U( "CharContoured" ), + PROP_CHAR_CONTOURED, + ::getBooleanCppuType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); + // CharRelief (see text.FontRelief) + rOutProperties.push_back( + Property( C2U( "CharRelief" ), + PROP_CHAR_RELIEF, + ::getCppuType( reinterpret_cast< const sal_Int16 * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); + + // CharEmphasize (see text.FontEmphasis) + rOutProperties.push_back( + Property( C2U( "CharEmphasis" ), + PROP_CHAR_EMPHASIS, + ::getCppuType( reinterpret_cast< const sal_Int16 * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); +// // RubyText +// rOutProperties.push_back( +// Property( C2U( "RubyText" ), +// PROP_CHAR_RUBY_TEXT, +// ::getCppuType( reinterpret_cast< const OUString * >(0)), +// beans::PropertyAttribute::BOUND +// | beans::PropertyAttribute::MAYBEDEFAULT )); +// // RubyAdjust (see text.RubyAdjust) +// rOutProperties.push_back( +// Property( C2U( "RubyAdjust" ), +// PROP_CHAR_RUBY_ADJUST, +// ::getCppuType( reinterpret_cast< const sal_Int16 * >(0)), +// beans::PropertyAttribute::BOUND +// | beans::PropertyAttribute::MAYBEDEFAULT )); +// // RubyCharStyleName +// rOutProperties.push_back( +// Property( C2U( "RubyStyleName" ), +// PROP_CHAR_RUBY_STYLE_NAME, +// ::getCppuType( reinterpret_cast< const OUString * >(0)), +// beans::PropertyAttribute::BOUND +// | beans::PropertyAttribute::MAYBEDEFAULT )); +// // RubyIsAbove +// rOutProperties.push_back( +// Property( C2U( "RubyIsAbove" ), +// PROP_CHAR_RUBY_IS_ABOVE, +// ::getBooleanCppuType(), +// beans::PropertyAttribute::BOUND +// | beans::PropertyAttribute::MAYBEDEFAULT )); +// // CharNoHyphenation +// rOutProperties.push_back( +// Property( C2U( "InhibitHyphenation" ), +// PROP_CHAR_INHIBIT_HYPHENATION, +// ::getBooleanCppuType(), +// beans::PropertyAttribute::BOUND +// | beans::PropertyAttribute::MAYBEDEFAULT )); + + // CharacterPropertiesAsian + // ===== + // CharFontNameAsian + rOutProperties.push_back( + Property( C2U( "CharFontNameAsian" ), + PROP_CHAR_ASIAN_FONT_NAME, + ::getCppuType( reinterpret_cast< const OUString * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); + // CharFontStyleNameAsian + rOutProperties.push_back( + Property( C2U( "CharFontStyleNameAsian" ), + PROP_CHAR_ASIAN_FONT_STYLE_NAME, + ::getCppuType( reinterpret_cast< const OUString * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT + | beans::PropertyAttribute::MAYBEVOID )); + // CharFontFamilyAsian (see awt.FontFamily) + rOutProperties.push_back( + Property( C2U( "CharFontFamilyAsian" ), + PROP_CHAR_ASIAN_FONT_FAMILY, + ::getCppuType( reinterpret_cast< const sal_Int16 * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); + // CharFontCharSetAsian (see awt.CharSet) + rOutProperties.push_back( + Property( C2U( "CharFontCharSetAsian" ), + PROP_CHAR_ASIAN_CHAR_SET, + ::getCppuType( reinterpret_cast< const sal_Int16 * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); + // CharFontPitchAsian (see awt.FontPitch) + rOutProperties.push_back( + Property( C2U( "CharFontPitchAsian" ), + PROP_CHAR_ASIAN_FONT_PITCH, + ::getCppuType( reinterpret_cast< const sal_Int16 * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); + // CharHeightAsian + rOutProperties.push_back( + Property( C2U( "CharHeightAsian" ), + PROP_CHAR_ASIAN_CHAR_HEIGHT, + ::getCppuType( reinterpret_cast< const float * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); + // CharWeightAsian + rOutProperties.push_back( + Property( C2U( "CharWeightAsian" ), + PROP_CHAR_ASIAN_WEIGHT, + ::getCppuType( reinterpret_cast< const float * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); + // CharPostureAsian + rOutProperties.push_back( + Property( C2U( "CharPostureAsian" ), + PROP_CHAR_ASIAN_POSTURE, + ::getCppuType( reinterpret_cast< const awt::FontSlant * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); + // CharLocaleAsian + rOutProperties.push_back( + Property( C2U( "CharLocaleAsian" ), + PROP_CHAR_ASIAN_LOCALE, + ::getCppuType( reinterpret_cast< const lang::Locale * >(0)), + //#i111967# no PropertyChangeEvent is fired on change so far + beans::PropertyAttribute::MAYBEDEFAULT )); + + // CharacterPropertiesComplex + // === + // CharFontNameComplex + rOutProperties.push_back( + Property( C2U( "CharFontNameComplex" ), + PROP_CHAR_COMPLEX_FONT_NAME, + ::getCppuType( reinterpret_cast< const OUString * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); + // CharFontStyleNameComplex + rOutProperties.push_back( + Property( C2U( "CharFontStyleNameComplex" ), + PROP_CHAR_COMPLEX_FONT_STYLE_NAME, + ::getCppuType( reinterpret_cast< const OUString * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT + | beans::PropertyAttribute::MAYBEVOID )); + // CharFontFamilyComplex (see awt.FontFamily) + rOutProperties.push_back( + Property( C2U( "CharFontFamilyComplex" ), + PROP_CHAR_COMPLEX_FONT_FAMILY, + ::getCppuType( reinterpret_cast< const sal_Int16 * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); + // CharFontCharSetComplex (see awt.CharSet) + rOutProperties.push_back( + Property( C2U( "CharFontCharSetComplex" ), + PROP_CHAR_COMPLEX_CHAR_SET, + ::getCppuType( reinterpret_cast< const sal_Int16 * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); + // CharFontPitchComplex (see awt.FontPitch) + rOutProperties.push_back( + Property( C2U( "CharFontPitchComplex" ), + PROP_CHAR_COMPLEX_FONT_PITCH, + ::getCppuType( reinterpret_cast< const sal_Int16 * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); + // CharHeightComplex + rOutProperties.push_back( + Property( C2U( "CharHeightComplex" ), + PROP_CHAR_COMPLEX_CHAR_HEIGHT, + ::getCppuType( reinterpret_cast< const float * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); + // CharWeightComplex + rOutProperties.push_back( + Property( C2U( "CharWeightComplex" ), + PROP_CHAR_COMPLEX_WEIGHT, + ::getCppuType( reinterpret_cast< const float * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); + // CharPostureComplex + rOutProperties.push_back( + Property( C2U( "CharPostureComplex" ), + PROP_CHAR_COMPLEX_POSTURE, + ::getCppuType( reinterpret_cast< const awt::FontSlant * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); + // CharLocaleComplex + rOutProperties.push_back( + Property( C2U( "CharLocaleComplex" ), + PROP_CHAR_COMPLEX_LOCALE, + ::getCppuType( reinterpret_cast< const lang::Locale * >(0)), + //#i111967# no PropertyChangeEvent is fired on change so far + beans::PropertyAttribute::MAYBEDEFAULT )); + + // Writing Mode left to right vs right to left + rOutProperties.push_back( + Property( C2U( "WritingMode" ), + PROP_WRITING_MODE, + ::getCppuType( reinterpret_cast< const sal_Int16 * >(0)), /*com::sun::star::text::WritingMode2*/ + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); + + rOutProperties.push_back( + Property( C2U( "ParaIsCharacterDistance" ), + PROP_PARA_IS_CHARACTER_DISTANCE, + ::getBooleanCppuType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); +} + +void CharacterProperties::AddDefaultsToMap( + ::chart::tPropertyValueMap & rOutMap ) +{ + const float fDefaultFontHeight = 13.0; + + SvtLinguConfig aLinguConfig; + lang::Locale aDefaultLocale; + aLinguConfig.GetProperty(C2U("DefaultLocale")) >>= aDefaultLocale; + lang::Locale aDefaultLocale_CJK; + aLinguConfig.GetProperty(C2U("DefaultLocale_CJK")) >>= aDefaultLocale_CJK; + lang::Locale aDefaultLocale_CTL; + aLinguConfig.GetProperty(C2U("DefaultLocale_CTL")) >>= aDefaultLocale_CTL; + + using namespace ::com::sun::star::i18n::ScriptType; + LanguageType nLang; + nLang = MsLangId::resolveSystemLanguageByScriptType(MsLangId::convertLocaleToLanguage(aDefaultLocale), LATIN); + Font aFont = OutputDevice::GetDefaultFont( DEFAULTFONT_LATIN_SPREADSHEET, nLang, DEFAULTFONT_FLAGS_ONLYONE, 0 ); + nLang = MsLangId::resolveSystemLanguageByScriptType(MsLangId::convertLocaleToLanguage( aDefaultLocale_CJK), ASIAN); + Font aFontCJK = OutputDevice::GetDefaultFont( DEFAULTFONT_CJK_SPREADSHEET, nLang, DEFAULTFONT_FLAGS_ONLYONE, 0 ); + nLang = MsLangId::resolveSystemLanguageByScriptType(MsLangId::convertLocaleToLanguage( aDefaultLocale_CTL), COMPLEX); + Font aFontCTL = OutputDevice::GetDefaultFont( DEFAULTFONT_CTL_SPREADSHEET, nLang, DEFAULTFONT_FLAGS_ONLYONE, 0 ); + + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_FONT_NAME, OUString( aFont.GetName() ) ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_FONT_STYLE_NAME, OUString(aFont.GetStyleName()) ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_FONT_FAMILY, sal_Int16(aFont.GetFamily()) );//awt::FontFamily::SWISS + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_FONT_CHAR_SET, sal_Int16(aFont.GetCharSet()) );//use awt::CharSet::DONTKNOW instead of SYSTEM to avoid assertion issue 50249 + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_FONT_PITCH, sal_Int16(aFont.GetPitch()) );//awt::FontPitch::VARIABLE + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( rOutMap, PROP_CHAR_COLOR, -1 ); //automatic color (COL_AUTO) + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_CHAR_HEIGHT, fDefaultFontHeight ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_UNDERLINE, awt::FontUnderline::NONE ); + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( rOutMap, PROP_CHAR_UNDERLINE_COLOR, -1 ); //automatic color (COL_AUTO) + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_UNDERLINE_HAS_COLOR, false ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_WEIGHT, awt::FontWeight::NORMAL ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_POSTURE, awt::FontSlant_NONE ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_AUTO_KERNING, true ); + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int16 >( rOutMap, PROP_CHAR_KERNING, 0 ); + +// ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_CASE_MAPPING, style::CaseMap::NONE ); +// ::chart::PropertyHelper::setPropertyValueDefault< sal_Int16 >( rOutMap, PROP_CHAR_ROTATION, 0 ); +// ::chart::PropertyHelper::setPropertyValueDefault< sal_Int16 >( rOutMap, PROP_CHAR_SCALE_WIDTH, 71 ); + +// ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_CROSSED_OUT, false ); + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int16 >( rOutMap, PROP_CHAR_STRIKE_OUT, awt::FontStrikeout::NONE ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_WORD_MODE, false ); +// ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_FLASH, false ); + + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_LOCALE, aDefaultLocale ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_SHADOWED, false ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_CONTOURED, false ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_RELIEF, text::FontRelief::NONE ); + + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_EMPHASIS, text::FontEmphasis::NONE ); + +// ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_RUBY_ADJUST, text::RubyAdjust_INDENT_BLOCK ); +// ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_RUBY_STYLE_NAME, ?? ); +// ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_RUBY_IS_ABOVE, true ); +// ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_INHIBIT_HYPHENATION, false ); + + // Asian (com.sun.star.style.CharacterPropertiesAsian) + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_ASIAN_CHAR_HEIGHT, fDefaultFontHeight ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_ASIAN_WEIGHT, awt::FontWeight::NORMAL ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_ASIAN_POSTURE, awt::FontSlant_NONE ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_ASIAN_LOCALE, aDefaultLocale_CJK ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_ASIAN_FONT_NAME, OUString( aFontCJK.GetName() ) ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_ASIAN_FONT_STYLE_NAME, OUString(aFontCJK.GetStyleName()) ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_ASIAN_FONT_FAMILY, sal_Int16(aFontCJK.GetFamily()) ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_ASIAN_CHAR_SET, sal_Int16(aFontCJK.GetCharSet()) ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_ASIAN_FONT_PITCH, sal_Int16(aFontCJK.GetPitch()) ); + + // Complex Text Layout (com.sun.star.style.CharacterPropertiesComplex) + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_COMPLEX_CHAR_HEIGHT, fDefaultFontHeight ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_COMPLEX_WEIGHT, awt::FontWeight::NORMAL ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_COMPLEX_POSTURE, awt::FontSlant_NONE ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_COMPLEX_LOCALE, aDefaultLocale_CTL ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_COMPLEX_FONT_NAME, OUString( aFontCTL.GetName() ) ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_COMPLEX_FONT_STYLE_NAME, OUString(aFontCTL.GetStyleName()) ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_COMPLEX_FONT_FAMILY, sal_Int16(aFontCTL.GetFamily()) ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_COMPLEX_CHAR_SET, sal_Int16(aFontCTL.GetCharSet()) ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_COMPLEX_FONT_PITCH, sal_Int16(aFontCTL.GetPitch()) ); + + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_WRITING_MODE, sal_Int16( com::sun::star::text::WritingMode2::PAGE ) ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_PARA_IS_CHARACTER_DISTANCE, sal_True ); +} + +bool CharacterProperties::IsCharacterPropertyHandle( sal_Int32 nHandle ) +{ + return ( FAST_PROPERTY_ID_START_CHAR_PROP <= nHandle && + nHandle < CharacterProperties::FAST_PROPERTY_ID_END_CHAR_PROP ); +} + +// static +awt::FontDescriptor CharacterProperties::createFontDescriptorFromPropertySet( + const uno::Reference< beans::XMultiPropertySet > & xMultiPropSet ) +{ + awt::FontDescriptor aResult; + // Note: keep this sorted! + ::comphelper::MakeVector< OUString > aPropNames + ( C2U("CharFontCharSet")); // CharSet + aPropNames + ( C2U("CharFontFamily")) // Family + ( C2U("CharFontName")) // Name + ( C2U("CharFontPitch")) // Pitch + ( C2U("CharFontStyleName")) // StyleName + ( C2U("CharHeight")) // Height + ( C2U("CharPosture")) // Slant + ( C2U("CharStrikeout")) // Strikeout + ( C2U("CharUnderline")) // Underline + ( C2U("CharWeight")) // Weight + ( C2U("CharWordMode")) // WordLineMode + ; + + uno::Sequence< OUString > aPropNameSeq( ContainerHelper::ContainerToSequence( aPropNames )); + uno::Sequence< uno::Any > aValues( xMultiPropSet->getPropertyValues( aPropNameSeq )); + + sal_Int32 i=0; + // Note keep this sorted according to the list above (comments are the fieldnames) + aValues[ i++ ] >>= aResult.CharSet; + aValues[ i++ ] >>= aResult.Family; + aValues[ i++ ] >>= aResult.Name; + aValues[ i++ ] >>= aResult.Pitch; + aValues[ i++ ] >>= aResult.StyleName; + float fCharHeight = 0; + aValues[ i++ ] >>= fCharHeight; + aResult.Height = static_cast< sal_Int16 >( fCharHeight ); + aValues[ i++ ] >>= aResult.Slant; + aValues[ i++ ] >>= aResult.Strikeout; + aValues[ i++ ] >>= aResult.Underline; + aValues[ i++ ] >>= aResult.Weight; + aValues[ i++ ] >>= aResult.WordLineMode; + OSL_ASSERT( i == aValues.getLength()); + + return aResult; +} + +} // namespace chart diff --git a/chart2/source/tools/ChartDebugTrace.cxx b/chart2/source/tools/ChartDebugTrace.cxx new file mode 100644 index 000000000000..9629138cb2be --- /dev/null +++ b/chart2/source/tools/ChartDebugTrace.cxx @@ -0,0 +1,417 @@ +/************************************************************************* + * + * 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 "ChartDebugTrace.hxx" +#include "macros.hxx" +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/chart2/AxisType.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/StackingDirection.hpp> +#include <rtl/math.hxx> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::rtl::OUString; + +#if OSL_DEBUG_LEVEL >= CHART_TRACE_OSL_DEBUG_LEVEL + +namespace +{ +/* +const char lcl_aSpace=' '; + +void lcl_IndentedTrace( int nIndent, char* pStr ) +{ + if( nIndent > 0 ) + { + OSL_TRACE( "%*c%s", nIndent, lcl_aSpace, pStr ); + } + else + { + OSL_TRACE( pStr ); + } +} + +void lcl_TraceException( const uno::Exception & aEx ) +{ + OSL_TRACE( + U2C( C2U( "*** Exception caught during trace. Type: " ) + + OUString::createFromAscii( typeid( aEx ).name()) + + C2U( ", Message: " ) + + aEx.Message )); +} + +void lcl_TraceCategories( const Reference< data::XLabeledDataSequence > & xCat, int nIndent ) +{ + if( ! xCat.is()) + return; + try + { + Reference< data::XDataSequence > xValues( xCat->getValues()); + if( xValues.is()) + { + OSL_TRACE( "%*ccategories: source: %s", nIndent, lcl_aSpace, + U2C( xValues->getSourceRangeRepresentation())); + } + Reference< data::XDataSequence > xLabel( xCat->getLabel()); + if( xLabel.is()) + { + OSL_TRACE( "%*ccategories' label: source: %s", nIndent, lcl_aSpace, + U2C( xLabel->getSourceRangeRepresentation())); + } + } + catch( uno::Exception & ex ) + { + lcl_TraceException( ex ); + } +} + +void lcl_TraceDataSeriesSeq( const Sequence< Reference< XDataSeries > > & aSeries, int nIndent ) +{ + for( sal_Int32 j = 0; j < aSeries.getLength(); ++j ) + { + Reference< beans::XPropertySet > xProp( aSeries[j], uno::UNO_QUERY ); + OUString aId; + + OSL_TRACE( "%*cindex %ld", nIndent, lcl_aSpace, j ); + + StackingDirection aStDir; + if( xProp.is() && + ( xProp->getPropertyValue( C2U( "StackingDirection" )) >>= aStDir ) && + aStDir != StackingDirection_NO_STACKING ) + { + OSL_TRACE( "%*cstacking in %s", nIndent + 2, lcl_aSpace, + (aStDir == StackingDirection_Y_STACKING) + ? "y-direction" : "z-direction" ); + } + + Reference< data::XDataSource > xSource( aSeries[j], uno::UNO_QUERY ); + if( xSource.is()) + { + Sequence< Reference< data::XLabeledDataSequence > > aSequences( xSource->getDataSequences()); + const sal_Int32 nMax = aSequences.getLength(); + for( sal_Int32 k = 0; k < nMax; ++k ) + { + if( aSequences[k].is()) + { + OUString aSourceId(C2U("<none>")); + if( aSequences[k]->getValues().is()) + aSourceId = aSequences[k]->getValues()->getSourceRangeRepresentation(); + xProp.set( aSequences[k]->getValues(), uno::UNO_QUERY ); + if( xProp.is() && + ( xProp->getPropertyValue( C2U( "Role" )) >>= aId )) + { + OSL_TRACE( "%*cdata sequence %d: role: %s, source: %s", + nIndent + 2, lcl_aSpace, k, U2C( aId ), U2C( aSourceId )); + } + else + { + OSL_TRACE( "%*cdata sequence %d, unknown role, source: %s", + nIndent + 2, lcl_aSpace, k, U2C( aSourceId ) ); + } + + aSourceId = C2U("<none>"); + if( aSequences[k]->getLabel().is()) + aSourceId = OUString( aSequences[k]->getLabel()->getSourceRangeRepresentation()); + xProp.set( aSequences[k]->getLabel(), uno::UNO_QUERY ); + if( xProp.is() && + ( xProp->getPropertyValue( C2U( "Role" )) >>= aId )) + { + OSL_TRACE( "%*cdata sequence label %d: role: %s, source: %s", + nIndent + 2, lcl_aSpace, k, U2C( aId ), U2C( aSourceId )); + } + else + { + OSL_TRACE( "%*cdata sequence label %d: unknown role, source: %s", + nIndent + 2, lcl_aSpace, k, U2C( aSourceId ) ); + } + } + } + } + } +} + +void lcl_TraceChartType( const Reference< XChartType > & xChartType, int nIndent ) +{ + if( xChartType.is()) + { + OSL_TRACE( "%*c* type: %s", nIndent, lcl_aSpace, U2C( xChartType->getChartType()) ); + + lcl_IndentedTrace( nIndent + 2, "Supported Roles" ); + sal_Int32 i=0; + Sequence< OUString > aMandRoles( xChartType->getSupportedMandatoryRoles()); + if( aMandRoles.getLength() > 0 ) + { + lcl_IndentedTrace( nIndent + 4, "mandatory" ); + for( i=0; i<aMandRoles.getLength(); ++i ) + { + OSL_TRACE( "%*c%s", nIndent + 6, lcl_aSpace, U2C( aMandRoles[i] )); + } + } + Sequence< OUString > aOptRoles( xChartType->getSupportedOptionalRoles()); + if( aOptRoles.getLength() > 0 ) + { + lcl_IndentedTrace( nIndent + 4, "optional" ); + for( i=0; i<aOptRoles.getLength(); ++i ) + { + OSL_TRACE( "%*c%s", nIndent + 6, lcl_aSpace, U2C( aOptRoles[i] )); + } + } + OSL_TRACE( "%*crole of sequence for label: %s", nIndent + 2, lcl_aSpace, + U2C( xChartType->getRoleOfSequenceForSeriesLabel())); + + Reference< XDataSeriesContainer > xDSCnt( xChartType, uno::UNO_QUERY ); + if( xDSCnt.is()) + { + lcl_IndentedTrace( nIndent + 2, "Data Series" ); + lcl_TraceDataSeriesSeq( xDSCnt->getDataSeries(), nIndent + 4 ); + } + } +} + +void lcl_TraceCoordinateSystem( const Reference< XCoordinateSystem > & xCooSys, int nIndent ) +{ + if( xCooSys.is()) try + { + sal_Int32 nDim = xCooSys->getDimension(); + OSL_TRACE( "%*c* dim: %ld, type: %s", nIndent, lcl_aSpace, + nDim, U2C( xCooSys->getCoordinateSystemType() )); + nIndent += 2; + OSL_TRACE( "%*cview service-name: %s", nIndent, lcl_aSpace, + U2C( xCooSys->getViewServiceName() )); + + Reference< beans::XPropertySet > xProp( xCooSys, uno::UNO_QUERY ); + if( xProp.is()) + { + Reference< beans::XPropertySetInfo > xInfo( xProp->getPropertySetInfo(), uno::UNO_QUERY ); + sal_Bool bSwap; + if( xInfo.is() && + xInfo->hasPropertyByName( C2U("SwapXAndYAxis")) && + (xProp->getPropertyValue( C2U("SwapXAndYAxis")) >>= bSwap) && + bSwap ) + { + lcl_IndentedTrace( nIndent, "swap x-axis and y-axis" ); + } + } + + if( nDim >= 2 ) + { + const sal_Int32 nMaxIndex = xCooSys->getMaximumAxisIndexByDimension(1); + for(sal_Int32 nI=0; nI<=nMaxIndex; ++nI) + { + Reference< XScale > xScale( xCooSys->getAxisByDimension( 1, nI )); + if( xScale.is()) + { + ScaleData aData( xScale->getScaleData()); + if( aData.AxisType==AxisType::PERCENT ) + lcl_IndentedTrace( nIndent, "percent stacking at y-scale" ); + } + } + } + + Sequence< uno::Any > aOrigin( xCooSys->getOrigin()); + double x, y, z; + ::rtl::math::setNan( &x ), ::rtl::math::setNan( &y ), ::rtl::math::setNan( &z ); + if( aOrigin.getLength() > 0 && + aOrigin[0].hasValue() ) + aOrigin[0] >>= x; + if( aOrigin.getLength() > 1 && + aOrigin[1].hasValue() ) + aOrigin[1] >>= y; + if( aOrigin.getLength() > 2 && + aOrigin[2].hasValue() ) + aOrigin[2] >>= z; + OSL_TRACE( "%*corigin: (%f, %f, %f)", nIndent, lcl_aSpace, x, y, z ); + + Reference< XChartTypeContainer > xCTCnt( xCooSys, uno::UNO_QUERY ); + if( xCTCnt.is()) + { + Sequence< Reference< XChartType > > aChartTypes( xCTCnt->getChartTypes()); + if( aChartTypes.getLength() > 0 ) + { + lcl_IndentedTrace( nIndent, "Chart Types" ); + for( sal_Int32 i=0; i<aChartTypes.getLength(); ++i ) + { + lcl_TraceChartType( aChartTypes[i], nIndent + 2 ); + } + } + } + } + catch( uno::Exception & ex ) + { + lcl_TraceException( ex ); + } +} + +void lcl_TraceMeter( + const Reference< XMeter > & xMeter, + const Sequence< Reference< XCoordinateSystem > > & aCooSys, + bool bWithCategories, + int nIndent ) +{ + try + { + Reference< XCoordinateSystem > xCooSys( xMeter->getCoordinateSystem()); + for( sal_Int32 i=0; i<aCooSys.getLength(); ++i ) + if( aCooSys[i] == xCooSys ) + { + OSL_TRACE( "%*cbelongs to Coordinate System %ld.", nIndent + 2, lcl_aSpace, i ); + } + OSL_TRACE( "%*crepresents Dimension %ld.", nIndent + 2, lcl_aSpace, xMeter->getRepresentedDimension()); + if( bWithCategories ) + { + Reference< XScale > xScale( xCooSys->getAxisByDimension( xMeter->getRepresentedDimension(), xMeter->getIndex() )); + if( xScale.is()) + { + ScaleData aData = xScale->getScaleData(); + if( aData.Categories.is()) + { + lcl_TraceCategories( aData.Categories, nIndent + 2 ); + } + } + } + } + catch( uno::Exception & ex ) + { + lcl_TraceException( ex ); + } +} +*/ +} // anonymous namespace +#endif + + +namespace chart +{ +namespace debug +{ + +#if OSL_DEBUG_LEVEL >= CHART_TRACE_OSL_DEBUG_LEVEL + +void ChartDebugTraceDocument( + const Reference< XChartDocument > & /*xDoc*/, + int /*nIndent*/ ) +{ + /* +#if OSL_DEBUG_LEVEL >= CHART_TRACE_OSL_DEBUG_LEVEL + try + { + OSL_TRACE( "%*cas %sternal data", nIndent, 'h', + xDoc->hasInternalDataProvider() ? "in": "ex" ); + + Reference< lang::XMultiServiceFactory > xCTManager( xDoc->getChartTypeManager(), uno::UNO_QUERY ); + if( xCTManager.is()) + { + Sequence< OUString > aServiceNames( xCTManager->getAvailableServiceNames()); + OSL_TRACE( "%*c ChartTypeManager has %ld entries", nIndent, '*', aServiceNames.getLength()); +# if OSL_DEBUG_LEVEL >= (CHART_TRACE_OSL_DEBUG_LEVEL + 1) + for( sal_Int32 i=0; i<aServiceNames.getLength(); ++i ) + { + OSL_TRACE( "%*c%s", nIndent + 2, lcl_aSpace, U2C( aServiceNames[i] )); + } +# endif + } + Reference< XDiagram > xDiagram( xDoc->getFirstDiagram()); + lcl_IndentedTrace( nIndent, "* Diagram" ); + ChartDebugTraceDiagram( xDiagram, nIndent + 2 ); + } + catch( uno::Exception & ex ) + { + lcl_TraceException( ex ); + } +#endif + */ +} + +void ChartDebugTraceDiagram( + const Reference< XDiagram > & /*xDiagram*/, + int /*nIndent*/ ) +{ + /* +#if OSL_DEBUG_LEVEL >= CHART_TRACE_OSL_DEBUG_LEVEL + try + { + Reference< XCoordinateSystemContainer > xCooSysCnt( xDiagram, uno::UNO_QUERY_THROW ); + Sequence< Reference< XCoordinateSystem > > aCooSys( xCooSysCnt->getCoordinateSystems() ); + if( aCooSys.getLength() > 0 ) + { + lcl_IndentedTrace( nIndent, "CoordinateSystems" ); + for( sal_Int32 i=0; i<aCooSys.getLength(); ++i ) + lcl_TraceCoordinateSystem( aCooSys[i], nIndent + 2 ); + } + else + { + lcl_IndentedTrace( nIndent, "<No Coordinate Systems>" ); + } + + Reference< XAxisContainer > xAxisCnt( xDiagram, uno::UNO_QUERY_THROW ); + Sequence< Reference< XAxis > > aAxes( xAxisCnt->getAxes() ); + if( aAxes.getLength() > 0 ) + { + lcl_IndentedTrace( nIndent, "Axes" ); + for( sal_Int32 i=0; i<aAxes.getLength(); ++i ) + lcl_TraceMeter( Reference< XMeter >( aAxes[i], uno::UNO_QUERY ), aCooSys, true, nIndent + 2 ); + } + else + { + lcl_IndentedTrace( nIndent, "<No Axes>" ); + } + + Reference< XGridContainer > xGridCnt( xDiagram, uno::UNO_QUERY_THROW ); + Sequence< Reference< XGrid > > aGrids( xGridCnt->getGrids() ); + if( aGrids.getLength() > 0 ) + { + lcl_IndentedTrace( nIndent, "Grids" ); + for( sal_Int32 i=0; i<aGrids.getLength(); ++i ) + lcl_TraceMeter( Reference< XMeter >( aGrids[i], uno::UNO_QUERY ), aCooSys, false, nIndent + 2 ); + } + else + { + lcl_IndentedTrace( nIndent, "<No Grids>" ); + } + } + catch( uno::Exception & ex ) + { + lcl_TraceException( ex ); + } + +#endif + +*/ +} +#endif + +} // namespace debug +} // namespace chart diff --git a/chart2/source/tools/ChartModelHelper.cxx b/chart2/source/tools/ChartModelHelper.cxx new file mode 100644 index 000000000000..a49b2abeac98 --- /dev/null +++ b/chart2/source/tools/ChartModelHelper.cxx @@ -0,0 +1,267 @@ +/************************************************************************* + * + * 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 "ChartModelHelper.hxx" +#include "macros.hxx" +#include "DiagramHelper.hxx" +#include "DataSourceHelper.hxx" +#include "ControllerLockGuard.hxx" +#include "RangeHighlighter.hxx" +#include "InternalDataProvider.hxx" + +#include <com/sun/star/chart2/data/XDataReceiver.hpp> +#include <com/sun/star/chart2/XChartDocument.hpp> +#include <com/sun/star/chart2/XChartTypeContainer.hpp> +#include <com/sun/star/chart2/XCoordinateSystemContainer.hpp> +#include <com/sun/star/chart2/XDataSeriesContainer.hpp> +#include <com/sun/star/embed/Aspects.hpp> +#include <com/sun/star/embed/XVisualObject.hpp> +#include <com/sun/star/view/XSelectionChangeListener.hpp> + +// header for define DBG_ASSERT +#include <tools/debug.hxx> + +//............................................................................. +namespace chart +{ +//............................................................................. +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +//static +uno::Reference< chart2::data::XRangeHighlighter > ChartModelHelper::createRangeHighlighter( + const uno::Reference< view::XSelectionSupplier > & xSelectionSupplier ) +{ + return new RangeHighlighter( xSelectionSupplier ); +} + +//static +uno::Reference< chart2::data::XDataProvider > ChartModelHelper::createInternalDataProvider( + const uno::Reference< ::com::sun::star::chart2::XChartDocument >& xChartDoc, bool bConnectToModel ) +{ + return new InternalDataProvider( xChartDoc, bConnectToModel ); +} + +//static +uno::Reference< XDiagram > ChartModelHelper::findDiagram( const uno::Reference< frame::XModel >& xModel ) +{ + uno::Reference< XChartDocument > xChartDoc( xModel, uno::UNO_QUERY ); + if( xChartDoc.is()) + return ChartModelHelper::findDiagram( xChartDoc ); + return NULL; +} + +// static +uno::Reference< XDiagram > ChartModelHelper::findDiagram( const uno::Reference< chart2::XChartDocument >& xChartDoc ) +{ + try + { + if( xChartDoc.is()) + return xChartDoc->getFirstDiagram(); + } + catch( uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + return NULL; +} + +//static +uno::Reference< XCoordinateSystem > ChartModelHelper::getFirstCoordinateSystem( const uno::Reference< frame::XModel >& xModel ) +{ + uno::Reference< XCoordinateSystem > XCooSys; + uno::Reference< XCoordinateSystemContainer > xCooSysCnt( ChartModelHelper::findDiagram( xModel ), uno::UNO_QUERY ); + if( xCooSysCnt.is() ) + { + uno::Sequence< uno::Reference< XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems() ); + if( aCooSysSeq.getLength() ) + XCooSys = aCooSysSeq[0]; + } + return XCooSys; +} + +// static +::std::vector< uno::Reference< XDataSeries > > ChartModelHelper::getDataSeries( + const uno::Reference< XChartDocument > & xChartDoc ) +{ + ::std::vector< uno::Reference< XDataSeries > > aResult; + + uno::Reference< XDiagram > xDiagram = ChartModelHelper::findDiagram( xChartDoc ); + if( xDiagram.is()) + aResult = DiagramHelper::getDataSeriesFromDiagram( xDiagram ); + + return aResult; +} + +// static +::std::vector< uno::Reference< XDataSeries > > ChartModelHelper::getDataSeries( + const uno::Reference< frame::XModel > & xModel ) +{ + return getDataSeries( uno::Reference< chart2::XChartDocument >( xModel, uno::UNO_QUERY )); +} + + +uno::Reference< XChartType > ChartModelHelper::getChartTypeOfSeries( + const uno::Reference< frame::XModel >& xModel + , const uno::Reference< XDataSeries >& xGivenDataSeries ) +{ + return DiagramHelper::getChartTypeOfSeries( ChartModelHelper::findDiagram( xModel ), xGivenDataSeries ); +} + +awt::Size ChartModelHelper::getDefaultPageSize() +{ + return awt::Size( 16000, 9000 ); +} + +awt::Size ChartModelHelper::getPageSize( const uno::Reference< frame::XModel >& xModel ) +{ + awt::Size aPageSize( ChartModelHelper::getDefaultPageSize() ); + uno::Reference< embed::XVisualObject > xVisualObject(xModel,uno::UNO_QUERY); + DBG_ASSERT(xVisualObject.is(),"need xVisualObject for page size"); + if( xVisualObject.is() ) + aPageSize = xVisualObject->getVisualAreaSize( embed::Aspects::MSOLE_CONTENT ); + return aPageSize; +} + +void ChartModelHelper::setPageSize( const awt::Size& rSize, const uno::Reference< frame::XModel >& xModel ) +{ + uno::Reference< embed::XVisualObject > xVisualObject(xModel,uno::UNO_QUERY); + DBG_ASSERT(xVisualObject.is(),"need xVisualObject for page size"); + if( xVisualObject.is() ) + xVisualObject->setVisualAreaSize( embed::Aspects::MSOLE_CONTENT, rSize ); +} + +void ChartModelHelper::triggerRangeHighlighting( const uno::Reference< frame::XModel >& xModel ) +{ + uno::Reference< chart2::data::XDataReceiver > xDataReceiver( xModel, uno::UNO_QUERY ); + if( xDataReceiver.is() ) + { + uno::Reference< view::XSelectionChangeListener > xSelectionChangeListener( xDataReceiver->getRangeHighlighter(), uno::UNO_QUERY ); + //trigger selection of cell range + if( xSelectionChangeListener.is() ) + { + lang::EventObject aEvent( xSelectionChangeListener ); + xSelectionChangeListener->selectionChanged( aEvent ); + } + } +} + +bool ChartModelHelper::isIncludeHiddenCells( const uno::Reference< frame::XModel >& xChartModel ) +{ + bool bIncluded = true; // hidden cells are included by default. + + uno::Reference< chart2::XDiagram > xDiagram( ChartModelHelper::findDiagram(xChartModel) ); + if (!xDiagram.is()) + return bIncluded; + + uno::Reference< beans::XPropertySet > xProp( xDiagram, uno::UNO_QUERY ); + if (!xProp.is()) + return bIncluded; + + try + { + xProp->getPropertyValue(C2U("IncludeHiddenCells")) >>= bIncluded; + } + catch( const beans::UnknownPropertyException& ) + { + } + + return bIncluded; +} + +bool ChartModelHelper::setIncludeHiddenCells( bool bIncludeHiddenCells, const uno::Reference< frame::XModel >& xChartModel ) +{ + bool bChanged = false; + try + { + ControllerLockGuard aLockedControllers( xChartModel ); + + uno::Reference< beans::XPropertySet > xDiagramProperties( ChartModelHelper::findDiagram(xChartModel), uno::UNO_QUERY ); + if (xDiagramProperties.is()) + { + bool bOldValue = bIncludeHiddenCells; + xDiagramProperties->getPropertyValue( C2U("IncludeHiddenCells") ) >>= bOldValue; + if( bOldValue == bIncludeHiddenCells ) + bChanged = true; + + //set the property on all instances in all cases to get the different objects in sync! + + uno::Any aNewValue = uno::makeAny(bIncludeHiddenCells); + + try + { + uno::Reference< chart2::XChartDocument > xChartDoc( xChartModel, uno::UNO_QUERY ); + if( xChartDoc.is() ) + { + uno::Reference< beans::XPropertySet > xDataProviderProperties( xChartDoc->getDataProvider(), uno::UNO_QUERY ); + if( xDataProviderProperties.is() ) + xDataProviderProperties->setPropertyValue(C2U("IncludeHiddenCells"), aNewValue ); + } + } + catch( const beans::UnknownPropertyException& ) + { + //the property is optional! + } + + try + { + uno::Reference< chart2::data::XDataSource > xUsedData( DataSourceHelper::getUsedData( xChartModel ) ); + if( xUsedData.is() ) + { + uno::Reference< beans::XPropertySet > xProp; + uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aData( xUsedData->getDataSequences()); + for( sal_Int32 i=0; i<aData.getLength(); ++i ) + { + xProp.set( uno::Reference< beans::XPropertySet >( aData[i]->getValues(), uno::UNO_QUERY ) ); + if(xProp.is()) + xProp->setPropertyValue(C2U("IncludeHiddenCells"), aNewValue ); + xProp.set( uno::Reference< beans::XPropertySet >( aData[i]->getLabel(), uno::UNO_QUERY ) ); + if(xProp.is()) + xProp->setPropertyValue(C2U("IncludeHiddenCells"), aNewValue ); + } + } + } + catch( const beans::UnknownPropertyException& ) + { + //the property is optional! + } + + xDiagramProperties->setPropertyValue( C2U("IncludeHiddenCells"), aNewValue); + } + } + catch (uno::Exception& e) + { + ASSERT_EXCEPTION(e); + } + return bChanged; +} + +//............................................................................. +} //namespace chart +//............................................................................. diff --git a/chart2/source/tools/ChartTypeHelper.cxx b/chart2/source/tools/ChartTypeHelper.cxx new file mode 100644 index 000000000000..b851a3864b97 --- /dev/null +++ b/chart2/source/tools/ChartTypeHelper.cxx @@ -0,0 +1,685 @@ +/************************************************************************* + * + * 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 "ChartTypeHelper.hxx" +#include "DiagramHelper.hxx" +#include "DataSeriesHelper.hxx" +#include "macros.hxx" +#include "servicenames_charttypes.hxx" + +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/chart/DataLabelPlacement.hpp> +#include <com/sun/star/chart2/XDataSeriesContainer.hpp> +#include <com/sun/star/chart/MissingValueTreatment.hpp> + +//............................................................................. +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +//............................................................................. +namespace chart +{ + +bool ChartTypeHelper::isSupportingAxisSideBySide( + const uno::Reference< chart2::XChartType >& xChartType, sal_Int32 nDimensionCount ) +{ + bool bResult = false; + + if( xChartType.is() && + nDimensionCount < 3 ) + { + bool bFound=false; + bool bAmbiguous=false; + StackMode eStackMode = DiagramHelper::getStackModeFromChartType( xChartType, bFound, bAmbiguous, 0 ); + if( eStackMode == StackMode_NONE && !bAmbiguous ) + { + rtl::OUString aChartTypeName = xChartType->getChartType(); + bResult = ( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_COLUMN) || + aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_BAR) ); + } + } + + return bResult; +} + +sal_Bool ChartTypeHelper::isSupportingGeometryProperties( const uno::Reference< XChartType >& xChartType, sal_Int32 nDimensionCount ) +{ + //form tab only for 3D-bar and 3D-column charts. + + //@todo ask charttype itself --> need model change first + if(xChartType.is()) + { + if(nDimensionCount==3) + { + rtl::OUString aChartTypeName = xChartType->getChartType(); + if( aChartTypeName.equals(CHART2_SERVICE_NAME_CHARTTYPE_BAR) ) + return sal_True; + if( aChartTypeName.equals(CHART2_SERVICE_NAME_CHARTTYPE_COLUMN) ) + return sal_True; + } + } + return sal_False; +} + +sal_Bool ChartTypeHelper::isSupportingStatisticProperties( const uno::Reference< XChartType >& xChartType, sal_Int32 nDimensionCount ) +{ + //3D charts, pie, net and stock do not support statistic properties + + //@todo ask charttype itself (and series? --> stock chart?) --> need model change first + if(xChartType.is()) + { + if(nDimensionCount==3) + return sal_False; + + rtl::OUString aChartTypeName = xChartType->getChartType(); + if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_PIE) ) + return sal_False; + if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_NET) ) + return sal_False; + if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_FILLED_NET) ) + return sal_False; + if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK) ) + return sal_False; + if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_BUBBLE) ) //todo: BubbleChart support error bars and trend lines + return sal_False; + } + return sal_True; +} + +sal_Bool ChartTypeHelper::isSupportingRegressionProperties( const uno::Reference< XChartType >& xChartType, sal_Int32 nDimensionCount ) +{ + // note: old chart: only scatter chart + return isSupportingStatisticProperties( xChartType, nDimensionCount ); +} + +sal_Bool ChartTypeHelper::isSupportingAreaProperties( const uno::Reference< XChartType >& xChartType, sal_Int32 nDimensionCount ) +{ + //2D line charts, net and stock do not support area properties + + //@todo ask charttype itself --> need model change first + if(xChartType.is()) + { + if(nDimensionCount==2) + { + rtl::OUString aChartTypeName = xChartType->getChartType(); + if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_LINE) ) + return sal_False; + if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_SCATTER) ) + return sal_False; + if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_NET) ) + return sal_False; + if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK) ) + return sal_False; + } + } + return sal_True; +} + +sal_Bool ChartTypeHelper::isSupportingSymbolProperties( const uno::Reference< XChartType >& xChartType, sal_Int32 nDimensionCount ) +{ + //2D line charts, 2D scatter charts and 2D net charts do support symbols + + //@todo ask charttype itself --> need model change first + if(xChartType.is()) + { + if(nDimensionCount==3) + return sal_False; + + rtl::OUString aChartTypeName = xChartType->getChartType(); + if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_LINE) ) + return sal_True; + if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_SCATTER) ) + return sal_True; + if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_NET) ) + return sal_True; + } + return sal_False; +} + +sal_Bool ChartTypeHelper::isSupportingMainAxis( const uno::Reference< XChartType >& xChartType, sal_Int32 nDimensionCount, sal_Int32 nDimensionIndex ) +{ + //pie charts do not support axis at all + //no 3rd axis for 2D charts + + //@todo ask charttype itself --> need model change first + if(xChartType.is()) + { + rtl::OUString aChartTypeName = xChartType->getChartType(); + if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_PIE) ) + return sal_False; + + if( nDimensionIndex == 2 ) + return nDimensionCount == 3; + } + return sal_True; +} + +sal_Bool ChartTypeHelper::isSupportingSecondaryAxis( const uno::Reference< XChartType >& xChartType, sal_Int32 nDimensionCount, sal_Int32 /*nDimensionIndex*/ ) +{ + //3D, pie and net charts do not support a secondary axis at all + + //@todo ask charttype itself --> need model change first + if(xChartType.is()) + { + if(nDimensionCount==3) + return sal_False; + + rtl::OUString aChartTypeName = xChartType->getChartType(); + if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_PIE) ) + return sal_False; + if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_NET) ) + return sal_False; + if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_FILLED_NET) ) + return sal_False; + } + return sal_True; +} + +sal_Bool ChartTypeHelper::isSupportingOverlapAndGapWidthProperties( + const uno::Reference< XChartType >& xChartType, sal_Int32 nDimensionCount ) +{ + //2D bar charts do support a this special properties + + //@todo ask charttype itself --> need model change first + if(xChartType.is()) + { + if(nDimensionCount==3) + return sal_False; + + rtl::OUString aChartTypeName = xChartType->getChartType(); + if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_COLUMN) ) + return sal_True; + if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_BAR) ) + return sal_True; + } + return sal_False; +} + +sal_Bool ChartTypeHelper::isSupportingBarConnectors( + const uno::Reference< chart2::XChartType >& xChartType, sal_Int32 nDimensionCount ) +{ + //2D bar charts with stacked series support this + + //@todo ask charttype itself --> need model change first + if(xChartType.is()) + { + if(nDimensionCount==3) + return sal_False; + + bool bFound=false; + bool bAmbiguous=false; + StackMode eStackMode = DiagramHelper::getStackModeFromChartType( xChartType, bFound, bAmbiguous, 0 ); + if( eStackMode != StackMode_Y_STACKED || bAmbiguous ) + return sal_False; + + rtl::OUString aChartTypeName = xChartType->getChartType(); + if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_COLUMN) ) + return sal_True; + if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_BAR) ) + return sal_True; // note: old chart was false here + } + return sal_False; +} + +uno::Sequence < sal_Int32 > ChartTypeHelper::getSupportedLabelPlacements( const uno::Reference< chart2::XChartType >& xChartType + , sal_Int32 nDimensionCount, sal_Bool bSwapXAndY + , const uno::Reference< chart2::XDataSeries >& xSeries ) +{ + (void)nDimensionCount; + + uno::Sequence < sal_Int32 > aRet; + if( !xChartType.is() ) + return aRet; + + rtl::OUString aChartTypeName = xChartType->getChartType(); + if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_PIE) ) + { + bool bDonut = false; + uno::Reference< beans::XPropertySet > xChartTypeProp( xChartType, uno::UNO_QUERY_THROW ); + if(xChartTypeProp.is()) + xChartTypeProp->getPropertyValue( C2U("UseRings")) >>= bDonut; + + if(!bDonut) + { + aRet.realloc(4); + sal_Int32* pSeq = aRet.getArray(); + *pSeq++ = ::com::sun::star::chart::DataLabelPlacement::AVOID_OVERLAP; + *pSeq++ = ::com::sun::star::chart::DataLabelPlacement::OUTSIDE; + *pSeq++ = ::com::sun::star::chart::DataLabelPlacement::INSIDE; + *pSeq++ = ::com::sun::star::chart::DataLabelPlacement::CENTER; + } + else + { + aRet.realloc(1); + sal_Int32* pSeq = aRet.getArray(); + *pSeq++ = ::com::sun::star::chart::DataLabelPlacement::CENTER; + } + } + else if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_SCATTER) + || aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_LINE) + || aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_BUBBLE) + ) + { + aRet.realloc(5); + sal_Int32* pSeq = aRet.getArray(); + *pSeq++ = ::com::sun::star::chart::DataLabelPlacement::TOP; + *pSeq++ = ::com::sun::star::chart::DataLabelPlacement::BOTTOM; + *pSeq++ = ::com::sun::star::chart::DataLabelPlacement::LEFT; + *pSeq++ = ::com::sun::star::chart::DataLabelPlacement::RIGHT; + *pSeq++ = ::com::sun::star::chart::DataLabelPlacement::CENTER; + } + else if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_COLUMN) + || aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_BAR) ) + { + + bool bStacked = false; + { + uno::Reference< beans::XPropertySet > xSeriesProp( xSeries, uno::UNO_QUERY ); + chart2::StackingDirection eStacking = chart2::StackingDirection_NO_STACKING; + xSeriesProp->getPropertyValue( C2U("StackingDirection") ) >>= eStacking; + bStacked = (chart2::StackingDirection_Y_STACKING == eStacking); + } + + aRet.realloc( bStacked ? 3 : 6 ); + sal_Int32* pSeq = aRet.getArray(); + if(!bStacked) + { + if(bSwapXAndY) + { + *pSeq++ = ::com::sun::star::chart::DataLabelPlacement::RIGHT; + *pSeq++ = ::com::sun::star::chart::DataLabelPlacement::LEFT; + } + else + { + *pSeq++ = ::com::sun::star::chart::DataLabelPlacement::TOP; + *pSeq++ = ::com::sun::star::chart::DataLabelPlacement::BOTTOM; + } + } + *pSeq++ = ::com::sun::star::chart::DataLabelPlacement::CENTER; + if(!bStacked) + *pSeq++ = ::com::sun::star::chart::DataLabelPlacement::OUTSIDE; + *pSeq++ = ::com::sun::star::chart::DataLabelPlacement::INSIDE; + *pSeq++ = ::com::sun::star::chart::DataLabelPlacement::NEAR_ORIGIN; + } + else if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_AREA) ) + { + aRet.realloc(1); + sal_Int32* pSeq = aRet.getArray(); + *pSeq++ = ::com::sun::star::chart::DataLabelPlacement::TOP; + } + else if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_NET) ) + { + aRet.realloc(6); + sal_Int32* pSeq = aRet.getArray(); + *pSeq++ = ::com::sun::star::chart::DataLabelPlacement::OUTSIDE; + *pSeq++ = ::com::sun::star::chart::DataLabelPlacement::TOP; + *pSeq++ = ::com::sun::star::chart::DataLabelPlacement::BOTTOM; + *pSeq++ = ::com::sun::star::chart::DataLabelPlacement::LEFT; + *pSeq++ = ::com::sun::star::chart::DataLabelPlacement::RIGHT; + *pSeq++ = ::com::sun::star::chart::DataLabelPlacement::CENTER; + } + else if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_FILLED_NET) ) + { + aRet.realloc(1); + sal_Int32* pSeq = aRet.getArray(); + *pSeq++ = ::com::sun::star::chart::DataLabelPlacement::OUTSIDE; + } + else if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK) ) + { + aRet.realloc( 1 ); + sal_Int32* pSeq = aRet.getArray(); + *pSeq++ = ::com::sun::star::chart::DataLabelPlacement::OUTSIDE; + } + else + { + OSL_ENSURE( false, "unknown charttype" ); + } + + return aRet; +} + +sal_Bool ChartTypeHelper::isSupportingRightAngledAxes( const uno::Reference< chart2::XChartType >& xChartType ) +{ + if(xChartType.is()) + { + rtl::OUString aChartTypeName = xChartType->getChartType(); + if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_PIE) ) + return sal_False; + } + return sal_True; +} + +bool ChartTypeHelper::isSupportingStartingAngle( const uno::Reference< chart2::XChartType >& xChartType ) +{ + if(xChartType.is()) + { + rtl::OUString aChartTypeName = xChartType->getChartType(); + if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_PIE) ) + return true; + } + return false; +} +bool ChartTypeHelper::isSupportingBaseValue( const uno::Reference< chart2::XChartType >& xChartType ) +{ + if(xChartType.is()) + { + rtl::OUString aChartTypeName = xChartType->getChartType(); + if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_COLUMN) + || aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_BAR) + || aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_AREA) + ) + return true; + } + return false; +} + +bool ChartTypeHelper::isSupportingAxisPositioning( const uno::Reference< chart2::XChartType >& xChartType, sal_Int32 nDimensionCount, sal_Int32 nDimensionIndex ) +{ + if(xChartType.is()) + { + rtl::OUString aChartTypeName = xChartType->getChartType(); + if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_NET) ) + return false; + if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_FILLED_NET) ) + return false; + } + if( nDimensionCount==3 ) + return nDimensionIndex<2; + return true; +} + +bool ChartTypeHelper::shiftTicksAtXAxisPerDefault( const uno::Reference< chart2::XChartType >& xChartType ) +{ + if(xChartType.is()) + { + rtl::OUString aChartTypeName = xChartType->getChartType(); + if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_COLUMN) + || aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_BAR) ) + return true; + } + return false; +} + +bool ChartTypeHelper::noBordersForSimpleScheme( const uno::Reference< chart2::XChartType >& xChartType ) +{ + if(xChartType.is()) + { + rtl::OUString aChartTypeName = xChartType->getChartType(); + if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_PIE) ) + return sal_True; + } + return sal_False; +} + +//static +sal_Int32 ChartTypeHelper::getDefaultDirectLightColor( bool bSimple, const uno::Reference< chart2::XChartType >& xChartType ) +{ + sal_Int32 nRet = static_cast< sal_Int32 >( 0x808080 ); // grey + if( xChartType .is() ) + { + rtl::OUString aChartType = xChartType->getChartType(); + if( aChartType.equals(CHART2_SERVICE_NAME_CHARTTYPE_PIE) ) + { + if( bSimple ) + nRet = static_cast< sal_Int32 >( 0x333333 ); // grey80 + else + nRet = static_cast< sal_Int32 >( 0xb3b3b3 ); // grey30 + } + else if( aChartType.equals(CHART2_SERVICE_NAME_CHARTTYPE_LINE) + || aChartType.equals(CHART2_SERVICE_NAME_CHARTTYPE_SCATTER) ) + nRet = static_cast< sal_Int32 >( 0x666666 ); // grey60 + } + return nRet; +} + +//static +sal_Int32 ChartTypeHelper::getDefaultAmbientLightColor( bool bSimple, const uno::Reference< chart2::XChartType >& xChartType ) +{ + sal_Int32 nRet = static_cast< sal_Int32 >( 0x999999 ); // grey40 + if( xChartType .is() ) + { + rtl::OUString aChartType = xChartType->getChartType(); + if( aChartType.equals(CHART2_SERVICE_NAME_CHARTTYPE_PIE) ) + { + if( bSimple ) + nRet = static_cast< sal_Int32 >( 0xcccccc ); // grey20 + else + nRet = static_cast< sal_Int32 >( 0x666666 ); // grey60 + } + } + return nRet; +} + +drawing::Direction3D ChartTypeHelper::getDefaultSimpleLightDirection( const uno::Reference< chart2::XChartType >& xChartType ) +{ + drawing::Direction3D aRet(0.0, 0.0, 1.0); + if( xChartType .is() ) + { + rtl::OUString aChartType = xChartType->getChartType(); + if( aChartType.equals(CHART2_SERVICE_NAME_CHARTTYPE_PIE) ) + aRet = drawing::Direction3D(0.0, 0.8, 0.5); + else if( aChartType.equals(CHART2_SERVICE_NAME_CHARTTYPE_LINE) + || aChartType.equals(CHART2_SERVICE_NAME_CHARTTYPE_SCATTER) ) + aRet = drawing::Direction3D(0.9, 0.5, 0.05); + } + return aRet; +} + +drawing::Direction3D ChartTypeHelper::getDefaultRealisticLightDirection( const uno::Reference< chart2::XChartType >& xChartType ) +{ + drawing::Direction3D aRet(0.0, 0.0, 1.0); + if( xChartType .is() ) + { + rtl::OUString aChartType = xChartType->getChartType(); + if( aChartType.equals(CHART2_SERVICE_NAME_CHARTTYPE_PIE) ) + aRet = drawing::Direction3D(0.6, 0.6, 0.6); + else if( aChartType.equals(CHART2_SERVICE_NAME_CHARTTYPE_LINE) + || aChartType.equals(CHART2_SERVICE_NAME_CHARTTYPE_SCATTER) ) + aRet = drawing::Direction3D(0.9, 0.5, 0.05); + } + return aRet; +} + +sal_Int32 ChartTypeHelper::getAxisType( const uno::Reference< + XChartType >& xChartType, sal_Int32 nDimensionIndex ) +{ + //retruned is a constant from constant group ::com::sun::star::chart2::AxisType + + //@todo ask charttype itself --> need model change first + if(!xChartType.is()) + return AxisType::CATEGORY; + + rtl::OUString aChartTypeName = xChartType->getChartType(); + if(2==nDimensionIndex)//z-axis + return AxisType::SERIES; + if(1==nDimensionIndex)//y-axis + return AxisType::REALNUMBER; + if(0==nDimensionIndex)//x-axis + { + if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_SCATTER) + || aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_BUBBLE) ) + return AxisType::REALNUMBER; + return AxisType::CATEGORY; + } + return AxisType::CATEGORY; +} + +sal_Int32 ChartTypeHelper::getNumberOfDisplayedSeries( + const uno::Reference< XChartType >& xChartType, + sal_Int32 nNumberOfSeries ) +{ + if( xChartType.is() ) + { + try + { + rtl::OUString aChartTypeName = xChartType->getChartType(); + if( aChartTypeName.equals(CHART2_SERVICE_NAME_CHARTTYPE_PIE)) + { + uno::Reference< beans::XPropertySet > xChartTypeProp( xChartType, uno::UNO_QUERY_THROW ); + bool bDonut = false; + if( (xChartTypeProp->getPropertyValue( C2U("UseRings")) >>= bDonut) + && !bDonut ) + { + return nNumberOfSeries>0 ? 1 : 0; + } + } + } + catch( const uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + } + return nNumberOfSeries; +} + +uno::Sequence < sal_Int32 > ChartTypeHelper::getSupportedMissingValueTreatments( const uno::Reference< XChartType >& xChartType ) +{ + uno::Sequence < sal_Int32 > aRet; + if( !xChartType.is() ) + return aRet; + + bool bStacked = false; + bool bFound=false; + bool bAmbiguous=false; + StackMode eStackMode = DiagramHelper::getStackModeFromChartType( xChartType, bFound, bAmbiguous, 0 ); + bStacked = bFound && (StackMode_Y_STACKED == eStackMode); + + rtl::OUString aChartTypeName = xChartType->getChartType(); + if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_COLUMN) || + aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_BAR) || + aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_BUBBLE) ) + { + aRet.realloc( 2 ); + sal_Int32* pSeq = aRet.getArray(); + *pSeq++ = ::com::sun::star::chart::MissingValueTreatment::LEAVE_GAP; + *pSeq++ = ::com::sun::star::chart::MissingValueTreatment::USE_ZERO; + } + else if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_AREA) ) + { + aRet.realloc( bStacked ? 1 : 2 ); + sal_Int32* pSeq = aRet.getArray(); + *pSeq++ = ::com::sun::star::chart::MissingValueTreatment::USE_ZERO; + if( !bStacked ) + *pSeq++ = ::com::sun::star::chart::MissingValueTreatment::CONTINUE; + } + else if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_LINE) || + aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_NET) || + aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_FILLED_NET) ) + { + aRet.realloc( bStacked ? 2 : 3 ); + sal_Int32* pSeq = aRet.getArray(); + *pSeq++ = ::com::sun::star::chart::MissingValueTreatment::LEAVE_GAP; + *pSeq++ = ::com::sun::star::chart::MissingValueTreatment::USE_ZERO; + if( !bStacked ) + *pSeq++ = ::com::sun::star::chart::MissingValueTreatment::CONTINUE; + } + else if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_SCATTER) ) + { + aRet.realloc( 3 ); + sal_Int32* pSeq = aRet.getArray(); + *pSeq++ = ::com::sun::star::chart::MissingValueTreatment::CONTINUE; + *pSeq++ = ::com::sun::star::chart::MissingValueTreatment::LEAVE_GAP; + *pSeq++ = ::com::sun::star::chart::MissingValueTreatment::USE_ZERO; + } + else if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_PIE) || + aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK) ) + { + aRet.realloc( 0 ); + } + else + { + OSL_ENSURE( false, "unknown charttype" ); + } + + return aRet; +} + +bool ChartTypeHelper::isSeriesInFrontOfAxisLine( const uno::Reference< XChartType >& xChartType ) +{ + if( xChartType.is() ) + { + rtl::OUString aChartTypeName = xChartType->getChartType(); + if( aChartTypeName.match( CHART2_SERVICE_NAME_CHARTTYPE_FILLED_NET ) ) + return false; + } + return true; +} + +rtl::OUString ChartTypeHelper::getRoleOfSequenceForYAxisNumberFormatDetection( const uno::Reference< XChartType >& xChartType ) +{ + rtl::OUString aRet( C2U( "values-y" ) ); + if( !xChartType.is() ) + return aRet; + rtl::OUString aChartTypeName = xChartType->getChartType(); + if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK) ) + aRet = xChartType->getRoleOfSequenceForSeriesLabel(); + return aRet; +} + +rtl::OUString ChartTypeHelper::getRoleOfSequenceForDataLabelNumberFormatDetection( const uno::Reference< XChartType >& xChartType ) +{ + rtl::OUString aRet( C2U( "values-y" ) ); + if( !xChartType.is() ) + return aRet; + rtl::OUString aChartTypeName = xChartType->getChartType(); + if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK) + || aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_BUBBLE) ) + aRet = xChartType->getRoleOfSequenceForSeriesLabel(); + return aRet; +} + +bool ChartTypeHelper::shouldLabelNumberFormatKeyBeDetectedFromYAxis( const uno::Reference< XChartType >& xChartType ) +{ + bool bRet = true; + rtl::OUString aChartTypeName = xChartType->getChartType(); + if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_BUBBLE) ) + bRet = false; + return bRet; +} + +bool ChartTypeHelper::isSupportingOnlyDeepStackingFor3D( const uno::Reference< XChartType >& xChartType ) +{ + bool bRet = false; + if( !xChartType.is() ) + return bRet; + + rtl::OUString aChartTypeName = xChartType->getChartType(); + if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_LINE) || + aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_SCATTER) || + aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_AREA) ) + { + bRet = true; + } + return bRet; +} + +//............................................................................. +} //namespace chart +//............................................................................. diff --git a/chart2/source/tools/ChartViewHelper.cxx b/chart2/source/tools/ChartViewHelper.cxx new file mode 100644 index 000000000000..55fbd368426a --- /dev/null +++ b/chart2/source/tools/ChartViewHelper.cxx @@ -0,0 +1,72 @@ +/************************************************************************* + * + * 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 "ChartViewHelper.hxx" +#include "macros.hxx" +#include "servicenames.hxx" + +// header for define DBG_ASSERT +#include <tools/debug.hxx> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/util/XModifyListener.hpp> + +//............................................................................. +namespace chart +{ +//............................................................................. +using namespace ::com::sun::star; +using ::com::sun::star::uno::Reference; + +//static +void ChartViewHelper::setViewToDirtyState( const uno::Reference< frame::XModel >& xChartModel ) +{ + try + { + uno::Reference< lang::XMultiServiceFactory > xFact( xChartModel, uno::UNO_QUERY ); + if( xFact.is() ) + { + Reference< util::XModifyListener > xModifyListener( + xFact->createInstance( CHART_VIEW_SERVICE_NAME ), uno::UNO_QUERY ); + if( xModifyListener.is() ) + { + lang::EventObject aEvent( Reference< lang::XComponent >( xChartModel, uno::UNO_QUERY ) ); + xModifyListener->modified( aEvent ); + } + } + } + catch( uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } +} +//............................................................................. +} //namespace chart +//............................................................................. diff --git a/chart2/source/tools/ColorPerPointHelper.cxx b/chart2/source/tools/ColorPerPointHelper.cxx new file mode 100644 index 000000000000..762cb436a9a7 --- /dev/null +++ b/chart2/source/tools/ColorPerPointHelper.cxx @@ -0,0 +1,97 @@ +/************************************************************************* + * + * 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 "ColorPerPointHelper.hxx" +#include "macros.hxx" +#include <com/sun/star/chart2/XDataSeries.hpp> +#include <com/sun/star/beans/XPropertyState.hpp> + +#include <algorithm> + +//............................................................................. +namespace chart +{ +//............................................................................. +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +//static +bool ColorPerPointHelper::hasPointOwnColor( + const ::com::sun::star::uno::Reference< + ::com::sun::star::beans::XPropertySet >& xDataSeriesProperties + , sal_Int32 nPointIndex + , const ::com::sun::star::uno::Reference< + ::com::sun::star::beans::XPropertySet >& xDataPointProperties //may be NULL this is just for performance + ) +{ + if( !xDataSeriesProperties.is() ) + return false; + + if( hasPointOwnProperties( xDataSeriesProperties, nPointIndex )) + { + uno::Reference< beans::XPropertyState > xPointState( xDataPointProperties, uno::UNO_QUERY ); + if( !xPointState.is() ) + { + uno::Reference< XDataSeries > xSeries( xDataSeriesProperties, uno::UNO_QUERY ); + if(xSeries.is()) + xPointState.set( xSeries->getDataPointByIndex( nPointIndex ), uno::UNO_QUERY ); + } + if( !xPointState.is() ) + return false; + + return (xPointState->getPropertyState( C2U("Color")) != beans::PropertyState_DEFAULT_VALUE ); + } + + return false; +} + +// static +bool ColorPerPointHelper::hasPointOwnProperties( + const ::com::sun::star::uno::Reference< + ::com::sun::star::beans::XPropertySet >& xSeriesProperties + , sal_Int32 nPointIndex ) +{ + if( xSeriesProperties.is() ) + { + uno::Sequence< sal_Int32 > aIndexList; + if( xSeriesProperties->getPropertyValue( C2U( "AttributedDataPoints" ) ) >>= aIndexList ) + { + const sal_Int32 * pBegIt = aIndexList.getConstArray(); + const sal_Int32 * pEndIt = pBegIt + aIndexList.getLength(); + return ( ::std::find( pBegIt, pEndIt, nPointIndex ) != pEndIt ); + } + } + + return false; +} + +//............................................................................. +} //namespace chart +//............................................................................. diff --git a/chart2/source/tools/CommonConverters.cxx b/chart2/source/tools/CommonConverters.cxx new file mode 100644 index 000000000000..e9d90248ce84 --- /dev/null +++ b/chart2/source/tools/CommonConverters.cxx @@ -0,0 +1,549 @@ +/************************************************************************* + * + * 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 "CommonConverters.hxx" +#include <com/sun/star/drawing/DoubleSequence.hpp> +#include <com/sun/star/text/WritingMode2.hpp> +#include <com/sun/star/chart2/data/XNumericalDataSequence.hpp> +#include <com/sun/star/chart2/data/XTextualDataSequence.hpp> +#include <rtl/math.hxx> +#include <basegfx/matrix/b3dhommatrix.hxx> + +#include <cstdarg> + + +//............................................................................. +namespace chart +{ +//............................................................................. + +using namespace ::com::sun::star; + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +// diverse methods for class conversions; e.g. ::basegfx::B3DHomMatrix to HomogenMatrix +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + +drawing::HomogenMatrix B3DHomMatrixToHomogenMatrix( const ::basegfx::B3DHomMatrix& rM ) +{ + drawing::HomogenMatrix aHM; + aHM.Line1.Column1 = rM.get(0, 0); + aHM.Line1.Column2 = rM.get(0, 1); + aHM.Line1.Column3 = rM.get(0, 2); + aHM.Line1.Column4 = rM.get(0, 3); + aHM.Line2.Column1 = rM.get(1, 0); + aHM.Line2.Column2 = rM.get(1, 1); + aHM.Line2.Column3 = rM.get(1, 2); + aHM.Line2.Column4 = rM.get(1, 3); + aHM.Line3.Column1 = rM.get(2, 0); + aHM.Line3.Column2 = rM.get(2, 1); + aHM.Line3.Column3 = rM.get(2, 2); + aHM.Line3.Column4 = rM.get(2, 3); + aHM.Line4.Column1 = rM.get(3, 0); + aHM.Line4.Column2 = rM.get(3, 1); + aHM.Line4.Column3 = rM.get(3, 2); + aHM.Line4.Column4 = rM.get(3, 3); + return aHM; +} + +::basegfx::B3DHomMatrix HomogenMatrixToB3DHomMatrix( const drawing::HomogenMatrix& rHM ) +{ + ::basegfx::B3DHomMatrix aM; + aM.set(0, 0, rHM.Line1.Column1); + aM.set(0, 1, rHM.Line1.Column2); + aM.set(0, 2, rHM.Line1.Column3); + aM.set(0, 3, rHM.Line1.Column4); + aM.set(1, 0, rHM.Line2.Column1); + aM.set(1, 1, rHM.Line2.Column2); + aM.set(1, 2, rHM.Line2.Column3); + aM.set(1, 3, rHM.Line2.Column4); + aM.set(2, 0, rHM.Line3.Column1); + aM.set(2, 1, rHM.Line3.Column2); + aM.set(2, 2, rHM.Line3.Column3); + aM.set(2, 3, rHM.Line3.Column4); + aM.set(3, 0, rHM.Line4.Column1); + aM.set(3, 1, rHM.Line4.Column2); + aM.set(3, 2, rHM.Line4.Column3); + aM.set(3, 3, rHM.Line4.Column4); + return aM; +} + +::basegfx::B2DHomMatrix IgnoreZ( const ::basegfx::B3DHomMatrix& rM ) +{ + ::basegfx::B2DHomMatrix aM; + aM.set(0, 0, rM.get(0, 0)); + aM.set(0, 1, rM.get(0, 1)); + aM.set(0, 2, rM.get(0, 3)); + aM.set(1, 0, rM.get(1, 0)); + aM.set(1, 1, rM.get(1, 1)); + aM.set(1, 2, rM.get(1, 3)); + aM.set(2, 0, rM.get(3, 0)); + aM.set(2, 1, rM.get(3, 1)); + aM.set(2, 2, rM.get(3, 3)); + return aM; +} + + +drawing::HomogenMatrix3 B2DHomMatrixToHomogenMatrix3( const ::basegfx::B2DHomMatrix& rM ) +{ + drawing::HomogenMatrix3 aHM; + aHM.Line1.Column1 = rM.get(0, 0); + aHM.Line1.Column2 = rM.get(0, 1); + aHM.Line1.Column3 = rM.get(0, 2); + aHM.Line2.Column1 = rM.get(1, 0); + aHM.Line2.Column2 = rM.get(1, 1); + aHM.Line2.Column3 = rM.get(1, 2); + aHM.Line3.Column1 = rM.get(2, 0); + aHM.Line3.Column2 = rM.get(2, 1); + aHM.Line3.Column3 = rM.get(2, 2); + return aHM; +} + +::basegfx::B3DPoint Position3DToB3DPoint( const drawing::Position3D& rPosition ) +{ + return ::basegfx::B3DPoint( + rPosition.PositionX , + rPosition.PositionY , + rPosition.PositionZ ); +} + +drawing::Direction3D B3DVectorToDirection3D( const ::basegfx::B3DVector& rVector) +{ + return drawing::Direction3D( + rVector.getX() + , rVector.getY() + , rVector.getZ() + ); +} + +drawing::Position3D B3DPointToPosition3D( const ::basegfx::B3DPoint& rPoint) +{ + return drawing::Position3D( + rPoint.getX() + , rPoint.getY() + , rPoint.getZ() + ); +} + +::basegfx::B3DVector Direction3DToB3DVector( const drawing::Direction3D& rDirection) +{ + return ::basegfx::B3DVector( + rDirection.DirectionX + , rDirection.DirectionY + , rDirection.DirectionZ + ); +} + +void AddPointToPoly( drawing::PolyPolygonShape3D& rPoly, const drawing::Position3D& rPos, sal_Int32 nPolygonIndex ) +{ + if(nPolygonIndex<0) + { + OSL_ENSURE( false, "The polygon index needs to be > 0"); + nPolygonIndex=0; + } + + //make sure that we have enough polygons + if(nPolygonIndex >= rPoly.SequenceX.getLength() ) + { + rPoly.SequenceX.realloc(nPolygonIndex+1); + rPoly.SequenceY.realloc(nPolygonIndex+1); + rPoly.SequenceZ.realloc(nPolygonIndex+1); + } + + drawing::DoubleSequence* pOuterSequenceX = &rPoly.SequenceX.getArray()[nPolygonIndex]; + drawing::DoubleSequence* pOuterSequenceY = &rPoly.SequenceY.getArray()[nPolygonIndex]; + drawing::DoubleSequence* pOuterSequenceZ = &rPoly.SequenceZ.getArray()[nPolygonIndex]; + + sal_Int32 nOldPointCount = pOuterSequenceX->getLength(); + + pOuterSequenceX->realloc(nOldPointCount+1); + pOuterSequenceY->realloc(nOldPointCount+1); + pOuterSequenceZ->realloc(nOldPointCount+1); + + double* pInnerSequenceX = pOuterSequenceX->getArray(); + double* pInnerSequenceY = pOuterSequenceY->getArray(); + double* pInnerSequenceZ = pOuterSequenceZ->getArray(); + + pInnerSequenceX[nOldPointCount] = rPos.PositionX; + pInnerSequenceY[nOldPointCount] = rPos.PositionY; + pInnerSequenceZ[nOldPointCount] = rPos.PositionZ; +} + +drawing::Position3D getPointFromPoly( const drawing::PolyPolygonShape3D& rPolygon, sal_Int32 nPointIndex, sal_Int32 nPolyIndex ) +{ + drawing::Position3D aRet(0.0,0.0,0.0); + + if( nPolyIndex>=0 && nPolyIndex<rPolygon.SequenceX.getLength()) + { + if(nPointIndex<rPolygon.SequenceX[nPolyIndex].getLength()) + { + aRet.PositionX = rPolygon.SequenceX[nPolyIndex][nPointIndex]; + aRet.PositionY = rPolygon.SequenceY[nPolyIndex][nPointIndex]; + aRet.PositionZ = rPolygon.SequenceZ[nPolyIndex][nPointIndex]; + } + else + { + ;DBG_ERROR("polygon was accessed with a wrong index"); + } + } + else + { + ;DBG_ERROR("polygon was accessed with a wrong index"); + } + return aRet; +} + +void addPolygon( drawing::PolyPolygonShape3D& rRet, const drawing::PolyPolygonShape3D& rAdd ) +{ + sal_Int32 nAddOuterCount = rAdd.SequenceX.getLength(); + sal_Int32 nOuterCount = rRet.SequenceX.getLength() + nAddOuterCount; + rRet.SequenceX.realloc( nOuterCount ); + rRet.SequenceY.realloc( nOuterCount ); + rRet.SequenceZ.realloc( nOuterCount ); + + sal_Int32 nIndex = 0; + sal_Int32 nOuter = nOuterCount - nAddOuterCount; + for( ; nOuter < nOuterCount; nOuter++ ) + { + if( nIndex >= nAddOuterCount ) + break; + + rRet.SequenceX[nOuter] = rAdd.SequenceX[nIndex]; + rRet.SequenceY[nOuter] = rAdd.SequenceY[nIndex]; + rRet.SequenceZ[nOuter] = rAdd.SequenceZ[nIndex]; + + nIndex++; + } +} + +void appendPoly( drawing::PolyPolygonShape3D& rRet, const drawing::PolyPolygonShape3D& rAdd ) +{ + sal_Int32 nOuterCount = Max( rRet.SequenceX.getLength(), rAdd.SequenceX.getLength() ); + rRet.SequenceX.realloc(nOuterCount); + rRet.SequenceY.realloc(nOuterCount); + rRet.SequenceZ.realloc(nOuterCount); + + for( sal_Int32 nOuter=0;nOuter<nOuterCount;nOuter++ ) + { + sal_Int32 nOldPointCount = rRet.SequenceX[nOuter].getLength(); + sal_Int32 nAddPointCount = 0; + if(nOuter<rAdd.SequenceX.getLength()) + nAddPointCount = rAdd.SequenceX[nOuter].getLength(); + if(!nAddPointCount) + continue; + + sal_Int32 nNewPointCount = nOldPointCount + nAddPointCount; + + rRet.SequenceX[nOuter].realloc(nNewPointCount); + rRet.SequenceY[nOuter].realloc(nNewPointCount); + rRet.SequenceZ[nOuter].realloc(nNewPointCount); + + sal_Int32 nPointTarget=nOldPointCount; + sal_Int32 nPointSource=nAddPointCount; + for( ; nPointSource-- ; nPointTarget++ ) + { + rRet.SequenceX[nOuter][nPointTarget] = rAdd.SequenceX[nOuter][nPointSource]; + rRet.SequenceY[nOuter][nPointTarget] = rAdd.SequenceY[nOuter][nPointSource]; + rRet.SequenceZ[nOuter][nPointTarget] = rAdd.SequenceZ[nOuter][nPointSource]; + } + } +} + +drawing::PolyPolygonShape3D BezierToPoly( + const drawing::PolyPolygonBezierCoords& rBezier ) +{ + const drawing::PointSequenceSequence& rPointSequence = rBezier.Coordinates; +// const drawing::FlagSequenceSequence& rFlags = rBezier.Flags; + + drawing::PolyPolygonShape3D aRet; + aRet.SequenceX.realloc( rPointSequence.getLength() ); + aRet.SequenceY.realloc( rPointSequence.getLength() ); + aRet.SequenceZ.realloc( rPointSequence.getLength() ); + + sal_Int32 nRealOuter = 0; + for(sal_Int32 nN = 0; nN < rPointSequence.getLength(); nN++) + { + sal_Int32 nInnerLength = rPointSequence[nN].getLength(); + aRet.SequenceX[nN].realloc( nInnerLength ); + aRet.SequenceY[nN].realloc( nInnerLength ); + aRet.SequenceZ[nN].realloc( nInnerLength ); + + bool bHasOuterFlags = nN < rBezier.Flags.getLength(); + + sal_Int32 nRealInner = 0; + for( sal_Int32 nM = 0; nM < nInnerLength; nM++) + { + bool bHasInnerFlags = bHasOuterFlags && (nM < rBezier.Flags[nN].getLength()); + + if( !bHasInnerFlags || (rBezier.Flags[nN][nM] == drawing::PolygonFlags_NORMAL) ) + { + aRet.SequenceX[nRealOuter][nRealInner] = rPointSequence[nN][nM].X; + aRet.SequenceY[nRealOuter][nRealInner] = rPointSequence[nN][nM].Y; + aRet.SequenceZ[nRealOuter][nRealInner] = 0.0; + nRealInner++; + } + } + + aRet.SequenceX[nRealOuter].realloc( nRealInner ); + aRet.SequenceY[nRealOuter].realloc( nRealInner ); + aRet.SequenceZ[nRealOuter].realloc( nRealInner ); + + if( nRealInner>0 ) + nRealOuter++; + } + + aRet.SequenceX.realloc( nRealOuter ); + aRet.SequenceY.realloc( nRealOuter ); + aRet.SequenceZ.realloc( nRealOuter ); + + return aRet; +} + +drawing::PointSequenceSequence PolyToPointSequence( + const drawing::PolyPolygonShape3D& rPolyPolygon ) +{ + drawing::PointSequenceSequence aRet; + aRet.realloc( rPolyPolygon.SequenceX.getLength() ); + + for(sal_Int32 nN = 0; nN < rPolyPolygon.SequenceX.getLength(); nN++) + { + sal_Int32 nInnerLength = rPolyPolygon.SequenceX[nN].getLength(); + aRet[nN].realloc( nInnerLength ); + for( sal_Int32 nM = 0; nM < nInnerLength; nM++) + { + aRet[nN][nM].X = static_cast<sal_Int32>(rPolyPolygon.SequenceX[nN][nM]); + aRet[nN][nM].Y = static_cast<sal_Int32>(rPolyPolygon.SequenceY[nN][nM]); + } + } + return aRet; +} + +void appendPointSequence( drawing::PointSequenceSequence& rTarget + , drawing::PointSequenceSequence& rAdd ) +{ + sal_Int32 nAddCount = rAdd.getLength(); + if(!nAddCount) + return; + sal_Int32 nOldCount = rTarget.getLength(); + + rTarget.realloc(nOldCount+nAddCount); + for(sal_Int32 nS=0; nS<nAddCount; nS++ ) + rTarget[nOldCount+nS]=rAdd[nS]; +} + +drawing::Position3D operator+( const drawing::Position3D& rPos + , const drawing::Direction3D& rDirection) +{ + return drawing::Position3D( + rPos.PositionX + rDirection.DirectionX + , rPos.PositionY + rDirection.DirectionY + , rPos.PositionZ + rDirection.DirectionZ + ); +} + +drawing::Direction3D operator-( const drawing::Position3D& rPos1 + , const drawing::Position3D& rPos2) +{ + return drawing::Direction3D( + rPos1.PositionX - rPos2.PositionX + , rPos1.PositionY - rPos2.PositionY + , rPos1.PositionZ - rPos2.PositionZ + ); +} + +bool operator==( const drawing::Position3D& rPos1 + , const drawing::Position3D& rPos2) +{ + return rPos1.PositionX == rPos2.PositionX + && rPos1.PositionY == rPos2.PositionY + && rPos1.PositionZ == rPos2.PositionZ; +} + +awt::Point Position3DToAWTPoint( const drawing::Position3D& rPos ) +{ + awt::Point aRet; + aRet.X = static_cast<sal_Int32>(rPos.PositionX); + aRet.Y = static_cast<sal_Int32>(rPos.PositionY); + return aRet; +} + +awt::Point ToPoint( const awt::Rectangle& rRectangle ) +{ + return awt::Point( rRectangle.X, rRectangle.Y ); +} + +awt::Size ToSize( const awt::Rectangle& rRectangle ) +{ + return awt::Size( rRectangle.Width, rRectangle.Height ); +} + +awt::Size Direction3DToAWTSize( const drawing::Direction3D& rDirection ) +{ + awt::Size aRet; + aRet.Width = static_cast<sal_Int32>(rDirection.DirectionX); + aRet.Height = static_cast<sal_Int32>(rDirection.DirectionY); + return aRet; +} + +uno::Sequence< double > B3DPointToSequence( const ::basegfx::B3DPoint& rPoint ) +{ + uno::Sequence< double > aRet(3); + aRet[0] = rPoint.getX(); + aRet[1] = rPoint.getY(); + aRet[2] = rPoint.getZ(); + return aRet; +} + +drawing::Position3D SequenceToPosition3D( const uno::Sequence< double >& rSeq ) +{ + OSL_ENSURE(rSeq.getLength()==3,"The sequence needs to have length 3 for conversion into vector"); + + drawing::Position3D aRet; + aRet.PositionX = rSeq.getLength()>0?rSeq[0]:0.0; + aRet.PositionY = rSeq.getLength()>1?rSeq[1]:0.0; + aRet.PositionZ = rSeq.getLength()>2?rSeq[2]:0.0; + return aRet; +} + +uno::Sequence< double > Position3DToSequence( const drawing::Position3D& rPosition ) +{ + uno::Sequence< double > aRet(3); + aRet[0] = rPosition.PositionX; + aRet[1] = rPosition.PositionY; + aRet[2] = rPosition.PositionZ; + return aRet; +} + +using namespace ::com::sun::star::chart2; + +uno::Sequence< double > DataSequenceToDoubleSequence( + const uno::Reference< data::XDataSequence >& xDataSequence ) +{ + uno::Sequence< double > aResult; + OSL_ASSERT( xDataSequence.is()); + if(!xDataSequence.is()) + return aResult; + + uno::Reference< data::XNumericalDataSequence > xNumericalDataSequence( xDataSequence, uno::UNO_QUERY ); + if( xNumericalDataSequence.is() ) + { + aResult = xNumericalDataSequence->getNumericalData(); + } + else + { + uno::Sequence< uno::Any > aValues = xDataSequence->getData(); + aResult.realloc(aValues.getLength()); + for(sal_Int32 nN=aValues.getLength();nN--;) + { + if( !(aValues[nN] >>= aResult[nN]) ) + ::rtl::math::setNan( &aResult[nN] ); + } + } + + return aResult; +} + +uno::Sequence< rtl::OUString > DataSequenceToStringSequence( + const uno::Reference< data::XDataSequence >& xDataSequence ) +{ + uno::Sequence< rtl::OUString > aResult; + OSL_ASSERT( xDataSequence.is()); + if(!xDataSequence.is()) + return aResult; + + uno::Reference< data::XTextualDataSequence > xTextualDataSequence( xDataSequence, uno::UNO_QUERY ); + if( xTextualDataSequence.is() ) + { + aResult = xTextualDataSequence->getTextualData(); + } + else + { + uno::Sequence< uno::Any > aValues = xDataSequence->getData(); + aResult.realloc(aValues.getLength()); + + for(sal_Int32 nN=aValues.getLength();nN--;) + aValues[nN] >>= aResult[nN]; + } + + return aResult; +} + +sal_Bool hasDoubleValue( const uno::Any& rAny ) +{ + sal_Bool bRet = sal_False; + double fValue = 0.0; + if( rAny >>= fValue ) + bRet = sal_True; + return bRet; +} + +sal_Bool hasLongOrShortValue( const uno::Any& rAny ) +{ + sal_Bool bRet = sal_False; + sal_Int32 n32 = 0; + if( rAny >>= n32 ) + bRet = sal_True; + else + { + sal_Int16 n16 = 0; + if( rAny >>= n16 ) + bRet = sal_True; + } + return bRet; +} +sal_Int16 getShortForLongAlso( const uno::Any& rAny ) +{ + sal_Int16 nRet = 0; + + if( !(rAny >>= nRet) ) + { + sal_Int32 n32 = 0; + if( rAny >>= n32 ) + nRet = static_cast<sal_Int16>(n32); + } + return nRet; +} + +bool replaceParamterInString( rtl::OUString & rInOutResourceString, + const rtl::OUString & rParamToReplace, + const rtl::OUString & rReplaceWith ) +{ + sal_Int32 nPos = rInOutResourceString.indexOf( rParamToReplace ); + if( nPos == -1 ) + return false; + + rInOutResourceString = rInOutResourceString.replaceAt( nPos + , rParamToReplace.getLength(), rReplaceWith ); + return true; +} + +//............................................................................. +} //namespace chart +//............................................................................. diff --git a/chart2/source/tools/ConfigColorScheme.cxx b/chart2/source/tools/ConfigColorScheme.cxx new file mode 100644 index 000000000000..fb7106d87096 --- /dev/null +++ b/chart2/source/tools/ConfigColorScheme.cxx @@ -0,0 +1,202 @@ +/************************************************************************* + * + * 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 "ConfigColorScheme.hxx" +#include "ContainerHelper.hxx" +#include "macros.hxx" + +#include <unotools/configitem.hxx> + +#include <set> + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::rtl::OUString; + +namespace +{ + +static const OUString aSeriesPropName( RTL_CONSTASCII_USTRINGPARAM("Series")); + +} // anonymous namespace + +// -------------------------------------------------------------------------------- + +namespace chart +{ + +uno::Reference< chart2::XColorScheme > createConfigColorScheme( const uno::Reference< uno::XComponentContext > & xContext ) +{ + return new ConfigColorScheme( xContext ); +} + +namespace impl +{ +class ChartConfigItem : public ::utl::ConfigItem +{ +public: + explicit ChartConfigItem( ConfigItemListener & rListener ); + virtual ~ChartConfigItem(); + + void addPropertyNotification( const OUString & rPropertyName ); + + uno::Any getProperty( const OUString & aPropertyName ); + +protected: + // ____ ::utl::ConfigItem ____ + virtual void Commit(); + virtual void Notify( const Sequence< OUString > & aPropertyNames ); + +private: + ConfigItemListener & m_rListener; + ::std::set< OUString > m_aPropertiesToNotify; +}; + +ChartConfigItem::ChartConfigItem( ConfigItemListener & rListener ) : + ::utl::ConfigItem( C2U("Office.Chart/DefaultColor")), + m_rListener( rListener ) +{} + +ChartConfigItem::~ChartConfigItem() +{} + +void ChartConfigItem::Notify( const Sequence< OUString > & aPropertyNames ) +{ + for( sal_Int32 nIdx=0; nIdx<aPropertyNames.getLength(); ++nIdx ) + { + if( m_aPropertiesToNotify.find( aPropertyNames[nIdx] ) != m_aPropertiesToNotify.end()) + m_rListener.notify( aPropertyNames[nIdx] ); + } +} + +void ChartConfigItem::Commit() +{} + +void ChartConfigItem::addPropertyNotification( const OUString & rPropertyName ) +{ + m_aPropertiesToNotify.insert( rPropertyName ); + EnableNotification( ContainerHelper::ContainerToSequence( m_aPropertiesToNotify )); +} + +uno::Any ChartConfigItem::getProperty( const OUString & aPropertyName ) +{ + Sequence< uno::Any > aValues( + GetProperties( Sequence< OUString >( &aPropertyName, 1 ))); + if( ! aValues.getLength()) + return uno::Any(); + return aValues[0]; +} + +} // namespace impl + +// -------------------------------------------------------------------------------- + +// explicit +ConfigColorScheme::ConfigColorScheme( + const Reference< uno::XComponentContext > & xContext ) : + m_xContext( xContext ), + m_nNumberOfColors( 0 ), + m_bNeedsUpdate( true ) +{ +} + +ConfigColorScheme::~ConfigColorScheme() +{} + +void ConfigColorScheme::retrieveConfigColors() +{ + if( ! m_xContext.is()) + return; + + // create config item if necessary + if( ! m_apChartConfigItem.get()) + { + m_apChartConfigItem.reset( + new impl::ChartConfigItem( *this )); + m_apChartConfigItem->addPropertyNotification( aSeriesPropName ); + } + OSL_ASSERT( m_apChartConfigItem.get()); + if( ! m_apChartConfigItem.get()) + return; + + // retrieve colors + uno::Any aValue( + m_apChartConfigItem->getProperty( aSeriesPropName )); + if( aValue >>= m_aColorSequence ) + m_nNumberOfColors = m_aColorSequence.getLength(); + m_bNeedsUpdate = false; +} + +// ____ XColorScheme ____ +::sal_Int32 SAL_CALL ConfigColorScheme::getColorByIndex( ::sal_Int32 nIndex ) + throw (uno::RuntimeException) +{ + if( m_bNeedsUpdate ) + retrieveConfigColors(); + + if( m_nNumberOfColors > 0 ) + return static_cast< sal_Int32 >( m_aColorSequence[ nIndex % m_nNumberOfColors ] ); + + // fall-back: hard-coded standard colors + static sal_Int32 nDefaultColors[] = { + 0x9999ff, 0x993366, 0xffffcc, + 0xccffff, 0x660066, 0xff8080, + 0x0066cc, 0xccccff, 0x000080, + 0xff00ff, 0x00ffff, 0xffff00 + }; + + static const sal_Int32 nMaxDefaultColors = sizeof( nDefaultColors ) / sizeof( sal_Int32 ); + return nDefaultColors[ nIndex % nMaxDefaultColors ]; +} + +void ConfigColorScheme::notify( const OUString & rPropertyName ) +{ + if( rPropertyName.equals( aSeriesPropName )) + m_bNeedsUpdate = true; +} + +// ================================================================================ + +Sequence< OUString > ConfigColorScheme::getSupportedServiceNames_Static() +{ + Sequence< OUString > aServices( 1 ); + aServices[ 0 ] = C2U( "com.sun.star.chart2.ColorScheme" ); + return aServices; +} + +// implement XServiceInfo methods basing upon getSupportedServiceNames_Static +APPHELPER_XSERVICEINFO_IMPL( ConfigColorScheme, + C2U( "com.sun.star.comp.chart2.ConfigDefaultColorScheme" )) + +// ================================================================================ + +} // namespace chart diff --git a/chart2/source/tools/ControllerLockGuard.cxx b/chart2/source/tools/ControllerLockGuard.cxx new file mode 100644 index 000000000000..4ef430c5e483 --- /dev/null +++ b/chart2/source/tools/ControllerLockGuard.cxx @@ -0,0 +1,89 @@ +/************************************************************************* + * + * 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 "ControllerLockGuard.hxx" + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::rtl::OUString; + +namespace chart +{ + +ControllerLockGuard::ControllerLockGuard( const Reference< frame::XModel > & xModel ) : + m_xModel( xModel ) +{ + if( m_xModel.is()) + m_xModel->lockControllers(); +} + +ControllerLockGuard::~ControllerLockGuard() +{ + if( m_xModel.is()) + m_xModel->unlockControllers(); +} + +// ================================================================================ + +ControllerLockHelper::ControllerLockHelper( const Reference< frame::XModel > & xModel ) : + m_xModel( xModel ) +{} + +ControllerLockHelper::~ControllerLockHelper() +{} + +void ControllerLockHelper::lockControllers() +{ + if( m_xModel.is()) + m_xModel->lockControllers(); +} + +void ControllerLockHelper::unlockControllers() +{ + if( m_xModel.is()) + m_xModel->unlockControllers(); +} + +// ================================================================================ + +ControllerLockHelperGuard::ControllerLockHelperGuard( ControllerLockHelper & rHelper ) : + m_rHelper( rHelper ) +{ + m_rHelper.lockControllers(); +} + +ControllerLockHelperGuard::~ControllerLockHelperGuard() +{ + m_rHelper.unlockControllers(); +} + +} // namespace chart diff --git a/chart2/source/tools/DataSeriesHelper.cxx b/chart2/source/tools/DataSeriesHelper.cxx new file mode 100644 index 000000000000..acff332d4229 --- /dev/null +++ b/chart2/source/tools/DataSeriesHelper.cxx @@ -0,0 +1,918 @@ +/************************************************************************* + * + * 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 "DataSeriesHelper.hxx" +#include "DiagramHelper.hxx" +#include "DataSource.hxx" +#include "macros.hxx" +#include "ContainerHelper.hxx" +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/chart2/DataPointLabel.hpp> +#include <com/sun/star/chart2/data/XTextualDataSequence.hpp> +#include <com/sun/star/chart2/StackingDirection.hpp> +#include <com/sun/star/chart2/data/LabelOrigin.hpp> +#include <com/sun/star/chart2/AxisType.hpp> +#include <com/sun/star/chart2/SymbolStyle.hpp> +#include <com/sun/star/chart2/Symbol.hpp> +#include <com/sun/star/drawing/LineStyle.hpp> + + +#include <com/sun/star/chart2/XCoordinateSystemContainer.hpp> +#include <com/sun/star/chart2/XChartTypeContainer.hpp> +#include <com/sun/star/chart2/XDataSeriesContainer.hpp> +#include <rtl/ustrbuf.hxx> + +#include <functional> +#include <algorithm> +#include <iterator> +#include <vector> +#include <set> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::rtl::OUString; +using ::rtl::OUStringBuffer; + +// ---------------------------------------- +namespace +{ + +class lcl_MatchesRole : public ::std::unary_function< Reference< chart2::data::XLabeledDataSequence >, bool > +{ +public: + explicit lcl_MatchesRole( const OUString & aRole, bool bMatchPrefix ) : + m_aRole( aRole ), + m_bMatchPrefix( bMatchPrefix ) + {} + + bool operator () ( const Reference< chart2::data::XLabeledDataSequence > & xSeq ) const + { + if(!xSeq.is()) + return false; + Reference< beans::XPropertySet > xProp( xSeq->getValues(), uno::UNO_QUERY ); + OUString aRole; + + if( m_bMatchPrefix ) + return ( xProp.is() && + (xProp->getPropertyValue( + OUString( RTL_CONSTASCII_USTRINGPARAM( "Role" )) ) >>= aRole ) && + aRole.match( m_aRole )); + + return ( xProp.is() && + (xProp->getPropertyValue( + OUString( RTL_CONSTASCII_USTRINGPARAM( "Role" )) ) >>= aRole ) && + m_aRole.equals( aRole )); + } + +private: + OUString m_aRole; + bool m_bMatchPrefix; +}; + +Reference< chart2::data::XLabeledDataSequence > lcl_findLSequenceWithOnlyLabel( + const Reference< chart2::data::XDataSource > & xDataSource ) +{ + Reference< chart2::data::XLabeledDataSequence > xResult; + Sequence< Reference< chart2::data::XLabeledDataSequence > > aSequences( xDataSource->getDataSequences()); + + for( sal_Int32 i=0; i<aSequences.getLength(); ++i ) + { + OSL_ENSURE( aSequences[i].is(), "empty LabeledDataSequence" ); + // no values are set but a label exists + if( aSequences[i].is() && + ( ! aSequences[i]->getValues().is() && + aSequences[i]->getLabel().is())) + { + xResult.set( aSequences[i] ); + break; + } + } + + return xResult; +} + +void lcl_getCooSysAndChartTypeOfSeries( + const Reference< chart2::XDataSeries > & xSeries, + const Reference< chart2::XDiagram > & xDiagram, + Reference< chart2::XCoordinateSystem > & xOutCooSys, + Reference< chart2::XChartType > & xOutChartType ) +{ + Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xDiagram, uno::UNO_QUERY ); + if( xCooSysCnt.is()) + { + Sequence< Reference< chart2::XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems()); + for( sal_Int32 nCooSysIdx=0; nCooSysIdx<aCooSysSeq.getLength(); ++nCooSysIdx ) + { + Reference< chart2::XChartTypeContainer > xCTCnt( aCooSysSeq[nCooSysIdx], uno::UNO_QUERY_THROW ); + Sequence< Reference< chart2::XChartType > > aChartTypes( xCTCnt->getChartTypes()); + for( sal_Int32 nCTIdx=0; nCTIdx<aChartTypes.getLength(); ++nCTIdx ) + { + Reference< chart2::XDataSeriesContainer > xSeriesCnt( aChartTypes[nCTIdx], uno::UNO_QUERY ); + if( xSeriesCnt.is()) + { + Sequence< Reference< chart2::XDataSeries > > aSeries( xSeriesCnt->getDataSeries()); + for( sal_Int32 nSeriesIdx=0; nSeriesIdx<aSeries.getLength(); ++nSeriesIdx ) + { + if( aSeries[nSeriesIdx] == xSeries ) + { + xOutCooSys.set( aCooSysSeq[nCooSysIdx] ); + xOutChartType.set( aChartTypes[nCTIdx] ); + } + } + } + } + } + } +} + +void lcl_insertOrDeleteDataLabelsToSeriesAndAllPoints( const Reference< chart2::XDataSeries >& xSeries, bool bInsert ) +{ + try + { + Reference< beans::XPropertySet > xSeriesProperties( xSeries, uno::UNO_QUERY ); + if( xSeriesProperties.is() ) + { + DataPointLabel aLabelAtSeries; + xSeriesProperties->getPropertyValue( C2U( "Label" ) ) >>= aLabelAtSeries; + aLabelAtSeries.ShowNumber = bInsert; + if( !bInsert ) + { + aLabelAtSeries.ShowNumberInPercent = false; + aLabelAtSeries.ShowCategoryName = false; + } + xSeriesProperties->setPropertyValue( C2U( "Label" ), uno::makeAny( aLabelAtSeries ) ); + uno::Sequence< sal_Int32 > aAttributedDataPointIndexList; + if( xSeriesProperties->getPropertyValue( C2U( "AttributedDataPoints" ) ) >>= aAttributedDataPointIndexList ) + { + for(sal_Int32 nN=aAttributedDataPointIndexList.getLength();nN--;) + { + Reference< beans::XPropertySet > xPointProp( xSeries->getDataPointByIndex(aAttributedDataPointIndexList[nN]) ); + if( xPointProp.is() ) + { + DataPointLabel aLabel; + xPointProp->getPropertyValue( C2U( "Label" ) ) >>= aLabel; + aLabel.ShowNumber = bInsert; + if( !bInsert ) + { + aLabel.ShowNumberInPercent = false; + aLabel.ShowCategoryName = false; + } + xPointProp->setPropertyValue( C2U( "Label" ), uno::makeAny( aLabel ) ); + } + } + } + } + } + catch( uno::Exception &e) + { + ASSERT_EXCEPTION( e ); + } +} + +} // anonymous namespace +// ---------------------------------------- + +namespace chart +{ + +namespace DataSeriesHelper +{ + +OUString GetRole( const uno::Reference< chart2::data::XLabeledDataSequence >& xLabeledDataSequence ) +{ + OUString aRet; + if( xLabeledDataSequence.is() ) + { + Reference< beans::XPropertySet > xProp( xLabeledDataSequence->getValues(), uno::UNO_QUERY ); + if( xProp.is() ) + xProp->getPropertyValue( C2U("Role") ) >>= aRet; + } + return aRet; +} + +Reference< chart2::data::XLabeledDataSequence > + getDataSequenceByRole( + const Reference< chart2::data::XDataSource > & xSource, OUString aRole, + bool bMatchPrefix /* = false */ ) +{ + Reference< chart2::data::XLabeledDataSequence > aNoResult; + if( ! xSource.is()) + return aNoResult; + Sequence< Reference< chart2::data::XLabeledDataSequence > > aLabeledSeq( xSource->getDataSequences()); + + const Reference< chart2::data::XLabeledDataSequence > * pBegin = aLabeledSeq.getConstArray(); + const Reference< chart2::data::XLabeledDataSequence > * pEnd = pBegin + aLabeledSeq.getLength(); + const Reference< chart2::data::XLabeledDataSequence > * pMatch = + ::std::find_if( pBegin, pEnd, lcl_MatchesRole( aRole, bMatchPrefix )); + + if( pMatch != pEnd ) + return *pMatch; + + return aNoResult; +} + +::std::vector< Reference< chart2::data::XLabeledDataSequence > > + getAllDataSequencesByRole( const Sequence< Reference< chart2::data::XLabeledDataSequence > > & aDataSequences, + OUString aRole, bool bMatchPrefix /* = false */ ) +{ + ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aResultVec; + ::std::remove_copy_if( aDataSequences.getConstArray(), aDataSequences.getConstArray() + aDataSequences.getLength(), + ::std::back_inserter( aResultVec ), + ::std::not1( lcl_MatchesRole( aRole, bMatchPrefix ))); + return aResultVec; +} + +Reference< chart2::data::XDataSource > + getDataSource( const Sequence< Reference< chart2::XDataSeries > > & aSeries ) +{ + ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aSeqVec; + + for( sal_Int32 i = 0; i < aSeries.getLength(); ++i ) + { + Reference< chart2::data::XDataSource > xSource( aSeries[ i ], uno::UNO_QUERY ); + if( xSource.is()) + { + Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeq( xSource->getDataSequences()); + ::std::copy( aSeq.getConstArray(), aSeq.getConstArray() + aSeq.getLength(), + ::std::back_inserter( aSeqVec )); + } + } + + return Reference< chart2::data::XDataSource >( + new DataSource( ContainerHelper::ContainerToSequence( aSeqVec ))); +} + +namespace +{ +OUString lcl_getDataSequenceLabel( const Reference< chart2::data::XDataSequence > & xSequence ) +{ + OUString aResult; + + Reference< chart2::data::XTextualDataSequence > xTextSeq( xSequence, uno::UNO_QUERY ); + if( xTextSeq.is()) + { + Sequence< OUString > aSeq( xTextSeq->getTextualData()); + + const sal_Int32 nMax = aSeq.getLength() - 1; + OUString aVal; + OUStringBuffer aBuf; + + for( sal_Int32 i = 0; i <= nMax; ++i ) + { + aBuf.append( aSeq[i] ); + if( i < nMax ) + aBuf.append( sal_Unicode( ' ' )); + } + aResult = aBuf.makeStringAndClear(); + } + else if( xSequence.is()) + { + Sequence< uno::Any > aSeq( xSequence->getData()); + + const sal_Int32 nMax = aSeq.getLength() - 1; + OUString aVal; + OUStringBuffer aBuf; + double fNum = 0; + + for( sal_Int32 i = 0; i <= nMax; ++i ) + { + if( aSeq[i] >>= aVal ) + { + aBuf.append( aVal ); + if( i < nMax ) + aBuf.append( sal_Unicode( ' ' )); + } + else if( aSeq[ i ] >>= fNum ) + { + aBuf.append( fNum ); + if( i < nMax ) + aBuf.append( sal_Unicode( ' ' )); + } + } + aResult = aBuf.makeStringAndClear(); + } + + return aResult; +} +} + +OUString getLabelForLabeledDataSequence( + const Reference< chart2::data::XLabeledDataSequence > & xLabeledSeq ) +{ + OUString aResult; + if( xLabeledSeq.is()) + { + Reference< chart2::data::XDataSequence > xSeq( xLabeledSeq->getLabel()); + if( xSeq.is() ) + aResult = lcl_getDataSequenceLabel( xSeq ); + if( !xSeq.is() || !aResult.getLength() ) + { + // no label set or label content is empty -> use auto-generated one + Reference< chart2::data::XDataSequence > xValueSeq( xLabeledSeq->getValues() ); + if( xValueSeq.is() ) + { + Sequence< OUString > aLabels( xValueSeq->generateLabel( + chart2::data::LabelOrigin_SHORT_SIDE ) ); + // no labels returned is interpreted as: auto-generation not + // supported by sequence + if( aLabels.getLength() ) + aResult=aLabels[0]; + else + { + //todo?: maybe use the index of the series as name + //but as the index may change it would be better to have such a name persistent + //what is not possible at the moment + //--> maybe use the identifier as part of the name ... + aResult = lcl_getDataSequenceLabel( xValueSeq ); + } + } + } + } + return aResult; +} + +OUString getDataSeriesLabel( + const Reference< chart2::XDataSeries > & xSeries, + const OUString & rLabelSequenceRole ) +{ + OUString aResult; + + Reference< chart2::data::XDataSource > xSource( xSeries, uno::UNO_QUERY ); + if( xSource.is()) + { + Reference< chart2::data::XLabeledDataSequence > xLabeledSeq( + ::chart::DataSeriesHelper::getDataSequenceByRole( xSource, rLabelSequenceRole )); + if( xLabeledSeq.is()) + aResult = getLabelForLabeledDataSequence( xLabeledSeq ); + else + { + // special case: labeled data series with only a label and no values may + // serve as label + xLabeledSeq.set( lcl_findLSequenceWithOnlyLabel( xSource )); + if( xLabeledSeq.is()) + { + Reference< chart2::data::XDataSequence > xSeq( xLabeledSeq->getLabel()); + if( xSeq.is()) + aResult = lcl_getDataSequenceLabel( xSeq ); + } + } + + } + + return aResult; +} + +void setStackModeAtSeries( + const Sequence< Reference< chart2::XDataSeries > > & aSeries, + const Reference< chart2::XCoordinateSystem > & xCorrespondingCoordinateSystem, + StackMode eStackMode ) +{ + if( eStackMode == StackMode_AMBIGUOUS ) + return; + + const OUString aPropName( RTL_CONSTASCII_USTRINGPARAM( "StackingDirection" )); + const uno::Any aPropValue = uno::makeAny( + ( (eStackMode == StackMode_Y_STACKED) || + (eStackMode == StackMode_Y_STACKED_PERCENT) ) + ? chart2::StackingDirection_Y_STACKING + : (eStackMode == StackMode_Z_STACKED ) + ? chart2::StackingDirection_Z_STACKING + : chart2::StackingDirection_NO_STACKING ); + + std::set< sal_Int32 > aAxisIndexSet; + for( sal_Int32 i=0; i<aSeries.getLength(); ++i ) + { + try + { + Reference< beans::XPropertySet > xProp( aSeries[i], uno::UNO_QUERY ); + if( xProp.is() ) + { + xProp->setPropertyValue( aPropName, aPropValue ); + + sal_Int32 nAxisIndex; + xProp->getPropertyValue( C2U("AttachedAxisIndex") ) >>= nAxisIndex; + aAxisIndexSet.insert(nAxisIndex); + } + } + catch( uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + } + + if( xCorrespondingCoordinateSystem.is() && + 1 < xCorrespondingCoordinateSystem->getDimension() ) + { + sal_Int32 nAxisIndexCount = aAxisIndexSet.size(); + if( !nAxisIndexCount ) + { + aAxisIndexSet.insert(0); + nAxisIndexCount = aAxisIndexSet.size(); + } + + for( ::std::set< sal_Int32 >::const_iterator aIt = aAxisIndexSet.begin(); + aIt != aAxisIndexSet.end(); ++aIt ) + { + sal_Int32 nAxisIndex = *aIt; + Reference< chart2::XAxis > xAxis( + xCorrespondingCoordinateSystem->getAxisByDimension( 1, nAxisIndex )); + if( xAxis.is()) + { + sal_Bool bPercent = (eStackMode == StackMode_Y_STACKED_PERCENT); + chart2::ScaleData aScaleData = xAxis->getScaleData(); + + if( bPercent != (aScaleData.AxisType==chart2::AxisType::PERCENT) ) + { + if( bPercent ) + aScaleData.AxisType = chart2::AxisType::PERCENT; + else + aScaleData.AxisType = chart2::AxisType::REALNUMBER; + xAxis->setScaleData( aScaleData ); + } + } + } + } +} + +sal_Int32 getAttachedAxisIndex( const Reference< chart2::XDataSeries > & xSeries ) +{ + sal_Int32 nRet = 0; + try + { + Reference< beans::XPropertySet > xProp( xSeries, uno::UNO_QUERY ); + if( xProp.is() ) + { + xProp->getPropertyValue( C2U("AttachedAxisIndex") ) >>= nRet; + } + } + catch( uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + return nRet; +} + +sal_Int32 getNumberFormatKeyFromAxis( + const Reference< chart2::XDataSeries > & xSeries, + const Reference< chart2::XCoordinateSystem > & xCorrespondingCoordinateSystem, + sal_Int32 nDimensionIndex, + sal_Int32 nAxisIndex /* = -1 */ ) +{ + sal_Int32 nResult = 0; + if( nAxisIndex == -1 ) + nAxisIndex = getAttachedAxisIndex( xSeries ); + try + { + Reference< beans::XPropertySet > xAxisProp( + xCorrespondingCoordinateSystem->getAxisByDimension( nDimensionIndex, nAxisIndex ), uno::UNO_QUERY ); + if( xAxisProp.is()) + xAxisProp->getPropertyValue( C2U("NumberFormat")) >>= nResult; + } + catch( const uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + + return nResult; +} + +Reference< chart2::XCoordinateSystem > getCoordinateSystemOfSeries( + const Reference< chart2::XDataSeries > & xSeries, + const Reference< chart2::XDiagram > & xDiagram ) +{ + Reference< chart2::XCoordinateSystem > xResult; + Reference< chart2::XChartType > xDummy; + lcl_getCooSysAndChartTypeOfSeries( xSeries, xDiagram, xResult, xDummy ); + + return xResult; +} + +Reference< chart2::XChartType > getChartTypeOfSeries( + const Reference< chart2::XDataSeries > & xSeries, + const Reference< chart2::XDiagram > & xDiagram ) +{ + Reference< chart2::XChartType > xResult; + Reference< chart2::XCoordinateSystem > xDummy; + lcl_getCooSysAndChartTypeOfSeries( xSeries, xDiagram, xDummy, xResult ); + + return xResult; +} + +void deleteSeries( + const Reference< chart2::XDataSeries > & xSeries, + const Reference< chart2::XChartType > & xChartType ) +{ + try + { + Reference< chart2::XDataSeriesContainer > xSeriesCnt( xChartType, uno::UNO_QUERY_THROW ); + ::std::vector< Reference< chart2::XDataSeries > > aSeries( + ContainerHelper::SequenceToVector( xSeriesCnt->getDataSeries())); + ::std::vector< Reference< chart2::XDataSeries > >::iterator aIt = + ::std::find( aSeries.begin(), aSeries.end(), xSeries ); + if( aIt != aSeries.end()) + { + aSeries.erase( aIt ); + xSeriesCnt->setDataSeries( ContainerHelper::ContainerToSequence( aSeries )); + } + } + catch( uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } +} + +void switchSymbolsOnOrOff( const Reference< beans::XPropertySet > & xSeriesProperties, + bool bSymbolsOn, sal_Int32 nSeriesIndex ) +{ + if( !xSeriesProperties.is() ) + return; + + chart2::Symbol aSymbProp; + if( (xSeriesProperties->getPropertyValue( C2U( "Symbol" )) >>= aSymbProp ) ) + { + if( !bSymbolsOn ) + aSymbProp.Style = chart2::SymbolStyle_NONE; + else if( aSymbProp.Style == chart2::SymbolStyle_NONE ) + { + aSymbProp.Style = chart2::SymbolStyle_STANDARD; + aSymbProp.StandardSymbol = nSeriesIndex; + } + xSeriesProperties->setPropertyValue( C2U( "Symbol" ), uno::makeAny( aSymbProp )); + } + //todo: check attributed data points +} + +void switchLinesOnOrOff( const Reference< beans::XPropertySet > & xSeriesProperties, bool bLinesOn ) +{ + if( !xSeriesProperties.is() ) + return; + + if( bLinesOn ) + { + // keep line-styles that are not NONE + drawing::LineStyle eLineStyle; + if( (xSeriesProperties->getPropertyValue( C2U( "LineStyle" )) >>= eLineStyle ) && + eLineStyle == drawing::LineStyle_NONE ) + { + xSeriesProperties->setPropertyValue( C2U( "LineStyle" ), uno::makeAny( drawing::LineStyle_SOLID ) ); + } + } + else + xSeriesProperties->setPropertyValue( C2U( "LineStyle" ), uno::makeAny( drawing::LineStyle_NONE ) ); +} + +void makeLinesThickOrThin( const Reference< beans::XPropertySet > & xSeriesProperties, bool bThick ) +{ + if( !xSeriesProperties.is() ) + return; + + sal_Int32 nNewValue = bThick ? 80 : 0; + sal_Int32 nOldValue = 0; + if( (xSeriesProperties->getPropertyValue( C2U( "LineWidth" )) >>= nOldValue ) && + nOldValue != nNewValue ) + { + if( !(bThick && nOldValue>0)) + xSeriesProperties->setPropertyValue( C2U( "LineWidth" ), uno::makeAny( nNewValue ) ); + } +} + +void setPropertyAlsoToAllAttributedDataPoints( const Reference< chart2::XDataSeries >& xSeries, + const OUString& rPropertyName, const uno::Any& rPropertyValue ) +{ + Reference< beans::XPropertySet > xSeriesProperties( xSeries, uno::UNO_QUERY ); + if( !xSeriesProperties.is() ) + return; + + xSeriesProperties->setPropertyValue( rPropertyName, rPropertyValue ); + uno::Sequence< sal_Int32 > aAttributedDataPointIndexList; + if( xSeriesProperties->getPropertyValue( C2U( "AttributedDataPoints" ) ) >>= aAttributedDataPointIndexList ) + { + for(sal_Int32 nN=aAttributedDataPointIndexList.getLength();nN--;) + { + Reference< beans::XPropertySet > xPointProp( xSeries->getDataPointByIndex(aAttributedDataPointIndexList[nN]) ); + if(!xPointProp.is()) + continue; + xPointProp->setPropertyValue( rPropertyName, rPropertyValue ); + } + } +} + +bool hasAttributedDataPointDifferentValue( const Reference< chart2::XDataSeries >& xSeries, + const OUString& rPropertyName, const uno::Any& rPropertyValue ) +{ + Reference< beans::XPropertySet > xSeriesProperties( xSeries, uno::UNO_QUERY ); + if( !xSeriesProperties.is() ) + return false; + + uno::Sequence< sal_Int32 > aAttributedDataPointIndexList; + if( xSeriesProperties->getPropertyValue( C2U( "AttributedDataPoints" ) ) >>= aAttributedDataPointIndexList ) + { + for(sal_Int32 nN=aAttributedDataPointIndexList.getLength();nN--;) + { + Reference< beans::XPropertySet > xPointProp( xSeries->getDataPointByIndex(aAttributedDataPointIndexList[nN]) ); + if(!xPointProp.is()) + continue; + uno::Any aPointValue( xPointProp->getPropertyValue( rPropertyName ) ); + if( !( rPropertyValue==aPointValue ) ) + return true; + } + } + return false; +} + +bool areAllSeriesAttachedToSameAxis( const uno::Reference< chart2::XChartType >& xChartType, sal_Int32 & rOutAxisIndex ) +{ + try + { + uno::Reference< chart2::XDataSeriesContainer > xDataSeriesContainer( xChartType, uno::UNO_QUERY_THROW ); + uno::Sequence< uno::Reference< chart2::XDataSeries > > aSeriesSeq( xDataSeriesContainer->getDataSeries()); + + const sal_Int32 nSeriesCount( aSeriesSeq.getLength()); + // AxisIndex can only be 0 or 1 + sal_Int32 nSeriesAtFirstAxis = 0; + sal_Int32 nSeriesAtSecondAxis = 0; + + for( sal_Int32 nI = 0; nI < nSeriesCount; ++nI ) + { + uno::Reference< chart2::XDataSeries > xSeries( aSeriesSeq[nI], uno::UNO_QUERY ); + sal_Int32 nAxisIndex = DataSeriesHelper::getAttachedAxisIndex( xSeries ); + if( nAxisIndex == 0 ) + ++nSeriesAtFirstAxis; + else if( nAxisIndex == 1 ) + ++nSeriesAtSecondAxis; + } + OSL_ENSURE( nSeriesAtFirstAxis + nSeriesAtSecondAxis == nSeriesCount, "Invalid axis index found" ); + + if( nSeriesAtFirstAxis == nSeriesCount ) + rOutAxisIndex = 0; + else if( nSeriesAtSecondAxis == nSeriesCount ) + rOutAxisIndex = 1; + + return ( nSeriesAtFirstAxis == nSeriesCount || + nSeriesAtSecondAxis == nSeriesCount ); + } + catch( const uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + return false; + } +} + +namespace +{ + +bool lcl_SequenceHasUnhiddenData( const uno::Reference< chart2::data::XDataSequence >& xDataSequence ) +{ + if( !xDataSequence.is() ) + return false; + uno::Reference< beans::XPropertySet > xProp( xDataSequence, uno::UNO_QUERY ); + if( xProp.is() ) + { + uno::Sequence< sal_Int32 > aHiddenValues; + try + { + xProp->getPropertyValue( C2U( "HiddenValues" ) ) >>= aHiddenValues; + if( !aHiddenValues.getLength() ) + return true; + } + catch( uno::Exception& e ) + { + (void)e; // avoid warning + return true; + } + } + if( xDataSequence->getData().getLength() ) + return true; + return false; +} + +} + +bool hasUnhiddenData( const uno::Reference< chart2::XDataSeries >& xSeries ) +{ + uno::Reference< chart2::data::XDataSource > xDataSource = + uno::Reference< chart2::data::XDataSource >( xSeries, uno::UNO_QUERY ); + + uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aDataSequences = xDataSource->getDataSequences(); + + for(sal_Int32 nN = aDataSequences.getLength();nN--;) + { + if( !aDataSequences[nN].is() ) + continue; + if( lcl_SequenceHasUnhiddenData( aDataSequences[nN]->getValues() ) ) + return true; + if( lcl_SequenceHasUnhiddenData( aDataSequences[nN]->getLabel() ) ) + return true; + } + return false; +} + +struct lcl_LessIndex +{ + inline bool operator() ( const sal_Int32& first, const sal_Int32& second ) + { + return ( first < second ); + } +}; + +sal_Int32 translateIndexFromHiddenToFullSequence( sal_Int32 nIndex, const Reference< chart2::data::XDataSequence >& xDataSequence, bool bTranslate ) +{ + if( !bTranslate ) + return nIndex; + + try + { + uno::Reference<beans::XPropertySet> xProp( xDataSequence, uno::UNO_QUERY ); + if( xProp.is()) + { + Sequence<sal_Int32> aHiddenIndicesSeq; + xProp->getPropertyValue( C2U("HiddenValues") ) >>= aHiddenIndicesSeq; + if( aHiddenIndicesSeq.getLength() ) + { + ::std::vector< sal_Int32 > aHiddenIndices( ContainerHelper::SequenceToVector( aHiddenIndicesSeq ) ); + ::std::sort( aHiddenIndices.begin(), aHiddenIndices.end(), lcl_LessIndex() ); + + sal_Int32 nHiddenCount = static_cast<sal_Int32>(aHiddenIndices.size()); + for( sal_Int32 nN = 0; nN < nHiddenCount; ++nN) + { + if( aHiddenIndices[nN] <= nIndex ) + nIndex += 1; + else + break; + } + } + } + } + catch (const beans::UnknownPropertyException&) + { + } + return nIndex; +} + +bool hasDataLabelsAtSeries( const Reference< chart2::XDataSeries >& xSeries ) +{ + bool bRet = false; + try + { + Reference< beans::XPropertySet > xProp( xSeries, uno::UNO_QUERY ); + if( xProp.is() ) + { + DataPointLabel aLabel; + if( (xProp->getPropertyValue( C2U( "Label" ) ) >>= aLabel) ) + bRet = aLabel.ShowNumber || aLabel.ShowNumberInPercent || aLabel.ShowCategoryName; + } + } + catch( uno::Exception &e) + { + ASSERT_EXCEPTION( e ); + } + return bRet; +} + +bool hasDataLabelsAtPoints( const Reference< chart2::XDataSeries >& xSeries ) +{ + bool bRet = false; + try + { + Reference< beans::XPropertySet > xSeriesProperties( xSeries, uno::UNO_QUERY ); + if( xSeriesProperties.is() ) + { + uno::Sequence< sal_Int32 > aAttributedDataPointIndexList; + if( xSeriesProperties->getPropertyValue( C2U( "AttributedDataPoints" ) ) >>= aAttributedDataPointIndexList ) + { + for(sal_Int32 nN=aAttributedDataPointIndexList.getLength();nN--;) + { + Reference< beans::XPropertySet > xPointProp( xSeries->getDataPointByIndex(aAttributedDataPointIndexList[nN]) ); + if( xPointProp.is() ) + { + DataPointLabel aLabel; + if( (xPointProp->getPropertyValue( C2U( "Label" ) ) >>= aLabel) ) + bRet = aLabel.ShowNumber || aLabel.ShowNumberInPercent || aLabel.ShowCategoryName; + if( bRet ) + break; + } + } + } + } + } + catch( uno::Exception &e) + { + ASSERT_EXCEPTION( e ); + } + return bRet; +} + +bool hasDataLabelAtPoint( const Reference< chart2::XDataSeries >& xSeries, sal_Int32 nPointIndex ) +{ + bool bRet = false; + try + { + Reference< beans::XPropertySet > xProp; + Reference< beans::XPropertySet > xSeriesProperties( xSeries, uno::UNO_QUERY ); + if( xSeriesProperties.is() ) + { + uno::Sequence< sal_Int32 > aAttributedDataPointIndexList; + if( xSeriesProperties->getPropertyValue( C2U( "AttributedDataPoints" ) ) >>= aAttributedDataPointIndexList ) + { + ::std::vector< sal_Int32 > aIndices( ContainerHelper::SequenceToVector( aAttributedDataPointIndexList ) ); + ::std::vector< sal_Int32 >::iterator aIt = ::std::find( aIndices.begin(), aIndices.end(), nPointIndex ); + if( aIt != aIndices.end()) + xProp = xSeries->getDataPointByIndex(nPointIndex); + else + xProp = xSeriesProperties; + } + if( xProp.is() ) + { + DataPointLabel aLabel; + if( (xProp->getPropertyValue( C2U( "Label" ) ) >>= aLabel) ) + bRet = aLabel.ShowNumber || aLabel.ShowNumberInPercent || aLabel.ShowCategoryName; + } + } + } + catch( uno::Exception &e) + { + ASSERT_EXCEPTION( e ); + } + return bRet; +} + +void insertDataLabelsToSeriesAndAllPoints( const Reference< chart2::XDataSeries >& xSeries ) +{ + lcl_insertOrDeleteDataLabelsToSeriesAndAllPoints( xSeries, true /*bInsert*/ ); +} + +void deleteDataLabelsFromSeriesAndAllPoints( const Reference< chart2::XDataSeries >& xSeries ) +{ + lcl_insertOrDeleteDataLabelsToSeriesAndAllPoints( xSeries, false /*bInsert*/ ); +} + + +void insertDataLabelToPoint( const Reference< beans::XPropertySet >& xPointProp ) +{ + try + { + if( xPointProp.is() ) + { + DataPointLabel aLabel; + xPointProp->getPropertyValue( C2U( "Label" ) ) >>= aLabel; + aLabel.ShowNumber = true; + xPointProp->setPropertyValue( C2U( "Label" ), uno::makeAny( aLabel ) ); + } + } + catch( uno::Exception &e) + { + ASSERT_EXCEPTION( e ); + } +} + +void deleteDataLabelsFromPoint( const Reference< beans::XPropertySet >& xPointProp ) +{ + try + { + if( xPointProp.is() ) + { + DataPointLabel aLabel; + xPointProp->getPropertyValue( C2U( "Label" ) ) >>= aLabel; + aLabel.ShowNumber = false; + aLabel.ShowNumberInPercent = false; + aLabel.ShowCategoryName = false; + xPointProp->setPropertyValue( C2U( "Label" ), uno::makeAny( aLabel ) ); + } + } + catch( uno::Exception &e) + { + ASSERT_EXCEPTION( e ); + } +} + +} // namespace DataSeriesHelper +} // namespace chart diff --git a/chart2/source/tools/DataSource.cxx b/chart2/source/tools/DataSource.cxx new file mode 100644 index 000000000000..edbf4dfacfeb --- /dev/null +++ b/chart2/source/tools/DataSource.cxx @@ -0,0 +1,91 @@ +/************************************************************************* + * + * 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 "DataSource.hxx" +#include "LabeledDataSequence.hxx" + +using ::rtl::OUString; +using ::osl::MutexGuard; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::RuntimeException; +using ::com::sun::star::uno::Any; + +using namespace ::com::sun::star; + +namespace +{ +static const ::rtl::OUString lcl_aServiceName( + RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.chart.DataSource" )); +} // anonymous namespace + +namespace chart +{ + +DataSource::DataSource( + const Reference< uno::XComponentContext > & /*xContext*/ ) +{} + +DataSource::DataSource( + const Sequence< Reference< chart2::data::XLabeledDataSequence > > & rSequences ) : + m_aDataSeq( rSequences ) +{} + +DataSource::~DataSource() +{} + +// ____ XDataSource ____ +Sequence< Reference< chart2::data::XLabeledDataSequence > > SAL_CALL DataSource::getDataSequences() + throw (uno::RuntimeException) +{ + return m_aDataSeq; +} + +// ____ XDataSink ____ +void SAL_CALL DataSource::setData( const Sequence< Reference< chart2::data::XLabeledDataSequence > >& aData ) + throw (uno::RuntimeException) +{ + m_aDataSeq = aData; +} + +// ================================================================================ + +Sequence< OUString > DataSource::getSupportedServiceNames_Static() +{ + Sequence< OUString > aServices( 1 ); + aServices[ 0 ] = OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.chart2.data.DataSource" )); + return aServices; +} + +// ================================================================================ + +APPHELPER_XSERVICEINFO_IMPL( DataSource, lcl_aServiceName ); + +} // namespace chart diff --git a/chart2/source/tools/DataSourceHelper.cxx b/chart2/source/tools/DataSourceHelper.cxx new file mode 100644 index 000000000000..0cc6ef4a4315 --- /dev/null +++ b/chart2/source/tools/DataSourceHelper.cxx @@ -0,0 +1,552 @@ +/************************************************************************* + * + * 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 "DataSourceHelper.hxx" +#include "macros.hxx" +#include "ChartModelHelper.hxx" +#include "DiagramHelper.hxx" +#include "DataSeriesHelper.hxx" +#include "DataSource.hxx" +#include "ContainerHelper.hxx" +#include "ControllerLockGuard.hxx" +#include "PropertyHelper.hxx" +#include "CachedDataSequence.hxx" +#include "LabeledDataSequence.hxx" + +#include <com/sun/star/chart2/XChartDocument.hpp> +#include <com/sun/star/chart2/data/XDataSource.hpp> +#include <com/sun/star/chart2/data/XLabeledDataSequence.hpp> + +#include <com/sun/star/chart/ChartDataRowSource.hpp> +#include <com/sun/star/chart/ErrorBarStyle.hpp> + +//............................................................................. +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; +using ::rtl::OUString; + +namespace +{ +void lcl_addRanges( ::std::vector< ::rtl::OUString > & rOutResult, + const uno::Reference< data::XLabeledDataSequence > & xLabeledSeq ) +{ + if( ! xLabeledSeq.is()) + return; + uno::Reference< data::XDataSequence > xSeq( xLabeledSeq->getLabel()); + if( xSeq.is()) + rOutResult.push_back( xSeq->getSourceRangeRepresentation()); + xSeq.set( xLabeledSeq->getValues()); + if( xSeq.is()) + rOutResult.push_back( xSeq->getSourceRangeRepresentation()); +} + +void lcl_addDataSourceRanges( + ::std::vector< ::rtl::OUString > & rOutResult, + const uno::Reference< data::XDataSource > & xDataSource ) +{ + if( xDataSource.is() ) + { + uno::Sequence< uno::Reference< data::XLabeledDataSequence > > aDataSequences( xDataSource->getDataSequences() ); + for( sal_Int32 i=0; i<aDataSequences.getLength(); ++i) + lcl_addRanges( rOutResult, aDataSequences[i] ); + } +} + +void lcl_addErrorBarRanges( + ::std::vector< ::rtl::OUString > & rOutResult, + const uno::Reference< XDataSeries > & xDataSeries ) +{ + uno::Reference< beans::XPropertySet > xSeriesProp( xDataSeries, uno::UNO_QUERY ); + if( !xSeriesProp.is()) + return; + + try + { + uno::Reference< beans::XPropertySet > xErrorBarProp; + if( ( xSeriesProp->getPropertyValue( C2U("ErrorBarY")) >>= xErrorBarProp ) && + xErrorBarProp.is()) + { + sal_Int32 eStyle = ::com::sun::star::chart::ErrorBarStyle::NONE; + if( ( xErrorBarProp->getPropertyValue( C2U("ErrorBarStyle")) >>= eStyle ) && + eStyle == ::com::sun::star::chart::ErrorBarStyle::FROM_DATA ) + { + uno::Reference< data::XDataSource > xErrorBarDataSource( xErrorBarProp, uno::UNO_QUERY ); + if( xErrorBarDataSource.is() ) + lcl_addDataSourceRanges( rOutResult, xErrorBarDataSource ); + } + } + } + catch( const uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } +} + +} // anonymous namespace + +Reference< chart2::data::XDataSource > DataSourceHelper::createDataSource( + const Sequence< Reference< chart2::data::XLabeledDataSequence > >& rSequences ) +{ + return new DataSource(rSequences); +} + +Reference< chart2::data::XDataSequence > DataSourceHelper::createCachedDataSequence() +{ + return new ::chart::CachedDataSequence(); +} + +Reference< chart2::data::XDataSequence > DataSourceHelper::createCachedDataSequence( const ::rtl::OUString& rSingleText ) +{ + return new ::chart::CachedDataSequence( rSingleText ); +} + +Reference< chart2::data::XLabeledDataSequence > DataSourceHelper::createLabeledDataSequence( + const Reference< chart2::data::XDataSequence >& xValues , + const Reference< chart2::data::XDataSequence >& xLabels ) +{ + return new ::chart::LabeledDataSequence( xValues, xLabels ); +} + +Reference< chart2::data::XLabeledDataSequence > DataSourceHelper::createLabeledDataSequence( + const Reference< chart2::data::XDataSequence >& xValues ) +{ + return new ::chart::LabeledDataSequence( xValues ); +} + +Reference< chart2::data::XLabeledDataSequence > DataSourceHelper::createLabeledDataSequence( + const Reference< uno::XComponentContext >& xContext ) +{ + return new ::chart::LabeledDataSequence( xContext ); +} + +uno::Sequence< beans::PropertyValue > DataSourceHelper::createArguments( + bool bUseColumns, bool bFirstCellAsLabel, bool bHasCategories ) +{ + ::com::sun::star::chart::ChartDataRowSource eRowSource = ::com::sun::star::chart::ChartDataRowSource_ROWS; + if( bUseColumns ) + eRowSource = ::com::sun::star::chart::ChartDataRowSource_COLUMNS; + + uno::Sequence< beans::PropertyValue > aArguments(3); + aArguments[0] = beans::PropertyValue( C2U("DataRowSource") + , -1, uno::makeAny( eRowSource ) + , beans::PropertyState_DIRECT_VALUE ); + aArguments[1] = beans::PropertyValue( C2U("FirstCellAsLabel") + , -1, uno::makeAny( bFirstCellAsLabel ) + , beans::PropertyState_DIRECT_VALUE ); + aArguments[2] = beans::PropertyValue( C2U("HasCategories") + , -1, uno::makeAny( bHasCategories ) + , beans::PropertyState_DIRECT_VALUE ); + + return aArguments; +} + +uno::Sequence< beans::PropertyValue > DataSourceHelper::createArguments( + const ::rtl::OUString & rRangeRepresentation, + const uno::Sequence< sal_Int32 >& rSequenceMapping, + bool bUseColumns, bool bFirstCellAsLabel, bool bHasCategories ) +{ + uno::Sequence< beans::PropertyValue > aArguments( createArguments( bUseColumns, bFirstCellAsLabel, bHasCategories )); + aArguments.realloc( aArguments.getLength() + 1 ); + aArguments[aArguments.getLength() - 1] = + beans::PropertyValue( C2U("CellRangeRepresentation") + , -1, uno::makeAny( rRangeRepresentation ) + , beans::PropertyState_DIRECT_VALUE ); + if( rSequenceMapping.getLength() ) + { + aArguments.realloc( aArguments.getLength() + 1 ); + aArguments[aArguments.getLength() - 1] = + beans::PropertyValue( C2U("SequenceMapping") + , -1, uno::makeAny( rSequenceMapping ) + , beans::PropertyState_DIRECT_VALUE ); + } + return aArguments; +} + +void DataSourceHelper::readArguments( const uno::Sequence< beans::PropertyValue >& rArguments + , ::rtl::OUString & rRangeRepresentation, uno::Sequence< sal_Int32 >& rSequenceMapping + , bool& bUseColumns, bool& bFirstCellAsLabel, bool& bHasCategories ) +{ + const beans::PropertyValue* pArguments = rArguments.getConstArray(); + for(sal_Int32 i=0; i<rArguments.getLength(); ++i, ++pArguments) + { + const beans::PropertyValue& aProperty = *pArguments; + if( aProperty.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "DataRowSource" ) )) + { + ::com::sun::star::chart::ChartDataRowSource eRowSource; + if( aProperty.Value >>= eRowSource ) + bUseColumns = (eRowSource==::com::sun::star::chart::ChartDataRowSource_COLUMNS); + } + else if( aProperty.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "FirstCellAsLabel" ) )) + { + aProperty.Value >>= bFirstCellAsLabel; + } + else if( aProperty.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "HasCategories" ) )) + { + aProperty.Value >>= bHasCategories; + } + else if( aProperty.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "CellRangeRepresentation" ) )) + { + aProperty.Value >>= rRangeRepresentation; + } + else if( aProperty.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "SequenceMapping" ) )) + { + aProperty.Value >>= rSequenceMapping; + } + } +} + +uno::Reference< chart2::data::XDataSource > DataSourceHelper::pressUsedDataIntoRectangularFormat( + const uno::Reference< chart2::XChartDocument >& xChartDoc, bool bWithCategories ) +{ + ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aResultVector; + + //categories are always the first sequence + Reference< chart2::XDiagram > xDiagram( xChartDoc->getFirstDiagram()); + + if( bWithCategories ) + { + Reference< chart2::data::XLabeledDataSequence > xCategories( DiagramHelper::getCategoriesFromDiagram( xDiagram ) ); + if( xCategories.is() ) + aResultVector.push_back( xCategories ); + } + + ::std::vector< Reference< chart2::XDataSeries > > xSeriesVector( DiagramHelper::getDataSeriesFromDiagram( xDiagram ) ); + uno::Reference< chart2::data::XDataSource > xSeriesSource( + DataSeriesHelper::getDataSource( ContainerHelper::ContainerToSequence(xSeriesVector) ) ); + Sequence< Reference< chart2::data::XLabeledDataSequence > > aDataSeqences( xSeriesSource->getDataSequences() ); + + //the first x-values is always the next sequence //todo ... other x-values get lost for old format + Reference< chart2::data::XLabeledDataSequence > xXValues( + DataSeriesHelper::getDataSequenceByRole( xSeriesSource, C2U("values-x") ) ); + if( xXValues.is() ) + aResultVector.push_back( xXValues ); + + //add all other sequences now without x-values + for( sal_Int32 nN=0; nN<aDataSeqences.getLength(); nN++ ) + { + OUString aRole( DataSeriesHelper::GetRole( aDataSeqences[nN] ) ); + if( !aRole.equals(C2U("values-x")) ) + aResultVector.push_back( aDataSeqences[nN] ); + } + + Sequence< Reference< chart2::data::XLabeledDataSequence > > aResultSequence( aResultVector.size() ); + ::std::copy( aResultVector.begin(), aResultVector.end(), aResultSequence.getArray() ); + + return new DataSource( aResultSequence ); +} + +uno::Sequence< ::rtl::OUString > DataSourceHelper::getUsedDataRanges( + const uno::Reference< chart2::XDiagram > & xDiagram ) +{ + ::std::vector< ::rtl::OUString > aResult; + + if( xDiagram.is()) + { + uno::Reference< data::XLabeledDataSequence > xCategories( DiagramHelper::getCategoriesFromDiagram( xDiagram ) ); + if( xCategories.is() ) + lcl_addRanges( aResult, xCategories ); + + ::std::vector< uno::Reference< XDataSeries > > aSeriesVector( DiagramHelper::getDataSeriesFromDiagram( xDiagram ) ); + for( ::std::vector< uno::Reference< XDataSeries > >::const_iterator aSeriesIt( aSeriesVector.begin() ) + ; aSeriesIt != aSeriesVector.end(); ++aSeriesIt ) + { + uno::Reference< data::XDataSource > xDataSource( *aSeriesIt, uno::UNO_QUERY ); + lcl_addDataSourceRanges( aResult, xDataSource ); + lcl_addErrorBarRanges( aResult, *aSeriesIt ); + } + } + + return ContainerHelper::ContainerToSequence( aResult ); +} + +uno::Sequence< ::rtl::OUString > DataSourceHelper::getUsedDataRanges( const uno::Reference< frame::XModel > & xChartModel ) +{ + uno::Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartModel ) ); + return getUsedDataRanges( xDiagram ); +} + +uno::Reference< chart2::data::XDataSource > DataSourceHelper::getUsedData( + const uno::Reference< chart2::XChartDocument >& xChartDoc ) +{ + return pressUsedDataIntoRectangularFormat( xChartDoc ); +} + +uno::Reference< chart2::data::XDataSource > DataSourceHelper::getUsedData( + const uno::Reference< frame::XModel >& xChartModel ) +{ + ::std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > aResult; + + uno::Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartModel ) ); + uno::Reference< data::XLabeledDataSequence > xCategories( DiagramHelper::getCategoriesFromDiagram( xDiagram ) ); + if( xCategories.is() ) + aResult.push_back( xCategories ); + + ::std::vector< uno::Reference< XDataSeries > > aSeriesVector( ChartModelHelper::getDataSeries( xChartModel ) ); + for( ::std::vector< uno::Reference< XDataSeries > >::const_iterator aSeriesIt( aSeriesVector.begin() ) + ; aSeriesIt != aSeriesVector.end(); ++aSeriesIt ) + { + uno::Reference< data::XDataSource > xDataSource( *aSeriesIt, uno::UNO_QUERY ); + if( !xDataSource.is() ) + continue; + uno::Sequence< uno::Reference< data::XLabeledDataSequence > > aDataSequences( xDataSource->getDataSequences() ); + ::std::copy( aDataSequences.getConstArray(), aDataSequences.getConstArray() + aDataSequences.getLength(), + ::std::back_inserter( aResult )); + } + + return uno::Reference< chart2::data::XDataSource >( + new DataSource( ContainerHelper::ContainerToSequence( aResult ))); +} + +bool DataSourceHelper::detectRangeSegmentation( + const uno::Reference< + frame::XModel >& xChartModel + , ::rtl::OUString& rOutRangeString + , ::com::sun::star::uno::Sequence< sal_Int32 >& rSequenceMapping + , bool& rOutUseColumns + , bool& rOutFirstCellAsLabel + , bool& rOutHasCategories ) +{ + bool bSomethingDetected = false; + + uno::Reference< XChartDocument > xChartDocument( xChartModel, uno::UNO_QUERY ); + if( !xChartDocument.is() ) + return bSomethingDetected; + uno::Reference< data::XDataProvider > xDataProvider( xChartDocument->getDataProvider() ); + if( !xDataProvider.is() ) + return bSomethingDetected; + + try + { + DataSourceHelper::readArguments( + xDataProvider->detectArguments( pressUsedDataIntoRectangularFormat( xChartDocument ) ), + rOutRangeString, rSequenceMapping, rOutUseColumns, rOutFirstCellAsLabel, rOutHasCategories ); + bSomethingDetected = (rOutRangeString.getLength() > 0); + + uno::Reference< chart2::data::XLabeledDataSequence > xCategories( + DiagramHelper::getCategoriesFromDiagram( xChartDocument->getFirstDiagram() )); + rOutHasCategories = xCategories.is(); + } + catch( uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + return bSomethingDetected; +} + +bool DataSourceHelper::allArgumentsForRectRangeDetected( + const uno::Reference< chart2::XChartDocument >& xChartDocument ) +{ + bool bHasDataRowSource = false; + bool bHasFirstCellAsLabel = false; +// bool bHasHasCategories = false; + bool bHasCellRangeRepresentation = false; +// bool bHasSequenceMapping = false; + + uno::Reference< data::XDataProvider > xDataProvider( xChartDocument->getDataProvider() ); + if( !xDataProvider.is() ) + return false; + + try + { + const uno::Sequence< beans::PropertyValue > aArguments( + xDataProvider->detectArguments( pressUsedDataIntoRectangularFormat( xChartDocument ))); + const beans::PropertyValue* pArguments = aArguments.getConstArray(); + for(sal_Int32 i=0; i<aArguments.getLength(); ++i, ++pArguments) + { + const beans::PropertyValue& aProperty = *pArguments; + if( aProperty.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "DataRowSource" ) )) + { + bHasDataRowSource = + (aProperty.Value.hasValue() && aProperty.Value.isExtractableTo( + ::getCppuType( reinterpret_cast< + const ::com::sun::star::chart::ChartDataRowSource * >(0)))); + } + else if( aProperty.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "FirstCellAsLabel" ) )) + { + bHasFirstCellAsLabel = + (aProperty.Value.hasValue() && aProperty.Value.isExtractableTo(::getBooleanCppuType())); + } +// else if( aProperty.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "HasCategories" ) )) +// { +// bHasHasCategories = +// (aProperty.Value.hasValue() && aProperty.Value.isExtractableTo(::getBooleanCppuType())); +// } + else if( aProperty.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "CellRangeRepresentation" ) )) + { + ::rtl::OUString aRange; + bHasCellRangeRepresentation = + (aProperty.Value.hasValue() && (aProperty.Value >>= aRange) && aRange.getLength() > 0); + } +// else if( aProperty.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "SequenceMapping" ) )) +// { +// bHasSequenceMapping = +// (aProperty.Value.hasValue() && aProperty.Value.isExtractableTo( +// ::getCppuType( reinterpret_cast< +// const uno::Sequence< sal_Int32 > * >(0)))); +// } + } + } + catch( const uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + + return (bHasCellRangeRepresentation && bHasDataRowSource && bHasFirstCellAsLabel); +} + +void DataSourceHelper::setRangeSegmentation( + const uno::Reference< frame::XModel >& xChartModel + , const ::com::sun::star::uno::Sequence< sal_Int32 >& rSequenceMapping + , bool bUseColumns , bool bFirstCellAsLabel, bool bUseCategories ) +{ + uno::Reference< XChartDocument > xChartDocument( xChartModel, uno::UNO_QUERY ); + if( !xChartDocument.is() ) + return; + uno::Reference< data::XDataProvider > xDataProvider( xChartDocument->getDataProvider() ); + if( !xDataProvider.is() ) + return; + uno::Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartModel ) ); + if( !xDiagram.is() ) + return; + uno::Reference< chart2::XChartTypeManager > xChartTypeManager( xChartDocument->getChartTypeManager() ); + if( !xChartTypeManager.is() ) + return; + uno::Reference< lang::XMultiServiceFactory > xTemplateFactory( xChartTypeManager, uno::UNO_QUERY ); + if( !xTemplateFactory.is() ) + return; + + ::rtl::OUString aRangeString; + bool bDummy; + uno::Sequence< sal_Int32 > aDummy; + readArguments( xDataProvider->detectArguments( pressUsedDataIntoRectangularFormat( xChartDocument )), + aRangeString, aDummy, bDummy, bDummy, bDummy ); + + uno::Sequence< beans::PropertyValue > aArguments( + createArguments( aRangeString, rSequenceMapping, bUseColumns, bFirstCellAsLabel, bUseCategories ) ); + + uno::Reference< chart2::data::XDataSource > xDataSource( xDataProvider->createDataSource( + aArguments ) ); + if( !xDataSource.is() ) + return; + + DiagramHelper::tTemplateWithServiceName aTemplateAndService = + DiagramHelper::getTemplateForDiagram( xDiagram, xTemplateFactory ); + + rtl::OUString aServiceName( aTemplateAndService.second ); + uno::Reference< chart2::XChartTypeTemplate > xTemplate = aTemplateAndService.first; + + if( !xTemplate.is() ) + { + if( aServiceName.getLength() == 0 ) + aServiceName = C2U("com.sun.star.chart2.template.Column"); + xTemplate.set( xTemplateFactory->createInstance( aServiceName ), uno::UNO_QUERY ); + } + if( !xTemplate.is() ) + return; + + // /-- locked controllers + ControllerLockGuard aCtrlLockGuard( xChartModel ); + xTemplate->changeDiagramData( xDiagram, xDataSource, aArguments ); + // \-- locked controllers +} + +Sequence< OUString > DataSourceHelper::getRangesFromLabeledDataSequence( + const Reference< data::XLabeledDataSequence > & xLSeq ) +{ + Sequence< OUString > aResult; + if( xLSeq.is()) + { + Reference< data::XDataSequence > xLabel( xLSeq->getLabel()); + Reference< data::XDataSequence > xValues( xLSeq->getValues()); + + if( xLabel.is()) + { + if( xValues.is()) + { + aResult.realloc( 2 ); + aResult[0] = xLabel->getSourceRangeRepresentation(); + aResult[1] = xValues->getSourceRangeRepresentation(); + } + else + { + aResult.realloc( 1 ); + aResult[0] = xLabel->getSourceRangeRepresentation(); + } + } + else if( xValues.is()) + { + aResult.realloc( 1 ); + aResult[0] = xValues->getSourceRangeRepresentation(); + } + } + return aResult; +} + +OUString DataSourceHelper::getRangeFromValues( + const Reference< data::XLabeledDataSequence > & xLSeq ) +{ + OUString aResult; + if( xLSeq.is() ) + { + Reference< data::XDataSequence > xValues( xLSeq->getValues() ); + if( xValues.is() ) + aResult = xValues->getSourceRangeRepresentation(); + } + return aResult; +} + +Sequence< OUString > DataSourceHelper::getRangesFromDataSource( const Reference< data::XDataSource > & xSource ) +{ + ::std::vector< OUString > aResult; + if( xSource.is()) + { + Sequence< Reference< data::XLabeledDataSequence > > aLSeqSeq( xSource->getDataSequences()); + for( sal_Int32 i=0; i<aLSeqSeq.getLength(); ++i ) + { + Reference< data::XDataSequence > xLabel( aLSeqSeq[i]->getLabel()); + Reference< data::XDataSequence > xValues( aLSeqSeq[i]->getValues()); + + if( xLabel.is()) + aResult.push_back( xLabel->getSourceRangeRepresentation()); + if( xValues.is()) + aResult.push_back( xValues->getSourceRangeRepresentation()); + } + } + return ContainerHelper::ContainerToSequence( aResult ); +} + +//............................................................................. +} //namespace chart +//............................................................................. diff --git a/chart2/source/tools/DiagramHelper.cxx b/chart2/source/tools/DiagramHelper.cxx new file mode 100644 index 000000000000..36afef60a6d4 --- /dev/null +++ b/chart2/source/tools/DiagramHelper.cxx @@ -0,0 +1,1559 @@ +/************************************************************************* + * + * 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 "DiagramHelper.hxx" +#include "LegendHelper.hxx" +#include "PropertyHelper.hxx" +#include "macros.hxx" +#include "DataSeriesHelper.hxx" +#include "AxisHelper.hxx" +#include "ContainerHelper.hxx" +#include "ChartTypeHelper.hxx" +#include "ChartModelHelper.hxx" +#include "CommonConverters.hxx" +#include "ExplicitCategoriesProvider.hxx" +#include "servicenames_charttypes.hxx" +#include "ChartModelHelper.hxx" +#include "RelativePositionHelper.hxx" +#include "ControllerLockGuard.hxx" + +#include <com/sun/star/chart/MissingValueTreatment.hpp> +#include <com/sun/star/chart/XChartDocument.hpp> +#include <com/sun/star/chart/XDiagramPositioning.hpp> +#include <com/sun/star/chart2/XTitled.hpp> +#include <com/sun/star/chart2/XChartTypeContainer.hpp> +#include <com/sun/star/chart2/XChartTypeTemplate.hpp> +#include <com/sun/star/chart2/XCoordinateSystemContainer.hpp> +#include <com/sun/star/chart2/XDataSeriesContainer.hpp> +#include <com/sun/star/chart2/InterpretedData.hpp> +#include <com/sun/star/chart2/AxisType.hpp> +#include <com/sun/star/chart2/DataPointGeometry3D.hpp> +#include <com/sun/star/chart2/RelativePosition.hpp> +#include <com/sun/star/chart2/RelativeSize.hpp> + +#include <unotools/saveopt.hxx> +#include <rtl/math.hxx> + +#include <com/sun/star/util/XModifiable.hpp> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; +using namespace ::std; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::rtl::OUString; + +namespace chart +{ + +// static +DiagramHelper::tTemplateWithServiceName + DiagramHelper::getTemplateForDiagram( + const Reference< XDiagram > & xDiagram, + const Reference< lang::XMultiServiceFactory > & xChartTypeManager, + const OUString & rPreferredTemplateName ) +{ + DiagramHelper::tTemplateWithServiceName aResult; + + if( ! (xChartTypeManager.is() && xDiagram.is())) + return aResult; + + Sequence< OUString > aServiceNames( xChartTypeManager->getAvailableServiceNames()); + const sal_Int32 nLength = aServiceNames.getLength(); + + bool bHasPreferredTemplate = (rPreferredTemplateName.getLength() > 0); + bool bTemplateFound = false; + + if( bHasPreferredTemplate ) + { + Reference< XChartTypeTemplate > xTempl( + xChartTypeManager->createInstance( rPreferredTemplateName ), uno::UNO_QUERY ); + + if( xTempl.is() && + xTempl->matchesTemplate( xDiagram, sal_True )) + { + aResult.first = xTempl; + aResult.second = rPreferredTemplateName; + bTemplateFound = true; + } + } + + for( sal_Int32 i = 0; ! bTemplateFound && i < nLength; ++i ) + { + try + { + if( ! bHasPreferredTemplate || + ! rPreferredTemplateName.equals( aServiceNames[ i ] )) + { + Reference< XChartTypeTemplate > xTempl( + xChartTypeManager->createInstance( aServiceNames[ i ] ), uno::UNO_QUERY_THROW ); + + if( xTempl->matchesTemplate( xDiagram, sal_True )) + { + aResult.first = xTempl; + aResult.second = aServiceNames[ i ]; + bTemplateFound = true; + } + } + } + catch( uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + } + + return aResult; +} + +// static +void DiagramHelper::setVertical( + const Reference< XDiagram > & xDiagram, + bool bVertical /* = true */ ) +{ + try + { + Reference< XCoordinateSystemContainer > xCnt( xDiagram, uno::UNO_QUERY ); + if( xCnt.is()) + { + Sequence< Reference< XCoordinateSystem > > aCooSys( + xCnt->getCoordinateSystems()); + uno::Any aValue; + aValue <<= bVertical; + for( sal_Int32 i=0; i<aCooSys.getLength(); ++i ) + { + uno::Reference< XCoordinateSystem > xCooSys( aCooSys[i] ); + Reference< beans::XPropertySet > xProp( xCooSys, uno::UNO_QUERY ); + bool bChanged = false; + if( xProp.is() ) + { + bool bOldSwap = sal_False; + if( !(xProp->getPropertyValue( C2U("SwapXAndYAxis") ) >>= bOldSwap) + || bVertical != bOldSwap ) + bChanged = true; + + if( bChanged ) + xProp->setPropertyValue( C2U("SwapXAndYAxis"), aValue ); + } + if( xCooSys.is() ) + { + const sal_Int32 nDimensionCount( xCooSys->getDimension() ); + sal_Int32 nDimIndex = 0; + for(nDimIndex=0; nDimIndex<nDimensionCount; ++nDimIndex) + { + const sal_Int32 nMaximumScaleIndex = xCooSys->getMaximumAxisIndexByDimension(nDimIndex); + for(sal_Int32 nI=0; nI<=nMaximumScaleIndex; ++nI) + { + Reference< chart2::XAxis > xAxis( xCooSys->getAxisByDimension( nDimIndex,nI )); + if( xAxis.is() ) + { + //adapt title rotation only when axis swapping has changed + if( bChanged ) + { + Reference< XTitled > xTitled( xAxis, uno::UNO_QUERY ); + if( xTitled.is()) + { + Reference< beans::XPropertySet > xTitleProps( xTitled->getTitleObject(), uno::UNO_QUERY ); + if( !xTitleProps.is() ) + continue; + double fAngleDegree = 0.0; + xTitleProps->getPropertyValue( C2U( "TextRotation" ) ) >>= fAngleDegree; + if( !::rtl::math::approxEqual( fAngleDegree, 0.0 ) + && !::rtl::math::approxEqual( fAngleDegree, 90.0 ) ) + continue; + + double fNewAngleDegree = 0.0; + if( !bVertical && nDimIndex == 1 ) + fNewAngleDegree = 90.0; + else if( bVertical && nDimIndex == 0 ) + fNewAngleDegree = 90.0; + + xTitleProps->setPropertyValue( C2U( "TextRotation" ), uno::makeAny( fNewAngleDegree )); + } + } + } + } + } + } + } + } + } + catch( uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } +} + +//static +bool DiagramHelper::getVertical( const uno::Reference< chart2::XDiagram > & xDiagram, + bool& rbFound, bool& rbAmbiguous ) +{ + bool bValue = false; + rbFound = false; + rbAmbiguous = false; + + Reference< XCoordinateSystemContainer > xCnt( xDiagram, uno::UNO_QUERY ); + if( xCnt.is()) + { + Sequence< Reference< XCoordinateSystem > > aCooSys( + xCnt->getCoordinateSystems()); + for( sal_Int32 i=0; i<aCooSys.getLength(); ++i ) + { + Reference< beans::XPropertySet > xProp( aCooSys[i], uno::UNO_QUERY ); + if( xProp.is()) + { + bool bCurrent = false; + if( xProp->getPropertyValue( C2U("SwapXAndYAxis") ) >>= bCurrent ) + { + if( !rbFound ) + { + bValue = bCurrent; + rbFound = true; + } + else if( bCurrent != bValue ) + { + // ambiguous -> choose always first found + rbAmbiguous = true; + } + } + } + } + } + return bValue; +} + +//static +void DiagramHelper::setStackMode( + const Reference< XDiagram > & xDiagram, + StackMode eStackMode, + bool bOnlyAtFirstChartType /* = true */ +) +{ + try + { + if( eStackMode == StackMode_AMBIGUOUS ) + return; + + bool bValueFound = false; + bool bIsAmbiguous = false; + StackMode eOldStackMode = DiagramHelper::getStackMode( xDiagram, bValueFound, bIsAmbiguous ); + + if( eStackMode == eOldStackMode && !bIsAmbiguous ) + return; + + StackingDirection eNewDirection = StackingDirection_NO_STACKING; + if( eStackMode == StackMode_Y_STACKED || eStackMode == StackMode_Y_STACKED_PERCENT ) + eNewDirection = StackingDirection_Y_STACKING; + else if( eStackMode == StackMode_Z_STACKED ) + eNewDirection = StackingDirection_Z_STACKING; + + uno::Any aNewDirection( uno::makeAny(eNewDirection) ); + + sal_Bool bPercent = sal_False; + if( eStackMode == StackMode_Y_STACKED_PERCENT ) + bPercent = sal_True; + + //iterate through all coordinate systems + uno::Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY ); + if( !xCooSysContainer.is() ) + return; + uno::Sequence< uno::Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() ); + for( sal_Int32 nCS = 0; nCS < aCooSysList.getLength(); ++nCS ) + { + uno::Reference< XCoordinateSystem > xCooSys( aCooSysList[nCS] ); + //set correct percent stacking + const sal_Int32 nMaximumScaleIndex = xCooSys->getMaximumAxisIndexByDimension(1); + for(sal_Int32 nI=0; nI<=nMaximumScaleIndex; ++nI) + { + Reference< chart2::XAxis > xAxis( xCooSys->getAxisByDimension( 1,nI )); + if( xAxis.is()) + { + chart2::ScaleData aScaleData = xAxis->getScaleData(); + if( (aScaleData.AxisType==AxisType::PERCENT) != bPercent ) + { + if( bPercent ) + aScaleData.AxisType = AxisType::PERCENT; + else + aScaleData.AxisType = AxisType::REALNUMBER; + xAxis->setScaleData( aScaleData ); + } + } + } + //iterate through all chart types in the current coordinate system + uno::Reference< XChartTypeContainer > xChartTypeContainer( xCooSys, uno::UNO_QUERY ); + if( !xChartTypeContainer.is() ) + continue; + uno::Sequence< uno::Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() ); + sal_Int32 nMax = aChartTypeList.getLength(); + if( bOnlyAtFirstChartType + && nMax >= 1 ) + nMax = 1; + for( sal_Int32 nT = 0; nT < nMax; ++nT ) + { + uno::Reference< XChartType > xChartType( aChartTypeList[nT] ); + + //iterate through all series in this chart type + uno::Reference< XDataSeriesContainer > xDataSeriesContainer( xChartType, uno::UNO_QUERY ); + OSL_ASSERT( xDataSeriesContainer.is()); + if( !xDataSeriesContainer.is() ) + continue; + + uno::Sequence< uno::Reference< XDataSeries > > aSeriesList( xDataSeriesContainer->getDataSeries() ); + for( sal_Int32 nS = 0; nS < aSeriesList.getLength(); ++nS ) + { + Reference< beans::XPropertySet > xProp( aSeriesList[nS], uno::UNO_QUERY ); + if(xProp.is()) + xProp->setPropertyValue( C2U( "StackingDirection" ), aNewDirection ); + } + } + } + } + catch( uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } +} + +//static + +StackMode DiagramHelper::getStackMode( const Reference< XDiagram > & xDiagram, bool& rbFound, bool& rbAmbiguous ) +{ + rbFound=false; + rbAmbiguous=false; + + StackMode eGlobalStackMode = StackMode_NONE; + + //iterate through all coordinate systems + uno::Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY ); + if( !xCooSysContainer.is() ) + return eGlobalStackMode; + uno::Sequence< uno::Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() ); + for( sal_Int32 nCS = 0; nCS < aCooSysList.getLength(); ++nCS ) + { + uno::Reference< XCoordinateSystem > xCooSys( aCooSysList[nCS] ); + + //iterate through all chart types in the current coordinate system + uno::Reference< XChartTypeContainer > xChartTypeContainer( xCooSys, uno::UNO_QUERY ); + if( !xChartTypeContainer.is() ) + continue; + uno::Sequence< uno::Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() ); + for( sal_Int32 nT = 0; nT < aChartTypeList.getLength(); ++nT ) + { + uno::Reference< XChartType > xChartType( aChartTypeList[nT] ); + + StackMode eLocalStackMode = DiagramHelper::getStackModeFromChartType( + xChartType, rbFound, rbAmbiguous, xCooSys ); + + if( rbFound && eLocalStackMode != eGlobalStackMode && nT>0 ) + { + rbAmbiguous = true; + return eGlobalStackMode; + } + + eGlobalStackMode = eLocalStackMode; + } + } + + return eGlobalStackMode; +} + +// static +StackMode DiagramHelper::getStackModeFromChartType( + const Reference< XChartType > & xChartType, + bool& rbFound, bool& rbAmbiguous, + const Reference< XCoordinateSystem > & xCorrespondingCoordinateSystem ) +{ + StackMode eStackMode = StackMode_NONE; + rbFound = false; + rbAmbiguous = false; + + try + { + Reference< XDataSeriesContainer > xDSCnt( xChartType, uno::UNO_QUERY_THROW ); + Sequence< Reference< chart2::XDataSeries > > aSeries( xDSCnt->getDataSeries()); + + chart2::StackingDirection eCommonDirection = chart2::StackingDirection_NO_STACKING; + bool bDirectionInitialized = false; + + // first series is irrelvant for stacking, start with second, unless + // there is only one series + const sal_Int32 nSeriesCount = aSeries.getLength(); + sal_Int32 i = (nSeriesCount == 1) ? 0: 1; + for( ; i<nSeriesCount; ++i ) + { + rbFound = true; + Reference< beans::XPropertySet > xProp( aSeries[i], uno::UNO_QUERY_THROW ); + chart2::StackingDirection eCurrentDirection = eCommonDirection; + // property is not MAYBEVOID + bool bSuccess = ( xProp->getPropertyValue( C2U("StackingDirection") ) >>= eCurrentDirection ); + OSL_ASSERT( bSuccess ); + (void)(bSuccess); // avoid warning in non-debug builds + if( ! bDirectionInitialized ) + { + eCommonDirection = eCurrentDirection; + bDirectionInitialized = true; + } + else + { + if( eCommonDirection != eCurrentDirection ) + { + rbAmbiguous = true; + break; + } + } + } + + if( rbFound ) + { + if( eCommonDirection == chart2::StackingDirection_Z_STACKING ) + eStackMode = StackMode_Z_STACKED; + else if( eCommonDirection == chart2::StackingDirection_Y_STACKING ) + { + eStackMode = StackMode_Y_STACKED; + + // percent stacking + if( xCorrespondingCoordinateSystem.is() ) + { + if( 1 < xCorrespondingCoordinateSystem->getDimension() ) + { + sal_Int32 nAxisIndex = 0; + if( nSeriesCount ) + nAxisIndex = DataSeriesHelper::getAttachedAxisIndex(aSeries[0]); + + Reference< chart2::XAxis > xAxis( + xCorrespondingCoordinateSystem->getAxisByDimension( 1,nAxisIndex )); + if( xAxis.is()) + { + chart2::ScaleData aScaleData = xAxis->getScaleData(); + if( aScaleData.AxisType==chart2::AxisType::PERCENT ) + eStackMode = StackMode_Y_STACKED_PERCENT; + } + } + } + } + } + } + catch( uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + + return eStackMode; +} + +// static +sal_Int32 DiagramHelper::getDimension( const Reference< XDiagram > & xDiagram ) +{ + // -1: not yet set + sal_Int32 nResult = -1; + + try + { + Reference< XCoordinateSystemContainer > xCooSysCnt( xDiagram, uno::UNO_QUERY ); + if( xCooSysCnt.is() ) + { + Sequence< Reference< XCoordinateSystem > > aCooSysSeq( + xCooSysCnt->getCoordinateSystems()); + + for( sal_Int32 i=0; i<aCooSysSeq.getLength(); ++i ) + { + Reference< XCoordinateSystem > xCooSys( aCooSysSeq[i] ); + if(xCooSys.is()) + { + nResult = xCooSys->getDimension(); + break; + } + } + } + } + catch( uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + + return nResult; +} + +// static +void DiagramHelper::setDimension( + const Reference< XDiagram > & xDiagram, + sal_Int32 nNewDimensionCount ) +{ + if( ! xDiagram.is()) + return; + + if( DiagramHelper::getDimension( xDiagram ) == nNewDimensionCount ) + return; + + try + { + bool rbFound = false; + bool rbAmbiguous = true; + StackMode eStackMode = DiagramHelper::getStackMode( xDiagram, rbFound, rbAmbiguous ); + bool bIsSupportingOnlyDeepStackingFor3D=false; + + //change all coordinate systems: + Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY_THROW ); + Sequence< Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() ); + for( sal_Int32 nCS = 0; nCS < aCooSysList.getLength(); ++nCS ) + { + Reference< XCoordinateSystem > xOldCooSys( aCooSysList[nCS], uno::UNO_QUERY ); + Reference< XCoordinateSystem > xNewCooSys; + + Reference< XChartTypeContainer > xChartTypeContainer( xOldCooSys, uno::UNO_QUERY ); + if( !xChartTypeContainer.is() ) + continue; + + Sequence< Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() ); + for( sal_Int32 nT = 0; nT < aChartTypeList.getLength(); ++nT ) + { + Reference< XChartType > xChartType( aChartTypeList[nT], uno::UNO_QUERY ); + bIsSupportingOnlyDeepStackingFor3D = ChartTypeHelper::isSupportingOnlyDeepStackingFor3D( xChartType ); + if(!xNewCooSys.is()) + { + xNewCooSys = xChartType->createCoordinateSystem( nNewDimensionCount ); + break; + } + //@todo make sure that all following charttypes are also capable of the new dimension + //otherwise separate them in a different group + //BM: might be done in replaceCoordinateSystem() + } + + // replace the old coordinate system at all places where it was used + DiagramHelper::replaceCoordinateSystem( xDiagram, xOldCooSys, xNewCooSys ); + } + + //correct stack mode if necessary + if( nNewDimensionCount==3 && eStackMode != StackMode_Z_STACKED && bIsSupportingOnlyDeepStackingFor3D ) + DiagramHelper::setStackMode( xDiagram, StackMode_Z_STACKED ); + else if( nNewDimensionCount==2 && eStackMode == StackMode_Z_STACKED ) + DiagramHelper::setStackMode( xDiagram, StackMode_NONE ); + } + catch( uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } +} + +// static +void DiagramHelper::replaceCoordinateSystem( + const Reference< XDiagram > & xDiagram, + const Reference< XCoordinateSystem > & xCooSysToReplace, + const Reference< XCoordinateSystem > & xReplacement ) +{ + OSL_ASSERT( xDiagram.is()); + if( ! xDiagram.is()) + return; + + // update the coordinate-system container + Reference< XCoordinateSystemContainer > xCont( xDiagram, uno::UNO_QUERY ); + if( xCont.is()) + { + try + { + Reference< chart2::data::XLabeledDataSequence > xCategories = DiagramHelper::getCategoriesFromDiagram( xDiagram ); + + // move chart types of xCooSysToReplace to xReplacement + Reference< XChartTypeContainer > xCTCntCooSys( xCooSysToReplace, uno::UNO_QUERY_THROW ); + Reference< XChartTypeContainer > xCTCntReplacement( xReplacement, uno::UNO_QUERY_THROW ); + xCTCntReplacement->setChartTypes( xCTCntCooSys->getChartTypes()); + + xCont->removeCoordinateSystem( xCooSysToReplace ); + xCont->addCoordinateSystem( xReplacement ); + + if( xCategories.is() ) + DiagramHelper::setCategoriesToDiagram( xCategories, xDiagram ); + } + catch( uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + } +} + +//static +bool DiagramHelper::isSeriesAttachedToMainAxis( + const uno::Reference< chart2::XDataSeries >& xDataSeries ) +{ + sal_Int32 nAxisIndex = DataSeriesHelper::getAttachedAxisIndex(xDataSeries); + return (nAxisIndex==0); +} + +//static +bool DiagramHelper::attachSeriesToAxis( bool bAttachToMainAxis + , const uno::Reference< chart2::XDataSeries >& xDataSeries + , const uno::Reference< chart2::XDiagram >& xDiagram + , const uno::Reference< uno::XComponentContext > & xContext + , bool bAdaptAxes ) +{ + bool bChanged = false; + + //set property at axis + Reference< beans::XPropertySet > xProp( xDataSeries, uno::UNO_QUERY_THROW ); + if( !xProp.is() ) + return bChanged; + + sal_Int32 nNewAxisIndex = bAttachToMainAxis ? 0 : 1; + sal_Int32 nOldAxisIndex = DataSeriesHelper::getAttachedAxisIndex(xDataSeries); + uno::Reference< chart2::XAxis > xOldAxis( DiagramHelper::getAttachedAxis( xDataSeries, xDiagram ) ); + + if( nOldAxisIndex != nNewAxisIndex ) + { + try + { + xProp->setPropertyValue( C2U("AttachedAxisIndex"), uno::makeAny( nNewAxisIndex ) ); + bChanged = true; + } + catch( const uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + } + + if( bChanged && xDiagram.is() ) + { + uno::Reference< XAxis > xAxis( AxisHelper::getAxis( 1, bAttachToMainAxis, xDiagram ) ); + if(!xAxis.is()) //create an axis if necessary + xAxis = AxisHelper::createAxis( 1, bAttachToMainAxis, xDiagram, xContext ); + if( bAdaptAxes ) + { + AxisHelper::makeAxisVisible( xAxis ); + AxisHelper::hideAxisIfNoDataIsAttached( xOldAxis, xDiagram ); + } + } + + return bChanged; +} + +//static +uno::Reference< XAxis > DiagramHelper::getAttachedAxis( + const uno::Reference< XDataSeries >& xSeries, + const uno::Reference< XDiagram >& xDiagram ) +{ + return AxisHelper::getAxis( 1, DiagramHelper::isSeriesAttachedToMainAxis( xSeries ), xDiagram ); +} + +//static +uno::Reference< XChartType > DiagramHelper::getChartTypeOfSeries( + const uno::Reference< chart2::XDiagram >& xDiagram + , const uno::Reference< XDataSeries >& xGivenDataSeries ) +{ + if( !xGivenDataSeries.is() ) + return 0; + if(!xDiagram.is()) + return 0; + + //iterate through the model to find the given xSeries + //the found parent indicates the charttype + + //iterate through all coordinate systems + uno::Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY ); + if( !xCooSysContainer.is()) + return 0; + + uno::Sequence< uno::Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() ); + for( sal_Int32 nCS = 0; nCS < aCooSysList.getLength(); ++nCS ) + { + uno::Reference< XCoordinateSystem > xCooSys( aCooSysList[nCS] ); + + //iterate through all chart types in the current coordinate system + uno::Reference< XChartTypeContainer > xChartTypeContainer( xCooSys, uno::UNO_QUERY ); + OSL_ASSERT( xChartTypeContainer.is()); + if( !xChartTypeContainer.is() ) + continue; + uno::Sequence< uno::Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() ); + for( sal_Int32 nT = 0; nT < aChartTypeList.getLength(); ++nT ) + { + uno::Reference< XChartType > xChartType( aChartTypeList[nT] ); + + //iterate through all series in this chart type + uno::Reference< XDataSeriesContainer > xDataSeriesContainer( xChartType, uno::UNO_QUERY ); + OSL_ASSERT( xDataSeriesContainer.is()); + if( !xDataSeriesContainer.is() ) + continue; + + uno::Sequence< uno::Reference< XDataSeries > > aSeriesList( xDataSeriesContainer->getDataSeries() ); + for( sal_Int32 nS = 0; nS < aSeriesList.getLength(); ++nS ) + { + if( xGivenDataSeries==aSeriesList[nS] ) + return xChartType; + } + } + } + return 0; +} + +// static +::std::vector< Reference< XDataSeries > > + DiagramHelper::getDataSeriesFromDiagram( + const Reference< XDiagram > & xDiagram ) +{ + ::std::vector< Reference< XDataSeries > > aResult; + + try + { + Reference< XCoordinateSystemContainer > xCooSysCnt( + xDiagram, uno::UNO_QUERY_THROW ); + Sequence< Reference< XCoordinateSystem > > aCooSysSeq( + xCooSysCnt->getCoordinateSystems()); + for( sal_Int32 i=0; i<aCooSysSeq.getLength(); ++i ) + { + Reference< XChartTypeContainer > xCTCnt( aCooSysSeq[i], uno::UNO_QUERY_THROW ); + Sequence< Reference< XChartType > > aChartTypeSeq( xCTCnt->getChartTypes()); + for( sal_Int32 j=0; j<aChartTypeSeq.getLength(); ++j ) + { + Reference< XDataSeriesContainer > xDSCnt( aChartTypeSeq[j], uno::UNO_QUERY_THROW ); + Sequence< Reference< XDataSeries > > aSeriesSeq( xDSCnt->getDataSeries() ); + ::std::copy( aSeriesSeq.getConstArray(), aSeriesSeq.getConstArray() + aSeriesSeq.getLength(), + ::std::back_inserter( aResult )); + } + } + } + catch( uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + + return aResult; +} + +Sequence< Sequence< Reference< XDataSeries > > > + DiagramHelper::getDataSeriesGroups( const Reference< XDiagram > & xDiagram ) +{ + vector< Sequence< Reference< XDataSeries > > > aResult; + + //iterate through all coordinate systems + Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY ); + if( xCooSysContainer.is() ) + { + Sequence< Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() ); + for( sal_Int32 nCS = 0; nCS < aCooSysList.getLength(); ++nCS ) + { + //iterate through all chart types in the current coordinate system + Reference< XChartTypeContainer > xChartTypeContainer( aCooSysList[nCS], uno::UNO_QUERY ); + if( !xChartTypeContainer.is() ) + continue; + Sequence< Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() ); + for( sal_Int32 nT = 0; nT < aChartTypeList.getLength(); ++nT ) + { + Reference< XDataSeriesContainer > xDataSeriesContainer( aChartTypeList[nT], uno::UNO_QUERY ); + if( !xDataSeriesContainer.is() ) + continue; + aResult.push_back( xDataSeriesContainer->getDataSeries() ); + } + } + } + return ContainerHelper::ContainerToSequence( aResult ); +} + +Reference< XChartType > + DiagramHelper::getChartTypeByIndex( const Reference< XDiagram >& xDiagram, sal_Int32 nIndex ) +{ + Reference< XChartType > xChartType; + + //iterate through all coordinate systems + Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY ); + if( ! xCooSysContainer.is()) + return xChartType; + + Sequence< Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() ); + sal_Int32 nTypesSoFar = 0; + for( sal_Int32 nCS = 0; nCS < aCooSysList.getLength(); ++nCS ) + { + Reference< XChartTypeContainer > xChartTypeContainer( aCooSysList[nCS], uno::UNO_QUERY ); + if( !xChartTypeContainer.is() ) + continue; + Sequence< Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() ); + if( nIndex >= 0 && nIndex < (nTypesSoFar + aChartTypeList.getLength()) ) + { + xChartType.set( aChartTypeList[nIndex - nTypesSoFar] ); + break; + } + nTypesSoFar += aChartTypeList.getLength(); + } + + return xChartType; +} + +namespace +{ + +std::vector< Reference< XAxis > > lcl_getAxisHoldingCategoriesFromDiagram( + const Reference< XDiagram > & xDiagram ) +{ + std::vector< Reference< XAxis > > aRet; + + Reference< XAxis > xResult; + // return first x-axis as fall-back + Reference< XAxis > xFallBack; + try + { + Reference< XCoordinateSystemContainer > xCooSysCnt( + xDiagram, uno::UNO_QUERY_THROW ); + Sequence< Reference< XCoordinateSystem > > aCooSysSeq( + xCooSysCnt->getCoordinateSystems()); + for( sal_Int32 i=0; i<aCooSysSeq.getLength(); ++i ) + { + Reference< XCoordinateSystem > xCooSys( aCooSysSeq[i] ); + OSL_ASSERT( xCooSys.is()); + for( sal_Int32 nN = xCooSys->getDimension(); nN--; ) + { + const sal_Int32 nMaximumScaleIndex = xCooSys->getMaximumAxisIndexByDimension(nN); + for(sal_Int32 nI=0; nI<=nMaximumScaleIndex; ++nI) + { + Reference< XAxis > xAxis = xCooSys->getAxisByDimension( nN,nI ); + OSL_ASSERT( xAxis.is()); + if( xAxis.is()) + { + ScaleData aScaleData = xAxis->getScaleData(); + if( aScaleData.Categories.is() || (aScaleData.AxisType == AxisType::CATEGORY) ) + { + aRet.push_back(xAxis); + } + if( (nN == 0) && !xFallBack.is()) + xFallBack.set( xAxis ); + } + } + } + } + } + catch( uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + + if( aRet.empty() ) + aRet.push_back(xFallBack); + + return aRet; +} + +} // anonymous namespace + +//static +bool DiagramHelper::isCategoryDiagram( + const Reference< XDiagram >& xDiagram ) +{ + try + { + Reference< XCoordinateSystemContainer > xCooSysCnt( + xDiagram, uno::UNO_QUERY_THROW ); + Sequence< Reference< XCoordinateSystem > > aCooSysSeq( + xCooSysCnt->getCoordinateSystems()); + for( sal_Int32 i=0; i<aCooSysSeq.getLength(); ++i ) + { + Reference< XCoordinateSystem > xCooSys( aCooSysSeq[i] ); + OSL_ASSERT( xCooSys.is()); + for( sal_Int32 nN = xCooSys->getDimension(); nN--; ) + { + const sal_Int32 nMaximumScaleIndex = xCooSys->getMaximumAxisIndexByDimension(nN); + for(sal_Int32 nI=0; nI<=nMaximumScaleIndex; ++nI) + { + Reference< XAxis > xAxis = xCooSys->getAxisByDimension( nN,nI ); + OSL_ASSERT( xAxis.is()); + if( xAxis.is()) + { + ScaleData aScaleData = xAxis->getScaleData(); + if( aScaleData.AxisType == AxisType::CATEGORY ) + return true; + } + } + } + } + } + catch( uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + + return false; +} + +// static +void DiagramHelper::setCategoriesToDiagram( + const Reference< chart2::data::XLabeledDataSequence >& xCategories, + const Reference< XDiagram >& xDiagram, + bool bSetAxisType /* = false */, + bool bCategoryAxis /* = true */ ) +{ + std::vector< Reference< chart2::XAxis > > aCatAxes( + lcl_getAxisHoldingCategoriesFromDiagram( xDiagram )); + + std::vector< Reference< chart2::XAxis > >::iterator aIt( aCatAxes.begin() ); + std::vector< Reference< chart2::XAxis > >::const_iterator aEnd( aCatAxes.end() ); + + for( aIt = aCatAxes.begin(); aIt != aEnd; ++aIt ) + { + Reference< chart2::XAxis > xCatAxis(*aIt); + if( xCatAxis.is()) + { + ScaleData aScaleData( xCatAxis->getScaleData()); + aScaleData.Categories = xCategories; + if( bSetAxisType ) + { + if( bCategoryAxis ) + aScaleData.AxisType = AxisType::CATEGORY; + else if( aScaleData.AxisType == AxisType::CATEGORY ) + aScaleData.AxisType = AxisType::REALNUMBER; + } + xCatAxis->setScaleData( aScaleData ); + } + } +} + +// static +Reference< data::XLabeledDataSequence > + DiagramHelper::getCategoriesFromDiagram( + const Reference< XDiagram > & xDiagram ) +{ + Reference< data::XLabeledDataSequence > xResult; + + try + { + std::vector< Reference< chart2::XAxis > > aCatAxes( + lcl_getAxisHoldingCategoriesFromDiagram( xDiagram )); + std::vector< Reference< chart2::XAxis > >::iterator aIt( aCatAxes.begin() ); + std::vector< Reference< chart2::XAxis > >::const_iterator aEnd( aCatAxes.end() ); + //search for first categories + if( aIt != aEnd ) + { + Reference< chart2::XAxis > xCatAxis(*aIt); + if( xCatAxis.is()) + { + ScaleData aScaleData( xCatAxis->getScaleData()); + if( aScaleData.Categories.is() ) + { + xResult.set( aScaleData.Categories ); + uno::Reference<beans::XPropertySet> xProp(aScaleData.Categories->getValues(), uno::UNO_QUERY ); + if( xProp.is() ) + { + try + { + xProp->setPropertyValue( C2U( "Role" ), uno::makeAny( C2U("categories") ) ); + } + catch( uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + } + } + } + } + } + catch( uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + + return xResult; +} + +void lcl_generateAutomaticCategoriesFromChartType( + Sequence< rtl::OUString >& rRet, + const Reference< XChartType >& xChartType ) +{ + if(!xChartType.is()) + return; + rtl::OUString aMainSeq( xChartType->getRoleOfSequenceForSeriesLabel() ); + Reference< XDataSeriesContainer > xSeriesCnt( xChartType, uno::UNO_QUERY ); + if( xSeriesCnt.is() ) + { + Sequence< Reference< XDataSeries > > aSeriesSeq( xSeriesCnt->getDataSeries() ); + for( sal_Int32 nS = 0; nS < aSeriesSeq.getLength(); nS++ ) + { + Reference< data::XDataSource > xDataSource( aSeriesSeq[nS], uno::UNO_QUERY ); + if( !xDataSource.is() ) + continue; + Reference< chart2::data::XLabeledDataSequence > xLabeledSeq( + ::chart::DataSeriesHelper::getDataSequenceByRole( xDataSource, aMainSeq )); + if( !xLabeledSeq.is() ) + continue; + Reference< chart2::data::XDataSequence > xValueSeq( xLabeledSeq->getValues() ); + if( !xValueSeq.is() ) + continue; + rRet = xValueSeq->generateLabel( chart2::data::LabelOrigin_LONG_SIDE ); + if( rRet.getLength() ) + return; + } + } +} + +Sequence< rtl::OUString > DiagramHelper::generateAutomaticCategoriesFromCooSys( const Reference< XCoordinateSystem > & xCooSys ) +{ + Sequence< rtl::OUString > aRet; + + Reference< XChartTypeContainer > xTypeCntr( xCooSys, uno::UNO_QUERY ); + if( xTypeCntr.is() ) + { + Sequence< Reference< XChartType > > aChartTypes( xTypeCntr->getChartTypes() ); + for( sal_Int32 nN=0; nN<aChartTypes.getLength(); nN++ ) + { + lcl_generateAutomaticCategoriesFromChartType( aRet, aChartTypes[nN] ); + if( aRet.getLength() ) + return aRet; + } + } + return aRet; +} + +//static +Sequence< rtl::OUString > DiagramHelper::getExplicitSimpleCategories( + const Reference< XChartDocument >& xChartDoc ) +{ + Sequence< rtl::OUString > aRet; + uno::Reference< frame::XModel > xChartModel( xChartDoc, uno::UNO_QUERY ); + if(xChartModel.is()) + { + uno::Reference< chart2::XCoordinateSystem > xCooSys( ChartModelHelper::getFirstCoordinateSystem( xChartModel ) ); + ExplicitCategoriesProvider aExplicitCategoriesProvider( xCooSys, xChartModel ); + aRet = aExplicitCategoriesProvider.getSimpleCategories(); + } + return aRet; +} + +// static +Sequence< Reference< XChartType > > + DiagramHelper::getChartTypesFromDiagram( + const Reference< XDiagram > & xDiagram ) +{ + ::std::vector< Reference< XChartType > > aResult; + + if(xDiagram.is()) + try + { + Reference< XCoordinateSystemContainer > xCooSysCnt( + xDiagram, uno::UNO_QUERY_THROW ); + Sequence< Reference< XCoordinateSystem > > aCooSysSeq( + xCooSysCnt->getCoordinateSystems()); + for( sal_Int32 i=0; i<aCooSysSeq.getLength(); ++i ) + { + Reference< XChartTypeContainer > xCTCnt( aCooSysSeq[i], uno::UNO_QUERY_THROW ); + Sequence< Reference< XChartType > > aChartTypeSeq( xCTCnt->getChartTypes()); + ::std::copy( aChartTypeSeq.getConstArray(), aChartTypeSeq.getConstArray() + aChartTypeSeq.getLength(), + ::std::back_inserter( aResult )); + } + } + catch( uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + + return ContainerHelper::ContainerToSequence( aResult ); +} + +//static +bool DiagramHelper::areChartTypesCompatible( const Reference< ::chart2::XChartType >& xFirstType, + const Reference< ::chart2::XChartType >& xSecondType ) +{ + if( !xFirstType.is() || !xSecondType.is() ) + return false; + + ::std::vector< ::rtl::OUString > aFirstRoles( ContainerHelper::SequenceToVector( xFirstType->getSupportedMandatoryRoles() ) ); + ::std::vector< ::rtl::OUString > aSecondRoles( ContainerHelper::SequenceToVector( xSecondType->getSupportedMandatoryRoles() ) ); + ::std::sort( aFirstRoles.begin(), aFirstRoles.end() ); + ::std::sort( aSecondRoles.begin(), aSecondRoles.end() ); + return ( aFirstRoles == aSecondRoles ); +} + +namespace +{ + /** + * This method implements the logic of checking if a series can be moved + * forward/backward. Depending on the "bDoMove" parameter the series will + * be moved (bDoMove = true) or the function just will test if the + * series can be moved without doing the move (bDoMove = false). + * + * @param xDiagram + * Reference to the diagram that contains the series. + * + * @param xGivenDataSeries + * Reference to the series that should moved or tested for moving. + * + * @param bForward + * Direction in which the series should be moved or tested for moving. + * + * @param bDoMove + * Should this function really move the series (true) or just test if it is + * possible (false). + * + * + * @returns + * in case of bDoMove == true + * - True : if the move was done + * - False : the move failed + * in case of bDoMove == false + * - True : the series can be moved + * - False : the series can not be moved + * + */ + +bool lcl_moveSeriesOrCheckIfMoveIsAllowed( + const Reference< XDiagram >& xDiagram, + const Reference< XDataSeries >& xGivenDataSeries, + bool bForward, + bool bDoMove ) +{ + bool bMovedOrMoveAllowed = false; + + try + { + uno::Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY ); + + //find position of series. + bool bFound = false; + + if( xGivenDataSeries.is() && xCooSysContainer.is() ) + { + uno::Sequence< uno::Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() ); + + for( sal_Int32 nCS = 0; !bFound && nCS < aCooSysList.getLength(); ++nCS ) + { + uno::Reference< XCoordinateSystem > xCooSys( aCooSysList[nCS] ); + + //iterate through all chart types in the current coordinate system + uno::Reference< XChartTypeContainer > xChartTypeContainer( xCooSys, uno::UNO_QUERY ); + OSL_ASSERT( xChartTypeContainer.is()); + if( !xChartTypeContainer.is() ) + continue; + uno::Sequence< uno::Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() ); + uno::Reference< XChartType > xFormerChartType; + + for( sal_Int32 nT = 0; !bFound && nT < aChartTypeList.getLength(); ++nT ) + { + uno::Reference< XChartType > xCurrentChartType( aChartTypeList[nT] ); + + //iterate through all series in this chart type + uno::Reference< XDataSeriesContainer > xDataSeriesContainer( xCurrentChartType, uno::UNO_QUERY ); + OSL_ASSERT( xDataSeriesContainer.is()); + if( !xDataSeriesContainer.is() ) + continue; + + uno::Sequence< uno::Reference< XDataSeries > > aSeriesList( xDataSeriesContainer->getDataSeries() ); + + for( sal_Int32 nS = 0; !bFound && nS < aSeriesList.getLength(); ++nS ) + { + + // We found the series we are interrested in ! + if( xGivenDataSeries==aSeriesList[nS] ) + { + sal_Int32 nOldSeriesIndex = nS; + bFound = true; + + try + { + sal_Int32 nNewSeriesIndex = nS; + + if( bForward ) + nNewSeriesIndex--; + else + nNewSeriesIndex++; + + + if( nNewSeriesIndex >= 0 && nNewSeriesIndex < aSeriesList.getLength() ) + { + //move series in the same charttype + bMovedOrMoveAllowed = true; + if( bDoMove ) + { + aSeriesList[ nOldSeriesIndex ] = aSeriesList[ nNewSeriesIndex ]; + aSeriesList[ nNewSeriesIndex ] = xGivenDataSeries; + xDataSeriesContainer->setDataSeries( aSeriesList ); + } + } + else if( nNewSeriesIndex<0 ) + { + //exchange series with former charttype + if( xFormerChartType.is() && DiagramHelper::areChartTypesCompatible( xFormerChartType, xCurrentChartType ) ) + { + bMovedOrMoveAllowed = true; + if( bDoMove ) + { + uno::Reference< XDataSeriesContainer > xOtherDataSeriesContainer( xFormerChartType, uno::UNO_QUERY ); + if( xOtherDataSeriesContainer.is() ) + { + uno::Sequence< uno::Reference< XDataSeries > > aOtherSeriesList( xOtherDataSeriesContainer->getDataSeries() ); + sal_Int32 nOtherSeriesIndex = aOtherSeriesList.getLength()-1; + if( nOtherSeriesIndex >= 0 && nOtherSeriesIndex < aOtherSeriesList.getLength() ) + { + uno::Reference< XDataSeries > xExchangeSeries( aOtherSeriesList[nOtherSeriesIndex] ); + aOtherSeriesList[nOtherSeriesIndex] = xGivenDataSeries; + xOtherDataSeriesContainer->setDataSeries(aOtherSeriesList); + + aSeriesList[nOldSeriesIndex]=xExchangeSeries; + xDataSeriesContainer->setDataSeries(aSeriesList); + } + } + } + } + } + else if( nT+1 < aChartTypeList.getLength() ) + { + //exchange series with next charttype + uno::Reference< XChartType > xOtherChartType( aChartTypeList[nT+1] ); + if( xOtherChartType.is() && DiagramHelper::areChartTypesCompatible( xOtherChartType, xCurrentChartType ) ) + { + bMovedOrMoveAllowed = true; + if( bDoMove ) + { + uno::Reference< XDataSeriesContainer > xOtherDataSeriesContainer( xOtherChartType, uno::UNO_QUERY ); + if( xOtherDataSeriesContainer.is() ) + { + uno::Sequence< uno::Reference< XDataSeries > > aOtherSeriesList( xOtherDataSeriesContainer->getDataSeries() ); + sal_Int32 nOtherSeriesIndex = 0; + if( nOtherSeriesIndex >= 0 && nOtherSeriesIndex < aOtherSeriesList.getLength() ) + { + uno::Reference< XDataSeries > xExchangeSeries( aOtherSeriesList[nOtherSeriesIndex] ); + aOtherSeriesList[nOtherSeriesIndex] = xGivenDataSeries; + xOtherDataSeriesContainer->setDataSeries(aOtherSeriesList); + + aSeriesList[nOldSeriesIndex]=xExchangeSeries; + xDataSeriesContainer->setDataSeries(aSeriesList); + } + } + } + } + } + } + catch( util::CloseVetoException& ) + { + } + catch( uno::RuntimeException& ) + { + } + } + } + xFormerChartType = xCurrentChartType; + } + } + } + } + catch( util::CloseVetoException& ) + { + } + catch( uno::RuntimeException& ) + { + } + return bMovedOrMoveAllowed; +} +} // anonymous namespace + + +bool DiagramHelper::isSeriesMoveable( + const Reference< XDiagram >& xDiagram, + const Reference< XDataSeries >& xGivenDataSeries, + bool bForward ) +{ + bool bIsMoveable = false; + const bool bDoMove = false; + + bIsMoveable = lcl_moveSeriesOrCheckIfMoveIsAllowed( + xDiagram, xGivenDataSeries, bForward, bDoMove ); + + return bIsMoveable; +} + + +bool DiagramHelper::moveSeries( const Reference< XDiagram >& xDiagram, const Reference< XDataSeries >& xGivenDataSeries, bool bForward ) +{ + bool bMoved = false; + const bool bDoMove = true; + + bMoved = lcl_moveSeriesOrCheckIfMoveIsAllowed( + xDiagram, xGivenDataSeries, bForward, bDoMove ); + + return bMoved; +} + +bool DiagramHelper::isSupportingFloorAndWall( const Reference< + chart2::XDiagram >& xDiagram ) +{ + //pies and donuts currently do not support this because of wrong files from older versions + //todo: allow this in future again, if fileversion are available for ole objects (metastream) + //thus the wrong bottom can be removed on import + + Sequence< Reference< chart2::XChartType > > aTypes( + ::chart::DiagramHelper::getChartTypesFromDiagram( xDiagram ) ); + for( sal_Int32 nN = 0; nN < aTypes.getLength(); nN++ ) + { + Reference< chart2::XChartType > xType( aTypes[nN] ); + if( xType.is() && xType->getChartType().match(CHART2_SERVICE_NAME_CHARTTYPE_PIE) ) + return false; + if( xType.is() && xType->getChartType().match(CHART2_SERVICE_NAME_CHARTTYPE_NET) ) + return false; + if( xType.is() && xType->getChartType().match(CHART2_SERVICE_NAME_CHARTTYPE_FILLED_NET) ) + return false; + } + return true; +} + +bool DiagramHelper::isPieOrDonutChart( const ::com::sun::star::uno::Reference< + ::com::sun::star::chart2::XDiagram >& xDiagram ) +{ + uno::Reference< chart2::XChartType > xChartType( DiagramHelper::getChartTypeByIndex( + xDiagram, 0 ) ); + + if( xChartType .is() ) + { + rtl::OUString aChartType = xChartType->getChartType(); + if( aChartType.equals(CHART2_SERVICE_NAME_CHARTTYPE_PIE) ) + return true; + } + return false; +} + +// static +sal_Int32 DiagramHelper::getGeometry3D( + const uno::Reference< chart2::XDiagram > & xDiagram, + bool& rbFound, bool& rbAmbiguous ) +{ + sal_Int32 nCommonGeom( DataPointGeometry3D::CUBOID ); + rbFound = false; + rbAmbiguous = false; + + ::std::vector< Reference< chart2::XDataSeries > > aSeriesVec( + DiagramHelper::getDataSeriesFromDiagram( xDiagram )); + + if( aSeriesVec.empty()) + rbAmbiguous = true; + + for( ::std::vector< Reference< chart2::XDataSeries > >::const_iterator aIt = + aSeriesVec.begin(); aIt != aSeriesVec.end(); ++aIt ) + { + try + { + sal_Int32 nGeom = 0; + Reference< beans::XPropertySet > xProp( *aIt, uno::UNO_QUERY_THROW ); + if( xProp->getPropertyValue( C2U( "Geometry3D" )) >>= nGeom ) + { + if( ! rbFound ) + { + // first series + nCommonGeom = nGeom; + rbFound = true; + } + // further series: compare for uniqueness + else if( nCommonGeom != nGeom ) + { + rbAmbiguous = true; + break; + } + } + } + catch( uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + } + + return nCommonGeom; +} + +// static +void DiagramHelper::setGeometry3D( + const Reference< chart2::XDiagram > & xDiagram, + sal_Int32 nNewGeometry ) +{ + ::std::vector< Reference< chart2::XDataSeries > > aSeriesVec( + DiagramHelper::getDataSeriesFromDiagram( xDiagram )); + + for( ::std::vector< Reference< chart2::XDataSeries > >::const_iterator aIt = + aSeriesVec.begin(); aIt != aSeriesVec.end(); ++aIt ) + { + DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints( + *aIt, C2U( "Geometry3D" ), uno::makeAny( nNewGeometry )); + } +} + +//static +sal_Int32 DiagramHelper::getCorrectedMissingValueTreatment( + const Reference< chart2::XDiagram > & xDiagram, + const Reference< chart2::XChartType >& xChartType ) +{ + sal_Int32 nResult = ::com::sun::star::chart::MissingValueTreatment::LEAVE_GAP; + uno::Sequence < sal_Int32 > aAvailableMissingValueTreatments( + ChartTypeHelper::getSupportedMissingValueTreatments( xChartType ) ); + + uno::Reference< beans::XPropertySet > xDiaProp( xDiagram, uno::UNO_QUERY ); + if( xDiaProp.is() && (xDiaProp->getPropertyValue( C2U( "MissingValueTreatment" ) ) >>= nResult) ) + { + //ensure that the set value is supported by this charttype + for( sal_Int32 nN = 0; nN < aAvailableMissingValueTreatments.getLength(); nN++ ) + if( aAvailableMissingValueTreatments[nN] == nResult ) + return nResult; //ok + } + + //otherwise use the first supported one + if( aAvailableMissingValueTreatments.getLength() ) + { + nResult = aAvailableMissingValueTreatments[0]; + return nResult; + } + + return nResult; +} + +//static +DiagramPositioningMode DiagramHelper::getDiagramPositioningMode( const uno::Reference< + chart2::XDiagram > & xDiagram ) +{ + DiagramPositioningMode eMode = DiagramPositioningMode_AUTO; + uno::Reference< beans::XPropertySet > xDiaProps( xDiagram, uno::UNO_QUERY ); + if( xDiaProps.is() ) + { + RelativePosition aRelPos; + RelativeSize aRelSize; + if( (xDiaProps->getPropertyValue(C2U("RelativePosition")) >>= aRelPos ) && + (xDiaProps->getPropertyValue(C2U("RelativeSize")) >>= aRelSize ) ) + { + bool bPosSizeExcludeAxes=false; + xDiaProps->getPropertyValue(C2U("PosSizeExcludeAxes")) >>= bPosSizeExcludeAxes; + if( bPosSizeExcludeAxes ) + eMode = DiagramPositioningMode_EXCLUDING; + else + eMode = DiagramPositioningMode_INCLUDING; + } + } + return eMode; +} + +void lcl_ensureRange0to1( double& rValue ) +{ + if(rValue<0.0) + rValue=0.0; + if(rValue>1.0) + rValue=1.0; +} + +//static +bool DiagramHelper::setDiagramPositioning( const uno::Reference< frame::XModel >& xChartModel, + const awt::Rectangle& rPosRect /*100th mm*/ ) +{ + ControllerLockGuard aCtrlLockGuard( xChartModel ); + + bool bChanged = false; + awt::Size aPageSize( ChartModelHelper::getPageSize(xChartModel) ); + uno::Reference< beans::XPropertySet > xDiaProps( ChartModelHelper::findDiagram( xChartModel ), uno::UNO_QUERY ); + if( !xDiaProps.is() ) + return bChanged; + + RelativePosition aOldPos; + RelativeSize aOldSize; + xDiaProps->getPropertyValue(C2U("RelativePosition") ) >>= aOldPos; + xDiaProps->getPropertyValue(C2U("RelativeSize") ) >>= aOldSize; + + RelativePosition aNewPos; + aNewPos.Anchor = drawing::Alignment_TOP_LEFT; + aNewPos.Primary = double(rPosRect.X)/double(aPageSize.Width); + aNewPos.Secondary = double(rPosRect.Y)/double(aPageSize.Height); + + chart2::RelativeSize aNewSize; + aNewSize.Primary = double(rPosRect.Width)/double(aPageSize.Width); + aNewSize.Secondary = double(rPosRect.Height)/double(aPageSize.Height); + + lcl_ensureRange0to1( aNewPos.Primary ); + lcl_ensureRange0to1( aNewPos.Secondary ); + lcl_ensureRange0to1( aNewSize.Primary ); + lcl_ensureRange0to1( aNewSize.Secondary ); + if( (aNewPos.Primary + aNewSize.Primary) > 1.0 ) + aNewPos.Primary = 1.0 - aNewSize.Primary; + if( (aNewPos.Secondary + aNewSize.Secondary) > 1.0 ) + aNewPos.Secondary = 1.0 - aNewSize.Secondary; + + xDiaProps->setPropertyValue( C2U( "RelativePosition" ), uno::makeAny(aNewPos) ); + xDiaProps->setPropertyValue( C2U( "RelativeSize" ), uno::makeAny(aNewSize) ); + + bChanged = (aOldPos.Anchor!=aNewPos.Anchor) || + (aOldPos.Primary!=aNewPos.Primary) || + (aOldPos.Secondary!=aNewPos.Secondary) || + (aOldSize.Primary!=aNewSize.Primary) || + (aOldSize.Secondary!=aNewSize.Secondary); + return bChanged; +} + +//static +awt::Rectangle DiagramHelper::getDiagramRectangleFromModel( const uno::Reference< frame::XModel >& xChartModel ) +{ + awt::Rectangle aRet(-1,-1,-1,-1); + + uno::Reference< beans::XPropertySet > xDiaProps( ChartModelHelper::findDiagram( xChartModel ), uno::UNO_QUERY ); + if( !xDiaProps.is() ) + return aRet; + + awt::Size aPageSize( ChartModelHelper::getPageSize(xChartModel) ); + + RelativePosition aRelPos; + RelativeSize aRelSize; + xDiaProps->getPropertyValue(C2U("RelativePosition") ) >>= aRelPos; + xDiaProps->getPropertyValue(C2U("RelativeSize") ) >>= aRelSize; + + awt::Size aAbsSize( + aRelSize.Primary * aPageSize.Width, + aRelSize.Secondary * aPageSize.Height ); + + awt::Point aAbsPos( + static_cast< sal_Int32 >( aRelPos.Primary * aPageSize.Width ), + static_cast< sal_Int32 >( aRelPos.Secondary * aPageSize.Height )); + + awt::Point aAbsPosLeftTop = RelativePositionHelper::getUpperLeftCornerOfAnchoredObject( aAbsPos, aAbsSize, aRelPos.Anchor ); + + aRet = awt::Rectangle(aAbsPosLeftTop.X, aAbsPosLeftTop.Y, aAbsSize.Width, aAbsSize.Height ); + + return aRet; +} + +//static +bool DiagramHelper::switchDiagramPositioningToExcludingPositioning( + const uno::Reference< frame::XModel >& xChartModel + , bool bResetModifiedState, bool bConvertAlsoFromAutoPositioning ) +{ + //return true if something was changed + const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() ); + if( nCurrentODFVersion == SvtSaveOptions::ODFVER_LATEST )//#i100778# todo: change this dependent on fileformat evolution + { + uno::Reference< ::com::sun::star::chart::XChartDocument > xOldDoc( xChartModel, uno::UNO_QUERY ) ; + if( xOldDoc.is() ) + { + uno::Reference< ::com::sun::star::chart::XDiagramPositioning > xDiagramPositioning( xOldDoc->getDiagram(), uno::UNO_QUERY ); + if( xDiagramPositioning.is() && ( bConvertAlsoFromAutoPositioning || !xDiagramPositioning->isAutomaticDiagramPositioning() ) + && !xDiagramPositioning->isExcludingDiagramPositioning() ) + { + ControllerLockGuard aCtrlLockGuard( xChartModel ); + uno::Reference< util::XModifiable > xModifiable( xChartModel, uno::UNO_QUERY ); + bool bModelWasModified = xModifiable.is() && xModifiable->isModified(); + xDiagramPositioning->setDiagramPositionExcludingAxes( xDiagramPositioning->calculateDiagramPositionExcludingAxes() ); + if(bResetModifiedState && !bModelWasModified && xModifiable.is() ) + xModifiable->setModified(sal_False); + return true; + } + } + } + return false; +} + +} // namespace chart diff --git a/chart2/source/tools/ErrorBar.cxx b/chart2/source/tools/ErrorBar.cxx new file mode 100644 index 000000000000..7468d8bb7896 --- /dev/null +++ b/chart2/source/tools/ErrorBar.cxx @@ -0,0 +1,363 @@ +/************************************************************************* + * + * 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 "ErrorBar.hxx" +#include "macros.hxx" +#include "LineProperties.hxx" +#include "ContainerHelper.hxx" +#include "EventListenerHelper.hxx" +#include "PropertyHelper.hxx" +#include "CloneHelper.hxx" + +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/chart/ErrorBarStyle.hpp> + +#include <rtl/math.hxx> +#include <rtl/ustrbuf.hxx> + +using namespace ::com::sun::star; + +using ::rtl::OUString; +using ::rtl::OUStringBuffer; +using ::com::sun::star::beans::Property; +using ::osl::MutexGuard; + +namespace +{ +static const OUString lcl_aServiceName( + RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.chart2.ErrorBar" )); + +enum +{ + PROP_ERROR_BAR_STYLE, + PROP_ERROR_BAR_POS_ERROR, + PROP_ERROR_BAR_NEG_ERROR, + PROP_ERROR_BAR_WEIGHT, + PROP_ERROR_BAR_SHOW_POS_ERROR, + PROP_ERROR_BAR_SHOW_NEG_ERROR +}; + +void lcl_AddPropertiesToVector( + ::std::vector< Property > & rOutProperties ) +{ + rOutProperties.push_back( + Property( C2U( "ErrorBarStyle" ), + PROP_ERROR_BAR_STYLE, + ::getCppuType( reinterpret_cast< sal_Int32 * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); + + rOutProperties.push_back( + Property( C2U( "PositiveError" ), + PROP_ERROR_BAR_POS_ERROR, + ::getCppuType( reinterpret_cast< const double * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); + rOutProperties.push_back( + Property( C2U( "NegativeError" ), + PROP_ERROR_BAR_NEG_ERROR, + ::getCppuType( reinterpret_cast< const double * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); + + rOutProperties.push_back( + Property( C2U( "Weight" ), + PROP_ERROR_BAR_WEIGHT, + ::getCppuType( reinterpret_cast< const double * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); + + rOutProperties.push_back( + Property( C2U( "ShowPositiveError" ), + PROP_ERROR_BAR_SHOW_POS_ERROR, + ::getBooleanCppuType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); + rOutProperties.push_back( + Property( C2U( "ShowNegativeError" ), + PROP_ERROR_BAR_SHOW_NEG_ERROR, + ::getBooleanCppuType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); +} + +void lcl_AddDefaultsToMap( + ::chart::tPropertyValueMap & rOutMap ) +{ + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_ERROR_BAR_STYLE, ::com::sun::star::chart::ErrorBarStyle::NONE ); + ::chart::PropertyHelper::setPropertyValueDefault< double >( rOutMap, PROP_ERROR_BAR_POS_ERROR, 0.0 ); + ::chart::PropertyHelper::setPropertyValueDefault< double >( rOutMap, PROP_ERROR_BAR_NEG_ERROR, 0.0 ); + ::chart::PropertyHelper::setPropertyValueDefault< double >( rOutMap, PROP_ERROR_BAR_WEIGHT, 1.0 ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_ERROR_BAR_SHOW_POS_ERROR, true ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_ERROR_BAR_SHOW_NEG_ERROR, true ); +} + +const uno::Sequence< Property > & lcl_GetPropertySequence() +{ + static uno::Sequence< Property > aPropSeq; + + // /-- + MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if( 0 == aPropSeq.getLength() ) + { + // get properties + ::std::vector< ::com::sun::star::beans::Property > aProperties; + lcl_AddPropertiesToVector( aProperties ); + ::chart::LineProperties::AddPropertiesToVector( aProperties ); + + // and sort them for access via bsearch + ::std::sort( aProperties.begin(), aProperties.end(), + ::chart::PropertyNameLess() ); + + // transfer result to static Sequence + aPropSeq = ::chart::ContainerHelper::ContainerToSequence( aProperties ); + } + + return aPropSeq; +} + +::cppu::IPropertyArrayHelper & lcl_getInfoHelper() +{ + static ::cppu::OPropertyArrayHelper aArrayHelper( + lcl_GetPropertySequence(), + /* bSorted = */ sal_True ); + + return aArrayHelper; +} + +bool lcl_isInternalData( const uno::Reference< chart2::data::XLabeledDataSequence > & xLSeq ) +{ + uno::Reference< lang::XServiceInfo > xServiceInfo( xLSeq, uno::UNO_QUERY ); + return ( xServiceInfo.is() && xServiceInfo->getImplementationName().equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM("com.sun.star.comp.chart2.LabeledDataSequence"))); +} + +} // anonymous namespace + +namespace chart +{ + +uno::Reference< beans::XPropertySet > createErrorBar( const uno::Reference< uno::XComponentContext > & xContext ) +{ + return new ErrorBar( xContext ); +} + +ErrorBar::ErrorBar( + uno::Reference< uno::XComponentContext > const & xContext ) : + ::property::OPropertySet( m_aMutex ), + m_xContext( xContext ), + m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()) +{} + +ErrorBar::ErrorBar( const ErrorBar & rOther ) : + MutexContainer(), + impl::ErrorBar_Base(), + ::property::OPropertySet( rOther, m_aMutex ), + m_xContext( rOther.m_xContext ), + m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()) +{ + if( ! rOther.m_aDataSequences.empty()) + { + if( lcl_isInternalData( rOther.m_aDataSequences.front())) + CloneHelper::CloneRefVector< tDataSequenceContainer::value_type >( + rOther.m_aDataSequences, m_aDataSequences ); + else + m_aDataSequences = rOther.m_aDataSequences; + ModifyListenerHelper::addListenerToAllElements( m_aDataSequences, m_xModifyEventForwarder ); + } +} + +ErrorBar::~ErrorBar() +{} + +uno::Reference< util::XCloneable > SAL_CALL ErrorBar::createClone() + throw (uno::RuntimeException) +{ + return uno::Reference< util::XCloneable >( new ErrorBar( *this )); +} + +// ================================================================================ + +// ____ OPropertySet ____ +uno::Any ErrorBar::GetDefaultValue( sal_Int32 nHandle ) const + throw(beans::UnknownPropertyException) +{ + static tPropertyValueMap aStaticDefaults; + + // /-- + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if( 0 == aStaticDefaults.size() ) + { + // initialize defaults + lcl_AddDefaultsToMap( aStaticDefaults ); + LineProperties::AddDefaultsToMap( aStaticDefaults ); + } + + tPropertyValueMap::const_iterator aFound( + aStaticDefaults.find( nHandle )); + + if( aFound == aStaticDefaults.end()) + return uno::Any(); + + return (*aFound).second; + // \-- +} + +::cppu::IPropertyArrayHelper & SAL_CALL ErrorBar::getInfoHelper() +{ + return lcl_getInfoHelper(); +} + + +// ____ XPropertySet ____ +uno::Reference< beans::XPropertySetInfo > SAL_CALL + ErrorBar::getPropertySetInfo() + throw (uno::RuntimeException) +{ + static uno::Reference< beans::XPropertySetInfo > xInfo; + + // /-- + MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if( !xInfo.is()) + { + xInfo = ::cppu::OPropertySetHelper::createPropertySetInfo( + getInfoHelper()); + } + + return xInfo; + // \-- +} + +// ____ XModifyBroadcaster ____ +void SAL_CALL ErrorBar::addModifyListener( const uno::Reference< util::XModifyListener >& aListener ) + throw (uno::RuntimeException) +{ + try + { + uno::Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW ); + xBroadcaster->addModifyListener( aListener ); + } + catch( const uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } +} + +void SAL_CALL ErrorBar::removeModifyListener( const uno::Reference< util::XModifyListener >& aListener ) + throw (uno::RuntimeException) +{ + try + { + uno::Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW ); + xBroadcaster->removeModifyListener( aListener ); + } + catch( const uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } +} + +// ____ XModifyListener ____ +void SAL_CALL ErrorBar::modified( const lang::EventObject& aEvent ) + throw (uno::RuntimeException) +{ + m_xModifyEventForwarder->modified( aEvent ); +} + +// ____ XEventListener (base of XModifyListener) ____ +void SAL_CALL ErrorBar::disposing( const lang::EventObject& /* Source */ ) + throw (uno::RuntimeException) +{ + // nothing +} + +// ____ XDataSink ____ +void SAL_CALL ErrorBar::setData( const uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > >& aData ) + throw (uno::RuntimeException) +{ + ModifyListenerHelper::removeListenerFromAllElements( m_aDataSequences, m_xModifyEventForwarder ); + EventListenerHelper::removeListenerFromAllElements( m_aDataSequences, this ); + m_aDataSequences = ContainerHelper::SequenceToVector( aData ); + EventListenerHelper::addListenerToAllElements( m_aDataSequences, this ); + ModifyListenerHelper::addListenerToAllElements( m_aDataSequences, m_xModifyEventForwarder ); +} + +// ____ XDataSource ____ +uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > SAL_CALL ErrorBar::getDataSequences() + throw (uno::RuntimeException) +{ + return ContainerHelper::ContainerToSequence( m_aDataSequences ); +} + +// ____ XChild ____ +uno::Reference< uno::XInterface > SAL_CALL ErrorBar::getParent() + throw (uno::RuntimeException) +{ + return m_xParent; +} + +void SAL_CALL ErrorBar::setParent( + const uno::Reference< uno::XInterface >& Parent ) + throw (lang::NoSupportException, + uno::RuntimeException) +{ + m_xParent.set( Parent ); +} + +// ____ OPropertySet ____ +void ErrorBar::firePropertyChangeEvent() +{ + fireModifyEvent(); +} + +void ErrorBar::fireModifyEvent() +{ + m_xModifyEventForwarder->modified( lang::EventObject( static_cast< uno::XWeak* >( this ))); +} + +// ================================================================================ + +uno::Sequence< ::rtl::OUString > ErrorBar::getSupportedServiceNames_Static() +{ + uno::Sequence< ::rtl::OUString > aServices( 2 ); + aServices[ 0 ] = lcl_aServiceName; + aServices[ 1 ] = C2U( "com.sun.star.chart2.ErrorBar" ); + return aServices; +} + +// implement XServiceInfo methods basing upon getSupportedServiceNames_Static +APPHELPER_XSERVICEINFO_IMPL( ErrorBar, lcl_aServiceName ); + +// needed by MSC compiler +using impl::ErrorBar_Base; + +IMPLEMENT_FORWARD_XINTERFACE2( ErrorBar, ErrorBar_Base, OPropertySet ) +IMPLEMENT_FORWARD_XTYPEPROVIDER2( ErrorBar, ErrorBar_Base, OPropertySet ) + +} // namespace chart diff --git a/chart2/source/tools/ExplicitCategoriesProvider.cxx b/chart2/source/tools/ExplicitCategoriesProvider.cxx new file mode 100644 index 000000000000..bd1c1bb79813 --- /dev/null +++ b/chart2/source/tools/ExplicitCategoriesProvider.cxx @@ -0,0 +1,422 @@ +/************************************************************************* + * + * 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 "ExplicitCategoriesProvider.hxx" +#include "DiagramHelper.hxx" +#include "CommonConverters.hxx" +#include "DataSourceHelper.hxx" +#include "ChartModelHelper.hxx" +#include "ContainerHelper.hxx" +#include "macros.hxx" + +//............................................................................. +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; +using ::rtl::OUString; +using ::std::vector; + + +ExplicitCategoriesProvider::ExplicitCategoriesProvider( const Reference< chart2::XCoordinateSystem >& xCooSysModel + , const uno::Reference< frame::XModel >& xChartModel ) + : m_bDirty(true) + , m_xCooSysModel( xCooSysModel ) + , m_xOriginalCategories() +{ + try + { + if( xCooSysModel.is() ) + { + uno::Reference< XAxis > xAxis( xCooSysModel->getAxisByDimension(0,0) ); + if( xAxis.is() ) + m_xOriginalCategories = xAxis->getScaleData().Categories; + } + + if( m_xOriginalCategories.is() ) + { + Reference< chart2::XChartDocument > xChartDoc( xChartModel, uno::UNO_QUERY ); + if( xChartDoc.is() ) + { + uno::Reference< data::XDataProvider > xDataProvider( xChartDoc->getDataProvider() ); + + if( xDataProvider.is() ) + { + OUString aCatgoriesRange( DataSourceHelper::getRangeFromValues( m_xOriginalCategories ) ); + const bool bFirstCellAsLabel = false; + const bool bHasCategories = false; + const uno::Sequence< sal_Int32 > aSequenceMapping; + + uno::Reference< data::XDataSource > xColumnCategoriesSource( xDataProvider->createDataSource( + DataSourceHelper::createArguments( aCatgoriesRange, aSequenceMapping, true /*bUseColumns*/ + , bFirstCellAsLabel, bHasCategories ) ) ); + + uno::Reference< data::XDataSource > xRowCategoriesSource( xDataProvider->createDataSource( + DataSourceHelper::createArguments( aCatgoriesRange, aSequenceMapping, false /*bUseColumns*/ + , bFirstCellAsLabel, bHasCategories ) ) ); + + if( xColumnCategoriesSource.is() && xRowCategoriesSource.is() ) + { + Sequence< Reference< data::XLabeledDataSequence> > aColumns = xColumnCategoriesSource->getDataSequences(); + Sequence< Reference< data::XLabeledDataSequence> > aRows = xRowCategoriesSource->getDataSequences(); + + sal_Int32 nColumnCount = aColumns.getLength(); + sal_Int32 nRowCount = aRows.getLength(); + if( nColumnCount>1 && nRowCount>1 ) + { + //we have complex categories + //->split them in the direction of the first series + //detect whether the first series is a row or a column + bool bSeriesUsesColumns = true; + ::std::vector< Reference< XDataSeries > > aSeries( ChartModelHelper::getDataSeries( xChartModel ) ); + if( !aSeries.empty() ) + { + uno::Reference< data::XDataSource > xSeriesSource( aSeries.front(), uno::UNO_QUERY ); + ::rtl::OUString aStringDummy; + bool bDummy; + uno::Sequence< sal_Int32 > aSeqDummy; + DataSourceHelper::readArguments( xDataProvider->detectArguments( xSeriesSource), + aStringDummy, aSeqDummy, bSeriesUsesColumns, bDummy, bDummy ); + } + if( bSeriesUsesColumns ) + m_aSplitCategoriesList=aColumns; + else + m_aSplitCategoriesList=aRows; + } + } + } + } + if( !m_aSplitCategoriesList.getLength() ) + { + m_aSplitCategoriesList.realloc(1); + m_aSplitCategoriesList[0]=m_xOriginalCategories; + } + } + } + catch( const uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } +} + +ExplicitCategoriesProvider::~ExplicitCategoriesProvider() +{ +} + +const Sequence< Reference< data::XLabeledDataSequence> >& ExplicitCategoriesProvider::getSplitCategoriesList() +{ + return m_aSplitCategoriesList; +} + +bool ExplicitCategoriesProvider::hasComplexCategories() const +{ + return m_aSplitCategoriesList.getLength() > 1; +} + +sal_Int32 ExplicitCategoriesProvider::getCategoryLevelCount() const +{ + sal_Int32 nCount = m_aSplitCategoriesList.getLength(); + if(!nCount) + nCount = 1; + return nCount; +} + +std::vector<sal_Int32> lcl_getLimitingBorders( const std::vector< ComplexCategory >& rComplexCategories ) +{ + std::vector<sal_Int32> aLimitingBorders; + std::vector< ComplexCategory >::const_iterator aIt( rComplexCategories.begin() ); + std::vector< ComplexCategory >::const_iterator aEnd( rComplexCategories.end() ); + sal_Int32 nBorderIndex = 0; /*border below the index*/ + for( ; aIt != aEnd; ++aIt ) + { + ComplexCategory aComplexCategory(*aIt); + nBorderIndex += aComplexCategory.Count; + aLimitingBorders.push_back(nBorderIndex); + } + return aLimitingBorders; +} + +uno::Sequence< rtl::OUString > lcl_DataToStringSequence( const uno::Reference< data::XDataSequence >& xDataSequence ) +{ + uno::Sequence< rtl::OUString > aStrings; + + OSL_ASSERT( xDataSequence.is()); + if( !xDataSequence.is() ) + return aStrings; + + + uno::Reference< data::XTextualDataSequence > xTextualDataSequence( xDataSequence, uno::UNO_QUERY ); + if( xTextualDataSequence.is() ) + { + aStrings = xTextualDataSequence->getTextualData(); + } + else + { + uno::Sequence< uno::Any > aValues = xDataSequence->getData(); + aStrings.realloc(aValues.getLength()); + + for(sal_Int32 nN=aValues.getLength();nN--;) + aValues[nN] >>= aStrings[nN]; + } + + return aStrings; +} + +SplitCategoriesProvider::~SplitCategoriesProvider() +{ +} + +class SplitCategoriesProvider_ForLabeledDataSequences : public SplitCategoriesProvider +{ +public: + + explicit SplitCategoriesProvider_ForLabeledDataSequences( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< + ::com::sun::star::chart2::data::XLabeledDataSequence> >& rSplitCategoriesList ) + : m_rSplitCategoriesList( rSplitCategoriesList ) + {} + virtual ~SplitCategoriesProvider_ForLabeledDataSequences() + {} + + virtual sal_Int32 getLevelCount() const; + virtual uno::Sequence< rtl::OUString > getStringsForLevel( sal_Int32 nIndex ) const; + +private: + const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< + ::com::sun::star::chart2::data::XLabeledDataSequence> >& m_rSplitCategoriesList; +}; + +sal_Int32 SplitCategoriesProvider_ForLabeledDataSequences::getLevelCount() const +{ + return m_rSplitCategoriesList.getLength(); +} +uno::Sequence< rtl::OUString > SplitCategoriesProvider_ForLabeledDataSequences::getStringsForLevel( sal_Int32 nLevel ) const +{ + uno::Sequence< rtl::OUString > aRet; + Reference< data::XLabeledDataSequence > xLabeledDataSequence( m_rSplitCategoriesList[nLevel] ); + if( xLabeledDataSequence.is() ) + aRet = lcl_DataToStringSequence( xLabeledDataSequence->getValues() ); + return aRet; +} + +std::vector< ComplexCategory > lcl_DataSequenceToComplexCategoryVector( + const uno::Sequence< rtl::OUString >& rStrings + , const std::vector<sal_Int32>& rLimitingBorders, bool bCreateSingleCategories ) +{ + std::vector< ComplexCategory > aResult; + + sal_Int32 nMaxCount = rStrings.getLength(); + OUString aPrevious; + sal_Int32 nCurrentCount=0; + for( sal_Int32 nN=0; nN<nMaxCount; nN++ ) + { + OUString aCurrent = rStrings[nN]; + if( bCreateSingleCategories || ::std::find( rLimitingBorders.begin(), rLimitingBorders.end(), nN ) != rLimitingBorders.end() ) + { + aResult.push_back( ComplexCategory(aPrevious,nCurrentCount) ); + nCurrentCount=1; + aPrevious = aCurrent; + } + else + { + if( aCurrent.getLength() && aPrevious != aCurrent ) + { + aResult.push_back( ComplexCategory(aPrevious,nCurrentCount) ); + nCurrentCount=1; + aPrevious = aCurrent; + } + else + nCurrentCount++; + } + } + if( nCurrentCount ) + aResult.push_back( ComplexCategory(aPrevious,nCurrentCount) ); + + return aResult; +} + +sal_Int32 lcl_getCategoryCount( std::vector< ComplexCategory >& rComplexCategories ) +{ + sal_Int32 nCount = 0; + std::vector< ComplexCategory >::iterator aIt( rComplexCategories.begin() ); + std::vector< ComplexCategory >::const_iterator aEnd( rComplexCategories.end() ); + for( ; aIt != aEnd; ++aIt ) + nCount+=aIt->Count; + return nCount; +} + +Sequence< OUString > lcl_getExplicitSimpleCategories( + const SplitCategoriesProvider& rSplitCategoriesProvider, + ::std::vector< ::std::vector< ComplexCategory > >& rComplexCats ) +{ + Sequence< OUString > aRet; + + rComplexCats.clear(); + sal_Int32 nLCount = rSplitCategoriesProvider.getLevelCount(); + for( sal_Int32 nL = 0; nL < nLCount; nL++ ) + { + std::vector<sal_Int32> aLimitingBorders; + if(nL>0) + aLimitingBorders = lcl_getLimitingBorders( rComplexCats.back() ); + rComplexCats.push_back( lcl_DataSequenceToComplexCategoryVector( + rSplitCategoriesProvider.getStringsForLevel(nL), aLimitingBorders, nL==(nLCount-1) ) ); + } + + std::vector< std::vector< ComplexCategory > >::iterator aOuterIt( rComplexCats.begin() ); + std::vector< std::vector< ComplexCategory > >::const_iterator aOuterEnd( rComplexCats.end() ); + + //ensure that the category count is the same on each level + sal_Int32 nMaxCategoryCount = 0; + { + for( aOuterIt=rComplexCats.begin(); aOuterIt != aOuterEnd; ++aOuterIt ) + { + sal_Int32 nCurrentCount = lcl_getCategoryCount( *aOuterIt ); + nMaxCategoryCount = std::max( nCurrentCount, nMaxCategoryCount ); + } + for( aOuterIt=rComplexCats.begin(); aOuterIt != aOuterEnd; ++aOuterIt ) + { + sal_Int32 nCurrentCount = lcl_getCategoryCount( *aOuterIt ); + if( nCurrentCount< nMaxCategoryCount ) + { + ComplexCategory& rComplexCategory = aOuterIt->back(); + rComplexCategory.Count += (nMaxCategoryCount-nCurrentCount); + } + } + } + + //create a list with an element for every index + std::vector< std::vector< ComplexCategory > > aComplexCatsPerIndex; + for( aOuterIt=rComplexCats.begin() ; aOuterIt != aOuterEnd; ++aOuterIt ) + { + std::vector< ComplexCategory > aSingleLevel; + std::vector< ComplexCategory >::iterator aIt( aOuterIt->begin() ); + std::vector< ComplexCategory >::const_iterator aEnd( aOuterIt->end() ); + for( ; aIt != aEnd; ++aIt ) + { + ComplexCategory aComplexCategory( *aIt ); + sal_Int32 nCount = aComplexCategory.Count; + while( nCount-- ) + aSingleLevel.push_back(aComplexCategory); + } + aComplexCatsPerIndex.push_back( aSingleLevel ); + } + + if(nMaxCategoryCount) + { + aRet.realloc(nMaxCategoryCount); + aOuterEnd = aComplexCatsPerIndex.end(); + OUString aSpace(C2U(" ")); + for(sal_Int32 nN=0; nN<nMaxCategoryCount; nN++) + { + OUString aText; + for( aOuterIt=aComplexCatsPerIndex.begin() ; aOuterIt != aOuterEnd; ++aOuterIt ) + { + OUString aAddText = (*aOuterIt)[nN].Text; + if( aAddText.getLength() ) + { + if(aText.getLength()) + aText += aSpace; + aText += aAddText; + } + } + aRet[nN]=aText; + } + } + return aRet; +} + +//static +Sequence< OUString > ExplicitCategoriesProvider::getExplicitSimpleCategories( + const SplitCategoriesProvider& rSplitCategoriesProvider ) +{ + vector< vector< ComplexCategory > > aComplexCats; + return lcl_getExplicitSimpleCategories( rSplitCategoriesProvider, aComplexCats ); +} + +void ExplicitCategoriesProvider::init() +{ + if( m_bDirty ) + { + m_aExplicitCategories.realloc(0); + m_aComplexCats.clear();//not one per index + + if( m_xOriginalCategories.is() ) + { + if( !hasComplexCategories() ) + m_aExplicitCategories = DataSequenceToStringSequence(m_xOriginalCategories->getValues()); + else + m_aExplicitCategories = lcl_getExplicitSimpleCategories( + SplitCategoriesProvider_ForLabeledDataSequences( m_aSplitCategoriesList ), m_aComplexCats ); + } + if(!m_aExplicitCategories.getLength()) + m_aExplicitCategories = DiagramHelper::generateAutomaticCategoriesFromCooSys( m_xCooSysModel ); + m_bDirty = false; + } +} + + +Sequence< ::rtl::OUString > ExplicitCategoriesProvider::getSimpleCategories() +{ + init(); + return m_aExplicitCategories; +} + +std::vector< ComplexCategory > ExplicitCategoriesProvider::getCategoriesByLevel( sal_Int32 nLevel ) +{ + std::vector< ComplexCategory > aRet; + init(); + sal_Int32 nMaxIndex = m_aComplexCats.size()-1; + if( nLevel >= 0 && nLevel <= nMaxIndex ) + aRet = m_aComplexCats[nMaxIndex-nLevel]; + return aRet; +} + +// static +OUString ExplicitCategoriesProvider::getCategoryByIndex( + const Reference< XCoordinateSystem >& xCooSysModel + , const uno::Reference< frame::XModel >& xChartModel + , sal_Int32 nIndex ) +{ + if( xCooSysModel.is()) + { + ExplicitCategoriesProvider aExplicitCategoriesProvider( xCooSysModel, xChartModel ); + Sequence< OUString > aCategories( aExplicitCategoriesProvider.getSimpleCategories()); + if( nIndex < aCategories.getLength()) + return aCategories[ nIndex ]; + } + return OUString(); +} + +//............................................................................. +} //namespace chart +//............................................................................. diff --git a/chart2/source/tools/ExponentialRegressionCurveCalculator.cxx b/chart2/source/tools/ExponentialRegressionCurveCalculator.cxx new file mode 100644 index 000000000000..d7bb86174323 --- /dev/null +++ b/chart2/source/tools/ExponentialRegressionCurveCalculator.cxx @@ -0,0 +1,183 @@ +/************************************************************************* + * + * 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 "ExponentialRegressionCurveCalculator.hxx" +#include "macros.hxx" +#include "RegressionCalculationHelper.hxx" + +#include <rtl/math.hxx> +#include <rtl/ustrbuf.hxx> + +using namespace ::com::sun::star; + +using ::rtl::OUString; +using ::rtl::OUStringBuffer; + +namespace chart +{ + +ExponentialRegressionCurveCalculator::ExponentialRegressionCurveCalculator() : + m_fSlope( 0.0 ), + m_fIntercept( 0.0 ) +{ + ::rtl::math::setNan( & m_fSlope ); + ::rtl::math::setNan( & m_fIntercept ); +} + +ExponentialRegressionCurveCalculator::~ExponentialRegressionCurveCalculator() +{} + +// ____ XRegressionCurveCalculator ____ +void SAL_CALL ExponentialRegressionCurveCalculator::recalculateRegression( + const uno::Sequence< double >& aXValues, + const uno::Sequence< double >& aYValues ) + throw (uno::RuntimeException) +{ + RegressionCalculationHelper::tDoubleVectorPair aValues( + RegressionCalculationHelper::cleanup( + aXValues, aYValues, + RegressionCalculationHelper::isValidAndYPositive())); + + const size_t nMax = aValues.first.size(); + if( nMax == 0 ) + { + ::rtl::math::setNan( & m_fSlope ); + ::rtl::math::setNan( & m_fIntercept ); + ::rtl::math::setNan( & m_fCorrelationCoeffitient ); + return; + } + + double fAverageX = 0.0, fAverageY = 0.0; + size_t i = 0; + for( i = 0; i < nMax; ++i ) + { + fAverageX += aValues.first[i]; + fAverageY += log( aValues.second[i] ); + } + + const double fN = static_cast< double >( nMax ); + fAverageX /= fN; + fAverageY /= fN; + + double fQx = 0.0, fQy = 0.0, fQxy = 0.0; + for( i = 0; i < nMax; ++i ) + { + double fDeltaX = aValues.first[i] - fAverageX; + double fDeltaY = log( aValues.second[i] ) - fAverageY; + + fQx += fDeltaX * fDeltaX; + fQy += fDeltaY * fDeltaY; + fQxy += fDeltaX * fDeltaY; + } + + m_fSlope = fQxy / fQx; + m_fIntercept = fAverageY - m_fSlope * fAverageX; + m_fCorrelationCoeffitient = fQxy / sqrt( fQx * fQy ); + + m_fSlope = exp( m_fSlope ); + m_fIntercept = exp( m_fIntercept ); +} + +double SAL_CALL ExponentialRegressionCurveCalculator::getCurveValue( double x ) + throw (lang::IllegalArgumentException, + uno::RuntimeException) +{ + double fResult; + ::rtl::math::setNan( & fResult ); + + if( ! ( ::rtl::math::isNan( m_fSlope ) || + ::rtl::math::isNan( m_fIntercept ))) + { + fResult = m_fIntercept * pow( m_fSlope, x ); + } + + return fResult; +} + +uno::Sequence< geometry::RealPoint2D > SAL_CALL ExponentialRegressionCurveCalculator::getCurveValues( + double min, double max, ::sal_Int32 nPointCount, + const uno::Reference< chart2::XScaling >& xScalingX, + const uno::Reference< chart2::XScaling >& xScalingY, + ::sal_Bool bMaySkipPointsInCalculation ) + throw (lang::IllegalArgumentException, + uno::RuntimeException) +{ + if( bMaySkipPointsInCalculation && + isLinearScaling( xScalingX ) && + isLogarithmicScaling( xScalingY )) + { + // optimize result + uno::Sequence< geometry::RealPoint2D > aResult( 2 ); + aResult[0].X = min; + aResult[0].Y = this->getCurveValue( min ); + aResult[1].X = max; + aResult[1].Y = this->getCurveValue( max ); + + return aResult; + } + + return RegressionCurveCalculator::getCurveValues( min, max, nPointCount, xScalingX, xScalingY, bMaySkipPointsInCalculation ); +} + + +OUString ExponentialRegressionCurveCalculator::ImplGetRepresentation( + const uno::Reference< util::XNumberFormatter >& xNumFormatter, + ::sal_Int32 nNumberFormatKey ) const +{ + OUStringBuffer aBuf( C2U( "f(x) = " )); + + if( m_fIntercept == 0.0 || + m_fSlope == 0.0 ) + { + aBuf.append( sal_Unicode( '0' )); + } + else if( rtl::math::approxEqual( m_fSlope, 1.0 ) ) + { + aBuf.append( getFormattedString( xNumFormatter, nNumberFormatKey, m_fIntercept )); + } + else + { + if( ! rtl::math::approxEqual( m_fIntercept, 1.0 ) ) + { + aBuf.append( getFormattedString( xNumFormatter, nNumberFormatKey, m_fIntercept )); + aBuf.append( sal_Unicode( 0x00b7 )); + } + + if( m_fSlope < 0.0 ) + aBuf.append( sal_Unicode( '(' )); + aBuf.append( getFormattedString( xNumFormatter, nNumberFormatKey, m_fSlope )); + if( m_fSlope < 0.0 ) + aBuf.append( sal_Unicode( ')' )); + aBuf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "^x" )); + } + + return aBuf.makeStringAndClear(); +} + +} // namespace chart diff --git a/chart2/source/tools/FillProperties.cxx b/chart2/source/tools/FillProperties.cxx new file mode 100644 index 000000000000..ee23727c321b --- /dev/null +++ b/chart2/source/tools/FillProperties.cxx @@ -0,0 +1,277 @@ +/************************************************************************* + * + * 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 "FillProperties.hxx" +#include "macros.hxx" +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/drawing/BitmapMode.hpp> +#include <com/sun/star/drawing/FillStyle.hpp> +#include <com/sun/star/drawing/RectanglePoint.hpp> + +using namespace ::com::sun::star; + +using ::com::sun::star::beans::Property; + +namespace chart +{ + +namespace +{ + +void lcl_AddPropertiesToVector_without_BitmapProperties( ::std::vector< ::com::sun::star::beans::Property > & rOutProperties ) +{ + rOutProperties.push_back( + Property( C2U( "FillStyle" ), + FillProperties::PROP_FILL_STYLE, + ::getCppuType( reinterpret_cast< const drawing::FillStyle * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); + + rOutProperties.push_back( + Property( C2U( "FillColor" ), + FillProperties::PROP_FILL_COLOR, + ::getCppuType( reinterpret_cast< const sal_Int32 * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID // "maybe auto" + | beans::PropertyAttribute::MAYBEDEFAULT )); + + rOutProperties.push_back( + Property( C2U( "FillTransparence" ), + FillProperties::PROP_FILL_TRANSPARENCE, + ::getCppuType( reinterpret_cast< const sal_Int16 * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); + + rOutProperties.push_back( + Property( C2U( "FillTransparenceGradientName" ), + FillProperties::PROP_FILL_TRANSPARENCE_GRADIENT_NAME, + ::getCppuType( reinterpret_cast< const ::rtl::OUString * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT )); + + //optional +// rOutProperties.push_back( +// Property( C2U( "FillTransparenceGradient" ), +// FillProperties::PROP_FILL_TRANSPARENCE_GRADIENT, +// ::getCppuType( reinterpret_cast< const awt::Gradient * >(0)), +// beans::PropertyAttribute::BOUND +// | beans::PropertyAttribute::MAYBEDEFAULT +// | beans::PropertyAttribute::MAYBEVOID )); + + rOutProperties.push_back( + Property( C2U( "FillGradientName" ), + FillProperties::PROP_FILL_GRADIENT_NAME, + ::getCppuType( reinterpret_cast< const ::rtl::OUString * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT )); + + rOutProperties.push_back( + beans::Property( C2U( "FillGradientStepCount" ), + FillProperties::PROP_FILL_GRADIENT_STEPCOUNT, + ::getCppuType( reinterpret_cast< const sal_Int16 * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID )); + + //optional +// rOutProperties.push_back( +// Property( C2U( "FillGradient" ), +// FillProperties::PROP_FILL_GRADIENT, +// ::getCppuType( reinterpret_cast< const awt::Gradient * >(0)), +// beans::PropertyAttribute::BOUND +// | beans::PropertyAttribute::MAYBEDEFAULT +// | beans::PropertyAttribute::MAYBEVOID )); + + rOutProperties.push_back( + Property( C2U( "FillHatchName" ), + FillProperties::PROP_FILL_HATCH_NAME, + ::getCppuType( reinterpret_cast< const ::rtl::OUString * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT )); + + //optional +// rOutProperties.push_back( +// Property( C2U( "FillHatch" ), +// FillProperties::PROP_FILL_HATCH, +// ::getCppuType( reinterpret_cast< const drawing::Hatch * >(0)), +// beans::PropertyAttribute::BOUND +// | beans::PropertyAttribute::MAYBEDEFAULT +// | beans::PropertyAttribute::MAYBEVOID )); + + //bitmap properties see lcl_AddPropertiesToVector_only_BitmapProperties() + + rOutProperties.push_back( + Property( C2U( "FillBackground" ), + FillProperties::PROP_FILL_BACKGROUND, + ::getCppuType( reinterpret_cast< const sal_Bool * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); +} + +//static +void lcl_AddPropertiesToVector_only_BitmapProperties( ::std::vector< ::com::sun::star::beans::Property > & rOutProperties ) +{ + rOutProperties.push_back( + Property( C2U( "FillBitmapName" ), + FillProperties::PROP_FILL_BITMAP_NAME, + ::getCppuType( reinterpret_cast< const ::rtl::OUString * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT )); + + //optional +// rOutProperties.push_back( +// Property( C2U( "FillBitmap" ), +// FillProperties::PROP_FILL_BITMAP, +// ::getCppuType( reinterpret_cast< const uno::Reference< awt::XBitmap > * >(0)), +// beans::PropertyAttribute::BOUND +// | beans::PropertyAttribute::MAYBEDEFAULT )); + + //optional +// rOutProperties.push_back( +// Property( C2U( "FillBitmapURL" ), +// FillProperties::PROP_FILL_BITMAP_URL, +// ::getCppuType( reinterpret_cast< const ::rtl::OUString * >(0)), +// beans::PropertyAttribute::BOUND +// | beans::PropertyAttribute::MAYBEDEFAULT )); + + rOutProperties.push_back( + Property( C2U( "FillBitmapOffsetX" ), + FillProperties::PROP_FILL_BITMAP_OFFSETX, + ::getCppuType( reinterpret_cast< const sal_Int16 * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); + + rOutProperties.push_back( + Property( C2U( "FillBitmapOffsetY" ), + FillProperties::PROP_FILL_BITMAP_OFFSETY, + ::getCppuType( reinterpret_cast< const sal_Int16 * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); + + rOutProperties.push_back( + Property( C2U( "FillBitmapPositionOffsetX" ), + FillProperties::PROP_FILL_BITMAP_POSITION_OFFSETX, + ::getCppuType( reinterpret_cast< const sal_Int16 * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); + + rOutProperties.push_back( + Property( C2U( "FillBitmapPositionOffsetY" ), + FillProperties::PROP_FILL_BITMAP_POSITION_OFFSETY, + ::getCppuType( reinterpret_cast< const sal_Int16 * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); + + + rOutProperties.push_back( + Property( C2U( "FillBitmapRectanglePoint" ), + FillProperties::PROP_FILL_BITMAP_RECTANGLEPOINT, + ::getCppuType( reinterpret_cast< const drawing::RectanglePoint * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); + + rOutProperties.push_back( + Property( C2U( "FillBitmapLogicalSize" ), + FillProperties::PROP_FILL_BITMAP_LOGICALSIZE, + ::getCppuType( reinterpret_cast< const sal_Bool * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); + + rOutProperties.push_back( + Property( C2U( "FillBitmapSizeX" ), + FillProperties::PROP_FILL_BITMAP_SIZEX, + ::getCppuType( reinterpret_cast< const sal_Int32 * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); + + rOutProperties.push_back( + Property( C2U( "FillBitmapSizeY" ), + FillProperties::PROP_FILL_BITMAP_SIZEY, + ::getCppuType( reinterpret_cast< const sal_Int32 * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); + + rOutProperties.push_back( + Property( C2U( "FillBitmapMode" ), + FillProperties::PROP_FILL_BITMAP_MODE, + ::getCppuType( reinterpret_cast< const drawing::BitmapMode * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); +} + + +void lcl_AddDefaultsToMap_without_BitmapProperties( + ::chart::tPropertyValueMap & rOutMap ) +{ + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, FillProperties::PROP_FILL_STYLE, drawing::FillStyle_SOLID ); + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( rOutMap, FillProperties::PROP_FILL_COLOR, 0xd9d9d9 ); // gray85 + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int16 >( rOutMap, FillProperties::PROP_FILL_TRANSPARENCE, 0 ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, FillProperties::PROP_FILL_BACKGROUND, false ); +} + +void lcl_AddDefaultsToMap_only_BitmapProperties( + ::chart::tPropertyValueMap & rOutMap ) +{ + uno::Any aSalInt16Zero = uno::makeAny( sal_Int16( 0 )); + uno::Any aSalInt32SizeDefault = uno::makeAny( sal_Int32( 0 )); + + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int16 >( rOutMap, FillProperties::PROP_FILL_BITMAP_OFFSETX, 0 ); + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int16 >( rOutMap, FillProperties::PROP_FILL_BITMAP_OFFSETY, 0 ); + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int16 >( rOutMap, FillProperties::PROP_FILL_BITMAP_POSITION_OFFSETX, 0 ); + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int16 >( rOutMap, FillProperties::PROP_FILL_BITMAP_POSITION_OFFSETY, 0 ); + + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, FillProperties::PROP_FILL_BITMAP_RECTANGLEPOINT, drawing::RectanglePoint_MIDDLE_MIDDLE ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, FillProperties::PROP_FILL_BITMAP_LOGICALSIZE, true ); + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( rOutMap, FillProperties::PROP_FILL_BITMAP_SIZEX, 0 ); + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( rOutMap, FillProperties::PROP_FILL_BITMAP_SIZEY, 0 ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, FillProperties::PROP_FILL_BITMAP_MODE, drawing::BitmapMode_REPEAT ); +} + +}//end anonymous namespace + +void FillProperties::AddPropertiesToVector( + ::std::vector< Property > & rOutProperties ) +{ + // Fill Properties see service drawing::FillProperties + // --------------- + lcl_AddPropertiesToVector_without_BitmapProperties( rOutProperties ); + lcl_AddPropertiesToVector_only_BitmapProperties( rOutProperties ); +} + +void FillProperties::AddDefaultsToMap( + ::chart::tPropertyValueMap & rOutMap ) +{ + lcl_AddDefaultsToMap_without_BitmapProperties( rOutMap ); + lcl_AddDefaultsToMap_only_BitmapProperties( rOutMap ); +} + +} // namespace chart diff --git a/chart2/source/tools/FormattedStringHelper.cxx b/chart2/source/tools/FormattedStringHelper.cxx new file mode 100644 index 000000000000..c13c87d45931 --- /dev/null +++ b/chart2/source/tools/FormattedStringHelper.cxx @@ -0,0 +1,80 @@ +/************************************************************************* + * + * 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 "FormattedStringHelper.hxx" +#include "macros.hxx" +#include "PropertyHelper.hxx" + +//............................................................................. +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; +using rtl::OUString; + +Sequence< Reference< chart2::XFormattedString > > + FormattedStringHelper::createFormattedStringSequence( + const Reference< uno::XComponentContext > & xContext + , const OUString & rString + , const Reference< beans::XPropertySet > & xTextProperties ) throw() +{ + Reference< XFormattedString > xFormStr; + try + { + if( xContext.is() ) + { + xFormStr.set( + xContext->getServiceManager()->createInstanceWithContext( + C2U("com.sun.star.chart2.FormattedString"), xContext ), + uno::UNO_QUERY_THROW ); + + xFormStr->setString( rString ); + + // set character properties + comphelper::copyProperties( + xTextProperties, Reference< beans::XPropertySet >( xFormStr, uno::UNO_QUERY ) ); + } + } + catch( uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + + return Sequence< Reference< XFormattedString > >( & xFormStr, 1 ); +} + +//............................................................................. +} //namespace chart +//............................................................................. + diff --git a/chart2/source/tools/ImplOPropertySet.cxx b/chart2/source/tools/ImplOPropertySet.cxx new file mode 100644 index 000000000000..faf1defd20ac --- /dev/null +++ b/chart2/source/tools/ImplOPropertySet.cxx @@ -0,0 +1,207 @@ +/************************************************************************* + * + * 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 "ImplOPropertySet.hxx" +#include "CloneHelper.hxx" + +#include <algorithm> +#include <functional> +#include <com/sun/star/beans/XFastPropertySet.hpp> + +using namespace ::com::sun::star; + +using ::rtl::OUString; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Any; + +namespace +{ + +struct lcl_getPropertyStateByHandle : + public ::std::unary_function< sal_Int32, beans::PropertyState > +{ + lcl_getPropertyStateByHandle( + const ::property::impl::ImplOPropertySet::tPropertyMap & rMap ) + : m_rMap( rMap ) + {} + + inline beans::PropertyState operator() ( sal_Int32 nHandle ) + { + if( m_rMap.end() == m_rMap.find( nHandle )) + return beans::PropertyState_DEFAULT_VALUE; + return beans::PropertyState_DIRECT_VALUE; + } + +private: + const ::property::impl::ImplOPropertySet::tPropertyMap & m_rMap; +}; + +template< typename K, typename V > +struct lcl_eraseMapEntry : + public ::std::unary_function< K, void > +{ + lcl_eraseMapEntry( ::std::map< K, V > & rMap ) + : m_rMap( rMap ) + {} + + inline void operator() ( const K & aKey ) + { + m_rMap.erase( aKey ); + } + +private: + ::std::map< K, V > m_rMap; +}; + +struct lcl_replaceInterfacePropertiesByClones : + public ::std::unary_function< ::property::impl::ImplOPropertySet::tPropertyMap::value_type, void > +{ + inline void operator() ( ::property::impl::ImplOPropertySet::tPropertyMap::value_type & rProp ) + { + if( rProp.second.hasValue() && + rProp.second.getValueType().getTypeClass() == uno::TypeClass_INTERFACE ) + { + Reference< util::XCloneable > xCloneable; + if( rProp.second >>= xCloneable ) + rProp.second <<= xCloneable->createClone(); + } + } +}; + +} // anonymous namespace + +namespace property +{ +namespace impl +{ + +ImplOPropertySet::ImplOPropertySet() +{} + +ImplOPropertySet::ImplOPropertySet( const ImplOPropertySet & rOther ) +{ + ::std::copy( rOther.m_aProperties.begin(), rOther.m_aProperties.end(), + ::std::inserter( m_aProperties, m_aProperties.begin() )); + cloneInterfaceProperties(); + m_xStyle.set( ::chart::CloneHelper::CreateRefClone< Reference< style::XStyle > >()( rOther.m_xStyle )); +} + +beans::PropertyState ImplOPropertySet::GetPropertyStateByHandle( sal_Int32 nHandle ) const +{ + return lcl_getPropertyStateByHandle( m_aProperties ) ( nHandle ); +} + +Sequence< beans::PropertyState > ImplOPropertySet::GetPropertyStatesByHandle( + const ::std::vector< sal_Int32 > & aHandles ) const +{ + Sequence< beans::PropertyState > aResult( aHandles.size()); + + ::std::transform( aHandles.begin(), aHandles.end(), + aResult.getArray(), + lcl_getPropertyStateByHandle( m_aProperties )); + + return aResult; +} + +void ImplOPropertySet::SetPropertyToDefault( sal_Int32 nHandle ) +{ + tPropertyMap::iterator aFoundIter( m_aProperties.find( nHandle ) ); + + if( m_aProperties.end() != aFoundIter ) + { + m_aProperties.erase( aFoundIter ); + } +} + +void ImplOPropertySet::SetPropertiesToDefault( + const ::std::vector< sal_Int32 > & aHandles ) +{ + ::std::for_each( aHandles.begin(), aHandles.end(), + lcl_eraseMapEntry< sal_Int32, Any >( m_aProperties ) ); +} + +void ImplOPropertySet::SetAllPropertiesToDefault() +{ + m_aProperties.clear(); +} + +bool ImplOPropertySet::GetPropertyValueByHandle( + Any & rValue, + sal_Int32 nHandle ) const +{ + bool bResult = false; + + tPropertyMap::const_iterator aFoundIter( m_aProperties.find( nHandle ) ); + + if( m_aProperties.end() != aFoundIter ) + { + rValue = (*aFoundIter).second; + bResult = true; + } + + return bResult; +} + +void ImplOPropertySet::SetPropertyValueByHandle( + sal_Int32 nHandle, const Any & rValue, Any * pOldValue ) +{ + if( pOldValue != NULL ) + { + tPropertyMap::const_iterator aFoundIter( m_aProperties.find( nHandle ) ); + if( m_aProperties.end() != aFoundIter ) + (*pOldValue) = (*aFoundIter).second; + } + + m_aProperties[ nHandle ] = rValue; +} + +bool ImplOPropertySet::SetStyle( const Reference< style::XStyle > & xStyle ) +{ + if( ! xStyle.is()) + return false; + + m_xStyle = xStyle; + return true; +} + +Reference< style::XStyle > ImplOPropertySet::GetStyle() const +{ + return m_xStyle; +} + +void ImplOPropertySet::cloneInterfaceProperties() +{ + ::std::for_each( m_aProperties.begin(), m_aProperties.end(), + lcl_replaceInterfacePropertiesByClones()); +} + + +} // namespace impl +} // namespace chart diff --git a/chart2/source/tools/ImplOPropertySet.hxx b/chart2/source/tools/ImplOPropertySet.hxx new file mode 100644 index 000000000000..505ab598d7da --- /dev/null +++ b/chart2/source/tools/ImplOPropertySet.hxx @@ -0,0 +1,96 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ +#ifndef CHART_IMPLOPROPERTYSET_HXX +#define CHART_IMPLOPROPERTYSET_HXX + +#include <com/sun/star/beans/PropertyState.hpp> +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/style/XStyle.hpp> + +#include <map> +#include <vector> + +namespace property +{ +namespace impl +{ + +class ImplOPropertySet +{ +public: + ImplOPropertySet(); + explicit ImplOPropertySet( const ImplOPropertySet & rOther ); + + /** supports states DIRECT_VALUE and DEFAULT_VALUE + */ + ::com::sun::star::beans::PropertyState + GetPropertyStateByHandle( sal_Int32 nHandle ) const; + + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyState > + GetPropertyStatesByHandle( const ::std::vector< sal_Int32 > & aHandles ) const; + + void SetPropertyToDefault( sal_Int32 nHandle ); + void SetPropertiesToDefault( const ::std::vector< sal_Int32 > & aHandles ); + void SetAllPropertiesToDefault(); + + /** @param rValue is set to the value for the property given in nHandle. If + the property is not set, the style chain is searched for any + instance set there. If there was no value found either in the + property set itself or any of its styles, rValue remains + unchanged and false is returned. + + @return false if the property is default, true otherwise. + */ + bool GetPropertyValueByHandle( + ::com::sun::star::uno::Any & rValue, + sal_Int32 nHandle ) const; + + void SetPropertyValueByHandle( sal_Int32 nHandle, + const ::com::sun::star::uno::Any & rValue, + ::com::sun::star::uno::Any * pOldValue = NULL ); + + bool SetStyle( const ::com::sun::star::uno::Reference< ::com::sun::star::style::XStyle > & xStyle ); + ::com::sun::star::uno::Reference< ::com::sun::star::style::XStyle > + GetStyle() const; + + typedef + ::std::map< sal_Int32, ::com::sun::star::uno::Any > + tPropertyMap; + +private: + void cloneInterfaceProperties(); + + tPropertyMap m_aProperties; + ::com::sun::star::uno::Reference< ::com::sun::star::style::XStyle > + m_xStyle; +}; + +} // namespace impl +} // namespace chart + +// CHART_IMPLOPROPERTYSET_HXX +#endif diff --git a/chart2/source/tools/InternalData.cxx b/chart2/source/tools/InternalData.cxx new file mode 100755 index 000000000000..65fc97a04b38 --- /dev/null +++ b/chart2/source/tools/InternalData.cxx @@ -0,0 +1,530 @@ +/************************************************************************* + * + * 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 "InternalData.hxx" +#include "ResId.hxx" +#include "Strings.hrc" +#include "macros.hxx" + +#include <rtl/math.hxx> + +using ::com::sun::star::uno::Sequence; +using ::rtl::OUString; + +using namespace ::std; + +namespace chart +{ + +// ---------------------------------------- +namespace +{ +struct lcl_NumberedStringGenerator +{ + lcl_NumberedStringGenerator( const OUString & rStub, const OUString & rWildcard ) : + m_aStub( rStub ), + m_nCounter( 0 ), + m_nStubStartIndex( rStub.indexOf( rWildcard )), + m_nWildcardLength( rWildcard.getLength()) + { + } + vector< OUString > operator()() + { + vector< OUString > aRet(1); + aRet[0] = m_aStub.replaceAt( m_nStubStartIndex, m_nWildcardLength, OUString::valueOf( ++m_nCounter )); + return aRet; + } +private: + OUString m_aStub; + sal_Int32 m_nCounter; + const sal_Int32 m_nStubStartIndex; + const sal_Int32 m_nWildcardLength; +}; + +template< typename T > + Sequence< T > lcl_ValarrayToSequence( const ::std::valarray< T > & rValarray ) +{ + // is there a more elegant way of conversion? + Sequence< T > aResult( rValarray.size()); + for( size_t i = 0; i < rValarray.size(); ++i ) + aResult[i] = rValarray[i]; + return aResult; +} + +} // anonymous namespace +// ---------------------------------------- + +InternalData::InternalData() + : m_nColumnCount( 0 ) + , m_nRowCount( 0 ) + , m_aRowLabels( 0 ) + , m_aColumnLabels( 0 ) +{} + +void InternalData::createDefaultData() +{ + const sal_Int32 nRowCount = 4; + const sal_Int32 nColumnCount = 3; + + m_nRowCount = nRowCount; + m_nColumnCount = nColumnCount; + const sal_Int32 nSize = nColumnCount * nRowCount; + // @todo: localize this! + const OUString aRowName( ::chart::SchResId::getResString( STR_ROW_LABEL )); + const OUString aColName( ::chart::SchResId::getResString( STR_COLUMN_LABEL )); + + const double fDefaultData[ nSize ] = + { 9.10, 3.20, 4.54, + 2.40, 8.80, 9.65, + 3.10, 1.50, 3.70, + 4.30, 9.02, 6.20 }; + + m_aData.resize( nSize ); + for( sal_Int32 i=0; i<nSize; ++i ) + m_aData[i] = fDefaultData[i]; + + m_aRowLabels.clear(); + m_aRowLabels.reserve( m_nRowCount ); + generate_n( back_inserter( m_aRowLabels ), m_nRowCount, + lcl_NumberedStringGenerator( aRowName, C2U("%ROWNUMBER") )); + + m_aColumnLabels.clear(); + m_aColumnLabels.reserve( m_nColumnCount ); + generate_n( back_inserter( m_aColumnLabels ), m_nColumnCount, + lcl_NumberedStringGenerator( aColName, C2U("%COLUMNNUMBER") )); +} + +void InternalData::setData( const Sequence< Sequence< double > >& rDataInRows ) +{ + m_nRowCount = rDataInRows.getLength(); + m_nColumnCount = (m_nRowCount ? rDataInRows[0].getLength() : 0); + + if( m_aRowLabels.size() != static_cast< sal_uInt32 >( m_nRowCount )) + m_aRowLabels.resize( m_nRowCount ); + if( m_aColumnLabels.size() != static_cast< sal_uInt32 >( m_nColumnCount )) + m_aColumnLabels.resize( m_nColumnCount ); + + m_aData.resize( m_nRowCount * m_nColumnCount ); + double fNan; + ::rtl::math::setNan( & fNan ); + // set all values to Nan + m_aData = fNan; + + for( sal_Int32 nRow=0; nRow<m_nRowCount; ++nRow ) + { + int nDataIdx = nRow*m_nColumnCount; + const sal_Int32 nMax = ::std::min( rDataInRows[nRow].getLength(), m_nColumnCount ); + for( sal_Int32 nCol=0; nCol < nMax; ++nCol ) + { + m_aData[nDataIdx] = rDataInRows[nRow][nCol]; + nDataIdx += 1; + } + } +} + +Sequence< Sequence< double > > InternalData::getData() const +{ + Sequence< Sequence< double > > aResult( m_nRowCount ); + + for( sal_Int32 i=0; i<m_nRowCount; ++i ) + aResult[i] = lcl_ValarrayToSequence< tDataType::value_type >( + m_aData[ ::std::slice( i*m_nColumnCount, m_nColumnCount, 1 ) ] ); + + return aResult; +} + +Sequence< double > InternalData::getColumnValues( sal_Int32 nColumnIndex ) const +{ + if( nColumnIndex >= 0 && nColumnIndex < m_nColumnCount ) + return lcl_ValarrayToSequence< tDataType::value_type >( + m_aData[ ::std::slice( nColumnIndex, m_nRowCount, m_nColumnCount ) ] ); + return Sequence< double >(); +} +Sequence< double > InternalData::getRowValues( sal_Int32 nRowIndex ) const +{ + if( nRowIndex >= 0 && nRowIndex < m_nRowCount ) + return lcl_ValarrayToSequence< tDataType::value_type >( + m_aData[ ::std::slice( nRowIndex*m_nColumnCount, m_nColumnCount, 1 ) ] ); + return Sequence< double >(); +} + +void InternalData::setColumnValues( sal_Int32 nColumnIndex, const vector< double > & rNewData ) +{ + if( nColumnIndex < 0 ) + return; + enlargeData( nColumnIndex + 1, rNewData.size() ); + + tDataType aSlice = m_aData[ ::std::slice( nColumnIndex, m_nRowCount, m_nColumnCount ) ]; + for( vector< double >::size_type i = 0; i < rNewData.size(); ++i ) + aSlice[i] = rNewData[i]; + m_aData[ ::std::slice( nColumnIndex, m_nRowCount, m_nColumnCount ) ] = aSlice; +} + +void InternalData::setRowValues( sal_Int32 nRowIndex, const vector< double > & rNewData ) +{ + if( nRowIndex < 0 ) + return; + enlargeData( rNewData.size(), nRowIndex+1 ); + + tDataType aSlice = m_aData[ ::std::slice( nRowIndex*m_nColumnCount, m_nColumnCount, 1 ) ]; + for( vector< double >::size_type i = 0; i < rNewData.size(); ++i ) + aSlice[i] = rNewData[i]; + m_aData[ ::std::slice( nRowIndex*m_nColumnCount, m_nColumnCount, 1 ) ]= aSlice; +} + +void InternalData::setComplexColumnLabel( sal_Int32 nColumnIndex, const vector< OUString >& rComplexLabel ) +{ + if( nColumnIndex < 0 ) + return; + if( nColumnIndex >= static_cast< sal_Int32 >( m_aColumnLabels.size() ) ) + { + m_aColumnLabels.resize(nColumnIndex+1); + enlargeData( nColumnIndex+1, 0 ); + } + + m_aColumnLabels[nColumnIndex]=rComplexLabel; +} +void InternalData::setComplexRowLabel( sal_Int32 nRowIndex, const vector< OUString >& rComplexLabel ) +{ + if( nRowIndex < 0 ) + return; + if( nRowIndex >= static_cast< sal_Int32 >( m_aRowLabels.size() ) ) + { + m_aRowLabels.resize(nRowIndex+1); + enlargeData( 0, nRowIndex+1 ); + } + + m_aRowLabels[nRowIndex] = rComplexLabel; +} + +vector< OUString > InternalData::getComplexColumnLabel( sal_Int32 nColumnIndex ) const +{ + if( nColumnIndex < static_cast< sal_Int32 >( m_aColumnLabels.size() ) ) + return m_aColumnLabels[nColumnIndex]; + else + return vector< OUString >(); +} +vector< OUString > InternalData::getComplexRowLabel( sal_Int32 nRowIndex ) const +{ + if( nRowIndex < static_cast< sal_Int32 >( m_aRowLabels.size() ) ) + return m_aRowLabels[nRowIndex]; + else + return vector< OUString >(); +} + +void InternalData::swapRowWithNext( sal_Int32 nRowIndex ) +{ + if( nRowIndex < m_nRowCount - 1 ) + { + const sal_Int32 nMax = m_nColumnCount; + for( sal_Int32 nColIdx=0; nColIdx<nMax; ++nColIdx ) + { + size_t nIndex1 = nColIdx + nRowIndex*m_nColumnCount; + size_t nIndex2 = nIndex1 + m_nColumnCount; + double fTemp = m_aData[nIndex1]; + m_aData[nIndex1] = m_aData[nIndex2]; + m_aData[nIndex2] = fTemp; + } + + vector< OUString > aTemp( m_aRowLabels[nRowIndex] ); + m_aRowLabels[nRowIndex] = m_aRowLabels[nRowIndex + 1]; + m_aRowLabels[nRowIndex + 1] = aTemp; + } +} + +void InternalData::swapColumnWithNext( sal_Int32 nColumnIndex ) +{ + if( nColumnIndex < m_nColumnCount - 1 ) + { + const sal_Int32 nMax = m_nRowCount; + for( sal_Int32 nRowIdx=0; nRowIdx<nMax; ++nRowIdx ) + { + size_t nIndex1 = nColumnIndex + nRowIdx*m_nColumnCount; + size_t nIndex2 = nIndex1 + 1; + double fTemp = m_aData[nIndex1]; + m_aData[nIndex1] = m_aData[nIndex2]; + m_aData[nIndex2] = fTemp; + } + + vector< OUString > aTemp( m_aColumnLabels[nColumnIndex] ); + m_aColumnLabels[nColumnIndex] = m_aColumnLabels[nColumnIndex + 1]; + m_aColumnLabels[nColumnIndex + 1] = aTemp; + } +} + +bool InternalData::enlargeData( sal_Int32 nColumnCount, sal_Int32 nRowCount ) +{ + sal_Int32 nNewColumnCount( ::std::max<sal_Int32>( m_nColumnCount, nColumnCount ) ); + sal_Int32 nNewRowCount( ::std::max<sal_Int32>( m_nRowCount, nRowCount ) ); + sal_Int32 nNewSize( nNewColumnCount*nNewRowCount ); + + bool bGrow = (nNewSize > m_nColumnCount*m_nRowCount); + + if( bGrow ) + { + double fNan; + ::rtl::math::setNan( &fNan ); + tDataType aNewData( fNan, nNewSize ); + // copy old data + for( int nCol=0; nCol<m_nColumnCount; ++nCol ) + static_cast< tDataType >( + aNewData[ ::std::slice( nCol, m_nRowCount, nNewColumnCount ) ] ) = + m_aData[ ::std::slice( nCol, m_nRowCount, m_nColumnCount ) ]; + + m_aData.resize( nNewSize ); + m_aData = aNewData; + } + m_nColumnCount = nNewColumnCount; + m_nRowCount = nNewRowCount; + return bGrow; +} + +void InternalData::insertColumn( sal_Int32 nAfterIndex ) +{ + // note: -1 is allowed, as we insert after the given index + OSL_ASSERT( nAfterIndex < m_nColumnCount && nAfterIndex >= -1 ); + if( nAfterIndex >= m_nColumnCount || nAfterIndex < -1 ) + return; + sal_Int32 nNewColumnCount = m_nColumnCount + 1; + sal_Int32 nNewSize( nNewColumnCount * m_nRowCount ); + + double fNan; + ::rtl::math::setNan( &fNan ); + tDataType aNewData( fNan, nNewSize ); + + // copy old data + int nCol=0; + for( ; nCol<=nAfterIndex; ++nCol ) + aNewData[ ::std::slice( nCol, m_nRowCount, nNewColumnCount ) ] = + static_cast< tDataType >( + m_aData[ ::std::slice( nCol, m_nRowCount, m_nColumnCount ) ] ); + for( ++nCol; nCol<nNewColumnCount; ++nCol ) + aNewData[ ::std::slice( nCol, m_nRowCount, nNewColumnCount ) ] = + static_cast< tDataType >( + m_aData[ ::std::slice( nCol - 1, m_nRowCount, m_nColumnCount ) ] ); + + m_nColumnCount = nNewColumnCount; + m_aData.resize( nNewSize ); + m_aData = aNewData; + + // labels + if( nAfterIndex < static_cast< sal_Int32 >( m_aColumnLabels.size())) + m_aColumnLabels.insert( m_aColumnLabels.begin() + (nAfterIndex + 1), vector< OUString >(1) ); + +#if OSL_DEBUG_LEVEL > 2 + traceData(); +#endif +} + +sal_Int32 InternalData::appendColumn() +{ + insertColumn( getColumnCount() - 1 ); + return getColumnCount() - 1; +} + +sal_Int32 InternalData::appendRow() +{ + insertRow( getRowCount() - 1 ); + return getRowCount() - 1; +} + +void InternalData::insertRow( sal_Int32 nAfterIndex ) +{ + // note: -1 is allowed, as we insert after the given index + OSL_ASSERT( nAfterIndex < m_nRowCount && nAfterIndex >= -1 ); + if( nAfterIndex >= m_nRowCount || nAfterIndex < -1 ) + return; + sal_Int32 nNewRowCount = m_nRowCount + 1; + sal_Int32 nNewSize( m_nColumnCount * nNewRowCount ); + + double fNan; + ::rtl::math::setNan( &fNan ); + tDataType aNewData( fNan, nNewSize ); + + // copy old data + sal_Int32 nIndex = nAfterIndex + 1; + aNewData[ ::std::slice( 0, nIndex * m_nColumnCount, 1 ) ] = + static_cast< tDataType >( + m_aData[ ::std::slice( 0, nIndex * m_nColumnCount, 1 ) ] ); + + if( nIndex < m_nRowCount ) + { + sal_Int32 nRemainingCount = m_nColumnCount * (m_nRowCount - nIndex); + aNewData[ ::std::slice( (nIndex + 1) * m_nColumnCount, nRemainingCount, 1 ) ] = + static_cast< tDataType >( + m_aData[ ::std::slice( nIndex * m_nColumnCount, nRemainingCount, 1 ) ] ); + } + + m_nRowCount = nNewRowCount; + m_aData.resize( nNewSize ); + m_aData = aNewData; + + // labels + if( nAfterIndex < static_cast< sal_Int32 >( m_aRowLabels.size())) + m_aRowLabels.insert( m_aRowLabels.begin() + nIndex, vector< OUString> (1)); + +#if OSL_DEBUG_LEVEL > 2 + traceData(); +#endif +} + +void InternalData::deleteColumn( sal_Int32 nAtIndex ) +{ + OSL_ASSERT( nAtIndex < m_nColumnCount && nAtIndex >= 0 ); + if( nAtIndex >= m_nColumnCount || m_nColumnCount < 1 || nAtIndex < 0 ) + return; + sal_Int32 nNewColumnCount = m_nColumnCount - 1; + sal_Int32 nNewSize( nNewColumnCount * m_nRowCount ); + + double fNan; + ::rtl::math::setNan( &fNan ); + tDataType aNewData( fNan, nNewSize ); + + // copy old data + int nCol=0; + for( ; nCol<nAtIndex; ++nCol ) + aNewData[ ::std::slice( nCol, m_nRowCount, nNewColumnCount ) ] = + static_cast< tDataType >( + m_aData[ ::std::slice( nCol, m_nRowCount, m_nColumnCount ) ] ); + for( ; nCol<nNewColumnCount; ++nCol ) + aNewData[ ::std::slice( nCol, m_nRowCount, nNewColumnCount ) ] = + static_cast< tDataType >( + m_aData[ ::std::slice( nCol + 1, m_nRowCount, m_nColumnCount ) ] ); + + m_nColumnCount = nNewColumnCount; + m_aData.resize( nNewSize ); + m_aData = aNewData; + + // labels + if( nAtIndex < static_cast< sal_Int32 >( m_aColumnLabels.size())) + m_aColumnLabels.erase( m_aColumnLabels.begin() + nAtIndex ); + +#if OSL_DEBUG_LEVEL > 2 + traceData(); +#endif +} + +void InternalData::deleteRow( sal_Int32 nAtIndex ) +{ + OSL_ASSERT( nAtIndex < m_nRowCount && nAtIndex >= 0 ); + if( nAtIndex >= m_nRowCount || m_nRowCount < 1 || nAtIndex < 0 ) + return; + sal_Int32 nNewRowCount = m_nRowCount - 1; + sal_Int32 nNewSize( m_nColumnCount * nNewRowCount ); + + double fNan; + ::rtl::math::setNan( &fNan ); + tDataType aNewData( fNan, nNewSize ); + + // copy old data + sal_Int32 nIndex = nAtIndex; + if( nIndex ) + aNewData[ ::std::slice( 0, nIndex * m_nColumnCount, 1 ) ] = + static_cast< tDataType >( + m_aData[ ::std::slice( 0, nIndex * m_nColumnCount, 1 ) ] ); + + if( nIndex < nNewRowCount ) + { + sal_Int32 nRemainingCount = m_nColumnCount * (nNewRowCount - nIndex); + aNewData[ ::std::slice( nIndex * m_nColumnCount, nRemainingCount, 1 ) ] = + static_cast< tDataType >( + m_aData[ ::std::slice( (nIndex + 1) * m_nColumnCount, nRemainingCount, 1 ) ] ); + } + + m_nRowCount = nNewRowCount; + m_aData.resize( nNewSize ); + m_aData = aNewData; + + // labels + if( nAtIndex < static_cast< sal_Int32 >( m_aRowLabels.size())) + m_aRowLabels.erase( m_aRowLabels.begin() + nAtIndex ); + +#if OSL_DEBUG_LEVEL > 2 + traceData(); +#endif +} + +sal_Int32 InternalData::getRowCount() const +{ + return m_nRowCount; +} + +sal_Int32 InternalData::getColumnCount() const +{ + return m_nColumnCount; +} + +void InternalData::setComplexRowLabels( const vector< vector< OUString > >& rNewRowLabels ) +{ + m_aRowLabels = rNewRowLabels; + sal_Int32 nNewRowCount = static_cast< sal_Int32 >( m_aRowLabels.size() ); + if( nNewRowCount < m_nRowCount ) + m_aRowLabels.resize( m_nRowCount ); + else + enlargeData( 0, nNewRowCount ); +} + +vector< vector< OUString > > InternalData::getComplexRowLabels() const +{ + return m_aRowLabels; +} + +void InternalData::setComplexColumnLabels( const vector< vector< OUString > >& rNewColumnLabels ) +{ + m_aColumnLabels = rNewColumnLabels; + sal_Int32 nNewColumnCount = static_cast< sal_Int32 >( m_aColumnLabels.size() ); + if( nNewColumnCount < m_nColumnCount ) + m_aColumnLabels.resize( m_nColumnCount ); + else + enlargeData( nNewColumnCount, 0 ); +} + +vector< vector< OUString > > InternalData::getComplexColumnLabels() const +{ + return m_aColumnLabels; +} + +#if OSL_DEBUG_LEVEL > 2 +void InternalData::traceData() const +{ + OSL_TRACE( "InternalData: Data in rows\n" ); + + for( sal_Int32 i=0; i<m_nRowCount; ++i ) + { + tDataType aSlice( m_aData[ ::std::slice( i*m_nColumnCount, m_nColumnCount, 1 ) ] ); + for( sal_Int32 j=0; j<m_nColumnCount; ++j ) + OSL_TRACE( "%lf ", aSlice[j] ); + OSL_TRACE( "\n" ); + } + OSL_TRACE( "\n" ); +} +#endif + +} // namespace chart diff --git a/chart2/source/tools/InternalDataProvider.cxx b/chart2/source/tools/InternalDataProvider.cxx new file mode 100644 index 000000000000..4abc51be31af --- /dev/null +++ b/chart2/source/tools/InternalDataProvider.cxx @@ -0,0 +1,1314 @@ +/************************************************************************* + * + * 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 <rtl/math.hxx> + +#include <valarray> + +#include "InternalDataProvider.hxx" +#include "LabeledDataSequence.hxx" +#include "DataSource.hxx" +#include "PropertyHelper.hxx" +#include "macros.hxx" +#include "XMLRangeHelper.hxx" +#include "ContainerHelper.hxx" +#include "CommonConverters.hxx" +#include "CommonFunctors.hxx" +#include "UncachedDataSequence.hxx" +#include "DataSourceHelper.hxx" +#include "ChartModelHelper.hxx" +#include "DiagramHelper.hxx" +#include "ExplicitCategoriesProvider.hxx" + +#include <com/sun/star/chart2/XChartDocument.hpp> +#include <com/sun/star/chart2/data/XDataSequence.hpp> +#include <com/sun/star/chart/ChartDataRowSource.hpp> +#include <rtl/ustrbuf.hxx> +#include <unotools/charclass.hxx> +#include <comphelper/sequenceashashmap.hxx> + +#include <vector> +#include <algorithm> + +using namespace ::com::sun::star; +using namespace ::std; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::rtl::OUString; +using ::rtl::OUStringBuffer; + +namespace chart +{ + +// ================================================================================ + +namespace +{ + +// note: in xmloff this name is used to indicate usage of own data +static const ::rtl::OUString lcl_aServiceName( + RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.chart.InternalDataProvider" )); + +static const ::rtl::OUString lcl_aCategoriesRangeName( + RTL_CONSTASCII_USTRINGPARAM( "categories" )); +static const ::rtl::OUString lcl_aCategoriesLevelRangeNamePrefix( + RTL_CONSTASCII_USTRINGPARAM( "categoriesL " )); //L <-> level +static const ::rtl::OUString lcl_aCategoriesPointRangeNamePrefix( + RTL_CONSTASCII_USTRINGPARAM( "categoriesP " )); //P <-> point +static const ::rtl::OUString lcl_aCategoriesRoleName( + RTL_CONSTASCII_USTRINGPARAM( "categories" )); +static const ::rtl::OUString lcl_aLabelRangePrefix( + RTL_CONSTASCII_USTRINGPARAM( "label " )); +static const ::rtl::OUString lcl_aCompleteRange( + RTL_CONSTASCII_USTRINGPARAM( "all" )); + +typedef ::std::multimap< OUString, uno::WeakReference< chart2::data::XDataSequence > > + lcl_tSequenceMap; + +struct lcl_setModified : public ::std::unary_function< lcl_tSequenceMap, void > +{ + void operator() ( const lcl_tSequenceMap::value_type & rMapEntry ) + { + // convert weak reference to reference + Reference< chart2::data::XDataSequence > xSeq( rMapEntry.second ); + if( xSeq.is()) + { + Reference< util::XModifiable > xMod( xSeq, uno::UNO_QUERY ); + if( xMod.is()) + xMod->setModified( sal_True ); + } + } +}; + +struct lcl_internalizeSeries : public ::std::unary_function< Reference< chart2::XDataSeries >, void > +{ + lcl_internalizeSeries( InternalData & rInternalData, + InternalDataProvider & rProvider, + bool bConnectToModel, bool bDataInColumns ) : + m_rInternalData( rInternalData ), + m_rProvider( rProvider ), + m_bConnectToModel( bConnectToModel ), + m_bDataInColumns( bDataInColumns ) + {} + void operator() ( const Reference< chart2::XDataSeries > & xSeries ) + { + Reference< chart2::data::XDataSource > xSource( xSeries, uno::UNO_QUERY ); + Reference< chart2::data::XDataSink > xSink( xSeries, uno::UNO_QUERY ); + if( xSource.is() && xSink.is() ) + { + Sequence< Reference< chart2::data::XLabeledDataSequence > > aOldSeriesData = xSource->getDataSequences(); + Sequence< Reference< chart2::data::XLabeledDataSequence > > aNewSeriesData( aOldSeriesData.getLength() ); + for( sal_Int32 i=0; i<aOldSeriesData.getLength(); ++i ) + { + sal_Int32 nNewIndex( m_bDataInColumns ? m_rInternalData.appendColumn() : m_rInternalData.appendRow() ); + OUString aIdentifier( OUString::valueOf( nNewIndex )); + //@todo: deal also with genericXDataSequence + Reference< chart2::data::XNumericalDataSequence > xValues( aOldSeriesData[i]->getValues(), uno::UNO_QUERY ); + Reference< chart2::data::XTextualDataSequence > xLabel( aOldSeriesData[i]->getLabel(), uno::UNO_QUERY ); + Reference< chart2::data::XDataSequence > xNewValues; + + if( xValues.is() ) + { + ::std::vector< double > aValues( ContainerHelper::SequenceToVector( xValues->getNumericalData())); + if( m_bDataInColumns ) + m_rInternalData.setColumnValues( nNewIndex, aValues ); + else + m_rInternalData.setRowValues( nNewIndex, aValues ); + if( m_bConnectToModel ) + { + xNewValues.set( m_rProvider.createDataSequenceByRangeRepresentation( aIdentifier )); + comphelper::copyProperties( + Reference< beans::XPropertySet >( xValues, uno::UNO_QUERY ), + Reference< beans::XPropertySet >( xNewValues, uno::UNO_QUERY )); + } + } + + if( xLabel.is() ) + { + if( m_bDataInColumns ) + m_rInternalData.setComplexColumnLabel( nNewIndex, ContainerHelper::SequenceToVector( xLabel->getTextualData() ) ); + else + m_rInternalData.setComplexRowLabel( nNewIndex, ContainerHelper::SequenceToVector( xLabel->getTextualData() ) ); + if( m_bConnectToModel ) + { + Reference< chart2::data::XDataSequence > xNewLabel( + m_rProvider.createDataSequenceByRangeRepresentation( lcl_aLabelRangePrefix + aIdentifier )); + comphelper::copyProperties( + Reference< beans::XPropertySet >( xLabel, uno::UNO_QUERY ), + Reference< beans::XPropertySet >( xNewLabel, uno::UNO_QUERY )); + aNewSeriesData[i] = Reference< chart2::data::XLabeledDataSequence >( + new LabeledDataSequence( xNewValues, xNewLabel )); + } + } + else + { + if( m_bConnectToModel ) + aNewSeriesData[i] = Reference< chart2::data::XLabeledDataSequence >( + new LabeledDataSequence( xNewValues )); + } + } + if( m_bConnectToModel ) + xSink->setData( aNewSeriesData ); + } + } + +private: + InternalData & m_rInternalData; + InternalDataProvider & m_rProvider; + bool m_bConnectToModel; + bool m_bDataInColumns; +}; + +struct lcl_makeAnyFromLevelVector : public ::std::unary_function< vector< OUString >, uno::Any > +{ +public: + + explicit lcl_makeAnyFromLevelVector( sal_Int32 nLevel ) : m_nLevel( nLevel ) + {} + + uno::Any operator() ( const vector< OUString >& rVector ) + { + OUString aString; + if( m_nLevel < static_cast< sal_Int32 >(rVector.size()) ) + aString = rVector[m_nLevel]; + return uno::makeAny( aString ); + } + +private: + sal_Int32 m_nLevel; +}; + +struct lcl_getStringFromLevelVector : public ::std::unary_function< vector< OUString >, OUString > +{ +public: + + explicit lcl_getStringFromLevelVector( sal_Int32 nLevel ) : m_nLevel( nLevel ) + {} + + OUString operator() ( const vector< OUString >& rVector ) + { + OUString aString; + if( m_nLevel < static_cast< sal_Int32 >(rVector.size()) ) + aString = rVector[m_nLevel]; + return aString; + } + +private: + sal_Int32 m_nLevel; +}; + + +struct lcl_setStringAtLevel : public ::std::binary_function< vector< OUString >, OUString, vector< OUString > > +{ +public: + + explicit lcl_setStringAtLevel( sal_Int32 nLevel ) : m_nLevel( nLevel ) + {} + + vector< OUString > operator() ( const vector< OUString >& rVector, const OUString& rNewText ) + { + vector< OUString > aRet( rVector ); + if( m_nLevel >= static_cast< sal_Int32 >(aRet.size()) ) + aRet.resize( m_nLevel+1 ); + aRet[ m_nLevel ]=rNewText; + return aRet; + } + +private: + sal_Int32 m_nLevel; +}; + +struct lcl_insertStringAtLevel : public ::std::unary_function< vector< OUString >, void > +{ +public: + + explicit lcl_insertStringAtLevel( sal_Int32 nLevel ) : m_nLevel( nLevel ) + {} + + void operator() ( vector< OUString >& rVector ) + { + if( m_nLevel > static_cast< sal_Int32 >(rVector.size()) ) + rVector.resize( m_nLevel ); + + vector< OUString >::iterator aIt( rVector.begin() ); + for( sal_Int32 nN=0; aIt<rVector.end(); aIt++, nN++) + { + if( nN==m_nLevel ) + break; + } + rVector.insert( aIt, OUString() ); + } + +private: + sal_Int32 m_nLevel; +}; + +struct lcl_removeStringAtLevel : public ::std::unary_function< vector< OUString >, void > +{ +public: + + explicit lcl_removeStringAtLevel( sal_Int32 nLevel ) : m_nLevel( nLevel ) + {} + + void operator() ( vector< OUString >& rVector ) + { + vector< OUString >::iterator aIt( rVector.begin() ); + for( sal_Int32 nN=0; aIt<rVector.end(); aIt++, nN++) + { + if( nN==m_nLevel ) + { + rVector.erase( aIt ); + break; + } + } + } + +private: + sal_Int32 m_nLevel; +}; + +vector< OUString > lcl_AnyToStringVector( const Sequence< uno::Any >& aAnySeq ) +{ + vector< OUString > aStringVec; + transform( aAnySeq.getConstArray(), aAnySeq.getConstArray() + aAnySeq.getLength(), + back_inserter( aStringVec ), CommonFunctors::AnyToString() ); + return aStringVec; +} + +Sequence< OUString > lcl_AnyToStringSequence( const Sequence< uno::Any >& aAnySeq ) +{ + Sequence< OUString > aResult; + aResult.realloc( aAnySeq.getLength() ); + transform( aAnySeq.getConstArray(), aAnySeq.getConstArray() + aAnySeq.getLength(), + aResult.getArray(), CommonFunctors::AnyToString() ); + return aResult; +} + +} // anonymous namespace + +// ================================================================================ + +InternalDataProvider::InternalDataProvider( const Reference< uno::XComponentContext > & /*_xContext*/) + : m_bDataInColumns( true ) +{} + +InternalDataProvider::InternalDataProvider( const Reference< chart2::XChartDocument > & xChartDoc, bool bConnectToModel ) + : m_bDataInColumns( true ) +{ + try + { + Reference< chart2::XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartDoc ) ); + if( xDiagram.is()) + { + Reference< frame::XModel > xChartModel( xChartDoc, uno::UNO_QUERY ); + + //data in columns? + { + ::rtl::OUString aRangeString; + bool bFirstCellAsLabel = true; + bool bHasCategories = true; + uno::Sequence< sal_Int32 > aSequenceMapping; + DataSourceHelper::detectRangeSegmentation( xChartModel, aRangeString, aSequenceMapping, m_bDataInColumns, bFirstCellAsLabel, bHasCategories ); + } + + // categories + { + vector< vector< OUString > > aNewCategories;//inner count is level + { + ExplicitCategoriesProvider aExplicitCategoriesProvider( ChartModelHelper::getFirstCoordinateSystem(xChartModel), xChartModel ); + const Sequence< Reference< chart2::data::XLabeledDataSequence> >& rSplitCategoriesList( aExplicitCategoriesProvider.getSplitCategoriesList() ); + sal_Int32 nLevelCount = rSplitCategoriesList.getLength(); + for( sal_Int32 nL = 0; nL<nLevelCount; nL++ ) + { + Reference< chart2::data::XLabeledDataSequence > xLDS( rSplitCategoriesList[nL] ); + if( !xLDS.is() ) + continue; + Reference< chart2::data::XTextualDataSequence > xSeq( xLDS->getValues(), uno::UNO_QUERY ); + Sequence< OUString > aStringSeq; + if( xSeq.is() ) + aStringSeq = xSeq->getTextualData(); // @todo: be able to deal with XDataSequence, too + sal_Int32 nLength = aStringSeq.getLength(); + if( static_cast< sal_Int32 >(aNewCategories.size()) < nLength ) + aNewCategories.resize( nLength ); + + transform( aNewCategories.begin(), aNewCategories.end(), aStringSeq.getConstArray(), + aNewCategories.begin(), lcl_setStringAtLevel(nL) ); + } + if( !nLevelCount ) + { + Sequence< OUString > aSimplecategories = aExplicitCategoriesProvider.getSimpleCategories(); + sal_Int32 nLength = aSimplecategories.getLength(); + aNewCategories.reserve( nLength ); + for( sal_Int32 nN=0; nN<nLength; nN++) + { + vector< OUString > aStringVector(1); + aStringVector[0] = aSimplecategories[nN]; + aNewCategories.push_back( aStringVector ); + } + } + } + + if( m_bDataInColumns ) + m_aInternalData.setComplexRowLabels( aNewCategories ); + else + m_aInternalData.setComplexColumnLabels( aNewCategories ); + if( bConnectToModel ) + DiagramHelper::setCategoriesToDiagram( new LabeledDataSequence( + createDataSequenceByRangeRepresentation( lcl_aCategoriesRangeName )), xDiagram ); + } + + // data series + ::std::vector< Reference< chart2::XDataSeries > > aSeriesVector( ChartModelHelper::getDataSeries( xChartDoc )); + ::std::for_each( aSeriesVector.begin(), aSeriesVector.end(), lcl_internalizeSeries( m_aInternalData, *this, bConnectToModel, m_bDataInColumns ) ); + } + } + catch( const uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } +} + +// copy-CTOR +InternalDataProvider::InternalDataProvider( const InternalDataProvider & rOther ) : + impl::InternalDataProvider_Base(), + m_aSequenceMap( rOther.m_aSequenceMap ), + m_aInternalData( rOther.m_aInternalData ), + m_bDataInColumns( rOther.m_bDataInColumns ) +{} + +InternalDataProvider::~InternalDataProvider() +{} + +void InternalDataProvider::lcl_addDataSequenceToMap( + const OUString & rRangeRepresentation, + const Reference< chart2::data::XDataSequence > & xSequence ) +{ + m_aSequenceMap.insert( + tSequenceMap::value_type( + rRangeRepresentation, + uno::WeakReference< chart2::data::XDataSequence >( xSequence ))); +} + +void InternalDataProvider::lcl_deleteMapReferences( const OUString & rRangeRepresentation ) +{ + // set sequence to deleted by setting its range to an empty string + tSequenceMapRange aRange( m_aSequenceMap.equal_range( rRangeRepresentation )); + for( tSequenceMap::iterator aIt( aRange.first ); aIt != aRange.second; ++aIt ) + { + Reference< chart2::data::XDataSequence > xSeq( aIt->second ); + if( xSeq.is()) + { + Reference< container::XNamed > xNamed( xSeq, uno::UNO_QUERY ); + if( xNamed.is()) + xNamed->setName( OUString()); + } + } + // remove from map + m_aSequenceMap.erase( aRange.first, aRange.second ); +} + +void InternalDataProvider::lcl_adaptMapReferences( + const OUString & rOldRangeRepresentation, + const OUString & rNewRangeRepresentation ) +{ + tSequenceMapRange aRange( m_aSequenceMap.equal_range( rOldRangeRepresentation )); + tSequenceMap aNewElements; + for( tSequenceMap::iterator aIt( aRange.first ); aIt != aRange.second; ++aIt ) + { + Reference< chart2::data::XDataSequence > xSeq( aIt->second ); + if( xSeq.is()) + { + Reference< container::XNamed > xNamed( xSeq, uno::UNO_QUERY ); + if( xNamed.is()) + xNamed->setName( rNewRangeRepresentation ); + } + aNewElements.insert( tSequenceMap::value_type( rNewRangeRepresentation, aIt->second )); + } + // erase map values for old index + m_aSequenceMap.erase( aRange.first, aRange.second ); + // add new entries for values with new index + ::std::copy( aNewElements.begin(), aNewElements.end(), + ::std::inserter( m_aSequenceMap, + m_aSequenceMap.upper_bound( rNewRangeRepresentation ))); +} + +void InternalDataProvider::lcl_increaseMapReferences( + sal_Int32 nBegin, sal_Int32 nEnd ) +{ + for( sal_Int32 nIndex = nEnd - 1; nIndex >= nBegin; --nIndex ) + { + lcl_adaptMapReferences( OUString::valueOf( nIndex ), + OUString::valueOf( nIndex + 1 )); + lcl_adaptMapReferences( lcl_aLabelRangePrefix + OUString::valueOf( nIndex ), + lcl_aLabelRangePrefix + OUString::valueOf( nIndex + 1 )); + } +} + +void InternalDataProvider::lcl_decreaseMapReferences( + sal_Int32 nBegin, sal_Int32 nEnd ) +{ + for( sal_Int32 nIndex = nBegin; nIndex < nEnd; ++nIndex ) + { + lcl_adaptMapReferences( OUString::valueOf( nIndex ), + OUString::valueOf( nIndex - 1 )); + lcl_adaptMapReferences( lcl_aLabelRangePrefix + OUString::valueOf( nIndex ), + lcl_aLabelRangePrefix + OUString::valueOf( nIndex - 1 )); + } +} + +Reference< chart2::data::XDataSequence > InternalDataProvider::lcl_createDataSequenceAndAddToMap( + const OUString & rRangeRepresentation ) +{ + Reference< chart2::data::XDataSequence > xSeq( + new UncachedDataSequence( this, rRangeRepresentation )); + lcl_addDataSequenceToMap( rRangeRepresentation, xSeq ); + return xSeq; +} + +Reference< chart2::data::XDataSequence > InternalDataProvider::lcl_createDataSequenceAndAddToMap( + const OUString & rRangeRepresentation, + const OUString & rRole ) +{ + Reference< chart2::data::XDataSequence > xSeq( + new UncachedDataSequence( this, rRangeRepresentation, rRole )); + lcl_addDataSequenceToMap( rRangeRepresentation, xSeq ); + return xSeq; +} + +void InternalDataProvider::createDefaultData() +{ + m_aInternalData.createDefaultData(); +} + +// ____ XDataProvider ____ +::sal_Bool SAL_CALL InternalDataProvider::createDataSourcePossible( const Sequence< beans::PropertyValue >& /* aArguments */ ) + throw (uno::RuntimeException) +{ + return true; +} + +namespace +{ + +sal_Int32 lcl_getInnerLevelCount( const vector< vector< OUString > >& rLabels ) +{ + sal_Int32 nCount = 1;//minimum is 1! + vector< vector< OUString > >::const_iterator aLevelIt( rLabels.begin() ); + vector< vector< OUString > >::const_iterator aLevelEnd( rLabels.end() ); + for( ;aLevelIt!=aLevelEnd; ++aLevelIt ) + { + const vector< ::rtl::OUString >& rCurrentLevelLabels = *aLevelIt; + nCount = std::max<sal_Int32>( rCurrentLevelLabels.size(), nCount ); + } + return nCount; +} + +}//end anonymous namespace + +Reference< chart2::data::XDataSource > SAL_CALL InternalDataProvider::createDataSource( + const Sequence< beans::PropertyValue >& aArguments ) + throw (lang::IllegalArgumentException, + uno::RuntimeException) +{ + OUString aRangeRepresentation; + bool bUseColumns = true; + bool bFirstCellAsLabel = true; + bool bHasCategories = true; + uno::Sequence< sal_Int32 > aSequenceMapping; + DataSourceHelper::readArguments( aArguments, aRangeRepresentation, aSequenceMapping, bUseColumns, bFirstCellAsLabel, bHasCategories ); + + if( aRangeRepresentation.equals( lcl_aCategoriesRangeName ) ) + { + //return split complex categories if we have any: + ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aComplexCategories; + vector< vector< OUString > > aCategories( m_bDataInColumns ? m_aInternalData.getComplexRowLabels() : m_aInternalData.getComplexColumnLabels()); + if( bUseColumns==m_bDataInColumns ) + { + sal_Int32 nLevelCount = lcl_getInnerLevelCount( aCategories ); + for( sal_Int32 nL=0; nL<nLevelCount; nL++ ) + aComplexCategories.push_back( new LabeledDataSequence( + new UncachedDataSequence( this + , lcl_aCategoriesLevelRangeNamePrefix + OUString::valueOf( nL ) + , lcl_aCategoriesRoleName ) ) ); + } + else + { + sal_Int32 nPointCount = m_bDataInColumns ? m_aInternalData.getRowCount() : m_aInternalData.getColumnCount(); + for( sal_Int32 nP=0; nP<nPointCount; nP++ ) + aComplexCategories.push_back( new LabeledDataSequence( + new UncachedDataSequence( this + , lcl_aCategoriesPointRangeNamePrefix + OUString::valueOf( nP ) + , lcl_aCategoriesRoleName ) ) ); + } + //don't add the created sequences to the map as they are used temporarily only ... + return new DataSource( ContainerHelper::ContainerToSequence(aComplexCategories) ); + } + + OSL_ASSERT( aRangeRepresentation.equals( lcl_aCompleteRange )); + + ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aResultLSeqVec; + + // categories + if( bHasCategories ) + aResultLSeqVec.push_back( + new LabeledDataSequence( lcl_createDataSequenceAndAddToMap( lcl_aCategoriesRangeName, lcl_aCategoriesRoleName ) ) ); + + // data with labels + ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aDataVec; + const sal_Int32 nCount = (bUseColumns ? m_aInternalData.getColumnCount() : m_aInternalData.getRowCount()); + for( sal_Int32 nIdx=0; nIdx<nCount; ++nIdx ) + { + aDataVec.push_back( + new LabeledDataSequence( + lcl_createDataSequenceAndAddToMap( OUString::valueOf( nIdx )), + lcl_createDataSequenceAndAddToMap( lcl_aLabelRangePrefix + OUString::valueOf( nIdx )))); + } + + // attention: this data provider has the limitation that it stores + // internally if data comes from columns or rows. It is intended for + // creating only one used data source. + // @todo: add this information in the range representation strings + m_bDataInColumns = bUseColumns; + + //reorder labeled sequences according to aSequenceMapping; ignore categories + for( sal_Int32 nNewIndex = 0; nNewIndex < aSequenceMapping.getLength(); nNewIndex++ ) + { + std::vector< LabeledDataSequence* >::size_type nOldIndex = aSequenceMapping[nNewIndex]; + if( nOldIndex < aDataVec.size() ) + { + if( aDataVec[nOldIndex].is() ) + { + aResultLSeqVec.push_back( aDataVec[nOldIndex] ); + aDataVec[nOldIndex] = 0; + } + } + } + + //add left over data sequences to result + ::std::vector< Reference< chart2::data::XLabeledDataSequence > >::iterator aIt(aDataVec.begin()); + const ::std::vector< Reference< chart2::data::XLabeledDataSequence > >::const_iterator aEndIt(aDataVec.end()); + for( ;aIt!=aEndIt; ++aIt) + { + if( aIt->is() ) + aResultLSeqVec.push_back( *aIt ); + } + + return new DataSource( ContainerHelper::ContainerToSequence(aResultLSeqVec) ); +} + +Sequence< beans::PropertyValue > SAL_CALL InternalDataProvider::detectArguments( + const Reference< chart2::data::XDataSource >& /* xDataSource */ ) + throw (uno::RuntimeException) +{ + Sequence< beans::PropertyValue > aArguments( 4 ); + aArguments[0] = beans::PropertyValue( + C2U("CellRangeRepresentation"), -1, uno::makeAny( lcl_aCompleteRange ), + beans::PropertyState_DIRECT_VALUE ); + aArguments[1] = beans::PropertyValue( + C2U("DataRowSource"), -1, uno::makeAny( + m_bDataInColumns + ? ::com::sun::star::chart::ChartDataRowSource_COLUMNS + : ::com::sun::star::chart::ChartDataRowSource_ROWS ), + beans::PropertyState_DIRECT_VALUE ); + // internal data always contains labels and categories + aArguments[2] = beans::PropertyValue( + C2U("FirstCellAsLabel"), -1, uno::makeAny( true ), beans::PropertyState_DIRECT_VALUE ); + aArguments[3] = beans::PropertyValue( + C2U("HasCategories"), -1, uno::makeAny( true ), beans::PropertyState_DIRECT_VALUE ); + + // #i85913# Sequence Mapping is not needed for internal data, as it is + // applied to the data when the data source is created. + + return aArguments; +} + +::sal_Bool SAL_CALL InternalDataProvider::createDataSequenceByRangeRepresentationPossible( const OUString& /* aRangeRepresentation */ ) + throw (uno::RuntimeException) +{ + return true; +} + +Reference< chart2::data::XDataSequence > SAL_CALL InternalDataProvider::createDataSequenceByRangeRepresentation( + const OUString& aRangeRepresentation ) + throw (lang::IllegalArgumentException, + uno::RuntimeException) +{ + if( aRangeRepresentation.match( lcl_aCategoriesRangeName )) + { + OSL_ASSERT( aRangeRepresentation.equals( lcl_aCategoriesRangeName ) );//it is not expected nor implmented that only parts of the categories are really requested + + // categories + return lcl_createDataSequenceAndAddToMap( lcl_aCategoriesRangeName, lcl_aCategoriesRoleName ); + } + else if( aRangeRepresentation.match( lcl_aLabelRangePrefix )) + { + // label + sal_Int32 nIndex = aRangeRepresentation.copy( lcl_aLabelRangePrefix.getLength()).toInt32(); + return lcl_createDataSequenceAndAddToMap( lcl_aLabelRangePrefix + OUString::valueOf( nIndex )); + } + else if( aRangeRepresentation.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "last" ))) + { + sal_Int32 nIndex = (m_bDataInColumns + ? m_aInternalData.getColumnCount() + : m_aInternalData.getRowCount()) - 1; + return lcl_createDataSequenceAndAddToMap( OUString::valueOf( nIndex )); + } + else if( aRangeRepresentation.getLength()) + { + // data + sal_Int32 nIndex = aRangeRepresentation.toInt32(); + return lcl_createDataSequenceAndAddToMap( OUString::valueOf( nIndex )); + } + + return Reference< chart2::data::XDataSequence >(); +} + +Reference< sheet::XRangeSelection > SAL_CALL InternalDataProvider::getRangeSelection() + throw (uno::RuntimeException) +{ + // there is no range selection component + return Reference< sheet::XRangeSelection >(); +} + +// ____ XInternalDataProvider ____ +::sal_Bool SAL_CALL InternalDataProvider::hasDataByRangeRepresentation( const OUString& aRange ) + throw (uno::RuntimeException) +{ + sal_Bool bResult = false; + + if( aRange.match( lcl_aCategoriesRangeName )) + { + OSL_ASSERT( aRange.equals( lcl_aCategoriesRangeName ) );//it is not expected nor implmented that only parts of the categories are really requested + bResult = true; + } + else if( aRange.match( lcl_aLabelRangePrefix )) + { + sal_Int32 nIndex = aRange.copy( lcl_aLabelRangePrefix.getLength()).toInt32(); + bResult = (nIndex < (m_bDataInColumns ? m_aInternalData.getColumnCount(): m_aInternalData.getRowCount())); + } + else + { + sal_Int32 nIndex = aRange.toInt32(); + bResult = (nIndex < (m_bDataInColumns ? m_aInternalData.getColumnCount(): m_aInternalData.getRowCount())); + } + + return bResult; +} + +Sequence< uno::Any > SAL_CALL InternalDataProvider::getDataByRangeRepresentation( const OUString& aRange ) + throw (uno::RuntimeException) +{ + Sequence< uno::Any > aResult; + + if( aRange.match( lcl_aLabelRangePrefix ) ) + { + sal_Int32 nIndex = aRange.copy( lcl_aLabelRangePrefix.getLength()).toInt32(); + vector< OUString > aComplexLabel = m_bDataInColumns + ? m_aInternalData.getComplexColumnLabel( nIndex ) + : m_aInternalData.getComplexRowLabel( nIndex ); + if( !aComplexLabel.empty() ) + { + aResult.realloc( aComplexLabel.size() ); + transform( aComplexLabel.begin(), aComplexLabel.end(), + aResult.getArray(), CommonFunctors::makeAny< OUString >()); + } + } + else if( aRange.match( lcl_aCategoriesPointRangeNamePrefix ) ) + { + sal_Int32 nPointIndex = aRange.copy( lcl_aCategoriesPointRangeNamePrefix.getLength() ).toInt32(); + vector< OUString > aComplexCategory = m_bDataInColumns + ? m_aInternalData.getComplexRowLabel( nPointIndex ) + : m_aInternalData.getComplexColumnLabel( nPointIndex ); + if( !aComplexCategory.empty() ) + { + aResult.realloc( aComplexCategory.size() ); + transform( aComplexCategory.begin(), aComplexCategory.end(), + aResult.getArray(), CommonFunctors::makeAny< OUString >()); + } + } + else if( aRange.match( lcl_aCategoriesLevelRangeNamePrefix ) ) + { + sal_Int32 nLevel = aRange.copy( lcl_aCategoriesLevelRangeNamePrefix.getLength() ).toInt32(); + vector< vector< OUString > > aCategories( m_bDataInColumns ? m_aInternalData.getComplexRowLabels() : m_aInternalData.getComplexColumnLabels()); + if( nLevel < lcl_getInnerLevelCount( aCategories ) ) + { + aResult.realloc( aCategories.size() ); + transform( aCategories.begin(), aCategories.end(), + aResult.getArray(), lcl_makeAnyFromLevelVector(nLevel) ); + } + } + else if( aRange.equals( lcl_aCategoriesRangeName ) ) + { + Sequence< OUString > aLabels = m_bDataInColumns ? this->getRowDescriptions() : this->getColumnDescriptions(); + aResult.realloc( aLabels.getLength() ); + transform( aLabels.getConstArray(), aLabels.getConstArray() + aLabels.getLength(), + aResult.getArray(), CommonFunctors::makeAny< OUString >() ); + } + else + { + sal_Int32 nIndex = aRange.toInt32(); + if( nIndex >= 0 ) + { + Sequence< double > aData; + if( m_bDataInColumns ) + aData = m_aInternalData.getColumnValues(nIndex); + else + aData = m_aInternalData.getRowValues(nIndex); + if( aData.getLength() ) + { + aResult.realloc( aData.getLength()); + transform( aData.getConstArray(), aData.getConstArray() + aData.getLength(), + aResult.getArray(), CommonFunctors::makeAny< double >()); + } + } + } + + return aResult; +} + +void SAL_CALL InternalDataProvider::setDataByRangeRepresentation( + const OUString& aRange, const Sequence< uno::Any >& aNewData ) + throw (uno::RuntimeException) +{ + if( aRange.match( lcl_aLabelRangePrefix ) ) + { + vector< OUString > aNewStrings( lcl_AnyToStringVector( aNewData ) ); + sal_uInt32 nIndex = aRange.copy( lcl_aLabelRangePrefix.getLength()).toInt32(); + if( m_bDataInColumns ) + m_aInternalData.setComplexColumnLabel( nIndex, aNewStrings ); + else + m_aInternalData.setComplexRowLabel( nIndex, aNewStrings ); + } + else if( aRange.match( lcl_aCategoriesPointRangeNamePrefix ) ) + { + vector< OUString > aNewStrings( lcl_AnyToStringVector( aNewData ) ); + sal_Int32 nPointIndex = aRange.copy( lcl_aCategoriesLevelRangeNamePrefix.getLength()).toInt32(); + if( m_bDataInColumns ) + m_aInternalData.setComplexRowLabel( nPointIndex, aNewStrings ); + else + m_aInternalData.setComplexColumnLabel( nPointIndex, aNewStrings ); + } + else if( aRange.match( lcl_aCategoriesLevelRangeNamePrefix ) ) + { + vector< OUString > aNewStrings( lcl_AnyToStringVector( aNewData ) ); + sal_Int32 nLevel = aRange.copy( lcl_aCategoriesLevelRangeNamePrefix.getLength()).toInt32(); + vector< vector< OUString > > aComplexCategories = m_bDataInColumns ? m_aInternalData.getComplexRowLabels() : m_aInternalData.getComplexColumnLabels(); + + //ensure equal length + if( aNewStrings.size() > aComplexCategories.size() ) + aComplexCategories.resize( aNewStrings.size() ); + else if( aNewStrings.size() < aComplexCategories.size() ) + aNewStrings.resize( aComplexCategories.size() ); + + transform( aComplexCategories.begin(), aComplexCategories.end(), aNewStrings.begin(), + aComplexCategories.begin(), lcl_setStringAtLevel(nLevel) ); + + if( m_bDataInColumns ) + m_aInternalData.setComplexRowLabels( aComplexCategories ); + else + m_aInternalData.setComplexColumnLabels( aComplexCategories ); + } + else if( aRange.equals( lcl_aCategoriesRangeName ) ) + { + if( m_bDataInColumns ) + this->setRowDescriptions( lcl_AnyToStringSequence(aNewData) ); + else + this->setColumnDescriptions( lcl_AnyToStringSequence(aNewData) ); + } + else + { + sal_Int32 nIndex = aRange.toInt32(); + if( nIndex>=0 ) + { + vector< double > aNewDataVec; + transform( aNewData.getConstArray(), aNewData.getConstArray() + aNewData.getLength(), + back_inserter( aNewDataVec ), CommonFunctors::AnyToDouble()); + if( m_bDataInColumns ) + m_aInternalData.setColumnValues( nIndex, aNewDataVec ); + else + m_aInternalData.setRowValues( nIndex, aNewDataVec ); + } + } +} + +void SAL_CALL InternalDataProvider::insertSequence( ::sal_Int32 nAfterIndex ) + throw (uno::RuntimeException) +{ + if( m_bDataInColumns ) + { + lcl_increaseMapReferences( nAfterIndex + 1, m_aInternalData.getColumnCount()); + m_aInternalData.insertColumn( nAfterIndex ); + } + else + { + lcl_increaseMapReferences( nAfterIndex + 1, m_aInternalData.getRowCount()); + m_aInternalData.insertRow( nAfterIndex ); + } +} + +void SAL_CALL InternalDataProvider::deleteSequence( ::sal_Int32 nAtIndex ) + throw (uno::RuntimeException) +{ + lcl_deleteMapReferences( OUString::valueOf( nAtIndex )); + lcl_deleteMapReferences( lcl_aLabelRangePrefix + OUString::valueOf( nAtIndex )); + if( m_bDataInColumns ) + { + lcl_decreaseMapReferences( nAtIndex + 1, m_aInternalData.getColumnCount()); + m_aInternalData.deleteColumn( nAtIndex ); + } + else + { + lcl_decreaseMapReferences( nAtIndex + 1, m_aInternalData.getRowCount()); + m_aInternalData.deleteRow( nAtIndex ); + } +} + +void SAL_CALL InternalDataProvider::appendSequence() + throw (uno::RuntimeException) +{ + if( m_bDataInColumns ) + m_aInternalData.appendColumn(); + else + m_aInternalData.appendRow(); +} + +void SAL_CALL InternalDataProvider::insertComplexCategoryLevel( sal_Int32 nLevel ) + throw (uno::RuntimeException) +{ + OSL_ENSURE( nLevel> 0, "you can only insert category levels > 0" );//the first categories level cannot be deleted, check the calling code for error + if( nLevel>0 ) + { + vector< vector< OUString > > aComplexCategories = m_bDataInColumns ? m_aInternalData.getComplexRowLabels() : m_aInternalData.getComplexColumnLabels(); + ::std::for_each( aComplexCategories.begin(), aComplexCategories.end(), lcl_insertStringAtLevel(nLevel) ); + if( m_bDataInColumns ) + m_aInternalData.setComplexRowLabels( aComplexCategories ); + else + m_aInternalData.setComplexColumnLabels( aComplexCategories ); + + tSequenceMapRange aRange( m_aSequenceMap.equal_range( lcl_aCategoriesRangeName )); + ::std::for_each( aRange.first, aRange.second, lcl_setModified()); + } +} +void SAL_CALL InternalDataProvider::deleteComplexCategoryLevel( sal_Int32 nLevel ) + throw (uno::RuntimeException) +{ + OSL_ENSURE( nLevel>0, "you can only delete category levels > 0" );//the first categories level cannot be deleted, check the calling code for error + if( nLevel>0 ) + { + vector< vector< OUString > > aComplexCategories = m_bDataInColumns ? m_aInternalData.getComplexRowLabels() : m_aInternalData.getComplexColumnLabels(); + ::std::for_each( aComplexCategories.begin(), aComplexCategories.end(), lcl_removeStringAtLevel(nLevel) ); + if( m_bDataInColumns ) + m_aInternalData.setComplexRowLabels( aComplexCategories ); + else + m_aInternalData.setComplexColumnLabels( aComplexCategories ); + + tSequenceMapRange aRange( m_aSequenceMap.equal_range( lcl_aCategoriesRangeName )); + ::std::for_each( aRange.first, aRange.second, lcl_setModified()); + } +} + +void SAL_CALL InternalDataProvider::insertDataPointForAllSequences( ::sal_Int32 nAfterIndex ) + throw (uno::RuntimeException) +{ + sal_Int32 nMaxRep = 0; + if( m_bDataInColumns ) + { + m_aInternalData.insertRow( nAfterIndex ); + nMaxRep = m_aInternalData.getColumnCount(); + } + else + { + m_aInternalData.insertColumn( nAfterIndex ); + nMaxRep = m_aInternalData.getRowCount(); + } + + // notify change to all affected ranges + tSequenceMap::const_iterator aBegin( m_aSequenceMap.lower_bound( C2U("0"))); + tSequenceMap::const_iterator aEnd( m_aSequenceMap.upper_bound( OUString::valueOf( nMaxRep ))); + ::std::for_each( aBegin, aEnd, lcl_setModified()); + + tSequenceMapRange aRange( m_aSequenceMap.equal_range( lcl_aCategoriesRangeName )); + ::std::for_each( aRange.first, aRange.second, lcl_setModified()); +} + +void SAL_CALL InternalDataProvider::deleteDataPointForAllSequences( ::sal_Int32 nAtIndex ) + throw (uno::RuntimeException) +{ + sal_Int32 nMaxRep = 0; + if( m_bDataInColumns ) + { + m_aInternalData.deleteRow( nAtIndex ); + nMaxRep = m_aInternalData.getColumnCount(); + } + else + { + m_aInternalData.deleteColumn( nAtIndex ); + nMaxRep = m_aInternalData.getRowCount(); + } + + // notify change to all affected ranges + tSequenceMap::const_iterator aBegin( m_aSequenceMap.lower_bound( C2U("0"))); + tSequenceMap::const_iterator aEnd( m_aSequenceMap.upper_bound( OUString::valueOf( nMaxRep ))); + ::std::for_each( aBegin, aEnd, lcl_setModified()); + + tSequenceMapRange aRange( m_aSequenceMap.equal_range( lcl_aCategoriesRangeName )); + ::std::for_each( aRange.first, aRange.second, lcl_setModified()); +} + +void SAL_CALL InternalDataProvider::swapDataPointWithNextOneForAllSequences( ::sal_Int32 nAtIndex ) + throw (uno::RuntimeException) +{ + if( m_bDataInColumns ) + m_aInternalData.swapRowWithNext( nAtIndex ); + else + m_aInternalData.swapColumnWithNext( nAtIndex ); + sal_Int32 nMaxRep = (m_bDataInColumns + ? m_aInternalData.getColumnCount() + : m_aInternalData.getRowCount()); + + // notify change to all affected ranges + tSequenceMap::const_iterator aBegin( m_aSequenceMap.lower_bound( C2U("0"))); + tSequenceMap::const_iterator aEnd( m_aSequenceMap.upper_bound( OUString::valueOf( nMaxRep ))); + ::std::for_each( aBegin, aEnd, lcl_setModified()); + + tSequenceMapRange aRange( m_aSequenceMap.equal_range( lcl_aCategoriesRangeName )); + ::std::for_each( aRange.first, aRange.second, lcl_setModified()); +} + +void SAL_CALL InternalDataProvider::registerDataSequenceForChanges( const Reference< chart2::data::XDataSequence >& xSeq ) + throw (uno::RuntimeException) +{ + if( xSeq.is()) + lcl_addDataSequenceToMap( xSeq->getSourceRangeRepresentation(), xSeq ); +} + + +// ____ XRangeXMLConversion ____ +OUString SAL_CALL InternalDataProvider::convertRangeToXML( const OUString& aRangeRepresentation ) + throw (lang::IllegalArgumentException, + uno::RuntimeException) +{ + XMLRangeHelper::CellRange aRange; + aRange.aTableName = OUString(RTL_CONSTASCII_USTRINGPARAM("local-table")); + + // attention: this data provider has the limitation that it stores + // internally if data comes from columns or rows. It is intended for + // creating only one used data source. + // @todo: add this information in the range representation strings + if( aRangeRepresentation.match( lcl_aCategoriesRangeName )) + { + OSL_ASSERT( aRangeRepresentation.equals( lcl_aCategoriesRangeName ) );//it is not expected nor implmented that only parts of the categories are really requested + aRange.aUpperLeft.bIsEmpty = false; + if( m_bDataInColumns ) + { + aRange.aUpperLeft.nColumn = 0; + aRange.aUpperLeft.nRow = 1; + aRange.aLowerRight = aRange.aUpperLeft; + aRange.aLowerRight.nRow = m_aInternalData.getRowCount(); + } + else + { + aRange.aUpperLeft.nColumn = 1; + aRange.aUpperLeft.nRow = 0; + aRange.aLowerRight = aRange.aUpperLeft; + aRange.aLowerRight.nColumn = m_aInternalData.getColumnCount(); + } + } + else if( aRangeRepresentation.match( lcl_aLabelRangePrefix )) + { + sal_Int32 nIndex = aRangeRepresentation.copy( lcl_aLabelRangePrefix.getLength()).toInt32(); + aRange.aUpperLeft.bIsEmpty = false; + aRange.aLowerRight.bIsEmpty = true; + if( m_bDataInColumns ) + { + aRange.aUpperLeft.nColumn = nIndex + 1; + aRange.aUpperLeft.nRow = 0; + } + else + { + aRange.aUpperLeft.nColumn = 0; + aRange.aUpperLeft.nRow = nIndex + 1; + } + } + else if( aRangeRepresentation.equals( lcl_aCompleteRange )) + { + aRange.aUpperLeft.bIsEmpty = false; + aRange.aLowerRight.bIsEmpty = false; + aRange.aUpperLeft.nColumn = 0; + aRange.aUpperLeft.nRow = 0; + aRange.aLowerRight.nColumn = m_aInternalData.getColumnCount(); + aRange.aLowerRight.nRow = m_aInternalData.getRowCount(); + } + else + { + sal_Int32 nIndex = aRangeRepresentation.toInt32(); + aRange.aUpperLeft.bIsEmpty = false; + if( m_bDataInColumns ) + { + aRange.aUpperLeft.nColumn = nIndex + 1; + aRange.aUpperLeft.nRow = 1; + aRange.aLowerRight = aRange.aUpperLeft; + aRange.aLowerRight.nRow = m_aInternalData.getRowCount(); + } + else + { + aRange.aUpperLeft.nColumn = 1; + aRange.aUpperLeft.nRow = nIndex + 1; + aRange.aLowerRight = aRange.aUpperLeft; + aRange.aLowerRight.nColumn = m_aInternalData.getColumnCount(); + } + } + + return XMLRangeHelper::getXMLStringFromCellRange( aRange ); +} + +OUString SAL_CALL InternalDataProvider::convertRangeFromXML( const OUString& aXMLRange ) + throw (lang::IllegalArgumentException, + uno::RuntimeException) +{ + XMLRangeHelper::CellRange aRange( XMLRangeHelper::getCellRangeFromXMLString( aXMLRange )); + if( aRange.aUpperLeft.bIsEmpty ) + { + OSL_ENSURE( aRange.aLowerRight.bIsEmpty, "Weird Range" ); + return OUString(); + } + + // "all" + if( !aRange.aLowerRight.bIsEmpty && + ( aRange.aUpperLeft.nColumn != aRange.aLowerRight.nColumn ) && + ( aRange.aUpperLeft.nRow != aRange.aLowerRight.nRow ) ) + return lcl_aCompleteRange; + + // attention: this data provider has the limitation that it stores + // internally if data comes from columns or rows. It is intended for + // creating only one used data source. + // @todo: add this information in the range representation strings + + // data in columns + if( m_bDataInColumns ) + { + if( aRange.aUpperLeft.nColumn == 0 ) + return lcl_aCategoriesRangeName; + if( aRange.aUpperLeft.nRow == 0 ) + return lcl_aLabelRangePrefix + OUString::valueOf( aRange.aUpperLeft.nColumn - 1 ); + + return OUString::valueOf( aRange.aUpperLeft.nColumn - 1 ); + } + + // data in rows + if( aRange.aUpperLeft.nRow == 0 ) + return lcl_aCategoriesRangeName; + if( aRange.aUpperLeft.nColumn == 0 ) + return lcl_aLabelRangePrefix + OUString::valueOf( aRange.aUpperLeft.nRow - 1 ); + + return OUString::valueOf( aRange.aUpperLeft.nRow - 1 ); +} + +namespace +{ +Sequence< Sequence< OUString > > lcl_convertComplexVectorToSequence( const vector< vector< OUString > >& rIn ) +{ + Sequence< Sequence< OUString > > aRet; + sal_Int32 nOuterCount = rIn.size(); + if( nOuterCount ) + { + aRet.realloc(nOuterCount); + for( sal_Int32 nN=0; nN<nOuterCount; nN++) + aRet[nN]=ContainerHelper::ContainerToSequence( rIn[nN] ); + } + return aRet; +} + +vector< vector< OUString > > lcl_convertComplexSequenceToVector( const Sequence< Sequence< OUString > >& rIn ) +{ + vector< vector< OUString > > aRet; + sal_Int32 nOuterCount = rIn.getLength(); + for( sal_Int32 nN=0; nN<nOuterCount; nN++) + aRet.push_back( ContainerHelper::SequenceToVector( rIn[nN] ) ); + return aRet; +} + +class SplitCategoriesProvider_ForComplexDescriptions : public SplitCategoriesProvider +{ +public: + + explicit SplitCategoriesProvider_ForComplexDescriptions( const ::std::vector< ::std::vector< ::rtl::OUString > >& rComplexDescriptions ) + : m_rComplexDescriptions( rComplexDescriptions ) + {} + virtual ~SplitCategoriesProvider_ForComplexDescriptions() + {} + + virtual sal_Int32 getLevelCount() const; + virtual uno::Sequence< rtl::OUString > getStringsForLevel( sal_Int32 nIndex ) const; + +private: + const ::std::vector< ::std::vector< ::rtl::OUString > >& m_rComplexDescriptions; +}; + +sal_Int32 SplitCategoriesProvider_ForComplexDescriptions::getLevelCount() const +{ + return lcl_getInnerLevelCount( m_rComplexDescriptions ); +} +uno::Sequence< rtl::OUString > SplitCategoriesProvider_ForComplexDescriptions::getStringsForLevel( sal_Int32 nLevel ) const +{ + uno::Sequence< rtl::OUString > aResult; + if( nLevel < lcl_getInnerLevelCount( m_rComplexDescriptions ) ) + { + aResult.realloc( m_rComplexDescriptions.size() ); + transform( m_rComplexDescriptions.begin(), m_rComplexDescriptions.end(), + aResult.getArray(), lcl_getStringFromLevelVector(nLevel) ); + } + return aResult; +} + +}//anonymous namespace + +// ____ XComplexDescriptionAccess ____ +Sequence< Sequence< OUString > > SAL_CALL InternalDataProvider::getComplexRowDescriptions() throw (uno::RuntimeException) +{ + return lcl_convertComplexVectorToSequence( m_aInternalData.getComplexRowLabels() ); +} +void SAL_CALL InternalDataProvider::setComplexRowDescriptions( const Sequence< Sequence< ::rtl::OUString > >& aRowDescriptions ) throw (uno::RuntimeException) +{ + m_aInternalData.setComplexRowLabels( lcl_convertComplexSequenceToVector(aRowDescriptions) ); +} +Sequence< Sequence< ::rtl::OUString > > SAL_CALL InternalDataProvider::getComplexColumnDescriptions() throw (uno::RuntimeException) +{ + return lcl_convertComplexVectorToSequence( m_aInternalData.getComplexColumnLabels() ); +} +void SAL_CALL InternalDataProvider::setComplexColumnDescriptions( const Sequence< Sequence< ::rtl::OUString > >& aColumnDescriptions ) throw (uno::RuntimeException) +{ + m_aInternalData.setComplexColumnLabels( lcl_convertComplexSequenceToVector(aColumnDescriptions) ); +} + +// ____ XChartDataArray ____ +Sequence< Sequence< double > > SAL_CALL InternalDataProvider::getData() + throw (uno::RuntimeException) +{ + return m_aInternalData.getData(); +} + +void SAL_CALL InternalDataProvider::setData( const Sequence< Sequence< double > >& rDataInRows ) + throw (uno::RuntimeException) +{ + return m_aInternalData.setData( rDataInRows ); +} + +void SAL_CALL InternalDataProvider::setRowDescriptions( const Sequence< OUString >& aRowDescriptions ) + throw (uno::RuntimeException) +{ + vector< vector< OUString > > aComplexDescriptions( aRowDescriptions.getLength() ); + transform( aComplexDescriptions.begin(), aComplexDescriptions.end(), aRowDescriptions.getConstArray(), + aComplexDescriptions.begin(), lcl_setStringAtLevel(0) ); + m_aInternalData.setComplexRowLabels( aComplexDescriptions ); +} + +void SAL_CALL InternalDataProvider::setColumnDescriptions( const Sequence< OUString >& aColumnDescriptions ) + throw (uno::RuntimeException) +{ + vector< vector< OUString > > aComplexDescriptions( aColumnDescriptions.getLength() ); + transform( aComplexDescriptions.begin(), aComplexDescriptions.end(), aColumnDescriptions.getConstArray(), + aComplexDescriptions.begin(), lcl_setStringAtLevel(0) ); + m_aInternalData.setComplexColumnLabels( aComplexDescriptions ); +} + +Sequence< OUString > SAL_CALL InternalDataProvider::getRowDescriptions() + throw (uno::RuntimeException) +{ + vector< vector< OUString > > aComplexLabels( m_aInternalData.getComplexRowLabels() ); + SplitCategoriesProvider_ForComplexDescriptions aProvider( aComplexLabels ); + return ExplicitCategoriesProvider::getExplicitSimpleCategories( aProvider ); +} + +Sequence< OUString > SAL_CALL InternalDataProvider::getColumnDescriptions() + throw (uno::RuntimeException) +{ + vector< vector< OUString > > aComplexLabels( m_aInternalData.getComplexColumnLabels() ); + SplitCategoriesProvider_ForComplexDescriptions aProvider( aComplexLabels ); + return ExplicitCategoriesProvider::getExplicitSimpleCategories( aProvider ); +} + +// ____ XChartData (base of XChartDataArray) ____ +void SAL_CALL InternalDataProvider::addChartDataChangeEventListener( + const Reference< ::com::sun::star::chart::XChartDataChangeEventListener >& ) + throw (uno::RuntimeException) +{ +} + +void SAL_CALL InternalDataProvider::removeChartDataChangeEventListener( + const Reference< ::com::sun::star::chart::XChartDataChangeEventListener >& ) + throw (uno::RuntimeException) +{ +} + +double SAL_CALL InternalDataProvider::getNotANumber() + throw (uno::RuntimeException) +{ + double fNan; + ::rtl::math::setNan( & fNan ); + return fNan; +} + +::sal_Bool SAL_CALL InternalDataProvider::isNotANumber( double nNumber ) + throw (uno::RuntimeException) +{ + return ::rtl::math::isNan( nNumber ) + || ::rtl::math::isInf( nNumber ); +} +// lang::XInitialization: +void SAL_CALL InternalDataProvider::initialize(const uno::Sequence< uno::Any > & _aArguments) throw (uno::RuntimeException, uno::Exception) +{ + comphelper::SequenceAsHashMap aArgs(_aArguments); + if ( aArgs.getUnpackedValueOrDefault(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CreateDefaultData")),sal_False) ) + createDefaultData(); +} +// ____ XCloneable ____ +Reference< util::XCloneable > SAL_CALL InternalDataProvider::createClone() + throw (uno::RuntimeException) +{ + return Reference< util::XCloneable >( new InternalDataProvider( *this )); +} + + +// ================================================================================ + +Sequence< OUString > InternalDataProvider::getSupportedServiceNames_Static() +{ + Sequence< OUString > aServices( 1 ); + aServices[ 0 ] = OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.chart2.data.DataProvider" )); + return aServices; +} + +// ================================================================================ + +APPHELPER_XSERVICEINFO_IMPL( InternalDataProvider, lcl_aServiceName ); + +} // namespace chart diff --git a/chart2/source/tools/LabeledDataSequence.cxx b/chart2/source/tools/LabeledDataSequence.cxx new file mode 100644 index 000000000000..21ade3aefadc --- /dev/null +++ b/chart2/source/tools/LabeledDataSequence.cxx @@ -0,0 +1,179 @@ +/************************************************************************* + * + * 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 "LabeledDataSequence.hxx" +#include "ModifyListenerHelper.hxx" +#include "macros.hxx" + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::rtl::OUString; + +namespace chart +{ + +LabeledDataSequence::LabeledDataSequence( const Reference< uno::XComponentContext > & xContext ) : + m_xContext( xContext ), + m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()) +{} + +LabeledDataSequence::LabeledDataSequence( + const uno::Reference< chart2::data::XDataSequence > & rValues ) : + m_xData( rValues ), + m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()) +{ + ModifyListenerHelper::addListener( m_xData, m_xModifyEventForwarder ); +} + +LabeledDataSequence::LabeledDataSequence( + const uno::Reference< chart2::data::XDataSequence > & rValues, + const uno::Reference< chart2::data::XDataSequence > & rLabel ) : + m_xData( rValues ), + m_xLabel( rLabel ), + m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()) +{ + ModifyListenerHelper::addListener( m_xData, m_xModifyEventForwarder ); + ModifyListenerHelper::addListener( m_xLabel, m_xModifyEventForwarder ); +} + +LabeledDataSequence::~LabeledDataSequence() +{ + if( m_xModifyEventForwarder.is()) + { + if( m_xData.is()) + ModifyListenerHelper::removeListener( m_xData, m_xModifyEventForwarder ); + if( m_xLabel.is()) + ModifyListenerHelper::removeListener( m_xLabel, m_xModifyEventForwarder ); + } +} + +// ____ XLabeledDataSequence ____ +uno::Reference< chart2::data::XDataSequence > SAL_CALL LabeledDataSequence::getValues() + throw (uno::RuntimeException) +{ + return m_xData; +} + +void SAL_CALL LabeledDataSequence::setValues( + const uno::Reference< chart2::data::XDataSequence >& xSequence ) + throw (uno::RuntimeException) +{ + if( m_xData != xSequence ) + { + ModifyListenerHelper::removeListener( m_xData, m_xModifyEventForwarder ); + m_xData = xSequence; + ModifyListenerHelper::addListener( m_xData, m_xModifyEventForwarder ); + } +} + +uno::Reference< chart2::data::XDataSequence > SAL_CALL LabeledDataSequence::getLabel() + throw (uno::RuntimeException) +{ + return m_xLabel; +} + +void SAL_CALL LabeledDataSequence::setLabel( + const uno::Reference< chart2::data::XDataSequence >& xSequence ) + throw (uno::RuntimeException) +{ + if( m_xLabel != xSequence ) + { + ModifyListenerHelper::removeListener( m_xLabel, m_xModifyEventForwarder ); + m_xLabel = xSequence; + ModifyListenerHelper::addListener( m_xLabel, m_xModifyEventForwarder ); + } +} + +// ____ XCloneable ____ +uno::Reference< util::XCloneable > SAL_CALL LabeledDataSequence::createClone() + throw (uno::RuntimeException) +{ + uno::Reference< chart2::data::XDataSequence > xNewValues( m_xData ); + uno::Reference< chart2::data::XDataSequence > xNewLabel( m_xLabel ); + + uno::Reference< util::XCloneable > xLabelCloneable( m_xLabel, uno::UNO_QUERY ); + if( xLabelCloneable.is()) + xNewLabel.set( xLabelCloneable->createClone(), uno::UNO_QUERY ); + + uno::Reference< util::XCloneable > xValuesCloneable( m_xData, uno::UNO_QUERY ); + if( xValuesCloneable.is()) + xNewValues.set( xValuesCloneable->createClone(), uno::UNO_QUERY ); + + return uno::Reference< util::XCloneable >( + new LabeledDataSequence( xNewValues, xNewLabel ) ); +} + +// ____ XModifyBroadcaster ____ +void SAL_CALL LabeledDataSequence::addModifyListener( const Reference< util::XModifyListener >& aListener ) + throw (uno::RuntimeException) +{ + try + { + Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW ); + xBroadcaster->addModifyListener( aListener ); + } + catch( const uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } +} + +void SAL_CALL LabeledDataSequence::removeModifyListener( const Reference< util::XModifyListener >& aListener ) + throw (uno::RuntimeException) +{ + try + { + Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW ); + xBroadcaster->removeModifyListener( aListener ); + } + catch( const uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } +} + +// ================================================================================ + +Sequence< OUString > LabeledDataSequence::getSupportedServiceNames_Static() +{ + Sequence< OUString > aServices( 1 ); + aServices[ 0 ] = C2U( "com.sun.star.chart2.data.LabeledDataSequence" ); + return aServices; +} + +// implement XServiceInfo methods basing upon getSupportedServiceNames_Static +APPHELPER_XSERVICEINFO_IMPL( LabeledDataSequence, + C2U( "com.sun.star.comp.chart2.LabeledDataSequence" )) + +// ================================================================================ + +} // namespace chart diff --git a/chart2/source/tools/LegendHelper.cxx b/chart2/source/tools/LegendHelper.cxx new file mode 100644 index 000000000000..4e778db1a68c --- /dev/null +++ b/chart2/source/tools/LegendHelper.cxx @@ -0,0 +1,147 @@ +/************************************************************************* + * + * 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 "LegendHelper.hxx" +#include "macros.hxx" +#include <com/sun/star/chart2/LegendExpansion.hpp> +#include <com/sun/star/chart2/LegendPosition.hpp> +#include <com/sun/star/chart2/RelativePosition.hpp> +#include <com/sun/star/chart2/XChartDocument.hpp> +#include <com/sun/star/chart2/XLegend.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <tools/debug.hxx> + +using namespace ::com::sun::star; +using ::com::sun::star::uno::Reference; + +//............................................................................. +namespace chart +{ +//............................................................................. + + +//static +Reference< chart2::XLegend > LegendHelper::showLegend( const Reference< frame::XModel >& xModel + , const uno::Reference< uno::XComponentContext >& xContext ) +{ + uno::Reference< chart2::XLegend > xLegend = LegendHelper::getLegend( xModel, xContext, true ); + uno::Reference< beans::XPropertySet > xProp( xLegend, uno::UNO_QUERY ); + if( xProp.is()) + { + xProp->setPropertyValue( C2U("Show"), uno::makeAny(sal_True) ); + + chart2::RelativePosition aRelativePosition; + if( !(xProp->getPropertyValue( C2U( "RelativePosition" )) >>= aRelativePosition) ) + { + chart2::LegendPosition ePos = chart2::LegendPosition_LINE_END; + if( !(xProp->getPropertyValue( C2U( "AnchorPosition" )) >>= ePos ) ) + xProp->setPropertyValue( C2U( "AnchorPosition" ), uno::makeAny( ePos )); + + chart2::LegendExpansion eExpansion = + ( ePos == chart2::LegendPosition_LINE_END || + ePos == chart2::LegendPosition_LINE_START ) + ? chart2::LegendExpansion_HIGH + : chart2::LegendExpansion_WIDE; + if( !(xProp->getPropertyValue( C2U( "Expansion" )) >>= eExpansion ) ) + xProp->setPropertyValue( C2U( "Expansion" ), uno::makeAny( eExpansion )); + + xProp->setPropertyValue( C2U( "RelativePosition" ), uno::Any()); + } + + } + return xLegend; +} + +//static +void LegendHelper::hideLegend( const Reference< frame::XModel >& xModel ) +{ + uno::Reference< chart2::XLegend > xLegend = LegendHelper::getLegend( xModel, 0, false ); + uno::Reference< beans::XPropertySet > xProp( xLegend, uno::UNO_QUERY ); + if( xProp.is()) + { + xProp->setPropertyValue( C2U("Show"), uno::makeAny(sal_False) ); + } +} + +// static +uno::Reference< chart2::XLegend > LegendHelper::getLegend( + const uno::Reference< frame::XModel >& xModel + , const uno::Reference< uno::XComponentContext >& xContext + , bool bCreate ) +{ + uno::Reference< chart2::XLegend > xResult; + + uno::Reference< chart2::XChartDocument > xChartDoc( xModel, uno::UNO_QUERY ); + if( xChartDoc.is()) + { + try + { + uno::Reference< chart2::XDiagram > xDia( xChartDoc->getFirstDiagram()); + if( xDia.is() ) + { + xResult.set( xDia->getLegend() ); + if( bCreate && !xResult.is() && xContext.is() ) + { + xResult.set( xContext->getServiceManager()->createInstanceWithContext( + C2U( "com.sun.star.chart2.Legend" ), xContext ), uno::UNO_QUERY ); + xDia->setLegend( xResult ); + } + } + else if(bCreate) + { + DBG_ERROR("need diagram for creation of legend"); + } + } + catch( uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + } + + return xResult; +} + +// static +bool LegendHelper::hasLegend( const uno::Reference< chart2::XDiagram > & xDiagram ) +{ + bool bReturn = false; + if( xDiagram.is()) + { + uno::Reference< beans::XPropertySet > xLegendProp( xDiagram->getLegend(), uno::UNO_QUERY ); + if( xLegendProp.is()) + xLegendProp->getPropertyValue( C2U("Show")) >>= bReturn; + } + + return bReturn; +} + +//............................................................................. +} //namespace chart +//............................................................................. + diff --git a/chart2/source/tools/LifeTime.cxx b/chart2/source/tools/LifeTime.cxx new file mode 100644 index 000000000000..444e894a101d --- /dev/null +++ b/chart2/source/tools/LifeTime.cxx @@ -0,0 +1,546 @@ +/************************************************************************* + * + * 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 "LifeTime.hxx" +#include "macros.hxx" +#include <osl/diagnose.h> + +#include <com/sun/star/util/XModifyListener.hpp> +#include <com/sun/star/util/XCloseListener.hpp> + +using namespace ::com::sun::star; + +namespace apphelper +{ +//-------------------------- + +LifeTimeManager::LifeTimeManager( lang::XComponent* pComponent, sal_Bool bLongLastingCallsCancelable ) + : m_aListenerContainer( m_aAccessMutex ) + , m_pComponent(pComponent) + , m_bLongLastingCallsCancelable(bLongLastingCallsCancelable) +{ + impl_init(); +} + +void LifeTimeManager::impl_init() +{ + m_bDisposed = sal_False; + m_bInDispose = sal_False; + m_nAccessCount = 0; + m_nLongLastingCallCount = 0; + m_aNoAccessCountCondition.set(); + m_aNoLongLastingCallCountCondition.set(); +} + +LifeTimeManager::~LifeTimeManager() +{ +} + +bool LifeTimeManager::impl_isDisposed( bool bAssert ) +{ + if( m_bDisposed || m_bInDispose ) + { + if( bAssert ) + { + OSL_ENSURE( sal_False, "This component is already disposed " ); + (void)(bAssert); + } + return sal_True; + } + return sal_False; +} + sal_Bool LifeTimeManager +::impl_canStartApiCall() +{ + if( impl_isDisposed() ) + return sal_False; //behave passive if already disposed + + //mutex is acquired + return sal_True; +} + + void LifeTimeManager +::impl_registerApiCall(sal_Bool bLongLastingCall) +{ + //only allowed if not disposed + //do not acquire the mutex here because it will be acquired already + m_nAccessCount++; + if(m_nAccessCount==1) + //@todo? is it ok to wake some threads here while we have acquired the mutex? + m_aNoAccessCountCondition.reset(); + + if(bLongLastingCall) + m_nLongLastingCallCount++; + if(m_nLongLastingCallCount==1) + m_aNoLongLastingCallCountCondition.reset(); +} + void LifeTimeManager +::impl_unregisterApiCall(sal_Bool bLongLastingCall) +{ + //Mutex needs to be acquired exactly ones + //mutex may be released inbetween in special case of impl_apiCallCountReachedNull() + + OSL_ENSURE( m_nAccessCount>0, "access count mismatch" ); + m_nAccessCount--; + if(bLongLastingCall) + m_nLongLastingCallCount--; + if( m_nLongLastingCallCount==0 ) + { + m_aNoLongLastingCallCountCondition.set(); + } + if( m_nAccessCount== 0) + { + m_aNoAccessCountCondition.set(); + impl_apiCallCountReachedNull(); + + } +} + + sal_Bool LifeTimeManager +::dispose() throw(uno::RuntimeException) +{ + //hold no mutex + { + osl::Guard< osl::Mutex > aGuard( m_aAccessMutex ); + + if( m_bDisposed || m_bInDispose ) + { + OSL_TRACE( "This component is already disposed " ); + return sal_False; //behave passive if already disposed + } + + m_bInDispose = true; + //adding any listener is not allowed anymore + //new calls will not be accepted + //still running calls have the freedom to finish their work without crash + } + //no mutex is acquired + + //--do the disposing of listeners after calling this method + { + uno::Reference< lang::XComponent > xComponent = + uno::Reference< lang::XComponent >(m_pComponent);; + if(xComponent.is()) + { + // notify XCLoseListeners + lang::EventObject aEvent( xComponent ); + m_aListenerContainer.disposeAndClear( aEvent ); + } + } + + //no mutex is acquired + { + osl::ClearableGuard< osl::Mutex > aGuard( m_aAccessMutex ); + OSL_ENSURE( !m_bDisposed, "dispose was called already" ); + m_bDisposed = sal_True; + aGuard.clear(); + } + //no mutex is acquired + + //wait until all still running calls have finished + //the accessCount cannot grow anymore, because all calls will return after checking m_bDisposed + m_aNoAccessCountCondition.wait(); + + //we are the only ones working on our data now + + return sal_True; + //--release all resources and references after calling this method successful +} + +//----------------------------------------------------------------- + +CloseableLifeTimeManager::CloseableLifeTimeManager( ::com::sun::star::util::XCloseable* pCloseable + , ::com::sun::star::lang::XComponent* pComponent + , sal_Bool bLongLastingCallsCancelable ) + : LifeTimeManager( pComponent, bLongLastingCallsCancelable ) + , m_pCloseable(pCloseable) +{ + impl_init(); +} + +CloseableLifeTimeManager::~CloseableLifeTimeManager() +{ +} + +bool CloseableLifeTimeManager::impl_isDisposedOrClosed( bool bAssert ) +{ + if( impl_isDisposed( bAssert ) ) + return sal_True; + + if( m_bClosed ) + { + if( bAssert ) + { + OSL_ENSURE( sal_False, "This object is already closed" ); + (void)(bAssert);//avoid warnings + } + return sal_True; + } + return sal_False; +} + + sal_Bool CloseableLifeTimeManager +::g_close_startTryClose(sal_Bool bDeliverOwnership) + throw ( uno::Exception ) +{ + //no mutex is allowed to be acquired + { + osl::ResettableGuard< osl::Mutex > aGuard( m_aAccessMutex ); + if( impl_isDisposedOrClosed(false) ) + return sal_False; + + //Mutex needs to be acquired exactly ones; will be released inbetween + if( !impl_canStartApiCall() ) + return sal_False; + //mutex is acquired + + //not closed already -> we try to close again + m_bInTryClose = sal_True; + m_aEndTryClosingCondition.reset(); + + impl_registerApiCall(sal_False); + } + + //------------------------------------------------ + //no mutex is acquired + + //only remove listener calls will be worked on until end of tryclose + //all other new calls will wait till end of try close // @todo? is that really ok + + //?? still running calls have the freedom to finish their work without crash + + try + { + uno::Reference< util::XCloseable > xCloseable = + uno::Reference< util::XCloseable >(m_pCloseable);; + if(xCloseable.is()) + { + //--call queryClosing on all registered close listeners + ::cppu::OInterfaceContainerHelper* pIC = m_aListenerContainer.getContainer( + ::getCppuType((const uno::Reference< util::XCloseListener >*)0) );; + if( pIC ) + { + //lang::EventObject aEvent( static_cast< util::XCloseable*>(xCloseable) ); + lang::EventObject aEvent( xCloseable ); + ::cppu::OInterfaceIteratorHelper aIt( *pIC ); + while( aIt.hasMoreElements() ) + { + uno::Reference< util::XCloseListener > xCloseListener( aIt.next(), uno::UNO_QUERY ); + if(xCloseListener.is()) + xCloseListener->queryClosing( aEvent, bDeliverOwnership ); + } + } + } + } + catch( uno::Exception& ex ) + { + //no mutex is acquired + g_close_endTryClose(bDeliverOwnership, sal_False); + (void)(ex); + throw; + } + return sal_True; +} + + void CloseableLifeTimeManager +::g_close_endTryClose(sal_Bool bDeliverOwnership, sal_Bool /* bMyVeto */ ) +{ + //this method is called, if the try to close was not successfull + osl::Guard< osl::Mutex > aGuard( m_aAccessMutex ); + impl_setOwnership( bDeliverOwnership, sal_False ); + + m_bInTryClose = sal_False; + m_aEndTryClosingCondition.set(); + + //Mutex needs to be acquired exactly ones + //mutex may be released inbetween in special case of impl_apiCallCountReachedNull() + impl_unregisterApiCall(sal_False); +} + + sal_Bool CloseableLifeTimeManager +::g_close_isNeedToCancelLongLastingCalls( sal_Bool bDeliverOwnership, util::CloseVetoException& ex ) + throw ( util::CloseVetoException ) +{ + //this method is called when no closelistener has had a veto during queryclosing + //the method returns false, if nothing stands against closing anymore + //it returns true, if some longlasting calls are running, which might be cancelled + //it throws the given exception, if long calls are running but not cancelable + + osl::Guard< osl::Mutex > aGuard( m_aAccessMutex ); + //this count cannot grow after try of close has started, because we wait in all those methods for end of try closing + if( !m_nLongLastingCallCount ) + return sal_False; + + if(m_bLongLastingCallsCancelable) + return sal_True; + + impl_setOwnership( bDeliverOwnership, sal_True ); + + m_bInTryClose = sal_False; + m_aEndTryClosingCondition.set(); + + //Mutex needs to be acquired exactly ones + //mutex may be released inbetween in special case of impl_apiCallCountReachedNull() + impl_unregisterApiCall(sal_False); + + throw ex; +} + + void CloseableLifeTimeManager +::g_close_endTryClose_doClose() +{ + //this method is called, if the try to close was successfull + osl::ResettableGuard< osl::Mutex > aGuard( m_aAccessMutex ); + + m_bInTryClose = sal_False; + m_aEndTryClosingCondition.set(); + + //Mutex needs to be acquired exactly ones + //mutex may be released inbetween in special case of impl_apiCallCountReachedNull() + impl_unregisterApiCall(sal_False); + impl_doClose(); +} + + void CloseableLifeTimeManager +::impl_setOwnership( sal_Bool bDeliverOwnership, sal_Bool bMyVeto ) +{ + m_bOwnership = bDeliverOwnership && bMyVeto; + m_bOwnershipIsWellKnown = sal_True; +} + sal_Bool CloseableLifeTimeManager +::impl_shouldCloseAtNextChance() +{ + return m_bOwnership; +} + + void CloseableLifeTimeManager +::impl_apiCallCountReachedNull() +{ + //Mutex needs to be acquired exactly ones + //mutex will be released inbetween in impl_doClose() + if( m_pCloseable && impl_shouldCloseAtNextChance() ) + impl_doClose(); +} + + void CloseableLifeTimeManager +::impl_doClose() +{ + //Mutex needs to be acquired exactly ones before calling impl_doClose() + + if(m_bClosed) + return; //behave as passive as possible, if disposed or closed already + if( m_bDisposed || m_bInDispose ) + return; //behave as passive as possible, if disposed or closed already + + //-------- + m_bClosed = sal_True; + + NegativeGuard< osl::Mutex > aNegativeGuard( m_aAccessMutex ); + //mutex is not acquired, mutex will be reacquired at the end of this method automatically + + uno::Reference< util::XCloseable > xCloseable=NULL; + try + { + xCloseable = uno::Reference< util::XCloseable >(m_pCloseable);; + if(xCloseable.is()) + { + //--call notifyClosing on all registered close listeners + ::cppu::OInterfaceContainerHelper* pIC = m_aListenerContainer.getContainer( + ::getCppuType((const uno::Reference< util::XCloseListener >*)0) );; + if( pIC ) + { + //lang::EventObject aEvent( static_cast< util::XCloseable*>(xCloseable) ); + lang::EventObject aEvent( xCloseable ); + ::cppu::OInterfaceIteratorHelper aIt( *pIC ); + while( aIt.hasMoreElements() ) + { + uno::Reference< util::XCloseListener > xListener( aIt.next(), uno::UNO_QUERY ); + if( xListener.is() ) + xListener->notifyClosing( aEvent ); + } + } + } + } + catch( uno::Exception& ex ) + { + ASSERT_EXCEPTION( ex ); + } + + if(xCloseable.is()) + { + uno::Reference< lang::XComponent > xComponent = + uno::Reference< lang::XComponent >( xCloseable, uno::UNO_QUERY ); + if(xComponent.is()) + { + OSL_ENSURE( m_bClosed, "a not closed component will be disposed " ); + xComponent->dispose(); + } + } + //mutex will be reacquired in destructor of aNegativeGuard +} + + sal_Bool CloseableLifeTimeManager +::g_addCloseListener( const uno::Reference< util::XCloseListener > & xListener ) + throw(uno::RuntimeException) +{ + osl::Guard< osl::Mutex > aGuard( m_aAccessMutex ); + //Mutex needs to be acquired exactly ones; will be released inbetween + if( !impl_canStartApiCall() ) + return sal_False; + //mutex is acquired + + m_aListenerContainer.addInterface( ::getCppuType((const uno::Reference< util::XCloseListener >*)0),xListener ); + m_bOwnership = sal_False; + return sal_True; +} + + sal_Bool CloseableLifeTimeManager +::impl_canStartApiCall() +{ + //Mutex needs to be acquired exactly ones before calling this method + //the mutex will be released inbetween and reacquired + + if( impl_isDisposed() ) + return sal_False; //behave passive if already disposed + if( m_bClosed ) + return sal_False; //behave passive if closing is already done + + //during try-close most calls need to wait for the decision + while( m_bInTryClose ) + { + //if someone tries to close this object at the moment + //we need to wait for his end because the result of the preceding call + //is relevant for our behaviour here + + m_aAccessMutex.release(); + m_aEndTryClosingCondition.wait(); //@todo??? this may block??? try closing + m_aAccessMutex.acquire(); + if( m_bDisposed || m_bInDispose || m_bClosed ) + return sal_False; //return if closed already + } + //mutex is acquired + return sal_True; +} + +//-------------------------- + + sal_Bool LifeTimeGuard +::startApiCall(sal_Bool bLongLastingCall) +{ + //Mutex needs to be acquired exactly ones; will be released inbetween + //mutex is requiered due to constructor of LifeTimeGuard + + OSL_ENSURE( !m_bCallRegistered, "this method is only allowed ones" ); + if(m_bCallRegistered) + return sal_False; + + //Mutex needs to be acquired exactly ones; will be released inbetween + if( !m_rManager.impl_canStartApiCall() ) + return sal_False; + //mutex is acquired + + m_bCallRegistered = sal_True; + m_bLongLastingCallRegistered = bLongLastingCall; + m_rManager.impl_registerApiCall(bLongLastingCall); + return sal_True; +} + +LifeTimeGuard::~LifeTimeGuard() +{ + try + { + //do acquire the mutex if it was cleared before + osl::MutexGuard g(m_rManager.m_aAccessMutex); + if(m_bCallRegistered) + { + //Mutex needs to be acquired exactly ones + //mutex may be released inbetween in special case of impl_apiCallCountReachedNull() + m_rManager.impl_unregisterApiCall(m_bLongLastingCallRegistered); + } + } + catch( uno::Exception& ex ) + { + //@todo ? allow a uno::RuntimeException from dispose to travel through?? + ex.Context.is(); //to avoid compilation warnings + } +} + +/* +the XCloseable::close method has to be implemented in the following way: +::close +{ + //hold no mutex + + if( !m_aLifeTimeManager.g_close_startTryClose( bDeliverOwnership ) ) + return; + //no mutex is acquired + + // At the end of this method may we must dispose ourself ... + // and may nobody from outside hold a reference to us ... + // then it's a good idea to do that by ourself. + uno::Reference< uno::XInterface > xSelfHold( static_cast< ::cppu::OWeakObject* >(this) ); + + //the listeners have had no veto + //check wether we self can close + { + util::CloseVetoException aVetoException = util::CloseVetoException( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "the model itself could not be closed" ) ) + , static_cast< ::cppu::OWeakObject* >(this)); + + if( m_aLifeTimeManager.g_close_isNeedToCancelLongLastingCalls( bDeliverOwnership, aVetoException ) ) + { + ////you can empty this block, if you never start longlasting calls or + ////if your longlasting calls are per default not cancelable (check how you have constructed your LifeTimeManager) + + sal_Bool bLongLastingCallsAreCanceled = sal_False; + try + { + //try to cancel running longlasting calls + //// @todo + } + catch( uno::Exception& ex ) + { + //// @todo + //do not throw anything here!! (without endTryClose) + } + //if not successful canceled + if(!bLongLastingCallsAreCanceled) + { + m_aLifeTimeManager.g_close_endTryClose( bDeliverOwnership, sal_True ); + throw aVetoException; + } + } + + } + m_aLifeTimeManager.g_close_endTryClose_doClose(); +} +*/ + +}//end namespace apphelper diff --git a/chart2/source/tools/LineProperties.cxx b/chart2/source/tools/LineProperties.cxx new file mode 100644 index 000000000000..95cf95e21a86 --- /dev/null +++ b/chart2/source/tools/LineProperties.cxx @@ -0,0 +1,185 @@ +/************************************************************************* + * + * 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 "LineProperties.hxx" +#include "macros.hxx" +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/drawing/LineStyle.hpp> +#include <com/sun/star/drawing/LineDash.hpp> +#include <com/sun/star/drawing/LineJoint.hpp> + +using namespace ::com::sun::star; + +using ::com::sun::star::beans::Property; + +namespace chart +{ + +void LineProperties::AddPropertiesToVector( + ::std::vector< Property > & rOutProperties ) +{ + // Line Properties see service drawing::LineProperties + // --------------- + rOutProperties.push_back( + Property( C2U( "LineStyle" ), + PROP_LINE_STYLE, + ::getCppuType( reinterpret_cast< const drawing::LineStyle * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); + + rOutProperties.push_back( + Property( C2U( "LineDash" ), + PROP_LINE_DASH, + ::getCppuType( reinterpret_cast< const drawing::LineDash * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID )); + +//not in service description + rOutProperties.push_back( + Property( C2U( "LineDashName" ), + PROP_LINE_DASH_NAME, + ::getCppuType( reinterpret_cast< const ::rtl::OUString * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT + | beans::PropertyAttribute::MAYBEVOID )); + + rOutProperties.push_back( + Property( C2U( "LineColor" ), + PROP_LINE_COLOR, + ::getCppuType( reinterpret_cast< const sal_Int32 * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); + + rOutProperties.push_back( + Property( C2U( "LineTransparence" ), + PROP_LINE_TRANSPARENCE, + ::getCppuType( reinterpret_cast< const sal_Int16 * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); + + rOutProperties.push_back( + Property( C2U( "LineWidth" ), + PROP_LINE_WIDTH, + ::getCppuType( reinterpret_cast< const sal_Int32 * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); + + rOutProperties.push_back( + Property( C2U( "LineJoint" ), + PROP_LINE_JOINT, + ::getCppuType( reinterpret_cast< const drawing::LineJoint * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); +} + +void LineProperties::AddDefaultsToMap( + ::chart::tPropertyValueMap & rOutMap ) +{ + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_LINE_STYLE, drawing::LineStyle_SOLID ); + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( rOutMap, PROP_LINE_WIDTH, 0 ); + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( rOutMap, PROP_LINE_COLOR, 0x000000 ); // black + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int16 >( rOutMap, PROP_LINE_TRANSPARENCE, 0 ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_LINE_JOINT, drawing::LineJoint_ROUND ); +} + +//static +bool LineProperties::IsLineVisible( const ::com::sun::star::uno::Reference< + ::com::sun::star::beans::XPropertySet >& xLineProperties ) +{ + bool bRet = false; + try + { + if( xLineProperties.is() ) + { + drawing::LineStyle aLineStyle(drawing::LineStyle_SOLID); + xLineProperties->getPropertyValue( C2U( "LineStyle" ) ) >>= aLineStyle; + if( aLineStyle != drawing::LineStyle_NONE ) + { + sal_Int16 nLineTransparence=0; + xLineProperties->getPropertyValue( C2U( "LineTransparence" ) ) >>= nLineTransparence; + if(100!=nLineTransparence) + { + bRet = true; + } + } + } + } + catch( const uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + return bRet; +} + +//static +void LineProperties::SetLineVisible( const ::com::sun::star::uno::Reference< + ::com::sun::star::beans::XPropertySet >& xLineProperties ) +{ + try + { + if( xLineProperties.is() ) + { + drawing::LineStyle aLineStyle(drawing::LineStyle_SOLID); + xLineProperties->getPropertyValue( C2U( "LineStyle" ) ) >>= aLineStyle; + if( aLineStyle == drawing::LineStyle_NONE ) + xLineProperties->setPropertyValue( C2U( "LineStyle" ), uno::makeAny( drawing::LineStyle_SOLID ) ); + + sal_Int16 nLineTransparence=0; + xLineProperties->getPropertyValue( C2U( "LineTransparence" ) ) >>= nLineTransparence; + if(100==nLineTransparence) + xLineProperties->setPropertyValue( C2U( "LineTransparence" ), uno::makeAny( sal_Int16(0) ) ); + } + } + catch( const uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } +} + +//static +void LineProperties::SetLineInvisible( const ::com::sun::star::uno::Reference< + ::com::sun::star::beans::XPropertySet >& xLineProperties ) +{ + try + { + if( xLineProperties.is() ) + { + drawing::LineStyle aLineStyle(drawing::LineStyle_SOLID); + xLineProperties->getPropertyValue( C2U( "LineStyle" ) ) >>= aLineStyle; + if( aLineStyle != drawing::LineStyle_NONE ) + xLineProperties->setPropertyValue( C2U( "LineStyle" ), uno::makeAny( drawing::LineStyle_NONE ) ); + } + } + catch( const uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } +} + +} // namespace chart diff --git a/chart2/source/tools/LinearRegressionCurveCalculator.cxx b/chart2/source/tools/LinearRegressionCurveCalculator.cxx new file mode 100644 index 000000000000..7a372cff4f51 --- /dev/null +++ b/chart2/source/tools/LinearRegressionCurveCalculator.cxx @@ -0,0 +1,179 @@ +/************************************************************************* + * + * 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 "LinearRegressionCurveCalculator.hxx" +#include "macros.hxx" +#include "RegressionCalculationHelper.hxx" + +#include <rtl/math.hxx> +#include <rtl/ustrbuf.hxx> + +using namespace ::com::sun::star; + +using ::rtl::OUString; +using ::rtl::OUStringBuffer; + +namespace chart +{ + +LinearRegressionCurveCalculator::LinearRegressionCurveCalculator() : + m_fSlope( 0.0 ), + m_fIntercept( 0.0 ) +{ + ::rtl::math::setNan( & m_fSlope ); + ::rtl::math::setNan( & m_fIntercept ); +} + +LinearRegressionCurveCalculator::~LinearRegressionCurveCalculator() +{} + +// ____ XRegressionCurveCalculator ____ +void SAL_CALL LinearRegressionCurveCalculator::recalculateRegression( + const uno::Sequence< double >& aXValues, + const uno::Sequence< double >& aYValues ) + throw (uno::RuntimeException) +{ + RegressionCalculationHelper::tDoubleVectorPair aValues( + RegressionCalculationHelper::cleanup( + aXValues, aYValues, + RegressionCalculationHelper::isValid())); + + const size_t nMax = aValues.first.size(); + if( nMax == 0 ) + { + ::rtl::math::setNan( & m_fSlope ); + ::rtl::math::setNan( & m_fIntercept ); + ::rtl::math::setNan( & m_fCorrelationCoeffitient ); + return; + } + + const double fN = static_cast< double >( nMax ); + double fSumX = 0.0, fSumY = 0.0, fSumXSq = 0.0, fSumYSq = 0.0, fSumXY = 0.0; + for( size_t i = 0; i < nMax; ++i ) + { + fSumX += aValues.first[i]; + fSumY += aValues.second[i]; + fSumXSq += aValues.first[i] * aValues.first[i]; + fSumYSq += aValues.second[i] * aValues.second[i]; + fSumXY += aValues.first[i] * aValues.second[i]; + } + + m_fSlope = (fN * fSumXY - fSumX * fSumY) / ( fN * fSumXSq - fSumX * fSumX ); + m_fIntercept = (fSumY - m_fSlope * fSumX) / fN; + + m_fCorrelationCoeffitient = ( fN * fSumXY - fSumX * fSumY ) / + sqrt( ( fN * fSumXSq - fSumX * fSumX ) * + ( fN * fSumYSq - fSumY * fSumY ) ); +} + +double SAL_CALL LinearRegressionCurveCalculator::getCurveValue( double x ) + throw (lang::IllegalArgumentException, + uno::RuntimeException) +{ + double fResult; + ::rtl::math::setNan( & fResult ); + + if( ! ( ::rtl::math::isNan( m_fSlope ) || + ::rtl::math::isNan( m_fIntercept ))) + { + fResult = m_fSlope * x + m_fIntercept; + } + + return fResult; +} + +uno::Sequence< geometry::RealPoint2D > SAL_CALL LinearRegressionCurveCalculator::getCurveValues( + double min, double max, ::sal_Int32 nPointCount, + const uno::Reference< chart2::XScaling >& xScalingX, + const uno::Reference< chart2::XScaling >& xScalingY, + ::sal_Bool bMaySkipPointsInCalculation ) + throw (lang::IllegalArgumentException, + uno::RuntimeException) +{ + if( bMaySkipPointsInCalculation && + isLinearScaling( xScalingX ) && + isLinearScaling( xScalingY )) + { + // optimize result + uno::Sequence< geometry::RealPoint2D > aResult( 2 ); + aResult[0].X = min; + aResult[0].Y = this->getCurveValue( min ); + aResult[1].X = max; + aResult[1].Y = this->getCurveValue( max ); + + return aResult; + } + return RegressionCurveCalculator::getCurveValues( min, max, nPointCount, xScalingX, xScalingY, bMaySkipPointsInCalculation ); +} + +OUString LinearRegressionCurveCalculator::ImplGetRepresentation( + const uno::Reference< util::XNumberFormatter >& xNumFormatter, + ::sal_Int32 nNumberFormatKey ) const +{ + OUStringBuffer aBuf( C2U( "f(x) = " )); + + bool bHaveSlope = false; + + if( m_fSlope != 0.0 ) + { + if( ::rtl::math::approxEqual( fabs( m_fSlope ), 1.0 )) + { + if( m_fSlope < 0 ) + aBuf.append( UC_MINUS_SIGN ); + } + else + aBuf.append( getFormattedString( xNumFormatter, nNumberFormatKey, m_fSlope )); + aBuf.append( sal_Unicode( 'x' )); + bHaveSlope = true; + } + + if( bHaveSlope ) + { + if( m_fIntercept < 0.0 ) + { + aBuf.append( UC_SPACE ); + aBuf.append( UC_MINUS_SIGN ); + aBuf.append( UC_SPACE ); + aBuf.append( getFormattedString( xNumFormatter, nNumberFormatKey, fabs( m_fIntercept ))); + } + else if( m_fIntercept > 0.0 ) + { + aBuf.appendAscii( RTL_CONSTASCII_STRINGPARAM( " + " )); + aBuf.append( getFormattedString( xNumFormatter, nNumberFormatKey, m_fIntercept )); + } + } + else + { + aBuf.append( getFormattedString( xNumFormatter, nNumberFormatKey, m_fIntercept )); + } + + return aBuf.makeStringAndClear(); +} + +} // namespace chart diff --git a/chart2/source/tools/LogarithmicRegressionCurveCalculator.cxx b/chart2/source/tools/LogarithmicRegressionCurveCalculator.cxx new file mode 100644 index 000000000000..c7c2db60431c --- /dev/null +++ b/chart2/source/tools/LogarithmicRegressionCurveCalculator.cxx @@ -0,0 +1,191 @@ +/************************************************************************* + * + * 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 "LogarithmicRegressionCurveCalculator.hxx" +#include "macros.hxx" +#include "RegressionCalculationHelper.hxx" + +#include <rtl/math.hxx> +#include <rtl/ustrbuf.hxx> + +using namespace ::com::sun::star; + +using ::rtl::OUString; +using ::rtl::OUStringBuffer; + +namespace chart +{ + +LogarithmicRegressionCurveCalculator::LogarithmicRegressionCurveCalculator() : + m_fSlope( 0.0 ), + m_fIntercept( 0.0 ) +{ + ::rtl::math::setNan( & m_fSlope ); + ::rtl::math::setNan( & m_fIntercept ); +} + +LogarithmicRegressionCurveCalculator::~LogarithmicRegressionCurveCalculator() +{} + +// ____ XRegressionCurve ____ +void SAL_CALL LogarithmicRegressionCurveCalculator::recalculateRegression( + const uno::Sequence< double >& aXValues, + const uno::Sequence< double >& aYValues ) + throw (uno::RuntimeException) +{ + RegressionCalculationHelper::tDoubleVectorPair aValues( + RegressionCalculationHelper::cleanup( + aXValues, aYValues, + RegressionCalculationHelper::isValidAndXPositive())); + + const size_t nMax = aValues.first.size(); + if( nMax == 0 ) + { + ::rtl::math::setNan( & m_fSlope ); + ::rtl::math::setNan( & m_fIntercept ); + ::rtl::math::setNan( & m_fCorrelationCoeffitient ); + return; + } + + double fAverageX = 0.0, fAverageY = 0.0; + size_t i = 0; + for( i = 0; i < nMax; ++i ) + { + fAverageX += log( aValues.first[i] ); + fAverageY += aValues.second[i]; + } + + const double fN = static_cast< double >( nMax ); + fAverageX /= fN; + fAverageY /= fN; + + double fQx = 0.0, fQy = 0.0, fQxy = 0.0; + for( i = 0; i < nMax; ++i ) + { + double fDeltaX = log( aValues.first[i] ) - fAverageX; + double fDeltaY = aValues.second[i] - fAverageY; + + fQx += fDeltaX * fDeltaX; + fQy += fDeltaY * fDeltaY; + fQxy += fDeltaX * fDeltaY; + } + + m_fSlope = fQxy / fQx; + m_fIntercept = fAverageY - m_fSlope * fAverageX; + m_fCorrelationCoeffitient = fQxy / sqrt( fQx * fQy ); +} + +double SAL_CALL LogarithmicRegressionCurveCalculator::getCurveValue( double x ) + throw (lang::IllegalArgumentException, + uno::RuntimeException) +{ + double fResult; + ::rtl::math::setNan( & fResult ); + + if( ! ( ::rtl::math::isNan( m_fSlope ) || + ::rtl::math::isNan( m_fIntercept ))) + { + fResult = m_fSlope * log( x ) + m_fIntercept; + } + + return fResult; +} + +uno::Sequence< geometry::RealPoint2D > SAL_CALL LogarithmicRegressionCurveCalculator::getCurveValues( + double min, double max, ::sal_Int32 nPointCount, + const uno::Reference< chart2::XScaling >& xScalingX, + const uno::Reference< chart2::XScaling >& xScalingY, + ::sal_Bool bMaySkipPointsInCalculation ) + throw (lang::IllegalArgumentException, + uno::RuntimeException) +{ + if( bMaySkipPointsInCalculation && + isLogarithmicScaling( xScalingX ) && + isLinearScaling( xScalingY )) + { + // optimize result + uno::Sequence< geometry::RealPoint2D > aResult( 2 ); + aResult[0].X = min; + aResult[0].Y = this->getCurveValue( min ); + aResult[1].X = max; + aResult[1].Y = this->getCurveValue( max ); + + return aResult; + } + return RegressionCurveCalculator::getCurveValues( min, max, nPointCount, xScalingX, xScalingY, bMaySkipPointsInCalculation ); +} + +OUString LogarithmicRegressionCurveCalculator::ImplGetRepresentation( + const uno::Reference< util::XNumberFormatter >& xNumFormatter, + ::sal_Int32 nNumberFormatKey ) const +{ + OUStringBuffer aBuf( C2U( "f(x) = " )); + + bool bHaveSlope = false; + + if( m_fSlope != 0.0 ) + { + if( ::rtl::math::approxEqual( fabs( m_fSlope ), 1.0 )) + { + if( m_fSlope < 0 ) + aBuf.append( UC_MINUS_SIGN ); + } + else + { + aBuf.append( getFormattedString( xNumFormatter, nNumberFormatKey, m_fSlope )); + aBuf.append( UC_SPACE ); + } + aBuf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "ln(x)" )); + bHaveSlope = true; + } + + if( bHaveSlope ) + { + if( m_fIntercept < 0.0 ) + { + aBuf.append( UC_SPACE ); + aBuf.append( UC_MINUS_SIGN ); + aBuf.append( UC_SPACE ); + aBuf.append( getFormattedString( xNumFormatter, nNumberFormatKey, fabs( m_fIntercept ))); + } + else if( m_fIntercept > 0.0 ) + { + aBuf.appendAscii( RTL_CONSTASCII_STRINGPARAM( " + " )); + aBuf.append( getFormattedString( xNumFormatter, nNumberFormatKey, m_fIntercept )); + } + } + else + { + aBuf.append( getFormattedString( xNumFormatter, nNumberFormatKey, m_fIntercept )); + } + + return aBuf.makeStringAndClear(); +} + +} // namespace chart diff --git a/chart2/source/tools/MeanValueRegressionCurveCalculator.cxx b/chart2/source/tools/MeanValueRegressionCurveCalculator.cxx new file mode 100644 index 000000000000..8277a5830b0a --- /dev/null +++ b/chart2/source/tools/MeanValueRegressionCurveCalculator.cxx @@ -0,0 +1,143 @@ +/************************************************************************* + * + * 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 "MeanValueRegressionCurveCalculator.hxx" +#include "macros.hxx" + +#include <rtl/math.hxx> +#include <rtl/ustrbuf.hxx> + +using namespace ::com::sun::star; + +using ::rtl::OUString; +using ::rtl::OUStringBuffer; + +namespace chart +{ + +MeanValueRegressionCurveCalculator::MeanValueRegressionCurveCalculator() : + m_fMeanValue( 0.0 ) +{ + ::rtl::math::setNan( & m_fMeanValue ); +} + +MeanValueRegressionCurveCalculator::~MeanValueRegressionCurveCalculator() +{} + +// ____ XRegressionCurveCalculator ____ +void SAL_CALL MeanValueRegressionCurveCalculator::recalculateRegression( + const uno::Sequence< double >& /*aXValues*/, + const uno::Sequence< double >& aYValues ) + throw (uno::RuntimeException) +{ + const sal_Int32 nDataLength = aYValues.getLength(); + sal_Int32 nMax = nDataLength; + double fSumY = 0.0; + const double * pY = aYValues.getConstArray(); + + for( sal_Int32 i = 0; i < nDataLength; ++i ) + { + if( ::rtl::math::isNan( pY[i] ) || + ::rtl::math::isInf( pY[i] )) + --nMax; + else + fSumY += pY[i]; + } + + m_fCorrelationCoeffitient = 0.0; + + if( nMax == 0 ) + { + ::rtl::math::setNan( & m_fMeanValue ); + } + else + { + m_fMeanValue = fSumY / static_cast< double >( nMax ); + + // correlation coefficient: standard deviation + if( nMax > 1 ) + { + double fErrorSum = 0.0; + for( sal_Int32 i = 0; i < nDataLength; ++i ) + { + if( !::rtl::math::isNan( pY[i] ) && + !::rtl::math::isInf( pY[i] )) + { + double v = m_fMeanValue - pY[i]; + fErrorSum += (v*v); + } + } + OSL_ASSERT( fErrorSum >= 0.0 ); + m_fCorrelationCoeffitient = sqrt( fErrorSum / (nMax - 1 )); + } + } +} + +double SAL_CALL MeanValueRegressionCurveCalculator::getCurveValue( double /*x*/ ) + throw (lang::IllegalArgumentException, + uno::RuntimeException) +{ + return m_fMeanValue; +} + + +uno::Sequence< geometry::RealPoint2D > SAL_CALL MeanValueRegressionCurveCalculator::getCurveValues( + double min, double max, ::sal_Int32 nPointCount, + const uno::Reference< chart2::XScaling >& xScalingX, + const uno::Reference< chart2::XScaling >& xScalingY, + ::sal_Bool bMaySkipPointsInCalculation ) + throw (lang::IllegalArgumentException, + uno::RuntimeException) +{ + if( bMaySkipPointsInCalculation ) + { + // optimize result + uno::Sequence< geometry::RealPoint2D > aResult( 2 ); + aResult[0].X = min; + aResult[0].Y = m_fMeanValue; + aResult[1].X = max; + aResult[1].Y = m_fMeanValue; + + return aResult; + } + return RegressionCurveCalculator::getCurveValues( min, max, nPointCount, xScalingX, xScalingY, bMaySkipPointsInCalculation ); +} + +OUString MeanValueRegressionCurveCalculator::ImplGetRepresentation( + const uno::Reference< util::XNumberFormatter >& xNumFormatter, + ::sal_Int32 nNumberFormatKey ) const +{ + OUStringBuffer aBuf( C2U( "f(x) = " )); + + aBuf.append( getFormattedString( xNumFormatter, nNumberFormatKey, m_fMeanValue )); + + return aBuf.makeStringAndClear(); +} + +} // namespace chart diff --git a/chart2/source/tools/MediaDescriptorHelper.cxx b/chart2/source/tools/MediaDescriptorHelper.cxx new file mode 100644 index 000000000000..687bc203a84f --- /dev/null +++ b/chart2/source/tools/MediaDescriptorHelper.cxx @@ -0,0 +1,221 @@ +/************************************************************************* + * + * 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 "MediaDescriptorHelper.hxx" + +using namespace ::com::sun::star; + +namespace apphelper +{ + + +const short FLAG_DEPRECATED =1; +const short FLAG_MODEL =2; + +#define WRITE_PROPERTY( MediaName, nFlags ) \ +if(rProp.Name.equals(::rtl::OUString::createFromAscii(#MediaName))) \ +{ \ + if( rProp.Value >>= MediaName ) \ + ISSET_##MediaName = sal_True; \ + if(nFlags & FLAG_DEPRECATED) \ + { \ + m_aDeprecatedProperties[nDeprecatedCount]=rProp;\ + nDeprecatedCount++; \ + } \ + else \ + { \ + m_aRegularProperties[nRegularCount]=rProp; \ + nRegularCount++; \ + if( nFlags & FLAG_MODEL) \ + { \ + m_aModelProperties[nModelCount]=rProp; \ + nModelCount++; \ + } \ + } \ +} + +MediaDescriptorHelper::MediaDescriptorHelper( const uno::Sequence< + beans::PropertyValue > & rMediaDescriptor ) +{ + impl_init(); + + m_aRegularProperties.realloc(0); + m_aRegularProperties.realloc(rMediaDescriptor.getLength()); + sal_Int32 nRegularCount = 0; + + m_aDeprecatedProperties.realloc(0); + m_aDeprecatedProperties.realloc(rMediaDescriptor.getLength()); + sal_Int32 nDeprecatedCount = 0; + + m_aAdditionalProperties.realloc(0); + m_aAdditionalProperties.realloc(rMediaDescriptor.getLength()); + sal_Int32 nAdditionalCount = 0; + + m_aModelProperties.realloc(0); + m_aModelProperties.realloc(rMediaDescriptor.getLength()); + sal_Int32 nModelCount = 0; + + + //read given rMediaDescriptor and store in internal structures: + for( sal_Int32 i= rMediaDescriptor.getLength();i--;) + { + const beans::PropertyValue& rProp = rMediaDescriptor[i]; + WRITE_PROPERTY( AsTemplate, FLAG_MODEL ) + else WRITE_PROPERTY( Author, FLAG_MODEL ) + else WRITE_PROPERTY( CharacterSet, FLAG_MODEL ) + else WRITE_PROPERTY( Comment, FLAG_MODEL ) + else WRITE_PROPERTY( ComponentData, FLAG_MODEL ) + else WRITE_PROPERTY( FileName, FLAG_DEPRECATED ) + else WRITE_PROPERTY( FilterData, FLAG_MODEL ) + else WRITE_PROPERTY( FilterName, FLAG_MODEL ) + else WRITE_PROPERTY( FilterFlags, FLAG_DEPRECATED) + else WRITE_PROPERTY( FilterOptions, FLAG_MODEL ) + else WRITE_PROPERTY( FrameName, FLAG_MODEL ) + else WRITE_PROPERTY( Hidden, FLAG_MODEL ) + else WRITE_PROPERTY( HierarchicalDocumentName, FLAG_MODEL ) + else WRITE_PROPERTY( OutputStream, 0 ) + else WRITE_PROPERTY( InputStream, 0 ) + else WRITE_PROPERTY( InteractionHandler, 0 ) + else WRITE_PROPERTY( JumpMark, 0 ) + else WRITE_PROPERTY( MediaType, FLAG_MODEL ) + else WRITE_PROPERTY( OpenFlags, FLAG_DEPRECATED ) + else WRITE_PROPERTY( OpenNewView, 0 ) + else WRITE_PROPERTY( Overwrite, FLAG_MODEL ) + else WRITE_PROPERTY( Password, FLAG_MODEL ) + else WRITE_PROPERTY( PosSize, 0 ) + else WRITE_PROPERTY( PostData, 0 ) + else WRITE_PROPERTY( PostString, FLAG_DEPRECATED ) + else WRITE_PROPERTY( Preview, FLAG_MODEL ) + else WRITE_PROPERTY( ReadOnly, 0 ) + else WRITE_PROPERTY( Referer, FLAG_MODEL ) + else WRITE_PROPERTY( SetEmbedded, 0 ) + else WRITE_PROPERTY( Silent, 0 ) + else WRITE_PROPERTY( StatusIndicator, 0 ) + else WRITE_PROPERTY( Storage, FLAG_MODEL ) + else WRITE_PROPERTY( Stream, FLAG_MODEL ) + else WRITE_PROPERTY( TemplateName, FLAG_DEPRECATED ) + else WRITE_PROPERTY( TemplateRegionName, FLAG_DEPRECATED ) + else WRITE_PROPERTY( Unpacked, FLAG_MODEL ) + else WRITE_PROPERTY( URL, FLAG_MODEL ) + else WRITE_PROPERTY( Version, FLAG_MODEL ) + else WRITE_PROPERTY( ViewData, FLAG_MODEL ) + else WRITE_PROPERTY( ViewId, FLAG_MODEL ) + else WRITE_PROPERTY( WinExtent, FLAG_DEPRECATED ) + else + { + m_aAdditionalProperties[nAdditionalCount]=rProp; + nAdditionalCount++; + } + } + + m_aRegularProperties.realloc(nRegularCount); + m_aDeprecatedProperties.realloc(nDeprecatedCount); + m_aAdditionalProperties.realloc(nAdditionalCount); + m_aModelProperties.realloc(nModelCount); +} + +void MediaDescriptorHelper::impl_init() +{ + AsTemplate = sal_False; + ISSET_AsTemplate = sal_False; + + ISSET_Author = sal_False; + ISSET_CharacterSet = sal_False; + ISSET_Comment = sal_False; + +// ::com::sun::star::uno::Any ComponentData; + ISSET_ComponentData = sal_False; + ISSET_FileName = sal_False; + +// ::com::sun::star::uno::Any FilterData; + ISSET_FilterData = sal_False; + ISSET_FilterName = sal_False; + ISSET_FilterFlags = sal_False; + ISSET_FilterOptions = sal_False; + ISSET_FrameName = sal_False; + + Hidden = sal_False; + ISSET_Hidden = sal_False; + ISSET_HierarchicalDocumentName = sal_False; + ISSET_OutputStream = sal_False; + ISSET_InputStream = sal_False; + ISSET_InteractionHandler = sal_False; + ISSET_JumpMark = sal_False; + ISSET_MediaType = sal_False; + ISSET_OpenFlags = sal_False; + OpenNewView = sal_False; + ISSET_OpenNewView = sal_False; + Overwrite = sal_False; + ISSET_Overwrite = sal_False; + ISSET_Password = sal_False; + +// ::com::sun::star::awt::Rectangle PosSize; + ISSET_PosSize = sal_False; + +// ::com::sun::star::uno::Sequence< sal_Int8 > PostData; + ISSET_PostData = sal_False; + ISSET_PostString = sal_False; + Preview = sal_False; + ISSET_Preview = sal_False; + ReadOnly = sal_False; + ISSET_ReadOnly = sal_False; + ISSET_Referer = sal_False; + ISSET_StatusIndicator = sal_False; + Silent = sal_False; + ISSET_Silent = sal_False; + ISSET_TemplateName = sal_False; + ISSET_TemplateRegionName = sal_False; + Unpacked = sal_False; + ISSET_Unpacked = sal_False; + ISSET_URL = sal_False; + Version = 0; + ISSET_Version = sal_False; + +// ::com::sun::star::uno::Any ViewData; + ISSET_ViewData = sal_False; + ViewId = 0; + ISSET_ViewId = sal_False; + + ISSET_WinExtent = sal_False; + + ISSET_Storage = sal_False; + ISSET_Stream = sal_False; +} + +MediaDescriptorHelper::~MediaDescriptorHelper() +{ + +} + + uno::Sequence< beans::PropertyValue > MediaDescriptorHelper +::getReducedForModel() +{ + return m_aModelProperties; +} +} diff --git a/chart2/source/tools/ModifyListenerCallBack.cxx b/chart2/source/tools/ModifyListenerCallBack.cxx new file mode 100644 index 000000000000..ae13b65c39c2 --- /dev/null +++ b/chart2/source/tools/ModifyListenerCallBack.cxx @@ -0,0 +1,134 @@ +/************************************************************************* + * + * 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 "ModifyListenerCallBack.hxx" +#include "MutexContainer.hxx" +#include <cppuhelper/compbase1.hxx> + +using namespace ::com::sun::star; +using ::com::sun::star::uno::Reference; + +namespace chart { + +typedef ::cppu::WeakComponentImplHelper1< + ::com::sun::star::util::XModifyListener > + ModifyListenerCallBack_Base; + +class ModifyListenerCallBack_impl + : public ::chart::MutexContainer + , public ModifyListenerCallBack_Base +{ +public: + explicit ModifyListenerCallBack_impl( const Link& rCallBack ); + virtual ~ModifyListenerCallBack_impl(); + + void startListening( const Reference< util::XModifyBroadcaster >& xBroadcaster ); + void stopListening(); + + //XModifyListener + virtual void SAL_CALL modified( const lang::EventObject& aEvent ) throw (uno::RuntimeException); + + //XEventListener + virtual void SAL_CALL disposing( const lang::EventObject& Source ) throw (uno::RuntimeException); + + using ::cppu::WeakComponentImplHelperBase::disposing; + +private: + Link m_aLink;//will be callef on modify + Reference< util::XModifyBroadcaster > m_xBroadcaster;//broadcaster to listen at +}; + + +ModifyListenerCallBack_impl::ModifyListenerCallBack_impl( const Link& rCallBack ) + : ModifyListenerCallBack_Base( m_aMutex ) + , m_aLink( rCallBack ) + , m_xBroadcaster(0) +{ +} + +ModifyListenerCallBack_impl::~ModifyListenerCallBack_impl() +{ +} + +//XModifyListener +void SAL_CALL ModifyListenerCallBack_impl::modified( const lang::EventObject& /*aEvent*/ ) throw (uno::RuntimeException) +{ + m_aLink.Call(0); +} + +//XEventListener +void SAL_CALL ModifyListenerCallBack_impl::disposing( const lang::EventObject& /*Source*/ ) throw (uno::RuntimeException) +{ + m_xBroadcaster.clear(); +} + +void ModifyListenerCallBack_impl::startListening( const ::com::sun::star::uno::Reference< ::com::sun::star::util::XModifyBroadcaster >& xBroadcaster ) +{ + if( m_xBroadcaster == xBroadcaster ) + return; + + stopListening(); + m_xBroadcaster = xBroadcaster; + if( m_xBroadcaster.is() ) + m_xBroadcaster->addModifyListener( this ); +} +void ModifyListenerCallBack_impl::stopListening() +{ + if( m_xBroadcaster.is() ) + { + m_xBroadcaster->removeModifyListener( this ); + m_xBroadcaster.clear(); + } +} + +//------------------------------------------- + +ModifyListenerCallBack::ModifyListenerCallBack( const Link& rCallBack ) + : pModifyListener_impl( new ModifyListenerCallBack_impl(rCallBack) ) + , m_xModifyListener( pModifyListener_impl ) +{ +} + +ModifyListenerCallBack::~ModifyListenerCallBack() +{ + stopListening(); +} + +void ModifyListenerCallBack::startListening( const ::com::sun::star::uno::Reference< ::com::sun::star::util::XModifyBroadcaster >& xBroadcaster ) +{ + pModifyListener_impl->startListening( xBroadcaster ); +} +void ModifyListenerCallBack::stopListening() +{ + pModifyListener_impl->stopListening(); +} + +} // namespace chart + diff --git a/chart2/source/tools/ModifyListenerHelper.cxx b/chart2/source/tools/ModifyListenerHelper.cxx new file mode 100644 index 000000000000..7ac5a2786cef --- /dev/null +++ b/chart2/source/tools/ModifyListenerHelper.cxx @@ -0,0 +1,213 @@ +/************************************************************************* + * + * 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 "ModifyListenerHelper.hxx" +#include "WeakListenerAdapter.hxx" +#include "macros.hxx" + +#include <cppuhelper/interfacecontainer.hxx> + +#include <com/sun/star/frame/XModel.hpp> + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::rtl::OUString; + +namespace +{ + +void lcl_fireModifyEvent( + ::cppu::OBroadcastHelper & rBroadcastHelper, + const Reference< uno::XWeak > & xEventSource, + const lang::EventObject * pEvent ) +{ + ::cppu::OInterfaceContainerHelper * pCntHlp = rBroadcastHelper.getContainer( + ::getCppuType( reinterpret_cast< Reference< util::XModifyListener > * >(0))); + if( pCntHlp ) + { + lang::EventObject aEventToSend; + if( pEvent ) + aEventToSend = *pEvent; + else + aEventToSend.Source.set( xEventSource ); + OSL_ENSURE( aEventToSend.Source.is(), "Sending event without source" ); + + ::cppu::OInterfaceIteratorHelper aIt( *pCntHlp ); + + while( aIt.hasMoreElements()) + { + Reference< util::XModifyListener > xModListener( aIt.next(), uno::UNO_QUERY ); + if( xModListener.is()) + xModListener->modified( aEventToSend ); + } + } +} + +struct lcl_weakReferenceToSame : public ::std::unary_function< + ::std::pair< + ::com::sun::star::uno::WeakReference< ::com::sun::star::util::XModifyListener >, + ::com::sun::star::uno::Reference< ::com::sun::star::util::XModifyListener > >, + bool > +{ + lcl_weakReferenceToSame( const Reference< util::XModifyListener > & xModListener ) : + m_xHardRef( xModListener ) + {} + + bool operator() ( const argument_type & xElem ) + { + Reference< util::XModifyListener > xWeakAsHard( xElem.first ); + if( xWeakAsHard.is()) + return (xWeakAsHard == m_xHardRef); + return false; + } + +private: + Reference< util::XModifyListener > m_xHardRef; +}; + +} // anonymous namespace + +// ================================================================================ + +namespace chart +{ +namespace ModifyListenerHelper +{ + +uno::Reference< util::XModifyListener > createModifyEventForwarder() +{ + return new ModifyEventForwarder(); +} + +ModifyEventForwarder::ModifyEventForwarder() : + ::cppu::WeakComponentImplHelper2< + ::com::sun::star::util::XModifyBroadcaster, + ::com::sun::star::util::XModifyListener >( m_aMutex ), + m_aModifyListeners( m_aMutex ) +{ +} + +void ModifyEventForwarder::FireEvent( const lang::EventObject & rEvent ) +{ + lcl_fireModifyEvent( m_aModifyListeners, Reference< uno::XWeak >(), & rEvent ); +} + +void ModifyEventForwarder::AddListener( const Reference< util::XModifyListener >& aListener ) +{ + try + { + Reference< util::XModifyListener > xListenerToAdd( aListener ); + + Reference< uno::XWeak > xWeak( aListener, uno::UNO_QUERY ); + if( xWeak.is()) + { + // remember the helper class for later remove + uno::WeakReference< util::XModifyListener > xWeakRef( aListener ); + xListenerToAdd.set( new WeakModifyListenerAdapter( xWeakRef )); + m_aListenerMap.push_back( tListenerMap::value_type( xWeakRef, xListenerToAdd )); + } + + m_aModifyListeners.addListener( ::getCppuType( &xListenerToAdd ), xListenerToAdd ); + } + catch( const uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } +} + +void ModifyEventForwarder::RemoveListener( const Reference< util::XModifyListener >& aListener ) +{ + try + { + // look up fitting helper class that has been added + Reference< util::XModifyListener > xListenerToRemove( aListener ); + tListenerMap::iterator aIt( + ::std::find_if( m_aListenerMap.begin(), m_aListenerMap.end(), lcl_weakReferenceToSame( aListener ))); + if( aIt != m_aListenerMap.end()) + { + xListenerToRemove.set( (*aIt).second ); + // map entry is no longer needed + m_aListenerMap.erase( aIt ); + } + + m_aModifyListeners.removeListener( ::getCppuType( &aListener ), xListenerToRemove ); + } + catch( const uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } +} + +void ModifyEventForwarder::DisposeAndClear( const Reference< uno::XWeak > & xSource ) +{ + ::cppu::OInterfaceContainerHelper * pCntHlp = m_aModifyListeners.getContainer( + ::getCppuType( reinterpret_cast< Reference< util::XModifyListener > * >(0))); + if( pCntHlp ) + pCntHlp->disposeAndClear( lang::EventObject( xSource ) ); +} + +// ____ XModifyBroadcaster ____ +void SAL_CALL ModifyEventForwarder::addModifyListener( const Reference< util::XModifyListener >& aListener ) + throw (uno::RuntimeException) +{ + AddListener( aListener ); +} + +void SAL_CALL ModifyEventForwarder::removeModifyListener( const Reference< util::XModifyListener >& aListener ) + throw (uno::RuntimeException) +{ + RemoveListener( aListener ); +} + +// ____ XModifyListener ____ +void SAL_CALL ModifyEventForwarder::modified( const lang::EventObject& aEvent ) + throw (uno::RuntimeException) +{ + FireEvent( aEvent ); +} + +// ____ XEventListener (base of XModifyListener) ____ +void SAL_CALL ModifyEventForwarder::disposing( const lang::EventObject& /* Source */ ) + throw (uno::RuntimeException) +{ + // nothing +} + +// ____ WeakComponentImplHelperBase ____ +void SAL_CALL ModifyEventForwarder::disposing() +{ + // dispose was called at this + DisposeAndClear( this ); +} + +} // namespace ModifyListenerHelper +} // namespace chart diff --git a/chart2/source/tools/MutexContainer.cxx b/chart2/source/tools/MutexContainer.cxx new file mode 100644 index 000000000000..4fbb14674cdb --- /dev/null +++ b/chart2/source/tools/MutexContainer.cxx @@ -0,0 +1,43 @@ +/************************************************************************* + * + * 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 "MutexContainer.hxx" + +namespace chart +{ + +MutexContainer::~MutexContainer() +{} + +::osl::Mutex & MutexContainer::GetMutex() const +{ + return m_aMutex; +} + +} // namespace chart diff --git a/chart2/source/tools/NameContainer.cxx b/chart2/source/tools/NameContainer.cxx new file mode 100644 index 000000000000..05169c4608f9 --- /dev/null +++ b/chart2/source/tools/NameContainer.cxx @@ -0,0 +1,189 @@ +/************************************************************************* + * + * 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 "NameContainer.hxx" + +/* +//SvXMLUnitConverter +#include <xmloff/xmluconv.hxx> +*/ +#include <com/sun/star/uno/Any.hxx> + +using namespace ::com::sun::star; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::Any; +using ::rtl::OUString; + + +//............................................................................. +namespace chart +{ +//............................................................................. + +uno::Reference< container::XNameContainer > createNameContainer( + const ::com::sun::star::uno::Type& rType, const rtl::OUString& rServicename, const rtl::OUString& rImplementationName ) +{ + return new NameContainer( rType, rServicename, rImplementationName ); +} + +NameContainer::NameContainer( const ::com::sun::star::uno::Type& rType, const OUString& rServicename, const OUString& rImplementationName ) + : m_aType( rType ) + , m_aServicename( rServicename ) + , m_aImplementationName( rImplementationName ) + , m_aMap() +{ +} + +NameContainer::NameContainer( + const NameContainer & rOther ) + : impl::NameContainer_Base() + , m_aType( rOther.m_aType ) + , m_aServicename( rOther.m_aServicename ) + , m_aImplementationName( rOther.m_aImplementationName ) + , m_aMap( rOther.m_aMap ) +{ +} + +NameContainer::~NameContainer() +{ +} + +//XServiceInfo +OUString SAL_CALL NameContainer::getImplementationName() + throw( ::com::sun::star::uno::RuntimeException ) +{ + return m_aImplementationName; +} + +sal_Bool SAL_CALL NameContainer::supportsService( const OUString& ServiceName ) + throw( ::com::sun::star::uno::RuntimeException ) +{ + Sequence< OUString > aSNL = getSupportedServiceNames(); + const OUString* pArray = aSNL.getArray(); + for( sal_Int32 i = 0; i < aSNL.getLength(); i++ ) + { + if( pArray[ i ] == ServiceName ) + return sal_True; + } + return sal_False; +} + +Sequence< OUString > SAL_CALL NameContainer::getSupportedServiceNames() + throw( ::com::sun::star::uno::RuntimeException ) +{ + Sequence< OUString > aSNS( 1 ); + aSNS.getArray()[ 0 ] = m_aServicename; + return aSNS; +} + +//----------------------------------------------------------------- +//----------------------------------------------------------------- +//----------------------------------------------------------------- + +// XNameContainer +void SAL_CALL NameContainer::insertByName( const OUString& rName, const Any& rElement ) + throw( lang::IllegalArgumentException, container::ElementExistException, lang::WrappedTargetException, uno::RuntimeException ) +{ + if( m_aMap.find( rName ) != m_aMap.end() ) + throw container::ElementExistException(); + m_aMap.insert( tContentMap::value_type( rName, rElement )); +} + + + +void SAL_CALL NameContainer::removeByName( const OUString& Name ) + throw( container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException) +{ + tContentMap::iterator aIt( m_aMap.find( Name )); + if( aIt == m_aMap.end()) + throw container::NoSuchElementException(); + m_aMap.erase( aIt ); +} + +// XNameReplace +void SAL_CALL NameContainer::replaceByName( const OUString& rName, const Any& rElement ) + throw( lang::IllegalArgumentException, container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException ) +{ + tContentMap::iterator aIt( m_aMap.find( rName )); + if( aIt == m_aMap.end() ) + throw container::NoSuchElementException(); + aIt->second = rElement; +} + +// XNameAccess +Any SAL_CALL NameContainer::getByName( const OUString& rName ) + throw( container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException) +{ + tContentMap::iterator aIter( m_aMap.find( rName ) ); + if( aIter == m_aMap.end() ) + throw container::NoSuchElementException(); + return aIter->second; +} + +Sequence< OUString > SAL_CALL NameContainer::getElementNames() + throw( uno::RuntimeException ) +{ + sal_Int32 nCount = m_aMap.size(); + Sequence< OUString > aSeq(nCount); + sal_Int32 nN = 0; + for( tContentMap::iterator aIter = m_aMap.begin(); aIter != m_aMap.end(), nN < nCount; aIter++, nN++ ) + aSeq[nN]=aIter->first; + return aSeq; +} + +sal_Bool SAL_CALL NameContainer::hasByName( const OUString& rName ) + throw( uno::RuntimeException ) +{ + return ( m_aMap.find( rName ) != m_aMap.end() ); +} + +// XElementAccess +sal_Bool SAL_CALL NameContainer::hasElements() + throw( uno::RuntimeException ) +{ + return ! m_aMap.empty(); +} + +uno::Type SAL_CALL NameContainer::getElementType() + throw( uno::RuntimeException ) +{ + return m_aType; +} + +// XCloneable +uno::Reference< util::XCloneable > SAL_CALL NameContainer::createClone() + throw ( uno::RuntimeException ) +{ + return uno::Reference< util::XCloneable >( new NameContainer( *this )); +} + +//............................................................................. +} //namespace chart +//............................................................................. diff --git a/chart2/source/tools/NamedFillProperties.cxx b/chart2/source/tools/NamedFillProperties.cxx new file mode 100644 index 000000000000..f904c34c1df1 --- /dev/null +++ b/chart2/source/tools/NamedFillProperties.cxx @@ -0,0 +1,114 @@ +/************************************************************************* + * + * 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 "NamedFillProperties.hxx" +#include "macros.hxx" +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/awt/Gradient.hpp> +#include <com/sun/star/drawing/Hatch.hpp> +#include <com/sun/star/chart2/FillBitmap.hpp> + +using namespace ::com::sun::star; + +using ::com::sun::star::beans::Property; +using ::rtl::OUString; + +namespace chart +{ + +void NamedFillProperties::AddPropertiesToVector( + ::std::vector< Property > & rOutProperties ) +{ + const uno::Type tCppuTypeString = ::getCppuType( reinterpret_cast< const OUString * >(0)); + + // Fill Properties + // --------------- + + //optional property: + rOutProperties.push_back( + Property( C2U( "FillTransparenceGradient" ), + PROP_FILL_TRANSPARENCE_GRADIENT, + ::getCppuType( reinterpret_cast< const awt::Gradient * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT + | beans::PropertyAttribute::MAYBEVOID )); + + //optional property: + rOutProperties.push_back( + Property( C2U( "FillGradient" ), + PROP_FILL_GRADIENT, + ::getCppuType( reinterpret_cast< const awt::Gradient * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT + | beans::PropertyAttribute::MAYBEVOID )); + + //optional property: + rOutProperties.push_back( + Property( C2U( "FillHatch" ), + PROP_FILL_HATCH, + ::getCppuType( reinterpret_cast< const drawing::Hatch * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT + | beans::PropertyAttribute::MAYBEVOID )); + + //optional property: + rOutProperties.push_back( + Property( C2U( "FillBitmapURL" ), + PROP_FILL_BITMAP, + ::getCppuType( reinterpret_cast< const ::rtl::OUString * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT + | beans::PropertyAttribute::MAYBEVOID )); +} + +void NamedFillProperties::AddDefaultsToMap( + ::chart::tPropertyValueMap & rOutMap ) +{ +} + +// static +OUString NamedFillProperties::GetPropertyNameForHandle( sal_Int32 nHandle ) +{ + //will return e.g. "FillGradientName" for PROP_FILL_GRADIENT_NAME + switch( nHandle ) + { + case PROP_FILL_GRADIENT_NAME: + return C2U( "FillGradientName" ); + case PROP_FILL_HATCH_NAME: + return C2U( "FillHatchName" ); + case PROP_FILL_BITMAP_NAME: + return C2U( "FillBitmapName" ); + case PROP_FILL_TRANSPARENCY_GRADIENT_NAME: + return C2U( "FillTransparenceGradientName" ); + } + return OUString(); +} + +} // namespace chart diff --git a/chart2/source/tools/NamedLineProperties.cxx b/chart2/source/tools/NamedLineProperties.cxx new file mode 100644 index 000000000000..02680abf690e --- /dev/null +++ b/chart2/source/tools/NamedLineProperties.cxx @@ -0,0 +1,99 @@ +/************************************************************************* + * + * 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 "NamedLineProperties.hxx" +#include "macros.hxx" +#include <com/sun/star/beans/PropertyAttribute.hpp> + +using namespace ::com::sun::star; + +using ::com::sun::star::beans::Property; +using ::rtl::OUString; + +namespace chart +{ + +// @deprecated !! +void NamedLineProperties::AddPropertiesToVector( + ::std::vector< Property > & rOutProperties ) +{ + const uno::Type tCppuTypeString = ::getCppuType( reinterpret_cast< const OUString * >(0)); + + // Line Properties + // --------------- + rOutProperties.push_back( + Property( C2U( "LineDash" ), + PROP_LINE_DASH, + ::getCppuType( reinterpret_cast< const drawing::LineDash * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID )); + + if( bIncludeLineEnds ) + { + rOutProperties.push_back( + Property( C2U( "LineStartName" ), + PROP_LINE_START_NAME, + tCppuTypeString, + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT + | beans::PropertyAttribute::MAYBEVOID )); + + rOutProperties.push_back( + Property( C2U( "LineEndName" ), + PROP_LINE_END_NAME, + tCppuTypeString, + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT + | beans::PropertyAttribute::MAYBEVOID )); + } +} + +void NamedLineProperties::AddDefaultsToMap( + ::chart::tPropertyValueMap & rOutMap, + bool bIncludeLineEnds /* = false */ ) +{ +} + +// static +OUString NamedLineProperties::GetPropertyNameForHandle( sal_Int32 nHandle ) +{ + //will return e.g. "LineDashName" for PROP_LINE_DASH_NAME + switch( nHandle ) + { + case PROP_LINE_DASH_NAME: + return C2U( "LineDashName" ); + case PROP_LINE_START_NAME: + case PROP_LINE_END_NAME: + break; + } + return OUString(); +} + +} // namespace chart diff --git a/chart2/source/tools/NamedProperties.cxx b/chart2/source/tools/NamedProperties.cxx new file mode 100644 index 000000000000..4fcb536b3279 --- /dev/null +++ b/chart2/source/tools/NamedProperties.cxx @@ -0,0 +1,59 @@ +/************************************************************************* + * + * 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 "NamedProperties.hxx" +#include "macros.hxx" +#include <com/sun/star/beans/PropertyAttribute.hpp> + +using namespace ::com::sun::star; + +using ::com::sun::star::beans::Property; +using ::rtl::OUString; + +namespace chart +{ + +void NamedProperties::AddPropertiesToVector( + ::std::vector< Property > & rOutProperties ) +{ + NamedFillProperties::AddPropertiesToVector( rOutProperties ); + NamedLineProperties::AddPropertiesToVector( rOutProperties ); +} + +// static +OUString NamedProperties::GetPropertyNameForHandle( sal_Int32 nHandle ) +{ + OUString aName = NamedFillProperties::GetPropertyNameForHandle( nHandle ); + if( !aName.getLength() ) + aName = NamedLineProperties::GetPropertyNameForHandle( nHandle ); + return aName; +} + +} // namespace chart diff --git a/chart2/source/tools/OPropertySet.cxx b/chart2/source/tools/OPropertySet.cxx new file mode 100644 index 000000000000..a1caac803dd7 --- /dev/null +++ b/chart2/source/tools/OPropertySet.cxx @@ -0,0 +1,530 @@ +/************************************************************************* + * + * 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 "OPropertySet.hxx" +#include "ImplOPropertySet.hxx" +#include "ContainerHelper.hxx" +#include <rtl/uuid.h> +#include <cppuhelper/queryinterface.hxx> + +#include <vector> +#include <algorithm> + +using namespace ::com::sun::star; + +using ::com::sun::star::style::XStyleSupplier; +// using ::com::sun::star::beans::XFastPropertyState; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::Any; +using ::rtl::OUString; +using ::osl::MutexGuard; + +// needed for MS compiler +using ::cppu::OBroadcastHelper; +using ::cppu::OPropertySetHelper; +using ::cppu::OWeakObject; + +namespace property +{ + +OPropertySet::OPropertySet( ::osl::Mutex & par_rMutex ) : + OBroadcastHelper( par_rMutex ), + // the following causes a warning; there seems to be no way to avoid it + OPropertySetHelper( static_cast< OBroadcastHelper & >( *this )), + m_rMutex( par_rMutex ), + m_pImplProperties( new impl::ImplOPropertySet() ), + m_bSetNewValuesExplicitlyEvenIfTheyEqualDefault(false) +{ +} + +OPropertySet::OPropertySet( const OPropertySet & rOther, ::osl::Mutex & par_rMutex ) : + OBroadcastHelper( par_rMutex ), + // the following causes a warning; there seems to be no way to avoid it + OPropertySetHelper( static_cast< OBroadcastHelper & >( *this )), + m_rMutex( par_rMutex ), + m_bSetNewValuesExplicitlyEvenIfTheyEqualDefault(false) +{ + // /-- + MutexGuard aGuard( m_rMutex ); + if( rOther.m_pImplProperties.get()) + m_pImplProperties.reset( new impl::ImplOPropertySet( * rOther.m_pImplProperties.get())); + // \-- +} + +void OPropertySet::SetNewValuesExplicitlyEvenIfTheyEqualDefault() +{ + m_bSetNewValuesExplicitlyEvenIfTheyEqualDefault = true; +} + +OPropertySet::~OPropertySet() +{} + +void OPropertySet::disposePropertySet() +{ + m_pImplProperties.reset( 0 ); +} + +Any SAL_CALL OPropertySet::queryInterface( const uno::Type& aType ) + throw (uno::RuntimeException) +{ + return ::cppu::queryInterface( + aType, +// static_cast< uno::XInterface * >( +// static_cast< uno::XWeak * >( this )), +// static_cast< uno::XWeak * >( this ), +// static_cast< lang::XServiceInfo * >( this ), + static_cast< lang::XTypeProvider * >( this ), + static_cast< beans::XPropertySet * >( this ), + static_cast< beans::XMultiPropertySet * >( this ), + static_cast< beans::XFastPropertySet * >( this ), + static_cast< beans::XPropertyState * >( this ), + static_cast< beans::XMultiPropertyStates * >( this ), + static_cast< XStyleSupplier * >( this ) ); +// static_cast< XFastPropertyState * >( this ) ); +} + +// void SAL_CALL OPropertySet::acquire() throw () +// { +// OWeakObject::acquire(); +// } + +// void SAL_CALL OPropertySet::release() throw () +// { +// OWeakObject::release(); +// } + + +// ____ XServiceInfo ____ +// OUString SAL_CALL +// OPropertySet::getImplementationName() +// throw (uno::RuntimeException) +// { +// return OUString( RTL_CONSTASCII_USTRINGPARAM( "property::OPropertySet" )); +// } + +// sal_Bool SAL_CALL +// OPropertySet::supportsService( const OUString& ServiceName ) +// throw (uno::RuntimeException) +// { +// return ( 0 == ServiceName.reverseCompareToAsciiL( +// RTL_CONSTASCII_STRINGPARAM( "com.sun.star.beans.PropertySet" ))); +// } + +// Sequence< OUString > SAL_CALL +// OPropertySet::getSupportedServiceNames() +// throw (uno::RuntimeException) +// { +// Sequence< OUString > aServiceNames( 1 ); +// aServiceNames[ 0 ] = OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.beans.PropertySet" )); +// return aServiceNames; +// } + +#define LCL_PROP_CPPUTYPE(t) (::getCppuType( reinterpret_cast< const Reference<t> *>(0))) + +// // ____ XTypeProvider ____ +Sequence< uno::Type > SAL_CALL + OPropertySet::getTypes() + throw (uno::RuntimeException) +{ + static Sequence< uno::Type > aTypeList; + + // /-- + MutexGuard aGuard( m_rMutex ); + + if( aTypeList.getLength() == 0 ) + { + ::std::vector< uno::Type > aTypes; + +// aTypes.push_back( LCL_PROP_CPPUTYPE( uno::XWeak )); +// aTypes.push_back( LCL_PROP_CPPUTYPE( lang::XServiceInfo )); + aTypes.push_back( LCL_PROP_CPPUTYPE( lang::XTypeProvider )); + aTypes.push_back( LCL_PROP_CPPUTYPE( beans::XPropertySet )); + aTypes.push_back( LCL_PROP_CPPUTYPE( beans::XMultiPropertySet )); + aTypes.push_back( LCL_PROP_CPPUTYPE( beans::XFastPropertySet )); + aTypes.push_back( LCL_PROP_CPPUTYPE( beans::XPropertyState )); + aTypes.push_back( LCL_PROP_CPPUTYPE( beans::XMultiPropertyStates )); + aTypes.push_back( LCL_PROP_CPPUTYPE( XStyleSupplier )); +// aTypes.push_back( LCL_PROP_CPPUTYPE( XFastPropertyState )); + + aTypeList = ::chart::ContainerHelper::ContainerToSequence( aTypes ); + } + + return aTypeList; + // \-- +} + +Sequence< sal_Int8 > SAL_CALL + OPropertySet::getImplementationId() + throw (uno::RuntimeException) +{ + static uno::Sequence< sal_Int8 > aId; + if( aId.getLength() == 0 ) + { + aId.realloc( 16 ); + rtl_createUuid( (sal_uInt8 *)aId.getArray(), 0, sal_True ); + } + return aId; +} + + +// ____ XPropertyState ____ +beans::PropertyState SAL_CALL + OPropertySet::getPropertyState( const OUString& PropertyName ) + throw (beans::UnknownPropertyException, + uno::RuntimeException) +{ + cppu::IPropertyArrayHelper & rPH = getInfoHelper(); + + return m_pImplProperties->GetPropertyStateByHandle( + rPH.getHandleByName( PropertyName )); +} + +Sequence< beans::PropertyState > SAL_CALL + OPropertySet::getPropertyStates( const Sequence< OUString >& aPropertyName ) + throw (beans::UnknownPropertyException, + uno::RuntimeException) +{ + cppu::IPropertyArrayHelper & rPH = getInfoHelper(); + + sal_Int32 * pHandles = new sal_Int32[ aPropertyName.getLength() ]; + rPH.fillHandles( pHandles, aPropertyName ); + + ::std::vector< sal_Int32 > aHandles( pHandles, pHandles + aPropertyName.getLength()); + delete[] pHandles; + + return m_pImplProperties->GetPropertyStatesByHandle( aHandles ); +} + +void SAL_CALL + OPropertySet::setPropertyToDefault( const OUString& PropertyName ) + throw (beans::UnknownPropertyException, + uno::RuntimeException) +{ + cppu::IPropertyArrayHelper & rPH = getInfoHelper(); + + m_pImplProperties->SetPropertyToDefault( rPH.getHandleByName( PropertyName )); + firePropertyChangeEvent(); +} + +Any SAL_CALL + OPropertySet::getPropertyDefault( const OUString& aPropertyName ) + throw (beans::UnknownPropertyException, + lang::WrappedTargetException, + uno::RuntimeException) +{ + cppu::IPropertyArrayHelper & rPH = getInfoHelper(); + + return GetDefaultValue( rPH.getHandleByName( aPropertyName ) ); +} + + +// ____ XMultiPropertyStates ____ + +// Note: getPropertyStates() is already implemented in XPropertyState with the +// same signature + +void SAL_CALL + OPropertySet::setAllPropertiesToDefault() + throw (uno::RuntimeException) +{ + m_pImplProperties->SetAllPropertiesToDefault(); + firePropertyChangeEvent(); +} + +void SAL_CALL + OPropertySet::setPropertiesToDefault( const Sequence< OUString >& aPropertyNames ) + throw (beans::UnknownPropertyException, + uno::RuntimeException) +{ + cppu::IPropertyArrayHelper & rPH = getInfoHelper(); + + sal_Int32 * pHandles = new sal_Int32[ aPropertyNames.getLength() ]; + rPH.fillHandles( pHandles, aPropertyNames ); + + ::std::vector< sal_Int32 > aHandles( pHandles, pHandles + aPropertyNames.getLength()); + delete[] pHandles; + + m_pImplProperties->SetPropertiesToDefault( aHandles ); +} + +Sequence< Any > SAL_CALL + OPropertySet::getPropertyDefaults( const Sequence< OUString >& aPropertyNames ) + throw (beans::UnknownPropertyException, + lang::WrappedTargetException, + uno::RuntimeException) +{ + ::cppu::IPropertyArrayHelper & rPH = getInfoHelper(); + const sal_Int32 nElements = aPropertyNames.getLength(); + + Sequence< Any > aResult( nElements ); + Any * pResultArray = aResult.getArray(); + sal_Int32 nI = 0; + + for( ; nI < nElements; ++nI ) + { + pResultArray[ nI ] = GetDefaultValue( + rPH.getHandleByName( aPropertyNames[ nI ] )); + } + + return aResult; +} + +sal_Bool SAL_CALL OPropertySet::convertFastPropertyValue + ( Any & rConvertedValue, + Any & rOldValue, + sal_Int32 nHandle, + const Any& rValue ) + throw (lang::IllegalArgumentException) +{ + getFastPropertyValue( rOldValue, nHandle ); + //accept longs also for short values + { + sal_Int16 nValue; + if( (rOldValue>>=nValue) && !(rValue>>=nValue) ) + { + sal_Int32 n32Value = 0; + if( rValue>>=n32Value ) + { + rConvertedValue = uno::makeAny( static_cast<sal_Int16>(n32Value) ); + return sal_True; + } + + sal_Int64 n64Value = 0; + if( rValue>>=n64Value ) + { + rConvertedValue = uno::makeAny( static_cast<sal_Int16>(n64Value) ); + return sal_True; + } + } + } + rConvertedValue = rValue; + if( !m_bSetNewValuesExplicitlyEvenIfTheyEqualDefault && rOldValue == rConvertedValue ) + return sal_False;//no change necessary + return sal_True; +} + +void SAL_CALL OPropertySet::setFastPropertyValue_NoBroadcast + ( sal_Int32 nHandle, + const Any& rValue ) + throw (uno::Exception) +{ +#if OSL_DEBUG_LEVEL > 0 + if( rValue.hasValue()) + { + cppu::IPropertyArrayHelper & rPH = getInfoHelper(); + OUString aName; + rPH.fillPropertyMembersByHandle( &aName, 0, nHandle ); + OSL_ENSURE( rValue.isExtractableTo( rPH.getPropertyByName( aName ).Type ), + "Property type is wrong" ); + } +#endif + + Any aDefault; + try + { + aDefault = GetDefaultValue( nHandle ); + } + catch( beans::UnknownPropertyException ex ) + { + aDefault.clear(); + } + m_pImplProperties->SetPropertyValueByHandle( nHandle, rValue ); + if( !m_bSetNewValuesExplicitlyEvenIfTheyEqualDefault && aDefault.hasValue() && aDefault == rValue ) //#i98893# don't export defaults to file + m_pImplProperties->SetPropertyToDefault( nHandle ); + else + m_pImplProperties->SetPropertyValueByHandle( nHandle, rValue ); +} + +void SAL_CALL OPropertySet::getFastPropertyValue + ( Any& rValue, + sal_Int32 nHandle ) const +{ + if( ! m_pImplProperties->GetPropertyValueByHandle( rValue, nHandle )) + { +// OSL_TRACE( "OPropertySet: asking style for property" ); + // property was not set -> try style + uno::Reference< beans::XFastPropertySet > xStylePropSet( m_pImplProperties->GetStyle(), uno::UNO_QUERY ); + if( xStylePropSet.is() ) + { +#ifdef DBG_UTIL + { + // check if the handle of the style points to the same property + // name as the handle in this property set + uno::Reference< beans::XPropertySet > xPropSet( xStylePropSet, uno::UNO_QUERY ); + if( xPropSet.is()) + { + uno::Reference< beans::XPropertySetInfo > xInfo( xPropSet->getPropertySetInfo(), + uno::UNO_QUERY ); + if( xInfo.is() ) + { + // for some reason the virtual method getInfoHelper() is + // not const + ::cppu::IPropertyArrayHelper & rPH = + const_cast< OPropertySet * >( this )->getInfoHelper(); + + // find the Property with Handle nHandle in Style + Sequence< beans::Property > aProps( xInfo->getProperties() ); + sal_Int32 nI = aProps.getLength() - 1; + while( ( nI >= 0 ) && nHandle != aProps[ nI ].Handle ) + --nI; + + if( nI >= 0 ) // => nHandle == aProps[nI].Handle + { + // check whether the handle in this property set is + // the same as the one in the style + beans::Property aProp( rPH.getPropertyByName( aProps[ nI ].Name ) ); + OSL_ENSURE( nHandle == aProp.Handle, + "HandleCheck: Handles for same property differ!" ); + + if( nHandle == aProp.Handle ) + { + OSL_ENSURE( aProp.Type == aProps[nI].Type, + "HandleCheck: Types differ!" ); + OSL_ENSURE( aProp.Attributes == aProps[nI].Attributes, + "HandleCheck: Attributes differ!" ); + } + } + else + { + OSL_ENSURE( false, "HandleCheck: Handle not found in Style" ); + } + } + else + OSL_ENSURE( false, "HandleCheck: Invalid XPropertySetInfo returned" ); + } + else + OSL_ENSURE( false, "HandleCheck: XPropertySet not supported" ); + } +#endif + rValue = xStylePropSet->getFastPropertyValue( nHandle ); + } + else + { +// OSL_TRACE( "OPropertySet: no style => getting default for property" ); + // there is no style (or the style does not support XFastPropertySet) + // => take the default value + try + { + rValue = GetDefaultValue( nHandle ); + } + catch( beans::UnknownPropertyException ex ) + { + rValue.clear(); + } + } + } +} + +void OPropertySet::firePropertyChangeEvent() +{ + // nothing in base class +} + +// ____ XStyleSupplier ____ +Reference< style::XStyle > SAL_CALL OPropertySet::getStyle() + throw (uno::RuntimeException) +{ + return m_pImplProperties->GetStyle(); +} + +void SAL_CALL OPropertySet::setStyle( const Reference< style::XStyle >& xStyle ) + throw (lang::IllegalArgumentException, + uno::RuntimeException) +{ + if( ! m_pImplProperties->SetStyle( xStyle )) + throw lang::IllegalArgumentException( + OUString( RTL_CONSTASCII_USTRINGPARAM( "Empty Style" )), + static_cast< beans::XPropertySet * >( this ), + 0 ); +} + +// ____ XFastPropertyState ____ +// beans::PropertyState OPropertySet::SAL_CALL getFastPropertyState( sal_Int32 nHandle ) +// throw (beans::UnknownPropertyException, +// uno::RuntimeException) +// { +// return m_pImplProperties->GetPropertyStateByHandle( nHandle ); +// } + +// uno::Sequence< beans::PropertyState > OPropertySet::SAL_CALL getFastPropertyStates( +// const uno::Sequence< sal_Int32 >& aHandles ) +// throw (beans::UnknownPropertyException, +// uno::RuntimeException) +// { +// ::std::vector< sal_Int32 > aHandleVec( +// aHandles.getConstArray(), +// aHandles.getConstArray() + aHandles.getLength() ); + +// return m_pImplProperties->GetPropertyStatesByHandle( aHandleVec ); +// } + +// void OPropertySet::SAL_CALL setFastPropertyToDefault( sal_Int32 nHandle ) +// throw (beans::UnknownPropertyException, +// uno::RuntimeException) +// { +// m_pImplProperties->SetPropertyToDefault( nHandle ); +// } + +// uno::Any OPropertySet::SAL_CALL getFastPropertyDefault( sal_Int32 nHandle ) +// throw (beans::UnknownPropertyException, +// lang::WrappedTargetException, +// uno::RuntimeException) +// { +// return GetDefaultValue( nHandle ); +// } + +// ____ XMultiPropertySet ____ +void SAL_CALL OPropertySet::setPropertyValues( + const Sequence< OUString >& PropertyNames, const Sequence< Any >& Values ) + throw(beans::PropertyVetoException, + lang::IllegalArgumentException, + lang::WrappedTargetException, + uno::RuntimeException) +{ + ::cppu::OPropertySetHelper::setPropertyValues( PropertyNames, Values ); + + firePropertyChangeEvent(); +} + +// ____ XFastPropertySet ____ +void SAL_CALL OPropertySet::setFastPropertyValue( sal_Int32 nHandle, const Any& rValue ) + throw(beans::UnknownPropertyException, + beans::PropertyVetoException, + lang::IllegalArgumentException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ::cppu::OPropertySetHelper::setFastPropertyValue( nHandle, rValue ); + + firePropertyChangeEvent(); +} + + +} // namespace property diff --git a/chart2/source/tools/ObjectIdentifier.cxx b/chart2/source/tools/ObjectIdentifier.cxx new file mode 100644 index 000000000000..0599f9317aed --- /dev/null +++ b/chart2/source/tools/ObjectIdentifier.cxx @@ -0,0 +1,1491 @@ +/************************************************************************* + * + * 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 "ObjectIdentifier.hxx" +#include "macros.hxx" +#include "TitleHelper.hxx" +#include "ChartModelHelper.hxx" +#include "AxisHelper.hxx" +#include "servicenames_charttypes.hxx" +#include "DiagramHelper.hxx" +#include "AxisIndexDefines.hxx" +#include <com/sun/star/chart2/XCoordinateSystemContainer.hpp> +#include <com/sun/star/chart2/XChartDocument.hpp> +#include <com/sun/star/chart2/XChartTypeContainer.hpp> +#include <com/sun/star/chart2/XDataSeriesContainer.hpp> +#include <com/sun/star/chart2/XAxis.hpp> +#include <com/sun/star/chart2/XRegressionCurveContainer.hpp> + +// header for define DBG_ASSERT +#include <tools/debug.hxx> +#include <comphelper/InlineContainer.hxx> + +#include <rtl/ustrbuf.hxx> + +//............................................................................. +namespace chart +{ +//............................................................................. +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +using rtl::OUString; +using rtl::OUStringBuffer; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Any; + +static OUString m_aMultiClick( C2U("MultiClick") ); +static OUString m_aDragMethodEquals( C2U("DragMethod=") ); +static OUString m_aDragParameterEquals( C2U("DragParameter=") ); +static OUString m_aProtocol( C2U("CID/") ); +static OUString m_aEmptyString; +static OUString m_aPieSegmentDragMethodServiceName( C2U("PieSegmentDraging") ); + +namespace +{ + +OUString lcl_createClassificationStringForType( ObjectType eObjectType + , const OUString& rDragMethodServiceName + , const OUString& rDragParameterString + ) +{ + OUStringBuffer aRet; + switch( eObjectType ) + { + //these object types are all selected only after their parents was selected before + case OBJECTTYPE_LEGEND_ENTRY: //parent is intended to be OBJECTTYPE_LEGEND + case OBJECTTYPE_DATA_POINT: //parent is intended to be OBJECTTYPE_DATA_SERIES + case OBJECTTYPE_DATA_LABEL: //parent is intended to be OBJECTTYPE_DATA_LABELS + case OBJECTTYPE_DATA_ERRORS_X: //parent is intended to be OBJECTTYPE_DATA_ERRORS + case OBJECTTYPE_DATA_ERRORS_Y: //parent is intended to be OBJECTTYPE_DATA_ERRORS + case OBJECTTYPE_DATA_ERRORS_Z: //parent is intended to be OBJECTTYPE_DATA_ERRORS + aRet=m_aMultiClick; + default: + ;//empty string + } + if( rDragMethodServiceName.getLength() ) + { + if( aRet.getLength() ) + aRet.appendAscii(":"); + aRet.append( m_aDragMethodEquals ); + aRet.append( rDragMethodServiceName ); + + if( rDragParameterString.getLength() ) + { + if( aRet.getLength() ) + aRet.appendAscii(":"); + aRet.append( m_aDragParameterEquals ); + aRet.append( rDragParameterString ); + } + } + return aRet.makeStringAndClear(); +} + +typedef ::comphelper::MakeMap< TitleHelper::eTitleType, OUString > tTitleMap; +const tTitleMap& lcl_getTitleMap() +{ + //maps the title type to the ParentParticle for that title + static tTitleMap m_aTitleMap = tTitleMap + ( TitleHelper::MAIN_TITLE, C2U("") ) + ( TitleHelper::SUB_TITLE, C2U("D=0") ) + ( TitleHelper::X_AXIS_TITLE, C2U("D=0:CS=0:Axis=0,0") ) + ( TitleHelper::Y_AXIS_TITLE, C2U("D=0:CS=0:Axis=1,0") ) + ( TitleHelper::Z_AXIS_TITLE, C2U("D=0:CS=0:Axis=2,0") ) + ( TitleHelper::SECONDARY_X_AXIS_TITLE, C2U("D=0:CS=0:Axis=0,1") ) + ( TitleHelper::SECONDARY_Y_AXIS_TITLE, C2U("D=0:CS=0:Axis=1,1") ) + ; + return m_aTitleMap; +} + +OUString lcl_getTitleParentParticle( TitleHelper::eTitleType aTitleType ) +{ + OUString aRet; + + const tTitleMap& rMap = lcl_getTitleMap(); + tTitleMap::const_iterator aIt( rMap.find( aTitleType ) ); + if( aIt != rMap.end()) + aRet = (*aIt).second; + + return aRet; +} + +Reference<XChartType> lcl_getFirstStockChartType( const Reference< frame::XModel >& xChartModel ) +{ + Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartModel ) ); + if(!xDiagram.is()) + return 0; + + //iterate through all coordinate systems + Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY ); + if( !xCooSysContainer.is()) + return 0; + + uno::Sequence< Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() ); + for( sal_Int32 nCS = 0; nCS < aCooSysList.getLength(); ++nCS ) + { + //iterate through all chart types in the current coordinate system + Reference< XChartTypeContainer > xChartTypeContainer( aCooSysList[nCS], uno::UNO_QUERY ); + if( !xChartTypeContainer.is() ) + continue; + + uno::Sequence< Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() ); + for( sal_Int32 nT = 0; nT < aChartTypeList.getLength(); ++nT ) + { + Reference< XChartType > xChartType( aChartTypeList[nT] ); + if(!xChartType.is()) + continue; + OUString aChartType = xChartType->getChartType(); + if( aChartType.equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK) ) + return xChartType; + } + } + return 0; +} + +OUString lcl_getIndexStringAfterString( const OUString& rString, const OUString& rSearchString ) +{ + OUStringBuffer aRet; + + sal_Int32 nIndexStart = rString.lastIndexOf( rSearchString ); + if( nIndexStart != -1 ) + { + nIndexStart += rSearchString.getLength(); + sal_Int32 nIndexEnd = rString.getLength(); + sal_Int32 nNextColon = rString.indexOf( ':', nIndexStart ); + if( nNextColon != -1 ) + nIndexEnd = nNextColon; + aRet = rString.copy(nIndexStart,nIndexEnd-nIndexStart); + } + + return aRet.makeStringAndClear(); +} + +sal_Int32 lcl_StringToIndex( const OUString& rIndexString ) +{ + sal_Int32 nRet = -1; + if( rIndexString.getLength() ) + { + nRet = rIndexString.toInt32(); + if( nRet < -1 ) + nRet = -1; + } + return nRet; +} + +void lcl_parseCooSysIndices( sal_Int32& rnDiagram, sal_Int32& rnCooSys, const OUString& rString ) +{ + rnDiagram = lcl_StringToIndex( lcl_getIndexStringAfterString( rString, C2U("D=") ) ); + rnCooSys = lcl_StringToIndex( lcl_getIndexStringAfterString( rString, C2U("CS=") ) ); +} + +void lcl_parseAxisIndices( sal_Int32& rnDimensionIndex, sal_Int32& rnAxisIndex, const OUString& rString ) +{ + OUString aAxisIndexString = lcl_getIndexStringAfterString( rString, C2U(":Axis=") ); + sal_Int32 nCharacterIndex=0; + rnDimensionIndex = lcl_StringToIndex( aAxisIndexString.getToken( 0, ',', nCharacterIndex ) ); + rnAxisIndex = lcl_StringToIndex( aAxisIndexString.getToken( 0, ',', nCharacterIndex ) ); +} + +void lcl_parseGridIndices( sal_Int32& rnSubGridIndex, const OUString& rString ) +{ + rnSubGridIndex = -1; + rnSubGridIndex = lcl_StringToIndex( lcl_getIndexStringAfterString( rString, C2U(":SubGrid=") ) ); +} + +void lcl_parseSeriesIndices( sal_Int32& rnChartTypeIndex, sal_Int32& rnSeriesIndex, sal_Int32& rnPointIndex, const OUString& rString ) +{ + rnChartTypeIndex = lcl_StringToIndex( lcl_getIndexStringAfterString( rString, C2U("CT=") ) ); + rnSeriesIndex = lcl_StringToIndex( lcl_getIndexStringAfterString( rString, C2U("Series=") ) ); + rnPointIndex = lcl_StringToIndex( lcl_getIndexStringAfterString( rString, C2U("Point=") ) ); +} + +void lcl_getDiagramAndCooSys( const OUString& rObjectCID + , const Reference< frame::XModel >& xChartModel + , Reference< XDiagram >& xDiagram + , Reference< XCoordinateSystem >& xCooSys ) +{ + sal_Int32 nDiagramIndex = -1; + sal_Int32 nCooSysIndex = -1; + lcl_parseCooSysIndices( nDiagramIndex, nCooSysIndex, rObjectCID ); + xDiagram = ChartModelHelper::findDiagram( xChartModel );//todo use nDiagramIndex when more than one diagram is possible in future + if( !xDiagram.is() ) + return; + + if( nCooSysIndex > -1 ) + { + Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY ); + if( xCooSysContainer.is() ) + { + uno::Sequence< Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() ); + if( nCooSysIndex < aCooSysList.getLength() ) + xCooSys = aCooSysList[nCooSysIndex]; + } + } +} + +} //anonymous namespace + +ObjectIdentifier::ObjectIdentifier() + :m_aObjectCID( OUString() ) + ,m_xAdditionalShape( 0 ) +{ +} + +ObjectIdentifier::ObjectIdentifier( const OUString& rObjectCID ) + :m_aObjectCID( rObjectCID ) + ,m_xAdditionalShape( 0 ) +{ +} + +ObjectIdentifier::ObjectIdentifier( const Reference< drawing::XShape >& rxShape ) + :m_aObjectCID( OUString() ) + ,m_xAdditionalShape( rxShape ) +{ +} + +ObjectIdentifier::ObjectIdentifier( const Any& rAny ) + :m_aObjectCID( OUString() ) + ,m_xAdditionalShape( 0 ) +{ + const uno::Type& rType = rAny.getValueType(); + if ( rType == ::getCppuType( static_cast< const OUString* >( 0 ) ) ) + { + rAny >>= m_aObjectCID; + } + else if ( rType == ::getCppuType( static_cast< const Reference< drawing::XShape >* >( 0 ) ) ) + { + rAny >>= m_xAdditionalShape; + } +} + +ObjectIdentifier::~ObjectIdentifier() +{ +} + +ObjectIdentifier::ObjectIdentifier( const ObjectIdentifier& rOID ) + :m_aObjectCID( rOID.m_aObjectCID ) + ,m_xAdditionalShape( rOID.m_xAdditionalShape ) +{ + +} + +ObjectIdentifier& ObjectIdentifier::operator=( const ObjectIdentifier& rOID ) +{ + m_aObjectCID = rOID.m_aObjectCID; + m_xAdditionalShape = rOID.m_xAdditionalShape; + return *this; +} + +bool ObjectIdentifier::operator==( const ObjectIdentifier& rOID ) const +{ + if ( areIdenticalObjects( m_aObjectCID, rOID.m_aObjectCID ) && + ( m_xAdditionalShape == rOID.m_xAdditionalShape ) ) + { + return true; + } + return false; +} + +bool ObjectIdentifier::operator!=( const ObjectIdentifier& rOID ) const +{ + return !operator==( rOID ); +} + +bool ObjectIdentifier::operator<( const ObjectIdentifier& rOID ) const +{ + bool bReturn = false; + if ( m_aObjectCID.getLength() && rOID.m_aObjectCID.getLength() ) + { + bReturn = ( m_aObjectCID.compareTo( rOID.m_aObjectCID ) < 0 ); + } + else if ( m_aObjectCID.getLength() ) + { + bReturn = true; + } + else if ( rOID.m_aObjectCID.getLength() ) + { + bReturn = false; + } + else if ( m_xAdditionalShape.is() && rOID.m_xAdditionalShape.is() ) + { + bReturn = ( m_xAdditionalShape < rOID.m_xAdditionalShape ); + } + return bReturn; +} + +//static +OUString ObjectIdentifier::createClassifiedIdentifierForObject( + const Reference< uno::XInterface >& xObject + , const Reference< frame::XModel >& xChartModel ) +{ + OUString aRet; + + enum ObjectType eObjectType = OBJECTTYPE_UNKNOWN; + OUString aObjectID; + OUString aParentParticle; + OUString aDragMethodServiceName; + OUString aDragParameterString; + + + try + { + //title + Reference< XTitle > xTitle( xObject, uno::UNO_QUERY ); + if( xTitle.is() ) + { + TitleHelper::eTitleType aTitleType; + if( TitleHelper::getTitleType( aTitleType, xTitle, xChartModel ) ) + { + eObjectType = OBJECTTYPE_TITLE; + aParentParticle = lcl_getTitleParentParticle( aTitleType ); + aRet = ObjectIdentifier::createClassifiedIdentifierWithParent( + eObjectType, aObjectID, aParentParticle, aDragMethodServiceName, aDragParameterString ); + } + return aRet; + + } + + //axis + Reference< XAxis > xAxis( xObject, uno::UNO_QUERY ); + if( xAxis.is() ) + { + Reference< XCoordinateSystem > xCooSys( AxisHelper::getCoordinateSystemOfAxis( xAxis, ChartModelHelper::findDiagram( xChartModel ) ) ); + rtl::OUString aCooSysParticle( createParticleForCoordinateSystem( xCooSys, xChartModel ) ); + sal_Int32 nDimensionIndex=-1; + sal_Int32 nAxisIndex=-1; + AxisHelper::getIndicesForAxis( xAxis, xCooSys, nDimensionIndex, nAxisIndex ); + rtl::OUString aAxisParticle( createParticleForAxis( nDimensionIndex, nAxisIndex ) ); + return createClassifiedIdentifierForParticles( aCooSysParticle, aAxisParticle ); + } + + //legend + Reference< XLegend > xLegend( xObject, uno::UNO_QUERY ); + if( xLegend.is() ) + { + return createClassifiedIdentifierForParticle( createParticleForLegend( xLegend, xChartModel ) ); + } + + //diagram + Reference< XDiagram > xDiagram( xObject, uno::UNO_QUERY ); + if( xDiagram.is() ) + { + return createClassifiedIdentifierForParticle( createParticleForDiagram( xDiagram, xChartModel ) ); + } + + //todo + //XDataSeries + //CooSys + //charttype + //datapoint? + //Gridproperties + } + catch( uno::Exception& ex) + { + ASSERT_EXCEPTION( ex ); + } + + if( eObjectType != OBJECTTYPE_UNKNOWN ) + { + aRet = ObjectIdentifier::createClassifiedIdentifierWithParent( + eObjectType, aObjectID, aParentParticle, aDragMethodServiceName, aDragParameterString ); + } + else + { + DBG_ASSERT(false,"give object could not be identifed in createClassifiedIdentifierForObject"); + } + + return aRet; +} + +//static +OUString ObjectIdentifier::createClassifiedIdentifierForParticle( + const OUString& rParticle ) +{ + return ObjectIdentifier::createClassifiedIdentifierForParticles( rParticle, OUString() ); +} + +//static +OUString ObjectIdentifier::createClassifiedIdentifierForParticles( + const OUString& rParentParticle + , const OUString& rChildParticle + , const OUString& rDragMethodServiceName + , const OUString& rDragParameterString ) +{ + ObjectType eObjectType( ObjectIdentifier::getObjectType( rChildParticle ) ); + if( eObjectType == OBJECTTYPE_UNKNOWN ) + eObjectType = ObjectIdentifier::getObjectType( rParentParticle ); + + OUStringBuffer aRet( m_aProtocol ); + aRet.append( lcl_createClassificationStringForType( eObjectType, rDragMethodServiceName, rDragParameterString )); + if(aRet.getLength()>m_aProtocol.getLength()) + aRet.appendAscii("/"); + + if(rParentParticle.getLength()) + { + aRet.append(rParentParticle); + if( rChildParticle.getLength() ) + aRet.appendAscii(":"); + } + aRet.append(rChildParticle); + + return aRet.makeStringAndClear(); +} + +//static +OUString ObjectIdentifier::createParticleForDiagram( + const Reference< XDiagram >& /*xDiagram*/ + , const Reference< frame::XModel >& /*xChartModel*/ ) +{ + static OUString aRet(C2U("D=0")); + //todo: if more than one diagram is implemeted, add the correct diagram index here + return aRet; +} + +//static +OUString ObjectIdentifier::createParticleForCoordinateSystem( + const Reference< XCoordinateSystem >& xCooSys + , const Reference< frame::XModel >& xChartModel ) +{ + OUStringBuffer aRet; + + Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartModel ) ); + Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY ); + if( xCooSysContainer.is() ) + { + sal_Int32 nCooSysIndex = 0; + uno::Sequence< Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() ); + for( ; nCooSysIndex < aCooSysList.getLength(); ++nCooSysIndex ) + { + Reference< XCoordinateSystem > xCurrentCooSys( aCooSysList[nCooSysIndex] ); + if( xCooSys == xCurrentCooSys ) + { + aRet = ObjectIdentifier::createParticleForDiagram( xDiagram, xChartModel ); + aRet.appendAscii(":CS="); + aRet.append( OUString::valueOf( nCooSysIndex ) ); + break; + } + } + } + + return aRet.makeStringAndClear(); +} + +//static +OUString ObjectIdentifier::createParticleForAxis( + sal_Int32 nDimensionIndex + , sal_Int32 nAxisIndex ) +{ + OUStringBuffer aRet(C2U("Axis=")); + + aRet.append( OUString::valueOf( nDimensionIndex ) ); + aRet.appendAscii(","); + aRet.append( OUString::valueOf( nAxisIndex ) ); + + return aRet.makeStringAndClear(); +} + +//static +OUString ObjectIdentifier::createParticleForGrid( + sal_Int32 nDimensionIndex + , sal_Int32 nAxisIndex ) +{ + OUStringBuffer aRet(C2U("Axis=")); + aRet.append( OUString::valueOf( nDimensionIndex ) ); + aRet.appendAscii(","); + aRet.append( OUString::valueOf( nAxisIndex ) ); + aRet.append( C2U(":Grid=0") ); + + return aRet.makeStringAndClear(); +} + +//static +OUString ObjectIdentifier::createClassifiedIdentifierForGrid( + const Reference< XAxis >& xAxis + , const Reference< frame::XModel >& xChartModel + , sal_Int32 nSubGridIndex ) +{ + //-1: main grid, 0: first subgrid etc + + rtl::OUString aAxisCID( createClassifiedIdentifierForObject( xAxis, xChartModel ) ); + rtl::OUString aGridCID( addChildParticle( aAxisCID + , createChildParticleWithIndex( OBJECTTYPE_GRID, 0 ) ) ); + if( nSubGridIndex >= 0 ) + { + aGridCID = addChildParticle( aGridCID + , createChildParticleWithIndex( OBJECTTYPE_SUBGRID, 0 ) ); + } + return aGridCID; +} + +//static +OUString ObjectIdentifier::createParticleForSeries( + sal_Int32 nDiagramIndex, sal_Int32 nCooSysIndex + , sal_Int32 nChartTypeIndex, sal_Int32 nSeriesIndex ) +{ + OUStringBuffer aRet; + + aRet.appendAscii("D="); + aRet.append( OUString::valueOf( nDiagramIndex ) ); + aRet.appendAscii(":CS="); + aRet.append( OUString::valueOf( nCooSysIndex ) ); + aRet.appendAscii(":CT="); + aRet.append( OUString::valueOf( nChartTypeIndex ) ); + aRet.appendAscii(":"); + aRet.append(getStringForType( OBJECTTYPE_DATA_SERIES )); + aRet.appendAscii("="); + aRet.append( OUString::valueOf( nSeriesIndex ) ); + + return aRet.makeStringAndClear(); +} + +//static +OUString ObjectIdentifier::createParticleForLegend( + const Reference< XLegend >& /*xLegend*/ + , const Reference< frame::XModel >& xChartModel ) +{ + OUStringBuffer aRet; + + Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartModel ) ); + //todo: if more than one diagram is implemeted, find the correct diagram wich is owner of the given legend + + aRet.append( ObjectIdentifier::createParticleForDiagram( xDiagram, xChartModel ) ); + aRet.appendAscii(":"); + aRet.append(getStringForType( OBJECTTYPE_LEGEND )); + aRet.appendAscii("="); + + return aRet.makeStringAndClear(); +} + +//static +OUString ObjectIdentifier::createClassifiedIdentifier( + enum ObjectType eObjectType //e.g. OBJECTTYPE_DATA_SERIES + , const OUString& rParticleID )//e.g. SeriesID +{ + return createClassifiedIdentifierWithParent( + eObjectType, rParticleID, m_aEmptyString ); +} + +//static +OUString ObjectIdentifier::createClassifiedIdentifierWithParent( + enum ObjectType eObjectType //e.g. OBJECTTYPE_DATA_POINT or OBJECTTYPE_GRID + , const OUString& rParticleID //e.g. Point Index or SubGrid Index + , const OUString& rParentPartical //e.g. "Series=SeriesID" or "Grid=GridId" + , const OUString& rDragMethodServiceName + , const OUString& rDragParameterString + ) + //, bool bIsMultiClickObject ) //e.g. true +{ + //e.g. "MultiClick/Series=2:Point=34" + + OUStringBuffer aRet( m_aProtocol ); + aRet.append( lcl_createClassificationStringForType( eObjectType, rDragMethodServiceName, rDragParameterString )); + if(aRet.getLength()>m_aProtocol.getLength()) + aRet.appendAscii("/"); + aRet.append(rParentPartical); + if(rParentPartical.getLength()) + aRet.appendAscii(":"); + + aRet.append(getStringForType( eObjectType )); + aRet.appendAscii("="); + aRet.append(rParticleID); + + return aRet.makeStringAndClear(); +} + +//static +const OUString& ObjectIdentifier::getPieSegmentDragMethodServiceName() +{ + return m_aPieSegmentDragMethodServiceName; +} + +//static +OUString ObjectIdentifier::createPieSegmentDragParameterString( + sal_Int32 nOffsetPercent + , const awt::Point& rMinimumPosition + , const awt::Point& rMaximumPosition ) +{ + OUStringBuffer aRet( OUString::valueOf( nOffsetPercent ) ); + aRet.append( sal_Unicode( ',' )); + aRet.append( OUString::valueOf( rMinimumPosition.X ) ); + aRet.append( sal_Unicode( ',' )); + aRet.append( OUString::valueOf( rMinimumPosition.Y ) ); + aRet.append( sal_Unicode( ',' )); + aRet.append( OUString::valueOf( rMaximumPosition.X ) ); + aRet.append( sal_Unicode( ',' )); + aRet.append( OUString::valueOf( rMaximumPosition.Y ) ); + return aRet.makeStringAndClear(); +} + +//static +bool ObjectIdentifier::parsePieSegmentDragParameterString( + const OUString& rDragParameterString + , sal_Int32& rOffsetPercent + , awt::Point& rMinimumPosition + , awt::Point& rMaximumPosition ) +{ + OUString aValue; + sal_Int32 nCharacterIndex = 0; + + OUString aValueString( rDragParameterString.getToken( 0, ',', nCharacterIndex ) ); + rOffsetPercent = aValueString.toInt32(); + if( nCharacterIndex < 0 ) + return false; + + aValueString = rDragParameterString.getToken( 0, ',', nCharacterIndex ); + rMinimumPosition.X = aValueString.toInt32(); + if( nCharacterIndex < 0 ) + return false; + + aValueString = rDragParameterString.getToken( 0, ',', nCharacterIndex ); + rMinimumPosition.Y = aValueString.toInt32(); + if( nCharacterIndex < 0 ) + return false; + + aValueString = rDragParameterString.getToken( 0, ',', nCharacterIndex ); + rMaximumPosition.X = aValueString.toInt32(); + if( nCharacterIndex < 0 ) + return false; + + aValueString = rDragParameterString.getToken( 0, ',', nCharacterIndex ); + rMaximumPosition.Y = aValueString.toInt32(); + if( nCharacterIndex < 0 ) + return false; + + return true; +} + +//static +OUString ObjectIdentifier::getDragMethodServiceName( const OUString& rCID ) +{ + OUString aRet; + + sal_Int32 nIndexStart = rCID.indexOf( m_aDragMethodEquals ); + if( nIndexStart != -1 ) + { + nIndexStart = rCID.indexOf( '=', nIndexStart ); + if( nIndexStart != -1 ) + { + nIndexStart++; + sal_Int32 nNextSlash = rCID.indexOf( '/', nIndexStart ); + if( nNextSlash != -1 ) + { + sal_Int32 nIndexEnd = nNextSlash; + sal_Int32 nNextColon = rCID.indexOf( ':', nIndexStart ); + if( nNextColon < nNextSlash ) + nIndexEnd = nNextColon; + aRet = rCID.copy(nIndexStart,nIndexEnd-nIndexStart); + } + } + } + return aRet; +} + +//static +OUString ObjectIdentifier::getDragParameterString( const OUString& rCID ) +{ + OUString aRet; + + sal_Int32 nIndexStart = rCID.indexOf( m_aDragParameterEquals ); + if( nIndexStart != -1 ) + { + nIndexStart = rCID.indexOf( '=', nIndexStart ); + if( nIndexStart != -1 ) + { + nIndexStart++; + sal_Int32 nNextSlash = rCID.indexOf( '/', nIndexStart ); + if( nNextSlash != -1 ) + { + sal_Int32 nIndexEnd = nNextSlash; + sal_Int32 nNextColon = rCID.indexOf( ':', nIndexStart ); + if( nNextColon < nNextSlash ) + nIndexEnd = nNextColon; + aRet = rCID.copy(nIndexStart,nIndexEnd-nIndexStart); + } + } + } + return aRet; +} + +//static +bool ObjectIdentifier::isDragableObject( const OUString& rClassifiedIdentifier ) +{ + ObjectType eObjectType = ObjectIdentifier::getObjectType( rClassifiedIdentifier ); + switch( eObjectType ) + { + case OBJECTTYPE_TITLE: + case OBJECTTYPE_LEGEND: + case OBJECTTYPE_DIAGRAM: + case OBJECTTYPE_DATA_CURVE_EQUATION: + //case OBJECTTYPE_DIAGRAM_WALL: + return true; + default: + OUString aDragMethodServiceName( ObjectIdentifier::getDragMethodServiceName( rClassifiedIdentifier ) ); + if( aDragMethodServiceName.getLength() ) + return true; + return false; + } + return false; +} + +bool ObjectIdentifier::isDragableObject() +{ + bool bReturn = false; + if ( isAutoGeneratedObject() ) + { + bReturn = isDragableObject( m_aObjectCID ); + } + else if ( isAdditionalShape() ) + { + bReturn = true; + } + return bReturn; +} + +//static +bool ObjectIdentifier::isRotateableObject( const OUString& rClassifiedIdentifier ) +{ + ObjectType eObjectType = ObjectIdentifier::getObjectType( rClassifiedIdentifier ); + switch( eObjectType ) + { + case OBJECTTYPE_DIAGRAM: + //case OBJECTTYPE_DIAGRAM_WALL: + return true; + default: + return false; + } + return false; +} + +//static +bool ObjectIdentifier::isMultiClickObject( const OUString& rClassifiedIdentifier ) +{ + //the name of a shape is it's ClassifiedIdentifier + + //a MultiClickObject is an object that is selectable by more than one click only ; + //before a MultiClickObject can be selected it is necessary that a named parent group object + //was selected before; + + //!!!!! by definition the name of a MultiClickObject starts with "CID/MultiClick:" + bool bRet = false; + bRet = rClassifiedIdentifier.match( m_aMultiClick, m_aProtocol.getLength() ); + return bRet; +} + +bool ObjectIdentifier::areSiblings( const OUString& rCID1, const OUString& rCID2 ) +{ + bool bRet=false; + sal_Int32 nLastSign1 = rCID1.lastIndexOf( '=' ); + sal_Int32 nLastSign2 = rCID2.lastIndexOf( '=' ); + if( nLastSign1 == rCID1.indexOf( '=' ) )//CID cannot be sibling if only one "=" occurs + bRet=false; + else if( nLastSign2 == rCID2.indexOf( '=' ) )//CID cannot be sibling if only one "=" occurs + bRet=false; + else if( ObjectIdentifier::areIdenticalObjects( rCID1, rCID2 ) ) + bRet=false; + else + { + OUString aParent1( ObjectIdentifier::getFullParentParticle( rCID1 ) ); + if( aParent1.getLength() ) + { + OUString aParent2( ObjectIdentifier::getFullParentParticle( rCID2 ) ); + bRet=aParent1.equals(aParent2); + } + //legend entries are special: + if(!bRet) + { + if( OBJECTTYPE_LEGEND_ENTRY == getObjectType(rCID1) + && OBJECTTYPE_LEGEND_ENTRY == getObjectType(rCID2) ) + bRet = true; + } + } + return bRet; +} + +bool ObjectIdentifier::areIdenticalObjects( const OUString& rCID1, const OUString& rCID2 ) +{ + if( rCID1.equals( rCID2 ) ) + return true; + //draggable pie or donut segments need special treatment, as their CIDs do change with offset + { + if( rCID1.indexOf( m_aPieSegmentDragMethodServiceName ) < 0 + || rCID2.indexOf( m_aPieSegmentDragMethodServiceName ) < 0 ) + return false; + + OUString aID1( ObjectIdentifier::getObjectID( rCID1 ) ); + OUString aID2( ObjectIdentifier::getObjectID( rCID2 ) ); + if( aID1.getLength() && aID1.equals( aID2 ) ) + return true; + } + return false; +} + +//static +OUString ObjectIdentifier::getStringForType( ObjectType eObjectType ) +{ + OUString aRet; + switch( eObjectType ) + { + case OBJECTTYPE_PAGE: + aRet=C2U("Page"); + break; + case OBJECTTYPE_TITLE: + aRet=C2U("Title"); + break; + case OBJECTTYPE_LEGEND: + aRet=C2U("Legend"); + break; + case OBJECTTYPE_LEGEND_ENTRY: + aRet=C2U("LegendEntry"); + break; + case OBJECTTYPE_DIAGRAM: + aRet=C2U("D"); + break; + case OBJECTTYPE_DIAGRAM_WALL: + aRet=C2U("DiagramWall"); + break; + case OBJECTTYPE_DIAGRAM_FLOOR: + aRet=C2U("DiagramFloor"); + break; + case OBJECTTYPE_AXIS: + aRet=C2U("Axis"); + break; + case OBJECTTYPE_AXIS_UNITLABEL: + aRet=C2U("AxisUnitLabel"); + break; + case OBJECTTYPE_GRID: + aRet=C2U("Grid"); + break; + case OBJECTTYPE_SUBGRID: + aRet=C2U("SubGrid"); + break; + case OBJECTTYPE_DATA_SERIES: + aRet=C2U("Series"); + break; + case OBJECTTYPE_DATA_POINT: + aRet=C2U("Point"); + break; + case OBJECTTYPE_DATA_LABELS: + aRet=C2U("DataLabels"); + break; + case OBJECTTYPE_DATA_LABEL: + aRet=C2U("DataLabel"); + break; + case OBJECTTYPE_DATA_ERRORS: + aRet=C2U("Errors"); + break; + case OBJECTTYPE_DATA_ERRORS_X: + aRet=C2U("ErrorsX"); + break; + case OBJECTTYPE_DATA_ERRORS_Y: + aRet=C2U("ErrorsY"); + break; + case OBJECTTYPE_DATA_ERRORS_Z: + aRet=C2U("ErrorsZ"); + break; + case OBJECTTYPE_DATA_CURVE: + aRet=C2U("Curve"); + break; + case OBJECTTYPE_DATA_CURVE_EQUATION: + aRet=C2U("Equation"); + break; + case OBJECTTYPE_DATA_AVERAGE_LINE: + aRet=C2U("Average"); + break; + case OBJECTTYPE_DATA_STOCK_RANGE: + aRet=C2U("StockRange"); + break; + case OBJECTTYPE_DATA_STOCK_LOSS: + aRet=C2U("StockLoss"); + break; + case OBJECTTYPE_DATA_STOCK_GAIN: + aRet=C2U("StockGain"); + break; + default: //OBJECTTYPE_UNKNOWN + ; + } + return aRet; +} + +//static +ObjectType ObjectIdentifier::getObjectType( const OUString& rCID ) +{ + ObjectType eRet; + sal_Int32 nLastSign = rCID.lastIndexOf( ':' );//last sign before the type string + if(nLastSign==-1) + nLastSign = rCID.lastIndexOf( '/' ); + if(nLastSign==-1) + { + sal_Int32 nEndIndex = rCID.lastIndexOf( '=' ); + if(nEndIndex==-1) + return OBJECTTYPE_UNKNOWN; + nLastSign = 0; + } + if( nLastSign>0 ) + nLastSign++; + + if( rCID.match(C2U("Page"),nLastSign) ) + eRet = OBJECTTYPE_PAGE; + else if( rCID.match(C2U("Title"),nLastSign) ) + eRet = OBJECTTYPE_TITLE; + else if( rCID.match(C2U("LegendEntry"),nLastSign) ) + eRet = OBJECTTYPE_LEGEND_ENTRY; + else if( rCID.match(C2U("Legend"),nLastSign) ) + eRet = OBJECTTYPE_LEGEND; + else if( rCID.match(C2U("DiagramWall"),nLastSign) ) + eRet = OBJECTTYPE_DIAGRAM_WALL; + else if( rCID.match(C2U("DiagramFloor"),nLastSign) ) + eRet = OBJECTTYPE_DIAGRAM_FLOOR; + else if( rCID.match(C2U("D="),nLastSign) ) + eRet = OBJECTTYPE_DIAGRAM; + else if( rCID.match(C2U("AxisUnitLabel"),nLastSign) ) + eRet = OBJECTTYPE_AXIS_UNITLABEL; + else if( rCID.match(C2U("Axis"),nLastSign) ) + eRet = OBJECTTYPE_AXIS; + else if( rCID.match(C2U("Grid"),nLastSign) ) + eRet = OBJECTTYPE_GRID; + else if( rCID.match(C2U("SubGrid"),nLastSign) ) + eRet = OBJECTTYPE_SUBGRID; + else if( rCID.match(C2U("Series"),nLastSign) ) + eRet = OBJECTTYPE_DATA_SERIES; + else if( rCID.match(C2U("Point"),nLastSign) ) + eRet = OBJECTTYPE_DATA_POINT; + else if( rCID.match(C2U("DataLabels"),nLastSign) ) + eRet = OBJECTTYPE_DATA_LABELS; + else if( rCID.match(C2U("DataLabel"),nLastSign) ) + eRet = OBJECTTYPE_DATA_LABEL; + else if( rCID.match(C2U("ErrorsX"),nLastSign) ) + eRet = OBJECTTYPE_DATA_ERRORS_X; + else if( rCID.match(C2U("ErrorsY"),nLastSign) ) + eRet = OBJECTTYPE_DATA_ERRORS_Y; + else if( rCID.match(C2U("ErrorsZ"),nLastSign) ) + eRet = OBJECTTYPE_DATA_ERRORS_Z; + else if( rCID.match(C2U("Errors"),nLastSign) ) + eRet = OBJECTTYPE_DATA_ERRORS; + else if( rCID.match(C2U("Curve"),nLastSign) ) + eRet = OBJECTTYPE_DATA_CURVE; + else if( rCID.match(C2U("Equation"),nLastSign) ) + eRet = OBJECTTYPE_DATA_CURVE_EQUATION; + else if( rCID.match(C2U("Average"),nLastSign) ) + eRet = OBJECTTYPE_DATA_AVERAGE_LINE; + else if( rCID.match(C2U("StockRange"),nLastSign) ) + eRet = OBJECTTYPE_DATA_STOCK_RANGE; + else if( rCID.match(C2U("StockLoss"),nLastSign) ) + eRet = OBJECTTYPE_DATA_STOCK_LOSS; + else if( rCID.match(C2U("StockGain"),nLastSign) ) + eRet = OBJECTTYPE_DATA_STOCK_GAIN; + else + eRet = OBJECTTYPE_UNKNOWN; + + return eRet; +} + +ObjectType ObjectIdentifier::getObjectType() +{ + ObjectType eObjectType( OBJECTTYPE_UNKNOWN ); + if ( isAutoGeneratedObject() ) + { + eObjectType = getObjectType( m_aObjectCID ); + } + else if ( isAdditionalShape() ) + { + eObjectType = OBJECTTYPE_SHAPE; + } + return eObjectType; +} + +//static +OUString ObjectIdentifier::createDataCurveCID( + const OUString& rSeriesParticle + , sal_Int32 nCurveIndex + , bool bAverageLine ) +{ + OUString aParticleID( OUString::valueOf( nCurveIndex ) ); + ObjectType eType = bAverageLine ? OBJECTTYPE_DATA_AVERAGE_LINE : OBJECTTYPE_DATA_CURVE; + return createClassifiedIdentifierWithParent( eType, aParticleID, rSeriesParticle ); +} + +//static +OUString ObjectIdentifier::createDataCurveEquationCID( + const OUString& rSeriesParticle + , sal_Int32 nCurveIndex ) +{ + OUString aParticleID( OUString::valueOf( nCurveIndex ) ); + return createClassifiedIdentifierWithParent( OBJECTTYPE_DATA_CURVE_EQUATION, aParticleID, rSeriesParticle ); +} + +//static +OUString ObjectIdentifier::addChildParticle( const rtl::OUString& rParticle, const rtl::OUString& rChildParticle ) +{ + OUStringBuffer aRet(rParticle); + + if( aRet.getLength() && rChildParticle.getLength() ) + aRet.appendAscii(":"); + if( rChildParticle.getLength() ) + aRet.append(rChildParticle); + + return aRet.makeStringAndClear(); +} + +//static +rtl::OUString ObjectIdentifier::createChildParticleWithIndex( ObjectType eObjectType, sal_Int32 nIndex ) +{ + OUStringBuffer aRet( getStringForType( eObjectType ) ); + if( aRet.getLength() ) + { + aRet.appendAscii("="); + aRet.append(OUString::valueOf(nIndex)); + } + return aRet.makeStringAndClear(); +} + +//static +sal_Int32 ObjectIdentifier::getIndexFromParticleOrCID( const rtl::OUString& rParticleOrCID ) +{ + sal_Int32 nRet = -1; + + OUString aIndexString = lcl_getIndexStringAfterString( rParticleOrCID, C2U("=") ); + sal_Int32 nCharacterIndex=0; + nRet = lcl_StringToIndex( aIndexString.getToken( 0, ',', nCharacterIndex ) ); + + return nRet; +} + +//static +OUString ObjectIdentifier::createSeriesSubObjectStub( ObjectType eSubObjectType + , const rtl::OUString& rSeriesParticle + , const rtl::OUString& rDragMethodServiceName + , const rtl::OUString& rDragParameterString ) +{ + OUString aChildParticle( getStringForType( eSubObjectType ) ); + aChildParticle+=(C2U("=")); + + return createClassifiedIdentifierForParticles( + rSeriesParticle, aChildParticle + , rDragMethodServiceName, rDragParameterString ); +} + +//static +OUString ObjectIdentifier::createPointCID( const OUString& rPointCID_Stub, sal_Int32 nIndex ) +{ + OUString aRet(rPointCID_Stub); + return aRet+=OUString::valueOf( nIndex ); +} + +//static +OUString ObjectIdentifier::getParticleID( const OUString& rCID ) +{ + OUString aRet; + sal_Int32 nLast = rCID.lastIndexOf('='); + if(nLast>=0) + aRet = rCID.copy(++nLast); + return aRet; +} + +//static +OUString ObjectIdentifier::getFullParentParticle( const OUString& rCID ) +{ + OUString aRet; + + sal_Int32 nStartPos = rCID.lastIndexOf('/'); + if( nStartPos>=0 ) + { + nStartPos++; + sal_Int32 nEndPos = rCID.lastIndexOf(':'); + if( nEndPos>=0 && nStartPos < nEndPos ) + { + aRet = rCID.copy(nStartPos,nEndPos-nStartPos); + } + } + + return aRet; +} + +//static +OUString ObjectIdentifier::getObjectID( const rtl::OUString& rCID ) +{ + OUString aRet; + + sal_Int32 nStartPos = rCID.lastIndexOf('/'); + if( nStartPos>=0 ) + { + nStartPos++; + sal_Int32 nEndPos = rCID.getLength(); + aRet = rCID.copy(nStartPos,nEndPos-nStartPos); + } + + return aRet; +} + +//static +bool ObjectIdentifier::isCID( const OUString& rName ) +{ + return rName.getLength() && rName.match( m_aProtocol ); +} + +Reference< beans::XPropertySet > ObjectIdentifier::getObjectPropertySet( + const OUString& rObjectCID, + const Reference< chart2::XChartDocument >& xChartDocument ) +{ + return ObjectIdentifier::getObjectPropertySet( + rObjectCID, Reference< frame::XModel >( xChartDocument, uno::UNO_QUERY )); +} + +//static +Reference< beans::XPropertySet > ObjectIdentifier::getObjectPropertySet( + const OUString& rObjectCID + , const Reference< frame::XModel >& xChartModel ) +{ + //return the model object that is indicated by rObjectCID + if(!rObjectCID.getLength()) + return NULL; + if(!xChartModel.is()) + return NULL; + + Reference< beans::XPropertySet > xObjectProperties = NULL; + try + { + ObjectType eObjectType = ObjectIdentifier::getObjectType( rObjectCID ); + OUString aParticleID = ObjectIdentifier::getParticleID( rObjectCID ); + + Reference< XDiagram > xDiagram; + Reference< XCoordinateSystem > xCooSys; + lcl_getDiagramAndCooSys( rObjectCID, xChartModel, xDiagram, xCooSys ); + + switch(eObjectType) + { + case OBJECTTYPE_PAGE: + { + Reference< XChartDocument > xChartDocument( xChartModel, uno::UNO_QUERY ); + if( xChartDocument.is()) + xObjectProperties.set( xChartDocument->getPageBackground() ); + } + break; + case OBJECTTYPE_TITLE: + { + TitleHelper::eTitleType aTitleType = getTitleTypeForCID( rObjectCID ); + Reference< XTitle > xTitle( TitleHelper::getTitle( aTitleType, xChartModel ) ); + xObjectProperties.set( xTitle, uno::UNO_QUERY ); + } + break; + case OBJECTTYPE_LEGEND: + { + if( xDiagram.is() ) + xObjectProperties.set( xDiagram->getLegend(), uno::UNO_QUERY ); + } + break; + case OBJECTTYPE_LEGEND_ENTRY: + break; + case OBJECTTYPE_DIAGRAM: + { + xObjectProperties.set( xDiagram, uno::UNO_QUERY ); + } + break; + case OBJECTTYPE_DIAGRAM_WALL: + { + if( xDiagram.is() ) + xObjectProperties.set( xDiagram->getWall() ); + } + break; + case OBJECTTYPE_DIAGRAM_FLOOR: + { + if( xDiagram.is() ) + xObjectProperties.set( xDiagram->getFloor() ); + } + break; + case OBJECTTYPE_AXIS: + { + sal_Int32 nDimensionIndex = -1; + sal_Int32 nAxisIndex = -1; + lcl_parseAxisIndices( nDimensionIndex, nAxisIndex, rObjectCID ); + + Reference< chart2::XAxis > xAxis( + AxisHelper::getAxis( nDimensionIndex, nAxisIndex, xCooSys ) ); + if( xAxis.is() ) + xObjectProperties.set( xAxis, uno::UNO_QUERY ); + } + break; + case OBJECTTYPE_AXIS_UNITLABEL: + break; + case OBJECTTYPE_GRID: + case OBJECTTYPE_SUBGRID: + { + sal_Int32 nDimensionIndex = -1; + sal_Int32 nAxisIndex = -1; + lcl_parseAxisIndices( nDimensionIndex, nAxisIndex, rObjectCID ); + + sal_Int32 nSubGridIndex = -1; + lcl_parseGridIndices( nSubGridIndex, rObjectCID ); + + xObjectProperties.set( AxisHelper::getGridProperties( xCooSys , nDimensionIndex, nAxisIndex, nSubGridIndex ) ); + } + break; + case OBJECTTYPE_DATA_LABELS: + case OBJECTTYPE_DATA_SERIES: + { + Reference< XDataSeries > xSeries( ObjectIdentifier::getDataSeriesForCID( + rObjectCID, xChartModel ) ); + if( xSeries.is() ) + xObjectProperties = Reference< beans::XPropertySet >( xSeries, uno::UNO_QUERY ); + + break; + } + case OBJECTTYPE_DATA_LABEL: + case OBJECTTYPE_DATA_POINT: + { + Reference< XDataSeries > xSeries( ObjectIdentifier::getDataSeriesForCID( + rObjectCID, xChartModel ) ); + if(xSeries.is()) + { + sal_Int32 nIndex = aParticleID.toInt32(); + xObjectProperties = xSeries->getDataPointByIndex( nIndex ); + } + break; + } + case OBJECTTYPE_DATA_ERRORS: + { + Reference< XDataSeries > xSeries( ObjectIdentifier::getDataSeriesForCID( + rObjectCID, xChartModel ) ); + if(xSeries.is()) + { + Reference< beans::XPropertySet > xSeriesProp( xSeries, uno::UNO_QUERY ); + Reference< beans::XPropertySet > xErrorBarProp; + if( xSeriesProp.is() ) + { + xSeriesProp->getPropertyValue( C2U( "ErrorBarY" )) >>= xErrorBarProp; + xObjectProperties = Reference< beans::XPropertySet >( xErrorBarProp, uno::UNO_QUERY ); + } + } + break; + } + case OBJECTTYPE_DATA_ERRORS_X: + break; + case OBJECTTYPE_DATA_ERRORS_Y: + break; + case OBJECTTYPE_DATA_ERRORS_Z: + break; + case OBJECTTYPE_DATA_AVERAGE_LINE: + case OBJECTTYPE_DATA_CURVE: + case OBJECTTYPE_DATA_CURVE_EQUATION: + { + Reference< XRegressionCurveContainer > xRegressionContainer( ObjectIdentifier::getDataSeriesForCID( + rObjectCID, xChartModel ), uno::UNO_QUERY ); + if(xRegressionContainer.is()) + { + sal_Int32 nIndex = aParticleID.toInt32(); + uno::Sequence< Reference< XRegressionCurve > > aCurveList = + xRegressionContainer->getRegressionCurves(); + if( nIndex >= 0 && nIndex <aCurveList.getLength() ) + { + if( eObjectType == OBJECTTYPE_DATA_CURVE_EQUATION ) + xObjectProperties.set( aCurveList[nIndex]->getEquationProperties()); + else + xObjectProperties.set( aCurveList[nIndex], uno::UNO_QUERY ); + } + } + break; + } + case OBJECTTYPE_DATA_STOCK_RANGE: + break; + case OBJECTTYPE_DATA_STOCK_LOSS: + { + Reference<XChartType> xChartType( lcl_getFirstStockChartType( xChartModel ) ); + Reference< beans::XPropertySet > xChartTypeProps( xChartType, uno::UNO_QUERY ); + if(xChartTypeProps.is()) + xChartTypeProps->getPropertyValue( C2U( "BlackDay" ) ) >>= xObjectProperties; + } + break; + case OBJECTTYPE_DATA_STOCK_GAIN: + { + Reference<XChartType> xChartType( lcl_getFirstStockChartType( xChartModel ) ); + Reference< beans::XPropertySet > xChartTypeProps( xChartType, uno::UNO_QUERY ); + if(xChartTypeProps.is()) + xChartTypeProps->getPropertyValue( C2U( "WhiteDay" ) ) >>= xObjectProperties; + } + break; + default: //OBJECTTYPE_UNKNOWN + break; + } + } + catch( uno::Exception& ex) + { + ASSERT_EXCEPTION( ex ); + } + return xObjectProperties; +} + +//static +Reference< XAxis > ObjectIdentifier::getAxisForCID( + const OUString& rObjectCID + , const Reference< frame::XModel >& xChartModel ) +{ + Reference< XDiagram > xDiagram; + Reference< XCoordinateSystem > xCooSys; + lcl_getDiagramAndCooSys( rObjectCID, xChartModel, xDiagram, xCooSys ); + + sal_Int32 nDimensionIndex = -1; + sal_Int32 nAxisIndex = -1; + lcl_parseAxisIndices( nDimensionIndex, nAxisIndex, rObjectCID ); + + return AxisHelper::getAxis( nDimensionIndex, nAxisIndex, xCooSys ); +} + +//static +Reference< XDataSeries > ObjectIdentifier::getDataSeriesForCID( + const OUString& rObjectCID + , const Reference< frame::XModel >& xChartModel ) +{ + Reference< XDataSeries > xSeries(NULL); + + Reference< XDiagram > xDiagram; + Reference< XCoordinateSystem > xCooSys; + lcl_getDiagramAndCooSys( rObjectCID, xChartModel, xDiagram, xCooSys ); + + sal_Int32 nChartTypeIndex = -1; + sal_Int32 nSeriesIndex = -1; + sal_Int32 nPointIndex = -1; + lcl_parseSeriesIndices( nChartTypeIndex, nSeriesIndex, nPointIndex, rObjectCID ); + + Reference< XDataSeriesContainer > xDataSeriesContainer( DiagramHelper::getChartTypeByIndex( xDiagram, nChartTypeIndex ), uno::UNO_QUERY ); + if( xDataSeriesContainer.is() ) + { + uno::Sequence< uno::Reference< XDataSeries > > aDataSeriesSeq( xDataSeriesContainer->getDataSeries() ); + if( nSeriesIndex >= 0 && nSeriesIndex < aDataSeriesSeq.getLength() ) + xSeries.set( aDataSeriesSeq[nSeriesIndex] ); + } + + return xSeries; +} + +//static +Reference< XDiagram > ObjectIdentifier::getDiagramForCID( + const rtl::OUString& rObjectCID + , const uno::Reference< frame::XModel >& xChartModel ) +{ + Reference< XDiagram > xDiagram; + + Reference< XCoordinateSystem > xCooSys; + lcl_getDiagramAndCooSys( rObjectCID, xChartModel, xDiagram, xCooSys ); + + return xDiagram; +} + +TitleHelper::eTitleType ObjectIdentifier::getTitleTypeForCID( const OUString& rCID ) +{ + TitleHelper::eTitleType eRet( TitleHelper::MAIN_TITLE ); + + OUString aParentParticle = ObjectIdentifier::getFullParentParticle( rCID ); + const tTitleMap& rMap = lcl_getTitleMap(); + tTitleMap::const_iterator aIt( rMap.begin() ); + for( ;aIt != rMap.end(); ++aIt ) + { + if( aParentParticle.equals( (*aIt).second ) ) + { + eRet = (*aIt).first; + break; + } + } + + return eRet; +} + +// static +OUString ObjectIdentifier::getSeriesParticleFromCID( const OUString& rCID ) +{ + sal_Int32 nDiagramIndex = -1; + sal_Int32 nCooSysIndex = -1; + lcl_parseCooSysIndices( nDiagramIndex, nCooSysIndex, rCID ); + + sal_Int32 nChartTypeIndex = -1; + sal_Int32 nSeriesIndex = -1; + sal_Int32 nPointIndex = -1; + lcl_parseSeriesIndices( nChartTypeIndex, nSeriesIndex, nPointIndex, rCID ); + + return ObjectIdentifier::createParticleForSeries( nDiagramIndex, nCooSysIndex, nChartTypeIndex, nSeriesIndex ); +} + +//static +OUString ObjectIdentifier::getMovedSeriesCID( const ::rtl::OUString& rObjectCID, sal_Bool bForward ) +{ + sal_Int32 nDiagramIndex = lcl_StringToIndex( lcl_getIndexStringAfterString( rObjectCID, C2U("CID/D=") ) ); + sal_Int32 nCooSysIndex = lcl_StringToIndex( lcl_getIndexStringAfterString( rObjectCID, C2U("CS=") ) ); + sal_Int32 nChartTypeIndex = lcl_StringToIndex( lcl_getIndexStringAfterString( rObjectCID, C2U("CT=") ) ); + sal_Int32 nSeriesIndex = lcl_StringToIndex( lcl_getIndexStringAfterString( rObjectCID, C2U("Series=") ) ); + + if( bForward ) + nSeriesIndex--; + else + nSeriesIndex++; + + OUString aRet = ObjectIdentifier::createParticleForSeries( nDiagramIndex, nCooSysIndex, nChartTypeIndex, nSeriesIndex ); + return ObjectIdentifier::createClassifiedIdentifierForParticle( aRet ); +} + +bool ObjectIdentifier::isValid() const +{ + return ( isAutoGeneratedObject() || isAdditionalShape() ); +} + +bool ObjectIdentifier::isAutoGeneratedObject() const +{ + return ( m_aObjectCID.getLength() > 0 ); +} + +bool ObjectIdentifier::isAdditionalShape() const +{ + return m_xAdditionalShape.is(); +} + +OUString ObjectIdentifier::getObjectCID() const +{ + return m_aObjectCID; +} + +Reference< drawing::XShape > ObjectIdentifier::getAdditionalShape() const +{ + return m_xAdditionalShape; +} + +Any ObjectIdentifier::getAny() const +{ + Any aAny; + if ( isAutoGeneratedObject() ) + { + aAny = uno::makeAny( getObjectCID() ); + } + else if ( isAdditionalShape() ) + { + aAny = uno::makeAny( getAdditionalShape() ); + } + return aAny; +} + +//............................................................................. +} //namespace chart +//............................................................................. diff --git a/chart2/source/tools/PotentialRegressionCurveCalculator.cxx b/chart2/source/tools/PotentialRegressionCurveCalculator.cxx new file mode 100644 index 000000000000..b1d10424b9a1 --- /dev/null +++ b/chart2/source/tools/PotentialRegressionCurveCalculator.cxx @@ -0,0 +1,177 @@ +/************************************************************************* + * + * 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 "PotentialRegressionCurveCalculator.hxx" +#include "macros.hxx" +#include "RegressionCalculationHelper.hxx" + +#include <rtl/math.hxx> +#include <rtl/ustrbuf.hxx> + +using namespace ::com::sun::star; + +using ::rtl::OUString; +using ::rtl::OUStringBuffer; + +namespace chart +{ + +PotentialRegressionCurveCalculator::PotentialRegressionCurveCalculator() : + m_fSlope( 0.0 ), + m_fIntercept( 0.0 ) +{ + ::rtl::math::setNan( & m_fSlope ); + ::rtl::math::setNan( & m_fIntercept ); +} + +PotentialRegressionCurveCalculator::~PotentialRegressionCurveCalculator() +{} + +// ____ XRegressionCurveCalculator ____ +void SAL_CALL PotentialRegressionCurveCalculator::recalculateRegression( + const uno::Sequence< double >& aXValues, + const uno::Sequence< double >& aYValues ) + throw (uno::RuntimeException) +{ + RegressionCalculationHelper::tDoubleVectorPair aValues( + RegressionCalculationHelper::cleanup( + aXValues, aYValues, + RegressionCalculationHelper::isValidAndBothPositive())); + + const size_t nMax = aValues.first.size(); + if( nMax == 0 ) + { + ::rtl::math::setNan( & m_fSlope ); + ::rtl::math::setNan( & m_fIntercept ); + ::rtl::math::setNan( & m_fCorrelationCoeffitient ); + return; + } + + double fAverageX = 0.0, fAverageY = 0.0; + size_t i = 0; + for( i = 0; i < nMax; ++i ) + { + fAverageX += log( aValues.first[i] ); + fAverageY += log( aValues.second[i] ); + } + + const double fN = static_cast< double >( nMax ); + fAverageX /= fN; + fAverageY /= fN; + + double fQx = 0.0, fQy = 0.0, fQxy = 0.0; + for( i = 0; i < nMax; ++i ) + { + double fDeltaX = log( aValues.first[i] ) - fAverageX; + double fDeltaY = log( aValues.second[i] ) - fAverageY; + + fQx += fDeltaX * fDeltaX; + fQy += fDeltaY * fDeltaY; + fQxy += fDeltaX * fDeltaY; + } + + m_fSlope = fQxy / fQx; + m_fIntercept = fAverageY - m_fSlope * fAverageX; + m_fCorrelationCoeffitient = fQxy / sqrt( fQx * fQy ); + + m_fIntercept = exp( m_fIntercept ); +} + +double SAL_CALL PotentialRegressionCurveCalculator::getCurveValue( double x ) + throw (lang::IllegalArgumentException, + uno::RuntimeException) +{ + double fResult; + ::rtl::math::setNan( & fResult ); + + if( ! ( ::rtl::math::isNan( m_fSlope ) || + ::rtl::math::isNan( m_fIntercept ))) + { + fResult = m_fIntercept * pow( x, m_fSlope ); + } + + return fResult; +} + +uno::Sequence< geometry::RealPoint2D > SAL_CALL PotentialRegressionCurveCalculator::getCurveValues( + double min, double max, ::sal_Int32 nPointCount, + const uno::Reference< chart2::XScaling >& xScalingX, + const uno::Reference< chart2::XScaling >& xScalingY, + ::sal_Bool bMaySkipPointsInCalculation ) + throw (lang::IllegalArgumentException, + uno::RuntimeException) +{ + if( bMaySkipPointsInCalculation && + isLogarithmicScaling( xScalingX ) && + isLogarithmicScaling( xScalingY )) + { + // optimize result + uno::Sequence< geometry::RealPoint2D > aResult( 2 ); + aResult[0].X = min; + aResult[0].Y = this->getCurveValue( min ); + aResult[1].X = max; + aResult[1].Y = this->getCurveValue( max ); + + return aResult; + } + return RegressionCurveCalculator::getCurveValues( min, max, nPointCount, xScalingX, xScalingY, bMaySkipPointsInCalculation ); +} + +OUString PotentialRegressionCurveCalculator::ImplGetRepresentation( + const uno::Reference< util::XNumberFormatter >& xNumFormatter, + ::sal_Int32 nNumberFormatKey ) const +{ + OUStringBuffer aBuf( C2U( "f(x) = " )); + + if( m_fIntercept == 0.0 ) + { + aBuf.append( sal_Unicode( '0' )); + } + else if( m_fSlope == 0.0 ) + { + aBuf.append( getFormattedString( xNumFormatter, nNumberFormatKey, m_fIntercept )); + } + else + { + if( ! rtl::math::approxEqual( m_fIntercept, 1.0 ) ) + { + aBuf.append( getFormattedString( xNumFormatter, nNumberFormatKey, m_fIntercept )); + aBuf.append( sal_Unicode( ' ' )); + } + if( m_fSlope != 0.0 ) + { + aBuf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "x^" )); + aBuf.append( getFormattedString( xNumFormatter, nNumberFormatKey, m_fSlope )); + } + } + + return aBuf.makeStringAndClear(); +} + +} // namespace chart diff --git a/chart2/source/tools/PropertyHelper.cxx b/chart2/source/tools/PropertyHelper.cxx new file mode 100644 index 000000000000..dd0a1ad6cf2f --- /dev/null +++ b/chart2/source/tools/PropertyHelper.cxx @@ -0,0 +1,314 @@ +/************************************************************************* + * + * 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 "PropertyHelper.hxx" +#include "ContainerHelper.hxx" +#include "macros.hxx" +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/container/XNameContainer.hpp> + +#include <vector> +#include <algorithm> +#include <functional> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::beans; +using ::rtl::OUString; +using ::com::sun::star::uno::Any; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; + +namespace +{ +struct lcl_EqualsElement : public ::std::unary_function< OUString, bool > +{ + explicit lcl_EqualsElement( const Any & rValue, const Reference< container::XNameAccess > & xAccess ) + : m_aValue( rValue ), m_xAccess( xAccess ) + { + OSL_ASSERT( m_xAccess.is()); + } + + bool operator() ( const OUString & rName ) + { + try + { + return (m_xAccess->getByName( rName ) == m_aValue); + } + catch( const uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + return false; + } + +private: + Any m_aValue; + Reference< container::XNameAccess > m_xAccess; +}; + +struct lcl_StringMatches : public ::std::unary_function< OUString ,bool > +{ + lcl_StringMatches( const OUString & rCmpStr ) : + m_aCmpStr( rCmpStr ) + {} + + bool operator() ( const OUString & rStr ) + { + return rStr.match( m_aCmpStr ); + } + +private: + OUString m_aCmpStr; +}; + +struct lcl_OUStringRestToInt32 : public ::std::unary_function< OUString, sal_Int32 > +{ + lcl_OUStringRestToInt32( sal_Int32 nPrefixLength ) : + m_nPrefixLength( nPrefixLength ) + {} + sal_Int32 operator() ( const OUString & rStr ) + { + if( m_nPrefixLength > rStr.getLength() ) + return 0; + return rStr.copy( m_nPrefixLength ).toInt32( 10 /* radix */ ); + } +private: + sal_Int32 m_nPrefixLength; +}; + +/** adds a fill gradient, fill hatch, fill bitmap, fill transparency gradient, + line dash or line marker to the corresponding name container with a unique + name. + + @param rPrefix + The prefix used for automated name generation. + + @param rPreferredName + If this string is not empty it is used as name if it is unique in the + table. Otherwise a new name is generated using pPrefix. + + @return the new name under which the property was stored in the table +*/ +OUString lcl_addNamedPropertyUniqueNameToTable( + const Any & rValue, + const Reference< container::XNameContainer > & xNameContainer, + const OUString & rPrefix, + const OUString & rPreferredName ) +{ + if( ! xNameContainer.is() || + ! rValue.hasValue() || + ( rValue.getValueType() != xNameContainer->getElementType())) + return rPreferredName; + + try + { + Reference< container::XNameAccess > xNameAccess( xNameContainer, uno::UNO_QUERY_THROW ); + ::std::vector< OUString > aNames( ::chart::ContainerHelper::SequenceToVector( xNameAccess->getElementNames())); + ::std::vector< OUString >::const_iterator aIt( + ::std::find_if( aNames.begin(), aNames.end(), lcl_EqualsElement( rValue, xNameAccess ))); + + // element not found in container + if( aIt == aNames.end()) + { + OUString aUniqueName; + + // check if preferred name is already used + if( rPreferredName.getLength()) + { + aIt = ::std::find( aNames.begin(), aNames.end(), rPreferredName ); + if( aIt == aNames.end()) + aUniqueName = rPreferredName; + } + + if( ! aUniqueName.getLength()) + { + // create a unique id using the prefix plus a number + ::std::vector< sal_Int32 > aNumbers; + ::std::vector< OUString >::iterator aNonConstIt( + ::std::partition( aNames.begin(), aNames.end(), lcl_StringMatches( rPrefix ))); + ::std::transform( aNames.begin(), aNonConstIt, + back_inserter( aNumbers ), + lcl_OUStringRestToInt32( rPrefix.getLength() )); + ::std::vector< sal_Int32 >::const_iterator aMaxIt( + ::std::max_element( aNumbers.begin(), aNumbers.end())); + + sal_Int32 nIndex = 1; + if( aMaxIt != aNumbers.end()) + nIndex = (*aMaxIt) + 1; + + aUniqueName = rPrefix + OUString::valueOf( nIndex ); + } + + OSL_ASSERT( aUniqueName.getLength()); + xNameContainer->insertByName( aUniqueName, rValue ); + return aUniqueName; + } + else + // element found => return name + return *aIt; + } + catch( const uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + + return rPreferredName; +} + +} // anonymous namespace + +namespace chart +{ +namespace PropertyHelper +{ + +OUString addLineDashUniqueNameToTable( + const Any & rValue, + const Reference< lang::XMultiServiceFactory > & xFact, + const OUString & rPreferredName ) +{ + if( xFact.is()) + { + Reference< container::XNameContainer > xNameCnt( + xFact->createInstance( C2U( "com.sun.star.drawing.DashTable" )), + uno::UNO_QUERY ); + if( xNameCnt.is()) + return lcl_addNamedPropertyUniqueNameToTable( + rValue, xNameCnt, C2U( "ChartDash " ), rPreferredName ); + } + return OUString(); +} + +OUString addGradientUniqueNameToTable( + const Any & rValue, + const Reference< lang::XMultiServiceFactory > & xFact, + const OUString & rPreferredName ) +{ + if( xFact.is()) + { + Reference< container::XNameContainer > xNameCnt( + xFact->createInstance( C2U( "com.sun.star.drawing.GradientTable" )), + uno::UNO_QUERY ); + if( xNameCnt.is()) + return lcl_addNamedPropertyUniqueNameToTable( + rValue, xNameCnt, C2U( "ChartGradient " ), rPreferredName ); + } + return OUString(); +} + + +OUString addTransparencyGradientUniqueNameToTable( + const Any & rValue, + const Reference< lang::XMultiServiceFactory > & xFact, + const OUString & rPreferredName ) +{ + if( xFact.is()) + { + Reference< container::XNameContainer > xNameCnt( + xFact->createInstance( C2U( "com.sun.star.drawing.TransparencyGradientTable" )), + uno::UNO_QUERY ); + if( xNameCnt.is()) + return lcl_addNamedPropertyUniqueNameToTable( + rValue, xNameCnt, C2U( "ChartTransparencyGradient " ), rPreferredName ); + } + return OUString(); +} + +OUString addHatchUniqueNameToTable( + const Any & rValue, + const Reference< lang::XMultiServiceFactory > & xFact, + const OUString & rPreferredName ) +{ + if( xFact.is()) + { + Reference< container::XNameContainer > xNameCnt( + xFact->createInstance( C2U( "com.sun.star.drawing.HatchTable" )), + uno::UNO_QUERY ); + if( xNameCnt.is()) + return lcl_addNamedPropertyUniqueNameToTable( + rValue, xNameCnt, C2U( "ChartHatch " ), rPreferredName ); + } + return OUString(); +} + +OUString addBitmapUniqueNameToTable( + const Any & rValue, + const Reference< lang::XMultiServiceFactory > & xFact, + const OUString & rPreferredName ) +{ + if( xFact.is()) + { + Reference< container::XNameContainer > xNameCnt( + xFact->createInstance( C2U( "com.sun.star.drawing.BitmapTable" )), + uno::UNO_QUERY ); + if( xNameCnt.is()) + return lcl_addNamedPropertyUniqueNameToTable( + rValue, xNameCnt, C2U( "ChartBitmap " ), rPreferredName ); + } + return OUString(); +} + +// ---------------------------------------- + +void setPropertyValueAny( tPropertyValueMap & rOutMap, tPropertyValueMapKey key, const uno::Any & rAny ) +{ + tPropertyValueMap::iterator aIt( rOutMap.find( key )); + if( aIt == rOutMap.end()) + rOutMap.insert( tPropertyValueMap::value_type( key, rAny )); + else + (*aIt).second = rAny; +} + +template<> + void setPropertyValue< ::com::sun::star::uno::Any >( tPropertyValueMap & rOutMap, tPropertyValueMapKey key, const ::com::sun::star::uno::Any & rAny ) +{ + setPropertyValueAny( rOutMap, key, rAny ); +} + +void setPropertyValueDefaultAny( tPropertyValueMap & rOutMap, tPropertyValueMapKey key, const uno::Any & rAny ) +{ + OSL_ENSURE( rOutMap.end() == rOutMap.find( key ), "Default already exists for property" ); + setPropertyValue( rOutMap, key, rAny ); +} + +template<> + void setPropertyValueDefault< ::com::sun::star::uno::Any >( tPropertyValueMap & rOutMap, tPropertyValueMapKey key, const ::com::sun::star::uno::Any & rAny ) +{ + setPropertyValueDefaultAny( rOutMap, key, rAny ); +} + + +void setEmptyPropertyValueDefault( tPropertyValueMap & rOutMap, tPropertyValueMapKey key ) +{ + setPropertyValueDefault( rOutMap, key, uno::Any()); +} + +} // namespace PropertyHelper + +} // namespace chart diff --git a/chart2/source/tools/RangeHighlighter.cxx b/chart2/source/tools/RangeHighlighter.cxx new file mode 100644 index 000000000000..1565344923b1 --- /dev/null +++ b/chart2/source/tools/RangeHighlighter.cxx @@ -0,0 +1,406 @@ +/************************************************************************* + * + * 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 "RangeHighlighter.hxx" +#include "WeakListenerAdapter.hxx" +#include "ChartModelHelper.hxx" +#include "DataSourceHelper.hxx" +#include "ContainerHelper.hxx" +#include "macros.hxx" +#include "ObjectIdentifier.hxx" +#include "DataSeriesHelper.hxx" + +#include <com/sun/star/chart2/XDataSeries.hpp> +#include <com/sun/star/chart/ErrorBarStyle.hpp> +#include <com/sun/star/drawing/XShape.hpp> + +#define PREFERED_DEFAULT_COLOR 0x0000ff + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::rtl::OUString; + +namespace +{ + +void lcl_fillRanges( + Sequence< chart2::data::HighlightedRange > & rOutRanges, + Sequence< OUString > aRangeStrings, + sal_Int32 nPreferredColor = PREFERED_DEFAULT_COLOR, + sal_Int32 nIndex = -1 ) +{ + rOutRanges.realloc( aRangeStrings.getLength()); + for( sal_Int32 i=0; i<aRangeStrings.getLength(); ++i ) + { + rOutRanges[i].RangeRepresentation = aRangeStrings[i]; + rOutRanges[i].PreferredColor = nPreferredColor; + rOutRanges[i].AllowMerginigWithOtherRanges = sal_False; + rOutRanges[i].Index = nIndex; + } +} + +} // anonymous namespace + +namespace chart +{ + +RangeHighlighter::RangeHighlighter( + const Reference< view::XSelectionSupplier > & xSelectionSupplier ) : + impl::RangeHighlighter_Base( m_aMutex ), + m_xSelectionSupplier( xSelectionSupplier ), + m_nAddedListenerCount( 0 ), + m_bIncludeHiddenCells(true) +{ +} + +RangeHighlighter::~RangeHighlighter() +{} + +// ____ XRangeHighlighter ____ +Sequence< chart2::data::HighlightedRange > SAL_CALL RangeHighlighter::getSelectedRanges() + throw (uno::RuntimeException) +{ + return m_aSelectedRanges; +} + +void RangeHighlighter::determineRanges() +{ + m_aSelectedRanges.realloc( 0 ); + if( m_xSelectionSupplier.is()) + { + try + { + Reference< frame::XController > xController( m_xSelectionSupplier, uno::UNO_QUERY ); + Reference< frame::XModel > xChartModel; + if( xController.is()) + xChartModel.set( xController->getModel()); + + m_bIncludeHiddenCells = ChartModelHelper::isIncludeHiddenCells( xChartModel ); + + uno::Any aSelection( m_xSelectionSupplier->getSelection()); + const uno::Type& rType = aSelection.getValueType(); + + if ( rType == ::getCppuType( static_cast< const OUString* >( 0 ) ) ) + { + // @todo??: maybe getSelection() should return a model object rather than a CID + + OUString aCID; + aSelection >>= aCID; + if ( aCID.getLength() > 0 ) + { + ObjectType eObjectType = ObjectIdentifier::getObjectType( aCID ); + sal_Int32 nIndex = ObjectIdentifier::getIndexFromParticleOrCID( aCID ); + Reference< chart2::XDataSeries > xDataSeries( ObjectIdentifier::getDataSeriesForCID( aCID, xChartModel ) ); + if( OBJECTTYPE_LEGEND_ENTRY == eObjectType ) + { + OUString aParentParticel( ObjectIdentifier::getFullParentParticle( aCID ) ); + ObjectType eParentObjectType = ObjectIdentifier::getObjectType( aParentParticel ); + eObjectType = eParentObjectType; + if( OBJECTTYPE_DATA_POINT == eObjectType ) + nIndex = ObjectIdentifier::getIndexFromParticleOrCID( aParentParticel ); + } + + if( OBJECTTYPE_DATA_POINT == eObjectType || OBJECTTYPE_DATA_LABEL == eObjectType ) + { + // Data Point + fillRangesForDataPoint( xDataSeries, nIndex ); + return; + } + else if( OBJECTTYPE_DATA_ERRORS == eObjectType ) + { + // select error bar ranges, or data series, if the style is + // not set to FROM_DATA + fillRangesForErrorBars( ObjectIdentifier::getObjectPropertySet( aCID, xChartModel ), xDataSeries ); + return; + } + else if( xDataSeries.is() ) + { + // Data Series + fillRangesForDataSeries( xDataSeries ); + return; + } + else if( OBJECTTYPE_AXIS == eObjectType ) + { + // Axis (Categories) + Reference< chart2::XAxis > xAxis( ObjectIdentifier::getObjectPropertySet( aCID, xChartModel ), uno::UNO_QUERY ); + if( xAxis.is()) + { + fillRangesForCategories( xAxis ); + return; + } + } + else if( OBJECTTYPE_PAGE == eObjectType + || OBJECTTYPE_DIAGRAM == eObjectType + || OBJECTTYPE_DIAGRAM_WALL == eObjectType + || OBJECTTYPE_DIAGRAM_FLOOR == eObjectType + ) + { + // Diagram + Reference< chart2::XDiagram > xDia( ObjectIdentifier::getDiagramForCID( aCID, xChartModel ) ); + if( xDia.is()) + { + fillRangesForDiagram( xDia ); + return; + } + } + } + } + else if ( rType == ::getCppuType( static_cast< const Reference< drawing::XShape >* >( 0 ) ) ) + { + // #i12587# support for shapes in chart + Reference< drawing::XShape > xShape; + aSelection >>= xShape; + if ( xShape.is() ) + { + return; + } + } + else + { + //if nothing is selected select all ranges + Reference< chart2::XChartDocument > xChartDoc( xChartModel, uno::UNO_QUERY_THROW ); + fillRangesForDiagram( xChartDoc->getFirstDiagram() ); + return; + } + } + catch( const uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + } +} + +void RangeHighlighter::fillRangesForDiagram( const Reference< chart2::XDiagram > & xDiagram ) +{ + Sequence< OUString > aSelectedRanges( DataSourceHelper::getUsedDataRanges( xDiagram )); + m_aSelectedRanges.realloc( aSelectedRanges.getLength()); + // @todo: merge ranges + for( sal_Int32 i=0; i<aSelectedRanges.getLength(); ++i ) + { + m_aSelectedRanges[i].RangeRepresentation = aSelectedRanges[i]; + m_aSelectedRanges[i].Index = -1; + m_aSelectedRanges[i].PreferredColor = PREFERED_DEFAULT_COLOR; + m_aSelectedRanges[i].AllowMerginigWithOtherRanges = sal_True; + } +} + +void RangeHighlighter::fillRangesForDataSeries( const uno::Reference< chart2::XDataSeries > & xSeries ) +{ + sal_Int32 nPreferredColor = PREFERED_DEFAULT_COLOR; + Reference< chart2::data::XDataSource > xSource( xSeries, uno::UNO_QUERY ); + if( xSource.is()) + lcl_fillRanges( m_aSelectedRanges, + ::chart::DataSourceHelper::getRangesFromDataSource( xSource ), + nPreferredColor ); +} + +void RangeHighlighter::fillRangesForErrorBars( + const uno::Reference< beans::XPropertySet > & xErrorBar, + const uno::Reference< chart2::XDataSeries > & xSeries ) +{ + // only show error bar ranges, if the style is set to FROM_DATA + bool bUsesRangesAsErrorBars = false; + try + { + sal_Int32 nStyle = ::com::sun::star::chart::ErrorBarStyle::NONE; + bUsesRangesAsErrorBars = + ( xErrorBar.is() && + (xErrorBar->getPropertyValue( C2U("ErrorBarStyle")) >>= nStyle) && + nStyle == ::com::sun::star::chart::ErrorBarStyle::FROM_DATA ); + } + catch( const uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + + if( bUsesRangesAsErrorBars ) + { + sal_Int32 nPreferredColor = PREFERED_DEFAULT_COLOR; + Reference< chart2::data::XDataSource > xSource( xErrorBar, uno::UNO_QUERY ); + if( xSource.is()) + lcl_fillRanges( m_aSelectedRanges, + ::chart::DataSourceHelper::getRangesFromDataSource( xSource ), + nPreferredColor ); + } + else + { + fillRangesForDataSeries( xSeries ); + } +} + +void RangeHighlighter::fillRangesForCategories( const Reference< chart2::XAxis > & xAxis ) +{ + if( ! xAxis.is()) + return; + chart2::ScaleData aData( xAxis->getScaleData()); + lcl_fillRanges( m_aSelectedRanges, + DataSourceHelper::getRangesFromLabeledDataSequence( aData.Categories )); +} + +void RangeHighlighter::fillRangesForDataPoint( const Reference< uno::XInterface > & xDataSeries, sal_Int32 nIndex ) +{ + sal_Int32 nPreferredColor = PREFERED_DEFAULT_COLOR; + if( xDataSeries.is()) + { + Reference< chart2::data::XDataSource > xSource( xDataSeries, uno::UNO_QUERY ); + if( xSource.is() ) + { + ::std::vector< chart2::data::HighlightedRange > aHilightedRanges; + Sequence< Reference< chart2::data::XLabeledDataSequence > > aLSeqSeq( xSource->getDataSequences()); + for( sal_Int32 i=0; i<aLSeqSeq.getLength(); ++i ) + { + Reference< chart2::data::XDataSequence > xLabel( aLSeqSeq[i]->getLabel()); + Reference< chart2::data::XDataSequence > xValues( aLSeqSeq[i]->getValues()); + + if( xLabel.is()) + aHilightedRanges.push_back( + chart2::data::HighlightedRange( + xLabel->getSourceRangeRepresentation(), + -1, + nPreferredColor, + sal_False )); + + sal_Int32 nUnhiddenIndex = DataSeriesHelper::translateIndexFromHiddenToFullSequence( nIndex, xValues, !m_bIncludeHiddenCells ); + if( xValues.is()) + aHilightedRanges.push_back( + chart2::data::HighlightedRange( + xValues->getSourceRangeRepresentation(), + nUnhiddenIndex, + nPreferredColor, + sal_False )); + } + m_aSelectedRanges = ContainerHelper::ContainerToSequence( aHilightedRanges ); + } + } +} + +void SAL_CALL RangeHighlighter::addSelectionChangeListener( const Reference< view::XSelectionChangeListener >& xListener ) + throw (uno::RuntimeException) +{ + if(!xListener.is()) + return; + + if( m_nAddedListenerCount == 0 ) + startListening(); + rBHelper.addListener( ::getCppuType( & xListener ), xListener); + ++m_nAddedListenerCount; + + //bring the new listener up to the current state + lang::EventObject aEvent( static_cast< lang::XComponent* >( this ) ); + xListener->selectionChanged( aEvent ); +} + +void SAL_CALL RangeHighlighter::removeSelectionChangeListener( const Reference< view::XSelectionChangeListener >& xListener ) + throw (uno::RuntimeException) +{ + rBHelper.removeListener( ::getCppuType( & xListener ), xListener ); + --m_nAddedListenerCount; + if( m_nAddedListenerCount == 0 ) + stopListening(); +} + +// ____ XSelectionChangeListener ____ +void SAL_CALL RangeHighlighter::selectionChanged( const lang::EventObject& /*aEvent*/ ) + throw (uno::RuntimeException) +{ + determineRanges(); + + // determine ranges of selected view objects + // if changed, fire an event + fireSelectionEvent(); +} + +void RangeHighlighter::fireSelectionEvent() +{ + ::cppu::OInterfaceContainerHelper* pIC = rBHelper.getContainer( + ::getCppuType((const uno::Reference< view::XSelectionChangeListener >*)0) ); + if( pIC ) + { + lang::EventObject aEvent( static_cast< lang::XComponent* >( this ) ); + ::cppu::OInterfaceIteratorHelper aIt( *pIC ); + while( aIt.hasMoreElements() ) + { + uno::Reference< view::XSelectionChangeListener > xListener( aIt.next(), uno::UNO_QUERY ); + if( xListener.is() ) + xListener->selectionChanged( aEvent ); + } + } +} + +void SAL_CALL RangeHighlighter::disposing( const lang::EventObject& Source ) + throw (uno::RuntimeException) +{ + if( Source.Source == m_xSelectionSupplier ) + { + m_xSelectionSupplier.clear(); + m_aSelectedRanges.realloc( 0 ); + fireSelectionEvent(); + } +} + +void RangeHighlighter::startListening() +{ + if( m_xSelectionSupplier.is()) + { + if( ! m_xListener.is()) + { + m_xListener.set( new WeakSelectionChangeListenerAdapter( this )); + determineRanges(); + } + m_xSelectionSupplier->addSelectionChangeListener( m_xListener ); + } +} + +void RangeHighlighter::stopListening() +{ + if( m_xSelectionSupplier.is() && m_xListener.is()) + { + m_xSelectionSupplier->removeSelectionChangeListener( m_xListener ); + m_xListener.clear(); + } +} + + +// ____ WeakComponentImplHelperBase ____ +// is called when dispose() is called at this component +void SAL_CALL RangeHighlighter::disposing() +{ + // @todo: remove listener. Currently the controller shows an assertion + // because it is already disposed +// stopListening(); + m_xListener.clear(); + m_xSelectionSupplier.clear(); + m_nAddedListenerCount = 0; + m_aSelectedRanges.realloc( 0 ); +} + +} // namespace chart diff --git a/chart2/source/tools/ReferenceSizeProvider.cxx b/chart2/source/tools/ReferenceSizeProvider.cxx new file mode 100644 index 000000000000..5a37f4980323 --- /dev/null +++ b/chart2/source/tools/ReferenceSizeProvider.cxx @@ -0,0 +1,378 @@ +/************************************************************************* + * + * 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 "ReferenceSizeProvider.hxx" +#include "RelativeSizeHelper.hxx" +#include "ChartModelHelper.hxx" +#include "DiagramHelper.hxx" +#include "macros.hxx" +#include "AxisHelper.hxx" +#include "DataSeriesHelper.hxx" + +#include <com/sun/star/chart2/XTitled.hpp> +#include <com/sun/star/chart2/XTitle.hpp> +#include <com/sun/star/chart2/XDataSeries.hpp> + +#include <vector> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::rtl::OUString; + +// ================================================================================ + +namespace chart +{ + +ReferenceSizeProvider::ReferenceSizeProvider( + awt::Size aPageSize, + const Reference< XChartDocument > & xChartDoc ) : + m_aPageSize( aPageSize ), + m_xChartDoc( xChartDoc ), + m_bUseAutoScale( getAutoResizeState( xChartDoc ) == AUTO_RESIZE_YES ) +{} + +awt::Size ReferenceSizeProvider::getPageSize() const +{ + return m_aPageSize; +} + +bool ReferenceSizeProvider::useAutoScale() const +{ + return m_bUseAutoScale; +} + +void ReferenceSizeProvider::impl_setValuesAtTitled( + const Reference< XTitled > & xTitled ) +{ + if( xTitled.is()) + { + Reference< XTitle > xTitle( xTitled->getTitleObject()); + if( xTitle.is()) + setValuesAtTitle( xTitle ); + } +} + +void ReferenceSizeProvider::setValuesAtTitle( + const Reference< XTitle > & xTitle ) +{ + try + { + Reference< beans::XPropertySet > xTitleProp( xTitle, uno::UNO_QUERY_THROW ); + awt::Size aOldRefSize; + bool bHasOldRefSize( + xTitleProp->getPropertyValue( C2U("ReferencePageSize")) >>= aOldRefSize ); + + // set from auto-resize on to off -> adapt font sizes at XFormattedStrings + if( bHasOldRefSize && ! useAutoScale()) + { + uno::Sequence< uno::Reference< XFormattedString > > aStrSeq( + xTitle->getText()); + for( sal_Int32 i=0; i<aStrSeq.getLength(); ++i ) + { + RelativeSizeHelper::adaptFontSizes( + Reference< beans::XPropertySet >( aStrSeq[i], uno::UNO_QUERY ), + aOldRefSize, getPageSize()); + } + } + + setValuesAtPropertySet( xTitleProp, /* bAdaptFontSizes = */ false ); + } + catch( const uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } +} + +void ReferenceSizeProvider::setValuesAtAllDataSeries() +{ + Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( m_xChartDoc )); + + // DataSeries/Points + ::std::vector< Reference< XDataSeries > > aSeries( + DiagramHelper::getDataSeriesFromDiagram( xDiagram )); + + for( ::std::vector< Reference< XDataSeries > >::const_iterator aIt( aSeries.begin()); + aIt != aSeries.end(); ++aIt ) + { + Reference< beans::XPropertySet > xSeriesProp( *aIt, uno::UNO_QUERY ); + if( xSeriesProp.is()) + { + // data points + Sequence< sal_Int32 > aPointIndexes; + try + { + if( xSeriesProp->getPropertyValue( C2U("AttributedDataPoints")) >>= aPointIndexes ) + { + for( sal_Int32 i=0; i< aPointIndexes.getLength(); ++i ) + setValuesAtPropertySet( + (*aIt)->getDataPointByIndex( aPointIndexes[i] ) ); + } + } + catch( const uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + + //it is important to correct the datapoint properties first as they do reference the series properties + setValuesAtPropertySet( xSeriesProp ); + } + } +} + +void ReferenceSizeProvider::setValuesAtPropertySet( + const Reference< beans::XPropertySet > & xProp, + bool bAdaptFontSizes /* = true */ ) +{ + if( ! xProp.is()) + return; + + static const OUString aRefSizeName( RTL_CONSTASCII_USTRINGPARAM("ReferencePageSize")); + + try + { + awt::Size aRefSize( getPageSize() ); + awt::Size aOldRefSize; + bool bHasOldRefSize( xProp->getPropertyValue( aRefSizeName ) >>= aOldRefSize ); + + if( useAutoScale()) + { + if( ! bHasOldRefSize ) + xProp->setPropertyValue( aRefSizeName, uno::makeAny( aRefSize )); + } + else + { + if( bHasOldRefSize ) + { + xProp->setPropertyValue( aRefSizeName, uno::Any()); + + // adapt font sizes + if( bAdaptFontSizes ) + RelativeSizeHelper::adaptFontSizes( xProp, aOldRefSize, aRefSize ); + } + } + } + catch( const uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } +} + +void ReferenceSizeProvider::getAutoResizeFromPropSet( + const Reference< beans::XPropertySet > & xProp, + ReferenceSizeProvider::AutoResizeState & rInOutState ) +{ + static const OUString aRefSizeName( RTL_CONSTASCII_USTRINGPARAM("ReferencePageSize")); + AutoResizeState eSingleState = AUTO_RESIZE_UNKNOWN; + + if( xProp.is()) + { + try + { + if( xProp->getPropertyValue( aRefSizeName ).hasValue()) + eSingleState = AUTO_RESIZE_YES; + else + eSingleState = AUTO_RESIZE_NO; + } + catch( uno::Exception ) + { + // unknown property -> state stays unknown + } + } + + // curent state unknown => nothing changes. Otherwise if current state + // differs from state so far, we have an ambiguity + if( rInOutState == AUTO_RESIZE_UNKNOWN ) + { + rInOutState = eSingleState; + } + else if( eSingleState != AUTO_RESIZE_UNKNOWN && + eSingleState != rInOutState ) + { + rInOutState = AUTO_RESIZE_AMBIGUOUS; + } +} + +void ReferenceSizeProvider::impl_getAutoResizeFromTitled( + const Reference< XTitled > & xTitled, + ReferenceSizeProvider::AutoResizeState & rInOutState ) +{ + if( xTitled.is()) + { + Reference< beans::XPropertySet > xProp( xTitled->getTitleObject(), uno::UNO_QUERY ); + if( xProp.is()) + getAutoResizeFromPropSet( xProp, rInOutState ); + } +} + +/** Retrieves the state auto-resize from all objects that support this + feature. If all objects return the same state, AUTO_RESIZE_YES or + AUTO_RESIZE_NO is returned. + + If no object supporting the feature is found, AUTO_RESIZE_UNKNOWN is + returned. If there are multiple objects, some with state YES and some + with state NO, AUTO_RESIZE_AMBIGUOUS is returned. +*/ +ReferenceSizeProvider::AutoResizeState ReferenceSizeProvider::getAutoResizeState( + const Reference< XChartDocument > & xChartDoc ) +{ + AutoResizeState eResult = AUTO_RESIZE_UNKNOWN; + + // Main Title + Reference< XTitled > xDocTitled( xChartDoc, uno::UNO_QUERY ); + if( xDocTitled.is()) + impl_getAutoResizeFromTitled( xDocTitled, eResult ); + if( eResult == AUTO_RESIZE_AMBIGUOUS ) + return eResult; + + // diagram is needed by the rest of the objects + Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartDoc ), uno::UNO_QUERY ); + if( ! xDiagram.is()) + return eResult; + + // Sub Title + Reference< XTitled > xDiaTitled( xDiagram, uno::UNO_QUERY ); + if( xDiaTitled.is()) + impl_getAutoResizeFromTitled( xDiaTitled, eResult ); + if( eResult == AUTO_RESIZE_AMBIGUOUS ) + return eResult; + + // Legend + Reference< beans::XPropertySet > xLegendProp( xDiagram->getLegend(), uno::UNO_QUERY ); + if( xLegendProp.is()) + getAutoResizeFromPropSet( xLegendProp, eResult ); + if( eResult == AUTO_RESIZE_AMBIGUOUS ) + return eResult; + + // Axes (incl. Axis Titles) + Sequence< Reference< XAxis > > aAxes( AxisHelper::getAllAxesOfDiagram( xDiagram ) ); + for( sal_Int32 i=0; i<aAxes.getLength(); ++i ) + { + Reference< beans::XPropertySet > xProp( aAxes[i], uno::UNO_QUERY ); + if( xProp.is()) + getAutoResizeFromPropSet( xProp, eResult ); + Reference< XTitled > xTitled( aAxes[i], uno::UNO_QUERY ); + if( xTitled.is()) + { + impl_getAutoResizeFromTitled( xTitled, eResult ); + if( eResult == AUTO_RESIZE_AMBIGUOUS ) + return eResult; + } + } + + // DataSeries/Points + ::std::vector< Reference< XDataSeries > > aSeries( + DiagramHelper::getDataSeriesFromDiagram( xDiagram )); + + for( ::std::vector< Reference< XDataSeries > >::const_iterator aIt( aSeries.begin()); + aIt != aSeries.end(); ++aIt ) + { + Reference< beans::XPropertySet > xSeriesProp( *aIt, uno::UNO_QUERY ); + if( xSeriesProp.is()) + { + getAutoResizeFromPropSet( xSeriesProp, eResult ); + if( eResult == AUTO_RESIZE_AMBIGUOUS ) + return eResult; + + // data points + Sequence< sal_Int32 > aPointIndexes; + try + { + if( xSeriesProp->getPropertyValue( C2U("AttributedDataPoints")) >>= aPointIndexes ) + { + for( sal_Int32 i=0; i< aPointIndexes.getLength(); ++i ) + { + getAutoResizeFromPropSet( + (*aIt)->getDataPointByIndex( aPointIndexes[i] ), eResult ); + if( eResult == AUTO_RESIZE_AMBIGUOUS ) + return eResult; + } + } + } + catch( const uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + } + } + + return eResult; +} + +void ReferenceSizeProvider::toggleAutoResizeState() +{ + setAutoResizeState( m_bUseAutoScale ? AUTO_RESIZE_NO : AUTO_RESIZE_YES ); +} + + +/** sets the auto-resize at all objects that support this feature for text. + eNewState must be either AUTO_RESIZE_YES or AUTO_RESIZE_NO +*/ +void ReferenceSizeProvider::setAutoResizeState( ReferenceSizeProvider::AutoResizeState eNewState ) +{ + m_bUseAutoScale = (eNewState == AUTO_RESIZE_YES); + + // Main Title + impl_setValuesAtTitled( Reference< XTitled >( m_xChartDoc, uno::UNO_QUERY )); + + // diagram is needed by the rest of the objects + Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( m_xChartDoc ), uno::UNO_QUERY ); + if( ! xDiagram.is()) + return; + + // Sub Title + impl_setValuesAtTitled( Reference< XTitled >( xDiagram, uno::UNO_QUERY )); + + // Legend + Reference< beans::XPropertySet > xLegendProp( xDiagram->getLegend(), uno::UNO_QUERY ); + if( xLegendProp.is()) + setValuesAtPropertySet( xLegendProp ); + + // Axes (incl. Axis Titles) + Sequence< Reference< XAxis > > aAxes( AxisHelper::getAllAxesOfDiagram( xDiagram ) ); + for( sal_Int32 i=0; i<aAxes.getLength(); ++i ) + { + Reference< beans::XPropertySet > xProp( aAxes[i], uno::UNO_QUERY ); + if( xProp.is()) + setValuesAtPropertySet( xProp ); + impl_setValuesAtTitled( Reference< XTitled >( aAxes[i], uno::UNO_QUERY )); + } + + // DataSeries/Points + setValuesAtAllDataSeries(); + + // recalculate new state (in case it stays unknown or is ambiguous + m_bUseAutoScale = (getAutoResizeState( m_xChartDoc ) == AUTO_RESIZE_YES); +} + +} // namespace chart diff --git a/chart2/source/tools/RegressionCalculationHelper.hxx b/chart2/source/tools/RegressionCalculationHelper.hxx new file mode 100644 index 000000000000..df407482b34d --- /dev/null +++ b/chart2/source/tools/RegressionCalculationHelper.hxx @@ -0,0 +1,131 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ +#ifndef CHART2_REGRESSIONCALCULATIONHELPER_HXX +#define CHART2_REGRESSIONCALCULATIONHELPER_HXX + +#include <rtl/math.hxx> + +#include <utility> +#include <functional> +#include <vector> +#include <rtl/math.hxx> + +#define NUMBER_TO_STR(number) (::rtl::OStringToOUString(::rtl::math::doubleToString( \ + number, rtl_math_StringFormat_G, 4, '.', true ),RTL_TEXTENCODING_ASCII_US )) + +#define UC_SPACE (sal_Unicode(' ')) +#define UC_MINUS_SIGN (sal_Unicode('-')) +// #define UC_MINUS_SIGN (sal_Unicode(0x2212)) + +namespace chart +{ +namespace RegressionCalculationHelper +{ + +typedef ::std::pair< ::std::vector< double >, ::std::vector< double > > tDoubleVectorPair; + +/** takes the given x- and y-values and copyies them into the resulting pair, + which contains x-values in the first element and the y-values in the second + one. All tuples for which aPred is false are not copied. + + <p>The functors below provide a set of useful predicates that can be + used to pass as parameter aPred.</p> + */ +template< class Pred > +tDoubleVectorPair + cleanup( const ::com::sun::star::uno::Sequence< double > & rXValues, + const ::com::sun::star::uno::Sequence< double > & rYValues, + Pred aPred ) +{ + tDoubleVectorPair aResult; + sal_Int32 nSize = ::std::min( rXValues.getLength(), rYValues.getLength()); + for( sal_Int32 i=0; i<nSize; ++i ) + { + if( aPred( rXValues[i], rYValues[i] )) + { + aResult.first.push_back( rXValues[i] ); + aResult.second.push_back( rYValues[i] ); + } + } + + return aResult; +} + + +class isValid : public ::std::binary_function< double, double, bool > +{ +public: + inline bool operator()( double x, double y ) + { return ! ( ::rtl::math::isNan( x ) || + ::rtl::math::isNan( y ) || + ::rtl::math::isInf( x ) || + ::rtl::math::isInf( y ) ); + } +}; + +class isValidAndXPositive : public ::std::binary_function< double, double, bool > +{ +public: + inline bool operator()( double x, double y ) + { return ! ( ::rtl::math::isNan( x ) || + ::rtl::math::isNan( y ) || + ::rtl::math::isInf( x ) || + ::rtl::math::isInf( y ) || + x <= 0.0 ); + } +}; + +class isValidAndYPositive : public ::std::binary_function< double, double, bool > +{ +public: + inline bool operator()( double x, double y ) + { return ! ( ::rtl::math::isNan( x ) || + ::rtl::math::isNan( y ) || + ::rtl::math::isInf( x ) || + ::rtl::math::isInf( y ) || + y <= 0.0 ); + } +}; + +class isValidAndBothPositive : public ::std::binary_function< double, double, bool > +{ +public: + inline bool operator()( double x, double y ) + { return ! ( ::rtl::math::isNan( x ) || + ::rtl::math::isNan( y ) || + ::rtl::math::isInf( x ) || + ::rtl::math::isInf( y ) || + x <= 0.0 || + y <= 0.0 ); + } +}; + +} // namespace RegressionCalculationHelper +} // namespace chart + +// CHART2_REGRESSIONCALCULATIONHELPER_HXX +#endif diff --git a/chart2/source/tools/RegressionCurveCalculator.cxx b/chart2/source/tools/RegressionCurveCalculator.cxx new file mode 100644 index 000000000000..68e041e668ca --- /dev/null +++ b/chart2/source/tools/RegressionCurveCalculator.cxx @@ -0,0 +1,168 @@ +/************************************************************************* + * + * 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 "RegressionCurveCalculator.hxx" +#include "RegressionCalculationHelper.hxx" +#include "servicenames_coosystems.hxx" + +#include <comphelper/processfactory.hxx> +#include <rtl/math.hxx> + +#include <com/sun/star/lang/XServiceName.hpp> + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::rtl::OUString; + +namespace chart +{ + +RegressionCurveCalculator::RegressionCurveCalculator() : + m_fCorrelationCoeffitient( 0.0 ) +{ + ::rtl::math::setNan( & m_fCorrelationCoeffitient ); +} + +RegressionCurveCalculator::~RegressionCurveCalculator() +{} + +// static +bool RegressionCurveCalculator::isLinearScaling( + const Reference< chart2::XScaling > & xScaling ) +{ + // no scaling means linear + if( !xScaling.is()) + return true; + static OUString aLinScalingServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.chart2.LinearScaling" )); + uno::Reference< lang::XServiceName > xServiceName( xScaling, uno::UNO_QUERY ); + return (xServiceName.is() && xServiceName->getServiceName().equals( aLinScalingServiceName )); +} + +// static +bool RegressionCurveCalculator::isLogarithmicScaling( + const Reference< chart2::XScaling > & xScaling ) +{ + static OUString aLogScalingServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.chart2.LogarithmicScaling" )); + uno::Reference< lang::XServiceName > xServiceName( xScaling, uno::UNO_QUERY ); + return (xServiceName.is() && xServiceName->getServiceName().equals( aLogScalingServiceName )); +} + + +OUString RegressionCurveCalculator::getFormattedString( + const Reference< util::XNumberFormatter >& xNumFormatter, + ::sal_Int32 nNumberFormatKey, + double fNumber ) const +{ + OUString aResult; + + if( xNumFormatter.is()) + aResult = xNumFormatter->convertNumberToString( nNumberFormatKey, fNumber ); + else + aResult = NUMBER_TO_STR( fNumber ); + + return aResult; +} + +Sequence< geometry::RealPoint2D > SAL_CALL RegressionCurveCalculator::getCurveValues( + double min, double max, ::sal_Int32 nPointCount, + const Reference< chart2::XScaling >& xScalingX, + const Reference< chart2::XScaling >& /* xScalingY */, + ::sal_Bool /* bMaySkipPointsInCalculation */ ) + throw (lang::IllegalArgumentException, + uno::RuntimeException) +{ + if( nPointCount < 2 ) + throw lang::IllegalArgumentException(); + + // determine if scaling and inverse scaling for x-values work + bool bDoXScaling( xScalingX.is()); + uno::Reference< chart2::XScaling > xInverseScaling; + if( bDoXScaling ) + xInverseScaling.set( xScalingX->getInverseScaling()); + bDoXScaling = bDoXScaling && xInverseScaling.is(); + + Sequence< geometry::RealPoint2D > aResult( nPointCount ); + + double fMin( min ); + double fFact = (max - min) / double(nPointCount-1); + if( bDoXScaling ) + { + fMin = xScalingX->doScaling( min ); + fFact = (xScalingX->doScaling( max ) - fMin) / double(nPointCount-1); + } + + for(sal_Int32 nP=0; nP<nPointCount; nP++) + { + double x = fMin + nP * fFact; + if( bDoXScaling ) + x = xInverseScaling->doScaling( x ); + aResult[nP].X = x; + aResult[nP].Y = this->getCurveValue( x ); + } + + return aResult; +} + +double SAL_CALL RegressionCurveCalculator::getCorrelationCoefficient() + throw (uno::RuntimeException) +{ + return m_fCorrelationCoeffitient; +} + +OUString SAL_CALL RegressionCurveCalculator::getRepresentation() + throw (uno::RuntimeException) +{ + return ImplGetRepresentation( Reference< util::XNumberFormatter >(), 0 ); +} + +OUString SAL_CALL RegressionCurveCalculator::getFormattedRepresentation( + const Reference< util::XNumberFormatsSupplier > & xNumFmtSupplier, + ::sal_Int32 nNumberFormatKey ) + throw (uno::RuntimeException) +{ + // create and prepare a number formatter + if( !xNumFmtSupplier.is()) + return getRepresentation(); + Reference< util::XNumberFormatter > xNumFormatter; + Reference< lang::XMultiServiceFactory > xFact( comphelper::getProcessServiceFactory(), uno::UNO_QUERY ); + if( xFact.is()) + xNumFormatter.set( xFact->createInstance( + OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.util.NumberFormatter"))), uno::UNO_QUERY ); + if( !xNumFormatter.is()) + return getRepresentation(); + xNumFormatter->attachNumberFormatsSupplier( xNumFmtSupplier ); + + return ImplGetRepresentation( xNumFormatter, nNumberFormatKey ); +} + + +} // namespace chart diff --git a/chart2/source/tools/RegressionCurveHelper.cxx b/chart2/source/tools/RegressionCurveHelper.cxx new file mode 100644 index 000000000000..b553dbc2d217 --- /dev/null +++ b/chart2/source/tools/RegressionCurveHelper.cxx @@ -0,0 +1,736 @@ +/************************************************************************* + * + * 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 "RegressionCurveHelper.hxx" +#include "MeanValueRegressionCurveCalculator.hxx" +#include "LinearRegressionCurveCalculator.hxx" +#include "LogarithmicRegressionCurveCalculator.hxx" +#include "ExponentialRegressionCurveCalculator.hxx" +#include "PotentialRegressionCurveCalculator.hxx" +#include "CommonConverters.hxx" +#include "RegressionCurveModel.hxx" +#include "ChartTypeHelper.hxx" +#include "ChartModelHelper.hxx" +#include "macros.hxx" +#include "PropertyHelper.hxx" +#include "ResId.hxx" +#include "Strings.hrc" +#include "DiagramHelper.hxx" +#include <com/sun/star/chart2/XChartDocument.hpp> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::XComponentContext; +using ::com::sun::star::lang::XServiceName; +using ::com::sun::star::beans::XPropertySet; +using ::com::sun::star::uno::Exception; +using ::rtl::OUString; + +namespace +{ +OUString lcl_getServiceNameForType( ::chart::RegressionCurveHelper::tRegressionType eType ) +{ + OUString aServiceName; + switch( eType ) + { + case ::chart::RegressionCurveHelper::REGRESSION_TYPE_LINEAR: + aServiceName = C2U( "com.sun.star.chart2.LinearRegressionCurve" ); + break; + case ::chart::RegressionCurveHelper::REGRESSION_TYPE_LOG: + aServiceName = C2U( "com.sun.star.chart2.LogarithmicRegressionCurve" ); + break; + case ::chart::RegressionCurveHelper::REGRESSION_TYPE_EXP: + aServiceName = C2U( "com.sun.star.chart2.ExponentialRegressionCurve" ); + break; + case ::chart::RegressionCurveHelper::REGRESSION_TYPE_POWER: + aServiceName = C2U( "com.sun.star.chart2.PotentialRegressionCurve" ); + break; + default: + OSL_ENSURE(false,"unknown regression curve type - use linear instead"); + aServiceName = C2U( "com.sun.star.chart2.LinearRegressionCurve" ); + break; + } + return aServiceName; +} +} // anonymous namespace + +//............................................................................. +namespace chart +{ +//............................................................................. + +// static +Reference< XRegressionCurve > RegressionCurveHelper::createMeanValueLine( + const Reference< XComponentContext > & xContext ) +{ + return Reference< XRegressionCurve >( + new MeanValueRegressionCurve( xContext )); +} + +// static +Reference< XRegressionCurve > RegressionCurveHelper::createRegressionCurveByServiceName( + const Reference< XComponentContext > & xContext, + ::rtl::OUString aServiceName ) +{ + Reference< XRegressionCurve > xResult; + + // todo: use factory methods with service name + if( aServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( + "com.sun.star.chart2.LinearRegressionCurve" ))) + { + xResult.set( + new LinearRegressionCurve( xContext )); + } + else if( aServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( + "com.sun.star.chart2.LogarithmicRegressionCurve" ))) + { + xResult.set( + new LogarithmicRegressionCurve( xContext )); + } + else if( aServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( + "com.sun.star.chart2.ExponentialRegressionCurve" ))) + { + xResult.set( + new ExponentialRegressionCurve( xContext )); + } + else if( aServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( + "com.sun.star.chart2.PotentialRegressionCurve" ))) + { + xResult.set( + new PotentialRegressionCurve( xContext )); + } + + return xResult; +} + +// ------------------------------------------------------------ + +// static +Reference< XRegressionCurveCalculator > RegressionCurveHelper::createRegressionCurveCalculatorByServiceName( + ::rtl::OUString aServiceName ) +{ + Reference< XRegressionCurveCalculator > xResult; + + // todo: use factory methods with service name + if( aServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( + "com.sun.star.chart2.MeanValueRegressionCurve" ))) + { + xResult.set( new MeanValueRegressionCurveCalculator()); + } + if( aServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( + "com.sun.star.chart2.LinearRegressionCurve" ))) + { + xResult.set( new LinearRegressionCurveCalculator()); + } + else if( aServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( + "com.sun.star.chart2.LogarithmicRegressionCurve" ))) + { + xResult.set( new LogarithmicRegressionCurveCalculator()); + } + else if( aServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( + "com.sun.star.chart2.ExponentialRegressionCurve" ))) + { + xResult.set( new ExponentialRegressionCurveCalculator()); + } + else if( aServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( + "com.sun.star.chart2.PotentialRegressionCurve" ))) + { + xResult.set( new PotentialRegressionCurveCalculator()); + } + + return xResult; +} + +// static +void RegressionCurveHelper::initializeCurveCalculator( + const Reference< XRegressionCurveCalculator > & xOutCurveCalculator, + const Reference< data::XDataSource > & xSource, + bool bUseXValuesIfAvailable /* = true */ ) +{ + if( ! (xOutCurveCalculator.is() && + xSource.is() )) + return; + + Sequence< double > aXValues, aYValues; + bool bXValuesFound = false, bYValuesFound = false; + + Sequence< Reference< data::XLabeledDataSequence > > aDataSeqs( xSource->getDataSequences()); + sal_Int32 i = 0; + for( i=0; + ! (bXValuesFound && bYValuesFound) && i<aDataSeqs.getLength(); + ++i ) + { + try + { + Reference< data::XDataSequence > xSeq( aDataSeqs[i]->getValues()); + Reference< XPropertySet > xProp( xSeq, uno::UNO_QUERY_THROW ); + ::rtl::OUString aRole; + if( xProp->getPropertyValue( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Role" ))) >>= aRole ) + { + if( bUseXValuesIfAvailable && + ! bXValuesFound && + aRole.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "values-x" ))) + { + aXValues = DataSequenceToDoubleSequence( xSeq ); + bXValuesFound = true; + } + else if( ! bYValuesFound && + aRole.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "values-y" ))) + { + aYValues = DataSequenceToDoubleSequence( xSeq ); + bYValuesFound = true; + } + } + } + catch( Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + } + + if( ! bXValuesFound && + bYValuesFound ) + { + // initialize with 1, 2, ... + //first category (index 0) matches with real number 1.0 + aXValues.realloc( aYValues.getLength()); + for( i=0; i<aXValues.getLength(); ++i ) + aXValues[i] = i+1; + bXValuesFound = true; + } + + if( bXValuesFound && bYValuesFound && + aXValues.getLength() > 0 && + aYValues.getLength() > 0 ) + xOutCurveCalculator->recalculateRegression( aXValues, aYValues ); +} + +// static +void RegressionCurveHelper::initializeCurveCalculator( + const Reference< XRegressionCurveCalculator > & xOutCurveCalculator, + const Reference< XDataSeries > & xSeries, + const Reference< frame::XModel > & xModel ) +{ + sal_Int32 nAxisType = ChartTypeHelper::getAxisType( + ChartModelHelper::getChartTypeOfSeries( xModel, xSeries ), 0 ); // x-axis + + initializeCurveCalculator( xOutCurveCalculator, + uno::Reference< data::XDataSource >( xSeries, uno::UNO_QUERY ), + (nAxisType == AxisType::REALNUMBER) ); +} + +// ---------------------------------------- + +// static +bool RegressionCurveHelper::hasMeanValueLine( + const uno::Reference< XRegressionCurveContainer > & xRegCnt ) +{ + if( !xRegCnt.is()) + return false; + + try + { + uno::Sequence< uno::Reference< XRegressionCurve > > aCurves( + xRegCnt->getRegressionCurves()); + for( sal_Int32 i = 0; i < aCurves.getLength(); ++i ) + { + if( isMeanValueLine( aCurves[i] )) + return true; + } + } + catch( Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + + return false; +} + +// static +bool RegressionCurveHelper::isMeanValueLine( + const uno::Reference< chart2::XRegressionCurve > & xRegCurve ) +{ + uno::Reference< XServiceName > xServName( xRegCurve, uno::UNO_QUERY ); + if( xServName.is() && + xServName->getServiceName().equals( + C2U( "com.sun.star.chart2.MeanValueRegressionCurve" ))) + return true; + return false; +} + +// static +uno::Reference< chart2::XRegressionCurve > + RegressionCurveHelper::getMeanValueLine( + const uno::Reference< chart2::XRegressionCurveContainer > & xRegCnt ) +{ + if( xRegCnt.is()) + { + try + { + uno::Sequence< uno::Reference< XRegressionCurve > > aCurves( + xRegCnt->getRegressionCurves()); + for( sal_Int32 i = 0; i < aCurves.getLength(); ++i ) + { + if( isMeanValueLine( aCurves[i] )) + return aCurves[i]; + } + } + catch( Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + } + + return uno::Reference< chart2::XRegressionCurve >(); +} + +// static +void RegressionCurveHelper::addMeanValueLine( + uno::Reference< XRegressionCurveContainer > & xRegCnt, + const uno::Reference< XComponentContext > & xContext, + const uno::Reference< XPropertySet > & xSeriesProp ) +{ + if( !xRegCnt.is() || + ::chart::RegressionCurveHelper::hasMeanValueLine( xRegCnt ) ) + return; + + // todo: use a valid context + uno::Reference< XRegressionCurve > xCurve( createMeanValueLine( xContext )); + xRegCnt->addRegressionCurve( xCurve ); + + if( xSeriesProp.is()) + { + uno::Reference< XPropertySet > xProp( xCurve, uno::UNO_QUERY ); + if( xProp.is()) + { + xProp->setPropertyValue( C2U( "LineColor" ), + xSeriesProp->getPropertyValue( C2U( "Color" ))); + } + } +} + +// static +void RegressionCurveHelper::removeMeanValueLine( + Reference< XRegressionCurveContainer > & xRegCnt ) +{ + if( !xRegCnt.is()) + return; + + try + { + Sequence< Reference< XRegressionCurve > > aCurves( + xRegCnt->getRegressionCurves()); + for( sal_Int32 i = 0; i < aCurves.getLength(); ++i ) + { + if( isMeanValueLine( aCurves[i] )) + { + xRegCnt->removeRegressionCurve( aCurves[i] ); + // attention: the iterator i has become invalid now + + // note: assume that there is only one mean-value curve + // to remove multiple mean-value curves remove the break + break; + } + } + } + catch( Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } +} + +void RegressionCurveHelper::addRegressionCurve( + tRegressionType eType, + uno::Reference< XRegressionCurveContainer > & xRegCnt, + const uno::Reference< XComponentContext > & /* xContext */, + const uno::Reference< beans::XPropertySet >& xPropertySource, + const uno::Reference< beans::XPropertySet >& xEquationProperties ) +{ + if( !xRegCnt.is() ) + return; + + if( eType == REGRESSION_TYPE_NONE ) + { + OSL_ENSURE(false,"don't create a regression curve of type none"); + return; + } + + uno::Reference< chart2::XRegressionCurve > xCurve; + ::rtl::OUString aServiceName( lcl_getServiceNameForType( eType )); + + if( aServiceName.getLength()) + { + // todo: use a valid context + xCurve.set( createRegressionCurveByServiceName( + uno::Reference< uno::XComponentContext >(), aServiceName )); + + if( xEquationProperties.is()) + xCurve->setEquationProperties( xEquationProperties ); + + uno::Reference< beans::XPropertySet > xProp( xCurve, uno::UNO_QUERY ); + if( xProp.is()) + { + if( xPropertySource.is()) + comphelper::copyProperties( xPropertySource, xProp ); + else + { + uno::Reference< XPropertySet > xSeriesProp( xRegCnt, uno::UNO_QUERY ); + if( xSeriesProp.is()) + { + xProp->setPropertyValue( C2U( "LineColor" ), + xSeriesProp->getPropertyValue( C2U( "Color" ))); + } +// xProp->setPropertyValue( C2U( "LineWidth" ), uno::makeAny( sal_Int32( 100 ))); + } + } + } + xRegCnt->addRegressionCurve( xCurve ); +} + +/** removes all regression curves that are not of type mean value + and returns true, if anything was removed + */ +bool RegressionCurveHelper::removeAllExceptMeanValueLine( + uno::Reference< chart2::XRegressionCurveContainer > & xRegCnt ) +{ + bool bRemovedSomething = false; + if( xRegCnt.is()) + { + try + { + uno::Sequence< uno::Reference< chart2::XRegressionCurve > > aCurves( + xRegCnt->getRegressionCurves()); + ::std::vector< uno::Reference< chart2::XRegressionCurve > > aCurvesToDelete; + for( sal_Int32 i = 0; i < aCurves.getLength(); ++i ) + { + if( ! isMeanValueLine( aCurves[i] )) + { + aCurvesToDelete.push_back( aCurves[ i ] ); + } + } + + for( ::std::vector< uno::Reference< chart2::XRegressionCurve > >::const_iterator aIt = aCurvesToDelete.begin(); + aIt != aCurvesToDelete.end(); ++aIt ) + { + xRegCnt->removeRegressionCurve( *aIt ); + bRemovedSomething = true; + } + } + catch( uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + } + return bRemovedSomething; +} + +void RegressionCurveHelper::removeEquations( + uno::Reference< chart2::XRegressionCurveContainer > & xRegCnt ) +{ + if( xRegCnt.is()) + { + try + { + uno::Sequence< uno::Reference< chart2::XRegressionCurve > > aCurves( + xRegCnt->getRegressionCurves()); + for( sal_Int32 i = 0; i < aCurves.getLength(); ++i ) + { + if( !isMeanValueLine( aCurves[i] ) ) + { + uno::Reference< chart2::XRegressionCurve > xRegCurve( aCurves[ i ] ); + if( xRegCurve.is() ) + { + uno::Reference< beans::XPropertySet > xEqProp( xRegCurve->getEquationProperties() ) ; + if( xEqProp.is()) + { + xEqProp->setPropertyValue( C2U("ShowEquation"), uno::makeAny( false )); + xEqProp->setPropertyValue( C2U("ShowCorrelationCoefficient"), uno::makeAny( false )); + } + } + } + } + } + catch( uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + } +} + +// static +void RegressionCurveHelper::replaceOrAddCurveAndReduceToOne( + tRegressionType eType, + uno::Reference< XRegressionCurveContainer > & xRegCnt, + const uno::Reference< XComponentContext > & xContext ) +{ + uno::Reference< chart2::XRegressionCurve > xRegressionCurve( getFirstCurveNotMeanValueLine( xRegCnt )); + if( ! xRegressionCurve.is()) + RegressionCurveHelper::addRegressionCurve( eType, xRegCnt, xContext ); + else + { + OUString aServiceName( lcl_getServiceNameForType( eType )); + if( aServiceName.getLength()) + { + RegressionCurveHelper::removeAllExceptMeanValueLine( xRegCnt ); + RegressionCurveHelper::addRegressionCurve( + eType, xRegCnt, xContext, + Reference< beans::XPropertySet >( xRegressionCurve, uno::UNO_QUERY ), + xRegressionCurve->getEquationProperties()); + } + } +} + +// static +uno::Reference< chart2::XRegressionCurve > RegressionCurveHelper::getFirstCurveNotMeanValueLine( + const Reference< XRegressionCurveContainer > & xRegCnt ) +{ + if( !xRegCnt.is()) + return NULL; + + try + { + uno::Sequence< uno::Reference< chart2::XRegressionCurve > > aCurves( + xRegCnt->getRegressionCurves()); + ::std::vector< uno::Reference< chart2::XRegressionCurve > > aCurvesToDelete; + for( sal_Int32 i = 0; i < aCurves.getLength(); ++i ) + { + if( ! isMeanValueLine( aCurves[i] )) + { + return aCurves[ i ]; + } + } + } + catch( Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + + return NULL; +} + +// static +RegressionCurveHelper::tRegressionType RegressionCurveHelper::getRegressionType( + const Reference< XRegressionCurve > & xCurve ) +{ + tRegressionType eResult = REGRESSION_TYPE_UNKNOWN; + + try + { + Reference< lang::XServiceName > xServName( xCurve, uno::UNO_QUERY ); + if( xServName.is()) + { + ::rtl::OUString aServiceName( xServName->getServiceName() ); + + if( aServiceName.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "com.sun.star.chart2.LinearRegressionCurve" ))) + { + eResult = REGRESSION_TYPE_LINEAR; + } + else if( aServiceName.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "com.sun.star.chart2.LogarithmicRegressionCurve" ))) + { + eResult = REGRESSION_TYPE_LOG; + } + else if( aServiceName.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "com.sun.star.chart2.ExponentialRegressionCurve" ))) + { + eResult = REGRESSION_TYPE_EXP; + } + else if( aServiceName.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "com.sun.star.chart2.PotentialRegressionCurve" ))) + { + eResult = REGRESSION_TYPE_POWER; + } + else if( aServiceName.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "com.sun.star.chart2.MeanValueRegressionCurve" ))) + { + eResult = REGRESSION_TYPE_MEAN_VALUE; + } + } + } + catch( Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + + return eResult; +} + +// static +RegressionCurveHelper::tRegressionType RegressionCurveHelper::getFirstRegressTypeNotMeanValueLine( + const Reference< XRegressionCurveContainer > & xRegCnt ) +{ + tRegressionType eResult = REGRESSION_TYPE_NONE; + + if( xRegCnt.is()) + { + Sequence< Reference< XRegressionCurve > > aCurves( + xRegCnt->getRegressionCurves()); + for( sal_Int32 i = 0; i < aCurves.getLength(); ++i ) + { + tRegressionType eType = getRegressionType( aCurves[i] ); + if( eType != REGRESSION_TYPE_MEAN_VALUE && + eType != REGRESSION_TYPE_UNKNOWN ) + { + eResult = eType; + break; + } + } + } + + return eResult; +} + +OUString RegressionCurveHelper::getUINameForRegressionCurve( const Reference< XRegressionCurve >& xRegressionCurve ) +{ + OUString aResult; + Reference< lang::XServiceName > xServiceName( xRegressionCurve, uno::UNO_QUERY ); + if( ! xServiceName.is()) + return aResult; + + OUString aServiceName( xServiceName->getServiceName()); + if( aServiceName.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "com.sun.star.chart2.MeanValueRegressionCurve" ))) + { + OSL_ENSURE( false, "Meanvalue lines in legend not supported" ); + aResult = OUString(); + // aResult = ::chart::SchResId::getResString( STR_OBJECT_AVERAGE_LINE ); + } + else if( aServiceName.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "com.sun.star.chart2.LinearRegressionCurve" ))) + { + aResult = ::chart::SchResId::getResString( STR_REGRESSION_LINEAR ); + } + else if( aServiceName.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "com.sun.star.chart2.LogarithmicRegressionCurve" ))) + { + aResult = ::chart::SchResId::getResString( STR_REGRESSION_LOG ); + } + else if( aServiceName.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "com.sun.star.chart2.ExponentialRegressionCurve" ))) + { + aResult = ::chart::SchResId::getResString( STR_REGRESSION_EXP ); + } + else if( aServiceName.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "com.sun.star.chart2.PotentialRegressionCurve" ))) + { + aResult = ::chart::SchResId::getResString( STR_REGRESSION_POWER ); + } + + return aResult; +} + +// static +::std::vector< Reference< chart2::XRegressionCurve > > + RegressionCurveHelper::getAllRegressionCurvesNotMeanValueLine( + const Reference< chart2::XDiagram > & xDiagram ) +{ + ::std::vector< Reference< chart2::XRegressionCurve > > aResult; + ::std::vector< Reference< chart2::XDataSeries > > aSeries( DiagramHelper::getDataSeriesFromDiagram( xDiagram )); + for( ::std::vector< Reference< chart2::XDataSeries > >::iterator aIt( aSeries.begin()); + aIt != aSeries.end(); ++aIt ) + { + Reference< chart2::XRegressionCurveContainer > xCurveCnt( *aIt, uno::UNO_QUERY ); + if( xCurveCnt.is()) + { + uno::Sequence< uno::Reference< chart2::XRegressionCurve > > aCurves( + xCurveCnt->getRegressionCurves()); + for( sal_Int32 i = 0; i < aCurves.getLength(); ++i ) + { + if( ! isMeanValueLine( aCurves[i] )) + aResult.push_back( aCurves[i] ); + } + } + } + + return aResult; +} + +// static +void RegressionCurveHelper::resetEquationPosition( + const Reference< chart2::XRegressionCurve > & xCurve ) +{ + if( xCurve.is()) + { + try + { + const OUString aPosPropertyName( RTL_CONSTASCII_USTRINGPARAM( "RelativePosition" )); + Reference< beans::XPropertySet > xEqProp( xCurve->getEquationProperties()); // since m233: , uno::UNO_SET_THROW ); + if( xEqProp->getPropertyValue( aPosPropertyName ).hasValue()) + xEqProp->setPropertyValue( aPosPropertyName, uno::Any()); + } + catch( const uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + } +} + +sal_Int32 RegressionCurveHelper::getRegressionCurveIndex( + const Reference< chart2::XRegressionCurveContainer > & xContainer, + const Reference< chart2::XRegressionCurve > & xCurve ) +{ + if( xContainer.is()) + { + uno::Sequence< uno::Reference< XRegressionCurve > > aCurves( + xContainer->getRegressionCurves()); + for( sal_Int32 i = 0; i < aCurves.getLength(); ++i ) + { + if( xCurve == aCurves[i] ) + return i; + } + } + return -1; +} + +bool RegressionCurveHelper::hasEquation( const Reference< chart2::XRegressionCurve > & xCurve ) +{ + bool bHasEquation = false; + if( xCurve.is()) + { + uno::Reference< beans::XPropertySet > xEquationProp( xCurve->getEquationProperties()); + if( xEquationProp.is()) + { + bool bShowEquation = false; + bool bShowCoefficient = false; + xEquationProp->getPropertyValue( C2U("ShowEquation")) >>= bShowEquation; + xEquationProp->getPropertyValue( C2U("ShowCorrelationCoefficient")) >>= bShowCoefficient; + bHasEquation = bShowEquation || bShowCoefficient; + } + } + return bHasEquation; +} + +//............................................................................. +} //namespace chart +//............................................................................. diff --git a/chart2/source/tools/RegressionCurveModel.cxx b/chart2/source/tools/RegressionCurveModel.cxx new file mode 100644 index 000000000000..cf5be998308e --- /dev/null +++ b/chart2/source/tools/RegressionCurveModel.cxx @@ -0,0 +1,441 @@ +/************************************************************************* + * + * 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 "RegressionCurveModel.hxx" +#include "macros.hxx" +#include "LineProperties.hxx" +#include "RegressionCurveHelper.hxx" +#include "RegressionCalculationHelper.hxx" +#include "RegressionEquation.hxx" +#include "ContainerHelper.hxx" +#include "CloneHelper.hxx" +#include "PropertyHelper.hxx" +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <rtl/math.hxx> +#include <rtl/ustrbuf.hxx> + +using namespace ::com::sun::star; + +using ::rtl::OUString; +using ::rtl::OUStringBuffer; +using ::com::sun::star::beans::Property; +using ::osl::MutexGuard; + +namespace +{ +static const OUString lcl_aImplementationName_MeanValue( + RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.chart2.MeanValueRegressionCurve" )); +static const OUString lcl_aImplementationName_Linear( + RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.chart2.LinearRegressionCurve" )); +static const OUString lcl_aImplementationName_Logarithmic( + RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.chart2.LogarithmicRegressionCurve" )); +static const OUString lcl_aImplementationName_Exponential( + RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.chart2.ExponentialRegressionCurve" )); +static const OUString lcl_aImplementationName_Potential( + RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.chart2.PotentialRegressionCurve" )); + +static const OUString lcl_aServiceName( + RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.chart2.RegressionCurve" )); + +const uno::Sequence< Property > & lcl_GetPropertySequence() +{ + static uno::Sequence< Property > aPropSeq; + + // /-- + MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if( 0 == aPropSeq.getLength() ) + { + // get properties + ::std::vector< ::com::sun::star::beans::Property > aProperties; + ::chart::LineProperties::AddPropertiesToVector( aProperties ); + + // and sort them for access via bsearch + ::std::sort( aProperties.begin(), aProperties.end(), + ::chart::PropertyNameLess() ); + + // transfer result to static Sequence + aPropSeq = ::chart::ContainerHelper::ContainerToSequence( aProperties ); + } + + return aPropSeq; +} + +::cppu::IPropertyArrayHelper & lcl_getInfoHelper() +{ + static ::cppu::OPropertyArrayHelper aArrayHelper( + lcl_GetPropertySequence(), + /* bSorted = */ sal_True ); + + return aArrayHelper; +} + +} // anonymous namespace + +namespace chart +{ + +RegressionCurveModel::RegressionCurveModel( + uno::Reference< uno::XComponentContext > const & xContext, + tCurveType eCurveType ) : + ::property::OPropertySet( m_aMutex ), + m_xContext( xContext ), + m_eRegressionCurveType( eCurveType ), + m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()), + m_xEquationProperties( new RegressionEquation( xContext )) +{ + // set 0 line width (default) hard, so that it is always written to XML, + // because the old implementation uses different defaults + setFastPropertyValue_NoBroadcast( + LineProperties::PROP_LINE_WIDTH, uno::makeAny( sal_Int32( 0 ))); + ModifyListenerHelper::addListener( m_xEquationProperties, m_xModifyEventForwarder ); +} + +RegressionCurveModel::RegressionCurveModel( const RegressionCurveModel & rOther ) : + MutexContainer(), + impl::RegressionCurveModel_Base(), + ::property::OPropertySet( rOther, m_aMutex ), + m_xContext( rOther.m_xContext ), + m_eRegressionCurveType( rOther.m_eRegressionCurveType ), + m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()) +{ + m_xEquationProperties.set( CloneHelper::CreateRefClone< uno::Reference< beans::XPropertySet > >()( rOther.m_xEquationProperties )); + ModifyListenerHelper::addListener( m_xEquationProperties, m_xModifyEventForwarder ); +} + +RegressionCurveModel::~RegressionCurveModel() +{} + +// ____ XRegressionCurve ____ +uno::Reference< chart2::XRegressionCurveCalculator > SAL_CALL + RegressionCurveModel::getCalculator() + throw (uno::RuntimeException) +{ + return RegressionCurveHelper::createRegressionCurveCalculatorByServiceName( getServiceName()); +} + +uno::Reference< beans::XPropertySet > SAL_CALL RegressionCurveModel::getEquationProperties() + throw (uno::RuntimeException) +{ + return m_xEquationProperties; +} + +void SAL_CALL RegressionCurveModel::setEquationProperties( const uno::Reference< beans::XPropertySet >& xEquationProperties ) + throw (uno::RuntimeException) +{ + if( xEquationProperties.is()) + { + if( m_xEquationProperties.is()) + ModifyListenerHelper::removeListener( m_xEquationProperties, m_xModifyEventForwarder ); + + m_xEquationProperties.set( xEquationProperties ); + ModifyListenerHelper::addListener( m_xEquationProperties, m_xModifyEventForwarder ); + fireModifyEvent(); + } +} + +// ____ XServiceName ____ +::rtl::OUString SAL_CALL RegressionCurveModel::getServiceName() + throw (uno::RuntimeException) +{ + switch( m_eRegressionCurveType ) + { + case CURVE_TYPE_MEAN_VALUE: + return C2U( "com.sun.star.chart2.MeanValueRegressionCurve" ); + case CURVE_TYPE_LINEAR: + return C2U( "com.sun.star.chart2.LinearRegressionCurve" ); + case CURVE_TYPE_LOGARITHM: + return C2U( "com.sun.star.chart2.LogarithmicRegressionCurve" ); + case CURVE_TYPE_EXPONENTIAL: + return C2U( "com.sun.star.chart2.ExponentialRegressionCurve" ); + case CURVE_TYPE_POWER: + return C2U( "com.sun.star.chart2.PotentialRegressionCurve" ); + } + + return ::rtl::OUString(); +} + +// ____ XModifyBroadcaster ____ +void SAL_CALL RegressionCurveModel::addModifyListener( const uno::Reference< util::XModifyListener >& aListener ) + throw (uno::RuntimeException) +{ + try + { + uno::Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW ); + xBroadcaster->addModifyListener( aListener ); + } + catch( const uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } +} + +void SAL_CALL RegressionCurveModel::removeModifyListener( const uno::Reference< util::XModifyListener >& aListener ) + throw (uno::RuntimeException) +{ + try + { + uno::Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW ); + xBroadcaster->removeModifyListener( aListener ); + } + catch( const uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } +} + +// ____ XModifyListener ____ +void SAL_CALL RegressionCurveModel::modified( const lang::EventObject& aEvent ) + throw (uno::RuntimeException) +{ + m_xModifyEventForwarder->modified( aEvent ); +} + +// ____ XEventListener (base of XModifyListener) ____ +void SAL_CALL RegressionCurveModel::disposing( const lang::EventObject& /* Source */ ) + throw (uno::RuntimeException) +{ + // nothing +} + +// ____ OPropertySet ____ +void RegressionCurveModel::firePropertyChangeEvent() +{ + fireModifyEvent(); +} + +void RegressionCurveModel::fireModifyEvent() +{ + m_xModifyEventForwarder->modified( lang::EventObject( static_cast< uno::XWeak* >( this ))); +} + +// ================================================================================ + +// ____ OPropertySet ____ +uno::Any RegressionCurveModel::GetDefaultValue( sal_Int32 nHandle ) const + throw(beans::UnknownPropertyException) +{ + static tPropertyValueMap aStaticDefaults; + + // /-- + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if( 0 == aStaticDefaults.size() ) + { + // initialize defaults + LineProperties::AddDefaultsToMap( aStaticDefaults ); + } + + tPropertyValueMap::const_iterator aFound( + aStaticDefaults.find( nHandle )); + + if( aFound == aStaticDefaults.end()) + return uno::Any(); + + return (*aFound).second; + // \-- +} + +::cppu::IPropertyArrayHelper & SAL_CALL RegressionCurveModel::getInfoHelper() +{ + return lcl_getInfoHelper(); +} + + +// ____ XPropertySet ____ +uno::Reference< beans::XPropertySetInfo > SAL_CALL + RegressionCurveModel::getPropertySetInfo() + throw (uno::RuntimeException) +{ + static uno::Reference< beans::XPropertySetInfo > xInfo; + + // /-- + MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if( !xInfo.is()) + { + xInfo = ::cppu::OPropertySetHelper::createPropertySetInfo( + getInfoHelper()); + } + + return xInfo; + // \-- +} + +// ================================================================================ + +// needed by MSC compiler +using impl::RegressionCurveModel_Base; + +IMPLEMENT_FORWARD_XINTERFACE2( RegressionCurveModel, RegressionCurveModel_Base, OPropertySet ) +IMPLEMENT_FORWARD_XTYPEPROVIDER2( RegressionCurveModel, RegressionCurveModel_Base, OPropertySet ) + + + +// implementations + +// -------------------------------------------------------------------------------- + +MeanValueRegressionCurve::MeanValueRegressionCurve( + const uno::Reference< uno::XComponentContext > & xContext ) + : RegressionCurveModel( xContext, RegressionCurveModel::CURVE_TYPE_MEAN_VALUE ) +{} +MeanValueRegressionCurve::MeanValueRegressionCurve( + const MeanValueRegressionCurve & rOther ) : + RegressionCurveModel( rOther ) +{} +MeanValueRegressionCurve::~MeanValueRegressionCurve() +{} +uno::Sequence< ::rtl::OUString > MeanValueRegressionCurve::getSupportedServiceNames_Static() +{ + uno::Sequence< ::rtl::OUString > aServices( 2 ); + aServices[ 0 ] = lcl_aServiceName; + aServices[ 1 ] = C2U( "com.sun.star.chart2.MeanValueRegressionCurve" ); + return aServices; +} +// implement XServiceInfo methods basing upon getSupportedServiceNames_Static +APPHELPER_XSERVICEINFO_IMPL( MeanValueRegressionCurve, lcl_aImplementationName_MeanValue ); + +uno::Reference< util::XCloneable > SAL_CALL MeanValueRegressionCurve::createClone() + throw (uno::RuntimeException) +{ + return uno::Reference< util::XCloneable >( new MeanValueRegressionCurve( *this )); +} + +// -------------------------------------------------------------------------------- + +LinearRegressionCurve::LinearRegressionCurve( + const uno::Reference< uno::XComponentContext > & xContext ) + : RegressionCurveModel( xContext, RegressionCurveModel::CURVE_TYPE_LINEAR ) +{} +LinearRegressionCurve::LinearRegressionCurve( + const LinearRegressionCurve & rOther ) : + RegressionCurveModel( rOther ) +{} +LinearRegressionCurve::~LinearRegressionCurve() +{} +uno::Sequence< ::rtl::OUString > LinearRegressionCurve::getSupportedServiceNames_Static() +{ + uno::Sequence< ::rtl::OUString > aServices( 2 ); + aServices[ 0 ] = lcl_aServiceName; + aServices[ 1 ] = C2U( "com.sun.star.chart2.LinearRegressionCurve" ); + return aServices; +} +// implement XServiceInfo methods basing upon getSupportedServiceNames_Static +APPHELPER_XSERVICEINFO_IMPL( LinearRegressionCurve, lcl_aImplementationName_Linear ); + +uno::Reference< util::XCloneable > SAL_CALL LinearRegressionCurve::createClone() + throw (uno::RuntimeException) +{ + return uno::Reference< util::XCloneable >( new LinearRegressionCurve( *this )); +} + +// -------------------------------------------------------------------------------- + +LogarithmicRegressionCurve::LogarithmicRegressionCurve( + const uno::Reference< uno::XComponentContext > & xContext ) + : RegressionCurveModel( xContext, RegressionCurveModel::CURVE_TYPE_LOGARITHM ) +{} +LogarithmicRegressionCurve::LogarithmicRegressionCurve( + const LogarithmicRegressionCurve & rOther ) : + RegressionCurveModel( rOther ) +{} +LogarithmicRegressionCurve::~LogarithmicRegressionCurve() +{} +uno::Sequence< ::rtl::OUString > LogarithmicRegressionCurve::getSupportedServiceNames_Static() +{ + uno::Sequence< ::rtl::OUString > aServices( 2 ); + aServices[ 0 ] = lcl_aServiceName; + aServices[ 1 ] = C2U( "com.sun.star.chart2.LogarithmicRegressionCurve" ); + return aServices; +} +// implement XServiceInfo methods basing upon getSupportedServiceNames_Static +APPHELPER_XSERVICEINFO_IMPL( LogarithmicRegressionCurve, lcl_aImplementationName_Logarithmic ); + +uno::Reference< util::XCloneable > SAL_CALL LogarithmicRegressionCurve::createClone() + throw (uno::RuntimeException) +{ + return uno::Reference< util::XCloneable >( new LogarithmicRegressionCurve( *this )); +} + +// -------------------------------------------------------------------------------- + +ExponentialRegressionCurve::ExponentialRegressionCurve( + const uno::Reference< uno::XComponentContext > & xContext ) + : RegressionCurveModel( xContext, RegressionCurveModel::CURVE_TYPE_EXPONENTIAL ) +{} +ExponentialRegressionCurve::ExponentialRegressionCurve( + const ExponentialRegressionCurve & rOther ) : + RegressionCurveModel( rOther ) +{} +ExponentialRegressionCurve::~ExponentialRegressionCurve() +{} +uno::Sequence< ::rtl::OUString > ExponentialRegressionCurve::getSupportedServiceNames_Static() +{ + uno::Sequence< ::rtl::OUString > aServices( 2 ); + aServices[ 0 ] = lcl_aServiceName; + aServices[ 1 ] = C2U( "com.sun.star.chart2.ExponentialRegressionCurve" ); + return aServices; +} +// implement XServiceInfo methods basing upon getSupportedServiceNames_Static +APPHELPER_XSERVICEINFO_IMPL( ExponentialRegressionCurve, lcl_aImplementationName_Exponential ); + +uno::Reference< util::XCloneable > SAL_CALL ExponentialRegressionCurve::createClone() + throw (uno::RuntimeException) +{ + return uno::Reference< util::XCloneable >( new ExponentialRegressionCurve( *this )); +} + +// -------------------------------------------------------------------------------- + +PotentialRegressionCurve::PotentialRegressionCurve( + const uno::Reference< uno::XComponentContext > & xContext ) + : RegressionCurveModel( xContext, RegressionCurveModel::CURVE_TYPE_POWER ) +{} +PotentialRegressionCurve::PotentialRegressionCurve( + const PotentialRegressionCurve & rOther ) : + RegressionCurveModel( rOther ) +{} +PotentialRegressionCurve::~PotentialRegressionCurve() +{} +uno::Sequence< ::rtl::OUString > PotentialRegressionCurve::getSupportedServiceNames_Static() +{ + uno::Sequence< ::rtl::OUString > aServices( 2 ); + aServices[ 0 ] = lcl_aServiceName; + aServices[ 1 ] = C2U( "com.sun.star.chart2.PotentialRegressionCurve" ); + return aServices; +} +// implement XServiceInfo methods basing upon getSupportedServiceNames_Static +APPHELPER_XSERVICEINFO_IMPL( PotentialRegressionCurve, lcl_aImplementationName_Potential ); + +uno::Reference< util::XCloneable > SAL_CALL PotentialRegressionCurve::createClone() + throw (uno::RuntimeException) +{ + return uno::Reference< util::XCloneable >( new PotentialRegressionCurve( *this )); +} + + +} // namespace chart diff --git a/chart2/source/tools/RegressionCurveModel.hxx b/chart2/source/tools/RegressionCurveModel.hxx new file mode 100644 index 000000000000..82098a76e45a --- /dev/null +++ b/chart2/source/tools/RegressionCurveModel.hxx @@ -0,0 +1,259 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ +#ifndef CHART2_REGRESSIONCURVEMODEL_HXX +#define CHART2_REGRESSIONCURVEMODEL_HXX + +#include "MutexContainer.hxx" +#include "OPropertySet.hxx" +#include "ServiceMacros.hxx" +#include "ModifyListenerHelper.hxx" + +#include <cppuhelper/implbase6.hxx> +#include <comphelper/uno3.hxx> + +#include <com/sun/star/chart2/XRegressionCurve.hpp> + +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XServiceName.hpp> +#include <com/sun/star/util/XCloneable.hpp> + +namespace chart +{ + +namespace impl +{ +typedef ::cppu::WeakImplHelper6< + ::com::sun::star::lang::XServiceInfo, + ::com::sun::star::lang::XServiceName, + ::com::sun::star::chart2::XRegressionCurve, + ::com::sun::star::util::XCloneable, + ::com::sun::star::util::XModifyBroadcaster, + ::com::sun::star::util::XModifyListener > + RegressionCurveModel_Base; +} + +class RegressionCurveModel : + public MutexContainer, + public impl::RegressionCurveModel_Base, + public ::property::OPropertySet +{ +public: + enum tCurveType + { + CURVE_TYPE_MEAN_VALUE, + CURVE_TYPE_LINEAR, + CURVE_TYPE_LOGARITHM, + CURVE_TYPE_EXPONENTIAL, + CURVE_TYPE_POWER + }; + + RegressionCurveModel( ::com::sun::star::uno::Reference< + ::com::sun::star::uno::XComponentContext > const & xContext, + tCurveType eCurveType ); + RegressionCurveModel( const RegressionCurveModel & rOther ); + virtual ~RegressionCurveModel(); + + /// merge XInterface implementations + DECLARE_XINTERFACE() + /// merge XTypeProvider implementations + DECLARE_XTYPEPROVIDER() + +protected: + // ____ OPropertySet ____ + virtual ::com::sun::star::uno::Any GetDefaultValue( sal_Int32 nHandle ) const + throw(::com::sun::star::beans::UnknownPropertyException); + + // ____ OPropertySet ____ + virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper(); + + // ____ XPropertySet ____ + virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL + getPropertySetInfo() + throw (::com::sun::star::uno::RuntimeException); + + // ____ XRegressionCurve ____ + virtual ::com::sun::star::uno::Reference< + ::com::sun::star::chart2::XRegressionCurveCalculator > SAL_CALL getCalculator() + throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > SAL_CALL getEquationProperties() + throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setEquationProperties( + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& xEquationProperties ) + throw (::com::sun::star::uno::RuntimeException); + + // ____ XServiceName ____ + virtual ::rtl::OUString SAL_CALL getServiceName() + throw (::com::sun::star::uno::RuntimeException); + + // ____ XCloneable ____ + // not implemented here +// virtual ::com::sun::star::uno::Reference< ::com::sun::star::util::XCloneable > SAL_CALL createClone() +// throw (::com::sun::star::uno::RuntimeException); + + // ____ XModifyBroadcaster ____ + virtual void SAL_CALL addModifyListener( + const ::com::sun::star::uno::Reference< ::com::sun::star::util::XModifyListener >& aListener ) + throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeModifyListener( + const ::com::sun::star::uno::Reference< ::com::sun::star::util::XModifyListener >& aListener ) + throw (::com::sun::star::uno::RuntimeException); + + // ____ XModifyListener ____ + virtual void SAL_CALL modified( + const ::com::sun::star::lang::EventObject& aEvent ) + throw (::com::sun::star::uno::RuntimeException); + + // ____ XEventListener (base of XModifyListener) ____ + virtual void SAL_CALL disposing( + const ::com::sun::star::lang::EventObject& Source ) + throw (::com::sun::star::uno::RuntimeException); + + using ::cppu::OPropertySetHelper::disposing; + + // ____ OPropertySet ____ + virtual void firePropertyChangeEvent(); + + void fireModifyEvent(); + +private: + ::com::sun::star::uno::Reference< + ::com::sun::star::uno::XComponentContext > + m_xContext; + + const tCurveType m_eRegressionCurveType; + + ::com::sun::star::uno::Reference< ::com::sun::star::util::XModifyListener > m_xModifyEventForwarder; + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > m_xEquationProperties; +}; + +// implementations for factory instantiation + +class MeanValueRegressionCurve : public RegressionCurveModel +{ +public: + explicit MeanValueRegressionCurve( + const ::com::sun::star::uno::Reference< + ::com::sun::star::uno::XComponentContext > & xContext ); + explicit MeanValueRegressionCurve( + const MeanValueRegressionCurve & rOther ); + virtual ~MeanValueRegressionCurve(); + + // ____ XCloneable ____ + virtual ::com::sun::star::uno::Reference< ::com::sun::star::util::XCloneable > SAL_CALL createClone() + throw (::com::sun::star::uno::RuntimeException); + + /// XServiceInfo declarations + APPHELPER_XSERVICEINFO_DECL() + /// establish methods for factory instatiation + APPHELPER_SERVICE_FACTORY_HELPER( MeanValueRegressionCurve ) +}; + +class LinearRegressionCurve : public RegressionCurveModel +{ +public: + explicit LinearRegressionCurve( + const ::com::sun::star::uno::Reference< + ::com::sun::star::uno::XComponentContext > & xContext ); + explicit LinearRegressionCurve( + const LinearRegressionCurve & rOther ); + virtual ~LinearRegressionCurve(); + + // ____ XCloneable ____ + virtual ::com::sun::star::uno::Reference< ::com::sun::star::util::XCloneable > SAL_CALL createClone() + throw (::com::sun::star::uno::RuntimeException); + + /// XServiceInfo declarations + APPHELPER_XSERVICEINFO_DECL() + /// establish methods for factory instatiation + APPHELPER_SERVICE_FACTORY_HELPER( LinearRegressionCurve ) +}; + +class LogarithmicRegressionCurve : public RegressionCurveModel +{ +public: + explicit LogarithmicRegressionCurve( + const ::com::sun::star::uno::Reference< + ::com::sun::star::uno::XComponentContext > & xContext ); + explicit LogarithmicRegressionCurve( + const LogarithmicRegressionCurve & rOther ); + virtual ~LogarithmicRegressionCurve(); + + // ____ XCloneable ____ + virtual ::com::sun::star::uno::Reference< ::com::sun::star::util::XCloneable > SAL_CALL createClone() + throw (::com::sun::star::uno::RuntimeException); + + /// XServiceInfo declarations + APPHELPER_XSERVICEINFO_DECL() + /// establish methods for factory instatiation + APPHELPER_SERVICE_FACTORY_HELPER( LogarithmicRegressionCurve ) +}; + +class ExponentialRegressionCurve : public RegressionCurveModel +{ +public: + explicit ExponentialRegressionCurve( + const ::com::sun::star::uno::Reference< + ::com::sun::star::uno::XComponentContext > & xContext ); + explicit ExponentialRegressionCurve( + const ExponentialRegressionCurve & rOther ); + virtual ~ExponentialRegressionCurve(); + + // ____ XCloneable ____ + virtual ::com::sun::star::uno::Reference< ::com::sun::star::util::XCloneable > SAL_CALL createClone() + throw (::com::sun::star::uno::RuntimeException); + + /// XServiceInfo declarations + APPHELPER_XSERVICEINFO_DECL() + /// establish methods for factory instatiation + APPHELPER_SERVICE_FACTORY_HELPER( ExponentialRegressionCurve ) +}; + +class PotentialRegressionCurve : public RegressionCurveModel +{ +public: + explicit PotentialRegressionCurve( + const ::com::sun::star::uno::Reference< + ::com::sun::star::uno::XComponentContext > & xContext ); + explicit PotentialRegressionCurve( + const PotentialRegressionCurve & rOther ); + virtual ~PotentialRegressionCurve(); + + // ____ XCloneable ____ + virtual ::com::sun::star::uno::Reference< ::com::sun::star::util::XCloneable > SAL_CALL createClone() + throw (::com::sun::star::uno::RuntimeException); + + /// XServiceInfo declarations + APPHELPER_XSERVICEINFO_DECL() + /// establish methods for factory instatiation + APPHELPER_SERVICE_FACTORY_HELPER( PotentialRegressionCurve ) +}; + +} // namespace chart + +// CHART2_REGRESSIONCURVEMODEL_HXX +#endif diff --git a/chart2/source/tools/RegressionEquation.cxx b/chart2/source/tools/RegressionEquation.cxx new file mode 100644 index 000000000000..ea16e5b7702a --- /dev/null +++ b/chart2/source/tools/RegressionEquation.cxx @@ -0,0 +1,362 @@ +/************************************************************************* + * + * 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 "RegressionEquation.hxx" +#include "LineProperties.hxx" +#include "FillProperties.hxx" +#include "UserDefinedProperties.hxx" +#include "CharacterProperties.hxx" +#include "PropertyHelper.hxx" +#include "macros.hxx" +#include "ContainerHelper.hxx" + +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/drawing/FillStyle.hpp> +#include <com/sun/star/drawing/LineStyle.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/chart2/RelativePosition.hpp> +#include <com/sun/star/awt/Size.hpp> + +#include <algorithm> + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::beans::Property; +using ::osl::MutexGuard; + +// ____________________________________________________________ + +namespace +{ + +static const ::rtl::OUString lcl_aImplementationName( + RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.chart2.RegressionEquation" )); +static const ::rtl::OUString lcl_aServiceName( + RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.chart2.RegressionEquation" )); + +enum +{ + PROP_EQUATION_SHOW, + PROP_EQUATION_SHOW_CORRELATION_COEFF, +// PROP_EQUATION_SEPARATOR, + PROP_EQUATION_REF_PAGE_SIZE, + PROP_EQUATION_REL_POS, + PROP_EQUATION_NUMBER_FORMAT +}; + +void lcl_AddPropertiesToVector( + ::std::vector< Property > & rOutProperties ) +{ + rOutProperties.push_back( + Property( C2U( "ShowEquation" ), + PROP_EQUATION_SHOW, + ::getBooleanCppuType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); + + rOutProperties.push_back( + Property( C2U( "ShowCorrelationCoefficient" ), + PROP_EQUATION_SHOW_CORRELATION_COEFF, + ::getBooleanCppuType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); + +// rOutProperties.push_back( +// Property( C2U( "Separator" ), +// PROP_EQUATION_SEPARATOR, +// ::getCppuType( reinterpret_cast< ::rtl::OUString * >(0)), +// beans::PropertyAttribute::BOUND +// | beans::PropertyAttribute::MAYBEDEFAULT )); + + rOutProperties.push_back( + Property( C2U( "ReferencePageSize" ), + PROP_EQUATION_REF_PAGE_SIZE, + ::getCppuType( reinterpret_cast< const awt::Size * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID )); + + rOutProperties.push_back( + Property( C2U( "RelativePosition" ), + PROP_EQUATION_REL_POS, + ::getCppuType( reinterpret_cast< const chart2::RelativePosition * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID )); + + rOutProperties.push_back( + Property( C2U( "NumberFormat" ), + PROP_EQUATION_NUMBER_FORMAT, + ::getCppuType( reinterpret_cast< const sal_Int32 * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID )); +} + +void lcl_AddDefaultsToMap( + ::chart::tPropertyValueMap & rOutMap ) +{ + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_EQUATION_SHOW, false ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_EQUATION_SHOW_CORRELATION_COEFF, false ); +// ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_EQUATION_SEPARATOR, ::rtl::OUString( sal_Unicode( '\n' ))); + + // override other defaults + ::chart::PropertyHelper::setPropertyValue( rOutMap, ::chart::FillProperties::PROP_FILL_STYLE, drawing::FillStyle_NONE ); + ::chart::PropertyHelper::setPropertyValue( rOutMap, ::chart::LineProperties::PROP_LINE_STYLE, drawing::LineStyle_NONE ); + + float fDefaultCharHeight = 10.0; + ::chart::PropertyHelper::setPropertyValue( rOutMap, ::chart::CharacterProperties::PROP_CHAR_CHAR_HEIGHT, fDefaultCharHeight ); + ::chart::PropertyHelper::setPropertyValue( rOutMap, ::chart::CharacterProperties::PROP_CHAR_ASIAN_CHAR_HEIGHT, fDefaultCharHeight ); + ::chart::PropertyHelper::setPropertyValue( rOutMap, ::chart::CharacterProperties::PROP_CHAR_COMPLEX_CHAR_HEIGHT, fDefaultCharHeight ); +} + +const uno::Sequence< Property > & lcl_GetPropertySequence() +{ + static uno::Sequence< Property > aPropSeq; + + // /-- + MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if( 0 == aPropSeq.getLength() ) + { + // get properties + ::std::vector< ::com::sun::star::beans::Property > aProperties; + lcl_AddPropertiesToVector( aProperties ); + ::chart::LineProperties::AddPropertiesToVector( aProperties ); + ::chart::FillProperties::AddPropertiesToVector( aProperties ); + ::chart::CharacterProperties::AddPropertiesToVector( aProperties ); + ::chart::UserDefinedProperties::AddPropertiesToVector( aProperties ); + + // and sort them for access via bsearch + ::std::sort( aProperties.begin(), aProperties.end(), + ::chart::PropertyNameLess() ); + + // transfer result to static Sequence + aPropSeq = ::chart::ContainerHelper::ContainerToSequence( aProperties ); + } + + return aPropSeq; +} + +::cppu::IPropertyArrayHelper & lcl_getInfoHelper() +{ + static ::cppu::OPropertyArrayHelper aArrayHelper( + lcl_GetPropertySequence(), + /* bSorted = */ sal_True ); + + return aArrayHelper; +} + +} // anonymous namespace + +// ____________________________________________________________ + +namespace chart +{ + +RegressionEquation::RegressionEquation( const Reference< uno::XComponentContext > & xContext ) : + ::property::OPropertySet( m_aMutex ), + m_xModifyEventForwarder( new ModifyListenerHelper::ModifyEventForwarder()), + m_xContext( xContext ) +{} + +RegressionEquation::RegressionEquation( const RegressionEquation & rOther ) : + MutexContainer(), + impl::RegressionEquation_Base(), + ::property::OPropertySet( rOther, m_aMutex ), + m_xModifyEventForwarder( new ModifyListenerHelper::ModifyEventForwarder()) +{} + +RegressionEquation::~RegressionEquation() +{} + + +// ____ XCloneable ____ +uno::Reference< util::XCloneable > SAL_CALL RegressionEquation::createClone() + throw (uno::RuntimeException) +{ + return uno::Reference< util::XCloneable >( new RegressionEquation( *this )); +} + +// ____ OPropertySet ____ +uno::Any RegressionEquation::GetDefaultValue( sal_Int32 nHandle ) const + throw(beans::UnknownPropertyException) +{ + static tPropertyValueMap aStaticDefaults; + + // /-- + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if( 0 == aStaticDefaults.size() ) + { + // initialize defaults + LineProperties::AddDefaultsToMap( aStaticDefaults ); + FillProperties::AddDefaultsToMap( aStaticDefaults ); + CharacterProperties::AddDefaultsToMap( aStaticDefaults ); + + // overrides a line property + lcl_AddDefaultsToMap( aStaticDefaults ); + } + + tPropertyValueMap::const_iterator aFound( + aStaticDefaults.find( nHandle )); + + if( aFound == aStaticDefaults.end()) + return uno::Any(); + + return (*aFound).second; + // \-- +} + +::cppu::IPropertyArrayHelper & SAL_CALL RegressionEquation::getInfoHelper() +{ + return lcl_getInfoHelper(); +} + +// ____ XPropertySet ____ +Reference< beans::XPropertySetInfo > SAL_CALL + RegressionEquation::getPropertySetInfo() + throw (uno::RuntimeException) +{ + static Reference< beans::XPropertySetInfo > xInfo; + + // /-- + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if( !xInfo.is()) + { + xInfo = ::cppu::OPropertySetHelper::createPropertySetInfo( + lcl_getInfoHelper()); + } + + return xInfo; + // \-- +} + + +// ____ XModifyBroadcaster ____ +void SAL_CALL RegressionEquation::addModifyListener( const uno::Reference< util::XModifyListener >& aListener ) + throw (uno::RuntimeException) +{ + try + { + uno::Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW ); + xBroadcaster->addModifyListener( aListener ); + } + catch( const uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } +} + +void SAL_CALL RegressionEquation::removeModifyListener( const uno::Reference< util::XModifyListener >& aListener ) + throw (uno::RuntimeException) +{ + try + { + uno::Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW ); + xBroadcaster->removeModifyListener( aListener ); + } + catch( const uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } +} + +// ____ XModifyListener ____ +void SAL_CALL RegressionEquation::modified( const lang::EventObject& aEvent ) + throw (uno::RuntimeException) +{ + m_xModifyEventForwarder->modified( aEvent ); +} + +// ____ XEventListener (base of XModifyListener) ____ +void SAL_CALL RegressionEquation::disposing( const lang::EventObject& /* Source */ ) + throw (uno::RuntimeException) +{ + // nothing +} + +// ____ OPropertySet ____ +void RegressionEquation::firePropertyChangeEvent() +{ + fireModifyEvent(); +} + +void RegressionEquation::fireModifyEvent() +{ + m_xModifyEventForwarder->modified( lang::EventObject( static_cast< uno::XWeak* >( this ))); +} + +// -------------------------------------------------------------------------------- + +// ____ XTitle ____ +uno::Sequence< uno::Reference< chart2::XFormattedString > > SAL_CALL RegressionEquation::getText() + throw (uno::RuntimeException) +{ + // /-- + MutexGuard aGuard( GetMutex() ); + return m_aStrings; + // \-- +} + +void SAL_CALL RegressionEquation::setText( const uno::Sequence< uno::Reference< chart2::XFormattedString > >& Strings ) + throw (uno::RuntimeException) +{ + // /-- + MutexGuard aGuard( GetMutex() ); + ModifyListenerHelper::removeListenerFromAllElements( + ContainerHelper::SequenceToVector( m_aStrings ), m_xModifyEventForwarder ); + m_aStrings = Strings; + ModifyListenerHelper::addListenerToAllElements( + ContainerHelper::SequenceToVector( m_aStrings ), m_xModifyEventForwarder ); + fireModifyEvent(); + // \-- +} + +// ================================================================================ + +uno::Sequence< ::rtl::OUString > RegressionEquation::getSupportedServiceNames_Static() +{ + const sal_Int32 nNumServices( 5 ); + sal_Int32 nI = 0; + uno::Sequence< ::rtl::OUString > aServices( nNumServices ); + aServices[ nI++ ] = lcl_aServiceName; + aServices[ nI++ ] = C2U( "com.sun.star.beans.PropertySet" ); + aServices[ nI++ ] = C2U( "com.sun.star.drawing.FillProperties" ); + aServices[ nI++ ] = C2U( "com.sun.star.drawing.LineProperties" ); + aServices[ nI++ ] = C2U( "com.sun.star.style.CharacterProperties" ); + OSL_ASSERT( nNumServices == nI ); + return aServices; +} + +// implement XServiceInfo methods basing upon getSupportedServiceNames_Static +APPHELPER_XSERVICEINFO_IMPL( RegressionEquation, lcl_aImplementationName ); + +using impl::RegressionEquation_Base; + +IMPLEMENT_FORWARD_XINTERFACE2( RegressionEquation, RegressionEquation_Base, ::property::OPropertySet ) + +} // namespace chart diff --git a/chart2/source/tools/RegressionEquation.hxx b/chart2/source/tools/RegressionEquation.hxx new file mode 100644 index 000000000000..35dbd828370d --- /dev/null +++ b/chart2/source/tools/RegressionEquation.hxx @@ -0,0 +1,143 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ +#ifndef CHART2_REGRESSIONEQUATION_HXX +#define CHART2_REGRESSIONEQUATION_HXX + +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/util/XCloneable.hpp> +#include <com/sun/star/util/XModifyBroadcaster.hpp> +#include <com/sun/star/util/XModifyListener.hpp> +#include <com/sun/star/chart2/XTitle.hpp> + +#include "MutexContainer.hxx" +#include "OPropertySet.hxx" +#include "ServiceMacros.hxx" +#include "ModifyListenerHelper.hxx" + +#include <cppuhelper/implbase4.hxx> +#include <comphelper/uno3.hxx> + +namespace chart +{ + +namespace impl +{ +typedef ::cppu::WeakImplHelper4< + ::com::sun::star::util::XCloneable, + ::com::sun::star::util::XModifyBroadcaster, + ::com::sun::star::util::XModifyListener, + ::com::sun::star::chart2::XTitle > + RegressionEquation_Base; +} + +class RegressionEquation : + public MutexContainer, + public impl::RegressionEquation_Base, + public ::property::OPropertySet +{ +public: + explicit RegressionEquation( + const ::com::sun::star::uno::Reference< + ::com::sun::star::uno::XComponentContext > & xContext ); + virtual ~RegressionEquation(); + + /// XServiceInfo declarations + APPHELPER_XSERVICEINFO_DECL() + /// merge XInterface implementations + DECLARE_XINTERFACE() + /// establish methods for factory instatiation + APPHELPER_SERVICE_FACTORY_HELPER( RegressionEquation ) + +protected: + explicit RegressionEquation( const RegressionEquation & rOther ); + + // ____ OPropertySet ____ + virtual ::com::sun::star::uno::Any GetDefaultValue( sal_Int32 nHandle ) const + throw(::com::sun::star::beans::UnknownPropertyException); + + virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper(); + + // ____ XPropertySet ____ + virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL + getPropertySetInfo() + throw (::com::sun::star::uno::RuntimeException); + + + // ____ XCloneable ____ + virtual ::com::sun::star::uno::Reference< ::com::sun::star::util::XCloneable > SAL_CALL createClone() + throw (::com::sun::star::uno::RuntimeException); + + // ____ XModifyBroadcaster ____ + virtual void SAL_CALL addModifyListener( + const ::com::sun::star::uno::Reference< ::com::sun::star::util::XModifyListener >& aListener ) + throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeModifyListener( + const ::com::sun::star::uno::Reference< ::com::sun::star::util::XModifyListener >& aListener ) + throw (::com::sun::star::uno::RuntimeException); + + // ____ XModifyListener ____ + virtual void SAL_CALL modified( + const ::com::sun::star::lang::EventObject& aEvent ) + throw (::com::sun::star::uno::RuntimeException); + + // ____ XEventListener (base of XModifyListener) ____ + virtual void SAL_CALL disposing( + const ::com::sun::star::lang::EventObject& Source ) + throw (::com::sun::star::uno::RuntimeException); + + // ____ XTitle ____ + virtual ::com::sun::star::uno::Sequence< + ::com::sun::star::uno::Reference< + ::com::sun::star::chart2::XFormattedString > > SAL_CALL getText() + throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setText( const ::com::sun::star::uno::Sequence< + ::com::sun::star::uno::Reference< + ::com::sun::star::chart2::XFormattedString > >& Strings ) + throw (::com::sun::star::uno::RuntimeException); + + using ::cppu::OPropertySetHelper::disposing; + + // ____ OPropertySet ____ + virtual void firePropertyChangeEvent(); + + void fireModifyEvent(); + +private: + ::com::sun::star::uno::Sequence< + ::com::sun::star::uno::Reference< + ::com::sun::star::chart2::XFormattedString > > m_aStrings; + + ::com::sun::star::uno::Reference< ::com::sun::star::util::XModifyListener > m_xModifyEventForwarder; + ::com::sun::star::uno::Reference< + ::com::sun::star::uno::XComponentContext > + m_xContext; +}; + +} // namespace chart + +// CHART2_REGRESSIONEQUATION_HXX +#endif diff --git a/chart2/source/tools/RelativePositionHelper.cxx b/chart2/source/tools/RelativePositionHelper.cxx new file mode 100644 index 000000000000..4d566b1f7f48 --- /dev/null +++ b/chart2/source/tools/RelativePositionHelper.cxx @@ -0,0 +1,399 @@ +/************************************************************************* + * + * 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 "RelativePositionHelper.hxx" +#include <rtl/math.hxx> + +using namespace ::com::sun::star; + +namespace chart +{ + +// static +chart2::RelativePosition RelativePositionHelper::getReanchoredPosition( + const chart2::RelativePosition & rPosition, + const chart2::RelativeSize & rObjectSize, + drawing::Alignment aNewAnchor ) +{ + chart2::RelativePosition aResult( rPosition ); + if( rPosition.Anchor != aNewAnchor ) + { + sal_Int32 nShiftHalfWidths = 0; + sal_Int32 nShiftHalfHeights = 0; + + // normalize to top-left + switch( rPosition.Anchor ) + { + case drawing::Alignment_TOP_LEFT: + break; + case drawing::Alignment_LEFT: + nShiftHalfHeights -= 1; + break; + case drawing::Alignment_BOTTOM_LEFT: + nShiftHalfHeights -= 2; + break; + case drawing::Alignment_TOP: + nShiftHalfWidths -= 1; + break; + case drawing::Alignment_CENTER: + nShiftHalfWidths -= 1; + nShiftHalfHeights -= 1; + break; + case drawing::Alignment_BOTTOM: + nShiftHalfWidths -= 1; + nShiftHalfHeights -= 2; + break; + case drawing::Alignment_TOP_RIGHT: + nShiftHalfWidths -= 2; + break; + case drawing::Alignment_RIGHT: + nShiftHalfWidths -= 2; + nShiftHalfHeights -= 1; + break; + case drawing::Alignment_BOTTOM_RIGHT: + nShiftHalfWidths -= 2; + nShiftHalfHeights -= 2; + break; + case drawing::Alignment_MAKE_FIXED_SIZE: + break; + } + + // transform + switch( aNewAnchor ) + { + case drawing::Alignment_TOP_LEFT: + break; + case drawing::Alignment_LEFT: + nShiftHalfHeights += 1; + break; + case drawing::Alignment_BOTTOM_LEFT: + nShiftHalfHeights += 2; + break; + case drawing::Alignment_TOP: + nShiftHalfWidths += 1; + break; + case drawing::Alignment_CENTER: + nShiftHalfWidths += 1; + nShiftHalfHeights += 1; + break; + case drawing::Alignment_BOTTOM: + nShiftHalfWidths += 1; + nShiftHalfHeights += 2; + break; + case drawing::Alignment_TOP_RIGHT: + nShiftHalfWidths += 2; + break; + case drawing::Alignment_RIGHT: + nShiftHalfWidths += 2; + nShiftHalfHeights += 1; + break; + case drawing::Alignment_BOTTOM_RIGHT: + nShiftHalfWidths += 2; + nShiftHalfHeights += 2; + break; + case drawing::Alignment_MAKE_FIXED_SIZE: + break; + } + + if( nShiftHalfWidths != 0 ) + aResult.Primary += (rObjectSize.Primary / 2.0) * nShiftHalfWidths; + if( nShiftHalfHeights != 0 ) + aResult.Secondary += (rObjectSize.Secondary / 2.0) * nShiftHalfHeights; + } + + return aResult; +} + + +// static +awt::Point RelativePositionHelper::getUpperLeftCornerOfAnchoredObject( + awt::Point aPoint + , awt::Size aObjectSize + , drawing::Alignment aAnchor ) +{ + awt::Point aResult( aPoint ); + + double fXDelta = 0.0; + double fYDelta = 0.0; + + // adapt x-value + switch( aAnchor ) + { + case drawing::Alignment_TOP: + case drawing::Alignment_CENTER: + case drawing::Alignment_BOTTOM: + fXDelta -= static_cast< double >( aObjectSize.Width ) / 2.0; + break; + case drawing::Alignment_TOP_RIGHT: + case drawing::Alignment_RIGHT: + case drawing::Alignment_BOTTOM_RIGHT: + fXDelta -= aObjectSize.Width; + break; + case drawing::Alignment_TOP_LEFT: + case drawing::Alignment_LEFT: + case drawing::Alignment_BOTTOM_LEFT: + default: + // nothing to do + break; + } + + // adapt y-value + switch( aAnchor ) + { + case drawing::Alignment_LEFT: + case drawing::Alignment_CENTER: + case drawing::Alignment_RIGHT: + fYDelta -= static_cast< double >( aObjectSize.Height ) / 2.0; + break; + case drawing::Alignment_BOTTOM_LEFT: + case drawing::Alignment_BOTTOM: + case drawing::Alignment_BOTTOM_RIGHT: + fYDelta -= aObjectSize.Height; + break; + case drawing::Alignment_TOP_LEFT: + case drawing::Alignment_TOP: + case drawing::Alignment_TOP_RIGHT: + default: + // nothing to do + break; + } + + aResult.X += static_cast< sal_Int32 >( ::rtl::math::round( fXDelta )); + aResult.Y += static_cast< sal_Int32 >( ::rtl::math::round( fYDelta )); + + return aResult; +} + +// static +awt::Point RelativePositionHelper::getCenterOfAnchoredObject( + awt::Point aPoint + , awt::Size aUnrotatedObjectSize + , drawing::Alignment aAnchor + , double fAnglePi ) +{ + awt::Point aResult( aPoint ); + + double fXDelta = 0.0; + double fYDelta = 0.0; + + // adapt x-value + switch( aAnchor ) + { + case drawing::Alignment_TOP: + case drawing::Alignment_CENTER: + case drawing::Alignment_BOTTOM: + // nothing to do + break; + case drawing::Alignment_TOP_RIGHT: + case drawing::Alignment_RIGHT: + case drawing::Alignment_BOTTOM_RIGHT: + fXDelta -= aUnrotatedObjectSize.Width/2; + break; + case drawing::Alignment_TOP_LEFT: + case drawing::Alignment_LEFT: + case drawing::Alignment_BOTTOM_LEFT: + default: + fXDelta += aUnrotatedObjectSize.Width/2; + break; + } + + // adapt y-value + switch( aAnchor ) + { + case drawing::Alignment_LEFT: + case drawing::Alignment_CENTER: + case drawing::Alignment_RIGHT: + // nothing to do + break; + case drawing::Alignment_BOTTOM_LEFT: + case drawing::Alignment_BOTTOM: + case drawing::Alignment_BOTTOM_RIGHT: + fYDelta -= aUnrotatedObjectSize.Height/2; + break; + case drawing::Alignment_TOP_LEFT: + case drawing::Alignment_TOP: + case drawing::Alignment_TOP_RIGHT: + fYDelta += aUnrotatedObjectSize.Height/2; + default: + // nothing to do + break; + } + + //take rotation into account: + aResult.X += static_cast< sal_Int32 >( + ::rtl::math::round( fXDelta * rtl::math::cos( fAnglePi ) + fYDelta * rtl::math::sin( fAnglePi ) ) ); + aResult.Y += static_cast< sal_Int32 >( + ::rtl::math::round( - fXDelta * rtl::math::sin( fAnglePi ) + fYDelta * rtl::math::cos( fAnglePi ) ) ); + + return aResult; +} + +bool RelativePositionHelper::centerGrow( + chart2::RelativePosition & rInOutPosition, + chart2::RelativeSize & rInOutSize, + double fAmountX, double fAmountY, + bool bCheck /* = true */ ) +{ + chart2::RelativePosition aPos( rInOutPosition ); + chart2::RelativeSize aSize( rInOutSize ); + const double fPosCheckThreshold = 0.02; + const double fSizeCheckThreshold = 0.1; + + // grow/shrink, back to relaative + aSize.Primary += fAmountX; + aSize.Secondary += fAmountY; + + double fShiftAmountX = fAmountX / 2.0; + double fShiftAmountY = fAmountY / 2.0; + + // shift X + switch( rInOutPosition.Anchor ) + { + case drawing::Alignment_TOP_LEFT: + case drawing::Alignment_LEFT: + case drawing::Alignment_BOTTOM_LEFT: + aPos.Primary -= fShiftAmountX; + break; + case drawing::Alignment_TOP: + case drawing::Alignment_CENTER: + case drawing::Alignment_BOTTOM: + // nothing + break; + case drawing::Alignment_TOP_RIGHT: + case drawing::Alignment_RIGHT: + case drawing::Alignment_BOTTOM_RIGHT: + aPos.Primary += fShiftAmountX; + break; + case drawing::Alignment_MAKE_FIXED_SIZE: + break; + } + + // shift Y + switch( rInOutPosition.Anchor ) + { + case drawing::Alignment_TOP: + case drawing::Alignment_TOP_LEFT: + case drawing::Alignment_TOP_RIGHT: + aPos.Secondary -= fShiftAmountY; + break; + case drawing::Alignment_CENTER: + case drawing::Alignment_LEFT: + case drawing::Alignment_RIGHT: + // nothing + break; + case drawing::Alignment_BOTTOM: + case drawing::Alignment_BOTTOM_LEFT: + case drawing::Alignment_BOTTOM_RIGHT: + aPos.Secondary += fShiftAmountY; + break; + case drawing::Alignment_MAKE_FIXED_SIZE: + break; + } + + // anchor must not be changed + OSL_ASSERT( rInOutPosition.Anchor == aPos.Anchor ); + + if( rInOutPosition.Primary == aPos.Primary && + rInOutPosition.Secondary == aPos.Secondary && + rInOutSize.Primary == aSize.Primary && + rInOutSize.Secondary == aSize.Secondary ) + return false; + + // check + if( bCheck ) + { + // Note: this somewhat complicated check allows the output being + // out-of-bounds if the input was also out-of-bounds, and the change is + // for "advantage". E.g., you have a chart that laps out on the left + // side. If you shrink it, this should be possible, also if it still + // laps out on the left side afterwards. But you shouldn't be able to + // grow it then. + + chart2::RelativePosition aUpperLeft( + RelativePositionHelper::getReanchoredPosition( aPos, aSize, drawing::Alignment_TOP_LEFT )); + chart2::RelativePosition aLowerRight( + RelativePositionHelper::getReanchoredPosition( aPos, aSize, drawing::Alignment_BOTTOM_RIGHT )); + + // Do not grow, if this leads to corners being off-screen + if( fAmountX > 0.0 && + ( (aUpperLeft.Primary < fPosCheckThreshold) || + (aLowerRight.Primary > (1.0 - fPosCheckThreshold)) )) + return false; + if( fAmountY > 0.0 && + ( (aUpperLeft.Secondary < fPosCheckThreshold) || + (aLowerRight.Secondary > (1.0 - fPosCheckThreshold)) )) + return false; + + // Do not shrink, if this leads to a size too small + if( fAmountX < 0.0 && + ( aSize.Primary < fSizeCheckThreshold )) + return false; + if( fAmountY < 0.0 && + ( aSize.Secondary < fSizeCheckThreshold )) + return false; + } + + rInOutPosition = aPos; + rInOutSize = aSize; + return true; +} + +bool RelativePositionHelper::moveObject( + chart2::RelativePosition & rInOutPosition, + const chart2::RelativeSize & rObjectSize, + double fAmountX, double fAmountY, + bool bCheck /* = true */ ) +{ + chart2::RelativePosition aPos( rInOutPosition ); + aPos.Primary += fAmountX; + aPos.Secondary += fAmountY; + const double fPosCheckThreshold = 0.02; + + if( bCheck ) + { + chart2::RelativePosition aUpperLeft( + RelativePositionHelper::getReanchoredPosition( aPos, rObjectSize, drawing::Alignment_TOP_LEFT )); + chart2::RelativePosition aLowerRight( aUpperLeft ); + aLowerRight.Primary += rObjectSize.Primary; + aLowerRight.Secondary += rObjectSize.Secondary; + + const double fFarEdgeThreshold = 1.0 - fPosCheckThreshold; + if( ( fAmountX > 0.0 && (aLowerRight.Primary > fFarEdgeThreshold)) || + ( fAmountX < 0.0 && (aUpperLeft.Primary < fPosCheckThreshold)) || + ( fAmountY > 0.0 && (aLowerRight.Secondary > fFarEdgeThreshold)) || + ( fAmountY < 0.0 && (aUpperLeft.Secondary < fPosCheckThreshold)) ) + return false; + } + + rInOutPosition = aPos; + return true; +} + +} // namespace chart diff --git a/chart2/source/tools/RelativeSizeHelper.cxx b/chart2/source/tools/RelativeSizeHelper.cxx new file mode 100644 index 000000000000..d3da090ca397 --- /dev/null +++ b/chart2/source/tools/RelativeSizeHelper.cxx @@ -0,0 +1,100 @@ +/************************************************************************* + * + * 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 "RelativeSizeHelper.hxx" +#include "macros.hxx" + +#include <vector> +#include <algorithm> + +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::beans; +using namespace ::std; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::makeAny; +using ::com::sun::star::uno::Exception; +using ::rtl::OUString; + +namespace chart +{ + +// static +double RelativeSizeHelper::calculate( + double fValue, + const Size & rOldReferenceSize, + const Size & rNewReferenceSize ) +{ + if( rOldReferenceSize.Width <= 0 || + rOldReferenceSize.Height <= 0 ) + return fValue; + + return min( + static_cast< double >( rNewReferenceSize.Width ) / static_cast< double >( rOldReferenceSize.Width ), + static_cast< double >( rNewReferenceSize.Height ) / static_cast< double >( rOldReferenceSize.Height )) + * fValue; +} + +// static +void RelativeSizeHelper::adaptFontSizes( + const Reference< XPropertySet > & xTargetProperties, + const Size & rOldReferenceSize, + const Size & rNewReferenceSize ) +{ + if( ! xTargetProperties.is()) + return; + + float fFontHeight = 0; + + vector< OUString > aProperties; + aProperties.push_back( OUString( RTL_CONSTASCII_USTRINGPARAM( "CharHeight" ))); + aProperties.push_back( OUString( RTL_CONSTASCII_USTRINGPARAM( "CharHeightAsian" ))); + aProperties.push_back( OUString( RTL_CONSTASCII_USTRINGPARAM( "CharHeightComplex" ))); + + for( vector< OUString >::const_iterator aIt = aProperties.begin(); + aIt != aProperties.end(); ++aIt ) + { + try + { + if( xTargetProperties->getPropertyValue( *aIt ) >>= fFontHeight ) + { + xTargetProperties->setPropertyValue( + *aIt, + makeAny( static_cast< float >( + calculate( fFontHeight, rOldReferenceSize, rNewReferenceSize )))); + } + } + catch( const Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + } +} + +} // namespace chart diff --git a/chart2/source/tools/ResId.cxx b/chart2/source/tools/ResId.cxx new file mode 100644 index 000000000000..0d6e35974aaa --- /dev/null +++ b/chart2/source/tools/ResId.cxx @@ -0,0 +1,47 @@ +/************************************************************************* + * + * 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 "ResId.hxx" +#include "RessourceManager.hxx" +#include <tools/string.hxx> + +namespace chart +{ + +SchResId::SchResId( sal_Int16 nId ) + : ResId( nId, RessourceManager::getRessourceManager() ) +{} + +::rtl::OUString SchResId::getResString( sal_Int16 nId ) +{ + return ::rtl::OUString( String( SchResId( nId ))); +} + +} // namespace chart diff --git a/chart2/source/tools/RessourceManager.cxx b/chart2/source/tools/RessourceManager.cxx new file mode 100644 index 000000000000..a2d43b309019 --- /dev/null +++ b/chart2/source/tools/RessourceManager.cxx @@ -0,0 +1,49 @@ +/************************************************************************* + * + * 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 "RessourceManager.hxx" + +#include <tools/resmgr.hxx> + +namespace chart +{ + +ResMgr * RessourceManager::m_pRessourceManager = 0; + +ResMgr & RessourceManager::getRessourceManager() +{ + // not threadsafe + if( ! m_pRessourceManager ) + m_pRessourceManager = CREATEVERSIONRESMGR( chartcontroller ); + OSL_ASSERT( m_pRessourceManager ); + return *m_pRessourceManager; +} + +} // namespace chart diff --git a/chart2/source/tools/Scaling.cxx b/chart2/source/tools/Scaling.cxx new file mode 100644 index 000000000000..e106f1dcc5e2 --- /dev/null +++ b/chart2/source/tools/Scaling.cxx @@ -0,0 +1,271 @@ +/************************************************************************* + * + * 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 "Scaling.hxx" +#include <rtl/math.hxx> +#include "com/sun/star/uno/RuntimeException.hpp" + +namespace +{ + +static const ::rtl::OUString lcl_aServiceName_Logarithmic( + RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.chart2.LogarithmicScaling" )); +static const ::rtl::OUString lcl_aServiceName_Exponential( + RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.chart2.ExponentialScaling" )); +static const ::rtl::OUString lcl_aServiceName_Linear( + RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.chart2.LinearScaling" )); +static const ::rtl::OUString lcl_aServiceName_Power( + RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.chart2.PowerScaling" )); + +static const ::rtl::OUString lcl_aImplementationName_Logarithmic( + RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.chart2.LogarithmicScaling" )); +static const ::rtl::OUString lcl_aImplementationName_Exponential( + RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.chart2.ExponentialScaling" )); +static const ::rtl::OUString lcl_aImplementationName_Linear( + RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.chart2.LinearScaling" )); +static const ::rtl::OUString lcl_aImplementationName_Power( + RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.chart2.PowerScaling" )); +} + +//............................................................................. +namespace chart +{ +//............................................................................. +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +LogarithmicScaling::LogarithmicScaling( const uno::Reference< uno::XComponentContext > & xContext ) : + m_fBase( 10.0 ), + m_fLogOfBase( log( 10.0 ) ), + m_xContext( xContext ) +{ +} + +LogarithmicScaling::LogarithmicScaling( double fBase ) : + m_fBase( fBase ), + m_fLogOfBase( log( fBase ) ) +{ +} + +LogarithmicScaling::~LogarithmicScaling() +{ +} + + double SAL_CALL +LogarithmicScaling::doScaling( double value ) + throw (uno::RuntimeException) +{ + double fResult; + if( ::rtl::math::isNan( value ) || ::rtl::math::isInf( value ) ) + ::rtl::math::setNan( & fResult ); + else + fResult = log( value ) / m_fLogOfBase; + return fResult; +} + + uno::Reference< XScaling > SAL_CALL +LogarithmicScaling::getInverseScaling() + throw (uno::RuntimeException) +{ + return new ExponentialScaling( m_fBase ); +} + + ::rtl::OUString SAL_CALL +LogarithmicScaling::getServiceName() + throw (uno::RuntimeException) +{ + return lcl_aServiceName_Logarithmic; +} + +uno::Sequence< ::rtl::OUString > LogarithmicScaling::getSupportedServiceNames_Static() +{ + return uno::Sequence< ::rtl::OUString >( & lcl_aServiceName_Logarithmic, 1 ); +} + +// implement XServiceInfo methods basing upon getSupportedServiceNames_Static +APPHELPER_XSERVICEINFO_IMPL( LogarithmicScaling, lcl_aServiceName_Logarithmic ) + +// ---------------------------------------- + +ExponentialScaling::ExponentialScaling( const uno::Reference< uno::XComponentContext > & xContext ) : + m_fBase( 10.0 ), + m_xContext( xContext ) +{ +} + +ExponentialScaling::ExponentialScaling( double fBase ) : + m_fBase( fBase ) +{ +} + +ExponentialScaling::~ExponentialScaling() +{ +} + + double SAL_CALL +ExponentialScaling::doScaling( double value ) + throw (uno::RuntimeException) +{ + double fResult; + if( ::rtl::math::isNan( value ) || ::rtl::math::isInf( value ) ) + ::rtl::math::setNan( & fResult ); + else + fResult = pow( m_fBase, value ); + return fResult; +} + + uno::Reference< XScaling > SAL_CALL +ExponentialScaling::getInverseScaling() + throw (uno::RuntimeException) +{ + return new LogarithmicScaling( m_fBase ); +} + + ::rtl::OUString SAL_CALL +ExponentialScaling::getServiceName() + throw (uno::RuntimeException) +{ + return lcl_aServiceName_Exponential; +} + +uno::Sequence< ::rtl::OUString > ExponentialScaling::getSupportedServiceNames_Static() +{ + return uno::Sequence< ::rtl::OUString >( & lcl_aServiceName_Exponential, 1 ); +} + +// implement XServiceInfo methods basing upon getSupportedServiceNames_Static +APPHELPER_XSERVICEINFO_IMPL( ExponentialScaling, lcl_aServiceName_Exponential ) + +// ---------------------------------------- + +LinearScaling::LinearScaling( const uno::Reference< uno::XComponentContext > & xContext ) : + m_fSlope( 1.0 ), + m_fOffset( 0.0 ), + m_xContext( xContext ) +{} + +LinearScaling::LinearScaling( double fSlope, double fOffset ) : + m_fSlope( fSlope ), + m_fOffset( fOffset ) +{} + +LinearScaling::~LinearScaling() +{} + +double SAL_CALL LinearScaling::doScaling( double value ) + throw (uno::RuntimeException) +{ + double fResult; + if( ::rtl::math::isNan( value ) || ::rtl::math::isInf( value ) ) + ::rtl::math::setNan( & fResult ); + else + fResult = m_fOffset + m_fSlope * value; + return fResult; +} + +uno::Reference< XScaling > SAL_CALL + LinearScaling::getInverseScaling() + throw (uno::RuntimeException) +{ + // ToDo: ApproxEqual ? + if( m_fSlope == 0 ) + throw uno::RuntimeException(); + + return new LinearScaling( 1.0 / m_fSlope, m_fOffset / m_fSlope ); +} + + ::rtl::OUString SAL_CALL +LinearScaling::getServiceName() + throw (uno::RuntimeException) +{ + return lcl_aServiceName_Linear; +} + +uno::Sequence< ::rtl::OUString > LinearScaling::getSupportedServiceNames_Static() +{ + return uno::Sequence< ::rtl::OUString >( & lcl_aServiceName_Linear, 1 ); +} + +// implement XServiceInfo methods basing upon getSupportedServiceNames_Static +APPHELPER_XSERVICEINFO_IMPL( LinearScaling, lcl_aServiceName_Linear ) + +// ---------------------------------------- + +PowerScaling::PowerScaling( const uno::Reference< uno::XComponentContext > & xContext ) : + m_fExponent( 10.0 ), + m_xContext( xContext ) +{} + +PowerScaling::PowerScaling( double fExponent ) : + m_fExponent( fExponent ) +{} + +PowerScaling::~PowerScaling() +{} + +double SAL_CALL PowerScaling::doScaling( double value ) + throw (uno::RuntimeException) +{ + double fResult; + if( ::rtl::math::isNan( value ) || ::rtl::math::isInf( value ) ) + ::rtl::math::setNan( & fResult ); + else + fResult = pow( value, m_fExponent ); + return fResult; +} + +uno::Reference< XScaling > SAL_CALL + PowerScaling::getInverseScaling() + throw (uno::RuntimeException) +{ + // ToDo: ApproxEqual ? + if( m_fExponent == 0 ) + throw uno::RuntimeException(); + + return new PowerScaling( 1.0 / m_fExponent ); +} + + ::rtl::OUString SAL_CALL +PowerScaling::getServiceName() + throw (uno::RuntimeException) +{ + return lcl_aServiceName_Power; +} + +uno::Sequence< ::rtl::OUString > PowerScaling::getSupportedServiceNames_Static() +{ + return uno::Sequence< ::rtl::OUString >( & lcl_aServiceName_Power, 1 ); +} + +// implement XServiceInfo methods basing upon getSupportedServiceNames_Static +APPHELPER_XSERVICEINFO_IMPL( PowerScaling, lcl_aServiceName_Power ) + +//............................................................................. +} //namespace chart +//............................................................................. diff --git a/chart2/source/tools/SceneProperties.cxx b/chart2/source/tools/SceneProperties.cxx new file mode 100644 index 000000000000..21a95d99be7d --- /dev/null +++ b/chart2/source/tools/SceneProperties.cxx @@ -0,0 +1,382 @@ +/************************************************************************* + * + * 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 "SceneProperties.hxx" +#include "macros.hxx" +#include "ChartTypeHelper.hxx" +#include "ThreeDHelper.hxx" +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/drawing/HomogenMatrix.hpp> +#include <com/sun/star/drawing/ShadeMode.hpp> +#include <com/sun/star/drawing/Direction3D.hpp> +#include <com/sun/star/drawing/ProjectionMode.hpp> +#include <com/sun/star/drawing/CameraGeometry.hpp> + +// for F_PI +#include <tools/solar.h> + +using namespace ::com::sun::star; + +using ::com::sun::star::beans::Property; + +namespace chart +{ + +void SceneProperties::AddPropertiesToVector( + ::std::vector< Property > & rOutProperties ) +{ + // transformation matrix + rOutProperties.push_back( + Property( C2U( "D3DTransformMatrix" ), + PROP_SCENE_TRANSF_MATRIX, + ::getCppuType( reinterpret_cast< const drawing::HomogenMatrix * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT )); + + // distance: deprecated ( this is not used by the chart view; it's only here for compatibility with old chart ) + rOutProperties.push_back( + Property( C2U( "D3DSceneDistance" ), + PROP_SCENE_DISTANCE, + ::getCppuType( reinterpret_cast< const sal_Int32 * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT )); + + // focalLength: deprecated ( this is not used by the chart view; it's only here for compatibility with old chart ) + rOutProperties.push_back( + Property( C2U( "D3DSceneFocalLength" ), + PROP_SCENE_FOCAL_LENGTH, + ::getCppuType( reinterpret_cast< const sal_Int32 * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT )); + + // shadowSlant + rOutProperties.push_back( + Property( C2U( "D3DSceneShadowSlant" ), + PROP_SCENE_SHADOW_SLANT, + ::getCppuType( reinterpret_cast< const sal_Int32 * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT )); + + // shadeMode + rOutProperties.push_back( + Property( C2U( "D3DSceneShadeMode" ), + PROP_SCENE_SHADE_MODE, + ::getCppuType( reinterpret_cast< const drawing::ShadeMode * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT )); + + // ambientColor + rOutProperties.push_back( + Property( C2U( "D3DSceneAmbientColor" ), + PROP_SCENE_AMBIENT_COLOR, + ::getCppuType( reinterpret_cast< const sal_Int32 * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT )); + + // lightingMode + rOutProperties.push_back( + Property( C2U( "D3DSceneTwoSidedLighting" ), + PROP_SCENE_TWO_SIDED_LIGHTING, + ::getBooleanCppuType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT )); + + // camera geometry + rOutProperties.push_back( + Property( C2U( "D3DCameraGeometry" ), + PROP_SCENE_CAMERA_GEOMETRY, + ::getCppuType( reinterpret_cast< const drawing::CameraGeometry * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT )); + + // perspective + rOutProperties.push_back( + Property( C2U( "D3DScenePerspective" ), + PROP_SCENE_PERSPECTIVE, + ::getCppuType( reinterpret_cast< const drawing::ProjectionMode * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT )); + + + // Light Sources + // ------------- + // light source 1 + rOutProperties.push_back( + Property( C2U( "D3DSceneLightColor1" ), + PROP_SCENE_LIGHT_COLOR_1, + ::getCppuType( reinterpret_cast< const sal_Int32 * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT )); + rOutProperties.push_back( + Property( C2U( "D3DSceneLightDirection1" ), + PROP_SCENE_LIGHT_DIRECTION_1, + ::getCppuType( reinterpret_cast< const drawing::Direction3D * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT )); + rOutProperties.push_back( + Property( C2U( "D3DSceneLightOn1" ), + PROP_SCENE_LIGHT_ON_1, + ::getBooleanCppuType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT )); + // light source 2 + rOutProperties.push_back( + Property( C2U( "D3DSceneLightColor2" ), + PROP_SCENE_LIGHT_COLOR_2, + ::getCppuType( reinterpret_cast< const sal_Int32 * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT )); + rOutProperties.push_back( + Property( C2U( "D3DSceneLightDirection2" ), + PROP_SCENE_LIGHT_DIRECTION_2, + ::getCppuType( reinterpret_cast< const drawing::Direction3D * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT )); + rOutProperties.push_back( + Property( C2U( "D3DSceneLightOn2" ), + PROP_SCENE_LIGHT_ON_2, + ::getBooleanCppuType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT )); + // light source 3 + rOutProperties.push_back( + Property( C2U( "D3DSceneLightColor3" ), + PROP_SCENE_LIGHT_COLOR_3, + ::getCppuType( reinterpret_cast< const sal_Int32 * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT )); + rOutProperties.push_back( + Property( C2U( "D3DSceneLightDirection3" ), + PROP_SCENE_LIGHT_DIRECTION_3, + ::getCppuType( reinterpret_cast< const drawing::Direction3D * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT )); + rOutProperties.push_back( + Property( C2U( "D3DSceneLightOn3" ), + PROP_SCENE_LIGHT_ON_3, + ::getBooleanCppuType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT )); + // light source 4 + rOutProperties.push_back( + Property( C2U( "D3DSceneLightColor4" ), + PROP_SCENE_LIGHT_COLOR_4, + ::getCppuType( reinterpret_cast< const sal_Int32 * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT )); + rOutProperties.push_back( + Property( C2U( "D3DSceneLightDirection4" ), + PROP_SCENE_LIGHT_DIRECTION_4, + ::getCppuType( reinterpret_cast< const drawing::Direction3D * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT )); + rOutProperties.push_back( + Property( C2U( "D3DSceneLightOn4" ), + PROP_SCENE_LIGHT_ON_4, + ::getBooleanCppuType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT )); + // light source 5 + rOutProperties.push_back( + Property( C2U( "D3DSceneLightColor5" ), + PROP_SCENE_LIGHT_COLOR_5, + ::getCppuType( reinterpret_cast< const sal_Int32 * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT )); + rOutProperties.push_back( + Property( C2U( "D3DSceneLightDirection5" ), + PROP_SCENE_LIGHT_DIRECTION_5, + ::getCppuType( reinterpret_cast< const drawing::Direction3D * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT )); + rOutProperties.push_back( + Property( C2U( "D3DSceneLightOn5" ), + PROP_SCENE_LIGHT_ON_5, + ::getBooleanCppuType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT )); + // light source 6 + rOutProperties.push_back( + Property( C2U( "D3DSceneLightColor6" ), + PROP_SCENE_LIGHT_COLOR_6, + ::getCppuType( reinterpret_cast< const sal_Int32 * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT )); + rOutProperties.push_back( + Property( C2U( "D3DSceneLightDirection6" ), + PROP_SCENE_LIGHT_DIRECTION_6, + ::getCppuType( reinterpret_cast< const drawing::Direction3D * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT )); + rOutProperties.push_back( + Property( C2U( "D3DSceneLightOn6" ), + PROP_SCENE_LIGHT_ON_6, + ::getBooleanCppuType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT )); + // light source 7 + rOutProperties.push_back( + Property( C2U( "D3DSceneLightColor7" ), + PROP_SCENE_LIGHT_COLOR_7, + ::getCppuType( reinterpret_cast< const sal_Int32 * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT )); + rOutProperties.push_back( + Property( C2U( "D3DSceneLightDirection7" ), + PROP_SCENE_LIGHT_DIRECTION_7, + ::getCppuType( reinterpret_cast< const drawing::Direction3D * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT )); + rOutProperties.push_back( + Property( C2U( "D3DSceneLightOn7" ), + PROP_SCENE_LIGHT_ON_7, + ::getBooleanCppuType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT )); + // light source 8 + rOutProperties.push_back( + Property( C2U( "D3DSceneLightColor8" ), + PROP_SCENE_LIGHT_COLOR_8, + ::getCppuType( reinterpret_cast< const sal_Int32 * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT )); + rOutProperties.push_back( + Property( C2U( "D3DSceneLightDirection8" ), + PROP_SCENE_LIGHT_DIRECTION_8, + ::getCppuType( reinterpret_cast< const drawing::Direction3D * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT )); + rOutProperties.push_back( + Property( C2U( "D3DSceneLightOn8" ), + PROP_SCENE_LIGHT_ON_8, + ::getBooleanCppuType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT )); +} + +void SceneProperties::AddDefaultsToMap( + ::chart::tPropertyValueMap & rOutMap ) +{ + // Identity Matrix + drawing::HomogenMatrix aMtx; + aMtx.Line1.Column1 = aMtx.Line2.Column2 = + aMtx.Line3.Column3 = aMtx.Line4.Column4 = 1.0; + aMtx.Line1.Column2 = aMtx.Line1.Column3 = aMtx.Line1.Column4 = + aMtx.Line2.Column1 = aMtx.Line2.Column3 = aMtx.Line2.Column4 = + aMtx.Line3.Column1 = aMtx.Line3.Column2 = aMtx.Line3.Column4 = + aMtx.Line4.Column1 = aMtx.Line4.Column2 = aMtx.Line4.Column3 = 0.0; + + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_TRANSF_MATRIX, aMtx ); + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( rOutMap, PROP_SCENE_DISTANCE, 4200 ); + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( rOutMap, PROP_SCENE_FOCAL_LENGTH, 8000 ); + +// PROP_SCENE_SHADOW_SLANT; + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_SHADE_MODE, drawing::ShadeMode_SMOOTH ); + + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( + rOutMap, PROP_SCENE_AMBIENT_COLOR, ChartTypeHelper::getDefaultAmbientLightColor(ThreeDLookScheme_Simple,0)); + + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_TWO_SIDED_LIGHTING, true ); + + drawing::Position3D vrp( 0.0, 0.0, 1.0 ); + drawing::Direction3D vpn( 0.0, 0.0, 1.0 ); + drawing::Direction3D vup( 0.0, 1.0, 0.0 ); + drawing::CameraGeometry aDefaultCameraGeometry( vrp, vpn, vup ); + + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_CAMERA_GEOMETRY, aDefaultCameraGeometry ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_PERSPECTIVE, drawing::ProjectionMode_PERSPECTIVE ); + + // Light Sources + // ------------- + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_LIGHT_ON_1, false ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_LIGHT_ON_2, true ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_LIGHT_ON_3, false ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_LIGHT_ON_4, false ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_LIGHT_ON_5, false ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_LIGHT_ON_6, false ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_LIGHT_ON_7, false ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_LIGHT_ON_8, false ); + + uno::Any aDefaultLightDirection( uno::makeAny( drawing::Direction3D( 0.0, 0.0, 1.0 ) ) ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_LIGHT_DIRECTION_1, aDefaultLightDirection ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_LIGHT_DIRECTION_2, ChartTypeHelper::getDefaultSimpleLightDirection(0)); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_LIGHT_DIRECTION_3, aDefaultLightDirection ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_LIGHT_DIRECTION_4, aDefaultLightDirection ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_LIGHT_DIRECTION_5, aDefaultLightDirection ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_LIGHT_DIRECTION_6, aDefaultLightDirection ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_LIGHT_DIRECTION_7, aDefaultLightDirection ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_LIGHT_DIRECTION_8, aDefaultLightDirection ); + + uno::Any aDefaultLightColor; + aDefaultLightColor <<= ChartTypeHelper::getDefaultDirectLightColor(ThreeDLookScheme_Simple,0); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_LIGHT_COLOR_1, aDefaultLightColor ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_LIGHT_COLOR_2, aDefaultLightColor ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_LIGHT_COLOR_3, aDefaultLightColor ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_LIGHT_COLOR_4, aDefaultLightColor ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_LIGHT_COLOR_5, aDefaultLightColor ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_LIGHT_COLOR_6, aDefaultLightColor ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_LIGHT_COLOR_7, aDefaultLightColor ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_LIGHT_COLOR_8, aDefaultLightColor ); +} + +} // namespace chart diff --git a/chart2/source/tools/StatisticsHelper.cxx b/chart2/source/tools/StatisticsHelper.cxx new file mode 100644 index 000000000000..721451c276da --- /dev/null +++ b/chart2/source/tools/StatisticsHelper.cxx @@ -0,0 +1,403 @@ +/************************************************************************* + * + * 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 "StatisticsHelper.hxx" +#include "DataSeriesHelper.hxx" +#include "ErrorBar.hxx" +#include "macros.hxx" + +#include <rtl/math.hxx> +#include <rtl/ustrbuf.hxx> +#include <comphelper/processfactory.hxx> + +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/chart2/data/XLabeledDataSequence.hpp> +#include <com/sun/star/chart2/data/XNumericalDataSequence.hpp> +#include <com/sun/star/chart2/data/XDataSink.hpp> +#include <com/sun/star/chart/ErrorBarStyle.hpp> + +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::Reference; +using ::rtl::OUString; +using ::rtl::OUStringBuffer; +using namespace ::com::sun::star; + +namespace +{ + +double lcl_getVariance( const Sequence< double > & rData, sal_Int32 & rOutValidCount, + bool bUnbiasedEstimator ) +{ + const sal_Int32 nCount = rData.getLength(); + rOutValidCount = nCount; + + double fSum = 0.0; + double fQuadSum = 0.0; + + for( sal_Int32 i = 0; i < nCount; ++i ) + { + const double fData = rData[i]; + if( ::rtl::math::isNan( fData )) + --rOutValidCount; + else + { + fSum += fData; + fQuadSum += fData * fData; + } + } + + double fResult; + if( rOutValidCount == 0 ) + ::rtl::math::setNan( & fResult ); + else + { + const double fN = static_cast< double >( rOutValidCount ); + if( bUnbiasedEstimator ) + fResult = (fQuadSum - fSum*fSum/fN) / (fN - 1); + else + fResult = (fQuadSum - fSum*fSum/fN) / fN; + } + + return fResult; +} + +Reference< chart2::data::XLabeledDataSequence > lcl_getErrorBarLabeledSequence( + const Reference< chart2::data::XDataSource > & xDataSource, + bool bPositiveValue, bool bYError, + OUString & rOutRoleNameUsed ) +{ + OUStringBuffer aRole( C2U("error-bars-")); + if( bYError ) + aRole.append( sal_Unicode( 'y' )); + else + aRole.append( sal_Unicode( 'x' )); + + OUString aPlainRole = aRole.makeStringAndClear(); + aRole.append( aPlainRole ); + aRole.append( sal_Unicode( '-' )); + + if( bPositiveValue ) + aRole = aRole.appendAscii( "positive" ); + else + aRole = aRole.appendAscii( "negative" ); + + OUString aLongRole = aRole.makeStringAndClear(); + Reference< chart2::data::XLabeledDataSequence > xLSeq( + ::chart::DataSeriesHelper::getDataSequenceByRole( xDataSource, aLongRole )); + // try role without "-negative" or "-positive" postfix + if( xLSeq.is()) + rOutRoleNameUsed = aLongRole; + else + { + xLSeq.set( ::chart::DataSeriesHelper::getDataSequenceByRole( xDataSource, aPlainRole )); + if( xLSeq.is()) + rOutRoleNameUsed = aPlainRole; + else + rOutRoleNameUsed = aLongRole; + } + + return xLSeq; +} + +void lcl_setRole( + const Reference< chart2::data::XDataSequence > & xNewSequence, + const OUString & rRole ) +{ + Reference< beans::XPropertySet > xSeqProp( xNewSequence, uno::UNO_QUERY ); + if( xSeqProp.is()) + xSeqProp->setPropertyValue( C2U("Role"), uno::makeAny( rRole )); +} + +void lcl_addSequenceToDataSource( + const Reference< chart2::data::XDataSource > & xDataSource, + const Reference< chart2::data::XDataSequence > & xNewSequence, + const OUString & rRole ) +{ + Reference< chart2::data::XDataSink > xSink( xDataSource, uno::UNO_QUERY ); + Reference< lang::XMultiServiceFactory > xFact( comphelper::getProcessServiceFactory(), uno::UNO_QUERY_THROW ); + if( ! ( xFact.is() && xSink.is() )) + return; + + Reference< chart2::data::XLabeledDataSequence > xLSeq( + xFact->createInstance( C2U("com.sun.star.chart2.data.LabeledDataSequence")), uno::UNO_QUERY ); + if( xLSeq.is()) + { + lcl_setRole( xNewSequence, rRole ); + xLSeq->setValues( xNewSequence ); + Sequence< Reference< chart2::data::XLabeledDataSequence > > aSequences( + xDataSource->getDataSequences()); + aSequences.realloc( aSequences.getLength() + 1 ); + aSequences[ aSequences.getLength() - 1 ] = xLSeq; + xSink->setData( aSequences ); + } +} + +void lcl_setXMLRangePropertyAtDataSequence( + const Reference< chart2::data::XDataSequence > & xDataSequence, + const OUString & rXMLRange ) +{ + try + { + const OUString aXMLRangePropName( C2U( "CachedXMLRange" )); + Reference< beans::XPropertySet > xProp( xDataSequence, uno::UNO_QUERY_THROW ); + Reference< beans::XPropertySetInfo > xInfo( xProp->getPropertySetInfo()); + if( xInfo.is() && xInfo->hasPropertyByName( aXMLRangePropName )) + xProp->setPropertyValue( aXMLRangePropName, uno::makeAny( rXMLRange )); + } + catch( const uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } +} + +} // anonymous namespace + +namespace chart +{ + +// static +double StatisticsHelper::getVariance( + const Sequence< double > & rData, + bool bUnbiasedEstimator /* = false */ ) +{ + sal_Int32 nValCount; + return lcl_getVariance( rData, nValCount, bUnbiasedEstimator ); +} + +// static +double StatisticsHelper::getStandardDeviation( const Sequence< double > & rData ) +{ + double fResult = getVariance( rData ); + if( ! ::rtl::math::isNan( fResult )) + fResult = sqrt( fResult ); + + return fResult; +} + +// static +double StatisticsHelper::getStandardError( const Sequence< double > & rData ) +{ + sal_Int32 nValCount; + double fVar = lcl_getVariance( rData, nValCount, false ); + double fResult; + + if( nValCount == 0 || + ::rtl::math::isNan( fVar )) + { + ::rtl::math::setNan( & fResult ); + } + else + { + // standard-deviation / sqrt(n) + fResult = sqrt( fVar ) / sqrt( double(nValCount) ); + } + + return fResult; +} + +// static +Reference< chart2::data::XLabeledDataSequence > StatisticsHelper::getErrorLabeledDataSequenceFromDataSource( + const Reference< chart2::data::XDataSource > & xDataSource, + bool bPositiveValue, + bool bYError /* = true */ ) +{ + Reference< chart2::data::XLabeledDataSequence > xResult; + if( !xDataSource.is()) + return xResult; + + OUString aRole; + Reference< chart2::data::XLabeledDataSequence > xLSeq( + lcl_getErrorBarLabeledSequence( xDataSource, bPositiveValue, bYError, aRole )); + if( xLSeq.is()) + xResult.set( xLSeq ); + + return xResult; +} + +// static +Reference< chart2::data::XDataSequence > StatisticsHelper::getErrorDataSequenceFromDataSource( + const Reference< chart2::data::XDataSource > & xDataSource, + bool bPositiveValue, + bool bYError /* = true */ ) +{ + Reference< chart2::data::XLabeledDataSequence > xLSeq( + StatisticsHelper::getErrorLabeledDataSequenceFromDataSource( + xDataSource, bPositiveValue, + bYError )); + if( !xLSeq.is()) + return Reference< chart2::data::XDataSequence >(); + + return xLSeq->getValues(); +} + +// static +double StatisticsHelper::getErrorFromDataSource( + const Reference< chart2::data::XDataSource > & xDataSource, + sal_Int32 nIndex, + bool bPositiveValue, + bool bYError /* = true */ ) +{ + double fResult = 0.0; + ::rtl::math::setNan( & fResult ); + + Reference< chart2::data::XDataSequence > xValues( + StatisticsHelper::getErrorDataSequenceFromDataSource( xDataSource, bPositiveValue, bYError )); + + Reference< chart2::data::XNumericalDataSequence > xNumValues( xValues, uno::UNO_QUERY ); + if( xNumValues.is()) + { + Sequence< double > aData( xNumValues->getNumericalData()); + if( nIndex < aData.getLength()) + fResult = aData[nIndex]; + } + else if( xValues.is()) + { + Sequence< uno::Any > aData( xValues->getData()); + if( nIndex < aData.getLength()) + aData[nIndex] >>= fResult; + } + + return fResult; +} + +// static +void StatisticsHelper::setErrorDataSequence( + const Reference< chart2::data::XDataSource > & xDataSource, + const Reference< chart2::data::XDataProvider > & xDataProvider, + const OUString & rNewRange, + bool bPositiveValue, + bool bYError /* = true */, + OUString * pXMLRange /* = 0 */ ) +{ + Reference< chart2::data::XDataSink > xDataSink( xDataSource, uno::UNO_QUERY ); + if( ! ( xDataSink.is() && xDataProvider.is())) + return; + + OUString aRole; + Reference< chart2::data::XLabeledDataSequence > xLSeq( + lcl_getErrorBarLabeledSequence( xDataSource, bPositiveValue, bYError, aRole )); + Reference< chart2::data::XDataSequence > xNewSequence( + xDataProvider->createDataSequenceByRangeRepresentation( rNewRange )); + if( xNewSequence.is()) + { + if( pXMLRange ) + lcl_setXMLRangePropertyAtDataSequence( xNewSequence, *pXMLRange ); + if( xLSeq.is()) + { + lcl_setRole( xNewSequence, aRole ); + xLSeq->setValues( xNewSequence ); + } + else + lcl_addSequenceToDataSource( xDataSource, xNewSequence, aRole ); + } +} + +// static +Reference< beans::XPropertySet > StatisticsHelper::addErrorBars( + const Reference< chart2::XDataSeries > & xDataSeries, + const Reference< uno::XComponentContext > & xContext, + sal_Int32 nStyle, + bool bYError /* = true */ ) +{ + Reference< beans::XPropertySet > xErrorBar; + Reference< beans::XPropertySet > xSeriesProp( xDataSeries, uno::UNO_QUERY ); + if( !xSeriesProp.is()) + return xErrorBar; + + const OUString aPropName( bYError ? C2U("ErrorBarY") : C2U("ErrorBarX")); + if( !( xSeriesProp->getPropertyValue( aPropName ) >>= xErrorBar ) || + !xErrorBar.is()) + { + xErrorBar.set( createErrorBar( xContext )); + } + + OSL_ASSERT( xErrorBar.is()); + if( xErrorBar.is()) + { + xErrorBar->setPropertyValue( C2U("ErrorBarStyle"), uno::makeAny( nStyle )); + } + + xSeriesProp->setPropertyValue( aPropName, uno::makeAny( xErrorBar )); + + return xErrorBar; +} + +// static +Reference< beans::XPropertySet > StatisticsHelper::getErrorBars( + const Reference< chart2::XDataSeries > & xDataSeries, + bool bYError /* = true */ ) +{ + Reference< beans::XPropertySet > xSeriesProp( xDataSeries, uno::UNO_QUERY ); + Reference< beans::XPropertySet > xErrorBar; + const OUString aPropName( bYError ? C2U("ErrorBarY") : C2U("ErrorBarX")); + + if ( xSeriesProp.is()) + xSeriesProp->getPropertyValue( aPropName ) >>= xErrorBar; + + return xErrorBar; +} + +// static +bool StatisticsHelper::hasErrorBars( + const Reference< chart2::XDataSeries > & xDataSeries, + bool bYError /* = true */ ) +{ + Reference< beans::XPropertySet > xErrorBar( getErrorBars( xDataSeries, bYError )); + sal_Int32 nStyle = ::com::sun::star::chart::ErrorBarStyle::NONE; + + return ( xErrorBar.is() && + ( xErrorBar->getPropertyValue( C2U("ErrorBarStyle")) >>= nStyle ) && + nStyle != ::com::sun::star::chart::ErrorBarStyle::NONE ); +} + +// static +void StatisticsHelper::removeErrorBars( + const Reference< chart2::XDataSeries > & xDataSeries, + bool bYError /* = true */ ) +{ + Reference< beans::XPropertySet > xErrorBar( getErrorBars( xDataSeries, bYError )); + if ( xErrorBar.is()) + xErrorBar->setPropertyValue( C2U("ErrorBarStyle"), uno::makeAny( + ::com::sun::star::chart::ErrorBarStyle::NONE )); +} + +// static +bool StatisticsHelper::usesErrorBarRanges( + const Reference< chart2::XDataSeries > & xDataSeries, + bool bYError /* = true */ ) +{ + Reference< beans::XPropertySet > xErrorBar( getErrorBars( xDataSeries, bYError )); + sal_Int32 nStyle = ::com::sun::star::chart::ErrorBarStyle::NONE; + + return ( xErrorBar.is() && + ( xErrorBar->getPropertyValue( C2U("ErrorBarStyle")) >>= nStyle ) && + nStyle == ::com::sun::star::chart::ErrorBarStyle::FROM_DATA ); +} + +} // namespace chart diff --git a/chart2/source/tools/ThreeDHelper.cxx b/chart2/source/tools/ThreeDHelper.cxx new file mode 100644 index 000000000000..44ed73eade43 --- /dev/null +++ b/chart2/source/tools/ThreeDHelper.cxx @@ -0,0 +1,1527 @@ +/************************************************************************* + * + * 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 "ThreeDHelper.hxx" +#include "macros.hxx" +#include "DiagramHelper.hxx" +#include "ChartTypeHelper.hxx" +#include "BaseGFXHelper.hxx" +#include "DataSeriesHelper.hxx" +#include <editeng/unoprnms.hxx> +#include <com/sun/star/beans/XPropertyState.hpp> +#include <com/sun/star/chart2/XDiagram.hpp> +#include <com/sun/star/drawing/LineStyle.hpp> + +#include <tools/debug.hxx> + +//............................................................................. +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; +using ::rtl::OUString; +using ::rtl::math::cos; +using ::rtl::math::sin; +using ::rtl::math::tan; + +#define FIXED_SIZE_FOR_3D_CHART_VOLUME (10000.0) + +namespace +{ + +bool lcl_isRightAngledAxesSetAndSupported( const Reference< beans::XPropertySet >& xSceneProperties ) +{ + sal_Bool bRightAngledAxes = sal_False; + if( xSceneProperties.is() ) + { + xSceneProperties->getPropertyValue( C2U("RightAngledAxes")) >>= bRightAngledAxes; + if(bRightAngledAxes) + { + uno::Reference< chart2::XDiagram > xDiagram( xSceneProperties, uno::UNO_QUERY ); + if( ChartTypeHelper::isSupportingRightAngledAxes( + DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) ) ) + { + return true; + } + } + } + return false; +} + +void lcl_RotateLightSource( const Reference< beans::XPropertySet >& xSceneProperties + , const OUString& rLightSourceDirection + , const OUString& rLightSourceOn + , const ::basegfx::B3DHomMatrix& rRotationMatrix ) +{ + if( xSceneProperties.is() ) + { + sal_Bool bLightOn = sal_False; + if( xSceneProperties->getPropertyValue( rLightSourceOn ) >>= bLightOn ) + { + if( bLightOn ) + { + drawing::Direction3D aLight; + if( xSceneProperties->getPropertyValue( rLightSourceDirection ) >>= aLight ) + { + ::basegfx::B3DVector aLightVector( BaseGFXHelper::Direction3DToB3DVector( aLight ) ); + aLightVector = rRotationMatrix*aLightVector; + + xSceneProperties->setPropertyValue( rLightSourceDirection + , uno::makeAny( BaseGFXHelper::B3DVectorToDirection3D( aLightVector ) ) ); + } + } + } + } +} + +void lcl_rotateLights( const ::basegfx::B3DHomMatrix& rLightRottion, const Reference< beans::XPropertySet >& xSceneProperties ) +{ + if(!xSceneProperties.is()) + return; + + ::basegfx::B3DHomMatrix aLightRottion( rLightRottion ); + BaseGFXHelper::ReduceToRotationMatrix( aLightRottion ); + + lcl_RotateLightSource( xSceneProperties, C2U("D3DSceneLightDirection1"), C2U("D3DSceneLightOn1"), aLightRottion ); + lcl_RotateLightSource( xSceneProperties, C2U("D3DSceneLightDirection2"), C2U("D3DSceneLightOn2"), aLightRottion ); + lcl_RotateLightSource( xSceneProperties, C2U("D3DSceneLightDirection3"), C2U("D3DSceneLightOn3"), aLightRottion ); + lcl_RotateLightSource( xSceneProperties, C2U("D3DSceneLightDirection4"), C2U("D3DSceneLightOn4"), aLightRottion ); + lcl_RotateLightSource( xSceneProperties, C2U("D3DSceneLightDirection5"), C2U("D3DSceneLightOn5"), aLightRottion ); + lcl_RotateLightSource( xSceneProperties, C2U("D3DSceneLightDirection6"), C2U("D3DSceneLightOn6"), aLightRottion ); + lcl_RotateLightSource( xSceneProperties, C2U("D3DSceneLightDirection7"), C2U("D3DSceneLightOn7"), aLightRottion ); + lcl_RotateLightSource( xSceneProperties, C2U("D3DSceneLightDirection8"), C2U("D3DSceneLightOn8"), aLightRottion ); +} + +::basegfx::B3DHomMatrix lcl_getInverseRotationMatrix( const Reference< beans::XPropertySet >& xSceneProperties ) +{ + ::basegfx::B3DHomMatrix aInverseRotation; + double fXAngleRad=0.0; + double fYAngleRad=0.0; + double fZAngleRad=0.0; + ThreeDHelper::getRotationAngleFromDiagram( + xSceneProperties, fXAngleRad, fYAngleRad, fZAngleRad ); + aInverseRotation.rotate( 0.0, 0.0, -fZAngleRad ); + aInverseRotation.rotate( 0.0, -fYAngleRad, 0.0 ); + aInverseRotation.rotate( -fXAngleRad, 0.0, 0.0 ); + return aInverseRotation; +} + +::basegfx::B3DHomMatrix lcl_getCompleteRotationMatrix( const Reference< beans::XPropertySet >& xSceneProperties ) +{ + ::basegfx::B3DHomMatrix aCompleteRotation; + double fXAngleRad=0.0; + double fYAngleRad=0.0; + double fZAngleRad=0.0; + ThreeDHelper::getRotationAngleFromDiagram( + xSceneProperties, fXAngleRad, fYAngleRad, fZAngleRad ); + aCompleteRotation.rotate( fXAngleRad, fYAngleRad, fZAngleRad ); + return aCompleteRotation; +} + +bool lcl_isEqual( const drawing::Direction3D& rA, const drawing::Direction3D& rB ) +{ + return ::rtl::math::approxEqual(rA.DirectionX, rB.DirectionX) + && ::rtl::math::approxEqual(rA.DirectionY, rB.DirectionY) + && ::rtl::math::approxEqual(rA.DirectionZ, rB.DirectionZ); +} + +bool lcl_isLightScheme( const uno::Reference< beans::XPropertySet >& xDiagramProps, bool bRealistic ) +{ + if(!xDiagramProps.is()) + return false; + + sal_Bool bIsOn = sal_False; + xDiagramProps->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_2 ) ) >>= bIsOn; + if(!bIsOn) + return false; + + uno::Reference< chart2::XDiagram > xDiagram( xDiagramProps, uno::UNO_QUERY ); + uno::Reference< chart2::XChartType > xChartType( DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) ); + + sal_Int32 nColor = 0; + xDiagramProps->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_2 ) ) >>= nColor; + if( nColor != ::chart::ChartTypeHelper::getDefaultDirectLightColor( !bRealistic, xChartType ) ) + return false; + + sal_Int32 nAmbientColor = 0; + xDiagramProps->getPropertyValue( C2U( UNO_NAME_3D_SCENE_AMBIENTCOLOR ) ) >>= nAmbientColor; + if( nAmbientColor != ::chart::ChartTypeHelper::getDefaultAmbientLightColor( !bRealistic, xChartType ) ) + return false; + + drawing::Direction3D aDirection(0,0,0); + xDiagramProps->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_2 ) ) >>= aDirection; + + drawing::Direction3D aDefaultDirection( bRealistic + ? ChartTypeHelper::getDefaultRealisticLightDirection(xChartType) + : ChartTypeHelper::getDefaultSimpleLightDirection(xChartType) ); + + //rotate default light direction when right angled axes are off but supported + { + sal_Bool bRightAngledAxes = sal_False; + xDiagramProps->getPropertyValue( C2U("RightAngledAxes")) >>= bRightAngledAxes; + if(!bRightAngledAxes) + { + if( ChartTypeHelper::isSupportingRightAngledAxes( + DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) ) ) + { + ::basegfx::B3DHomMatrix aRotation( lcl_getCompleteRotationMatrix( xDiagramProps ) ); + BaseGFXHelper::ReduceToRotationMatrix( aRotation ); + ::basegfx::B3DVector aLightVector( BaseGFXHelper::Direction3DToB3DVector( aDefaultDirection ) ); + aLightVector = aRotation*aLightVector; + aDefaultDirection = BaseGFXHelper::B3DVectorToDirection3D( aLightVector ); + } + } + } + + return lcl_isEqual( aDirection, aDefaultDirection ); +} + +bool lcl_isRealisticLightScheme( const uno::Reference< beans::XPropertySet >& xDiagramProps ) +{ + return lcl_isLightScheme( xDiagramProps, true /*bRealistic*/ ); +} +bool lcl_isSimpleLightScheme( const uno::Reference< beans::XPropertySet >& xDiagramProps ) +{ + return lcl_isLightScheme( xDiagramProps, false /*bRealistic*/ ); +} +void lcl_setLightsForScheme( const uno::Reference< beans::XPropertySet >& xDiagramProps, const ThreeDLookScheme& rScheme ) +{ + if(!xDiagramProps.is()) + return; + if( rScheme == ThreeDLookScheme_Unknown) + return; + + xDiagramProps->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_2 ), uno::makeAny( sal_True ) ); + + uno::Reference< chart2::XDiagram > xDiagram( xDiagramProps, uno::UNO_QUERY ); + uno::Reference< chart2::XChartType > xChartType( DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) ); + uno::Any aADirection( uno::makeAny( rScheme == ThreeDLookScheme_Simple + ? ChartTypeHelper::getDefaultSimpleLightDirection(xChartType) + : ChartTypeHelper::getDefaultRealisticLightDirection(xChartType) ) ); + + xDiagramProps->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_2 ), aADirection ); + //rotate light direction when right angled axes are off but supported + { + sal_Bool bRightAngledAxes = sal_False; + xDiagramProps->getPropertyValue( C2U("RightAngledAxes")) >>= bRightAngledAxes; + if(!bRightAngledAxes) + { + if( ChartTypeHelper::isSupportingRightAngledAxes( xChartType ) ) + { + ::basegfx::B3DHomMatrix aRotation( lcl_getCompleteRotationMatrix( xDiagramProps ) ); + BaseGFXHelper::ReduceToRotationMatrix( aRotation ); + lcl_RotateLightSource( xDiagramProps, C2U("D3DSceneLightDirection2"), C2U("D3DSceneLightOn2"), aRotation ); + } + } + } + + sal_Int32 nColor = ::chart::ChartTypeHelper::getDefaultDirectLightColor( rScheme==ThreeDLookScheme_Simple, xChartType ); + xDiagramProps->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_2 ), uno::makeAny( nColor ) ); + + sal_Int32 nAmbientColor = ::chart::ChartTypeHelper::getDefaultAmbientLightColor( rScheme==ThreeDLookScheme_Simple, xChartType ); + xDiagramProps->setPropertyValue( C2U( UNO_NAME_3D_SCENE_AMBIENTCOLOR ), uno::makeAny( nAmbientColor ) ); +} + +bool lcl_isRealisticScheme( drawing::ShadeMode aShadeMode + , sal_Int32 nRoundedEdges + , sal_Int32 nObjectLines ) +{ + if(aShadeMode!=drawing::ShadeMode_SMOOTH) + return false; + if(nRoundedEdges!=5) + return false; + if(nObjectLines!=0) + return false; + return true; +} + +bool lcl_isSimpleScheme( drawing::ShadeMode aShadeMode + , sal_Int32 nRoundedEdges + , sal_Int32 nObjectLines + , const uno::Reference< XDiagram >& xDiagram ) +{ + if(aShadeMode!=drawing::ShadeMode_FLAT) + return false; + if(nRoundedEdges!=0) + return false; + if(nObjectLines==0) + { + uno::Reference< chart2::XChartType > xChartType( DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) ); + return ChartTypeHelper::noBordersForSimpleScheme( xChartType ); + } + if(nObjectLines!=1) + return false; + return true; +} + +void lcl_setRealisticScheme( drawing::ShadeMode& rShadeMode + , sal_Int32& rnRoundedEdges + , sal_Int32& rnObjectLines ) +{ + rShadeMode = drawing::ShadeMode_SMOOTH; + rnRoundedEdges = 5; + rnObjectLines = 0; +} + +void lcl_setSimpleScheme( drawing::ShadeMode& rShadeMode + , sal_Int32& rnRoundedEdges + , sal_Int32& rnObjectLines + , const uno::Reference< XDiagram >& xDiagram ) +{ + rShadeMode = drawing::ShadeMode_FLAT; + rnRoundedEdges = 0; + + uno::Reference< chart2::XChartType > xChartType( DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) ); + rnObjectLines = ChartTypeHelper::noBordersForSimpleScheme( xChartType ) ? 0 : 1; +} + +} //end anonymous namespace + + +drawing::CameraGeometry ThreeDHelper::getDefaultCameraGeometry( bool bPie ) +{ + // ViewReferencePoint (Point on the View plane) + drawing::Position3D vrp(17634.6218373783, 10271.4823817647, 24594.8639082739); + // ViewPlaneNormal (Normal to the View Plane) + drawing::Direction3D vpn(0.416199821709347, 0.173649045905254, 0.892537795986984); + // ViewUpVector (determines the v-axis direction on the view plane as + // projection of VUP parallel to VPN onto th view pane) + drawing::Direction3D vup(-0.0733876362771618, 0.984807599917971, -0.157379306090273); + + if( bPie ) + { + vrp = drawing::Position3D( 0.0, 0.0, 87591.2408759124 );//--> 5 percent perspecitve + vpn = drawing::Direction3D( 0.0, 0.0, 1.0 ); + vup = drawing::Direction3D( 0.0, 1.0, 0.0 ); + } + + return drawing::CameraGeometry( vrp, vpn, vup ); +} + +namespace +{ +::basegfx::B3DHomMatrix lcl_getCameraMatrix( const uno::Reference< beans::XPropertySet >& xSceneProperties ) +{ + drawing::HomogenMatrix aCameraMatrix; + + drawing::CameraGeometry aCG( ThreeDHelper::getDefaultCameraGeometry() ); + if( xSceneProperties.is() ) + xSceneProperties->getPropertyValue( C2U( "D3DCameraGeometry" ) ) >>= aCG; + + ::basegfx::B3DVector aVPN( BaseGFXHelper::Direction3DToB3DVector( aCG.vpn ) ); + ::basegfx::B3DVector aVUP( BaseGFXHelper::Direction3DToB3DVector( aCG.vup ) ); + + //normalize vectors: + aVPN.normalize(); + aVUP.normalize(); + + ::basegfx::B3DVector aCross = ::basegfx::cross( aVUP, aVPN ); + + //first line is VUP x VPN + aCameraMatrix.Line1.Column1 = aCross[0]; + aCameraMatrix.Line1.Column2 = aCross[1]; + aCameraMatrix.Line1.Column3 = aCross[2]; + aCameraMatrix.Line1.Column4 = 0.0; + + //second line is VUP + aCameraMatrix.Line2.Column1 = aVUP[0]; + aCameraMatrix.Line2.Column2 = aVUP[1]; + aCameraMatrix.Line2.Column3 = aVUP[2]; + aCameraMatrix.Line2.Column4 = 0.0; + + //third line is VPN + aCameraMatrix.Line3.Column1 = aVPN[0]; + aCameraMatrix.Line3.Column2 = aVPN[1]; + aCameraMatrix.Line3.Column3 = aVPN[2]; + aCameraMatrix.Line3.Column4 = 0.0; + + //fourth line is 0 0 0 1 + aCameraMatrix.Line4.Column1 = 0.0; + aCameraMatrix.Line4.Column2 = 0.0; + aCameraMatrix.Line4.Column3 = 0.0; + aCameraMatrix.Line4.Column4 = 1.0; + + return BaseGFXHelper::HomogenMatrixToB3DHomMatrix( aCameraMatrix ); +} + +double lcl_shiftAngleToIntervalMinusPiToPi( double fAngleRad ) +{ + //valid range: ]-Pi,Pi] + while( fAngleRad<=-F_PI ) + fAngleRad+=(2*F_PI); + while( fAngleRad>F_PI ) + fAngleRad-=(2*F_PI); + return fAngleRad; +} + +void lcl_shiftAngleToIntervalMinus180To180( sal_Int32& rnAngleDegree ) +{ + //valid range: ]-180,180] + while( rnAngleDegree<=-180 ) + rnAngleDegree+=360; + while( rnAngleDegree>180 ) + rnAngleDegree-=360; +} + +void lcl_shiftAngleToIntervalZeroTo360( sal_Int32& rnAngleDegree ) +{ + //valid range: [0,360[ + while( rnAngleDegree<0 ) + rnAngleDegree+=360; + while( rnAngleDegree>=360 ) + rnAngleDegree-=360; +} + +void lcl_ensureIntervalMinus1To1( double& rSinOrCos ) +{ + if (rSinOrCos < -1.0) + rSinOrCos = -1.0; + else if (rSinOrCos > 1.0) + rSinOrCos = 1.0; +} + +bool lcl_isSinZero( double fAngleRad ) +{ + return ::basegfx::fTools::equalZero( sin(fAngleRad), 0.0000001 ); +} +bool lcl_isCosZero( double fAngleRad ) +{ + return ::basegfx::fTools::equalZero( cos(fAngleRad), 0.0000001 ); +} + +} + +void ThreeDHelper::convertElevationRotationDegToXYZAngleRad( + sal_Int32 nElevationDeg, sal_Int32 nRotationDeg, + double& rfXAngleRad, double& rfYAngleRad, double& rfZAngleRad) +{ + // for a description of the algorithm see issue 72994 + //http://www.openoffice.org/issues/show_bug.cgi?id=72994 + //http://www.openoffice.org/nonav/issues/showattachment.cgi/50608/DescriptionCorrected.odt + + lcl_shiftAngleToIntervalZeroTo360( nElevationDeg ); + lcl_shiftAngleToIntervalZeroTo360( nRotationDeg ); + + double& x = rfXAngleRad; + double& y = rfYAngleRad; + double& z = rfZAngleRad; + + double E = F_PI*nElevationDeg/180; //elevation in Rad + double R = F_PI*nRotationDeg/180; //rotation in Rad + + if( (nRotationDeg == 0 || nRotationDeg == 180 ) + && ( nElevationDeg == 90 || nElevationDeg == 270 ) ) + { + //sR==0 && cE==0 + z = 0.0; + //element 23 + double f23 = cos(R)*sin(E); + if(f23>0) + x = F_PI/2; + else + x = -F_PI/2; + y = R; + } + else if( ( nRotationDeg == 90 || nRotationDeg == 270 ) + && ( nElevationDeg == 90 || nElevationDeg == 270 ) ) + { + //cR==0 && cE==0 + z = F_PI/2; + if( sin(R)>0 ) + x = F_PI/2.0; + else + x = -F_PI/2.0; + + if( (sin(R)*sin(E))>0 ) + y = 0.0; + else + y = F_PI; + } + else if( (nRotationDeg == 0 || nRotationDeg == 180 ) + && ( nElevationDeg == 0 || nElevationDeg == 180 ) ) + { + //sR==0 && sE==0 + z = 0.0; + y = R; + x = E; + } + else if( ( nRotationDeg == 90 || nRotationDeg == 270 ) + && ( nElevationDeg == 0 || nElevationDeg == 180 ) ) + { + //cR==0 && sE==0 + z = 0.0; + + if( (sin(R)/cos(E))>0 ) + y = F_PI/2; + else + y = -F_PI/2; + + if( (cos(E))>0 ) + x = 0; + else + x = F_PI; + } + else if ( nElevationDeg == 0 || nElevationDeg == 180 ) + { + //sR!=0 cR!=0 sE==0 + z = 0.0; + x = E; + y = R; + //use element 13 for sign + if((cos(x)*sin(y)*sin(R))<0.0) + y *= -1.0; + } + else if ( nElevationDeg == 90 || nElevationDeg == 270 ) + { + //sR!=0 cR!=0 cE==0 + //element 12 + 22 --> y=0 or F_PI and x=+-F_PI/2 + //-->element 13/23: + z = atan(sin(R)/(cos(R)*sin(E))); + //use element 13 for sign for x + if( (sin(R)*sin(z))>0.0 ) + x = F_PI/2; + else + x = -F_PI/2; + //use element 21 for y + if( (sin(R)*sin(E)*sin(z))>0.0) + y = 0.0; + else + y = F_PI; + } + else if ( nRotationDeg == 0 || nRotationDeg == 180 ) + { + //sE!=0 cE!=0 sR==0 + z = 0.0; + x = E; + y = R; + double f23 = cos(R)*sin(E); + if( (f23 * sin(x)) < 0.0 ) + x *= -1.0; //todo ?? + } + else if (nRotationDeg == 90 || nRotationDeg == 270) + { + //sE!=0 cE!=0 cR==0 + //z = +- F_PI/2; + //x = +- F_PI/2; + z = F_PI/2; + x = F_PI/2; + double sR = sin(R); + if( sR<0.0 ) + x *= -1.0; //different signs for x and z + + //use element 21: + double cy = sR*sin(E)/sin(z); + lcl_ensureIntervalMinus1To1(cy); + y = acos(cy); + + //use element 22 for sign: + if( (sin(x)*sin(y)*sin(z)*cos(E))<0.0) + y *= -1.0; + } + else + { + z = atan(tan(R) * sin(E)); + if(cos(z)==0.0) + { + DBG_ERROR("calculation error in ThreeDHelper::convertElevationRotationDegToXYZAngleRad"); + return; + } + double cy = cos(R)/cos(z); + lcl_ensureIntervalMinus1To1(cy); + y = acos(cy); + + //element 12 in 23 + double fDenominator = cos(z)*(1.0-pow(sin(y),2)); + if(fDenominator==0.0) + { + DBG_ERROR("calculation error in ThreeDHelper::convertElevationRotationDegToXYZAngleRad"); + return; + } + double sx = cos(R)*sin(E)/fDenominator; + lcl_ensureIntervalMinus1To1(sx); + x = asin( sx ); + + //use element 13 for sign: + double f13a = cos(x)*cos(z)*sin(y); + double f13b = sin(R)-sx*sin(z); + if( (f13b*f13a)<0.0 ) + { + //change x or y + //use element 22 for further investigations: + //try + y *= -1; + double f22a = cos(x)*cos(z); + double f22b = cos(E)-(sx*sin(y)*sin(z)); + if( (f22a*f22b)<0.0 ) + { + y *= -1; + x=(F_PI-x); + } + } + else + { + //change nothing or both + //use element 22 for further investigations: + double f22a = cos(x)*cos(z); + double f22b = cos(E)-(sx*sin(y)*sin(z)); + if( (f22a*f22b)<0.0 ) + { + y *= -1; + x=(F_PI-x); + } + } + } +} + +void ThreeDHelper::convertXYZAngleRadToElevationRotationDeg( + sal_Int32& rnElevationDeg, sal_Int32& rnRotationDeg, + double fXRad, double fYRad, double fZRad) +{ + // for a description of the algorithm see issue 72994 + //http://www.openoffice.org/issues/show_bug.cgi?id=72994 + //http://www.openoffice.org/nonav/issues/showattachment.cgi/50608/DescriptionCorrected.odt + + double R = 0.0; //Rotation in Rad + double E = 0.0; //Elevation in Rad + + double& x = fXRad; + double& y = fYRad; + double& z = fZRad; + + double f11 = cos(y)*cos(z); + + if( lcl_isSinZero(y) ) + { + //siny == 0 + + if( lcl_isCosZero(x) ) + { + //siny == 0 && cosx == 0 + + if( lcl_isSinZero(z) ) + { + //siny == 0 && cosx == 0 && sinz == 0 + //example: x=+-90 y=0oder180 z=0(oder180) + + //element 13+11 + if( f11 > 0 ) + R = 0.0; + else + R = F_PI; + + //element 23 + double f23 = cos(z)*sin(x) / cos(R); + if( f23 > 0 ) + E = F_PI/2.0; + else + E = -F_PI/2.0; + } + else if( lcl_isCosZero(z) ) + { + //siny == 0 && cosx == 0 && cosz == 0 + //example: x=+-90 y=0oder180 z=+-90 + + double f13 = sin(x)*sin(z); + //element 13+11 + if( f13 > 0 ) + R = F_PI/2.0; + else + R = -F_PI/2.0; + + //element 21 + double f21 = cos(y)*sin(z) / sin(R); + if( f21 > 0 ) + E = F_PI/2.0; + else + E = -F_PI/2.0; + } + else + { + //siny == 0 && cosx == 0 && cosz != 0 && sinz != 0 + //element 11 && 13 + double f13 = sin(x)*sin(z); + R = atan( f13/f11 ); + + if(f11<0) + R+=F_PI; + + //element 23 + double f23 = cos(z)*sin(x); + if( f23/cos(R) > 0 ) + E = F_PI/2.0; + else + E = -F_PI/2.0; + } + } + else if( lcl_isSinZero(x) ) + { + //sinY==0 sinX==0 + //element 13+11 + if( f11 > 0 ) + R = 0.0; + else + R = F_PI; + + double f22 = cos(x)*cos(z); + if( f22 > 0 ) + E = 0.0; + else + E = F_PI; + } + else if( lcl_isSinZero(z) ) + { + //sinY==0 sinZ==0 sinx!=0 cosx!=0 + //element 13+11 + if( f11 > 0 ) + R = 0.0; + else + R = F_PI; + + //element 22 && 23 + double f22 = cos(x)*cos(z); + double f23 = cos(z)*sin(x); + E = atan( f23/(f22*cos(R)) ); + if( (f22*cos(E))<0 ) + E+=F_PI; + } + else if( lcl_isCosZero(z) ) + { + //sinY == 0 && cosZ == 0 && cosx != 0 && sinx != 0 + double f13 = sin(x)*sin(z); + //element 13+11 + if( f13 > 0 ) + R = F_PI/2.0; + else + R = -F_PI/2.0; + + //element 21+22 + double f21 = cos(y)*sin(z); + if( f21/sin(R) > 0 ) + E = F_PI/2.0; + else + E = -F_PI/2.0; + } + else + { + //sinY == 0 && all other !=0 + double f13 = sin(x)*sin(z); + R = atan( f13/f11 ); + if( (f11*cos(R))<0.0 ) + R+=F_PI; + + double f22 = cos(x)*cos(z); + if( !lcl_isCosZero(R) ) + E = atan( cos(z)*sin(x) /( f22*cos(R) ) ); + else + E = atan( cos(y)*sin(z) /( f22*sin(R) ) ); + if( (f22*cos(E))<0 ) + E+=F_PI; + } + } + else if( lcl_isCosZero(y) ) + { + //cosY==0 + + double f13 = sin(x)*sin(z)+cos(x)*cos(z)*sin(y); + if( f13 >= 0 ) + R = F_PI/2.0; + else + R = -F_PI/2.0; + + double f22 = cos(x)*cos(z)+sin(x)*sin(y)*sin(z); + if( f22 >= 0 ) + E = 0.0; + else + E = F_PI; + } + else if( lcl_isSinZero(x) ) + { + //cosY!=0 sinY!=0 sinX=0 + if( lcl_isSinZero(z) ) + { + //cosY!=0 sinY!=0 sinX=0 sinZ=0 + double f13 = cos(x)*cos(z)*sin(y); + R = atan( f13/f11 ); + //R = asin(f13); + if( f11<0 ) + R+=F_PI; + + double f22 = cos(x)*cos(z); + if( f22>0 ) + E = 0.0; + else + E = F_PI; + } + else if( lcl_isCosZero(z) ) + { + //cosY!=0 sinY!=0 sinX=0 cosZ=0 + R = x; + E = y;//or -y + //use 23 for 'signs' + double f23 = -1.0*cos(x)*sin(y)*sin(z); + if( (f23*cos(R)*sin(E))<0.0 ) + { + //change R or E + E = -y; + } + } + else + { + //cosY!=0 sinY!=0 sinX=0 sinZ!=0 cosZ!=0 + double f13 = cos(x)*cos(z)*sin(y); + R = atan( f13/f11 ); + + if( f11<0 ) + R+=F_PI; + + double f21 = cos(y)*sin(z); + double f22 = cos(x)*cos(z); + E = atan(f21/(f22*sin(R)) ); + + if( (f22*cos(E))<0.0 ) + E+=F_PI; + } + } + else if( lcl_isCosZero(x) ) + { + //cosY!=0 sinY!=0 cosX=0 + + if( lcl_isSinZero(z) ) + { + //cosY!=0 sinY!=0 cosX=0 sinZ=0 + R=0;//13 -> R=0 or F_PI + if( f11<0.0 ) + R=F_PI; + E=F_PI/2;//22 -> E=+-F_PI/2 + //use element 11 and 23 for sign + double f23 = cos(z)*sin(x); + if( (f11*f23*sin(E))<0.0 ) + E=-F_PI/2.0; + } + else if( lcl_isCosZero(z) ) + { + //cosY!=0 sinY!=0 cosX=0 cosZ=0 + //element 11 & 13: + if( (sin(x)*sin(z))>0.0 ) + R=F_PI/2.0; + else + R=-F_PI/2.0; + //element 22: + E=acos( sin(x)*sin(y)*sin(z)); + //use element 21 for sign: + if( (cos(y)*sin(z)*sin(R)*sin(E))<0.0 ) + E*=-1.0; + } + else + { + //cosY!=0 sinY!=0 cosX=0 sinZ!=0 cosZ!=0 + //element 13/11 + R = atan( sin(x)*sin(z)/(cos(y)*cos(z)) ); + //use 13 for 'sign' + if( (sin(x)*sin(z))<0.0 ) + R += F_PI; + //element 22 + E = acos(sin(x)*sin(y)*sin(z) ); + //use 21 for sign + if( (cos(y)*sin(z)*sin(R)*sin(E))<0.0 ) + E*=-1.0; + } + } + else if( lcl_isSinZero(z) ) + { + //cosY!=0 sinY!=0 sinX!=0 cosX!=0 sinZ=0 + //element 11 + R=y; + //use elenment 13 for sign + if( (cos(x)*cos(z)*sin(y)*sin(R))<0.0 ) + R*=-1.0; + //element 22 + E = acos( cos(x)*cos(z) ); + //use element 23 for sign + if( (cos(z)*sin(x)*cos(R)*sin(E))<0.0 ) + E*=-1.0; + } + else if( lcl_isCosZero(z) ) + { + //cosY!=0 sinY!=0 sinX!=0 cosX!=0 cosZ=0 + //element 21/23 + R=atan(-cos(y)/(cos(x)*sin(y))); + //use element 13 for 'sign' + if( (sin(x)*sin(z)*sin(R))<0.0 ) + R+=F_PI; + //element 21/22 + E=atan( cos(y)*sin(z)/(sin(R)*sin(x)*sin(y)*sin(z)) ); + //use element 23 for 'sign' + if( (-cos(x)*sin(y)*sin(z)*cos(R)*sin(E))<0.0 ) + E+=F_PI; + } + else + { + //cosY!=0 sinY!=0 sinX!=0 cosX!=0 sinZ!=0 cosZ!=0 + //13/11: + double f13 = sin(x)*sin(z)+cos(x)*cos(z)*sin(y); + R = atan( f13/ f11 ); + if(f11<0.0) + R+=F_PI; + double f22 = cos(x)*cos(z)+sin(x)*sin(y)*sin(z); + double f23 = cos(x)*sin(y)*sin(z)-cos(z)*sin(x); + //23/22: + E = atan( -1.0*f23/(f22*cos(R)) ); + if(f22<0.0) + E+=F_PI; + } + + rnElevationDeg = ::basegfx::fround( BaseGFXHelper::Rad2Deg( E ) ); + rnRotationDeg = ::basegfx::fround( BaseGFXHelper::Rad2Deg( R ) ); +} + +double ThreeDHelper::getValueClippedToRange( double fAngle, const double& fPositivLimit ) +{ + if( fAngle<-1*fPositivLimit ) + fAngle=-1*fPositivLimit; + else if( fAngle>fPositivLimit ) + fAngle=fPositivLimit; + return fAngle; +} + +double ThreeDHelper::getXDegreeAngleLimitForRightAngledAxes() +{ + return 90.0; +} + +double ThreeDHelper::getYDegreeAngleLimitForRightAngledAxes() +{ + return 45.0; +} + +void ThreeDHelper::adaptRadAnglesForRightAngledAxes( double& rfXAngleRad, double& rfYAngleRad ) +{ + rfXAngleRad = ThreeDHelper::getValueClippedToRange(rfXAngleRad, BaseGFXHelper::Deg2Rad(ThreeDHelper::getXDegreeAngleLimitForRightAngledAxes()) ); + rfYAngleRad = ThreeDHelper::getValueClippedToRange(rfYAngleRad, BaseGFXHelper::Deg2Rad(ThreeDHelper::getYDegreeAngleLimitForRightAngledAxes()) ); +} + +void ThreeDHelper::getRotationAngleFromDiagram( + const Reference< beans::XPropertySet >& xSceneProperties, double& rfXAngleRad, double& rfYAngleRad, double& rfZAngleRad ) +{ + //takes the camera and the transformation matrix into account + + rfXAngleRad = rfYAngleRad = rfZAngleRad = 0.0; + + if( !xSceneProperties.is() ) + return; + + //get camera rotation + ::basegfx::B3DHomMatrix aFixCameraRotationMatrix( lcl_getCameraMatrix( xSceneProperties ) ); + BaseGFXHelper::ReduceToRotationMatrix( aFixCameraRotationMatrix ); + + //get scene rotation + ::basegfx::B3DHomMatrix aSceneRotation; + { + drawing::HomogenMatrix aHomMatrix; + if( xSceneProperties->getPropertyValue( C2U("D3DTransformMatrix")) >>= aHomMatrix ) + { + aSceneRotation = BaseGFXHelper::HomogenMatrixToB3DHomMatrix( aHomMatrix ); + BaseGFXHelper::ReduceToRotationMatrix( aSceneRotation ); + } + } + + ::basegfx::B3DHomMatrix aResultRotation = aFixCameraRotationMatrix * aSceneRotation; + ::basegfx::B3DTuple aRotation( BaseGFXHelper::GetRotationFromMatrix( aResultRotation ) ); + + rfXAngleRad = lcl_shiftAngleToIntervalMinusPiToPi(aRotation.getX()); + rfYAngleRad = lcl_shiftAngleToIntervalMinusPiToPi(aRotation.getY()); + rfZAngleRad = lcl_shiftAngleToIntervalMinusPiToPi(aRotation.getZ()); + + if(rfZAngleRad<(-F_PI/2) || rfZAngleRad>(F_PI/2)) + { + rfZAngleRad-=F_PI; + rfXAngleRad-=F_PI; + rfYAngleRad=(F_PI-rfYAngleRad); + + rfXAngleRad = lcl_shiftAngleToIntervalMinusPiToPi(rfXAngleRad); + rfYAngleRad = lcl_shiftAngleToIntervalMinusPiToPi(rfYAngleRad); + rfZAngleRad = lcl_shiftAngleToIntervalMinusPiToPi(rfZAngleRad); + } +} + +void ThreeDHelper::switchRightAngledAxes( const Reference< beans::XPropertySet >& xSceneProperties, sal_Bool bRightAngledAxes, bool bRotateLights ) +{ + try + { + if( xSceneProperties.is() ) + { + sal_Bool bOldRightAngledAxes = sal_False; + xSceneProperties->getPropertyValue( C2U("RightAngledAxes")) >>= bOldRightAngledAxes; + if( bOldRightAngledAxes!=bRightAngledAxes) + { + xSceneProperties->setPropertyValue( C2U("RightAngledAxes"), uno::makeAny( bRightAngledAxes )); + if( bRotateLights ) + { + if(bRightAngledAxes) + { + ::basegfx::B3DHomMatrix aInverseRotation( lcl_getInverseRotationMatrix( xSceneProperties ) ); + lcl_rotateLights( aInverseRotation, xSceneProperties ); + } + else + { + ::basegfx::B3DHomMatrix aCompleteRotation( lcl_getCompleteRotationMatrix( xSceneProperties ) ); + lcl_rotateLights( aCompleteRotation, xSceneProperties ); + } + } + } + } + } + catch( const uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } +} + +void ThreeDHelper::setRotationAngleToDiagram( + const Reference< beans::XPropertySet >& xSceneProperties + , double fXAngleRad, double fYAngleRad, double fZAngleRad ) +{ + //the rotation of the camera is not touched but taken into account + //the rotation difference is applied to the transformation matrix + + //the light sources will be adapted also + + if( !xSceneProperties.is() ) + return; + + try + { + //remind old rotation for adaption of light directions + ::basegfx::B3DHomMatrix aInverseOldRotation( lcl_getInverseRotationMatrix( xSceneProperties ) ); + + ::basegfx::B3DHomMatrix aInverseCameraRotation; + { + ::basegfx::B3DTuple aR( BaseGFXHelper::GetRotationFromMatrix( + lcl_getCameraMatrix( xSceneProperties ) ) ); + aInverseCameraRotation.rotate( 0.0, 0.0, -aR.getZ() ); + aInverseCameraRotation.rotate( 0.0, -aR.getY(), 0.0 ); + aInverseCameraRotation.rotate( -aR.getX(), 0.0, 0.0 ); + } + + ::basegfx::B3DHomMatrix aCumulatedRotation; + aCumulatedRotation.rotate( fXAngleRad, fYAngleRad, fZAngleRad ); + + //calculate new scene matrix + ::basegfx::B3DHomMatrix aSceneRotation = aInverseCameraRotation*aCumulatedRotation; + BaseGFXHelper::ReduceToRotationMatrix( aSceneRotation ); + + //set new rotation to transformation matrix + xSceneProperties->setPropertyValue( + C2U("D3DTransformMatrix"), uno::makeAny( BaseGFXHelper::B3DHomMatrixToHomogenMatrix( aSceneRotation ))); + + //rotate lights if RightAngledAxes are not set or not supported + sal_Bool bRightAngledAxes = sal_False; + xSceneProperties->getPropertyValue( C2U("RightAngledAxes")) >>= bRightAngledAxes; + uno::Reference< chart2::XDiagram > xDiagram( xSceneProperties, uno::UNO_QUERY ); + if(!bRightAngledAxes || !ChartTypeHelper::isSupportingRightAngledAxes( + DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) ) ) + { + ::basegfx::B3DHomMatrix aNewRotation; + aNewRotation.rotate( fXAngleRad, fYAngleRad, fZAngleRad ); + lcl_rotateLights( aNewRotation*aInverseOldRotation, xSceneProperties ); + } + } + catch( const uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } +} + +void ThreeDHelper::getRotationFromDiagram( const uno::Reference< beans::XPropertySet >& xSceneProperties + , sal_Int32& rnHorizontalAngleDegree, sal_Int32& rnVerticalAngleDegree ) +{ + double fXAngle, fYAngle, fZAngle; + ThreeDHelper::getRotationAngleFromDiagram( xSceneProperties, fXAngle, fYAngle, fZAngle ); + + if( !lcl_isRightAngledAxesSetAndSupported( xSceneProperties ) ) + { + ThreeDHelper::convertXYZAngleRadToElevationRotationDeg( + rnHorizontalAngleDegree, rnVerticalAngleDegree, fXAngle, fYAngle, fZAngle); + rnVerticalAngleDegree*=-1; + } + else + { + fXAngle = BaseGFXHelper::Rad2Deg( fXAngle ); + fYAngle = BaseGFXHelper::Rad2Deg( fYAngle ); + fZAngle = BaseGFXHelper::Rad2Deg( fZAngle ); + + rnHorizontalAngleDegree = ::basegfx::fround(fXAngle); + rnVerticalAngleDegree = ::basegfx::fround(-1.0*fYAngle); + //nZRotation = ::basegfx::fround(-1.0*fZAngle); + } + + lcl_shiftAngleToIntervalMinus180To180( rnHorizontalAngleDegree ); + lcl_shiftAngleToIntervalMinus180To180( rnVerticalAngleDegree ); +} + +void ThreeDHelper::setRotationToDiagram( const uno::Reference< beans::XPropertySet >& xSceneProperties + , sal_Int32 nHorizontalAngleDegree, sal_Int32 nVerticalYAngleDegree ) +{ + //todo: x and y is not equal to horz and vert in case of RightAngledAxes==false + double fXAngle = BaseGFXHelper::Deg2Rad( nHorizontalAngleDegree ); + double fYAngle = BaseGFXHelper::Deg2Rad( -1*nVerticalYAngleDegree ); + double fZAngle = 0.0; + + if( !lcl_isRightAngledAxesSetAndSupported( xSceneProperties ) ) + ThreeDHelper::convertElevationRotationDegToXYZAngleRad( + nHorizontalAngleDegree, -1*nVerticalYAngleDegree, fXAngle, fYAngle, fZAngle ); + + ThreeDHelper::setRotationAngleToDiagram( xSceneProperties, fXAngle, fYAngle, fZAngle ); +} + +void ThreeDHelper::getCameraDistanceRange( double& rfMinimumDistance, double& rfMaximumDistance ) +{ + rfMinimumDistance = 3.0/4.0*FIXED_SIZE_FOR_3D_CHART_VOLUME;//empiric value + rfMaximumDistance = 20.0*FIXED_SIZE_FOR_3D_CHART_VOLUME;//empiric value +} + +void ThreeDHelper::ensureCameraDistanceRange( double& rfCameraDistance ) +{ + double fMin, fMax; + getCameraDistanceRange( fMin, fMax ); + if( rfCameraDistance < fMin ) + rfCameraDistance = fMin; + if( rfCameraDistance > fMax ) + rfCameraDistance = fMax; +} + +double ThreeDHelper::getCameraDistance( + const Reference< beans::XPropertySet >& xSceneProperties ) +{ + double fCameraDistance = FIXED_SIZE_FOR_3D_CHART_VOLUME; + + if( !xSceneProperties.is() ) + return fCameraDistance; + + try + { + drawing::CameraGeometry aCG( ThreeDHelper::getDefaultCameraGeometry() ); + xSceneProperties->getPropertyValue( C2U( "D3DCameraGeometry" ) ) >>= aCG; + ::basegfx::B3DVector aVRP( BaseGFXHelper::Position3DToB3DVector( aCG.vrp ) ); + fCameraDistance = aVRP.getLength(); + + ensureCameraDistanceRange( fCameraDistance ); + } + catch( const uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + return fCameraDistance; +} + +void ThreeDHelper::setCameraDistance( + const Reference< beans::XPropertySet >& xSceneProperties, double fCameraDistance ) +{ + if( !xSceneProperties.is() ) + return; + + try + { + if( fCameraDistance <= 0 ) + fCameraDistance = FIXED_SIZE_FOR_3D_CHART_VOLUME; + + drawing::CameraGeometry aCG( ThreeDHelper::getDefaultCameraGeometry() ); + xSceneProperties->getPropertyValue( C2U( "D3DCameraGeometry" ) ) >>= aCG; + ::basegfx::B3DVector aVRP( BaseGFXHelper::Position3DToB3DVector( aCG.vrp ) ); + if( ::basegfx::fTools::equalZero( aVRP.getLength() ) ) + aVRP = ::basegfx::B3DVector(0,0,1); + aVRP.setLength(fCameraDistance); + aCG.vrp = BaseGFXHelper::B3DVectorToPosition3D( aVRP ); + + xSceneProperties->setPropertyValue( C2U("D3DCameraGeometry"), uno::makeAny( aCG )); + } + catch( const uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } +} + +//static +double ThreeDHelper::CameraDistanceToPerspective( double fCameraDistance ) +{ + double fRet = fCameraDistance; + double fMin, fMax; + ThreeDHelper::getCameraDistanceRange( fMin, fMax ); + //fMax <-> 0; fMin <->100 + //a/x + b = y + double a = 100.0*fMax*fMin/(fMax-fMin); + double b = -a/fMax; + + fRet = a/fCameraDistance + b; + + return fRet; +} + +//static +double ThreeDHelper::PerspectiveToCameraDistance( double fPerspective ) +{ + double fRet = fPerspective; + double fMin, fMax; + ThreeDHelper::getCameraDistanceRange( fMin, fMax ); + //fMax <-> 0; fMin <->100 + //a/x + b = y + double a = 100.0*fMax*fMin/(fMax-fMin); + double b = -a/fMax; + + fRet = a/(fPerspective - b); + + return fRet; +} + +//static +ThreeDLookScheme ThreeDHelper::detectScheme( const uno::Reference< XDiagram >& xDiagram ) +{ + ThreeDLookScheme aScheme = ThreeDLookScheme_Unknown; + + sal_Int32 nRoundedEdges; + sal_Int32 nObjectLines; + ThreeDHelper::getRoundedEdgesAndObjectLines( xDiagram, nRoundedEdges, nObjectLines ); + + //get shade mode and light settings: + drawing::ShadeMode aShadeMode( drawing::ShadeMode_SMOOTH ); + uno::Reference< beans::XPropertySet > xDiagramProps( xDiagram, uno::UNO_QUERY ); + try + { + if( xDiagramProps.is() ) + xDiagramProps->getPropertyValue( C2U( "D3DSceneShadeMode" ) )>>= aShadeMode; + } + catch( uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + + if( lcl_isSimpleScheme( aShadeMode, nRoundedEdges, nObjectLines, xDiagram ) ) + { + if( lcl_isSimpleLightScheme(xDiagramProps) ) + aScheme = ThreeDLookScheme_Simple; + } + else if( lcl_isRealisticScheme( aShadeMode, nRoundedEdges, nObjectLines ) ) + { + if( lcl_isRealisticLightScheme(xDiagramProps) ) + aScheme = ThreeDLookScheme_Realistic; + } + + return aScheme; +} + +void ThreeDHelper::setScheme( const uno::Reference< XDiagram >& xDiagram, ThreeDLookScheme aScheme ) +{ + if( aScheme == ThreeDLookScheme_Unknown ) + return; + + drawing::ShadeMode aShadeMode; + sal_Int32 nRoundedEdges; + sal_Int32 nObjectLines; + + if( aScheme == ThreeDLookScheme_Simple ) + lcl_setSimpleScheme(aShadeMode,nRoundedEdges,nObjectLines,xDiagram); + else + lcl_setRealisticScheme(aShadeMode,nRoundedEdges,nObjectLines); + + try + { + ThreeDHelper::setRoundedEdgesAndObjectLines( xDiagram, nRoundedEdges, nObjectLines ); + + uno::Reference< beans::XPropertySet > xProp( xDiagram, uno::UNO_QUERY ); + if( xProp.is() ) + { + drawing::ShadeMode aOldShadeMode; + if( ! ( (xProp->getPropertyValue( C2U( "D3DSceneShadeMode" ) )>>=aOldShadeMode) && + aOldShadeMode == aShadeMode )) + { + xProp->setPropertyValue( C2U( "D3DSceneShadeMode" ), uno::makeAny( aShadeMode )); + } + } + + lcl_setLightsForScheme( xProp, aScheme ); + } + catch( uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + +} + +//static +void ThreeDHelper::set3DSettingsToDefault( const uno::Reference< beans::XPropertySet >& xSceneProperties ) +{ + Reference< beans::XPropertyState > xState( xSceneProperties, uno::UNO_QUERY ); + if(xState.is()) + { + xState->setPropertyToDefault( C2U("D3DSceneDistance")); + xState->setPropertyToDefault( C2U("D3DSceneFocalLength")); + } + ThreeDHelper::setDefaultRotation( xSceneProperties ); + ThreeDHelper::setDefaultIllumination( xSceneProperties ); +} + +//static +void ThreeDHelper::setDefaultRotation( const uno::Reference< beans::XPropertySet >& xSceneProperties, bool bPieOrDonut ) +{ + if( !xSceneProperties.is() ) + return; + + drawing::CameraGeometry aCameraGeo( ThreeDHelper::getDefaultCameraGeometry( bPieOrDonut ) ); + xSceneProperties->setPropertyValue( C2U("D3DCameraGeometry"), uno::makeAny( aCameraGeo )); + + ::basegfx::B3DHomMatrix aSceneRotation; + if( bPieOrDonut ) + aSceneRotation.rotate( -F_PI/3.0, 0, 0 ); + xSceneProperties->setPropertyValue( C2U("D3DTransformMatrix"), + uno::makeAny( BaseGFXHelper::B3DHomMatrixToHomogenMatrix( aSceneRotation ))); +} + +//static +void ThreeDHelper::setDefaultRotation( const uno::Reference< beans::XPropertySet >& xSceneProperties ) +{ + bool bPieOrDonut( DiagramHelper::isPieOrDonutChart( uno::Reference< XDiagram >(xSceneProperties, uno::UNO_QUERY) ) ); + ThreeDHelper::setDefaultRotation( xSceneProperties, bPieOrDonut ); +} + +//static +void ThreeDHelper::setDefaultIllumination( const uno::Reference< beans::XPropertySet >& xSceneProperties ) +{ + if( !xSceneProperties.is() ) + return; + + drawing::ShadeMode aShadeMode( drawing::ShadeMode_SMOOTH ); + try + { + xSceneProperties->getPropertyValue( C2U( "D3DSceneShadeMode" ) )>>= aShadeMode; + xSceneProperties->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_1 ), uno::makeAny( sal_False ) ); + xSceneProperties->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_3 ), uno::makeAny( sal_False ) ); + xSceneProperties->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_4 ), uno::makeAny( sal_False ) ); + xSceneProperties->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_5 ), uno::makeAny( sal_False ) ); + xSceneProperties->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_6 ), uno::makeAny( sal_False ) ); + xSceneProperties->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_7 ), uno::makeAny( sal_False ) ); + xSceneProperties->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_8 ), uno::makeAny( sal_False ) ); + } + catch( uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + + ThreeDLookScheme aScheme = (drawing::ShadeMode_FLAT==aShadeMode) ? ThreeDLookScheme_Simple : ThreeDLookScheme_Realistic; + lcl_setLightsForScheme( xSceneProperties, aScheme ); +} + +//static +void ThreeDHelper::getRoundedEdgesAndObjectLines( + const uno::Reference< XDiagram > & xDiagram + , sal_Int32& rnRoundedEdges, sal_Int32& rnObjectLines ) +{ + rnRoundedEdges = -1; + rnObjectLines = -1; + try + { + bool bDifferentRoundedEdges = false; + bool bDifferentObjectLines = false; + + drawing::LineStyle aLineStyle( drawing::LineStyle_SOLID ); + + ::std::vector< uno::Reference< XDataSeries > > aSeriesList( + DiagramHelper::getDataSeriesFromDiagram( xDiagram ) ); + sal_Int32 nSeriesCount = static_cast<sal_Int32>( aSeriesList.size() ); + + rtl::OUString aPercentDiagonalPropertyName( C2U( "PercentDiagonal" ) ); + rtl::OUString aBorderStylePropertyName( C2U( "BorderStyle" ) ); + + for( sal_Int32 nS = 0; nS < nSeriesCount; ++nS ) + { + uno::Reference< XDataSeries > xSeries( aSeriesList[nS] ); + uno::Reference< beans::XPropertySet > xProp( xSeries, uno::UNO_QUERY ); + if(!nS) + { + rnRoundedEdges = 0; + try + { + sal_Int16 nPercentDiagonal = 0; + + xProp->getPropertyValue( aPercentDiagonalPropertyName ) >>= nPercentDiagonal; + rnRoundedEdges = static_cast< sal_Int32 >( nPercentDiagonal ); + + if( DataSeriesHelper::hasAttributedDataPointDifferentValue( xSeries + , aPercentDiagonalPropertyName, uno::makeAny(nPercentDiagonal) ) ) + bDifferentRoundedEdges = true; + } + catch( uno::Exception& e ) + { + ASSERT_EXCEPTION( e ); + bDifferentRoundedEdges = true; + } + try + { + xProp->getPropertyValue( aBorderStylePropertyName ) >>= aLineStyle; + + if( DataSeriesHelper::hasAttributedDataPointDifferentValue( xSeries + , aBorderStylePropertyName, uno::makeAny(aLineStyle) ) ) + bDifferentObjectLines = true; + } + catch( uno::Exception& e ) + { + ASSERT_EXCEPTION( e ); + bDifferentObjectLines = true; + } + } + else + { + if( !bDifferentRoundedEdges ) + { + sal_Int16 nPercentDiagonal = 0; + xProp->getPropertyValue( aPercentDiagonalPropertyName ) >>= nPercentDiagonal; + sal_Int32 nCurrentRoundedEdges = static_cast< sal_Int32 >( nPercentDiagonal ); + if(nCurrentRoundedEdges!=rnRoundedEdges + || DataSeriesHelper::hasAttributedDataPointDifferentValue( xSeries + , aPercentDiagonalPropertyName, uno::makeAny( static_cast< sal_Int16 >(rnRoundedEdges) ) ) ) + { + bDifferentRoundedEdges = true; + nCurrentRoundedEdges = -1; + } + } + + if( !bDifferentObjectLines ) + { + drawing::LineStyle aCurrentLineStyle; + xProp->getPropertyValue( aBorderStylePropertyName ) >>= aCurrentLineStyle; + if(aCurrentLineStyle!=aLineStyle + || DataSeriesHelper::hasAttributedDataPointDifferentValue( xSeries + , aBorderStylePropertyName, uno::makeAny(aLineStyle) ) ) + bDifferentObjectLines = true; + } + } + if( bDifferentRoundedEdges && bDifferentObjectLines ) + break; + } + + //set rnObjectLines + rnObjectLines = 0; + if( bDifferentObjectLines ) + rnObjectLines = -1; + else if( aLineStyle == drawing::LineStyle_SOLID ) + rnObjectLines = 1; + } + catch( uno::Exception& e ) + { + ASSERT_EXCEPTION( e ); + } +} +//static +void ThreeDHelper::setRoundedEdgesAndObjectLines( + const uno::Reference< XDiagram > & xDiagram + , sal_Int32 nRoundedEdges, sal_Int32 nObjectLines ) +{ + if( (nRoundedEdges<0||nRoundedEdges>100) && nObjectLines!=0 && nObjectLines!=1 ) + return; + + drawing::LineStyle aLineStyle( drawing::LineStyle_NONE ); + if(nObjectLines==1) + aLineStyle = drawing::LineStyle_SOLID; + + uno::Any aALineStyle( uno::makeAny(aLineStyle)); + uno::Any aARoundedEdges( uno::makeAny( static_cast< sal_Int16 >( nRoundedEdges ))); + + ::std::vector< uno::Reference< XDataSeries > > aSeriesList( + DiagramHelper::getDataSeriesFromDiagram( xDiagram ) ); + sal_Int32 nSeriesCount = static_cast<sal_Int32>( aSeriesList.size() ); + for( sal_Int32 nS = 0; nS < nSeriesCount; ++nS ) + { + uno::Reference< XDataSeries > xSeries( aSeriesList[nS] ); + + if( nRoundedEdges>=0 && nRoundedEdges<=100 ) + DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints( xSeries, C2U( "PercentDiagonal" ), aARoundedEdges ); + + if( nObjectLines==0 || nObjectLines==1 ) + DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints( xSeries, C2U( "BorderStyle" ), aALineStyle ); + } +} + +//static +CuboidPlanePosition ThreeDHelper::getAutomaticCuboidPlanePositionForStandardLeftWall( const Reference< beans::XPropertySet >& xSceneProperties ) +{ + CuboidPlanePosition eRet(CuboidPlanePosition_Left); + + double fXAngleRad=0.0; double fYAngleRad=0.0; double fZAngleRad=0.0; + ThreeDHelper::getRotationAngleFromDiagram( xSceneProperties, fXAngleRad, fYAngleRad, fZAngleRad ); + if( lcl_isRightAngledAxesSetAndSupported( xSceneProperties ) ) + { + ThreeDHelper::adaptRadAnglesForRightAngledAxes( fXAngleRad, fYAngleRad ); + fZAngleRad=0.0; + } + if( sin(fYAngleRad)>0.0 ) + eRet = CuboidPlanePosition_Right; + return eRet; +} + +//static +CuboidPlanePosition ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBackWall( const Reference< beans::XPropertySet >& xSceneProperties ) +{ + CuboidPlanePosition eRet(CuboidPlanePosition_Back); + + double fXAngleRad=0.0; double fYAngleRad=0.0; double fZAngleRad=0.0; + ThreeDHelper::getRotationAngleFromDiagram( xSceneProperties, fXAngleRad, fYAngleRad, fZAngleRad ); + if( lcl_isRightAngledAxesSetAndSupported( xSceneProperties ) ) + { + ThreeDHelper::adaptRadAnglesForRightAngledAxes( fXAngleRad, fYAngleRad ); + fZAngleRad=0.0; + } + if( cos(fXAngleRad)*cos(fYAngleRad)<0.0 ) + eRet = CuboidPlanePosition_Front; + return eRet; +} + +//static +CuboidPlanePosition ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBottom( const Reference< beans::XPropertySet >& xSceneProperties ) +{ + CuboidPlanePosition eRet(CuboidPlanePosition_Bottom); + + double fXAngleRad=0.0; double fYAngleRad=0.0; double fZAngleRad=0.0; + ThreeDHelper::getRotationAngleFromDiagram( xSceneProperties, fXAngleRad, fYAngleRad, fZAngleRad ); + if( lcl_isRightAngledAxesSetAndSupported( xSceneProperties ) ) + { + ThreeDHelper::adaptRadAnglesForRightAngledAxes( fXAngleRad, fYAngleRad ); + fZAngleRad=0.0; + } + if( sin(fXAngleRad)*cos(fYAngleRad)<0.0 ) + eRet = CuboidPlanePosition_Top; + return eRet; +} + +//............................................................................. +} //namespace chart +//............................................................................. diff --git a/chart2/source/tools/TitleHelper.cxx b/chart2/source/tools/TitleHelper.cxx new file mode 100644 index 000000000000..828a523245ff --- /dev/null +++ b/chart2/source/tools/TitleHelper.cxx @@ -0,0 +1,378 @@ +/************************************************************************* + * + * 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 "TitleHelper.hxx" +#include "ChartModelHelper.hxx" +#include "macros.hxx" +#include "AxisHelper.hxx" +#include "DiagramHelper.hxx" +#include <com/sun/star/chart2/XChartDocument.hpp> +#include <rtl/ustrbuf.hxx> + +//............................................................................. +namespace chart +{ +//............................................................................. + +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; +using ::com::sun::star::uno::Reference; + +uno::Reference< XTitled > lcl_getTitleParentFromDiagram( + TitleHelper::eTitleType nTitleIndex + , const uno::Reference< XDiagram >& xDiagram ) +{ + uno::Reference< XTitled > xResult; + + if( nTitleIndex == TitleHelper::TITLE_AT_STANDARD_X_AXIS_POSITION || + nTitleIndex == TitleHelper::TITLE_AT_STANDARD_Y_AXIS_POSITION ) + { + bool bDummy = false; + bool bIsVertical = DiagramHelper::getVertical( xDiagram, bDummy, bDummy ); + + if( nTitleIndex == TitleHelper::TITLE_AT_STANDARD_Y_AXIS_POSITION ) + nTitleIndex = bIsVertical ? TitleHelper::X_AXIS_TITLE : TitleHelper::Y_AXIS_TITLE; + else + nTitleIndex = bIsVertical ? TitleHelper::Y_AXIS_TITLE : TitleHelper::X_AXIS_TITLE; + } + + + switch( nTitleIndex ) + { + case TitleHelper::SUB_TITLE: + if( xDiagram.is()) + xResult.set( xDiagram, uno::UNO_QUERY ); + break; + case TitleHelper::X_AXIS_TITLE: + if( xDiagram.is()) + xResult.set( AxisHelper::getAxis( 0, true, xDiagram ), uno::UNO_QUERY ); + break; + case TitleHelper::Y_AXIS_TITLE: + if( xDiagram.is()) + xResult.set( AxisHelper::getAxis( 1, true, xDiagram ), uno::UNO_QUERY ); + break; + case TitleHelper::Z_AXIS_TITLE: + if( xDiagram.is()) + xResult.set( AxisHelper::getAxis( 2, true, xDiagram ), uno::UNO_QUERY ); + break; + case TitleHelper::SECONDARY_X_AXIS_TITLE: + if( xDiagram.is()) + xResult.set( AxisHelper::getAxis( 0, false, xDiagram ), uno::UNO_QUERY ); + break; + case TitleHelper::SECONDARY_Y_AXIS_TITLE: + if( xDiagram.is()) + xResult.set( AxisHelper::getAxis( 1, false, xDiagram ), uno::UNO_QUERY ); + break; + + case TitleHelper::MAIN_TITLE: + default: + OSL_ENSURE( false, "Unsupported Title-Type requested" ); + break; + } + + return xResult; +} + +uno::Reference< XTitled > lcl_getTitleParent( TitleHelper::eTitleType nTitleIndex + , const uno::Reference< frame::XModel >& xModel ) +{ + uno::Reference< XTitled > xResult; + uno::Reference< XChartDocument > xChartDoc( xModel, uno::UNO_QUERY ); + uno::Reference< XDiagram > xDiagram; + if( xChartDoc.is()) + xDiagram.set( xChartDoc->getFirstDiagram()); + + switch( nTitleIndex ) + { + case TitleHelper::MAIN_TITLE: + xResult.set( xModel, uno::UNO_QUERY ); + break; + case TitleHelper::SUB_TITLE: + case TitleHelper::X_AXIS_TITLE: + case TitleHelper::Y_AXIS_TITLE: + case TitleHelper::Z_AXIS_TITLE: + case TitleHelper::TITLE_AT_STANDARD_X_AXIS_POSITION: + case TitleHelper::TITLE_AT_STANDARD_Y_AXIS_POSITION: + case TitleHelper::SECONDARY_X_AXIS_TITLE: + case TitleHelper::SECONDARY_Y_AXIS_TITLE: + xResult.set( lcl_getTitleParentFromDiagram( nTitleIndex, xDiagram )); + break; + default: + OSL_ENSURE( false, "Unsupported Title-Type requested" ); + break; + } + + return xResult; +} + +uno::Reference< XTitle > TitleHelper::getTitle( TitleHelper::eTitleType nTitleIndex + , const uno::Reference< frame::XModel >& xModel ) +{ + uno::Reference< XTitled > xTitled( lcl_getTitleParent( nTitleIndex, xModel ) ); + if( xTitled.is()) + return xTitled->getTitleObject(); + return NULL; +} + +uno::Reference< XTitle > TitleHelper::createTitle( + TitleHelper::eTitleType eTitleType + , const rtl::OUString& rTitleText + , const uno::Reference< frame::XModel >& xModel + , const uno::Reference< uno::XComponentContext > & xContext + , ReferenceSizeProvider * pRefSizeProvider ) +{ + uno::Reference< XTitle > xTitle; + uno::Reference< XTitled > xTitled( lcl_getTitleParent( eTitleType, xModel ) ); + + if( !xTitled.is() ) + { + uno::Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xModel ) ); + uno::Reference< chart2::XAxis > xAxis; + switch( eTitleType ) + { + case TitleHelper::SECONDARY_X_AXIS_TITLE: + xAxis = AxisHelper::createAxis( 0, false, xDiagram, xContext ); + break; + case TitleHelper::SECONDARY_Y_AXIS_TITLE: + xAxis = AxisHelper::createAxis( 1, false, xDiagram, xContext ); + break; + default: + break; + } + uno::Reference< beans::XPropertySet > xProps( xAxis, uno::UNO_QUERY ); + if( xProps.is() ) + { + xProps->setPropertyValue( C2U( "Show" ), uno::makeAny( sal_False ) ); + xTitled = lcl_getTitleParent( eTitleType, xModel ); + } + } + + if(xTitled.is()) + { + uno::Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xModel ) ); + + xTitle.set( xContext->getServiceManager()->createInstanceWithContext( + C2U( "com.sun.star.chart2.Title" ), + xContext ), uno::UNO_QUERY ); + + if(xTitle.is()) + { + // default char height (main: 13.0 == default) + float fDefaultCharHeightSub = 11.0; + float fDefaultCharHeightAxis = 9.0; + switch( eTitleType ) + { + case TitleHelper::SUB_TITLE: + TitleHelper::setCompleteString( + rTitleText, xTitle, xContext, & fDefaultCharHeightSub ); + break; + case TitleHelper::X_AXIS_TITLE: + case TitleHelper::Y_AXIS_TITLE: + case TitleHelper::Z_AXIS_TITLE: + case TitleHelper::TITLE_AT_STANDARD_X_AXIS_POSITION: + case TitleHelper::TITLE_AT_STANDARD_Y_AXIS_POSITION: + case TitleHelper::SECONDARY_X_AXIS_TITLE: + case TitleHelper::SECONDARY_Y_AXIS_TITLE: + TitleHelper::setCompleteString( + rTitleText, xTitle, xContext, & fDefaultCharHeightAxis ); + break; + default: + TitleHelper::setCompleteString( rTitleText, xTitle, xContext ); + break; + } + + // set/clear autoscale + if( pRefSizeProvider ) + pRefSizeProvider->setValuesAtTitle( xTitle ); + + xTitled->setTitleObject( xTitle ); + + //default rotation 90 degree for y axis title in normal coordinatesystems or for x axis title for swapped coordinatesystems + if( eTitleType == TitleHelper::X_AXIS_TITLE || + eTitleType == TitleHelper::Y_AXIS_TITLE || + eTitleType == TitleHelper::SECONDARY_X_AXIS_TITLE || + eTitleType == TitleHelper::SECONDARY_Y_AXIS_TITLE ) + + { + try + { + bool bDummy = false; + bool bIsVertical = DiagramHelper::getVertical( xDiagram, bDummy, bDummy ); + + Reference< beans::XPropertySet > xTitleProps( xTitle, uno::UNO_QUERY ); + if( xTitleProps.is() ) + { + double fNewAngleDegree = 90.0; + if( (!bIsVertical && eTitleType == TitleHelper::Y_AXIS_TITLE) + || (bIsVertical && eTitleType == TitleHelper::X_AXIS_TITLE) + || (!bIsVertical && eTitleType == TitleHelper::SECONDARY_Y_AXIS_TITLE) + || (bIsVertical && eTitleType == TitleHelper::SECONDARY_X_AXIS_TITLE) ) + xTitleProps->setPropertyValue( C2U( "TextRotation" ), uno::makeAny( fNewAngleDegree )); + } + } + catch( uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + } + } + } + return xTitle; + +} + +rtl::OUString TitleHelper::getCompleteString( const uno::Reference< XTitle >& xTitle ) +{ + rtl::OUString aRet; + if(!xTitle.is()) + return aRet; + uno::Sequence< uno::Reference< XFormattedString > > aStringList = xTitle->getText(); + for( sal_Int32 nN=0; nN<aStringList.getLength();nN++ ) + aRet += aStringList[nN]->getString(); + return aRet; +} + +void TitleHelper::setCompleteString( const rtl::OUString& rNewText + , const uno::Reference< XTitle >& xTitle + , const uno::Reference< uno::XComponentContext > & xContext + , float * pDefaultCharHeight /* = 0 */ ) +{ + //the format of the first old text portion will be maintained if there is any + if(!xTitle.is()) + return; + + rtl::OUString aNewText = rNewText; + + bool bStacked = false; + uno::Reference< beans::XPropertySet > xTitleProperties( xTitle, uno::UNO_QUERY ); + if( xTitleProperties.is() ) + xTitleProperties->getPropertyValue( C2U( "StackCharacters" ) ) >>= bStacked; + + if( bStacked ) + { + //#i99841# remove linebreaks that were added for vertical stacking + rtl::OUStringBuffer aUnstackedStr; + rtl::OUStringBuffer aSource(rNewText); + + bool bBreakIgnored = false; + sal_Int32 nLen = rNewText.getLength(); + for( sal_Int32 nPos = 0; nPos < nLen; ++nPos ) + { + sal_Unicode aChar = aSource.charAt( nPos ); + if( aChar != '\n' ) + { + aUnstackedStr.append( aChar ); + bBreakIgnored = false; + } + else if( aChar == '\n' && bBreakIgnored ) + aUnstackedStr.append( aChar ); + else + bBreakIgnored = true; + } + aNewText = aUnstackedStr.makeStringAndClear(); + } + + uno::Sequence< uno::Reference< XFormattedString > > aNewStringList(1); + + uno::Sequence< uno::Reference< XFormattedString > > aOldStringList = xTitle->getText(); + if( aOldStringList.getLength() ) + { + aNewStringList[0].set( aOldStringList[0] ); + aNewStringList[0]->setString( aNewText ); + } + else + { + uno::Reference< uno::XInterface > xI( + xContext->getServiceManager()->createInstanceWithContext( + C2U( "com.sun.star.chart2.FormattedString" ), xContext ) ); + uno::Reference< XFormattedString > xFormattedString( xI, uno::UNO_QUERY ); + + if(xFormattedString.is()) + { + xFormattedString->setString( aNewText ); + aNewStringList[0].set( xFormattedString ); + if( pDefaultCharHeight != 0 ) + { + try + { + uno::Reference< beans::XPropertySet > xProp( xFormattedString, uno::UNO_QUERY_THROW ); + + uno::Any aFontSize( uno::makeAny( *pDefaultCharHeight )); + xProp->setPropertyValue( C2U("CharHeight"), aFontSize ); + xProp->setPropertyValue( C2U("CharHeightAsian"), aFontSize ); + xProp->setPropertyValue( C2U("CharHeightComplex"), aFontSize ); + } + catch( uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + } + } + } + xTitle->setText( aNewStringList ); +} + +void TitleHelper::removeTitle( TitleHelper::eTitleType nTitleIndex + , const ::com::sun::star::uno::Reference< + ::com::sun::star::frame::XModel >& xModel ) +{ + uno::Reference< XTitled > xTitled( lcl_getTitleParent( nTitleIndex, xModel ) ); + if( xTitled.is()) + { + xTitled->setTitleObject(NULL); + } +} + +bool TitleHelper::getTitleType( eTitleType& rType + , const ::com::sun::star::uno::Reference< + ::com::sun::star::chart2::XTitle >& xTitle + , const ::com::sun::star::uno::Reference< + ::com::sun::star::frame::XModel >& xModel ) +{ + if( !xTitle.is() || !xModel.is() ) + return false; + + Reference< chart2::XTitle > xCurrentTitle; + for( sal_Int32 nTitleType = TITLE_BEGIN; nTitleType < NORMAL_TITLE_END; nTitleType++ ) + { + xCurrentTitle = TitleHelper::getTitle( static_cast<eTitleType>(nTitleType), xModel ); + if( xCurrentTitle == xTitle ) + { + rType = static_cast<eTitleType>(nTitleType); + return true; + } + } + + return false; +} + +//............................................................................. +} //namespace chart +//............................................................................. + diff --git a/chart2/source/tools/TrueGuard.cxx b/chart2/source/tools/TrueGuard.cxx new file mode 100644 index 000000000000..6992552367ed --- /dev/null +++ b/chart2/source/tools/TrueGuard.cxx @@ -0,0 +1,47 @@ +/************************************************************************* + * + * 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 "TrueGuard.hxx" + +namespace chart +{ + +TrueGuard::TrueGuard( bool& rbTrueDuringGuardedTime ) + : m_rbTrueDuringGuardedTime( rbTrueDuringGuardedTime ) +{ + m_rbTrueDuringGuardedTime = true; +} + +TrueGuard::~TrueGuard() +{ + m_rbTrueDuringGuardedTime = false; +} + +} // namespace chart diff --git a/chart2/source/tools/UncachedDataSequence.cxx b/chart2/source/tools/UncachedDataSequence.cxx new file mode 100644 index 000000000000..52cc6b9c03b6 --- /dev/null +++ b/chart2/source/tools/UncachedDataSequence.cxx @@ -0,0 +1,379 @@ +/************************************************************************* + * + * 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 "UncachedDataSequence.hxx" +#include "macros.hxx" +#include "PropertyHelper.hxx" +#include "CommonFunctors.hxx" +#include "ModifyListenerHelper.hxx" + +#include <algorithm> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <rtl/math.hxx> + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Any; +using ::rtl::OUString; +using ::osl::MutexGuard; + +// necessary for MS compiler +using ::comphelper::OPropertyContainer; +using ::chart::impl::UncachedDataSequence_Base; + +namespace +{ +static const OUString lcl_aServiceName( + RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.chart.UncachedDataSequence" )); + +enum +{ +// PROP_SOURCE_IDENTIFIER, + PROP_NUMBERFORMAT_KEY, + PROP_PROPOSED_ROLE, + PROP_XML_RANGE +}; +} // anonymous namespace + + +// ____________________ +namespace chart +{ + +UncachedDataSequence::UncachedDataSequence( + const Reference< chart2::XInternalDataProvider > & xIntDataProv, + const OUString & rRangeRepresentation ) + : OPropertyContainer( GetBroadcastHelper()), + UncachedDataSequence_Base( GetMutex()), + m_nNumberFormatKey(0), + m_xDataProvider( xIntDataProv ), + m_aSourceRepresentation( rRangeRepresentation ), + m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()) +{ + registerProperties(); +} + +UncachedDataSequence::UncachedDataSequence( + const Reference< chart2::XInternalDataProvider > & xIntDataProv, + const OUString & rRangeRepresentation, + const OUString & rRole ) + : OPropertyContainer( GetBroadcastHelper()), + UncachedDataSequence_Base( GetMutex()), + m_nNumberFormatKey(0), + m_xDataProvider( xIntDataProv ), + m_aSourceRepresentation( rRangeRepresentation ), + m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()) +{ + registerProperties(); + setFastPropertyValue_NoBroadcast( PROP_PROPOSED_ROLE, uno::makeAny( rRole )); +} + +UncachedDataSequence::UncachedDataSequence( const UncachedDataSequence & rSource ) + : ::comphelper::OMutexAndBroadcastHelper(), + OPropertyContainer( GetBroadcastHelper()), + ::comphelper::OPropertyArrayUsageHelper< UncachedDataSequence >(), + UncachedDataSequence_Base( GetMutex()), + m_nNumberFormatKey( rSource.m_nNumberFormatKey ), + m_sRole( rSource.m_sRole ), + m_xDataProvider( rSource.m_xDataProvider ), + m_aSourceRepresentation( rSource.m_aSourceRepresentation ), + m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()) +{ + registerProperties(); +} + +UncachedDataSequence::~UncachedDataSequence() +{} + +void UncachedDataSequence::registerProperties() +{ + registerProperty( C2U( "NumberFormatKey" ), + PROP_NUMBERFORMAT_KEY, + 0, // PropertyAttributes + & m_nNumberFormatKey, + ::getCppuType( & m_nNumberFormatKey ) ); + + registerProperty( C2U( "Role" ), + PROP_PROPOSED_ROLE, + 0, // PropertyAttributes + & m_sRole, + ::getCppuType( & m_sRole ) ); + + registerProperty( C2U( "CachedXMLRange" ), + PROP_XML_RANGE, + 0, // PropertyAttributes + & m_aXMLRange, + ::getCppuType( & m_aXMLRange ) ); +} + +// ================================================================================ + +Sequence< OUString > UncachedDataSequence::getSupportedServiceNames_Static() +{ + Sequence< OUString > aServices( 4 ); + aServices[ 0 ] = lcl_aServiceName; + aServices[ 1 ] = C2U( "com.sun.star.chart2.data.DataSequence" ); + aServices[ 2 ] = C2U( "com.sun.star.chart2.data.NumericalDataSequence" ); + aServices[ 3 ] = C2U( "com.sun.star.chart2.data.TextualDataSequence" ); + return aServices; +} + +IMPLEMENT_FORWARD_XINTERFACE2( UncachedDataSequence, UncachedDataSequence_Base, OPropertyContainer ) +IMPLEMENT_FORWARD_XTYPEPROVIDER2( UncachedDataSequence, UncachedDataSequence_Base, OPropertyContainer ) + +// ____ XPropertySet ____ +Reference< beans::XPropertySetInfo > SAL_CALL UncachedDataSequence::getPropertySetInfo() + throw(uno::RuntimeException) +{ + return Reference< beans::XPropertySetInfo >( createPropertySetInfo( getInfoHelper() ) ); +} + +// ____ ::comphelper::OPropertySetHelper ____ +// __________________________________________ +::cppu::IPropertyArrayHelper& UncachedDataSequence::getInfoHelper() +{ + return *getArrayHelper(); +} + +// ____ ::comphelper::OPropertyArrayHelper ____ +// ____________________________________________ +::cppu::IPropertyArrayHelper* UncachedDataSequence::createArrayHelper() const +{ + Sequence< beans::Property > aProps; + // describes all properties which have been registered in the ctor + describeProperties( aProps ); + + return new ::cppu::OPropertyArrayHelper( aProps ); +} + +// implement XServiceInfo methods basing upon getSupportedServiceNames_Static +APPHELPER_XSERVICEINFO_IMPL( UncachedDataSequence, lcl_aServiceName ) + +// ================================================================================ + +// ________ XNumericalDataSequence ________ +Sequence< double > SAL_CALL UncachedDataSequence::getNumericalData() + throw (uno::RuntimeException) +{ + Sequence< double > aResult; + // /-- + MutexGuard aGuard( GetMutex() ); + if( m_xDataProvider.is()) + { + Sequence< uno::Any > aValues( m_xDataProvider->getDataByRangeRepresentation( m_aSourceRepresentation )); + aResult.realloc( aValues.getLength()); + ::std::transform( aValues.getConstArray(), aValues.getConstArray() + aValues.getLength(), + aResult.getArray(), CommonFunctors::AnyToDouble()); + } + return aResult; + // \-- +} + +// ________ XTextualDataSequence ________ +Sequence< OUString > SAL_CALL UncachedDataSequence::getTextualData() + throw (uno::RuntimeException) +{ + Sequence< OUString > aResult; + // /-- + MutexGuard aGuard( GetMutex() ); + if( m_xDataProvider.is()) + { + Sequence< uno::Any > aValues( m_xDataProvider->getDataByRangeRepresentation( m_aSourceRepresentation )); + aResult.realloc( aValues.getLength()); + ::std::transform( aValues.getConstArray(), aValues.getConstArray() + aValues.getLength(), + aResult.getArray(), CommonFunctors::AnyToString()); + } + return aResult; + // \-- +} + +// ________ XDataSequence ________ +Sequence< Any > SAL_CALL UncachedDataSequence::getData() + throw (uno::RuntimeException) +{ + // /-- + MutexGuard aGuard( GetMutex() ); + if( m_xDataProvider.is()) + return m_xDataProvider->getDataByRangeRepresentation( m_aSourceRepresentation ); + return Sequence< Any >(); + // \-- +} + +OUString SAL_CALL UncachedDataSequence::getSourceRangeRepresentation() + throw (uno::RuntimeException) +{ + return getName(); +} + + +Sequence< OUString > SAL_CALL UncachedDataSequence::generateLabel( chart2::data::LabelOrigin ) + throw (uno::RuntimeException) +{ + // auto-generated label is an empty string + static const Sequence< OUString > aOneEmptyString( 1 ); + return aOneEmptyString; +} + +::sal_Int32 SAL_CALL UncachedDataSequence::getNumberFormatKeyByIndex( ::sal_Int32 ) + throw (lang::IndexOutOfBoundsException, + uno::RuntimeException) +{ + return m_nNumberFormatKey; +} + +// ____ XIndexReplace ____ +void SAL_CALL UncachedDataSequence::replaceByIndex( ::sal_Int32 Index, const uno::Any& Element ) + throw (lang::IllegalArgumentException, + lang::IndexOutOfBoundsException, + lang::WrappedTargetException, + uno::RuntimeException) +{ + // /-- + MutexGuard aGuard( GetMutex() ); + Sequence< Any > aData( getData()); + if( Index < aData.getLength() && + m_xDataProvider.is() ) + { + aData[Index] = Element; + m_xDataProvider->setDataByRangeRepresentation( m_aSourceRepresentation, aData ); + fireModifyEvent(); + } +} + +// ____ XIndexAccess (base of XIndexReplace) ____ +::sal_Int32 SAL_CALL UncachedDataSequence::getCount() + throw (uno::RuntimeException) +{ + OSL_ENSURE( false, "Implement!" ); + return 0; +} + +uno::Any SAL_CALL UncachedDataSequence::getByIndex( ::sal_Int32 ) + throw (lang::IndexOutOfBoundsException, + lang::WrappedTargetException, + uno::RuntimeException) +{ + OSL_ENSURE( false, "Implement!" ); + return uno::Any(); +} + +// ____ XElementAccess (base of XIndexAccess) ____ +uno::Type SAL_CALL UncachedDataSequence::getElementType() + throw (uno::RuntimeException) +{ + return ::getCppuType( reinterpret_cast< uno::Any * >(0)); +} + +::sal_Bool SAL_CALL UncachedDataSequence::hasElements() + throw (uno::RuntimeException) +{ + if( ! m_xDataProvider.is()) + return sal_False; + return m_xDataProvider->hasDataByRangeRepresentation( m_aSourceRepresentation ); +} + +// ____ XNamed ____ +::rtl::OUString SAL_CALL UncachedDataSequence::getName() + throw (uno::RuntimeException) +{ + return m_aSourceRepresentation; +} + +void SAL_CALL UncachedDataSequence::setName( const OUString& aName ) + throw (uno::RuntimeException) +{ + m_aSourceRepresentation = aName; + fireModifyEvent(); +} + + + +Reference< util::XCloneable > SAL_CALL UncachedDataSequence::createClone() + throw (uno::RuntimeException) +{ + UncachedDataSequence * pNewSeq = new UncachedDataSequence( *this ); + return Reference< util::XCloneable >( pNewSeq ); +} + + +// ____ XModifiable ____ +::sal_Bool SAL_CALL UncachedDataSequence::isModified() + throw (uno::RuntimeException) +{ + return sal_False; +} + +void SAL_CALL UncachedDataSequence::setModified( ::sal_Bool bModified ) + throw (beans::PropertyVetoException, + uno::RuntimeException) +{ + if( bModified ) + fireModifyEvent(); +} + +// ____ XModifyBroadcaster (base of XModifiable) ____ +void SAL_CALL UncachedDataSequence::addModifyListener( const Reference< util::XModifyListener >& aListener ) + throw (uno::RuntimeException) +{ + try + { + Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW ); + xBroadcaster->addModifyListener( aListener ); + } + catch( const uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } +} + +void SAL_CALL UncachedDataSequence::removeModifyListener( const Reference< util::XModifyListener >& aListener ) + throw (uno::RuntimeException) +{ + try + { + Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW ); + xBroadcaster->removeModifyListener( aListener ); + } + catch( const uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } +} + +void UncachedDataSequence::fireModifyEvent() +{ + // @todo: currently never called, as data changes are not yet reported by + // the data provider + m_xModifyEventForwarder->modified( lang::EventObject( static_cast< uno::XWeak* >( this ))); +} + +} // namespace chart diff --git a/chart2/source/tools/UserDefinedProperties.cxx b/chart2/source/tools/UserDefinedProperties.cxx new file mode 100644 index 000000000000..707c48c1a6cc --- /dev/null +++ b/chart2/source/tools/UserDefinedProperties.cxx @@ -0,0 +1,73 @@ +/************************************************************************* + * + * 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 "UserDefinedProperties.hxx" +#include "macros.hxx" +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/container/XNameContainer.hpp> + +using namespace ::com::sun::star; + +using ::com::sun::star::beans::Property; + +namespace chart +{ + +void UserDefinedProperties::AddPropertiesToVector( + ::std::vector< Property > & rOutProperties ) +{ + rOutProperties.push_back( + Property( C2U( "ChartUserDefinedAttributes" ), + PROP_XML_USERDEF_CHART, + ::getCppuType( reinterpret_cast< const uno::Reference< container::XNameContainer > * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID )); + rOutProperties.push_back( + Property( C2U( "TextUserDefinedAttributes" ), + PROP_XML_USERDEF_TEXT, + ::getCppuType( reinterpret_cast< const uno::Reference< container::XNameContainer > * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID )); + rOutProperties.push_back( + Property( C2U( "ParaUserDefinedAttributes" ), + PROP_XML_USERDEF_PARA, + ::getCppuType( reinterpret_cast< const uno::Reference< container::XNameContainer > * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID )); + // UserDefinedAttributeSupplier + // ---------------------------- + rOutProperties.push_back( + Property( C2U( "UserDefinedAttributes" ), + PROP_XML_USERDEF, + ::getCppuType( reinterpret_cast< const uno::Reference< container::XNameContainer > * >(0)), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID )); +} + +} // namespace chart diff --git a/chart2/source/tools/WeakListenerAdapter.cxx b/chart2/source/tools/WeakListenerAdapter.cxx new file mode 100644 index 000000000000..bbb54e20bdce --- /dev/null +++ b/chart2/source/tools/WeakListenerAdapter.cxx @@ -0,0 +1,76 @@ +/************************************************************************* + * + * 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 "WeakListenerAdapter.hxx" + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::rtl::OUString; + +namespace chart +{ + +WeakModifyListenerAdapter::WeakModifyListenerAdapter( + const uno::WeakReference< util::XModifyListener > & xListener ) : + WeakListenerAdapter< ::com::sun::star::util::XModifyListener >( xListener ) +{} + +WeakModifyListenerAdapter::~WeakModifyListenerAdapter() +{} + +void SAL_CALL WeakModifyListenerAdapter::modified( const lang::EventObject& aEvent ) + throw (uno::RuntimeException) +{ + Reference< util::XModifyListener > xModListener( getListener() ); + if( xModListener.is()) + xModListener->modified( aEvent ); +} + +// -------------------------------------------------------------------------------- + +WeakSelectionChangeListenerAdapter::WeakSelectionChangeListenerAdapter( + const Reference< view::XSelectionChangeListener > & xListener ) : + WeakListenerAdapter< ::com::sun::star::view::XSelectionChangeListener >( xListener ) +{} + +WeakSelectionChangeListenerAdapter::~WeakSelectionChangeListenerAdapter() +{} + +void SAL_CALL WeakSelectionChangeListenerAdapter::selectionChanged( const lang::EventObject& aEvent ) + throw (uno::RuntimeException) +{ + Reference< view::XSelectionChangeListener > xSelChgListener( getListener() ); + if( xSelChgListener.is()) + xSelChgListener->selectionChanged( aEvent ); +} + +} // namespace chart diff --git a/chart2/source/tools/WrappedDefaultProperty.cxx b/chart2/source/tools/WrappedDefaultProperty.cxx new file mode 100644 index 000000000000..03178d204ef7 --- /dev/null +++ b/chart2/source/tools/WrappedDefaultProperty.cxx @@ -0,0 +1,92 @@ +/************************************************************************* + * + * 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 "WrappedDefaultProperty.hxx" +#include "macros.hxx" + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::rtl::OUString; + +namespace chart +{ + +WrappedDefaultProperty::WrappedDefaultProperty( + const OUString& rOuterName, const OUString& rInnerName, + const uno::Any& rNewOuterDefault ) : + WrappedProperty( rOuterName, rInnerName ), + m_aOuterDefaultValue( rNewOuterDefault ) +{} + +WrappedDefaultProperty::~WrappedDefaultProperty() +{} + +void WrappedDefaultProperty::setPropertyToDefault( + const Reference< beans::XPropertyState >& xInnerPropertyState ) const + throw (beans::UnknownPropertyException, + uno::RuntimeException) +{ + Reference< beans::XPropertySet > xInnerPropSet( xInnerPropertyState, uno::UNO_QUERY ); + if( xInnerPropSet.is()) + this->setPropertyValue( m_aOuterDefaultValue, xInnerPropSet ); +} + +uno::Any WrappedDefaultProperty::getPropertyDefault( + const Reference< beans::XPropertyState >& /* xInnerPropertyState */ ) const + throw (beans::UnknownPropertyException, + lang::WrappedTargetException, + uno::RuntimeException) +{ + return m_aOuterDefaultValue; +} + +beans::PropertyState WrappedDefaultProperty::getPropertyState( + const Reference< beans::XPropertyState >& xInnerPropertyState ) const + throw (beans::UnknownPropertyException, + uno::RuntimeException) +{ + beans::PropertyState aState = beans::PropertyState_DIRECT_VALUE; + try + { + Reference< beans::XPropertySet > xInnerProp( xInnerPropertyState, uno::UNO_QUERY_THROW ); + uno::Any aValue = this->getPropertyValue( xInnerProp ); + if( m_aOuterDefaultValue == this->convertInnerToOuterValue( aValue )) + aState = beans::PropertyState_DEFAULT_VALUE; + } + catch( beans::UnknownPropertyException& ex ) + { + ASSERT_EXCEPTION( ex ); + } + return aState; +} + +} // namespace chart diff --git a/chart2/source/tools/WrappedDirectStateProperty.cxx b/chart2/source/tools/WrappedDirectStateProperty.cxx new file mode 100644 index 000000000000..601b6e199d59 --- /dev/null +++ b/chart2/source/tools/WrappedDirectStateProperty.cxx @@ -0,0 +1,59 @@ +/************************************************************************* + * + * 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 "WrappedDirectStateProperty.hxx" +#include "macros.hxx" + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::rtl::OUString; + +namespace chart +{ + +WrappedDirectStateProperty::WrappedDirectStateProperty( + const OUString& rOuterName, const OUString& rInnerName ) : + WrappedProperty( rOuterName, rInnerName ) +{} + +WrappedDirectStateProperty::~WrappedDirectStateProperty() +{} + +beans::PropertyState WrappedDirectStateProperty::getPropertyState( + const Reference< beans::XPropertyState >& /* xInnerPropertyState */ ) const + throw (beans::UnknownPropertyException, + uno::RuntimeException) +{ + return beans::PropertyState_DIRECT_VALUE; +} + +} // namespace chart diff --git a/chart2/source/tools/WrappedIgnoreProperty.cxx b/chart2/source/tools/WrappedIgnoreProperty.cxx new file mode 100644 index 000000000000..aaa6c545a799 --- /dev/null +++ b/chart2/source/tools/WrappedIgnoreProperty.cxx @@ -0,0 +1,148 @@ +/************************************************************************* + * + * 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 "WrappedIgnoreProperty.hxx" +#include "macros.hxx" +#include <com/sun/star/awt/Gradient.hpp> +#include <com/sun/star/drawing/Hatch.hpp> +#include <com/sun/star/drawing/BitmapMode.hpp> +#include <com/sun/star/drawing/FillStyle.hpp> +#include <com/sun/star/drawing/LineDash.hpp> +#include <com/sun/star/drawing/LineJoint.hpp> +#include <com/sun/star/drawing/LineStyle.hpp> +#include <com/sun/star/drawing/RectanglePoint.hpp> + +using namespace ::com::sun::star; +using ::com::sun::star::uno::Any; +using ::com::sun::star::uno::Reference; +using ::rtl::OUString; + +//............................................................................. +namespace chart +{ +//............................................................................. + + +WrappedIgnoreProperty::WrappedIgnoreProperty( const OUString& rOuterName, const Any& rDefaultValue ) + : WrappedProperty( rOuterName, OUString() ) + , m_aDefaultValue( rDefaultValue ) + , m_aCurrentValue( rDefaultValue ) +{ +} +WrappedIgnoreProperty::~WrappedIgnoreProperty() +{ +} + +void WrappedIgnoreProperty::setPropertyValue( const Any& rOuterValue, const Reference< beans::XPropertySet >& /* xInnerPropertySet */ ) const + throw (beans::UnknownPropertyException, beans::PropertyVetoException, lang::IllegalArgumentException, lang::WrappedTargetException, uno::RuntimeException) +{ + m_aCurrentValue = rOuterValue; +} + +Any WrappedIgnoreProperty::getPropertyValue( const Reference< beans::XPropertySet >& /* xInnerPropertySet */ ) const + throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException) +{ + return m_aCurrentValue; +} + +void WrappedIgnoreProperty::setPropertyToDefault( const Reference< beans::XPropertyState >& /* xInnerPropertyState */ ) const + throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException) +{ + m_aCurrentValue = m_aDefaultValue; +} + +Any WrappedIgnoreProperty::getPropertyDefault( const Reference< beans::XPropertyState >& /* xInnerPropertyState */ ) const + throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException) +{ + return m_aDefaultValue; +} + +beans::PropertyState WrappedIgnoreProperty::getPropertyState( const Reference< beans::XPropertyState >& /* xInnerPropertyState */ ) const + throw (beans::UnknownPropertyException, uno::RuntimeException) +{ + return ( m_aCurrentValue == m_aDefaultValue + ? beans::PropertyState_DEFAULT_VALUE + : beans::PropertyState_DIRECT_VALUE ); +} + +//static +void WrappedIgnoreProperties::addIgnoreLineProperties( std::vector< WrappedProperty* >& rList ) +{ + rList.push_back( new WrappedIgnoreProperty( C2U( "LineStyle" ), uno::makeAny( drawing::LineStyle_SOLID ) ) ); +// rList.push_back( new WrappedIgnoreProperty( C2U( "LineDash" ), uno::makeAny( drawing::LineDash() ) ) ); + rList.push_back( new WrappedIgnoreProperty( C2U( "LineDashName" ), uno::makeAny( rtl::OUString() ) ) ); + rList.push_back( new WrappedIgnoreProperty( C2U( "LineColor" ), uno::makeAny( sal_Int32(0) ) ) ); + rList.push_back( new WrappedIgnoreProperty( C2U( "LineTransparence" ), uno::makeAny( sal_Int16(0) ) ) ); + rList.push_back( new WrappedIgnoreProperty( C2U( "LineWidth" ), uno::makeAny( sal_Int32(0) ) ) ); + rList.push_back( new WrappedIgnoreProperty( C2U( "LineJoint" ), uno::makeAny( drawing::LineJoint_ROUND ) ) ); +} + +//static +void WrappedIgnoreProperties::addIgnoreFillProperties( std::vector< WrappedProperty* >& rList ) +{ + addIgnoreFillProperties_without_BitmapProperties( rList ); + addIgnoreFillProperties_only_BitmapProperties( rList ); +} + +//static +void WrappedIgnoreProperties::addIgnoreFillProperties_without_BitmapProperties( ::std::vector< WrappedProperty* >& rList ) +{ + rList.push_back( new WrappedIgnoreProperty( C2U( "FillStyle" ), uno::makeAny( drawing::FillStyle_SOLID ) ) ); + rList.push_back( new WrappedIgnoreProperty( C2U( "FillColor" ), uno::makeAny( sal_Int32(-1) ) ) ); + rList.push_back( new WrappedIgnoreProperty( C2U( "FillTransparence" ), uno::makeAny( sal_Int16(0) ) ) ); + rList.push_back( new WrappedIgnoreProperty( C2U( "FillTransparenceGradientName" ), uno::makeAny( ::rtl::OUString() ) ) ); +// rList.push_back( new WrappedIgnoreProperty( C2U( "FillTransparenceGradient" ), uno::makeAny( awt::Gradient() ) ) ); + rList.push_back( new WrappedIgnoreProperty( C2U( "FillGradientName" ), uno::makeAny( ::rtl::OUString() ) ) ); +// rList.push_back( new WrappedIgnoreProperty( C2U( "FillGradient" ), uno::makeAny( awt::Gradient() ) ) ); + rList.push_back( new WrappedIgnoreProperty( C2U( "FillHatchName" ), uno::makeAny( ::rtl::OUString() ) ) ); +// rList.push_back( new WrappedIgnoreProperty( C2U( "FillHatch" ), uno::makeAny( drawing::Hatch() ) ) ); + rList.push_back( new WrappedIgnoreProperty( C2U( "FillBackground" ), uno::makeAny( sal_Bool(sal_False) ) ) ); +} + +//static +void WrappedIgnoreProperties::addIgnoreFillProperties_only_BitmapProperties( ::std::vector< WrappedProperty* >& rList ) +{ +// rList.push_back( new WrappedIgnoreProperty( C2U( "FillBitmapName" ), uno::makeAny( ::rtl::OUString() ) ) ); +// rList.push_back( new WrappedIgnoreProperty( C2U( "FillBitmap" ), uno::makeAny( uno::Reference< awt::XBitmap > (0) ) ) ); +// rList.push_back( new WrappedIgnoreProperty( C2U( "FillBitmapURL" ), uno::makeAny( ::rtl::OUString() ) ) ); + rList.push_back( new WrappedIgnoreProperty( C2U( "FillBitmapOffsetX" ), uno::makeAny( sal_Int16(0) ) ) ); + rList.push_back( new WrappedIgnoreProperty( C2U( "FillBitmapOffsetY" ), uno::makeAny( sal_Int16(0) ) ) ); + rList.push_back( new WrappedIgnoreProperty( C2U( "FillBitmapPositionOffsetX" ), uno::makeAny( sal_Int16(0) ) ) ); + rList.push_back( new WrappedIgnoreProperty( C2U( "FillBitmapPositionOffsetY" ), uno::makeAny( sal_Int16(0) ) ) ); + rList.push_back( new WrappedIgnoreProperty( C2U( "FillBitmapRectanglePoint" ), uno::makeAny( drawing::RectanglePoint_LEFT_TOP ) ) ); + rList.push_back( new WrappedIgnoreProperty( C2U( "FillBitmapLogicalSize" ), uno::makeAny( sal_Bool(sal_False) ) ) );//todo correct default? + rList.push_back( new WrappedIgnoreProperty( C2U( "FillBitmapSizeX" ), uno::makeAny( sal_Int32(10) ) ) );//todo which default? + rList.push_back( new WrappedIgnoreProperty( C2U( "FillBitmapSizeY" ), uno::makeAny( sal_Int32(10) ) ) );//todo which default? + rList.push_back( new WrappedIgnoreProperty( C2U( "FillBitmapMode" ), uno::makeAny( drawing::BitmapMode_REPEAT ) ) ); +} + +//............................................................................. +} //namespace chart +//............................................................................. diff --git a/chart2/source/tools/WrappedProperty.cxx b/chart2/source/tools/WrappedProperty.cxx new file mode 100644 index 000000000000..b41d8a331f11 --- /dev/null +++ b/chart2/source/tools/WrappedProperty.cxx @@ -0,0 +1,150 @@ +/************************************************************************* + * + * 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 "WrappedProperty.hxx" +#include "macros.hxx" +#include <com/sun/star/drawing/LineStyle.hpp> + +using namespace ::com::sun::star; +using ::com::sun::star::uno::Any; +using ::com::sun::star::uno::Reference; +using ::rtl::OUString; + + +//............................................................................. +namespace chart +{ +//............................................................................. + +WrappedProperty::WrappedProperty( const OUString& rOuterName, const OUString& rInnerName) + : m_aOuterName( rOuterName ) + , m_aInnerName( rInnerName ) +{ +} +WrappedProperty::~WrappedProperty() +{ +} + +const OUString& WrappedProperty::getOuterName() const +{ + return m_aOuterName; +} + +//virtual +::rtl::OUString WrappedProperty::getInnerName() const +{ + return m_aInnerName; +} + +Any WrappedProperty::convertInnerToOuterValue( const Any& rInnerValue ) const +{ + return rInnerValue; +} +Any WrappedProperty::convertOuterToInnerValue( const Any& rOuterValue ) const +{ + return rOuterValue; +} + +void WrappedProperty::setPropertyValue( const Any& rOuterValue, const Reference< beans::XPropertySet >& xInnerPropertySet ) const + throw (beans::UnknownPropertyException, beans::PropertyVetoException, lang::IllegalArgumentException, lang::WrappedTargetException, uno::RuntimeException) +{ + if(xInnerPropertySet.is()) + xInnerPropertySet->setPropertyValue( this->getInnerName(), this->convertOuterToInnerValue( rOuterValue ) ); +} + +Any WrappedProperty::getPropertyValue( const Reference< beans::XPropertySet >& xInnerPropertySet ) const + throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException) +{ + Any aRet; + if( xInnerPropertySet.is() ) + { + aRet = xInnerPropertySet->getPropertyValue( this->getInnerName() ); + aRet = this->convertInnerToOuterValue( aRet ); + } + return aRet; +} + +void WrappedProperty::setPropertyToDefault( const Reference< beans::XPropertyState >& xInnerPropertyState ) const + throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException) +{ + if( xInnerPropertyState.is() && this->getInnerName().getLength() ) + xInnerPropertyState->setPropertyToDefault(this->getInnerName()); + else + { + Reference< beans::XPropertySet > xInnerProp( xInnerPropertyState, uno::UNO_QUERY ); + setPropertyValue( getPropertyDefault( xInnerPropertyState ), xInnerProp ); + } +} + +Any WrappedProperty::getPropertyDefault( const Reference< beans::XPropertyState >& xInnerPropertyState ) const + throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException) +{ + Any aRet; + if( xInnerPropertyState.is() ) + { + aRet = xInnerPropertyState->getPropertyDefault( this->getInnerName() ); + aRet = this->convertInnerToOuterValue( aRet ); + } + return aRet; +} + +beans::PropertyState WrappedProperty::getPropertyState( const Reference< beans::XPropertyState >& xInnerPropertyState ) const + throw (beans::UnknownPropertyException, uno::RuntimeException) +{ + beans::PropertyState aState = beans::PropertyState_DIRECT_VALUE; + rtl::OUString aInnerName( this->getInnerName() ); + if( xInnerPropertyState.is() && aInnerName.getLength() ) + aState = xInnerPropertyState->getPropertyState( aInnerName ); + else + { + try + { + Reference< beans::XPropertySet > xInnerProp( xInnerPropertyState, uno::UNO_QUERY ); + uno::Any aValue = this->getPropertyValue( xInnerProp ); + if( !aValue.hasValue() ) + aState = beans::PropertyState_DEFAULT_VALUE; + else + { + uno::Any aDefault = this->getPropertyDefault( xInnerPropertyState ); + if( aValue == aDefault ) + aState = beans::PropertyState_DEFAULT_VALUE; + } + } + catch( beans::UnknownPropertyException& ex ) + { + ASSERT_EXCEPTION( ex ); + } + } + return aState; +} + +//............................................................................. +} //namespace chart +//............................................................................. diff --git a/chart2/source/tools/WrappedPropertySet.cxx b/chart2/source/tools/WrappedPropertySet.cxx new file mode 100644 index 000000000000..843aeb261a5f --- /dev/null +++ b/chart2/source/tools/WrappedPropertySet.cxx @@ -0,0 +1,495 @@ +/************************************************************************* + * + * 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 "WrappedPropertySet.hxx" +#include "macros.hxx" + +// header for define DELETEZ +#include <tools/solar.h> + +#include <tools/debug.hxx> + +//............................................................................. +namespace chart +{ +//............................................................................. + +using namespace ::com::sun::star; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::Any; +using ::rtl::OUString; + +WrappedPropertySet::WrappedPropertySet() + : MutexContainer() + , m_xInfo(0) + , m_pPropertyArrayHelper(0) + , m_pWrappedPropertyMap(0) +{ +} +WrappedPropertySet::~WrappedPropertySet() +{ + clearWrappedPropertySet(); +} + +Reference< beans::XPropertyState > WrappedPropertySet::getInnerPropertyState() +{ + return Reference< beans::XPropertyState >( getInnerPropertySet(), uno::UNO_QUERY ); +} + +void WrappedPropertySet::clearWrappedPropertySet() +{ + // /-- + ::osl::MutexGuard aGuard( m_aMutex ); + + //delete all wrapped properties + if(m_pWrappedPropertyMap) + { + for( tWrappedPropertyMap::iterator aIt = m_pWrappedPropertyMap->begin() + ; aIt!= m_pWrappedPropertyMap->end(); aIt++ ) + { + const WrappedProperty* pWrappedProperty = (*aIt).second; + DELETEZ(pWrappedProperty); + } + } + + DELETEZ(m_pPropertyArrayHelper); + DELETEZ(m_pWrappedPropertyMap); + + m_xInfo = NULL; + // \-- +} + +//XPropertySet +Reference< beans::XPropertySetInfo > SAL_CALL WrappedPropertySet::getPropertySetInfo( ) + throw (uno::RuntimeException) +{ + if( !m_xInfo.is() ) + { + // /-- + ::osl::MutexGuard aGuard( m_aMutex ); + if( !m_xInfo.is() ) + { + m_xInfo = ::cppu::OPropertySetHelper::createPropertySetInfo( getInfoHelper() ); + } + // \-- + } + return m_xInfo; +} + +void SAL_CALL WrappedPropertySet::setPropertyValue( const OUString& rPropertyName, const Any& rValue ) + throw (beans::UnknownPropertyException, beans::PropertyVetoException, lang::IllegalArgumentException, lang::WrappedTargetException, uno::RuntimeException) +{ + try + { + sal_Int32 nHandle = getInfoHelper().getHandleByName( rPropertyName ); + const WrappedProperty* pWrappedProperty = getWrappedProperty( nHandle ); + Reference< beans::XPropertySet > xInnerPropertySet( this->getInnerPropertySet() ); + if( pWrappedProperty ) + pWrappedProperty->setPropertyValue( rValue, xInnerPropertySet ); + else if( xInnerPropertySet.is() ) + xInnerPropertySet->setPropertyValue( rPropertyName, rValue ); + else + { +#if OSL_DEBUG_LEVEL > 1 + DBG_ERROR("found no inner property set to map to"); +#endif + } + } + catch( beans::UnknownPropertyException& ex ) + { + throw ex; + } + catch( beans::PropertyVetoException& ex ) + { + throw ex; + } + catch( lang::IllegalArgumentException& ex ) + { + throw ex; + } + catch( lang::WrappedTargetException& ex ) + { + throw ex; + } + catch( uno::RuntimeException& ex ) + { + throw ex; + } + catch( uno::Exception& ex ) + { + OSL_ENSURE(false,"invalid exception caught in WrappedPropertySet::setPropertyValue"); + lang::WrappedTargetException aWrappedException; + aWrappedException.TargetException = uno::makeAny( ex ); + throw aWrappedException; + } +} +Any SAL_CALL WrappedPropertySet::getPropertyValue( const OUString& rPropertyName ) + throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException) +{ + Any aRet; + + try + { + sal_Int32 nHandle = getInfoHelper().getHandleByName( rPropertyName ); + const WrappedProperty* pWrappedProperty = getWrappedProperty( nHandle ); + Reference< beans::XPropertySet > xInnerPropertySet( this->getInnerPropertySet() ); + if( pWrappedProperty ) + aRet = pWrappedProperty->getPropertyValue( xInnerPropertySet ); + else if( xInnerPropertySet.is() ) + aRet = xInnerPropertySet->getPropertyValue( rPropertyName ); + else + { +#if OSL_DEBUG_LEVEL > 1 + DBG_ERROR("found no inner property set to map to"); +#endif + } + } + catch( beans::UnknownPropertyException& ex ) + { + throw ex; + } + catch( lang::WrappedTargetException& ex ) + { + throw ex; + } + catch( uno::RuntimeException& ex ) + { + throw ex; + } + catch( uno::Exception& ex ) + { + OSL_ENSURE(false,"invalid exception caught in WrappedPropertySet::setPropertyValue"); + lang::WrappedTargetException aWrappedException; + aWrappedException.TargetException = uno::makeAny( ex ); + throw aWrappedException; + } + + return aRet; +} + +void SAL_CALL WrappedPropertySet::addPropertyChangeListener( const OUString& rPropertyName, const Reference< beans::XPropertyChangeListener >& xListener ) + throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException) +{ + Reference< beans::XPropertySet > xInnerPropertySet( this->getInnerPropertySet() ); + if( xInnerPropertySet.is() ) + { + const WrappedProperty* pWrappedProperty = getWrappedProperty( rPropertyName ); + if( pWrappedProperty ) + xInnerPropertySet->addPropertyChangeListener( pWrappedProperty->getInnerName(), xListener ); + else + xInnerPropertySet->addPropertyChangeListener( rPropertyName, xListener ); + } +// m_aBoundListenerContainer.addInterface( (sal_Int32)nHandle, xListener ); +} +void SAL_CALL WrappedPropertySet::removePropertyChangeListener( const OUString& rPropertyName, const Reference< beans::XPropertyChangeListener >& aListener ) + throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException) +{ + Reference< beans::XPropertySet > xInnerPropertySet( this->getInnerPropertySet() ); + if( xInnerPropertySet.is() ) + { + const WrappedProperty* pWrappedProperty = getWrappedProperty( rPropertyName ); + if( pWrappedProperty ) + xInnerPropertySet->removePropertyChangeListener( pWrappedProperty->getInnerName(), aListener ); + else + xInnerPropertySet->removePropertyChangeListener( rPropertyName, aListener ); + } +} +void SAL_CALL WrappedPropertySet::addVetoableChangeListener( const OUString& rPropertyName, const Reference< beans::XVetoableChangeListener >& aListener ) + throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException) +{ + Reference< beans::XPropertySet > xInnerPropertySet( this->getInnerPropertySet() ); + if( xInnerPropertySet.is() ) + { + const WrappedProperty* pWrappedProperty = getWrappedProperty( rPropertyName ); + if( pWrappedProperty ) + xInnerPropertySet->addVetoableChangeListener( pWrappedProperty->getInnerName(), aListener ); + else + xInnerPropertySet->addVetoableChangeListener( rPropertyName, aListener ); + } +} +void SAL_CALL WrappedPropertySet::removeVetoableChangeListener( const OUString& rPropertyName, const Reference< beans::XVetoableChangeListener >& aListener ) + throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException) +{ + Reference< beans::XPropertySet > xInnerPropertySet( this->getInnerPropertySet() ); + if( xInnerPropertySet.is() ) + { + const WrappedProperty* pWrappedProperty = getWrappedProperty( rPropertyName ); + if( pWrappedProperty ) + xInnerPropertySet->removeVetoableChangeListener( pWrappedProperty->getInnerName(), aListener ); + else + xInnerPropertySet->removeVetoableChangeListener( rPropertyName, aListener ); + } +} + +//XMultiPropertySet +void SAL_CALL WrappedPropertySet::setPropertyValues( const Sequence< OUString >& rNameSeq, const Sequence< Any >& rValueSeq ) + throw (beans::PropertyVetoException, lang::IllegalArgumentException, lang::WrappedTargetException, uno::RuntimeException) +{ + bool bUnknownProperty = false; + sal_Int32 nMinCount = std::min( rValueSeq.getLength(), rNameSeq.getLength() ); + for(sal_Int32 nN=0; nN<nMinCount; nN++) + { + ::rtl::OUString aPropertyName( rNameSeq[nN] ); + try + { + this->setPropertyValue( aPropertyName, rValueSeq[nN] ); + } + catch( beans::UnknownPropertyException& ex ) + { + ASSERT_EXCEPTION( ex ); + bUnknownProperty = true; + } + } + //todo: store unknown properties elsewhere +// if( bUnknownProperty ) +// throw beans::UnknownPropertyException(); +} +Sequence< Any > SAL_CALL WrappedPropertySet::getPropertyValues( const Sequence< OUString >& rNameSeq ) + throw (uno::RuntimeException) +{ + Sequence< Any > aRetSeq; + if( rNameSeq.getLength() ) + { + aRetSeq.realloc( rNameSeq.getLength() ); + for(sal_Int32 nN=0; nN<rNameSeq.getLength(); nN++) + { + try + { + ::rtl::OUString aPropertyName( rNameSeq[nN] ); + aRetSeq[nN] = this->getPropertyValue( aPropertyName ); + } + catch( beans::UnknownPropertyException& ex ) + { + ASSERT_EXCEPTION( ex ); + } + catch( lang::WrappedTargetException& ex ) + { + ASSERT_EXCEPTION( ex ); + } + } + } + return aRetSeq; +} +void SAL_CALL WrappedPropertySet::addPropertiesChangeListener( const Sequence< OUString >& /* rNameSeq */, const Reference< beans::XPropertiesChangeListener >& /* xListener */ ) + throw (uno::RuntimeException) +{ + OSL_ENSURE(false,"not implemented yet"); + //todo +} +void SAL_CALL WrappedPropertySet::removePropertiesChangeListener( const Reference< beans::XPropertiesChangeListener >& /* xListener */ ) + throw (uno::RuntimeException) +{ + OSL_ENSURE(false,"not implemented yet"); + //todo +} +void SAL_CALL WrappedPropertySet::firePropertiesChangeEvent( const Sequence< OUString >& /* rNameSeq */, const Reference< beans::XPropertiesChangeListener >& /* xListener */ ) + throw (uno::RuntimeException) +{ + OSL_ENSURE(false,"not implemented yet"); + //todo +} + +//XPropertyState +beans::PropertyState SAL_CALL WrappedPropertySet::getPropertyState( const OUString& rPropertyName ) + throw (beans::UnknownPropertyException, uno::RuntimeException) +{ + beans::PropertyState aState( beans::PropertyState_DIRECT_VALUE ); + + Reference< beans::XPropertyState > xInnerPropertyState( this->getInnerPropertyState() ); + if( xInnerPropertyState.is() ) + { + const WrappedProperty* pWrappedProperty = getWrappedProperty( rPropertyName ); + if( pWrappedProperty ) + aState = pWrappedProperty->getPropertyState( xInnerPropertyState ); + else + aState = xInnerPropertyState->getPropertyState( rPropertyName ); + } + return aState; +} + +const WrappedProperty* WrappedPropertySet::getWrappedProperty( const ::rtl::OUString& rOuterName ) +{ + sal_Int32 nHandle = getInfoHelper().getHandleByName( rOuterName ); + return getWrappedProperty( nHandle ); +} + +const WrappedProperty* WrappedPropertySet::getWrappedProperty( sal_Int32 nHandle ) +{ + tWrappedPropertyMap::const_iterator aFound( getWrappedPropertyMap().find( nHandle ) ); + if( aFound != getWrappedPropertyMap().end() ) + return (*aFound).second; + return 0; +} + +Sequence< beans::PropertyState > SAL_CALL WrappedPropertySet::getPropertyStates( const Sequence< OUString >& rNameSeq ) + throw (beans::UnknownPropertyException, uno::RuntimeException) +{ + Sequence< beans::PropertyState > aRetSeq; + if( rNameSeq.getLength() ) + { + aRetSeq.realloc( rNameSeq.getLength() ); + for(sal_Int32 nN=0; nN<rNameSeq.getLength(); nN++) + { + ::rtl::OUString aPropertyName( rNameSeq[nN] ); + aRetSeq[nN] = this->getPropertyState( aPropertyName ); + } + } + return aRetSeq; +} + +void SAL_CALL WrappedPropertySet::setPropertyToDefault( const OUString& rPropertyName ) + throw (beans::UnknownPropertyException, uno::RuntimeException) +{ + Reference< beans::XPropertyState > xInnerPropertyState( this->getInnerPropertyState() ); + if( xInnerPropertyState.is() ) + { + const WrappedProperty* pWrappedProperty = getWrappedProperty( rPropertyName ); + if( pWrappedProperty ) + pWrappedProperty->setPropertyToDefault( xInnerPropertyState ); + else + xInnerPropertyState->setPropertyToDefault( rPropertyName ); + } +} +Any SAL_CALL WrappedPropertySet::getPropertyDefault( const OUString& rPropertyName ) + throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException) +{ + Any aRet; + Reference< beans::XPropertyState > xInnerPropertyState( this->getInnerPropertyState() ); + if( xInnerPropertyState.is() ) + { + const WrappedProperty* pWrappedProperty = getWrappedProperty( rPropertyName ); + if( pWrappedProperty ) + aRet = pWrappedProperty->getPropertyDefault(xInnerPropertyState); + else + aRet = xInnerPropertyState->getPropertyDefault( rPropertyName ); + } + return aRet; +} + +//XMultiPropertyStates +void SAL_CALL WrappedPropertySet::setAllPropertiesToDefault( ) + throw (uno::RuntimeException) +{ + const Sequence< beans::Property >& rPropSeq = getPropertySequence(); + for(sal_Int32 nN=0; nN<rPropSeq.getLength(); nN++) + { + ::rtl::OUString aPropertyName( rPropSeq[nN].Name ); + this->setPropertyToDefault( aPropertyName ); + } +} +void SAL_CALL WrappedPropertySet::setPropertiesToDefault( const Sequence< OUString >& rNameSeq ) + throw (beans::UnknownPropertyException, uno::RuntimeException) +{ + for(sal_Int32 nN=0; nN<rNameSeq.getLength(); nN++) + { + ::rtl::OUString aPropertyName( rNameSeq[nN] ); + this->setPropertyToDefault( aPropertyName ); + } +} +Sequence< Any > SAL_CALL WrappedPropertySet::getPropertyDefaults( const Sequence< OUString >& rNameSeq ) + throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException) +{ + Sequence< Any > aRetSeq; + if( rNameSeq.getLength() ) + { + aRetSeq.realloc( rNameSeq.getLength() ); + for(sal_Int32 nN=0; nN<rNameSeq.getLength(); nN++) + { + ::rtl::OUString aPropertyName( rNameSeq[nN] ); + aRetSeq[nN] = this->getPropertyDefault( aPropertyName ); + } + } + return aRetSeq; +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + +::cppu::IPropertyArrayHelper& WrappedPropertySet::getInfoHelper() +{ + if(!m_pPropertyArrayHelper) + { + // /-- + ::osl::MutexGuard aGuard( m_aMutex ); + if(!m_pPropertyArrayHelper) + { + sal_Bool bSorted = sal_True; + m_pPropertyArrayHelper = new ::cppu::OPropertyArrayHelper( getPropertySequence(), bSorted ); + } + // \-- + } + return *m_pPropertyArrayHelper; +} + +//----------------------------------------------------------------------------- + +tWrappedPropertyMap& WrappedPropertySet::getWrappedPropertyMap() +{ + if(!m_pWrappedPropertyMap) + { + // /-- + ::osl::MutexGuard aGuard( m_aMutex ); + if(!m_pWrappedPropertyMap) + { + std::vector< WrappedProperty* > aPropList( createWrappedProperties() ); + m_pWrappedPropertyMap = new tWrappedPropertyMap(); + + for( std::vector< WrappedProperty* >::const_iterator aIt = aPropList.begin(); aIt!=aPropList.end(); ++aIt ) + { + WrappedProperty* pProperty = *aIt; + if(pProperty) + { + sal_Int32 nHandle = getInfoHelper().getHandleByName( pProperty->getOuterName() ); + + if( nHandle == -1 ) + { + OSL_ENSURE( false, "missing property in property list" ); + delete pProperty;//we are owner or the created WrappedProperties + } + else if( m_pWrappedPropertyMap->find( nHandle ) != m_pWrappedPropertyMap->end() ) + { + //duplicate Wrapped property + OSL_ENSURE( false, "duplicate Wrapped property" ); + delete pProperty;//we are owner or the created WrappedProperties + } + else + (*m_pWrappedPropertyMap)[ nHandle ] = pProperty; + } + } + } + // \-- + } + return *m_pWrappedPropertyMap; +} + +//............................................................................. +} //namespace chart +//............................................................................. diff --git a/chart2/source/tools/XMLRangeHelper.cxx b/chart2/source/tools/XMLRangeHelper.cxx new file mode 100644 index 000000000000..c5d345db0124 --- /dev/null +++ b/chart2/source/tools/XMLRangeHelper.cxx @@ -0,0 +1,418 @@ +/************************************************************************* + * + * 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 "XMLRangeHelper.hxx" +#include <unotools/charclass.hxx> +#include <rtl/ustrbuf.hxx> + +#include <algorithm> +#include <functional> + +using ::rtl::OUString; +using ::rtl::OUStringBuffer; + +// ================================================================================ + +namespace +{ +/** unary function that escapes backslashes and single quotes in a sal_Unicode + array (which you can get from an OUString with getStr()) and puts the result + into the OUStringBuffer given in the CTOR + */ +class lcl_Escape : public ::std::unary_function< sal_Unicode, void > +{ +public: + lcl_Escape( ::rtl::OUStringBuffer & aResultBuffer ) : m_aResultBuffer( aResultBuffer ) {} + void operator() ( sal_Unicode aChar ) + { + static const sal_Unicode m_aQuote( '\'' ); + static const sal_Unicode m_aBackslash( '\\' ); + + if( aChar == m_aQuote || + aChar == m_aBackslash ) + m_aResultBuffer.append( m_aBackslash ); + m_aResultBuffer.append( aChar ); + } + +private: + ::rtl::OUStringBuffer & m_aResultBuffer; +}; + +// ---------------------------------------- + +/** unary function that removes backslash escapes in a sal_Unicode array (which + you can get from an OUString with getStr()) and puts the result into the + OUStringBuffer given in the CTOR + */ +class lcl_UnEscape : public ::std::unary_function< sal_Unicode, void > +{ +public: + lcl_UnEscape( ::rtl::OUStringBuffer & aResultBuffer ) : m_aResultBuffer( aResultBuffer ) {} + void operator() ( sal_Unicode aChar ) + { + static const sal_Unicode m_aBackslash( '\\' ); + + if( aChar != m_aBackslash ) + m_aResultBuffer.append( aChar ); + } + +private: + ::rtl::OUStringBuffer & m_aResultBuffer; +}; + +// ---------------------------------------- + +OUStringBuffer lcl_getXMLStringForCell( const ::chart::XMLRangeHelper::Cell & rCell ) +{ + ::rtl::OUStringBuffer aBuffer; + if( rCell.empty()) + return aBuffer; + + sal_Int32 nCol = rCell.nColumn; + aBuffer.append( (sal_Unicode)'.' ); + if( ! rCell.bRelativeColumn ) + aBuffer.append( (sal_Unicode)'$' ); + + // get A, B, C, ..., AA, AB, ... representation of column number + if( nCol < 26 ) + aBuffer.append( (sal_Unicode)('A' + nCol) ); + else if( nCol < 702 ) + { + aBuffer.append( (sal_Unicode)('A' + nCol / 26 - 1 )); + aBuffer.append( (sal_Unicode)('A' + nCol % 26) ); + } + else // works for nCol <= 18,278 + { + aBuffer.append( (sal_Unicode)('A' + nCol / 702 - 1 )); + aBuffer.append( (sal_Unicode)('A' + (nCol % 702) / 26 )); + aBuffer.append( (sal_Unicode)('A' + nCol % 26) ); + } + + // write row number as number + if( ! rCell.bRelativeRow ) + aBuffer.append( (sal_Unicode)'$' ); + aBuffer.append( rCell.nRow + (sal_Int32)1 ); + + return aBuffer; +} + +void lcl_getSingleCellAddressFromXMLString( + const ::rtl::OUString& rXMLString, + sal_Int32 nStartPos, sal_Int32 nEndPos, + ::chart::XMLRangeHelper::Cell & rOutCell ) +{ + // expect "\$?[a-zA-Z]+\$?[1-9][0-9]*" + static const sal_Unicode aDollar( '$' ); + static const sal_Unicode aLetterA( 'A' ); + + ::rtl::OUString aCellStr = rXMLString.copy( nStartPos, nEndPos - nStartPos + 1 ).toAsciiUpperCase(); + const sal_Unicode* pStrArray = aCellStr.getStr(); + sal_Int32 nLength = aCellStr.getLength(); + sal_Int32 i = nLength - 1, nColumn = 0; + + // parse number for row + while( CharClass::isAsciiDigit( pStrArray[ i ] ) && i >= 0 ) + i--; + rOutCell.nRow = (aCellStr.copy( i + 1 )).toInt32() - 1; + // a dollar in XML means absolute (whereas in UI it means relative) + if( pStrArray[ i ] == aDollar ) + { + i--; + rOutCell.bRelativeRow = false; + } + else + rOutCell.bRelativeRow = true; + + // parse rest for column + sal_Int32 nPower = 1; + while( CharClass::isAsciiAlpha( pStrArray[ i ] )) + { + nColumn += (pStrArray[ i ] - aLetterA + 1) * nPower; + i--; + nPower *= 26; + } + rOutCell.nColumn = nColumn - 1; + + rOutCell.bRelativeColumn = true; + if( i >= 0 && + pStrArray[ i ] == aDollar ) + rOutCell.bRelativeColumn = false; + rOutCell.bIsEmpty = false; +} + +bool lcl_getCellAddressFromXMLString( + const ::rtl::OUString& rXMLString, + sal_Int32 nStartPos, sal_Int32 nEndPos, + ::chart::XMLRangeHelper::Cell & rOutCell, + ::rtl::OUString& rOutTableName ) +{ + static const sal_Unicode aDot( '.' ); + static const sal_Unicode aQuote( '\'' ); + static const sal_Unicode aBackslash( '\\' ); + + sal_Int32 nNextDelimiterPos = nStartPos; + + sal_Int32 nDelimiterPos = nStartPos; + bool bInQuotation = false; + // parse table name + while( nDelimiterPos < nEndPos && + ( bInQuotation || rXMLString[ nDelimiterPos ] != aDot )) + { + // skip escaped characters (with backslash) + if( rXMLString[ nDelimiterPos ] == aBackslash ) + ++nDelimiterPos; + // toggle quotation mode when finding single quotes + else if( rXMLString[ nDelimiterPos ] == aQuote ) + bInQuotation = ! bInQuotation; + + ++nDelimiterPos; + } + + if( nDelimiterPos == -1 ) + return false; + + if( nDelimiterPos > nStartPos && nDelimiterPos < nEndPos ) + { + // there is a table name before the address + + ::rtl::OUStringBuffer aTableNameBuffer; + const sal_Unicode * pTableName = rXMLString.getStr(); + + // remove escapes from table name + ::std::for_each( pTableName + nStartPos, + pTableName + nDelimiterPos, + lcl_UnEscape( aTableNameBuffer )); + + // unquote quoted table name + const sal_Unicode * pBuf = aTableNameBuffer.getStr(); + if( pBuf[ 0 ] == aQuote && + pBuf[ aTableNameBuffer.getLength() - 1 ] == aQuote ) + { + ::rtl::OUString aName = aTableNameBuffer.makeStringAndClear(); + rOutTableName = aName.copy( 1, aName.getLength() - 2 ); + } + else + rOutTableName = aTableNameBuffer.makeStringAndClear(); + } + else + nDelimiterPos = nStartPos; + + for( sal_Int32 i = 0; + nNextDelimiterPos < nEndPos; + nDelimiterPos = nNextDelimiterPos, i++ ) + { + nNextDelimiterPos = rXMLString.indexOf( aDot, nDelimiterPos + 1 ); + if( nNextDelimiterPos == -1 || + nNextDelimiterPos > nEndPos ) + nNextDelimiterPos = nEndPos + 1; + + if( i==0 ) + // only take first cell + lcl_getSingleCellAddressFromXMLString( + rXMLString, nDelimiterPos + 1, nNextDelimiterPos - 1, rOutCell ); + } + + return true; +} + +bool lcl_getCellRangeAddressFromXMLString( + const ::rtl::OUString& rXMLString, + sal_Int32 nStartPos, sal_Int32 nEndPos, + ::chart::XMLRangeHelper::CellRange & rOutRange ) +{ + bool bResult = true; + static const sal_Unicode aColon( ':' ); + static const sal_Unicode aQuote( '\'' ); + static const sal_Unicode aBackslash( '\\' ); + + sal_Int32 nDelimiterPos = nStartPos; + bool bInQuotation = false; + // parse table name + while( nDelimiterPos < nEndPos && + ( bInQuotation || rXMLString[ nDelimiterPos ] != aColon )) + { + // skip escaped characters (with backslash) + if( rXMLString[ nDelimiterPos ] == aBackslash ) + ++nDelimiterPos; + // toggle quotation mode when finding single quotes + else if( rXMLString[ nDelimiterPos ] == aQuote ) + bInQuotation = ! bInQuotation; + + ++nDelimiterPos; + } + + if( nDelimiterPos == nEndPos ) + { + // only one cell + bResult = lcl_getCellAddressFromXMLString( rXMLString, nStartPos, nEndPos, + rOutRange.aUpperLeft, + rOutRange.aTableName ); + if( !rOutRange.aTableName.getLength() ) + bResult = false; + } + else + { + // range (separated by a colon) + bResult = lcl_getCellAddressFromXMLString( rXMLString, nStartPos, nDelimiterPos - 1, + rOutRange.aUpperLeft, + rOutRange.aTableName ); + if( !rOutRange.aTableName.getLength() ) + bResult = false; + + ::rtl::OUString sTableSecondName; + if( bResult ) + { + bResult = lcl_getCellAddressFromXMLString( rXMLString, nDelimiterPos + 1, nEndPos, + rOutRange.aLowerRight, + sTableSecondName ); + } + if( bResult && + sTableSecondName.getLength() && + ! sTableSecondName.equals( rOutRange.aTableName )) + bResult = false; + } + + return bResult; +} + +} // anonymous namespace + +// ================================================================================ + +namespace chart +{ +namespace XMLRangeHelper +{ + +CellRange getCellRangeFromXMLString( const OUString & rXMLString ) +{ + static const sal_Unicode aSpace( ' ' ); + static const sal_Unicode aQuote( '\'' ); +// static const sal_Unicode aDoubleQuote( '\"' ); + static const sal_Unicode aDollar( '$' ); + static const sal_Unicode aBackslash( '\\' ); + + sal_Int32 nStartPos = 0; + sal_Int32 nEndPos = nStartPos; + const sal_Int32 nLength = rXMLString.getLength(); + + // reset + CellRange aResult; + + // iterate over different ranges + for( sal_Int32 i = 0; + nEndPos < nLength; + nStartPos = ++nEndPos, i++ ) + { + // find start point of next range + + // ignore leading '$' + if( rXMLString[ nEndPos ] == aDollar) + nEndPos++; + + bool bInQuotation = false; + // parse range + while( nEndPos < nLength && + ( bInQuotation || rXMLString[ nEndPos ] != aSpace )) + { + // skip escaped characters (with backslash) + if( rXMLString[ nEndPos ] == aBackslash ) + ++nEndPos; + // toggle quotation mode when finding single quotes + else if( rXMLString[ nEndPos ] == aQuote ) + bInQuotation = ! bInQuotation; + + ++nEndPos; + } + + if( ! lcl_getCellRangeAddressFromXMLString( + rXMLString, + nStartPos, nEndPos - 1, + aResult )) + { + // if an error occured, bail out + return CellRange(); + } + } + + return aResult; +} + +OUString getXMLStringFromCellRange( const CellRange & rRange ) +{ + static const sal_Unicode aSpace( ' ' ); + static const sal_Unicode aQuote( '\'' ); + + ::rtl::OUStringBuffer aBuffer; + + if( (rRange.aTableName).getLength()) + { + bool bNeedsEscaping = ( rRange.aTableName.indexOf( aQuote ) > -1 ); + bool bNeedsQuoting = bNeedsEscaping || ( rRange.aTableName.indexOf( aSpace ) > -1 ); + + // quote table name if it contains spaces or quotes + if( bNeedsQuoting ) + { + // leading quote + aBuffer.append( aQuote ); + + // escape existing quotes + if( bNeedsEscaping ) + { + const sal_Unicode * pTableNameBeg = rRange.aTableName.getStr(); + + // append the quoted string at the buffer + ::std::for_each( pTableNameBeg, + pTableNameBeg + rRange.aTableName.getLength(), + lcl_Escape( aBuffer ) ); + } + else + aBuffer.append( rRange.aTableName ); + + // final quote + aBuffer.append( aQuote ); + } + else + aBuffer.append( rRange.aTableName ); + } + aBuffer.append( lcl_getXMLStringForCell( rRange.aUpperLeft )); + + if( ! rRange.aLowerRight.empty()) + { + // we have a range (not a single cell) + aBuffer.append( sal_Unicode( ':' )); + aBuffer.append( lcl_getXMLStringForCell( rRange.aLowerRight )); + } + + return aBuffer.makeStringAndClear(); +} + +} // namespace XMLRangeHelper +} // namespace chart diff --git a/chart2/source/tools/_serviceregistration_tools.cxx b/chart2/source/tools/_serviceregistration_tools.cxx new file mode 100644 index 000000000000..387b87dfab5a --- /dev/null +++ b/chart2/source/tools/_serviceregistration_tools.cxx @@ -0,0 +1,200 @@ +/************************************************************************* + * + * 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 <cppuhelper/implementationentry.hxx> +#include "LabeledDataSequence.hxx" +#include "CachedDataSequence.hxx" +#include "DataSource.hxx" +#include "ConfigColorScheme.hxx" +#include "Scaling.hxx" +#include "ErrorBar.hxx" +#include "RegressionCurveModel.hxx" +#include "RegressionEquation.hxx" +#include "InternalDataProvider.hxx" +#include "charttoolsdllapi.hxx" + +static struct ::cppu::ImplementationEntry g_entries_chart2_tools[] = +{ + { + ::chart::LabeledDataSequence::create + , ::chart::LabeledDataSequence::getImplementationName_Static + , ::chart::LabeledDataSequence::getSupportedServiceNames_Static + , ::cppu::createSingleComponentFactory + , 0 + , 0 + } + ,{ + ::chart::CachedDataSequence::create + , ::chart::CachedDataSequence::getImplementationName_Static + , ::chart::CachedDataSequence::getSupportedServiceNames_Static + , ::cppu::createSingleComponentFactory + , 0 + , 0 + } + ,{ + ::chart::DataSource::create + , ::chart::DataSource::getImplementationName_Static + , ::chart::DataSource::getSupportedServiceNames_Static + , ::cppu::createSingleComponentFactory + , 0 + , 0 + } + ,{ + ::chart::ConfigColorScheme::create + , ::chart::ConfigColorScheme::getImplementationName_Static + , ::chart::ConfigColorScheme::getSupportedServiceNames_Static + , ::cppu::createSingleComponentFactory + , 0 + , 0 + } + + ,{ + ::chart::LogarithmicScaling::create + , ::chart::LogarithmicScaling::getImplementationName_Static + , ::chart::LogarithmicScaling::getSupportedServiceNames_Static + , ::cppu::createSingleComponentFactory + , 0 + , 0 + } + ,{ + ::chart::ExponentialScaling::create + , ::chart::ExponentialScaling::getImplementationName_Static + , ::chart::ExponentialScaling::getSupportedServiceNames_Static + , ::cppu::createSingleComponentFactory + , 0 + , 0 + } + ,{ + ::chart::LinearScaling::create + , ::chart::LinearScaling::getImplementationName_Static + , ::chart::LinearScaling::getSupportedServiceNames_Static + , ::cppu::createSingleComponentFactory + , 0 + , 0 + } + ,{ + ::chart::PowerScaling::create + , ::chart::PowerScaling::getImplementationName_Static + , ::chart::PowerScaling::getSupportedServiceNames_Static + , ::cppu::createSingleComponentFactory + , 0 + , 0 + } + ,{ + ::chart::ErrorBar::create + , ::chart::ErrorBar::getImplementationName_Static + , ::chart::ErrorBar::getSupportedServiceNames_Static + , ::cppu::createSingleComponentFactory + , 0 + , 0 + } + ,{ + ::chart::MeanValueRegressionCurve::create + , ::chart::MeanValueRegressionCurve::getImplementationName_Static + , ::chart::MeanValueRegressionCurve::getSupportedServiceNames_Static + , ::cppu::createSingleComponentFactory + , 0 + , 0 + } + ,{ + ::chart::LinearRegressionCurve::create + , ::chart::LinearRegressionCurve::getImplementationName_Static + , ::chart::LinearRegressionCurve::getSupportedServiceNames_Static + , ::cppu::createSingleComponentFactory + , 0 + , 0 + } + ,{ + ::chart::LogarithmicRegressionCurve::create + , ::chart::LogarithmicRegressionCurve::getImplementationName_Static + , ::chart::LogarithmicRegressionCurve::getSupportedServiceNames_Static + , ::cppu::createSingleComponentFactory + , 0 + , 0 + } + ,{ + ::chart::ExponentialRegressionCurve::create + , ::chart::ExponentialRegressionCurve::getImplementationName_Static + , ::chart::ExponentialRegressionCurve::getSupportedServiceNames_Static + , ::cppu::createSingleComponentFactory + , 0 + , 0 + } + ,{ + ::chart::PotentialRegressionCurve::create + , ::chart::PotentialRegressionCurve::getImplementationName_Static + , ::chart::PotentialRegressionCurve::getSupportedServiceNames_Static + , ::cppu::createSingleComponentFactory + , 0 + , 0 + } + ,{ + ::chart::RegressionEquation::create + , ::chart::RegressionEquation::getImplementationName_Static + , ::chart::RegressionEquation::getSupportedServiceNames_Static + , ::cppu::createSingleComponentFactory + , 0 + , 0 + } + ,{ + ::chart::InternalDataProvider::create + , ::chart::InternalDataProvider::getImplementationName_Static + , ::chart::InternalDataProvider::getSupportedServiceNames_Static + , ::cppu::createSingleComponentFactory + , 0 + , 0 + } + ,{ 0, 0, 0, 0, 0, 0 } +}; + +// component exports +extern "C" +{ +//================================================================================================== +OOO_DLLPUBLIC_CHARTTOOLS void SAL_CALL component_getImplementationEnvironment( + const sal_Char ** ppEnvTypeName, uno_Environment ** /* ppEnv */ ) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} +//================================================================================================== +OOO_DLLPUBLIC_CHARTTOOLS sal_Bool SAL_CALL component_writeInfo( + void * pServiceManager, void * pRegistryKey ) +{ + return ::cppu::component_writeInfoHelper( + pServiceManager, pRegistryKey, g_entries_chart2_tools ); +} +//================================================================================================== +OOO_DLLPUBLIC_CHARTTOOLS void * SAL_CALL component_getFactory( + const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey ) +{ + return ::cppu::component_getFactoryHelper( + pImplName, pServiceManager, pRegistryKey , g_entries_chart2_tools ); +} +} +//========================================================================= diff --git a/chart2/source/tools/exports.flt b/chart2/source/tools/exports.flt new file mode 100644 index 000000000000..376659ce91b7 --- /dev/null +++ b/chart2/source/tools/exports.flt @@ -0,0 +1,3 @@ +_real@ +_TI1 +_TI2 diff --git a/chart2/source/tools/makefile.mk b/chart2/source/tools/makefile.mk new file mode 100644 index 000000000000..2f990af7adb0 --- /dev/null +++ b/chart2/source/tools/makefile.mk @@ -0,0 +1,189 @@ +#************************************************************************* +# +# 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. +# +#************************************************************************* + +PRJ= ..$/.. +PRJNAME= chart2 +TARGET= charttools + +PRJINC= $(PRJ)$/source + +USE_DEFFILE= TRUE +ENABLE_EXCEPTIONS= TRUE +VISIBILITY_HIDDEN= TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE: $(PRJ)$/util$/makefile.pmk + +CDEFS += -DOOO_DLLIMPLEMENTATION_CHARTTOOLS + +# --- export library ------------------------------------------------- + +#You can use several library macros of this form to build libraries that +#do not consist of all object files in a directory or to merge different libraries. +#LIB1TARGET= $(SLB)$/_$(TARGET).lib + +#Specifies object files to bind into linked libraries. +SLOFILES= \ + $(SLO)$/ErrorBar.obj \ + $(SLO)$/TrueGuard.obj \ + $(SLO)$/LifeTime.obj \ + $(SLO)$/MediaDescriptorHelper.obj \ + $(SLO)$/ConfigColorScheme.obj \ + $(SLO)$/ColorPerPointHelper.obj \ + $(SLO)$/ObjectIdentifier.obj \ + $(SLO)$/CachedDataSequence.obj \ + $(SLO)$/CommonConverters.obj \ + $(SLO)$/DataSeriesHelper.obj \ + $(SLO)$/DataSource.obj \ + $(SLO)$/DataSourceHelper.obj \ + $(SLO)$/DiagramHelper.obj \ + $(SLO)$/ExponentialRegressionCurveCalculator.obj \ + $(SLO)$/ImplOPropertySet.obj \ + $(SLO)$/InternalData.obj \ + $(SLO)$/InternalDataProvider.obj \ + $(SLO)$/LabeledDataSequence.obj \ + $(SLO)$/LinearRegressionCurveCalculator.obj \ + $(SLO)$/LogarithmicRegressionCurveCalculator.obj \ + $(SLO)$/MeanValueRegressionCurveCalculator.obj \ + $(SLO)$/OPropertySet.obj \ + $(SLO)$/WrappedPropertySet.obj \ + $(SLO)$/WrappedProperty.obj \ + $(SLO)$/WrappedIgnoreProperty.obj \ + $(SLO)$/WrappedDefaultProperty.obj \ + $(SLO)$/WrappedDirectStateProperty.obj \ + $(SLO)$/PotentialRegressionCurveCalculator.obj \ + $(SLO)$/RegressionCurveHelper.obj \ + $(SLO)$/RegressionCurveModel.obj \ + $(SLO)$/RelativeSizeHelper.obj \ + $(SLO)$/RelativePositionHelper.obj \ + $(SLO)$/Scaling.obj \ + $(SLO)$/SceneProperties.obj \ + $(SLO)$/ThreeDHelper.obj \ + $(SLO)$/StatisticsHelper.obj \ + $(SLO)$/ChartModelHelper.obj \ + $(SLO)$/ChartViewHelper.obj \ + $(SLO)$/ChartTypeHelper.obj \ + $(SLO)$/AxisHelper.obj \ + $(SLO)$/MutexContainer.obj \ + $(SLO)$/PropertyHelper.obj \ + $(SLO)$/FormattedStringHelper.obj \ + $(SLO)$/TitleHelper.obj \ + $(SLO)$/LegendHelper.obj \ + $(SLO)$/CharacterProperties.obj \ + $(SLO)$/LineProperties.obj \ + $(SLO)$/FillProperties.obj \ + $(SLO)$/UserDefinedProperties.obj \ + $(SLO)$/NameContainer.obj \ + $(SLO)$/ChartDebugTrace.obj \ + $(SLO)$/_serviceregistration_tools.obj \ + $(SLO)$/UncachedDataSequence.obj \ + $(SLO)$/XMLRangeHelper.obj \ + $(SLO)$/ModifyListenerHelper.obj \ + $(SLO)$/ModifyListenerCallBack.obj \ + $(SLO)$/BaseGFXHelper.obj \ + $(SLO)$/ControllerLockGuard.obj \ + $(SLO)$/WeakListenerAdapter.obj \ + $(SLO)$/ResId.obj \ + $(SLO)$/RessourceManager.obj \ + $(SLO)$/RangeHighlighter.obj \ + $(SLO)$/ReferenceSizeProvider.obj \ + $(SLO)$/ExplicitCategoriesProvider.obj \ + $(SLO)$/RegressionCurveCalculator.obj \ + $(SLO)$/RegressionEquation.obj + +DISABLED_SLOFILES= \ + $(SLO)$/NamedFillProperties.obj \ + $(SLO)$/NamedLineProperties.obj \ + $(SLO)$/NamedProperties.obj + +#-------- + +#Indicates the filename of the shared library. +SHL1TARGET= $(TARGET)$(DLLPOSTFIX) + +#indicates dependencies: +SHL1DEPN= +#Specifies an import library to create. For Win32 only. +SHL1IMPLIB= i$(TARGET) + +#Specifies libraries from the same module to put into the shared library. +#was created above +SHL1LIBS= $(SLB)$/$(TARGET).lib + +#Links import libraries. + +SHL1STDLIBS= \ + $(CPPULIB) \ + $(CPPUHELPERLIB) \ + $(COMPHELPERLIB) \ + $(SALLIB) \ + $(TOOLSLIB) \ + $(SVLLIB) \ + $(VCLLIB) \ + $(I18NISOLANGLIB) \ + $(BASEGFXLIB) \ + $(UNOTOOLSLIB) + +# $(SVLIB) \ +# $(SVTOOLLIB) \ +# $(SVXLIB) \ +# $(TKLIB) \ +# $(SFXLIB) + +#--------exports + +#specifies the exported symbols for Windows only: +SHL1DEF= $(MISC)$/$(SHL1TARGET).def + +#Specifies the library name to parse for symbols. For Win32 only. +DEFLIB1NAME= $(TARGET) + +#A file of symbols to export. +#DEF1EXPORTFILE= $(PRJ)$/source$/inc$/exports.dxp + +#--------definition file + +#name of the definition file: +DEF1NAME= $(SHL1TARGET) + +# indicates definition file dependencies +DEF1DEPN= $(MISC)$/$(SHL1TARGET).flt + +#A comment on the definition file. +DEF1DES= Chart Tools + +# --- Targets ----------------------------------------------------------------- + +.INCLUDE: target.mk + +# --- Filter ----------------------------------------------------------- + +$(MISC)$/$(SHL1TARGET).flt: makefile.mk \ + exports.flt + $(TYPE) exports.flt > $@ + |