/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the 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 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 { //............................................................................. Reference< XRegressionCurve > RegressionCurveHelper::createMeanValueLine( const Reference< XComponentContext > & xContext ) { return Reference< XRegressionCurve >( new MeanValueRegressionCurve( xContext )); } 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; } // ------------------------------------------------------------ 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; } 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 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 0 && aYValues.getLength() > 0 ) xOutCurveCalculator->recalculateRegression( aXValues, aYValues ); } 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) ); } // ---------------------------------------- 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; } 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; } 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 >(); } 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" ))); } } } 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.isEmpty() ) { // 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 ); } } } 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.isEmpty() ) { RegressionCurveHelper::removeAllExceptMeanValueLine( xRegCnt ); RegressionCurveHelper::addRegressionCurve( eType, xRegCnt, xContext, Reference< beans::XPropertySet >( xRegressionCurve, uno::UNO_QUERY ), xRegressionCurve->getEquationProperties()); } } } 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; } 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; } 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" ))) { aResult = ::chart::SchResId::getResString( STR_REGRESSION_MEAN ); } 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; } ::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; } 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 //.............................................................................