diff options
Diffstat (limited to 'chart2/source/view/main/VDataSeries.cxx')
-rw-r--r-- | chart2/source/view/main/VDataSeries.cxx | 221 |
1 files changed, 114 insertions, 107 deletions
diff --git a/chart2/source/view/main/VDataSeries.cxx b/chart2/source/view/main/VDataSeries.cxx index f648b7510cec..d2456110b79b 100644 --- a/chart2/source/view/main/VDataSeries.cxx +++ b/chart2/source/view/main/VDataSeries.cxx @@ -37,7 +37,8 @@ #include "LabelPositionHelper.hxx" #include "ChartTypeHelper.hxx" #include "ContainerHelper.hxx" -#include "MeanValueRegressionCurveCalculator.hxx" +#include "DataSeriesHelper.hxx" +#include "RegressionCurveHelper.hxx" #include <com/sun/star/chart/MissingValueTreatment.hpp> #include <com/sun/star/chart2/Symbol.hpp> @@ -61,87 +62,10 @@ using namespace ::com::sun::star; using namespace ::com::sun::star::chart2; using ::com::sun::star::uno::Reference; -namespace -{ - struct lcl_LessIndex - { - inline bool operator() ( const sal_Int32& first, - const sal_Int32& second ) - { - return ( first < second ); - } - }; - - void lcl_removeIndices( uno::Sequence< double >& rValues, const uno::Sequence< sal_Int32 >& rIndicesToRemove ) - { - if( !rIndicesToRemove.getLength() ) - return; - - ::std::vector< sal_Int32 > aIndicesToRemove( ContainerHelper::SequenceToVector( rIndicesToRemove) ); - ::std::sort( aIndicesToRemove.begin(), aIndicesToRemove.end(), lcl_LessIndex() ); - - sal_Int32 nTarget=0; - sal_Int32 nR = 0; - sal_Int32 nRemove = aIndicesToRemove[nR]; - for( sal_Int32 nSource=0; nSource<rValues.getLength(); nSource++ ) - { - if( nSource<nRemove || nRemove==-1 ) - { - if( nTarget < nSource ) - rValues[nTarget]=rValues[nSource]; - nTarget++; - continue; - } - if( nSource==nRemove ) - { - ++nR; - if( nR<static_cast<sal_Int32>(aIndicesToRemove.size()) ) - nRemove = aIndicesToRemove[nR]; - else - nRemove = -1; - } - } - - if( nTarget>0 ) - rValues.realloc( nTarget ); - else - rValues.realloc(0); - } -} - void VDataSequence::init( const uno::Reference< data::XDataSequence >& xModel ) { - bool bDisplayHiddenCells = true; //todo: make this configurable in future - bool bIsHidden = false; - uno::Sequence< sal_Int32 > aHiddenValues; - if( !bDisplayHiddenCells ) - { - uno::Reference<beans::XPropertySet> xProp(xModel, uno::UNO_QUERY ); - if( xProp.is()) - { - try - { - xProp->getPropertyValue( C2U( "IsHidden" ) ) >>= bIsHidden; - xProp->getPropertyValue( C2U( "HiddenValues" ) ) >>= aHiddenValues; - } - catch( uno::Exception& e ) - { - ASSERT_EXCEPTION( e ); - } - } - } - Model = xModel; - if( bDisplayHiddenCells || !bIsHidden ) - Doubles = DataSequenceToDoubleSequence( xModel ); - - if( !bDisplayHiddenCells ) - { - if( bIsHidden ) - Doubles.realloc(0); - else if( aHiddenValues.getLength() ) - lcl_removeIndices( Doubles, aHiddenValues ); - } + Doubles = DataSequenceToDoubleSequence( xModel ); } bool VDataSequence::is() const @@ -200,27 +124,37 @@ struct lcl_LessXOfPoint } }; -void lcl_clearIfTextIsContained( VDataSequence& rData, const uno::Reference<data::XDataSequence>& xDataSequence ) +void lcl_clearIfNoValuesButTextIsContained( VDataSequence& rData, const uno::Reference<data::XDataSequence>& xDataSequence ) { + //#i71686#, #i101968#, #i102428# + sal_Int32 nCount = rData.Doubles.getLength(); + for( sal_Int32 i = 0; i < nCount; ++i ) + { + if( !::rtl::math::isNan( rData.Doubles[i] ) ) + return; + } + //no double value is countained + //is there any text? uno::Sequence< rtl::OUString > aStrings( DataSequenceToStringSequence( xDataSequence ) ); - for( sal_Int32 i = 0; i < rData.Doubles.getLength(); ++i ) + sal_Int32 nTextCount = aStrings.getLength(); + for( sal_Int32 j = 0; j < nTextCount; ++j ) { - if( ::rtl::math::isNan( rData.Doubles[i] ) ) + if( aStrings[j].getLength() ) { - if( i < aStrings.getLength() && aStrings[i].getLength() ) - { - rData.clear(); - break; - } + rData.clear(); + return; } } + //no content at all } +void lcl_maybeReplaceNanWithZero( double& rfValue, sal_Int32 nMissingValueTreatment ) +{ + if( nMissingValueTreatment == ::com::sun::star::chart::MissingValueTreatment::USE_ZERO + && ::rtl::math::isNan(rfValue) || ::rtl::math::isInf(rfValue) ) + rfValue = 0.0; } -VDataSeries::VDataSeries() -{ - DBG_ERROR("not implemented"); } VDataSeries::VDataSeries( const uno::Reference< XDataSeries >& xDataSeries ) @@ -244,6 +178,8 @@ VDataSeries::VDataSeries( const uno::Reference< XDataSeries >& xDataSeries ) , m_aValues_Y_Max() , m_aValues_Y_First() , m_aValues_Y_Last() + , m_aValues_Bubble_Size() + , m_pValueSequenceForDataLabelNumberFormatDetection(&m_aValues_Y) , m_fYMeanValue(1.0) @@ -274,6 +210,7 @@ VDataSeries::VDataSeries( const uno::Reference< XDataSeries >& xDataSeries ) , m_apSymbolProperties_InvisibleSymbolForSelection(NULL) , m_nCurrentAttributedPoint(-1) , m_nMissingValueTreatment(::com::sun::star::chart::MissingValueTreatment::LEAVE_GAP) + , m_bAllowPercentValueInDataLabel(false) { ::rtl::math::setNan( & m_fYMeanValue ); @@ -299,7 +236,7 @@ VDataSeries::VDataSeries( const uno::Reference< XDataSeries >& xDataSeries ) if( aRole.equals(C2U("values-x")) ) { m_aValues_X.init( xDataSequence ); - lcl_clearIfTextIsContained( m_aValues_X, xDataSequence ); + lcl_clearIfNoValuesButTextIsContained( m_aValues_X, xDataSequence ); } else if( aRole.equals(C2U("values-y")) ) m_aValues_Y.init( xDataSequence ); @@ -311,7 +248,8 @@ VDataSeries::VDataSeries( const uno::Reference< XDataSeries >& xDataSeries ) m_aValues_Y_First.init( xDataSequence ); else if( aRole.equals(C2U("values-last")) ) m_aValues_Y_Last.init( xDataSequence ); - //@todo assign the other roles (+ error for unknown?) + else if( aRole.equals(C2U("values-size")) ) + m_aValues_Bubble_Size.init( xDataSequence ); } catch( uno::Exception& e ) { @@ -323,13 +261,15 @@ VDataSeries::VDataSeries( const uno::Reference< XDataSeries >& xDataSeries ) //determine the point count m_nPointCount = m_aValues_Y.getLength(); { + if( m_nPointCount < m_aValues_Bubble_Size.getLength() ) + m_nPointCount = m_aValues_Bubble_Size.getLength(); if( m_nPointCount < m_aValues_Y_Min.getLength() ) m_nPointCount = m_aValues_Y_Min.getLength(); - if( m_nPointCount < m_aValues_Y_Max.getLength() ) + if( m_nPointCount < m_aValues_Y_Max.getLength() ) m_nPointCount = m_aValues_Y_Max.getLength(); - if( m_nPointCount < m_aValues_Y_First.getLength() ) + if( m_nPointCount < m_aValues_Y_First.getLength() ) m_nPointCount = m_aValues_Y_First.getLength(); - if( m_nPointCount < m_aValues_Y_Last.getLength() ) + if( m_nPointCount < m_aValues_Y_Last.getLength() ) m_nPointCount = m_aValues_Y_Last.getLength(); } @@ -412,6 +352,7 @@ void VDataSeries::releaseShapes() void VDataSeries::setCategoryXAxis() { m_aValues_X.clear(); + m_bAllowPercentValueInDataLabel = true; } void VDataSeries::setGlobalSeriesIndex( sal_Int32 nGlobalSeriesIndex ) @@ -526,27 +467,48 @@ sal_Int32 VDataSeries::getTotalPointCount() const return m_nPointCount; } -double VDataSeries::getX( sal_Int32 index ) const +double VDataSeries::getXValue( sal_Int32 index ) const { + double fRet = 0.0; if(m_aValues_X.is()) { if( 0<=index && index<m_aValues_X.getLength() ) - return m_aValues_X.Doubles[index]; + fRet = m_aValues_X.Doubles[index]; + else + ::rtl::math::setNan( &fRet ); } else { // #i70133# always return correct X position - needed for short data series if( 0<=index /*&& index < m_nPointCount*/ ) - return index+1;//first category (index 0) matches with real number 1.0 + fRet = index+1;//first category (index 0) matches with real number 1.0 + else + ::rtl::math::setNan( &fRet ); } - double fNan; - ::rtl::math::setNan( & fNan ); - return fNan; + lcl_maybeReplaceNanWithZero( fRet, getMissingValueTreatment() ); + return fRet; } -double VDataSeries::getY( sal_Int32 index ) const +double VDataSeries::getYValue( sal_Int32 index ) const { - return m_aValues_Y.getValue( index ); + double fRet = 0.0; + if(m_aValues_Y.is()) + { + if( 0<=index && index<m_aValues_Y.getLength() ) + fRet = m_aValues_Y.Doubles[index]; + else + ::rtl::math::setNan( &fRet ); + } + else + { + // #i70133# always return correct X position - needed for short data series + if( 0<=index /*&& index < m_nPointCount*/ ) + fRet = index+1;//first category (index 0) matches with real number 1.0 + else + ::rtl::math::setNan( &fRet ); + } + lcl_maybeReplaceNanWithZero( fRet, getMissingValueTreatment() ); + return fRet; } double VDataSeries::getY_Min( sal_Int32 index ) const @@ -565,6 +527,10 @@ double VDataSeries::getY_Last( sal_Int32 index ) const { return m_aValues_Y_Last.getValue( index ); } +double VDataSeries::getBubble_Size( sal_Int32 index ) const +{ + return m_aValues_Bubble_Size.getValue( index ); +} bool VDataSeries::hasExplicitNumberFormat( sal_Int32 nPointIndex, bool bForPercentage ) const { @@ -585,9 +551,37 @@ sal_Int32 VDataSeries::getExplicitNumberFormat( sal_Int32 nPointIndex, bool bFor xPointProp->getPropertyValue(aPropName) >>= nNumberFormat; return nNumberFormat; } +void VDataSeries::setRoleOfSequenceForDataLabelNumberFormatDetection( const rtl::OUString& rRole ) +{ + if( rRole.equals(C2U("values-y")) ) + m_pValueSequenceForDataLabelNumberFormatDetection = &m_aValues_Y; + else if( rRole.equals(C2U("values-size")) ) + m_pValueSequenceForDataLabelNumberFormatDetection = &m_aValues_Bubble_Size; + else if( rRole.equals(C2U("values-min")) ) + m_pValueSequenceForDataLabelNumberFormatDetection = &m_aValues_Y_Min; + else if( rRole.equals(C2U("values-max")) ) + m_pValueSequenceForDataLabelNumberFormatDetection = &m_aValues_Y_Max; + else if( rRole.equals(C2U("values-first")) ) + m_pValueSequenceForDataLabelNumberFormatDetection = &m_aValues_Y_First; + else if( rRole.equals(C2U("values-last")) ) + m_pValueSequenceForDataLabelNumberFormatDetection = &m_aValues_Y_Last; + else if( rRole.equals(C2U("values-x")) ) + m_pValueSequenceForDataLabelNumberFormatDetection = &m_aValues_X; +} +bool VDataSeries::shouldLabelNumberFormatKeyBeDetectedFromYAxis() const +{ + if( m_pValueSequenceForDataLabelNumberFormatDetection == &m_aValues_Bubble_Size ) + return false; + else if( m_pValueSequenceForDataLabelNumberFormatDetection == &m_aValues_X ) + return false; + return true; +} sal_Int32 VDataSeries::detectNumberFormatKey( sal_Int32 index ) const { - return m_aValues_Y.detectNumberFormatKey( index ); + sal_Int32 nRet = 0; + if( m_pValueSequenceForDataLabelNumberFormatDetection ) + nRet = m_pValueSequenceForDataLabelNumberFormatDetection->detectNumberFormatKey( index ); + return nRet; } sal_Int32 VDataSeries::getLabelPlacement( sal_Int32 nPointIndex, const uno::Reference< chart2::XChartType >& xChartType, sal_Int32 nDimensionCount, sal_Bool bSwapXAndY ) const @@ -626,7 +620,7 @@ sal_Int32 VDataSeries::getLabelPlacement( sal_Int32 nPointIndex, const uno::Refe double VDataSeries::getMinimumofAllDifferentYValues( sal_Int32 index ) const { - double fY = getY( index ); + double fY = getYValue( index ); double fY_Min = getY_Min( index ); double fY_Max = getY_Max( index ); double fY_First = getY_First( index ); @@ -653,7 +647,7 @@ double VDataSeries::getMinimumofAllDifferentYValues( sal_Int32 index ) const double VDataSeries::getMaximumofAllDifferentYValues( sal_Int32 index ) const { - double fY = getY( index ); + double fY = getYValue( index ); double fY_Min = getY_Min( index ); double fY_Max = getY_Max( index ); double fY_First = getY_First( index ); @@ -693,6 +687,14 @@ uno::Sequence< double > VDataSeries::getAllX() const uno::Sequence< double > VDataSeries::getAllY() const { + if(!m_aValues_Y.is() && !m_aValues_Y.getLength() && m_nPointCount) + { + //init y values from indexes + //first y-value (index 0) matches with real number 1.0 + m_aValues_Y.Doubles.realloc( m_nPointCount ); + for(sal_Int32 nN=m_aValues_Y.getLength();nN--;) + m_aValues_Y.Doubles[nN] = nN+1; + } return m_aValues_Y.Doubles; } @@ -700,7 +702,7 @@ double VDataSeries::getYMeanValue() const { if( ::rtl::math::isNan( m_fYMeanValue ) ) { - uno::Reference< XRegressionCurveCalculator > xCalculator( new MeanValueRegressionCurveCalculator() ); + uno::Reference< XRegressionCurveCalculator > xCalculator( RegressionCurveHelper::createRegressionCurveCalculatorByServiceName( C2U("com.sun.star.chart2.MeanValueRegressionCurve") ) ); uno::Sequence< double > aXValuesDummy; xCalculator->recalculateRegression( aXValuesDummy, getAllY() ); double fXDummy = 1.0; @@ -887,6 +889,11 @@ DataPointLabel* VDataSeries::getDataPointLabel( sal_Int32 index ) const m_apLabel_Series = getDataPointLabelFromPropertySet( this->getPropertiesOfPoint( index ) ); pRet = m_apLabel_Series.get(); } + if( !m_bAllowPercentValueInDataLabel ) + { + if( pRet ) + pRet->ShowNumberInPercent = false; + } return pRet; } |