diff options
author | Kohei Yoshida <kyoshida@novell.com> | 2011-03-10 16:55:21 -0500 |
---|---|---|
committer | Kohei Yoshida <kyoshida@novell.com> | 2011-03-10 20:21:13 -0500 |
commit | 12343c15568dcc2c9209d8ca41fda2263122448f (patch) | |
tree | 3212a89c6cd8ea2e0aee7103aa9669bbb8a6f307 /chart2/source/view/axes | |
parent | Typo. (diff) | |
parent | masterfix DEV300: #i10000# usage of L10N build_type (diff) | |
download | core-12343c15568dcc2c9209d8ca41fda2263122448f.tar.gz core-12343c15568dcc2c9209d8ca41fda2263122448f.zip |
Merge commit 'ooo/DEV300_m101' into integration/dev300_m101
Diffstat (limited to 'chart2/source/view/axes')
33 files changed, 2661 insertions, 519 deletions
diff --git a/chart2/source/view/axes/DateHelper.cxx b/chart2/source/view/axes/DateHelper.cxx new file mode 100644 index 000000000000..7159a733498f --- /dev/null +++ b/chart2/source/view/axes/DateHelper.cxx @@ -0,0 +1,132 @@ +/************************************************************************* + * + * 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 "DateHelper.hxx" +#include "DateScaling.hxx" +#include <rtl/math.hxx> +#include <com/sun/star/chart/TimeUnit.hpp> + +//............................................................................. +namespace chart +{ +//............................................................................. +using namespace ::com::sun::star; + +bool DateHelper::IsInSameYear( const Date& rD1, const Date& rD2 ) +{ + return rD1.GetYear() == rD2.GetYear(); +} +bool DateHelper::IsInSameMonth( const Date& rD1, const Date& rD2 ) +{ + return (rD1.GetYear() == rD2.GetYear()) + && (rD1.GetMonth() == rD2.GetMonth()); +} +long DateHelper::GetMonthsBetweenDates( Date aD1, Date aD2 ) +{ + Date aHelp = aD1; + long nSign = 1; + if( aD1 < aD2 ) + { + aD1 = aD2; + aD2 = aHelp; + nSign = -1; + } + + return nSign*( ( aD1.GetMonth() - aD2.GetMonth() ) + + ( aD1.GetYear() - aD2.GetYear() )*12 ); +} + +Date DateHelper::GetDateSomeMonthsAway( const Date& rD, long nMonthDistance ) +{ + Date aRet(rD); + long nMonth = rD.GetMonth()+nMonthDistance; + long nNewMonth = nMonth%12; + long nNewYear = rD.GetYear() + nMonth/12; + if( nMonth <= 0 || !nNewMonth ) + nNewYear--; + if( nNewMonth <= 0 ) + nNewMonth += 12; + aRet.SetMonth( sal_uInt16(nNewMonth) ); + aRet.SetYear( sal_uInt16(nNewYear) ); + while(!aRet.IsValid()) + aRet--; + return aRet; +} + +Date DateHelper::GetDateSomeYearsAway( const Date& rD, long nYearDistance ) +{ + Date aRet(rD); + aRet.SetYear( static_cast<sal_uInt16>(rD.GetYear()+nYearDistance) ); + while(!aRet.IsValid()) + aRet--; + return aRet; +} + +bool DateHelper::IsLessThanOneMonthAway( const Date& rD1, const Date& rD2 ) +{ + Date aDMin( DateHelper::GetDateSomeMonthsAway( rD1, -1 ) ); + Date aDMax( DateHelper::GetDateSomeMonthsAway( rD1, 1 ) ); + + if( rD2 > aDMin && rD2 < aDMax ) + return true; + return false; +} + +bool DateHelper::IsLessThanOneYearAway( const Date& rD1, const Date& rD2 ) +{ + Date aDMin( DateHelper::GetDateSomeYearsAway( rD1, -1 ) ); + Date aDMax( DateHelper::GetDateSomeYearsAway( rD1, 1 ) ); + + if( rD2 > aDMin && rD2 < aDMax ) + return true; + return false; +} + +double DateHelper::RasterizeDateValue( double fValue, const Date& rNullDate, long TimeResolution ) +{ + Date aDate(rNullDate); aDate += static_cast<long>(::rtl::math::approxFloor(fValue)); + switch(TimeResolution) + { + case ::com::sun::star::chart::TimeUnit::DAY: + break; + case ::com::sun::star::chart::TimeUnit::YEAR: + aDate.SetMonth(1); + aDate.SetDay(1); + break; + case ::com::sun::star::chart::TimeUnit::MONTH: + default: + aDate.SetDay(1); + break; + } + return aDate - rNullDate; +} + +//............................................................................. +} //namespace chart +//............................................................................. diff --git a/chart2/source/view/axes/DateScaling.cxx b/chart2/source/view/axes/DateScaling.cxx new file mode 100644 index 000000000000..8a69e83abbc8 --- /dev/null +++ b/chart2/source/view/axes/DateScaling.cxx @@ -0,0 +1,216 @@ +/************************************************************************* + * + * 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 "DateScaling.hxx" +#include <com/sun/star/chart/TimeUnit.hpp> +#include <rtl/math.hxx> +#include "com/sun/star/uno/RuntimeException.hpp" + +namespace +{ + +static const ::rtl::OUString lcl_aServiceName_DateScaling( + RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.chart2.DateScaling" )); +static const ::rtl::OUString lcl_aServiceName_InverseDateScaling( + RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.chart2.InverseDateScaling" )); + +static const ::rtl::OUString lcl_aImplementationName_DateScaling( + RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.chart2.DateScaling" )); +static const ::rtl::OUString lcl_aImplementationName_InverseDateScaling( + RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.chart2.InverseDateScaling" )); + +static const double lcl_fNumberOfMonths = 12.0;//todo: this needs to be offered by basic tools Date class if it should be more generic +} + +//............................................................................. +namespace chart +{ +//............................................................................. +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; +using ::com::sun::star::chart::TimeUnit::DAY; +using ::com::sun::star::chart::TimeUnit::MONTH; +using ::com::sun::star::chart::TimeUnit::YEAR; + +DateScaling::DateScaling( const Date& rNullDate, sal_Int32 nTimeUnit, bool bShifted ) + : m_aNullDate( rNullDate ) + , m_nTimeUnit( nTimeUnit ) + , m_bShifted( bShifted ) +{ +} + +DateScaling::~DateScaling() +{ +} + +double SAL_CALL DateScaling::doScaling( double value ) + throw (uno::RuntimeException) +{ + double fResult(value); + if( ::rtl::math::isNan( value ) || ::rtl::math::isInf( value ) ) + ::rtl::math::setNan( & fResult ); + else + { + Date aDate(m_aNullDate); + aDate += static_cast<long>(::rtl::math::approxFloor(value)); + switch( m_nTimeUnit ) + { + case DAY: + fResult = value; + if(m_bShifted) + fResult+=0.5; + break; + case YEAR: + case MONTH: + default: + fResult = aDate.GetYear(); + fResult *= lcl_fNumberOfMonths;//asssuming equal count of months in each year + fResult += aDate.GetMonth(); + + double fDayOfMonth = aDate.GetDay(); + fDayOfMonth -= 1.0; + double fDaysInMonth = aDate.GetDaysInMonth(); + fResult += fDayOfMonth/fDaysInMonth; + if(m_bShifted) + { + if( YEAR==m_nTimeUnit ) + fResult += 0.5*lcl_fNumberOfMonths; + else + fResult += 0.5; + } + break; + } + } + return fResult; +} + +uno::Reference< XScaling > SAL_CALL DateScaling::getInverseScaling() + throw (uno::RuntimeException) +{ + return new InverseDateScaling( m_aNullDate, m_nTimeUnit, m_bShifted ); +} + +::rtl::OUString SAL_CALL DateScaling::getServiceName() + throw (uno::RuntimeException) +{ + return lcl_aServiceName_DateScaling; +} + +uno::Sequence< ::rtl::OUString > DateScaling::getSupportedServiceNames_Static() +{ + return uno::Sequence< ::rtl::OUString >( & lcl_aServiceName_DateScaling, 1 ); +} + +// implement XServiceInfo methods basing upon getSupportedServiceNames_Static +APPHELPER_XSERVICEINFO_IMPL( DateScaling, lcl_aServiceName_DateScaling ) + +// ---------------------------------------- + +InverseDateScaling::InverseDateScaling( const Date& rNullDate, sal_Int32 nTimeUnit, bool bShifted ) + : m_aNullDate( rNullDate ) + , m_nTimeUnit( nTimeUnit ) + , m_bShifted( bShifted ) +{ +} + +InverseDateScaling::~InverseDateScaling() +{ +} + +double SAL_CALL InverseDateScaling::doScaling( double value ) + throw (uno::RuntimeException) +{ + double fResult(value); + if( ::rtl::math::isNan( value ) || ::rtl::math::isInf( value ) ) + ::rtl::math::setNan( & fResult ); + else + { + switch( m_nTimeUnit ) + { + case DAY: + if(m_bShifted) + value -= 0.5; + fResult = value; + break; + case YEAR: + case MONTH: + default: + //Date aDate(m_aNullDate); + if(m_bShifted) + { + if( YEAR==m_nTimeUnit ) + value -= 0.5*lcl_fNumberOfMonths; + else + value -= 0.5; + } + Date aDate; + double fYear = ::rtl::math::approxFloor(value/lcl_fNumberOfMonths); + double fMonth = ::rtl::math::approxFloor(value-(fYear*lcl_fNumberOfMonths)); + if( fMonth==0.0 ) + { + fYear--; + fMonth=12.0; + } + aDate.SetYear( static_cast<sal_uInt16>(fYear) ); + aDate.SetMonth( static_cast<sal_uInt16>(fMonth) ); + aDate.SetDay( 1 ); + double fMonthCount = (fYear*lcl_fNumberOfMonths)+fMonth; + double fDay = (value-fMonthCount)*aDate.GetDaysInMonth(); + fDay += 1.0; + aDate.SetDay( static_cast<sal_uInt16>(::rtl::math::round(fDay)) ); + fResult = aDate - m_aNullDate; + break; + } + } + return fResult; +} + +uno::Reference< XScaling > SAL_CALL InverseDateScaling::getInverseScaling() + throw (uno::RuntimeException) +{ + return new DateScaling( m_aNullDate, m_nTimeUnit, m_bShifted ); +} + +::rtl::OUString SAL_CALL InverseDateScaling::getServiceName() + throw (uno::RuntimeException) +{ + return lcl_aServiceName_InverseDateScaling; +} + +uno::Sequence< ::rtl::OUString > InverseDateScaling::getSupportedServiceNames_Static() +{ + return uno::Sequence< ::rtl::OUString >( & lcl_aServiceName_InverseDateScaling, 1 ); +} + +// implement XServiceInfo methods basing upon getSupportedServiceNames_Static +APPHELPER_XSERVICEINFO_IMPL( InverseDateScaling, lcl_aServiceName_InverseDateScaling ) + +//............................................................................. +} //namespace chart +//............................................................................. diff --git a/chart2/source/view/axes/DateScaling.hxx b/chart2/source/view/axes/DateScaling.hxx new file mode 100644 index 000000000000..5e550604a957 --- /dev/null +++ b/chart2/source/view/axes/DateScaling.hxx @@ -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. + * + ************************************************************************/ +#ifndef _CHART2_DATESCALING_HXX +#define _CHART2_DATESCALING_HXX +#include "ServiceMacros.hxx" +#include <com/sun/star/chart2/XScaling.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XServiceName.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <cppuhelper/implbase3.hxx> +#include <tools/date.hxx> + +//............................................................................. +namespace chart +{ +//............................................................................. + +//----------------------------------------------------------------------------- +/** +*/ + +class DateScaling : + public ::cppu::WeakImplHelper3 < + ::com::sun::star::chart2::XScaling, + ::com::sun::star::lang::XServiceName, + ::com::sun::star::lang::XServiceInfo + > +{ +public: + DateScaling( const Date& rNullDate, sal_Int32 nTimeUnit, bool bShifted ); + virtual ~DateScaling(); + + /// declare XServiceInfo methods + APPHELPER_XSERVICEINFO_DECL() + + // ____ XScaling ____ + virtual double SAL_CALL doScaling( double value ) + throw (::com::sun::star::uno::RuntimeException); + + virtual ::com::sun::star::uno::Reference< + ::com::sun::star::chart2::XScaling > SAL_CALL + getInverseScaling() throw (::com::sun::star::uno::RuntimeException); + + // ____ XServiceName ____ + virtual ::rtl::OUString SAL_CALL getServiceName() + throw (::com::sun::star::uno::RuntimeException); + +private: + const Date m_aNullDate; + const sal_Int32 m_nTimeUnit; + const bool m_bShifted; +}; + +class InverseDateScaling : + public ::cppu::WeakImplHelper3 < + ::com::sun::star::chart2::XScaling, + ::com::sun::star::lang::XServiceName, + ::com::sun::star::lang::XServiceInfo + > +{ +public: + InverseDateScaling( const Date& rNullDate, sal_Int32 nTimeUnit, bool bShifted ); + virtual ~InverseDateScaling(); + + /// declare XServiceInfo methods + APPHELPER_XSERVICEINFO_DECL() + + // ____ XScaling ____ + virtual double SAL_CALL doScaling( double value ) + throw (::com::sun::star::uno::RuntimeException); + + virtual ::com::sun::star::uno::Reference< + ::com::sun::star::chart2::XScaling > SAL_CALL + getInverseScaling() throw (::com::sun::star::uno::RuntimeException); + + // ____ XServiceName ____ + virtual ::rtl::OUString SAL_CALL getServiceName() + throw (::com::sun::star::uno::RuntimeException); + +private: + const Date m_aNullDate; + const sal_Int32 m_nTimeUnit; + const bool m_bShifted; +}; + +//............................................................................. +} //namespace chart +//............................................................................. +#endif + diff --git a/chart2/source/view/axes/MinimumAndMaximumSupplier.cxx b/chart2/source/view/axes/MinimumAndMaximumSupplier.cxx index f9522bdc0005..669c2f9c42b9 100644 --- a/chart2/source/view/axes/MinimumAndMaximumSupplier.cxx +++ b/chart2/source/view/axes/MinimumAndMaximumSupplier.cxx @@ -30,6 +30,9 @@ #include "precompiled_chart2.hxx" #include "MinimumAndMaximumSupplier.hxx" + +#include <com/sun/star/chart/TimeUnit.hpp> + #include <rtl/math.hxx> #include <com/sun/star/awt/Size.hpp> @@ -197,6 +200,24 @@ void MergedMinimumAndMaximumSupplier::clearMinimumAndMaximumSupplierList() m_aMinimumAndMaximumSupplierList.clear(); } +long MergedMinimumAndMaximumSupplier::calculateTimeResolutionOnXAxis() +{ + long nRet = ::com::sun::star::chart::TimeUnit::YEAR; + for( MinimumAndMaximumSupplierSet::iterator aIt = begin(), aEnd = end(); aIt != aEnd; ++aIt ) + { + long nCurrent = (*aIt)->calculateTimeResolutionOnXAxis(); + if(nRet>nCurrent) + nRet=nCurrent; + } + return nRet; +} + +void MergedMinimumAndMaximumSupplier::setTimeResolutionOnXAxis( long nTimeResolution, const Date& rNullDate ) +{ + for( MinimumAndMaximumSupplierSet::iterator aIt = begin(), aEnd = end(); aIt != aEnd; ++aIt ) + (*aIt)->setTimeResolutionOnXAxis( nTimeResolution, rNullDate ); +} + //............................................................................. } //namespace chart //............................................................................. diff --git a/chart2/source/view/axes/ScaleAutomatism.cxx b/chart2/source/view/axes/ScaleAutomatism.cxx index 72256024ef7c..dcd987a0bbc3 100644 --- a/chart2/source/view/axes/ScaleAutomatism.cxx +++ b/chart2/source/view/axes/ScaleAutomatism.cxx @@ -30,8 +30,12 @@ #include "precompiled_chart2.hxx" #include "ScaleAutomatism.hxx" #include "macros.hxx" -#include "TickmarkHelper.hxx" +#include "Tickmarks_Equidistant.hxx" +#include "DateHelper.hxx" +#include "DateScaling.hxx" #include "AxisHelper.hxx" +#include <com/sun/star/chart/TimeUnit.hpp> + #include <rtl/math.hxx> #include <tools/debug.hxx> @@ -41,6 +45,9 @@ namespace chart //............................................................................. using namespace ::com::sun::star; using namespace ::com::sun::star::chart2; +using ::com::sun::star::chart::TimeUnit::DAY; +using ::com::sun::star::chart::TimeUnit::MONTH; +using ::com::sun::star::chart::TimeUnit::YEAR; const sal_Int32 MAXIMUM_MANUAL_INCREMENT_COUNT = 500; const sal_Int32 MAXIMUM_AUTO_INCREMENT_COUNT = 10; @@ -57,7 +64,42 @@ void lcl_ensureMaximumSubIncrementCount( sal_Int32& rnSubIntervalCount ) }//end anonymous namespace -ScaleAutomatism::ScaleAutomatism( const ScaleData& rSourceScale ) + +//............................................................................. + +ExplicitScaleData::ExplicitScaleData() + : Minimum(0.0) + , Maximum(10.0) + , Origin(0.0) + , Orientation(::com::sun::star::chart2::AxisOrientation_MATHEMATICAL) + , Scaling() + , AxisType(::com::sun::star::chart2::AxisType::REALNUMBER) + , ShiftedCategoryPosition(false) + , TimeResolution(::com::sun::star::chart::TimeUnit::DAY) + , NullDate(30,12,1899) +{ +} + +ExplicitSubIncrement::ExplicitSubIncrement() + : IntervalCount(2) + , PostEquidistant(true) +{ +} + + +ExplicitIncrementData::ExplicitIncrementData() + : MajorTimeInterval(1,::com::sun::star::chart::TimeUnit::DAY) + , MinorTimeInterval(1,::com::sun::star::chart::TimeUnit::DAY) + , Distance(1.0) + , PostEquidistant(true) + , BaseValue(0.0) + , SubIncrements() +{ +} + +//............................................................................. + +ScaleAutomatism::ScaleAutomatism( const ScaleData& rSourceScale, const Date& rNullDate ) : m_aSourceScale( rSourceScale ) , m_fValueMinimum( 0.0 ) , m_fValueMaximum( 0.0 ) @@ -66,6 +108,8 @@ ScaleAutomatism::ScaleAutomatism( const ScaleData& rSourceScale ) , m_bExpandIfValuesCloseToBorder( false ) , m_bExpandWideValuesToZero( false ) , m_bExpandNarrowValuesTowardZero( false ) + , m_nTimeResolution(::com::sun::star::chart::TimeUnit::DAY) + , m_aNullDate(rNullDate) { ::rtl::math::setNan( &m_fValueMinimum ); ::rtl::math::setNan( &m_fValueMaximum ); @@ -112,14 +156,19 @@ void ScaleAutomatism::setMaximumAutoMainIncrementCount( sal_Int32 nMaximumAutoMa m_nMaximumAutoMainIncrementCount = nMaximumAutoMainIncrementCount; } +void ScaleAutomatism::setAutomaticTimeResolution( sal_Int32 nTimeResolution ) +{ + m_nTimeResolution = nTimeResolution; +} + void ScaleAutomatism::calculateExplicitScaleAndIncrement( ExplicitScaleData& rExplicitScale, ExplicitIncrementData& rExplicitIncrement ) const { // fill explicit scale rExplicitScale.Orientation = m_aSourceScale.Orientation; rExplicitScale.Scaling = m_aSourceScale.Scaling; - rExplicitScale.Breaks = m_aSourceScale.Breaks; rExplicitScale.AxisType = m_aSourceScale.AxisType; + rExplicitScale.NullDate = m_aNullDate; bool bAutoMinimum = !(m_aSourceScale.Minimum >>= rExplicitScale.Minimum); bool bAutoMaximum = !(m_aSourceScale.Maximum >>= rExplicitScale.Maximum); @@ -131,7 +180,12 @@ void ScaleAutomatism::calculateExplicitScaleAndIncrement( if( m_aSourceScale.AxisType==AxisType::PERCENT ) rExplicitScale.Minimum = 0.0; else if( ::rtl::math::isNan( m_fValueMinimum ) ) - rExplicitScale.Minimum = 0.0; //@todo get Minimum from scaling or from plotter???? + { + if( m_aSourceScale.AxisType==AxisType::DATE ) + rExplicitScale.Minimum = 36526.0; //1.1.2000 + else + rExplicitScale.Minimum = 0.0; //@todo get Minimum from scaling or from plotter???? + } else rExplicitScale.Minimum = m_fValueMinimum; } @@ -142,7 +196,12 @@ void ScaleAutomatism::calculateExplicitScaleAndIncrement( if( m_aSourceScale.AxisType==AxisType::PERCENT ) rExplicitScale.Maximum = 1.0; else if( ::rtl::math::isNan( m_fValueMaximum ) ) - rExplicitScale.Maximum = 10.0; //@todo get Maximum from scaling or from plotter???? + { + if( m_aSourceScale.AxisType==AxisType::DATE ) + rExplicitScale.Maximum = 40179.0; //1.1.2010 + else + rExplicitScale.Maximum = 10.0; //@todo get Maximum from scaling or from plotter???? + } else rExplicitScale.Maximum = m_fValueMaximum; } @@ -150,14 +209,14 @@ void ScaleAutomatism::calculateExplicitScaleAndIncrement( //--------------------------------------------------------------- //fill explicit increment - rExplicitIncrement.ShiftedPosition = (m_aSourceScale.AxisType==AxisType::SERIES) ? true : false; + rExplicitScale.ShiftedCategoryPosition = m_aSourceScale.ShiftedCategoryPosition; bool bIsLogarithm = false; //minimum and maximum of the ExplicitScaleData may be changed if allowed - if( m_aSourceScale.AxisType==AxisType::CATEGORY || m_aSourceScale.AxisType==AxisType::SERIES ) - { + if( m_aSourceScale.AxisType==AxisType::DATE ) + calculateExplicitIncrementAndScaleForDateTimeAxis( rExplicitScale, rExplicitIncrement, bAutoMinimum, bAutoMaximum ); + else if( m_aSourceScale.AxisType==AxisType::CATEGORY || m_aSourceScale.AxisType==AxisType::SERIES ) calculateExplicitIncrementAndScaleForCategory( rExplicitScale, rExplicitIncrement, bAutoMinimum, bAutoMaximum ); - } else { bIsLogarithm = AxisHelper::isLogarithmic( rExplicitScale.Scaling ); @@ -187,6 +246,11 @@ ScaleData ScaleAutomatism::getScale() const return m_aSourceScale; } +Date ScaleAutomatism::getNullDate() const +{ + return m_aNullDate; +} + // private -------------------------------------------------------------------- void ScaleAutomatism::calculateExplicitIncrementAndScaleForCategory( @@ -197,6 +261,9 @@ void ScaleAutomatism::calculateExplicitIncrementAndScaleForCategory( // no scaling for categories rExplicitScale.Scaling.clear(); + if( rExplicitScale.ShiftedCategoryPosition ) + rExplicitScale.Maximum += 1.0; + // ensure that at least one category is visible if( rExplicitScale.Maximum <= rExplicitScale.Minimum ) rExplicitScale.Maximum = rExplicitScale.Minimum + 1.0; @@ -208,9 +275,9 @@ void ScaleAutomatism::calculateExplicitIncrementAndScaleForCategory( // automatic minimum and maximum if( bAutoMinimum && m_bExpandBorderToIncrementRhythm ) - rExplicitScale.Minimum = TickmarkHelper::getMinimumAtIncrement( rExplicitScale.Minimum, rExplicitIncrement ); + rExplicitScale.Minimum = EquidistantTickFactory::getMinimumAtIncrement( rExplicitScale.Minimum, rExplicitIncrement ); if( bAutoMaximum && m_bExpandBorderToIncrementRhythm ) - rExplicitScale.Maximum = TickmarkHelper::getMaximumAtIncrement( rExplicitScale.Maximum, rExplicitIncrement ); + rExplicitScale.Maximum = EquidistantTickFactory::getMaximumAtIncrement( rExplicitScale.Maximum, rExplicitIncrement ); //prevent performace killover double fDistanceCount = ::rtl::math::approxFloor( (rExplicitScale.Maximum-rExplicitScale.Minimum) / rExplicitIncrement.Distance ); @@ -224,29 +291,28 @@ void ScaleAutomatism::calculateExplicitIncrementAndScaleForCategory( //--------------------------------------------------------------- //fill explicit sub increment sal_Int32 nSubCount = m_aSourceScale.IncrementData.SubIncrements.getLength(); - rExplicitIncrement.SubIncrements.realloc(nSubCount); for( sal_Int32 nN=0; nN<nSubCount; nN++ ) { - const SubIncrement& rSubIncrement = m_aSourceScale.IncrementData.SubIncrements[nN]; - ExplicitSubIncrement& rExplicitSubIncrement = rExplicitIncrement.SubIncrements[nN]; - - if(!(rSubIncrement.IntervalCount>>=rExplicitSubIncrement.IntervalCount)) + ExplicitSubIncrement aExplicitSubIncrement; + const SubIncrement& rSubIncrement= m_aSourceScale.IncrementData.SubIncrements[nN]; + if(!(rSubIncrement.IntervalCount>>=aExplicitSubIncrement.IntervalCount)) { //scaling dependent //@todo autocalculate IntervalCount dependent on MainIncrement and scaling - rExplicitSubIncrement.IntervalCount = 2; + aExplicitSubIncrement.IntervalCount = 2; } - lcl_ensureMaximumSubIncrementCount( rExplicitSubIncrement.IntervalCount ); - if(!(rSubIncrement.PostEquidistant>>=rExplicitSubIncrement.PostEquidistant)) + lcl_ensureMaximumSubIncrementCount( aExplicitSubIncrement.IntervalCount ); + if(!(rSubIncrement.PostEquidistant>>=aExplicitSubIncrement.PostEquidistant)) { //scaling dependent - rExplicitSubIncrement.PostEquidistant = sal_False; + aExplicitSubIncrement.PostEquidistant = sal_False; } + rExplicitIncrement.SubIncrements.push_back(aExplicitSubIncrement); } } -//@todo these method should become part of the scaling interface and implementation somehow -//@todo problem with outparamters at api +//----------------------------------------------------------------------------------------- + void ScaleAutomatism::calculateExplicitIncrementAndScaleForLogarithmic( ExplicitScaleData& rExplicitScale, ExplicitIncrementData& rExplicitIncrement, @@ -413,7 +479,7 @@ void ScaleAutomatism::calculateExplicitIncrementAndScaleForLogarithmic( // round to entire multiples of the distance and add additional space if( bAutoMinimum && m_bExpandBorderToIncrementRhythm ) { - fAxisMinimum = TickmarkHelper::getMinimumAtIncrement( fAxisMinimum, rExplicitIncrement ); + fAxisMinimum = EquidistantTickFactory::getMinimumAtIncrement( fAxisMinimum, rExplicitIncrement ); //ensure valid values after scaling #i100995# if( !bAutoDistance ) @@ -429,7 +495,7 @@ void ScaleAutomatism::calculateExplicitIncrementAndScaleForLogarithmic( } if( bAutoMaximum && m_bExpandBorderToIncrementRhythm ) { - fAxisMaximum = TickmarkHelper::getMaximumAtIncrement( fAxisMaximum, rExplicitIncrement ); + fAxisMaximum = EquidistantTickFactory::getMaximumAtIncrement( fAxisMaximum, rExplicitIncrement ); //ensure valid values after scaling #i100995# if( !bAutoDistance ) @@ -489,27 +555,210 @@ void ScaleAutomatism::calculateExplicitIncrementAndScaleForLogarithmic( //--------------------------------------------------------------- //fill explicit sub increment sal_Int32 nSubCount = m_aSourceScale.IncrementData.SubIncrements.getLength(); - rExplicitIncrement.SubIncrements.realloc(nSubCount); for( sal_Int32 nN=0; nN<nSubCount; nN++ ) { - const SubIncrement& rSubIncrement = m_aSourceScale.IncrementData.SubIncrements[nN]; - ExplicitSubIncrement& rExplicitSubIncrement = rExplicitIncrement.SubIncrements[nN]; - - if(!(rSubIncrement.IntervalCount>>=rExplicitSubIncrement.IntervalCount)) + ExplicitSubIncrement aExplicitSubIncrement; + const SubIncrement& rSubIncrement = m_aSourceScale.IncrementData.SubIncrements[nN]; + if(!(rSubIncrement.IntervalCount>>=aExplicitSubIncrement.IntervalCount)) { //scaling dependent //@todo autocalculate IntervalCount dependent on MainIncrement and scaling - rExplicitSubIncrement.IntervalCount = 9; + aExplicitSubIncrement.IntervalCount = 9; } - lcl_ensureMaximumSubIncrementCount( rExplicitSubIncrement.IntervalCount ); - if(!(rSubIncrement.PostEquidistant>>=rExplicitSubIncrement.PostEquidistant)) + lcl_ensureMaximumSubIncrementCount( aExplicitSubIncrement.IntervalCount ); + if(!(rSubIncrement.PostEquidistant>>=aExplicitSubIncrement.PostEquidistant)) { //scaling dependent - rExplicitSubIncrement.PostEquidistant = sal_False; + aExplicitSubIncrement.PostEquidistant = sal_False; } + rExplicitIncrement.SubIncrements.push_back(aExplicitSubIncrement); } } +//----------------------------------------------------------------------------------------- + +void ScaleAutomatism::calculateExplicitIncrementAndScaleForDateTimeAxis( + ExplicitScaleData& rExplicitScale, + ExplicitIncrementData& rExplicitIncrement, + bool bAutoMinimum, bool bAutoMaximum ) const +{ + Date aMinDate(m_aNullDate); aMinDate += static_cast<long>(::rtl::math::approxFloor(rExplicitScale.Minimum)); + Date aMaxDate(m_aNullDate); aMaxDate += static_cast<long>(::rtl::math::approxFloor(rExplicitScale.Maximum)); + rExplicitIncrement.PostEquidistant = sal_False; + + if( aMinDate > aMaxDate ) + { + std::swap(aMinDate,aMaxDate); + } + + if( !(m_aSourceScale.TimeIncrement.TimeResolution >>= rExplicitScale.TimeResolution) ) + rExplicitScale.TimeResolution = m_nTimeResolution; + + rExplicitScale.Scaling = new DateScaling(m_aNullDate,rExplicitScale.TimeResolution,false); + + // choose min and max suitable to time resolution + switch( rExplicitScale.TimeResolution ) + { + case DAY: + if( rExplicitScale.ShiftedCategoryPosition ) + aMaxDate++;//for explicit scales we need one interval more (maximum excluded) + break; + case MONTH: + aMinDate.SetDay(1); + aMaxDate.SetDay(1); + if( rExplicitScale.ShiftedCategoryPosition ) + aMaxDate = DateHelper::GetDateSomeMonthsAway(aMaxDate,1);//for explicit scales we need one interval more (maximum excluded) + if( DateHelper::IsLessThanOneMonthAway( aMinDate, aMaxDate ) ) + { + if( bAutoMaximum || !bAutoMinimum ) + aMaxDate = DateHelper::GetDateSomeMonthsAway(aMinDate,1); + else + aMinDate = DateHelper::GetDateSomeMonthsAway(aMaxDate,-1); + } + break; + case YEAR: + aMinDate.SetDay(1); + aMinDate.SetMonth(1); + aMaxDate.SetDay(1); + aMaxDate.SetMonth(1); + if( rExplicitScale.ShiftedCategoryPosition ) + aMaxDate = DateHelper::GetDateSomeYearsAway(aMaxDate,1);//for explicit scales we need one interval more (maximum excluded) + if( DateHelper::IsLessThanOneYearAway( aMinDate, aMaxDate ) ) + { + if( bAutoMaximum || !bAutoMinimum ) + aMaxDate = DateHelper::GetDateSomeYearsAway(aMinDate,1); + else + aMinDate = DateHelper::GetDateSomeYearsAway(aMaxDate,-1); + } + break; + } + + // set the resulting limits (swap back to negative range if needed) + rExplicitScale.Minimum = aMinDate - m_aNullDate; + rExplicitScale.Maximum = aMaxDate - m_aNullDate; + + bool bAutoMajor = !(m_aSourceScale.TimeIncrement.MajorTimeInterval >>= rExplicitIncrement.MajorTimeInterval); + bool bAutoMinor = !(m_aSourceScale.TimeIncrement.MinorTimeInterval >>= rExplicitIncrement.MinorTimeInterval); + + sal_Int32 nMaxMainIncrementCount = bAutoMajor ? + m_nMaximumAutoMainIncrementCount : MAXIMUM_MANUAL_INCREMENT_COUNT; + if( nMaxMainIncrementCount > 1 ) + nMaxMainIncrementCount--; + + + //choose major time interval: + long nDayCount = (aMaxDate-aMinDate); + long nMainIncrementCount = 1; + if( !bAutoMajor ) + { + long nIntervalDayCount = rExplicitIncrement.MajorTimeInterval.Number; + if( rExplicitIncrement.MajorTimeInterval.TimeUnit < rExplicitScale.TimeResolution ) + rExplicitIncrement.MajorTimeInterval.TimeUnit = rExplicitScale.TimeResolution; + switch( rExplicitIncrement.MajorTimeInterval.TimeUnit ) + { + case DAY: + break; + case MONTH: + nIntervalDayCount*=31;//todo: maybe different for other calendars... get localized calendar according to set number format at axis ... + break; + case YEAR: + nIntervalDayCount*=365;//todo: maybe different for other calendars... get localized calendar according to set number format at axis ... + break; + } + nMainIncrementCount = nDayCount/nIntervalDayCount; + if( nMainIncrementCount > nMaxMainIncrementCount ) + bAutoMajor = true; + } + if( bAutoMajor ) + { + long nNumer = 1; + long nIntervalDays = nDayCount / nMaxMainIncrementCount; + double nDaysPerInterval = 1.0; + if( nIntervalDays>365 || YEAR==rExplicitScale.TimeResolution ) + { + rExplicitIncrement.MajorTimeInterval.TimeUnit = YEAR; + nDaysPerInterval = 365.0;//todo: maybe different for other calendars... get localized calendar according to set number format at axis ... + } + else if( nIntervalDays>31 || MONTH==rExplicitScale.TimeResolution ) + { + rExplicitIncrement.MajorTimeInterval.TimeUnit = MONTH; + nDaysPerInterval = 31.0;//todo: maybe different for other calendars... get localized calendar according to set number format at axis ... + } + else + { + rExplicitIncrement.MajorTimeInterval.TimeUnit = DAY; + nDaysPerInterval = 1.0; + } + + nNumer = static_cast<sal_Int32>( rtl::math::approxCeil( nIntervalDays/nDaysPerInterval ) ); + if(nNumer<=0) + nNumer=1; + rExplicitIncrement.MajorTimeInterval.Number = nNumer; + nMainIncrementCount = nDayCount/(nNumer*nDaysPerInterval); + } + + //choose minor time interval: + if( !bAutoMinor ) + { + if( rExplicitIncrement.MinorTimeInterval.TimeUnit > rExplicitIncrement.MajorTimeInterval.TimeUnit ) + rExplicitIncrement.MinorTimeInterval.TimeUnit = rExplicitIncrement.MajorTimeInterval.TimeUnit; + long nIntervalDayCount = rExplicitIncrement.MinorTimeInterval.Number; + switch( rExplicitIncrement.MinorTimeInterval.TimeUnit ) + { + case DAY: + break; + case MONTH: + nIntervalDayCount*=31;//todo: maybe different for other calendars... get localized calendar according to set number format at axis ... + break; + case YEAR: + nIntervalDayCount*=365;//todo: maybe different for other calendars... get localized calendar according to set number format at axis ... + break; + } + if( nDayCount/nIntervalDayCount > nMaxMainIncrementCount ) + bAutoMinor = true; + } + if( bAutoMinor ) + { + rExplicitIncrement.MinorTimeInterval.TimeUnit = rExplicitIncrement.MajorTimeInterval.TimeUnit; + rExplicitIncrement.MinorTimeInterval.Number = 1; + if( nMainIncrementCount > 100 ) + rExplicitIncrement.MinorTimeInterval.Number = rExplicitIncrement.MajorTimeInterval.Number; + else + { + if( rExplicitIncrement.MajorTimeInterval.Number >= 2 ) + { + if( !(rExplicitIncrement.MajorTimeInterval.Number%2) ) + rExplicitIncrement.MinorTimeInterval.Number = rExplicitIncrement.MajorTimeInterval.Number/2; + else if( !(rExplicitIncrement.MajorTimeInterval.Number%3) ) + rExplicitIncrement.MinorTimeInterval.Number = rExplicitIncrement.MajorTimeInterval.Number/3; + else if( !(rExplicitIncrement.MajorTimeInterval.Number%5) ) + rExplicitIncrement.MinorTimeInterval.Number = rExplicitIncrement.MajorTimeInterval.Number/5; + else if( rExplicitIncrement.MajorTimeInterval.Number > 50 ) + rExplicitIncrement.MinorTimeInterval.Number = rExplicitIncrement.MajorTimeInterval.Number; + } + else + { + switch( rExplicitIncrement.MajorTimeInterval.TimeUnit ) + { + case DAY: + break; + case MONTH: + if( rExplicitScale.TimeResolution == DAY ) + rExplicitIncrement.MinorTimeInterval.TimeUnit = DAY; + break; + case YEAR: + if( rExplicitScale.TimeResolution <= MONTH ) + rExplicitIncrement.MinorTimeInterval.TimeUnit = MONTH; + break; + } + } + } + } + +} + +//----------------------------------------------------------------------------------------- + void ScaleAutomatism::calculateExplicitIncrementAndScaleForLinear( ExplicitScaleData& rExplicitScale, ExplicitIncrementData& rExplicitIncrement, @@ -693,7 +942,7 @@ void ScaleAutomatism::calculateExplicitIncrementAndScaleForLinear( { // round to entire multiples of the distance, based on the base value if( m_bExpandBorderToIncrementRhythm ) - fAxisMinimum = TickmarkHelper::getMinimumAtIncrement( fAxisMinimum, rExplicitIncrement ); + fAxisMinimum = EquidistantTickFactory::getMinimumAtIncrement( fAxisMinimum, rExplicitIncrement ); // additional space, if source minimum is to near at axis minimum if( m_bExpandIfValuesCloseToBorder ) if( (fAxisMinimum != 0.0) && ((fAxisMaximum - fSourceMinimum) / (fAxisMaximum - fAxisMinimum) > 20.0 / 21.0) ) @@ -703,7 +952,7 @@ void ScaleAutomatism::calculateExplicitIncrementAndScaleForLinear( { // round to entire multiples of the distance, based on the base value if( m_bExpandBorderToIncrementRhythm ) - fAxisMaximum = TickmarkHelper::getMaximumAtIncrement( fAxisMaximum, rExplicitIncrement ); + fAxisMaximum = EquidistantTickFactory::getMaximumAtIncrement( fAxisMaximum, rExplicitIncrement ); // additional space, if source maximum is to near at axis maximum if( m_bExpandIfValuesCloseToBorder ) if( (fAxisMaximum != 0.0) && ((fSourceMaximum - fAxisMinimum) / (fAxisMaximum - fAxisMinimum) > 20.0 / 21.0) ) @@ -735,24 +984,23 @@ void ScaleAutomatism::calculateExplicitIncrementAndScaleForLinear( //--------------------------------------------------------------- //fill explicit sub increment sal_Int32 nSubCount = m_aSourceScale.IncrementData.SubIncrements.getLength(); - rExplicitIncrement.SubIncrements.realloc(nSubCount); for( sal_Int32 nN=0; nN<nSubCount; nN++ ) { - const SubIncrement& rSubIncrement = m_aSourceScale.IncrementData.SubIncrements[nN]; - ExplicitSubIncrement& rExplicitSubIncrement = rExplicitIncrement.SubIncrements[nN]; - - if(!(rSubIncrement.IntervalCount>>=rExplicitSubIncrement.IntervalCount)) + ExplicitSubIncrement aExplicitSubIncrement; + const SubIncrement& rSubIncrement= m_aSourceScale.IncrementData.SubIncrements[nN]; + if(!(rSubIncrement.IntervalCount>>=aExplicitSubIncrement.IntervalCount)) { //scaling dependent //@todo autocalculate IntervalCount dependent on MainIncrement and scaling - rExplicitSubIncrement.IntervalCount = 2; + aExplicitSubIncrement.IntervalCount = 2; } - lcl_ensureMaximumSubIncrementCount( rExplicitSubIncrement.IntervalCount ); - if(!(rSubIncrement.PostEquidistant>>=rExplicitSubIncrement.PostEquidistant)) + lcl_ensureMaximumSubIncrementCount( aExplicitSubIncrement.IntervalCount ); + if(!(rSubIncrement.PostEquidistant>>=aExplicitSubIncrement.PostEquidistant)) { //scaling dependent - rExplicitSubIncrement.PostEquidistant = sal_False; + aExplicitSubIncrement.PostEquidistant = sal_False; } + rExplicitIncrement.SubIncrements.push_back(aExplicitSubIncrement); } } diff --git a/chart2/source/view/axes/Tickmarks.cxx b/chart2/source/view/axes/Tickmarks.cxx new file mode 100644 index 000000000000..834fe66eb97b --- /dev/null +++ b/chart2/source/view/axes/Tickmarks.cxx @@ -0,0 +1,333 @@ +/************************************************************************* + * + * 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 "Tickmarks.hxx" +#include "Tickmarks_Equidistant.hxx" +#include "Tickmarks_Dates.hxx" +#include "ViewDefines.hxx" +#include <rtl/math.hxx> +#include <tools/debug.hxx> +#include <memory> + +//............................................................................. +namespace chart +{ +//............................................................................. +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; +using namespace ::rtl::math; +using ::basegfx::B2DVector; + +TickInfo::TickInfo( const ::com::sun::star::uno::Reference< + ::com::sun::star::chart2::XScaling >& xInverse ) +: fScaledTickValue( 0.0 ) +, xInverseScaling( xInverse ) +, aTickScreenPosition(0.0,0.0) +, bPaintIt( true ) +, xTextShape( NULL ) +, nFactorForLimitedTextWidth(1) +{ +} + +double TickInfo::getUnscaledTickValue() const +{ + if( xInverseScaling.is() ) + return xInverseScaling->doScaling( fScaledTickValue ); + else + return fScaledTickValue; +} + +sal_Int32 TickInfo::getScreenDistanceBetweenTicks( const TickInfo& rOherTickInfo ) const +{ + //return the positive distance between the two first tickmarks in screen values + + B2DVector aDistance = rOherTickInfo.aTickScreenPosition - aTickScreenPosition; + sal_Int32 nRet = static_cast<sal_Int32>(aDistance.getLength()); + if(nRet<0) + nRet *= -1; + return nRet; +} + +PureTickIter::PureTickIter( ::std::vector< TickInfo >& rTickInfoVector ) + : m_rTickVector(rTickInfoVector) + , m_aTickIter(m_rTickVector.begin()) +{ +} +PureTickIter::~PureTickIter() +{ +} +TickInfo* PureTickIter::firstInfo() +{ + m_aTickIter = m_rTickVector.begin(); + if(m_aTickIter!=m_rTickVector.end()) + return &*m_aTickIter; + return 0; +} +TickInfo* PureTickIter::nextInfo() +{ + if(m_aTickIter!=m_rTickVector.end()) + { + m_aTickIter++; + if(m_aTickIter!=m_rTickVector.end()) + return &*m_aTickIter; + } + return 0; +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + +TickFactory::TickFactory( + const ExplicitScaleData& rScale, const ExplicitIncrementData& rIncrement ) + : m_rScale( rScale ) + , m_rIncrement( rIncrement ) + , m_xInverseScaling(NULL) +{ + //@todo: make sure that the scale is valid for the scaling + + if( m_rScale.Scaling.is() ) + { + m_xInverseScaling = m_rScale.Scaling->getInverseScaling(); + DBG_ASSERT( m_xInverseScaling.is(), "each Scaling needs to return a inverse Scaling" ); + } + + m_fScaledVisibleMin = m_rScale.Minimum; + if( m_xInverseScaling.is() ) + m_fScaledVisibleMin = m_rScale.Scaling->doScaling(m_fScaledVisibleMin); + + m_fScaledVisibleMax = m_rScale.Maximum; + if( m_xInverseScaling.is() ) + m_fScaledVisibleMax = m_rScale.Scaling->doScaling(m_fScaledVisibleMax); +} + +TickFactory::~TickFactory() +{ +} + +bool TickFactory::isDateAxis() const +{ + return m_rScale.AxisType == AxisType::DATE; +} + +void TickFactory::getAllTicks( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ) const +{ + if( isDateAxis() ) + DateTickFactory( m_rScale, m_rIncrement ).getAllTicks( rAllTickInfos ); + else + EquidistantTickFactory( m_rScale, m_rIncrement ).getAllTicks( rAllTickInfos ); +} + +void TickFactory::getAllTicksShifted( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ) const +{ + if( isDateAxis() ) + DateTickFactory( m_rScale, m_rIncrement ).getAllTicksShifted( rAllTickInfos ); + else + EquidistantTickFactory( m_rScale, m_rIncrement ).getAllTicksShifted( rAllTickInfos ); +} + +//----------------------------------------------------------------------------- +// ___TickFactory_2D___ +//----------------------------------------------------------------------------- +TickFactory_2D::TickFactory_2D( + const ExplicitScaleData& rScale, const ExplicitIncrementData& rIncrement + //, double fStrech_SceneToScreen, double fOffset_SceneToScreen ) + , const B2DVector& rStartScreenPos, const B2DVector& rEndScreenPos + , const B2DVector& rAxisLineToLabelLineShift ) + : TickFactory( rScale, rIncrement ) + , m_aAxisStartScreenPosition2D(rStartScreenPos) + , m_aAxisEndScreenPosition2D(rEndScreenPos) + , m_aAxisLineToLabelLineShift(rAxisLineToLabelLineShift) + , m_fStrech_LogicToScreen(1.0) + , m_fOffset_LogicToScreen(0.0) +{ + double fWidthY = m_fScaledVisibleMax - m_fScaledVisibleMin; + if( AxisOrientation_MATHEMATICAL==m_rScale.Orientation ) + { + m_fStrech_LogicToScreen = 1.0/fWidthY; + m_fOffset_LogicToScreen = -m_fScaledVisibleMin; + } + else + { + B2DVector aSwap(m_aAxisStartScreenPosition2D); + m_aAxisStartScreenPosition2D = m_aAxisEndScreenPosition2D; + m_aAxisEndScreenPosition2D = aSwap; + + m_fStrech_LogicToScreen = -1.0/fWidthY; + m_fOffset_LogicToScreen = -m_fScaledVisibleMax; + } +} + +TickFactory_2D::~TickFactory_2D() +{ +} + +bool TickFactory_2D::isHorizontalAxis() const +{ + return ( m_aAxisStartScreenPosition2D.getY() == m_aAxisEndScreenPosition2D.getY() ); +} +bool TickFactory_2D::isVerticalAxis() const +{ + return ( m_aAxisStartScreenPosition2D.getX() == m_aAxisEndScreenPosition2D.getX() ); +} + +//static +sal_Int32 TickFactory_2D::getTickScreenDistance( TickIter& rIter ) +{ + //return the positive distance between the two first tickmarks in screen values + //if there are less than two tickmarks -1 is returned + + const TickInfo* pFirstTickInfo = rIter.firstInfo(); + const TickInfo* pSecondTickInfo = rIter.nextInfo(); + if(!pSecondTickInfo || !pFirstTickInfo) + return -1; + + return pFirstTickInfo->getScreenDistanceBetweenTicks( *pSecondTickInfo ); +} + +B2DVector TickFactory_2D::getTickScreenPosition2D( double fScaledLogicTickValue ) const +{ + B2DVector aRet(m_aAxisStartScreenPosition2D); + aRet += (m_aAxisEndScreenPosition2D-m_aAxisStartScreenPosition2D) + *((fScaledLogicTickValue+m_fOffset_LogicToScreen)*m_fStrech_LogicToScreen); + return aRet; +} + +void TickFactory_2D::addPointSequenceForTickLine( drawing::PointSequenceSequence& rPoints + , sal_Int32 nSequenceIndex + , double fScaledLogicTickValue, double fInnerDirectionSign + , const TickmarkProperties& rTickmarkProperties + , bool bPlaceAtLabels ) const +{ + if( fInnerDirectionSign==0.0 ) + fInnerDirectionSign = 1.0; + + B2DVector aTickScreenPosition = this->getTickScreenPosition2D(fScaledLogicTickValue); + if( bPlaceAtLabels ) + aTickScreenPosition += m_aAxisLineToLabelLineShift; + + B2DVector aMainDirection = m_aAxisEndScreenPosition2D-m_aAxisStartScreenPosition2D; + aMainDirection.normalize(); + B2DVector aOrthoDirection(-aMainDirection.getY(),aMainDirection.getX()); + aOrthoDirection *= fInnerDirectionSign; + aOrthoDirection.normalize(); + + B2DVector aStart = aTickScreenPosition + aOrthoDirection*rTickmarkProperties.RelativePos; + B2DVector aEnd = aStart - aOrthoDirection*rTickmarkProperties.Length; + + rPoints[nSequenceIndex].realloc(2); + rPoints[nSequenceIndex][0].X = static_cast<sal_Int32>(aStart.getX()); + rPoints[nSequenceIndex][0].Y = static_cast<sal_Int32>(aStart.getY()); + rPoints[nSequenceIndex][1].X = static_cast<sal_Int32>(aEnd.getX()); + rPoints[nSequenceIndex][1].Y = static_cast<sal_Int32>(aEnd.getY()); +} + +B2DVector TickFactory_2D::getDistanceAxisTickToText( const AxisProperties& rAxisProperties, bool bIncludeFarAwayDistanceIfSo, bool bIncludeSpaceBetweenTickAndText ) const +{ + bool bFarAwayLabels = false; + if( ::com::sun::star::chart::ChartAxisLabelPosition_OUTSIDE_START == rAxisProperties.m_eLabelPos + || ::com::sun::star::chart::ChartAxisLabelPosition_OUTSIDE_END == rAxisProperties.m_eLabelPos ) + bFarAwayLabels = true; + + double fInnerDirectionSign = rAxisProperties.m_fInnerDirectionSign; + if( fInnerDirectionSign==0.0 ) + fInnerDirectionSign = 1.0; + + B2DVector aMainDirection = m_aAxisEndScreenPosition2D-m_aAxisStartScreenPosition2D; + aMainDirection.normalize(); + B2DVector aOrthoDirection(-aMainDirection.getY(),aMainDirection.getX()); + aOrthoDirection *= fInnerDirectionSign; + aOrthoDirection.normalize(); + + B2DVector aStart(0,0), aEnd(0,0); + if( bFarAwayLabels ) + { + TickmarkProperties aProps( AxisProperties::getBiggestTickmarkProperties() ); + aStart = aOrthoDirection*aProps.RelativePos; + aEnd = aStart - aOrthoDirection*aProps.Length; + } + else + { + for( sal_Int32 nN=rAxisProperties.m_aTickmarkPropertiesList.size();nN--;) + { + const TickmarkProperties& rProps = rAxisProperties.m_aTickmarkPropertiesList[nN]; + B2DVector aNewStart = aOrthoDirection*rProps.RelativePos; + B2DVector aNewEnd = aNewStart - aOrthoDirection*rProps.Length; + if(aNewStart.getLength()>aStart.getLength()) + aStart=aNewStart; + if(aNewEnd.getLength()>aEnd.getLength()) + aEnd=aNewEnd; + } + } + + B2DVector aLabelDirection(aStart); + if( rAxisProperties.m_fInnerDirectionSign != rAxisProperties.m_fLabelDirectionSign ) + aLabelDirection = aEnd; + + B2DVector aOrthoLabelDirection(aOrthoDirection); + if( rAxisProperties.m_fInnerDirectionSign != rAxisProperties.m_fLabelDirectionSign ) + aOrthoLabelDirection*=-1.0; + aOrthoLabelDirection.normalize(); + if( bIncludeSpaceBetweenTickAndText ) + aLabelDirection += aOrthoLabelDirection*AXIS2D_TICKLABELSPACING; + if( bFarAwayLabels && bIncludeFarAwayDistanceIfSo ) + aLabelDirection += m_aAxisLineToLabelLineShift; + return aLabelDirection; +} + +void TickFactory_2D::createPointSequenceForAxisMainLine( drawing::PointSequenceSequence& rPoints ) const +{ + rPoints[0].realloc(2); + rPoints[0][0].X = static_cast<sal_Int32>(m_aAxisStartScreenPosition2D.getX()); + rPoints[0][0].Y = static_cast<sal_Int32>(m_aAxisStartScreenPosition2D.getY()); + rPoints[0][1].X = static_cast<sal_Int32>(m_aAxisEndScreenPosition2D.getX()); + rPoints[0][1].Y = static_cast<sal_Int32>(m_aAxisEndScreenPosition2D.getY()); +} + +void TickFactory_2D::updateScreenValues( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ) const +{ + //get the transformed screen values for all tickmarks in rAllTickInfos + ::std::vector< ::std::vector< TickInfo > >::iterator aDepthIter = rAllTickInfos.begin(); + const ::std::vector< ::std::vector< TickInfo > >::const_iterator aDepthEnd = rAllTickInfos.end(); + for( ; aDepthIter != aDepthEnd; aDepthIter++ ) + { + ::std::vector< TickInfo >::iterator aTickIter = (*aDepthIter).begin(); + const ::std::vector< TickInfo >::const_iterator aTickEnd = (*aDepthIter).end(); + for( ; aTickIter != aTickEnd; aTickIter++ ) + { + TickInfo& rTickInfo = (*aTickIter); + rTickInfo.aTickScreenPosition = + this->getTickScreenPosition2D( rTickInfo.fScaledTickValue ); + } + } +} + +//............................................................................. +} //namespace chart +//............................................................................. diff --git a/chart2/source/view/axes/Tickmarks.hxx b/chart2/source/view/axes/Tickmarks.hxx new file mode 100644 index 000000000000..62fa5fef92d0 --- /dev/null +++ b/chart2/source/view/axes/Tickmarks.hxx @@ -0,0 +1,166 @@ +/************************************************************************* + * + * 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_TICKMARKS_HXX +#define _CHART2_TICKMARKS_HXX + +#include "TickmarkProperties.hxx" +#include "VAxisProperties.hxx" +#include "chartview/ExplicitScaleValues.hxx" +#include <basegfx/vector/b2dvector.hxx> +#include <com/sun/star/drawing/PointSequenceSequence.hpp> +#include <com/sun/star/drawing/XShape.hpp> +#include <com/sun/star/uno/Sequence.h> + +#include <vector> + +//............................................................................. +namespace chart +{ +//............................................................................. + +using ::basegfx::B2DVector; +//----------------------------------------------------------------------------- +/** +*/ + +struct TickInfo +{ + double fScaledTickValue; + ::com::sun::star::uno::Reference< + ::com::sun::star::chart2::XScaling > xInverseScaling; + + ::basegfx::B2DVector aTickScreenPosition; + bool bPaintIt; + + ::com::sun::star::uno::Reference< + ::com::sun::star::drawing::XShape > xTextShape; + + rtl::OUString aText;//used only for complex categories so far + sal_Int32 nFactorForLimitedTextWidth;//categories in higher levels of complex categories can have more place than a single simple category + +//methods: + TickInfo( const ::com::sun::star::uno::Reference< + ::com::sun::star::chart2::XScaling >& xInverseScaling ); + + double getUnscaledTickValue() const; + sal_Int32 getScreenDistanceBetweenTicks( const TickInfo& rOherTickInfo ) const; +private: + TickInfo(); +}; +class TickIter +{ +public: + virtual ~TickIter(){}; + virtual TickInfo* firstInfo()=0; + virtual TickInfo* nextInfo()=0; +}; + +class PureTickIter : public TickIter +{ +public: + PureTickIter( ::std::vector< TickInfo >& rTickInfoVector ); + virtual ~PureTickIter(); + virtual TickInfo* firstInfo(); + virtual TickInfo* nextInfo(); + +private: + ::std::vector< TickInfo >& m_rTickVector; + ::std::vector< TickInfo >::iterator m_aTickIter; +}; + +class TickFactory +{ +public: + TickFactory( + const ExplicitScaleData& rScale + , const ExplicitIncrementData& rIncrement ); + virtual ~TickFactory(); + + void getAllTicks( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ) const; + void getAllTicksShifted( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ) const; + virtual void updateScreenValues( ::std::vector< ::std::vector< TickInfo > >& /*rAllTickInfos*/ ) const {} + +private: //methods + bool isDateAxis() const; + +protected: //member + ExplicitScaleData m_rScale; + ExplicitIncrementData m_rIncrement; + ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XScaling > + m_xInverseScaling; + + //minimum and maximum of the visible range after scaling + double m_fScaledVisibleMin; + double m_fScaledVisibleMax; +}; + +class TickFactory_2D : public TickFactory +{ +public: + TickFactory_2D( + const ExplicitScaleData& rScale + , const ExplicitIncrementData& rIncrement + , const ::basegfx::B2DVector& rStartScreenPos, const ::basegfx::B2DVector& rEndScreenPos + , const ::basegfx::B2DVector& rAxisLineToLabelLineShift ); + //, double fStrech_SceneToScreen, double fOffset_SceneToScreen ); + virtual ~TickFactory_2D(); + + static sal_Int32 getTickScreenDistance( TickIter& rIter ); + + void createPointSequenceForAxisMainLine( ::com::sun::star::drawing::PointSequenceSequence& rPoints ) const; + void addPointSequenceForTickLine( ::com::sun::star::drawing::PointSequenceSequence& rPoints + , sal_Int32 nSequenceIndex + , double fScaledLogicTickValue, double fInnerDirectionSign + , const TickmarkProperties& rTickmarkProperties, bool bPlaceAtLabels ) const; + ::basegfx::B2DVector getDistanceAxisTickToText( const AxisProperties& rAxisProperties + , bool bIncludeFarAwayDistanceIfSo = false + , bool bIncludeSpaceBetweenTickAndText = true ) const; + + virtual void updateScreenValues( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ) const; + + bool isHorizontalAxis() const; + bool isVerticalAxis() const; + +protected: //methods + ::basegfx::B2DVector getTickScreenPosition2D( double fScaledLogicTickValue ) const; + +private: //member + ::basegfx::B2DVector m_aAxisStartScreenPosition2D; + ::basegfx::B2DVector m_aAxisEndScreenPosition2D; + + //labels might be posioned high or low on the border of the diagram far away from the axis + //add this vector to go from the axis line to the label line (border of the diagram) + ::basegfx::B2DVector m_aAxisLineToLabelLineShift; + + double m_fStrech_LogicToScreen; + double m_fOffset_LogicToScreen; +}; + +//............................................................................. +} //namespace chart +//............................................................................. +#endif diff --git a/chart2/source/view/axes/Tickmarks_Dates.cxx b/chart2/source/view/axes/Tickmarks_Dates.cxx new file mode 100644 index 000000000000..b5177fe307b8 --- /dev/null +++ b/chart2/source/view/axes/Tickmarks_Dates.cxx @@ -0,0 +1,171 @@ +/************************************************************************* + * + * 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 "Tickmarks_Dates.hxx" +#include "DateScaling.hxx" +#include <rtl/math.hxx> +#include <tools/debug.hxx> +#include "DateHelper.hxx" + +//............................................................................. +namespace chart +{ +//............................................................................. +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; +using namespace ::rtl::math; +using ::basegfx::B2DVector; +using ::com::sun::star::chart::TimeUnit::DAY; +using ::com::sun::star::chart::TimeUnit::MONTH; +using ::com::sun::star::chart::TimeUnit::YEAR; + +DateTickFactory::DateTickFactory( + const ExplicitScaleData& rScale, const ExplicitIncrementData& rIncrement ) + : m_aScale( rScale ) + , m_aIncrement( rIncrement ) + , m_xInverseScaling(NULL) +{ + //@todo: make sure that the scale is valid for the scaling + + if( m_aScale.Scaling.is() ) + { + m_xInverseScaling = m_aScale.Scaling->getInverseScaling(); + DBG_ASSERT( m_xInverseScaling.is(), "each Scaling needs to return a inverse Scaling" ); + } + + m_fScaledVisibleMin = m_aScale.Minimum; + if( m_xInverseScaling.is() ) + m_fScaledVisibleMin = m_aScale.Scaling->doScaling(m_fScaledVisibleMin); + + m_fScaledVisibleMax = m_aScale.Maximum; + if( m_xInverseScaling.is() ) + m_fScaledVisibleMax = m_aScale.Scaling->doScaling(m_fScaledVisibleMax); +} + +DateTickFactory::~DateTickFactory() +{ +} + +void DateTickFactory::getAllTicks( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos, bool bShifted ) const +{ + rAllTickInfos.resize(2); + ::std::vector< TickInfo >& rMajorTicks = rAllTickInfos[0]; + ::std::vector< TickInfo >& rMinorTicks = rAllTickInfos[1]; + rMajorTicks.clear(); + rMinorTicks.clear(); + + Date aNull(m_aScale.NullDate); + + Date aDate = aNull + ::rtl::math::approxFloor(m_aScale.Minimum); + Date aMaxDate = aNull + ::rtl::math::approxFloor(m_aScale.Maximum); + + uno::Reference< chart2::XScaling > xScaling(m_aScale.Scaling); + uno::Reference< chart2::XScaling > xInverseScaling(m_xInverseScaling); + if( bShifted ) + { + xScaling = new DateScaling(aNull,m_aScale.TimeResolution,true/*bShifted*/); + xInverseScaling = xScaling->getInverseScaling(); + } + + //create major date tickinfos + while( aDate<= aMaxDate ) + { + if( bShifted && aDate==aMaxDate ) + break; + + TickInfo aNewTick(xInverseScaling); aNewTick.fScaledTickValue = aDate - aNull; + + if( xInverseScaling.is() ) + aNewTick.fScaledTickValue = xScaling->doScaling(aNewTick.fScaledTickValue); + rMajorTicks.push_back( aNewTick ); + + if(m_aIncrement.MajorTimeInterval.Number<=0) + break; + + //find next major date + switch( m_aIncrement.MajorTimeInterval.TimeUnit ) + { + case DAY: + aDate += m_aIncrement.MajorTimeInterval.Number; + break; + case YEAR: + aDate = DateHelper::GetDateSomeYearsAway( aDate, m_aIncrement.MajorTimeInterval.Number ); + break; + case MONTH: + default: + aDate = DateHelper::GetDateSomeMonthsAway( aDate, m_aIncrement.MajorTimeInterval.Number ); + break; + } + } + + //create minor date tickinfos + aDate = aNull + ::rtl::math::approxFloor(m_aScale.Minimum); + while( aDate<= aMaxDate ) + { + if( bShifted && aDate==aMaxDate ) + break; + + TickInfo aNewTick(xInverseScaling); aNewTick.fScaledTickValue = aDate - aNull; + if( xInverseScaling.is() ) + aNewTick.fScaledTickValue = xScaling->doScaling(aNewTick.fScaledTickValue); + rMinorTicks.push_back( aNewTick ); + + if(m_aIncrement.MinorTimeInterval.Number<=0) + break; + + //find next minor date + switch( m_aIncrement.MinorTimeInterval.TimeUnit ) + { + case DAY: + aDate += m_aIncrement.MinorTimeInterval.Number; + break; + case YEAR: + aDate = DateHelper::GetDateSomeYearsAway( aDate, m_aIncrement.MinorTimeInterval.Number ); + break; + case MONTH: + default: + aDate = DateHelper::GetDateSomeMonthsAway( aDate, m_aIncrement.MinorTimeInterval.Number ); + break; + } + } +} + +void DateTickFactory::getAllTicks( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ) const +{ + getAllTicks( rAllTickInfos, false ); +} + +void DateTickFactory::getAllTicksShifted( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ) const +{ + getAllTicks( rAllTickInfos, true ); +} + +//............................................................................. +} //namespace chart +//............................................................................. diff --git a/chart2/source/view/axes/Tickmarks_Dates.hxx b/chart2/source/view/axes/Tickmarks_Dates.hxx new file mode 100644 index 000000000000..464e8b4ca24c --- /dev/null +++ b/chart2/source/view/axes/Tickmarks_Dates.hxx @@ -0,0 +1,65 @@ +/************************************************************************* + * + * 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_TICKMARKS_DATES_HXX +#define _CHART2_TICKMARKS_DATES_HXX + +#include "Tickmarks.hxx" + +//............................................................................. +namespace chart +{ +//............................................................................. + +class DateTickFactory +{ +public: + DateTickFactory( + const ExplicitScaleData& rScale + , const ExplicitIncrementData& rIncrement ); + ~DateTickFactory(); + + void getAllTicks( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ) const; + void getAllTicksShifted( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ) const; + +private: //methods + void getAllTicks( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos, bool bShifted ) const; + +private: //member + ExplicitScaleData m_aScale; + ExplicitIncrementData m_aIncrement; + ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XScaling > + m_xInverseScaling; + + //minimum and maximum of the visible range after scaling + double m_fScaledVisibleMin; + double m_fScaledVisibleMax; +}; + +//............................................................................. +} //namespace chart +//............................................................................. +#endif diff --git a/chart2/source/view/axes/Tickmarks_Equidistant.cxx b/chart2/source/view/axes/Tickmarks_Equidistant.cxx new file mode 100644 index 000000000000..9344af1ffac9 --- /dev/null +++ b/chart2/source/view/axes/Tickmarks_Equidistant.cxx @@ -0,0 +1,671 @@ +/************************************************************************* + * + * 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 "Tickmarks_Equidistant.hxx" +#include "ViewDefines.hxx" +#include <rtl/math.hxx> +#include <tools/debug.hxx> +#include <memory> + +//............................................................................. +namespace chart +{ +//............................................................................. +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; +using namespace ::rtl::math; +using ::basegfx::B2DVector; + +//static +double EquidistantTickFactory::getMinimumAtIncrement( double fMin, const ExplicitIncrementData& rIncrement ) +{ + //the returned value will be <= fMin and on a Major Tick given by rIncrement + if(rIncrement.Distance<=0.0) + return fMin; + + double fRet = rIncrement.BaseValue + + floor( approxSub( fMin, rIncrement.BaseValue ) + / rIncrement.Distance) + *rIncrement.Distance; + + if( fRet > fMin ) + { + if( !approxEqual(fRet, fMin) ) + fRet -= rIncrement.Distance; + } + return fRet; +} +//static +double EquidistantTickFactory::getMaximumAtIncrement( double fMax, const ExplicitIncrementData& rIncrement ) +{ + //the returned value will be >= fMax and on a Major Tick given by rIncrement + if(rIncrement.Distance<=0.0) + return fMax; + + double fRet = rIncrement.BaseValue + + floor( approxSub( fMax, rIncrement.BaseValue ) + / rIncrement.Distance) + *rIncrement.Distance; + + if( fRet < fMax ) + { + if( !approxEqual(fRet, fMax) ) + fRet += rIncrement.Distance; + } + return fRet; +} + +EquidistantTickFactory::EquidistantTickFactory( + const ExplicitScaleData& rScale, const ExplicitIncrementData& rIncrement ) + : m_rScale( rScale ) + , m_rIncrement( rIncrement ) + , m_xInverseScaling(NULL) + , m_pfCurrentValues(NULL) +{ + //@todo: make sure that the scale is valid for the scaling + + m_pfCurrentValues = new double[getTickDepth()]; + + if( m_rScale.Scaling.is() ) + { + m_xInverseScaling = m_rScale.Scaling->getInverseScaling(); + DBG_ASSERT( m_xInverseScaling.is(), "each Scaling needs to return a inverse Scaling" ); + } + + double fMin = m_fScaledVisibleMin = m_rScale.Minimum; + if( m_xInverseScaling.is() ) + { + m_fScaledVisibleMin = m_rScale.Scaling->doScaling(m_fScaledVisibleMin); + if(m_rIncrement.PostEquidistant ) + fMin = m_fScaledVisibleMin; + } + + double fMax = m_fScaledVisibleMax = m_rScale.Maximum; + if( m_xInverseScaling.is() ) + { + m_fScaledVisibleMax = m_rScale.Scaling->doScaling(m_fScaledVisibleMax); + if(m_rIncrement.PostEquidistant ) + fMax = m_fScaledVisibleMax; + } + + //-- + m_fOuterMajorTickBorderMin = EquidistantTickFactory::getMinimumAtIncrement( fMin, m_rIncrement ); + m_fOuterMajorTickBorderMax = EquidistantTickFactory::getMaximumAtIncrement( fMax, m_rIncrement ); + //-- + + m_fOuterMajorTickBorderMin_Scaled = m_fOuterMajorTickBorderMin; + m_fOuterMajorTickBorderMax_Scaled = m_fOuterMajorTickBorderMax; + if(!m_rIncrement.PostEquidistant && m_xInverseScaling.is() ) + { + m_fOuterMajorTickBorderMin_Scaled = m_rScale.Scaling->doScaling(m_fOuterMajorTickBorderMin); + m_fOuterMajorTickBorderMax_Scaled = m_rScale.Scaling->doScaling(m_fOuterMajorTickBorderMax); + + //check validity of new range: m_fOuterMajorTickBorderMin <-> m_fOuterMajorTickBorderMax + //it is assumed here, that the original range in the given Scale is valid + if( !rtl::math::isFinite(m_fOuterMajorTickBorderMin_Scaled) ) + { + m_fOuterMajorTickBorderMin += m_rIncrement.Distance; + m_fOuterMajorTickBorderMin_Scaled = m_rScale.Scaling->doScaling(m_fOuterMajorTickBorderMin); + } + if( !rtl::math::isFinite(m_fOuterMajorTickBorderMax_Scaled) ) + { + m_fOuterMajorTickBorderMax -= m_rIncrement.Distance; + m_fOuterMajorTickBorderMax_Scaled = m_rScale.Scaling->doScaling(m_fOuterMajorTickBorderMax); + } + } +} + +EquidistantTickFactory::~EquidistantTickFactory() +{ + delete[] m_pfCurrentValues; +} + +sal_Int32 EquidistantTickFactory::getTickDepth() const +{ + return static_cast<sal_Int32>(m_rIncrement.SubIncrements.size()) + 1; +} + +void EquidistantTickFactory::addSubTicks( sal_Int32 nDepth, uno::Sequence< uno::Sequence< double > >& rParentTicks ) const +{ + EquidistantTickIter aIter( rParentTicks, m_rIncrement, 0, nDepth-1 ); + double* pfNextParentTick = aIter.firstValue(); + if(!pfNextParentTick) + return; + double fLastParentTick = *pfNextParentTick; + pfNextParentTick = aIter.nextValue(); + if(!pfNextParentTick) + return; + + sal_Int32 nMaxSubTickCount = this->getMaxTickCount( nDepth ); + if(!nMaxSubTickCount) + return; + + uno::Sequence< double > aSubTicks(nMaxSubTickCount); + sal_Int32 nRealSubTickCount = 0; + sal_Int32 nIntervalCount = m_rIncrement.SubIncrements[nDepth-1].IntervalCount; + + double* pValue = NULL; + for(; pfNextParentTick; fLastParentTick=*pfNextParentTick, pfNextParentTick = aIter.nextValue()) + { + for( sal_Int32 nPartTick = 1; nPartTick<nIntervalCount; nPartTick++ ) + { + pValue = this->getMinorTick( nPartTick, nDepth + , fLastParentTick, *pfNextParentTick ); + if(!pValue) + continue; + + aSubTicks[nRealSubTickCount] = *pValue; + nRealSubTickCount++; + } + } + + aSubTicks.realloc(nRealSubTickCount); + rParentTicks[nDepth] = aSubTicks; + if(static_cast<sal_Int32>(m_rIncrement.SubIncrements.size())>nDepth) + addSubTicks( nDepth+1, rParentTicks ); +} + + +sal_Int32 EquidistantTickFactory::getMaxTickCount( sal_Int32 nDepth ) const +{ + //return the maximum amount of ticks + //possibly open intervals at the two ends of the region are handled as if they were completely visible + //(this is necessary for calculating the sub ticks at the borders correctly) + + if( nDepth >= getTickDepth() ) + return 0; + if( m_fOuterMajorTickBorderMax < m_fOuterMajorTickBorderMin ) + return 0; + if( m_rIncrement.Distance<=0.0) + return 0; + + double fSub; + if(m_rIncrement.PostEquidistant ) + fSub = approxSub( m_fScaledVisibleMax, m_fScaledVisibleMin ); + else + fSub = approxSub( m_rScale.Maximum, m_rScale.Minimum ); + + if (!isFinite(fSub)) + return 0; + + sal_Int32 nIntervalCount = static_cast<sal_Int32>( fSub / m_rIncrement.Distance ); + + nIntervalCount+=3; + for(sal_Int32 nN=0; nN<nDepth-1; nN++) + { + if( m_rIncrement.SubIncrements[nN].IntervalCount>1 ) + nIntervalCount *= m_rIncrement.SubIncrements[nN].IntervalCount; + } + + sal_Int32 nTickCount = nIntervalCount; + if(nDepth>0 && m_rIncrement.SubIncrements[nDepth-1].IntervalCount>1) + nTickCount = nIntervalCount * (m_rIncrement.SubIncrements[nDepth-1].IntervalCount-1); + + return nTickCount; +} + +double* EquidistantTickFactory::getMajorTick( sal_Int32 nTick ) const +{ + m_pfCurrentValues[0] = m_fOuterMajorTickBorderMin + nTick*m_rIncrement.Distance; + + if(m_pfCurrentValues[0]>m_fOuterMajorTickBorderMax) + { + if( !approxEqual(m_pfCurrentValues[0],m_fOuterMajorTickBorderMax) ) + return NULL; + } + if(m_pfCurrentValues[0]<m_fOuterMajorTickBorderMin) + { + if( !approxEqual(m_pfCurrentValues[0],m_fOuterMajorTickBorderMin) ) + return NULL; + } + + //return always the value after scaling + if(!m_rIncrement.PostEquidistant && m_xInverseScaling.is() ) + m_pfCurrentValues[0] = m_rScale.Scaling->doScaling( m_pfCurrentValues[0] ); + + return &m_pfCurrentValues[0]; +} + +double* EquidistantTickFactory::getMinorTick( sal_Int32 nTick, sal_Int32 nDepth + , double fStartParentTick, double fNextParentTick ) const +{ + //check validity of arguments + { + //DBG_ASSERT( fStartParentTick < fNextParentTick, "fStartParentTick >= fNextParentTick"); + if(fStartParentTick >= fNextParentTick) + return NULL; + if(nDepth>static_cast<sal_Int32>(m_rIncrement.SubIncrements.size()) || nDepth<=0) + return NULL; + + //subticks are only calculated if they are laying between parent ticks: + if(nTick<=0) + return NULL; + if(nTick>=m_rIncrement.SubIncrements[nDepth-1].IntervalCount) + return NULL; + } + + bool bPostEquidistant = m_rIncrement.SubIncrements[nDepth-1].PostEquidistant; + + double fAdaptedStartParent = fStartParentTick; + double fAdaptedNextParent = fNextParentTick; + + if( !bPostEquidistant && m_xInverseScaling.is() ) + { + fAdaptedStartParent = m_xInverseScaling->doScaling(fStartParentTick); + fAdaptedNextParent = m_xInverseScaling->doScaling(fNextParentTick); + } + + double fDistance = (fAdaptedNextParent - fAdaptedStartParent)/m_rIncrement.SubIncrements[nDepth-1].IntervalCount; + + m_pfCurrentValues[nDepth] = fAdaptedStartParent + nTick*fDistance; + + //return always the value after scaling + if(!bPostEquidistant && m_xInverseScaling.is() ) + m_pfCurrentValues[nDepth] = m_rScale.Scaling->doScaling( m_pfCurrentValues[nDepth] ); + + if( !isWithinOuterBorder( m_pfCurrentValues[nDepth] ) ) + return NULL; + + return &m_pfCurrentValues[nDepth]; +} + +bool EquidistantTickFactory::isWithinOuterBorder( double fScaledValue ) const +{ + if(fScaledValue>m_fOuterMajorTickBorderMax_Scaled) + return false; + if(fScaledValue<m_fOuterMajorTickBorderMin_Scaled) + return false; + + return true; +} + +bool EquidistantTickFactory::isVisible( double fScaledValue ) const +{ + if(fScaledValue>m_fScaledVisibleMax) + { + if( !approxEqual(fScaledValue,m_fScaledVisibleMax) ) + return false; + } + if(fScaledValue<m_fScaledVisibleMin) + { + if( !approxEqual(fScaledValue,m_fScaledVisibleMin) ) + return false; + } + return true; +} + +void EquidistantTickFactory::getAllTicks( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ) const +{ + uno::Sequence< uno::Sequence< double > > aAllTicks; + + //create point sequences for each tick depth + sal_Int32 nDepthCount = this->getTickDepth(); + sal_Int32 nMaxMajorTickCount = this->getMaxTickCount( 0 ); + + aAllTicks.realloc(nDepthCount); + aAllTicks[0].realloc(nMaxMajorTickCount); + + sal_Int32 nRealMajorTickCount = 0; + double* pValue = NULL; + for( sal_Int32 nMajorTick=0; nMajorTick<nMaxMajorTickCount; nMajorTick++ ) + { + pValue = this->getMajorTick( nMajorTick ); + if(!pValue) + continue; + aAllTicks[0][nRealMajorTickCount] = *pValue; + nRealMajorTickCount++; + } + if(!nRealMajorTickCount) + return; + aAllTicks[0].realloc(nRealMajorTickCount); + + if(nDepthCount>0) + this->addSubTicks( 1, aAllTicks ); + + //so far we have added all ticks between the outer major tick marks + //this was necessary to create sub ticks correctly + //now we reduce all ticks to the visible ones that lie between the real borders + sal_Int32 nDepth = 0; + sal_Int32 nTick = 0; + for( nDepth = 0; nDepth < nDepthCount; nDepth++) + { + sal_Int32 nInvisibleAtLowerBorder = 0; + sal_Int32 nInvisibleAtUpperBorder = 0; + //we need only to check all ticks within the first major interval at each border + sal_Int32 nCheckCount = 1; + for(sal_Int32 nN=0; nN<nDepth; nN++) + { + if( m_rIncrement.SubIncrements[nN].IntervalCount>1 ) + nCheckCount *= m_rIncrement.SubIncrements[nN].IntervalCount; + } + uno::Sequence< double >& rTicks = aAllTicks[nDepth]; + sal_Int32 nCount = rTicks.getLength(); + //check lower border + for( nTick=0; nTick<nCheckCount && nTick<nCount; nTick++) + { + if( !isVisible( rTicks[nTick] ) ) + nInvisibleAtLowerBorder++; + } + //check upper border + for( nTick=nCount-1; nTick>nCount-1-nCheckCount && nTick>=0; nTick--) + { + if( !isVisible( rTicks[nTick] ) ) + nInvisibleAtUpperBorder++; + } + //resize sequence + if( !nInvisibleAtLowerBorder && !nInvisibleAtUpperBorder) + continue; + if( !nInvisibleAtLowerBorder ) + rTicks.realloc(nCount-nInvisibleAtUpperBorder); + else + { + sal_Int32 nNewCount = nCount-nInvisibleAtUpperBorder-nInvisibleAtLowerBorder; + if(nNewCount<0) + nNewCount=0; + + uno::Sequence< double > aOldTicks(rTicks); + rTicks.realloc(nNewCount); + for(nTick = 0; nTick<nNewCount; nTick++) + rTicks[nTick] = aOldTicks[nInvisibleAtLowerBorder+nTick]; + } + } + + //fill return value + rAllTickInfos.resize(aAllTicks.getLength()); + for( nDepth=0 ;nDepth<aAllTicks.getLength(); nDepth++ ) + { + sal_Int32 nCount = aAllTicks[nDepth].getLength(); + + ::std::vector< TickInfo >& rTickInfoVector = rAllTickInfos[nDepth]; + rTickInfoVector.clear(); + rTickInfoVector.reserve( nCount ); + for(sal_Int32 nN = 0; nN<nCount; nN++) + { + TickInfo aTickInfo(m_xInverseScaling); + aTickInfo.fScaledTickValue = aAllTicks[nDepth][nN]; + rTickInfoVector.push_back(aTickInfo); + } + } +} + +void EquidistantTickFactory::getAllTicksShifted( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ) const +{ + ExplicitIncrementData aShiftedIncrement( m_rIncrement ); + aShiftedIncrement.BaseValue = m_rIncrement.BaseValue-m_rIncrement.Distance/2.0; + EquidistantTickFactory( m_rScale, aShiftedIncrement ).getAllTicks(rAllTickInfos); +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + +EquidistantTickIter::EquidistantTickIter( const uno::Sequence< uno::Sequence< double > >& rTicks + , const ExplicitIncrementData& rIncrement + , sal_Int32 nMinDepth, sal_Int32 nMaxDepth ) + : m_pSimpleTicks(&rTicks) + , m_pInfoTicks(0) + , m_rIncrement(rIncrement) + , m_nMinDepth(0), m_nMaxDepth(0) + , m_nTickCount(0), m_pnPositions(NULL) + , m_pnPreParentCount(NULL), m_pbIntervalFinished(NULL) + , m_nCurrentDepth(-1), m_nCurrentPos(-1), m_fCurrentValue( 0.0 ) +{ + initIter( nMinDepth, nMaxDepth ); +} + +EquidistantTickIter::EquidistantTickIter( ::std::vector< ::std::vector< TickInfo > >& rTicks + , const ExplicitIncrementData& rIncrement + , sal_Int32 nMinDepth, sal_Int32 nMaxDepth ) + : m_pSimpleTicks(NULL) + , m_pInfoTicks(&rTicks) + , m_rIncrement(rIncrement) + , m_nMinDepth(0), m_nMaxDepth(0) + , m_nTickCount(0), m_pnPositions(NULL) + , m_pnPreParentCount(NULL), m_pbIntervalFinished(NULL) + , m_nCurrentDepth(-1), m_nCurrentPos(-1), m_fCurrentValue( 0.0 ) +{ + initIter( nMinDepth, nMaxDepth ); +} + +void EquidistantTickIter::initIter( sal_Int32 /*nMinDepth*/, sal_Int32 nMaxDepth ) +{ + m_nMaxDepth = nMaxDepth; + if(nMaxDepth<0 || m_nMaxDepth>getMaxDepth()) + m_nMaxDepth=getMaxDepth(); + + sal_Int32 nDepth = 0; + for( nDepth = 0; nDepth<=m_nMaxDepth ;nDepth++ ) + m_nTickCount += getTickCount(nDepth); + + if(!m_nTickCount) + return; + + m_pnPositions = new sal_Int32[m_nMaxDepth+1]; + + m_pnPreParentCount = new sal_Int32[m_nMaxDepth+1]; + m_pbIntervalFinished = new bool[m_nMaxDepth+1]; + m_pnPreParentCount[0] = 0; + m_pbIntervalFinished[0] = false; + double fParentValue = getTickValue(0,0); + for( nDepth = 1; nDepth<=m_nMaxDepth ;nDepth++ ) + { + m_pbIntervalFinished[nDepth] = false; + + sal_Int32 nPreParentCount = 0; + sal_Int32 nCount = getTickCount(nDepth); + for(sal_Int32 nN = 0; nN<nCount; nN++) + { + if(getTickValue(nDepth,nN) < fParentValue) + nPreParentCount++; + else + break; + } + m_pnPreParentCount[nDepth] = nPreParentCount; + if(nCount) + { + double fNextParentValue = getTickValue(nDepth,0); + if( fNextParentValue < fParentValue ) + fParentValue = fNextParentValue; + } + } +} + +EquidistantTickIter::~EquidistantTickIter() +{ + delete[] m_pnPositions; + delete[] m_pnPreParentCount; + delete[] m_pbIntervalFinished; +} + +sal_Int32 EquidistantTickIter::getStartDepth() const +{ + //find the depth of the first visible tickmark: + //it is the depth of the smallest value + sal_Int32 nReturnDepth=0; + double fMinValue = DBL_MAX; + for(sal_Int32 nDepth = 0; nDepth<=m_nMaxDepth ;nDepth++ ) + { + sal_Int32 nCount = getTickCount(nDepth); + if( !nCount ) + continue; + double fThisValue = getTickValue(nDepth,0); + if(fThisValue<fMinValue) + { + nReturnDepth = nDepth; + fMinValue = fThisValue; + } + } + return nReturnDepth; +} + +double* EquidistantTickIter::firstValue() +{ + if( gotoFirst() ) + { + m_fCurrentValue = getTickValue(m_nCurrentDepth, m_pnPositions[m_nCurrentDepth]); + return &m_fCurrentValue; + } + return NULL; +} + +TickInfo* EquidistantTickIter::firstInfo() +{ + if( m_pInfoTicks && gotoFirst() ) + return &(*m_pInfoTicks)[m_nCurrentDepth][m_pnPositions[m_nCurrentDepth]]; + return NULL; +} + +sal_Int32 EquidistantTickIter::getIntervalCount( sal_Int32 nDepth ) +{ + if(nDepth>static_cast<sal_Int32>(m_rIncrement.SubIncrements.size()) || nDepth<0) + return 0; + + if(!nDepth) + return m_nTickCount; + + return m_rIncrement.SubIncrements[nDepth-1].IntervalCount; +} + +bool EquidistantTickIter::isAtLastPartTick() +{ + if(!m_nCurrentDepth) + return false; + sal_Int32 nIntervalCount = getIntervalCount( m_nCurrentDepth ); + if(!nIntervalCount || nIntervalCount == 1) + return true; + if( m_pbIntervalFinished[m_nCurrentDepth] ) + return false; + sal_Int32 nPos = m_pnPositions[m_nCurrentDepth]+1; + if(m_pnPreParentCount[m_nCurrentDepth]) + nPos += nIntervalCount-1 - m_pnPreParentCount[m_nCurrentDepth]; + bool bRet = nPos && nPos % (nIntervalCount-1) == 0; + if(!nPos && !m_pnPreParentCount[m_nCurrentDepth] + && m_pnPositions[m_nCurrentDepth-1]==-1 ) + bRet = true; + return bRet; +} + +bool EquidistantTickIter::gotoFirst() +{ + if( m_nMaxDepth<0 ) + return false; + if( !m_nTickCount ) + return false; + + for(sal_Int32 nDepth = 0; nDepth<=m_nMaxDepth ;nDepth++ ) + m_pnPositions[nDepth] = -1; + + m_nCurrentPos = 0; + m_nCurrentDepth = getStartDepth(); + m_pnPositions[m_nCurrentDepth] = 0; + return true; +} + +bool EquidistantTickIter::gotoNext() +{ + if( m_nCurrentPos < 0 ) + return false; + m_nCurrentPos++; + + if( m_nCurrentPos >= m_nTickCount ) + return false; + + if( m_nCurrentDepth==m_nMaxDepth && isAtLastPartTick() ) + { + do + { + m_pbIntervalFinished[m_nCurrentDepth] = true; + m_nCurrentDepth--; + } + while( m_nCurrentDepth && isAtLastPartTick() ); + } + else if( m_nCurrentDepth<m_nMaxDepth ) + { + do + { + m_nCurrentDepth++; + } + while( m_nCurrentDepth<m_nMaxDepth ); + } + m_pbIntervalFinished[m_nCurrentDepth] = false; + m_pnPositions[m_nCurrentDepth] = m_pnPositions[m_nCurrentDepth]+1; + return true; +} + +bool EquidistantTickIter::gotoIndex( sal_Int32 nTickIndex ) +{ + if( nTickIndex < 0 ) + return false; + if( nTickIndex >= m_nTickCount ) + return false; + + if( nTickIndex < m_nCurrentPos ) + if( !gotoFirst() ) + return false; + + while( nTickIndex > m_nCurrentPos ) + if( !gotoNext() ) + return false; + + return true; +} + +sal_Int32 EquidistantTickIter::getCurrentIndex() const +{ + return m_nCurrentPos; +} +sal_Int32 EquidistantTickIter::getMaxIndex() const +{ + return m_nTickCount-1; +} + +double* EquidistantTickIter::nextValue() +{ + if( gotoNext() ) + { + m_fCurrentValue = getTickValue(m_nCurrentDepth, m_pnPositions[m_nCurrentDepth]); + return &m_fCurrentValue; + } + return NULL; +} + +TickInfo* EquidistantTickIter::nextInfo() +{ + if( m_pInfoTicks && gotoNext() && + static_cast< sal_Int32 >( + (*m_pInfoTicks)[m_nCurrentDepth].size()) > m_pnPositions[m_nCurrentDepth] ) + { + return &(*m_pInfoTicks)[m_nCurrentDepth][m_pnPositions[m_nCurrentDepth]]; + } + return NULL; +} + +//............................................................................. +} //namespace chart +//............................................................................. diff --git a/chart2/source/view/axes/TickmarkHelper.hxx b/chart2/source/view/axes/Tickmarks_Equidistant.hxx index 27f7e0ad2086..836a93d28db2 100644 --- a/chart2/source/view/axes/TickmarkHelper.hxx +++ b/chart2/source/view/axes/Tickmarks_Equidistant.hxx @@ -1,4 +1,3 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -25,19 +24,10 @@ * for a copy of the LGPLv3 License. * ************************************************************************/ -#ifndef _CHART2_TICKMARKHELPER_HXX -#define _CHART2_TICKMARKHELPER_HXX +#ifndef _CHART2_TICKMARKS_EQUIDISTANT_HXX +#define _CHART2_TICKMARKS_EQUIDISTANT_HXX -#include "TickmarkProperties.hxx" -#include "VAxisProperties.hxx" -#include <com/sun/star/chart2/ExplicitIncrementData.hpp> -#include <com/sun/star/chart2/ExplicitScaleData.hpp> -#include <basegfx/vector/b2dvector.hxx> -#include <com/sun/star/drawing/PointSequenceSequence.hpp> -#include <com/sun/star/drawing/XShape.hpp> -#include <com/sun/star/uno/Sequence.h> - -#include <vector> +#include "Tickmarks.hxx" //............................................................................. namespace chart @@ -49,57 +39,15 @@ using ::basegfx::B2DVector; /** */ -struct TickInfo -{ - double fScaledTickValue; - double fUnscaledTickValue; - - ::basegfx::B2DVector aTickScreenPosition; - bool bPaintIt; - - ::com::sun::star::uno::Reference< - ::com::sun::star::drawing::XShape > xTextShape; - - rtl::OUString aText;//used only for complex categories so far - sal_Int32 nFactorForLimitedTextWidth;//categories in higher levels of complex categories can have more place than a single simple category - -//methods: - TickInfo(); - void updateUnscaledValue( const ::com::sun::star::uno::Reference< - ::com::sun::star::chart2::XScaling >& xInverseScaling ); - - sal_Int32 getScreenDistanceBetweenTicks( const TickInfo& rOherTickInfo ) const; -}; -class TickIter -{ -public: - virtual ~TickIter(){}; - virtual TickInfo* firstInfo()=0; - virtual TickInfo* nextInfo()=0; -}; - -class PureTickIter : public TickIter -{ -public: - PureTickIter( ::std::vector< TickInfo >& rTickInfoVector ); - virtual ~PureTickIter(); - virtual TickInfo* firstInfo(); - virtual TickInfo* nextInfo(); - -private: - ::std::vector< TickInfo >& m_rTickVector; - ::std::vector< TickInfo >::iterator m_aTickIter; -}; - class EquidistantTickIter : public TickIter { public: EquidistantTickIter( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< double > >& rTicks - , const ::com::sun::star::chart2::ExplicitIncrementData& rIncrement + , const ExplicitIncrementData& rIncrement , sal_Int32 nMinDepth=0, sal_Int32 nMaxDepth=-1 ); EquidistantTickIter( ::std::vector< ::std::vector< TickInfo > >& rTickInfos - , const ::com::sun::star::chart2::ExplicitIncrementData& rIncrement + , const ExplicitIncrementData& rIncrement , sal_Int32 nMinDepth=0, sal_Int32 nMaxDepth=-1 ); virtual ~EquidistantTickIter(); @@ -153,7 +101,7 @@ private: //member const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< double > >* m_pSimpleTicks; ::std::vector< ::std::vector< TickInfo > >* m_pInfoTicks; - const ::com::sun::star::chart2::ExplicitIncrementData& m_rIncrement; + const ExplicitIncrementData& m_rIncrement; //iteration from m_nMinDepth to m_nMaxDepth sal_Int32 m_nMinDepth; sal_Int32 m_nMaxDepth; @@ -167,24 +115,21 @@ private: //member double m_fCurrentValue; }; -class TickmarkHelper +class EquidistantTickFactory { public: - TickmarkHelper( - const ::com::sun::star::chart2::ExplicitScaleData& rScale - , const ::com::sun::star::chart2::ExplicitIncrementData& rIncrement ); - virtual ~TickmarkHelper(); + EquidistantTickFactory( + const ExplicitScaleData& rScale + , const ExplicitIncrementData& rIncrement ); + ~EquidistantTickFactory(); - virtual TickmarkHelper* createShiftedTickmarkHelper() const; + void getAllTicks( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ) const; + void getAllTicksShifted( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ) const; - void getAllTicks( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ) const; - void getAllTicksShifted( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ) const; + static double getMinimumAtIncrement( double fMin, const ExplicitIncrementData& rIncrement ); + static double getMaximumAtIncrement( double fMax, const ExplicitIncrementData& rIncrement ); - // - static double getMinimumAtIncrement( double fMin, const ::com::sun::star::chart2::ExplicitIncrementData& rIncrement ); - static double getMaximumAtIncrement( double fMax, const ::com::sun::star::chart2::ExplicitIncrementData& rIncrement ); - -protected: //methods +private: //methods void addSubTicks( sal_Int32 nDepth, ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< double > >& rParentTicks ) const; @@ -193,87 +138,29 @@ protected: //methods , double fStartParentTick, double fNextParentTick ) const; sal_Int32 getMaxTickCount( sal_Int32 nDepth = 0 ) const; sal_Int32 getTickDepth() const; + bool isVisible( double fValue ) const; bool isWithinOuterBorder( double fScaledValue ) const; //all within the outer major tick marks - virtual void updateScreenValues( ::std::vector< ::std::vector< TickInfo > >& /*rAllTickInfos*/ ) const {} - -protected: //member - ::com::sun::star::chart2::ExplicitScaleData m_rScale; - ::com::sun::star::chart2::ExplicitIncrementData m_rIncrement; - +private: //member + ExplicitScaleData m_rScale; + ExplicitIncrementData m_rIncrement; ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XScaling > m_xInverseScaling; + + //minimum and maximum of the visible range after scaling + double m_fScaledVisibleMin; + double m_fScaledVisibleMax; + double* m_pfCurrentValues; //major-tick positions that may lay outside the visible range but complete partly visible intervals at the borders double m_fOuterMajorTickBorderMin; double m_fOuterMajorTickBorderMax; double m_fOuterMajorTickBorderMin_Scaled; double m_fOuterMajorTickBorderMax_Scaled; - - //minimum and maximum of the visible range after scaling - double m_fScaledVisibleMin; - double m_fScaledVisibleMax; -}; - -class TickmarkHelper_2D : public TickmarkHelper -{ -public: - TickmarkHelper_2D( - const ::com::sun::star::chart2::ExplicitScaleData& rScale - , const ::com::sun::star::chart2::ExplicitIncrementData& rIncrement - , const ::basegfx::B2DVector& rStartScreenPos, const ::basegfx::B2DVector& rEndScreenPos - , const ::basegfx::B2DVector& rAxisLineToLabelLineShift ); - //, double fStrech_SceneToScreen, double fOffset_SceneToScreen ); - virtual ~TickmarkHelper_2D(); - - virtual TickmarkHelper* createShiftedTickmarkHelper() const; - - static sal_Int32 getTickScreenDistance( TickIter& rIter ); - - void createPointSequenceForAxisMainLine( ::com::sun::star::drawing::PointSequenceSequence& rPoints ) const; - void addPointSequenceForTickLine( ::com::sun::star::drawing::PointSequenceSequence& rPoints - , sal_Int32 nSequenceIndex - , double fScaledLogicTickValue, double fInnerDirectionSign - , const TickmarkProperties& rTickmarkProperties, bool bPlaceAtLabels ) const; - ::basegfx::B2DVector getDistanceAxisTickToText( const AxisProperties& rAxisProperties - , bool bIncludeFarAwayDistanceIfSo = false - , bool bIncludeSpaceBetweenTickAndText = true ) const; - - virtual void updateScreenValues( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ) const; - - bool isHorizontalAxis() const; - bool isVerticalAxis() const; - -protected: //methods - ::basegfx::B2DVector getTickScreenPosition2D( double fScaledLogicTickValue ) const; - -private: //member - ::basegfx::B2DVector m_aAxisStartScreenPosition2D; - ::basegfx::B2DVector m_aAxisEndScreenPosition2D; - - //labels might be posioned high or low on the border of the diagram far away from the axis - //add this vector to go from the axis line to the label line (border of the diagram) - ::basegfx::B2DVector m_aAxisLineToLabelLineShift; - - double m_fStrech_LogicToScreen; - double m_fOffset_LogicToScreen; -}; - -class TickmarkHelper_3D : public TickmarkHelper -{ -public: - TickmarkHelper_3D( - const ::com::sun::star::chart2::ExplicitScaleData& rScale - , const ::com::sun::star::chart2::ExplicitIncrementData& rIncrement ); - virtual ~TickmarkHelper_3D(); - - virtual TickmarkHelper* createShiftedTickmarkHelper() const; }; //............................................................................. } //namespace chart //............................................................................. #endif - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/axes/VAxisBase.cxx b/chart2/source/view/axes/VAxisBase.cxx index cc9402c669aa..e662634e939d 100644 --- a/chart2/source/view/axes/VAxisBase.cxx +++ b/chart2/source/view/axes/VAxisBase.cxx @@ -32,7 +32,7 @@ #include "VAxisBase.hxx" #include "ShapeFactory.hxx" #include "CommonConverters.hxx" -#include "TickmarkHelper.hxx" +#include "Tickmarks.hxx" #include "macros.hxx" // header for define DBG_ASSERT @@ -71,7 +71,7 @@ sal_Int32 VAxisBase::getDimensionCount() return m_nDimension; } -void SAL_CALL VAxisBase::initAxisLabelProperties( const ::com::sun::star::awt::Size& rFontReferenceSize +void VAxisBase::initAxisLabelProperties( const ::com::sun::star::awt::Size& rFontReferenceSize , const ::com::sun::star::awt::Rectangle& rMaximumSpaceForLabels ) { m_aAxisLabelProperties.m_aFontReferenceSize = rFontReferenceSize; @@ -107,6 +107,15 @@ void SAL_CALL VAxisBase::initAxisLabelProperties( const ::com::sun::star::awt::S m_aAxisLabelProperties.eStaggering = SIDE_BY_SIDE; } +bool VAxisBase::isDateAxis() const +{ + return AxisType::DATE == m_aScale.AxisType; +} +bool VAxisBase::isComplexCategoryAxis() const +{ + return m_aAxisProperties.m_bComplexCategories && m_bUseTextLabels; +} + void VAxisBase::recordMaximumTextSize( const Reference< drawing::XShape >& xShape, double fRotationAngleDegree ) { if( m_bRecordMaximumTextSize && xShape.is() ) @@ -131,7 +140,7 @@ void VAxisBase::setExrtaLinePositionAtOtherAxis( const double& fCrossingAt ) m_aAxisProperties.m_pfExrtaLinePositionAtOtherAxis = new double(fCrossingAt); } -sal_Bool SAL_CALL VAxisBase::isAnythingToDraw() +sal_Bool VAxisBase::isAnythingToDraw() { if( !m_aAxisProperties.m_xAxisModel.is() ) return false; @@ -151,7 +160,7 @@ sal_Bool SAL_CALL VAxisBase::isAnythingToDraw() return true; } -void SAL_CALL VAxisBase::setExplicitScaleAndIncrement( +void VAxisBase::setExplicitScaleAndIncrement( const ExplicitScaleData& rScale , const ExplicitIncrementData& rIncrement ) throw (uno::RuntimeException) @@ -163,8 +172,11 @@ void SAL_CALL VAxisBase::setExplicitScaleAndIncrement( void VAxisBase::createAllTickInfos( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ) { - std::auto_ptr< TickmarkHelper > apTickmarkHelper( this->createTickmarkHelper() ); - apTickmarkHelper->getAllTicks( rAllTickInfos ); + std::auto_ptr< TickFactory > apTickFactory( this->createTickFactory() ); + if( m_aScale.ShiftedCategoryPosition ) + apTickFactory->getAllTicksShifted( rAllTickInfos ); + else + apTickFactory->getAllTicks( rAllTickInfos ); } bool VAxisBase::prepareShapeCreation() @@ -245,7 +257,7 @@ void VAxisBase::updateUnscaledValuesAtTicks( TickIter& rIter ) for( TickInfo* pTickInfo = rIter.firstInfo() ; pTickInfo; pTickInfo = rIter.nextInfo() ) { - pTickInfo->updateUnscaledValue( xInverseScaling ); + //xxxxx pTickInfo->updateUnscaledValue( xInverseScaling ); } } diff --git a/chart2/source/view/axes/VAxisBase.hxx b/chart2/source/view/axes/VAxisBase.hxx index fbf1bc6eb0f6..ecee96c8e339 100644 --- a/chart2/source/view/axes/VAxisBase.hxx +++ b/chart2/source/view/axes/VAxisBase.hxx @@ -30,7 +30,7 @@ #include "VAxisOrGridBase.hxx" #include "VAxisProperties.hxx" -#include "TickmarkHelper.hxx" +#include "Tickmarks.hxx" #include <com/sun/star/util/XNumberFormatsSupplier.hpp> //............................................................................. @@ -53,18 +53,18 @@ public: sal_Int32 getDimensionCount(); - virtual void SAL_CALL createMaximumLabels()=0; - virtual void SAL_CALL createLabels()=0; - virtual void SAL_CALL updatePositions()=0; + virtual void createMaximumLabels()=0; + virtual void createLabels()=0; + virtual void updatePositions()=0; - virtual sal_Bool SAL_CALL isAnythingToDraw(); - virtual void SAL_CALL initAxisLabelProperties( + virtual sal_Bool isAnythingToDraw(); + virtual void initAxisLabelProperties( const ::com::sun::star::awt::Size& rFontReferenceSize , const ::com::sun::star::awt::Rectangle& rMaximumSpaceForLabels ); - virtual void SAL_CALL setExplicitScaleAndIncrement( - const ::com::sun::star::chart2::ExplicitScaleData& rScale - , const ::com::sun::star::chart2::ExplicitIncrementData& rIncrement ) + virtual void setExplicitScaleAndIncrement( + const ExplicitScaleData& rScale + , const ExplicitIncrementData& rIncrement ) throw (::com::sun::star::uno::RuntimeException); virtual sal_Int32 estimateMaximumAutoMainIncrementCount(); @@ -84,6 +84,9 @@ protected: //methods ::com::sun::star::drawing::XShape >& xShape , double fRotationAngleDegree ); + bool isDateAxis() const; + bool isComplexCategoryAxis() const; + protected: //member ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier > m_xNumberFormatsSupplier; AxisProperties m_aAxisProperties; diff --git a/chart2/source/view/axes/VAxisOrGridBase.cxx b/chart2/source/view/axes/VAxisOrGridBase.cxx index 19e219e5fb37..489af51f7c0e 100644 --- a/chart2/source/view/axes/VAxisOrGridBase.cxx +++ b/chart2/source/view/axes/VAxisOrGridBase.cxx @@ -32,7 +32,7 @@ #include "VAxisOrGridBase.hxx" #include "ShapeFactory.hxx" #include "CommonConverters.hxx" -#include "TickmarkHelper.hxx" +#include "Tickmarks.hxx" // header for define DBG_ASSERT #include <tools/debug.hxx> @@ -58,7 +58,7 @@ VAxisOrGridBase::~VAxisOrGridBase() { } -void SAL_CALL VAxisOrGridBase::setExplicitScaleAndIncrement( +void VAxisOrGridBase::setExplicitScaleAndIncrement( const ExplicitScaleData& rScale , const ExplicitIncrementData& rIncrement ) throw (uno::RuntimeException) @@ -80,18 +80,9 @@ void VAxisOrGridBase::set3DWallPositions( CuboidPlanePosition eLeftWallPos, Cubo m_eBottomPos = eBottomPos; } -TickmarkHelper* VAxisOrGridBase::createTickmarkHelper() +TickFactory* VAxisOrGridBase::createTickFactory() { - TickmarkHelper* pRet=NULL; - if( 2==m_nDimension ) - { - pRet = new TickmarkHelper( m_aScale, m_aIncrement ); - } - else - { - pRet = new TickmarkHelper_3D( m_aScale, m_aIncrement ); - } - return pRet; + return new TickFactory( m_aScale, m_aIncrement ); } //............................................................................. diff --git a/chart2/source/view/axes/VAxisOrGridBase.hxx b/chart2/source/view/axes/VAxisOrGridBase.hxx index e884fe785954..38a89b7b86f9 100644 --- a/chart2/source/view/axes/VAxisOrGridBase.hxx +++ b/chart2/source/view/axes/VAxisOrGridBase.hxx @@ -30,9 +30,8 @@ #include "PlotterBase.hxx" #include "ThreeDHelper.hxx" +#include "chartview/ExplicitScaleValues.hxx" -#include <com/sun/star/chart2/ExplicitIncrementData.hpp> -#include <com/sun/star/chart2/ExplicitScaleData.hpp> #include <com/sun/star/drawing/HomogenMatrix.hpp> #include <com/sun/star/drawing/XShapes.hpp> #include <com/sun/star/lang/XMultiServiceFactory.hpp> @@ -47,7 +46,7 @@ namespace chart /** */ class ShapeFactory; -class TickmarkHelper; +class TickFactory; class VAxisOrGridBase : public PlotterBase { @@ -56,22 +55,22 @@ public: virtual ~VAxisOrGridBase(); virtual void setTransformationSceneToScreen( const ::com::sun::star::drawing::HomogenMatrix& rMatrix ); - virtual void SAL_CALL setExplicitScaleAndIncrement( - const ::com::sun::star::chart2::ExplicitScaleData& rScale - , const ::com::sun::star::chart2::ExplicitIncrementData& rIncrement ) + virtual void setExplicitScaleAndIncrement( + const ExplicitScaleData& rScale + , const ExplicitIncrementData& rIncrement ) throw (::com::sun::star::uno::RuntimeException); void set3DWallPositions( CuboidPlanePosition eLeftWallPos, CuboidPlanePosition eBackWallPos, CuboidPlanePosition eBottomPos ); - virtual TickmarkHelper* createTickmarkHelper(); + virtual TickFactory* createTickFactory(); //------------------------------------------------------------------------- //------------------------------------------------------------------------- protected: //member - ::com::sun::star::chart2::ExplicitScaleData m_aScale; - ::com::sun::star::chart2::ExplicitIncrementData m_aIncrement; - sal_Int32 m_nDimensionIndex; + ExplicitScaleData m_aScale; + ExplicitIncrementData m_aIncrement; + sal_Int32 m_nDimensionIndex; - ::basegfx::B3DHomMatrix m_aMatrixScreenToScene; + ::basegfx::B3DHomMatrix m_aMatrixScreenToScene; CuboidPlanePosition m_eLeftWallPos; CuboidPlanePosition m_eBackWallPos; diff --git a/chart2/source/view/axes/VAxisProperties.cxx b/chart2/source/view/axes/VAxisProperties.cxx index 4bf06fd1c032..1063789d1db7 100644 --- a/chart2/source/view/axes/VAxisProperties.cxx +++ b/chart2/source/view/axes/VAxisProperties.cxx @@ -183,7 +183,6 @@ AxisProperties::AxisProperties( const uno::Reference< XAxis >& xAxisModel , m_pfExrtaLinePositionAtOtherAxis(NULL) , m_bCrossingAxisHasReverseDirection(false) , m_bCrossingAxisIsCategoryAxes(false) - , m_bAxisBetweenCategories(false) , m_fLabelDirectionSign(1.0) , m_fInnerDirectionSign(1.0) , m_aLabelAlignment(LABEL_ALIGN_RIGHT_TOP) @@ -213,7 +212,6 @@ AxisProperties::AxisProperties( const AxisProperties& rAxisProperties ) , m_pfExrtaLinePositionAtOtherAxis( NULL ) , m_bCrossingAxisHasReverseDirection( rAxisProperties.m_bCrossingAxisHasReverseDirection ) , m_bCrossingAxisIsCategoryAxes( rAxisProperties.m_bCrossingAxisIsCategoryAxes ) - , m_bAxisBetweenCategories( rAxisProperties.m_bAxisBetweenCategories ) , m_fLabelDirectionSign( rAxisProperties.m_fLabelDirectionSign ) , m_fInnerDirectionSign( rAxisProperties.m_fInnerDirectionSign ) , m_aLabelAlignment( rAxisProperties.m_aLabelAlignment ) @@ -280,11 +278,7 @@ void AxisProperties::initAxisPositioning( const uno::Reference< beans::XProperty xAxisProp->getPropertyValue(C2U( "CrossoverValue" )) >>= fValue; if( m_bCrossingAxisIsCategoryAxes ) - { fValue = ::rtl::math::round(fValue); - if( m_bAxisBetweenCategories ) - fValue-=0.5; - } m_pfMainLinePositionAtOtherAxis = new double(fValue); } else if( ::com::sun::star::chart::ChartAxisPosition_ZERO == m_eCrossoverType ) @@ -318,8 +312,17 @@ void AxisProperties::init( bool bCartesian ) if( m_nDimensionIndex<2 ) initAxisPositioning( xProp ); + ScaleData aScaleData = m_xAxisModel->getScaleData(); + if( m_nDimensionIndex==0 ) + AxisHelper::checkDateAxis( aScaleData, m_pExplicitCategoriesProvider, bCartesian ); + m_nAxisType = aScaleData.AxisType; + if( bCartesian ) { + if( m_nDimensionIndex == 0 && m_nAxisType == AxisType::CATEGORY + && m_pExplicitCategoriesProvider && m_pExplicitCategoriesProvider->hasComplexCategories() ) + m_bComplexCategories = true; + if( ::com::sun::star::chart::ChartAxisPosition_END == m_eCrossoverType ) m_fInnerDirectionSign = m_bCrossingAxisHasReverseDirection ? 1 : -1; else @@ -361,10 +364,6 @@ void AxisProperties::init( bool bCartesian ) //init display labels xProp->getPropertyValue( C2U( "DisplayLabels" ) ) >>= m_bDisplayLabels; - //init categories - ScaleData aScaleData = m_xAxisModel->getScaleData(); - m_nAxisType = aScaleData.AxisType; - //init TickmarkProperties xProp->getPropertyValue( C2U( "MajorTickmarks" ) ) >>= m_nMajorTickmarks; xProp->getPropertyValue( C2U( "MinorTickmarks" ) ) >>= m_nMinorTickmarks; diff --git a/chart2/source/view/axes/VAxisProperties.hxx b/chart2/source/view/axes/VAxisProperties.hxx index 0f2c835cbf29..9e57ee4b5c65 100644 --- a/chart2/source/view/axes/VAxisProperties.hxx +++ b/chart2/source/view/axes/VAxisProperties.hxx @@ -112,7 +112,6 @@ struct AxisProperties bool m_bCrossingAxisHasReverseDirection; bool m_bCrossingAxisIsCategoryAxes; - bool m_bAxisBetweenCategories; //this direction is used to indicate in which direction the labels are to be drawn double m_fLabelDirectionSign; diff --git a/chart2/source/view/axes/VCartesianAxis.cxx b/chart2/source/view/axes/VCartesianAxis.cxx index d22a9ff4b7b8..5451f5cbb9ab 100644 --- a/chart2/source/view/axes/VCartesianAxis.cxx +++ b/chart2/source/view/axes/VCartesianAxis.cxx @@ -37,11 +37,12 @@ #include "macros.hxx" #include "ViewDefines.hxx" #include "PropertyMapper.hxx" -#include "chartview/NumberFormatterWrapper.hxx" +#include "NumberFormatterWrapper.hxx" #include "LabelPositionHelper.hxx" #include "TrueGuard.hxx" #include "BaseGFXHelper.hxx" #include "AxisHelper.hxx" +#include "Tickmarks_Equidistant.hxx" #include <rtl/math.hxx> #include <tools/color.hxx> @@ -49,6 +50,8 @@ #include <com/sun/star/text/XText.hpp> #include <com/sun/star/text/WritingMode2.hpp> #include <editeng/unoprnms.hxx> +#include <svx/unoshape.hxx> +#include <svx/unoshtxt.hxx> #include <algorithm> #include <memory> @@ -111,7 +114,7 @@ Reference< drawing::XShape > createSingleLabel( //correctPositionForRotation LabelPositionHelper::correctPositionForRotation( xShape2DText - , rAxisProperties.m_aLabelAlignment, rAxisLabelProperties.fRotationAngleDegree, false ); + , rAxisProperties.m_aLabelAlignment, rAxisLabelProperties.fRotationAngleDegree, rAxisProperties.m_bComplexCategories ); return xShape2DText; } @@ -177,7 +180,7 @@ void removeShapesAtWrongRhythm( TickIter& rIter } } -class EquidistantLabelIterator : public EquidistantTickIter +class LabelIterator : public TickIter { //this Iterator iterates over existing text labels @@ -191,39 +194,36 @@ class EquidistantLabelIterator : public EquidistantTickIter //we iterate through all labels public: - EquidistantLabelIterator( ::std::vector< ::std::vector< TickInfo > >& rTickInfos - , const ::com::sun::star::chart2::ExplicitIncrementData& rIncrement + LabelIterator( ::std::vector< TickInfo >& rTickInfoVector , const AxisLabelStaggering eAxisLabelStaggering - , bool bInnerLine - , sal_Int32 nMinDepth=0, sal_Int32 nMaxDepth=-1 ); + , bool bInnerLine ); virtual TickInfo* firstInfo(); virtual TickInfo* nextInfo(); private: //methods - EquidistantLabelIterator(); + LabelIterator(); private: //member + PureTickIter m_aPureTickIter; const AxisLabelStaggering m_eAxisLabelStaggering; - bool m_bInnerLine; + bool m_bInnerLine; }; -EquidistantLabelIterator::EquidistantLabelIterator( ::std::vector< ::std::vector< TickInfo > >& rTickInfos - , const ::com::sun::star::chart2::ExplicitIncrementData& rIncrement +LabelIterator::LabelIterator( ::std::vector< TickInfo >& rTickInfoVector , const AxisLabelStaggering eAxisLabelStaggering - , bool bInnerLine - , sal_Int32 nMinDepth, sal_Int32 nMaxDepth ) - : EquidistantTickIter( rTickInfos, rIncrement, nMinDepth, nMaxDepth ) + , bool bInnerLine ) + : m_aPureTickIter( rTickInfoVector ) , m_eAxisLabelStaggering(eAxisLabelStaggering) , m_bInnerLine(bInnerLine) { } -TickInfo* EquidistantLabelIterator::firstInfo() +TickInfo* LabelIterator::firstInfo() { - TickInfo* pTickInfo = EquidistantTickIter::firstInfo(); + TickInfo* pTickInfo = m_aPureTickIter.firstInfo(); while( pTickInfo && !pTickInfo->xTextShape.is() ) - pTickInfo = EquidistantTickIter::nextInfo(); + pTickInfo = m_aPureTickIter.nextInfo(); if(!pTickInfo) return NULL; if( (STAGGER_EVEN==m_eAxisLabelStaggering && m_bInnerLine) @@ -233,7 +233,7 @@ TickInfo* EquidistantLabelIterator::firstInfo() { //skip first label do - pTickInfo = EquidistantTickIter::nextInfo(); + pTickInfo = m_aPureTickIter.nextInfo(); while( pTickInfo && !pTickInfo->xTextShape.is() ); } if(!pTickInfo) @@ -241,12 +241,12 @@ TickInfo* EquidistantLabelIterator::firstInfo() return pTickInfo; } -TickInfo* EquidistantLabelIterator::nextInfo() +TickInfo* LabelIterator::nextInfo() { TickInfo* pTickInfo = NULL; //get next label do - pTickInfo = EquidistantTickIter::nextInfo(); + pTickInfo = m_aPureTickIter.nextInfo(); while( pTickInfo && !pTickInfo->xTextShape.is() ); if( STAGGER_EVEN==m_eAxisLabelStaggering @@ -254,13 +254,13 @@ TickInfo* EquidistantLabelIterator::nextInfo() { //skip one label do - pTickInfo = EquidistantTickIter::nextInfo(); + pTickInfo = m_aPureTickIter.nextInfo(); while( pTickInfo && !pTickInfo->xTextShape.is() ); } return pTickInfo; } -B2DVector lcl_getLabelsDistance( TickIter& rIter, const B2DVector& rDistanceTickToText ) +B2DVector lcl_getLabelsDistance( TickIter& rIter, const B2DVector& rDistanceTickToText, double fRotationAngleDegree ) { //calculates the height or width of a line of labels //thus a following line of labels can be shifted for that distance @@ -283,7 +283,7 @@ B2DVector lcl_getLabelsDistance( TickIter& rIter, const B2DVector& rDistanceTick xShape2DText = pTickInfo->xTextShape; if( xShape2DText.is() ) { - awt::Size aSize = xShape2DText->getSize(); + awt::Size aSize = ShapeFactory::getSizeAfterRotation( xShape2DText, fRotationAngleDegree ); if(fabs(aStaggerDirection.getX())>fabs(aStaggerDirection.getY())) nDistance = ::std::max(nDistance,aSize.Width); else @@ -320,64 +320,102 @@ void lcl_shiftLables( TickIter& rIter, const B2DVector& rStaggerDistance ) } } -class MaxLabelEquidistantTickIter : public EquidistantTickIter +bool lcl_hasWordBreak( const Reference< drawing::XShape >& rxShape ) +{ + if ( rxShape.is() ) + { + SvxShape* pShape = SvxShape::getImplementation( rxShape ); + SvxShapeText* pShapeText = dynamic_cast< SvxShapeText* >( pShape ); + if ( pShapeText ) + { + SvxTextEditSource* pTextEditSource = dynamic_cast< SvxTextEditSource* >( pShapeText->GetEditSource() ); + if ( pTextEditSource ) + { + pTextEditSource->UpdateOutliner(); + SvxTextForwarder* pTextForwarder = pTextEditSource->GetTextForwarder(); + if ( pTextForwarder ) + { + sal_uInt16 nParaCount = pTextForwarder->GetParagraphCount(); + for ( sal_uInt16 nPara = 0; nPara < nParaCount; ++nPara ) + { + sal_uInt16 nLineCount = pTextForwarder->GetLineCount( nPara ); + for ( sal_uInt16 nLine = 0; nLine < nLineCount; ++nLine ) + { + sal_uInt16 nLineStart = 0; + sal_uInt16 nLineEnd = 0; + pTextForwarder->GetLineBoundaries( nLineStart, nLineEnd, nPara, nLine ); + sal_uInt16 nWordStart = 0; + sal_uInt16 nWordEnd = 0; + if ( pTextForwarder->GetWordIndices( nPara, nLineStart, nWordStart, nWordEnd ) && + ( nWordStart != nLineStart ) ) + { + return true; + } + } + } + } + } + } + } + + return false; +} + +class MaxLabelTickIter : public TickIter { //iterate over first two and last two labels and the longest label public: - MaxLabelEquidistantTickIter( ::std::vector< ::std::vector< TickInfo > >& rTickInfos - , const ::com::sun::star::chart2::ExplicitIncrementData& rIncrement + MaxLabelTickIter( ::std::vector< TickInfo >& rTickInfoVector , sal_Int32 nLongestLabelIndex ); - virtual ~MaxLabelEquidistantTickIter(); + virtual ~MaxLabelTickIter(); - virtual TickInfo* nextInfo(); + virtual TickInfo* firstInfo(); + virtual TickInfo* nextInfo(); private: - sal_Int32 m_nLongestLabelIndex; + ::std::vector< TickInfo >& m_rTickInfoVector; + ::std::vector< sal_Int32 > m_aValidIndices; + sal_Int32 m_nCurrentIndex; }; -MaxLabelEquidistantTickIter::MaxLabelEquidistantTickIter( ::std::vector< ::std::vector< TickInfo > >& rTickInfos - , const ::com::sun::star::chart2::ExplicitIncrementData& rIncrement +MaxLabelTickIter::MaxLabelTickIter( ::std::vector< TickInfo >& rTickInfoVector , sal_Int32 nLongestLabelIndex ) - : EquidistantTickIter( rTickInfos, rIncrement, 0//nMinDepth - , 0//nMaxDepth - ) - , m_nLongestLabelIndex( nLongestLabelIndex ) + : m_rTickInfoVector(rTickInfoVector) + , m_nCurrentIndex(0) { - sal_Int32 nMaxIndex = getMaxIndex(); - - //ensure correct value: - if( m_nLongestLabelIndex<0 || m_nLongestLabelIndex>nMaxIndex) - m_nLongestLabelIndex = 0; - - //last label is checked anyhow - if( m_nLongestLabelIndex==nMaxIndex ) - m_nLongestLabelIndex = 0; - //label before last is checked anyhow - if( m_nLongestLabelIndex+1==nMaxIndex ) - m_nLongestLabelIndex = 0; + sal_Int32 nMaxIndex = m_rTickInfoVector.size()-1; + if( nLongestLabelIndex<0 || nLongestLabelIndex>=nMaxIndex-1 ) + nLongestLabelIndex = 0; + + if( nMaxIndex>=0 ) + m_aValidIndices.push_back(0); + if( nMaxIndex>=1 ) + m_aValidIndices.push_back(1); + if( nLongestLabelIndex>1 ) + m_aValidIndices.push_back(nLongestLabelIndex); + if( nMaxIndex > 2 ) + m_aValidIndices.push_back(nMaxIndex-1); + if( nMaxIndex > 1 ) + m_aValidIndices.push_back(nMaxIndex); } -MaxLabelEquidistantTickIter::~MaxLabelEquidistantTickIter() +MaxLabelTickIter::~MaxLabelTickIter() { } -TickInfo* MaxLabelEquidistantTickIter::nextInfo() +TickInfo* MaxLabelTickIter::firstInfo() { - sal_Int32 nCurrentPos = getCurrentIndex(); - sal_Int32 nMaxIndex = getMaxIndex(); - if( nCurrentPos>0 ) - { - if( m_nLongestLabelIndex>1 && nCurrentPos<m_nLongestLabelIndex ) - gotoIndex( m_nLongestLabelIndex-1 ) ; - else - { - if( nMaxIndex>3 && nCurrentPos<nMaxIndex-1 ) - gotoIndex( nMaxIndex-2 ); - else if( nMaxIndex>2 && nCurrentPos<nMaxIndex ) - gotoIndex( nMaxIndex-1 ); - } - } + m_nCurrentIndex = 0; + if( m_nCurrentIndex < static_cast<sal_Int32>(m_aValidIndices.size()) ) + return &m_rTickInfoVector[m_aValidIndices[m_nCurrentIndex]]; + return 0; +} - return EquidistantTickIter::nextInfo(); +TickInfo* MaxLabelTickIter::nextInfo() +{ + m_nCurrentIndex++; + if( m_nCurrentIndex>=0 && m_nCurrentIndex<static_cast<sal_Int32>(m_aValidIndices.size()) ) + return &m_rTickInfoVector[m_aValidIndices[m_nCurrentIndex]]; + return 0; } bool VCartesianAxis::isBreakOfLabelsAllowed( const AxisLabelProperties& rAxisLabelProperties @@ -447,27 +485,27 @@ void VCartesianAxis::createAllTickInfosFromComplexCategories( ::std::vector< ::s std::vector< ComplexCategory >::const_iterator aEnd(aComplexCategories.end()); for(;aIt!=aEnd;++aIt) { - TickInfo aTickInfo; + TickInfo aTickInfo(0); ComplexCategory aCat(*aIt); sal_Int32 nCount = aCat.Count; - if( nCatIndex + 0.5 + nCount >= m_aScale.Maximum ) + if( nCatIndex + 1.0 + nCount >= m_aScale.Maximum ) { - nCount = static_cast<sal_Int32>(m_aScale.Maximum - 0.5 - nCatIndex); + nCount = static_cast<sal_Int32>(m_aScale.Maximum - 1.0 - nCatIndex); if( nCount <= 0 ) nCount = 1; } - aTickInfo.fScaledTickValue = nCatIndex + 0.5 + nCount/2.0; + aTickInfo.fScaledTickValue = nCatIndex + 1.0 + nCount/2.0; aTickInfo.nFactorForLimitedTextWidth = nCount; aTickInfo.aText = aCat.Text; aTickInfoVector.push_back(aTickInfo); nCatIndex += nCount; - if( nCatIndex + 0.5 >= m_aScale.Maximum ) + if( nCatIndex + 1.0 >= m_aScale.Maximum ) break; } rAllTickInfos.push_back(aTickInfoVector); } } - else //bShiftedPosition==true + else //bShiftedPosition==false { rAllTickInfos.clear(); sal_Int32 nLevel=0; @@ -481,19 +519,19 @@ void VCartesianAxis::createAllTickInfosFromComplexCategories( ::std::vector< ::s std::vector< ComplexCategory >::const_iterator aEnd(aComplexCategories.end()); for(;aIt!=aEnd;++aIt) { - TickInfo aTickInfo; + TickInfo aTickInfo(0); ComplexCategory aCat(*aIt); - aTickInfo.fScaledTickValue = nCatIndex + 0.5; + aTickInfo.fScaledTickValue = nCatIndex + 1.0; aTickInfoVector.push_back(aTickInfo); nCatIndex += aCat.Count; - if( nCatIndex + 0.5 > m_aScale.Maximum ) + if( nCatIndex + 1.0 > m_aScale.Maximum ) break; } //fill up with single ticks until maximum scale - while( nCatIndex + 0.5 < m_aScale.Maximum ) + while( nCatIndex + 1.0 < m_aScale.Maximum ) { - TickInfo aTickInfo; - aTickInfo.fScaledTickValue = nCatIndex + 0.5; + TickInfo aTickInfo(0); + aTickInfo.fScaledTickValue = nCatIndex + 1.0; aTickInfoVector.push_back(aTickInfo); nCatIndex ++; if( nLevel>0 ) @@ -501,7 +539,7 @@ void VCartesianAxis::createAllTickInfosFromComplexCategories( ::std::vector< ::s } //add an additional tick at the end { - TickInfo aTickInfo; + TickInfo aTickInfo(0); aTickInfo.fScaledTickValue = m_aScale.Maximum; aTickInfoVector.push_back(aTickInfo); } @@ -512,7 +550,7 @@ void VCartesianAxis::createAllTickInfosFromComplexCategories( ::std::vector< ::s void VCartesianAxis::createAllTickInfos( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ) { - if( m_aAxisProperties.m_bComplexCategories && m_bUseTextLabels ) + if( isComplexCategoryAxis() ) createAllTickInfosFromComplexCategories( rAllTickInfos, false ); else VAxisBase::createAllTickInfos(rAllTickInfos); @@ -520,21 +558,13 @@ void VCartesianAxis::createAllTickInfos( ::std::vector< ::std::vector< TickInfo ::std::auto_ptr< TickIter > VCartesianAxis::createLabelTickIterator( sal_Int32 nTextLevel ) { - if( m_aAxisProperties.m_bComplexCategories && m_bUseTextLabels ) - { - if( nTextLevel>=0 && nTextLevel < static_cast< sal_Int32 >(m_aAllTickInfos.size()) ) - return ::std::auto_ptr< TickIter >( new PureTickIter( m_aAllTickInfos[nTextLevel] ) ); - } - else - { - if(nTextLevel==0) - return ::std::auto_ptr< TickIter >( new EquidistantTickIter( m_aAllTickInfos, m_aIncrement, 0, 0 ) ); - } + if( nTextLevel>=0 && nTextLevel < static_cast< sal_Int32 >(m_aAllTickInfos.size()) ) + return ::std::auto_ptr< TickIter >( new PureTickIter( m_aAllTickInfos[nTextLevel] ) ); return ::std::auto_ptr< TickIter >(); } ::std::auto_ptr< TickIter > VCartesianAxis::createMaximumLabelTickIterator( sal_Int32 nTextLevel ) { - if( m_aAxisProperties.m_bComplexCategories && m_bUseTextLabels ) + if( isComplexCategoryAxis() || isDateAxis() ) { return createLabelTickIterator( nTextLevel ); //mmmm maybe todo: create less than all texts here } @@ -542,8 +572,11 @@ void VCartesianAxis::createAllTickInfos( ::std::vector< ::std::vector< TickInfo { if(nTextLevel==0) { - sal_Int32 nLongestLabelIndex = m_bUseTextLabels ? this->getIndexOfLongestLabel( m_aTextLabels ) : 0; - return ::std::auto_ptr< TickIter >( new MaxLabelEquidistantTickIter( m_aAllTickInfos, m_aIncrement, nLongestLabelIndex ) ); + if( !m_aAllTickInfos.empty() ) + { + sal_Int32 nLongestLabelIndex = m_bUseTextLabels ? this->getIndexOfLongestLabel( m_aTextLabels ) : 0; + return ::std::auto_ptr< TickIter >( new MaxLabelTickIter( m_aAllTickInfos[0], nLongestLabelIndex ) ); + } } } return ::std::auto_ptr< TickIter >(); @@ -552,7 +585,7 @@ void VCartesianAxis::createAllTickInfos( ::std::vector< ::std::vector< TickInfo sal_Int32 VCartesianAxis::getTextLevelCount() const { sal_Int32 nTextLevelCount = 1; - if( m_aAxisProperties.m_bComplexCategories && m_bUseTextLabels ) + if( isComplexCategoryAxis() ) nTextLevelCount = m_aAxisProperties.m_pExplicitCategoriesProvider->getCategoryLevelCount(); return nTextLevelCount; } @@ -561,7 +594,7 @@ bool VCartesianAxis::createTextShapes( const Reference< drawing::XShapes >& xTarget , TickIter& rTickIter , AxisLabelProperties& rAxisLabelProperties - , TickmarkHelper_2D* pTickmarkHelper + , TickFactory_2D* pTickFactory , sal_Int32 nScreenDistanceBetweenTicks ) { //returns true if the text shapes have been created succesfully @@ -575,10 +608,10 @@ bool VCartesianAxis::createTextShapes( FixedNumberFormatter aFixedNumberFormatter( m_xNumberFormatsSupplier, rAxisLabelProperties.nNumberFormatKey ); - const bool bIsHorizontalAxis = pTickmarkHelper->isHorizontalAxis(); - const bool bIsVerticalAxis = pTickmarkHelper->isVerticalAxis(); + const bool bIsHorizontalAxis = pTickFactory->isHorizontalAxis(); + const bool bIsVerticalAxis = pTickFactory->isVerticalAxis(); bool bIsStaggered = rAxisLabelProperties.getIsStaggered(); - B2DVector aTextToTickDistance( pTickmarkHelper->getDistanceAxisTickToText( m_aAxisProperties, true ) ); + B2DVector aTextToTickDistance( pTickFactory->getDistanceAxisTickToText( m_aAxisProperties, true ) ); sal_Int32 nLimitedSpaceForText = -1; if( isBreakOfLabelsAllowed( rAxisLabelProperties, bIsHorizontalAxis ) ) { @@ -674,7 +707,7 @@ bool VCartesianAxis::createTextShapes( } } - pTickInfo->updateUnscaledValue( xInverseScaling ); + //xxxxx pTickInfo->updateUnscaledValue( xInverseScaling ); bool bHasExtraColor=false; sal_Int32 nExtraColor=0; @@ -682,7 +715,7 @@ bool VCartesianAxis::createTextShapes( rtl::OUString aLabel; if(pCategories) { - sal_Int32 nIndex = static_cast< sal_Int32 >(pTickInfo->fUnscaledTickValue) - 1; //first category (index 0) matches with real number 1.0 + sal_Int32 nIndex = static_cast< sal_Int32 >(pTickInfo->getUnscaledTickValue()) - 1; //first category (index 0) matches with real number 1.0 if( nIndex>=0 && nIndex<pCategories->getLength() ) aLabel = (*pCategories)[nIndex]; } @@ -691,7 +724,7 @@ bool VCartesianAxis::createTextShapes( aLabel = pTickInfo->aText; } else - aLabel = aFixedNumberFormatter.getFormattedString( pTickInfo->fUnscaledTickValue, nExtraColor, bHasExtraColor ); + aLabel = aFixedNumberFormatter.getFormattedString( pTickInfo->getUnscaledTickValue(), nExtraColor, bHasExtraColor ); if(pColorAny) *pColorAny = uno::makeAny(bHasExtraColor?nExtraColor:nColor); @@ -715,10 +748,23 @@ bool VCartesianAxis::createTextShapes( recordMaximumTextSize( pTickInfo->xTextShape, rAxisLabelProperties.fRotationAngleDegree ); + //better rotate if single words are broken apart + if( nLimitedSpaceForText>0 && !rAxisLabelProperties.bOverlapAllowed + && ::rtl::math::approxEqual( rAxisLabelProperties.fRotationAngleDegree, 0.0 ) + && m_aAxisProperties.m_bComplexCategories + && lcl_hasWordBreak( pTickInfo->xTextShape ) ) + { + rAxisLabelProperties.fRotationAngleDegree = 90; + rAxisLabelProperties.bLineBreakAllowed = false; + m_aAxisLabelProperties.fRotationAngleDegree = rAxisLabelProperties.fRotationAngleDegree; + removeTextShapesFromTicks(); + return false; + } + //if NO OVERLAP -> remove overlapping shapes if( pLastVisibleNeighbourTickInfo && !rAxisLabelProperties.bOverlapAllowed ) { - if( doesOverlap( pLastVisibleNeighbourTickInfo->xTextShape, pTickInfo->xTextShape, m_aAxisLabelProperties.fRotationAngleDegree ) ) + if( doesOverlap( pLastVisibleNeighbourTickInfo->xTextShape, pTickInfo->xTextShape, rAxisLabelProperties.fRotationAngleDegree ) ) { bool bOverlapAlsoAfterSwitchingOnAutoStaggering = true; if( !bIsStaggered && isAutoStaggeringOfLabelsAllowed( rAxisLabelProperties, bIsHorizontalAxis, bIsVerticalAxis ) ) @@ -1190,12 +1236,12 @@ void VCartesianAxis::get2DAxisMainLine( B2DVector& rStart, B2DVector& rEnd, doub } } -TickmarkHelper* VCartesianAxis::createTickmarkHelper() +TickFactory* VCartesianAxis::createTickFactory() { - return createTickmarkHelper2D(); + return createTickFactory2D(); } -TickmarkHelper_2D* VCartesianAxis::createTickmarkHelper2D() +TickFactory_2D* VCartesianAxis::createTickFactory2D() { B2DVector aStart, aEnd; this->get2DAxisMainLine( aStart, aEnd, this->getLogicValueWhereMainLineCrossesOtherAxis() ); @@ -1203,7 +1249,7 @@ TickmarkHelper_2D* VCartesianAxis::createTickmarkHelper2D() B2DVector aLabelLineStart, aLabelLineEnd; this->get2DAxisMainLine( aLabelLineStart, aLabelLineEnd, this->getLogicValueWhereLabelLineCrossesOtherAxis() ); - return new TickmarkHelper_2D( m_aScale, m_aIncrement, aStart, aEnd, aLabelLineStart-aStart ); + return new TickFactory_2D( m_aScale, m_aIncrement, aStart, aEnd, aLabelLineStart-aStart ); } void lcl_hideIdenticalScreenValues( TickIter& rTickIter ) @@ -1227,7 +1273,7 @@ void lcl_hideIdenticalScreenValues( TickIter& rTickIter ) //'hide' tickmarks with identical screen values in aAllTickInfos void VCartesianAxis::hideIdenticalScreenValues( ::std::vector< ::std::vector< TickInfo > >& rTickInfos ) const { - if( m_aAxisProperties.m_bComplexCategories && m_bUseTextLabels ) + if( isComplexCategoryAxis() || isDateAxis() ) { sal_Int32 nCount = rTickInfos.size(); for( sal_Int32 nN=0; nN<nCount; nN++ ) @@ -1273,12 +1319,12 @@ sal_Int32 VCartesianAxis::estimateMaximumAutoMainIncrementCount() return nRet; } -void VCartesianAxis::doStaggeringOfLabels( const AxisLabelProperties& rAxisLabelProperties, TickmarkHelper_2D* pTickmarkHelper2D ) +void VCartesianAxis::doStaggeringOfLabels( const AxisLabelProperties& rAxisLabelProperties, TickFactory_2D* pTickFactory2D ) { - if( !pTickmarkHelper2D ) + if( !pTickFactory2D ) return; - if( m_aAxisProperties.m_bComplexCategories && m_bUseTextLabels ) + if( isComplexCategoryAxis() ) { sal_Int32 nTextLevelCount = getTextLevelCount(); B2DVector aCummulatedLabelsDistance(0,0); @@ -1287,27 +1333,33 @@ void VCartesianAxis::doStaggeringOfLabels( const AxisLabelProperties& rAxisLabel ::std::auto_ptr< TickIter > apTickIter = createLabelTickIterator( nTextLevel ); if(apTickIter.get()) { + double fRotationAngleDegree = m_aAxisLabelProperties.fRotationAngleDegree; if( nTextLevel>0 ) + { lcl_shiftLables( *apTickIter.get(), aCummulatedLabelsDistance ); + fRotationAngleDegree = 0.0; + } aCummulatedLabelsDistance += lcl_getLabelsDistance( *apTickIter.get() - , pTickmarkHelper2D->getDistanceAxisTickToText( m_aAxisProperties ) ); + , pTickFactory2D->getDistanceAxisTickToText( m_aAxisProperties ) + , fRotationAngleDegree ); } } } else if( rAxisLabelProperties.getIsStaggered() ) { - EquidistantLabelIterator aInnerIter( m_aAllTickInfos, m_aIncrement - , rAxisLabelProperties.eStaggering, true, 0, 0 ); - EquidistantLabelIterator aOuterIter( m_aAllTickInfos, m_aIncrement - , rAxisLabelProperties.eStaggering, false, 0, 0 ); - - lcl_shiftLables( aOuterIter - , lcl_getLabelsDistance( aInnerIter - , pTickmarkHelper2D->getDistanceAxisTickToText( m_aAxisProperties ) ) ); + if( !m_aAllTickInfos.empty() ) + { + LabelIterator aInnerIter( m_aAllTickInfos[0], rAxisLabelProperties.eStaggering, true ); + LabelIterator aOuterIter( m_aAllTickInfos[0], rAxisLabelProperties.eStaggering, false ); + + lcl_shiftLables( aOuterIter + , lcl_getLabelsDistance( aInnerIter + , pTickFactory2D->getDistanceAxisTickToText( m_aAxisProperties ), 0.0 ) ); + } } } -void SAL_CALL VCartesianAxis::createLabels() +void VCartesianAxis::createLabels() { if( !prepareShapeCreation() ) return; @@ -1316,14 +1368,14 @@ void SAL_CALL VCartesianAxis::createLabels() //create labels if( m_aAxisProperties.m_bDisplayLabels ) { - std::auto_ptr< TickmarkHelper_2D > apTickmarkHelper2D( this->createTickmarkHelper2D() ); - TickmarkHelper_2D* pTickmarkHelper2D = apTickmarkHelper2D.get(); - if( !pTickmarkHelper2D ) + std::auto_ptr< TickFactory_2D > apTickFactory2D( this->createTickFactory2D() ); + TickFactory_2D* pTickFactory2D = apTickFactory2D.get(); + if( !pTickFactory2D ) return; //----------------------------------------- //get the transformed screen values for all tickmarks in aAllTickInfos - pTickmarkHelper2D->updateScreenValues( m_aAllTickInfos ); + pTickFactory2D->updateScreenValues( m_aAllTickInfos ); //----------------------------------------- //'hide' tickmarks with identical screen values in aAllTickInfos hideIdenticalScreenValues( m_aAllTickInfos ); @@ -1340,25 +1392,38 @@ void SAL_CALL VCartesianAxis::createLabels() { if(nTextLevel==0) { - nScreenDistanceBetweenTicks = TickmarkHelper_2D::getTickScreenDistance( *apTickIter.get() ); + nScreenDistanceBetweenTicks = TickFactory_2D::getTickScreenDistance( *apTickIter.get() ); if( nTextLevelCount>1 ) nScreenDistanceBetweenTicks*=2; //the above used tick iter does contain also the sub ticks -> thus the given distance is only the half } - AxisLabelProperties aCopy(m_aAxisLabelProperties); - aCopy.bRhythmIsFix = true; - aCopy.nRhythm = 1; - AxisLabelProperties& rAxisLabelProperties = nTextLevel==0 ? m_aAxisLabelProperties : aCopy; - while( !createTextShapes( m_xTextTarget, *apTickIter.get(), rAxisLabelProperties, pTickmarkHelper2D, nScreenDistanceBetweenTicks ) ) + AxisLabelProperties aComplexProps(m_aAxisLabelProperties); + if( m_aAxisProperties.m_bComplexCategories ) + { + if( nTextLevel==0 ) + { + aComplexProps.bLineBreakAllowed = true; + aComplexProps.bOverlapAllowed = !::rtl::math::approxEqual( aComplexProps.fRotationAngleDegree, 0.0 ); + } + else + { + aComplexProps.bOverlapAllowed = true; + aComplexProps.bRhythmIsFix = true; + aComplexProps.nRhythm = 1; + aComplexProps.fRotationAngleDegree = 0.0; + } + } + AxisLabelProperties& rAxisLabelProperties = m_aAxisProperties.m_bComplexCategories ? aComplexProps : m_aAxisLabelProperties; + while( !createTextShapes( m_xTextTarget, *apTickIter.get(), rAxisLabelProperties, pTickFactory2D, nScreenDistanceBetweenTicks ) ) { }; } } - doStaggeringOfLabels( m_aAxisLabelProperties, pTickmarkHelper2D ); + doStaggeringOfLabels( m_aAxisLabelProperties, pTickFactory2D ); } } -void SAL_CALL VCartesianAxis::createMaximumLabels() +void VCartesianAxis::createMaximumLabels() { TrueGuard aRecordMaximumTextSize(m_bRecordMaximumTextSize); @@ -1369,20 +1434,20 @@ void SAL_CALL VCartesianAxis::createMaximumLabels() //create labels if( m_aAxisProperties.m_bDisplayLabels ) { - std::auto_ptr< TickmarkHelper_2D > apTickmarkHelper2D( this->createTickmarkHelper2D() ); - TickmarkHelper_2D* pTickmarkHelper2D = apTickmarkHelper2D.get(); - if( !pTickmarkHelper2D ) + std::auto_ptr< TickFactory_2D > apTickFactory2D( this->createTickFactory2D() ); + TickFactory_2D* pTickFactory2D = apTickFactory2D.get(); + if( !pTickFactory2D ) return; //----------------------------------------- //get the transformed screen values for all tickmarks in aAllTickInfos - pTickmarkHelper2D->updateScreenValues( m_aAllTickInfos ); + pTickFactory2D->updateScreenValues( m_aAllTickInfos ); //create tick mark text shapes //@todo: iterate through all tick depth wich should be labeled AxisLabelProperties aAxisLabelProperties( m_aAxisLabelProperties ); - if( isAutoStaggeringOfLabelsAllowed( aAxisLabelProperties, pTickmarkHelper2D->isHorizontalAxis(), pTickmarkHelper2D->isVerticalAxis() ) ) + if( isAutoStaggeringOfLabelsAllowed( aAxisLabelProperties, pTickFactory2D->isHorizontalAxis(), pTickFactory2D->isVerticalAxis() ) ) aAxisLabelProperties.eStaggering = STAGGER_EVEN; aAxisLabelProperties.bOverlapAllowed = true; aAxisLabelProperties.bLineBreakAllowed = false; @@ -1392,33 +1457,33 @@ void SAL_CALL VCartesianAxis::createMaximumLabels() ::std::auto_ptr< TickIter > apTickIter = createMaximumLabelTickIterator( nTextLevel ); if(apTickIter.get()) { - while( !createTextShapes( m_xTextTarget, *apTickIter.get(), aAxisLabelProperties, pTickmarkHelper2D, -1 ) ) + while( !createTextShapes( m_xTextTarget, *apTickIter.get(), aAxisLabelProperties, pTickFactory2D, -1 ) ) { }; } } - doStaggeringOfLabels( aAxisLabelProperties, pTickmarkHelper2D ); + doStaggeringOfLabels( aAxisLabelProperties, pTickFactory2D ); } } -void SAL_CALL VCartesianAxis::updatePositions() +void VCartesianAxis::updatePositions() { //----------------------------------------- //update positions of labels if( m_aAxisProperties.m_bDisplayLabels ) { - std::auto_ptr< TickmarkHelper_2D > apTickmarkHelper2D( this->createTickmarkHelper2D() ); - TickmarkHelper_2D* pTickmarkHelper2D = apTickmarkHelper2D.get(); - if( !pTickmarkHelper2D ) + std::auto_ptr< TickFactory_2D > apTickFactory2D( this->createTickFactory2D() ); + TickFactory_2D* pTickFactory2D = apTickFactory2D.get(); + if( !pTickFactory2D ) return; //----------------------------------------- //update positions of all existing text shapes - pTickmarkHelper2D->updateScreenValues( m_aAllTickInfos ); + pTickFactory2D->updateScreenValues( m_aAllTickInfos ); ::std::vector< ::std::vector< TickInfo > >::iterator aDepthIter = m_aAllTickInfos.begin(); const ::std::vector< ::std::vector< TickInfo > >::const_iterator aDepthEnd = m_aAllTickInfos.end(); - for( ; aDepthIter != aDepthEnd; aDepthIter++ ) + for( sal_Int32 nDepth=0; aDepthIter != aDepthEnd; aDepthIter++, nDepth++ ) { ::std::vector< TickInfo >::iterator aTickIter = aDepthIter->begin(); const ::std::vector< TickInfo >::const_iterator aTickEnd = aDepthIter->end(); @@ -1428,15 +1493,19 @@ void SAL_CALL VCartesianAxis::updatePositions() Reference< drawing::XShape > xShape2DText( rTickInfo.xTextShape ); if( xShape2DText.is() ) { - B2DVector aTextToTickDistance( pTickmarkHelper2D->getDistanceAxisTickToText( m_aAxisProperties, true ) ); + B2DVector aTextToTickDistance( pTickFactory2D->getDistanceAxisTickToText( m_aAxisProperties, true ) ); B2DVector aTickScreenPos2D( rTickInfo.aTickScreenPosition ); aTickScreenPos2D += aTextToTickDistance; awt::Point aAnchorScreenPosition2D( static_cast<sal_Int32>(aTickScreenPos2D.getX()) ,static_cast<sal_Int32>(aTickScreenPos2D.getY())); + double fRotationAngleDegree = m_aAxisLabelProperties.fRotationAngleDegree; + if( nDepth>0 ) + fRotationAngleDegree = 0.0; + // #i78696# use mathematically correct rotation now - const double fRotationAnglePi(m_aAxisLabelProperties.fRotationAngleDegree * (F_PI / -180.0)); + const double fRotationAnglePi(fRotationAngleDegree * (F_PI / -180.0)); uno::Any aATransformation = ShapeFactory::makeTransformation(aAnchorScreenPosition2D, fRotationAnglePi); //set new position @@ -1455,16 +1524,16 @@ void SAL_CALL VCartesianAxis::updatePositions() //correctPositionForRotation LabelPositionHelper::correctPositionForRotation( xShape2DText - , m_aAxisProperties.m_aLabelAlignment, m_aAxisLabelProperties.fRotationAngleDegree, false ); + , m_aAxisProperties.m_aLabelAlignment, fRotationAngleDegree, m_aAxisProperties.m_bComplexCategories ); } } } - doStaggeringOfLabels( m_aAxisLabelProperties, pTickmarkHelper2D ); + doStaggeringOfLabels( m_aAxisLabelProperties, pTickFactory2D ); } } -void VCartesianAxis::createTickMarkLineShapes( ::std::vector< TickInfo >& rTickInfos, const TickmarkProperties& rTickmarkProperties, TickmarkHelper_2D& rTickmarkHelper2D, bool bOnlyAtLabels ) +void VCartesianAxis::createTickMarkLineShapes( ::std::vector< TickInfo >& rTickInfos, const TickmarkProperties& rTickmarkProperties, TickFactory_2D& rTickFactory2D, bool bOnlyAtLabels ) { sal_Int32 nPointCount = rTickInfos.size(); drawing::PointSequenceSequence aPoints(2*nPointCount); @@ -1483,11 +1552,11 @@ void VCartesianAxis::createTickMarkLineShapes( ::std::vector< TickInfo >& rTickI fInnerDirectionSign *= -1.0; bTicksAtLabels = bTicksAtLabels || bOnlyAtLabels; //add ticks at labels: - rTickmarkHelper2D.addPointSequenceForTickLine( aPoints, nN++, (*aTickIter).fScaledTickValue + rTickFactory2D.addPointSequenceForTickLine( aPoints, nN++, (*aTickIter).fScaledTickValue , fInnerDirectionSign , rTickmarkProperties, bTicksAtLabels ); //add ticks at axis (without lables): if( !bOnlyAtLabels && m_aAxisProperties.m_eTickmarkPos == ::com::sun::star::chart::ChartAxisMarkPosition_AT_LABELS_AND_AXIS ) - rTickmarkHelper2D.addPointSequenceForTickLine( aPoints, nN++, (*aTickIter).fScaledTickValue + rTickFactory2D.addPointSequenceForTickLine( aPoints, nN++, (*aTickIter).fScaledTickValue , m_aAxisProperties.m_fInnerDirectionSign, rTickmarkProperties, !bTicksAtLabels ); } aPoints.realloc(nN); @@ -1495,14 +1564,14 @@ void VCartesianAxis::createTickMarkLineShapes( ::std::vector< TickInfo >& rTickI , &rTickmarkProperties.aLineProperties ); } -void SAL_CALL VCartesianAxis::createShapes() +void VCartesianAxis::createShapes() { if( !prepareShapeCreation() ) return; - std::auto_ptr< TickmarkHelper_2D > apTickmarkHelper2D( this->createTickmarkHelper2D() ); - TickmarkHelper_2D* pTickmarkHelper2D = apTickmarkHelper2D.get(); - if( !pTickmarkHelper2D ) + std::auto_ptr< TickFactory_2D > apTickFactory2D( this->createTickFactory2D() ); + TickFactory_2D* pTickFactory2D = apTickFactory2D.get(); + if( !pTickFactory2D ) return; //----------------------------------------- @@ -1511,23 +1580,26 @@ void SAL_CALL VCartesianAxis::createShapes() { //----------------------------------------- //create extra long ticks to separate complex categories (create them only there where the labels are) - if( m_aAxisProperties.m_bComplexCategories && m_bUseTextLabels ) + if( isComplexCategoryAxis() ) { ::std::vector< ::std::vector< TickInfo > > aComplexTickInfos; createAllTickInfosFromComplexCategories( aComplexTickInfos, true ); - pTickmarkHelper2D->updateScreenValues( aComplexTickInfos ); + pTickFactory2D->updateScreenValues( aComplexTickInfos ); hideIdenticalScreenValues( aComplexTickInfos ); ::std::vector<TickmarkProperties> aTickmarkPropertiesList; static bool bIncludeSpaceBetweenTickAndText = false; - sal_Int32 nOffset = static_cast<sal_Int32>(pTickmarkHelper2D->getDistanceAxisTickToText( m_aAxisProperties, false, bIncludeSpaceBetweenTickAndText ).getLength()); + sal_Int32 nOffset = static_cast<sal_Int32>(pTickFactory2D->getDistanceAxisTickToText( m_aAxisProperties, false, bIncludeSpaceBetweenTickAndText ).getLength()); sal_Int32 nTextLevelCount = getTextLevelCount(); for( sal_Int32 nTextLevel=0; nTextLevel<nTextLevelCount; nTextLevel++ ) { ::std::auto_ptr< TickIter > apTickIter = createLabelTickIterator( nTextLevel ); if( apTickIter.get() ) { - B2DVector aLabelsDistance( lcl_getLabelsDistance( *apTickIter.get(), pTickmarkHelper2D->getDistanceAxisTickToText( m_aAxisProperties, false ) ) ); + double fRotationAngleDegree = m_aAxisLabelProperties.fRotationAngleDegree; + if( nTextLevel>0 ) + fRotationAngleDegree = 0.0; + B2DVector aLabelsDistance( lcl_getLabelsDistance( *apTickIter.get(), pTickFactory2D->getDistanceAxisTickToText( m_aAxisProperties, false ), fRotationAngleDegree ) ); sal_Int32 nCurrentLength = static_cast<sal_Int32>(aLabelsDistance.getLength()); aTickmarkPropertiesList.push_back( m_aAxisProperties.makeTickmarkPropertiesForComplexCategories( nOffset + nCurrentLength, 0, nTextLevel ) ); nOffset += nCurrentLength; @@ -1541,20 +1613,20 @@ void SAL_CALL VCartesianAxis::createShapes() { if(nDepth==0 && !m_aAxisProperties.m_nMajorTickmarks) continue; - createTickMarkLineShapes( *aDepthIter, aTickmarkPropertiesList[nDepth], *pTickmarkHelper2D, true /*bOnlyAtLabels*/ ); + createTickMarkLineShapes( *aDepthIter, aTickmarkPropertiesList[nDepth], *pTickFactory2D, true /*bOnlyAtLabels*/ ); } } //----------------------------------------- //create normal ticks for major and minor intervals { - ::std::vector< ::std::vector< TickInfo > > aAllShiftedTickInfos; - if( m_aIncrement.ShiftedPosition || ( m_aAxisProperties.m_bComplexCategories && m_bUseTextLabels ) ) + ::std::vector< ::std::vector< TickInfo > > aUnshiftedTickInfos; + if( m_aScale.ShiftedCategoryPosition )// if ShiftedCategoryPosition==true the tickmarks in m_aAllTickInfos are shifted { - pTickmarkHelper2D->getAllTicksShifted( aAllShiftedTickInfos ); - pTickmarkHelper2D->updateScreenValues( aAllShiftedTickInfos ); - hideIdenticalScreenValues( aAllShiftedTickInfos ); + pTickFactory2D->getAllTicks( aUnshiftedTickInfos ); + pTickFactory2D->updateScreenValues( aUnshiftedTickInfos ); + hideIdenticalScreenValues( aUnshiftedTickInfos ); } - ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos = m_aIncrement.ShiftedPosition ? aAllShiftedTickInfos : m_aAllTickInfos; + ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos = m_aScale.ShiftedCategoryPosition ? aUnshiftedTickInfos : m_aAllTickInfos; ::std::vector< ::std::vector< TickInfo > >::iterator aDepthIter = rAllTickInfos.begin(); const ::std::vector< ::std::vector< TickInfo > >::const_iterator aDepthEnd = rAllTickInfos.end(); @@ -1563,14 +1635,14 @@ void SAL_CALL VCartesianAxis::createShapes() sal_Int32 nTickmarkPropertiesCount = m_aAxisProperties.m_aTickmarkPropertiesList.size(); for( sal_Int32 nDepth=0; aDepthIter != aDepthEnd && nDepth < nTickmarkPropertiesCount; aDepthIter++, nDepth++ ) - createTickMarkLineShapes( *aDepthIter, m_aAxisProperties.m_aTickmarkPropertiesList[nDepth], *pTickmarkHelper2D, false /*bOnlyAtLabels*/ ); + createTickMarkLineShapes( *aDepthIter, m_aAxisProperties.m_aTickmarkPropertiesList[nDepth], *pTickFactory2D, false /*bOnlyAtLabels*/ ); } //----------------------------------------- //create axis main lines //it serves also as the handle shape for the axis selection { drawing::PointSequenceSequence aPoints(1); - apTickmarkHelper2D->createPointSequenceForAxisMainLine( aPoints ); + apTickFactory2D->createPointSequenceForAxisMainLine( aPoints ); Reference< drawing::XShape > xShape = m_pShapeFactory->createLine2D( m_xGroupShape_Shapes, aPoints , &m_aAxisProperties.m_aLineProperties ); diff --git a/chart2/source/view/axes/VCartesianAxis.hxx b/chart2/source/view/axes/VCartesianAxis.hxx index 9786a56ff95c..68c93bb2e101 100644 --- a/chart2/source/view/axes/VCartesianAxis.hxx +++ b/chart2/source/view/axes/VCartesianAxis.hxx @@ -56,20 +56,11 @@ public: virtual ~VCartesianAxis(); - //------------------------------------------------------------------------- - // partly chart2::XPlotter - //------------------------------------------------------------------------- - - /* - virtual ::rtl::OUString SAL_CALL getCoordinateSystemTypeID( ) throw (::com::sun::star::uno::RuntimeException); - virtual void SAL_CALL setTransformation( const ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XTransformation >& xTransformationToLogicTarget, const ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XTransformation >& xTransformationToFinalPage ) throw (::com::sun::star::uno::RuntimeException); - */ - - virtual void SAL_CALL createMaximumLabels(); - virtual void SAL_CALL createLabels(); - virtual void SAL_CALL updatePositions(); + virtual void createMaximumLabels(); + virtual void createLabels(); + virtual void updatePositions(); - virtual void SAL_CALL createShapes(); + virtual void createShapes(); virtual sal_Int32 estimateMaximumAutoMainIncrementCount(); virtual void createAllTickInfos( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ); @@ -80,7 +71,7 @@ public: sal_Int32 getTextLevelCount() const; //------------------------------------------------------------------------- - virtual TickmarkHelper* createTickmarkHelper(); + virtual TickFactory* createTickFactory(); //------------------------------------------------------------------------- double getLogicValueWhereMainLineCrossesOtherAxis() const; @@ -123,16 +114,16 @@ protected: //methods ::com::sun::star::drawing::XShapes >& xTarget , TickIter& rTickIter , AxisLabelProperties& rAxisLabelProperties - , TickmarkHelper_2D* pTickmarkHelper + , TickFactory_2D* pTickFactory , sal_Int32 nScreenDistanceBetweenTicks ); - void createTickMarkLineShapes( ::std::vector< TickInfo >& rTickInfos, const TickmarkProperties& rTickmarkProperties, TickmarkHelper_2D& rTickmarkHelper2D, bool bOnlyAtLabels ); + void createTickMarkLineShapes( ::std::vector< TickInfo >& rTickInfos, const TickmarkProperties& rTickmarkProperties, TickFactory_2D& rTickFactory2D, bool bOnlyAtLabels ); - TickmarkHelper_2D* createTickmarkHelper2D(); + TickFactory_2D* createTickFactory2D(); void hideIdenticalScreenValues( ::std::vector< ::std::vector< TickInfo > >& rTickInfos ) const; void doStaggeringOfLabels( const AxisLabelProperties& rAxisLabelProperties - , TickmarkHelper_2D* pTickmarkHelper2D ); + , TickFactory_2D* pTickFactory2D ); bool isAutoStaggeringOfLabelsAllowed( const AxisLabelProperties& rAxisLabelProperties , bool bIsHorizontalAxis, bool bIsVerticalAxis ); bool isBreakOfLabelsAllowed( const AxisLabelProperties& rAxisLabelProperties, bool bIsHorizontalAxis ); diff --git a/chart2/source/view/axes/VCartesianCoordinateSystem.cxx b/chart2/source/view/axes/VCartesianCoordinateSystem.cxx index 49b87ee0d46a..53c0da1c12fe 100644 --- a/chart2/source/view/axes/VCartesianCoordinateSystem.cxx +++ b/chart2/source/view/axes/VCartesianCoordinateSystem.cxx @@ -149,11 +149,7 @@ void VCartesianCoordinateSystem::createVAxisList( aAxisProperties.m_bCrossingAxisHasReverseDirection = (AxisOrientation_REVERSE==aCrossingScale.Orientation); if( aCrossingScale.AxisType == AxisType::CATEGORY ) - { aAxisProperties.m_bCrossingAxisIsCategoryAxes = true; - aAxisProperties.m_bAxisBetweenCategories = ChartTypeHelper::shiftTicksAtXAxisPerDefault( AxisHelper::getChartTypeByIndex( m_xCooSysModel, 0 ) ) - || ( aAxisProperties.m_pExplicitCategoriesProvider && aAxisProperties.m_pExplicitCategoriesProvider->hasComplexCategories() ); - } } if( nDimensionIndex == 2 ) @@ -168,17 +164,11 @@ void VCartesianCoordinateSystem::createVAxisList( if(aAxisProperties.m_bDisplayLabels) aAxisProperties.m_nNumberFormatKey = this->getNumberFormatKeyForAxis( xAxis, xNumberFormatsSupplier ); - if( nDimensionIndex == 0 && aAxisProperties.m_nAxisType == AxisType::CATEGORY - && aAxisProperties.m_pExplicitCategoriesProvider ) - { - if( aAxisProperties.m_pExplicitCategoriesProvider->hasComplexCategories() ) - aAxisProperties.m_bComplexCategories = true; - } - ::boost::shared_ptr< VAxisBase > apVAxis( new VCartesianAxis(aAxisProperties,xNumberFormatsSupplier,nDimensionIndex,nDimensionCount) ); tFullAxisIndex aFullAxisIndex( nDimensionIndex, nAxisIndex ); m_aAxisMap[aFullAxisIndex] = apVAxis; apVAxis->set3DWallPositions( m_eLeftWallPos, m_eBackWallPos, m_eBottomPos ); + apVAxis->initAxisLabelProperties(rFontReferenceSize,rMaximumSpaceForLabels); } } diff --git a/chart2/source/view/axes/VCartesianGrid.cxx b/chart2/source/view/axes/VCartesianGrid.cxx index 5e42ba7eed79..e0aca77d9ba9 100644 --- a/chart2/source/view/axes/VCartesianGrid.cxx +++ b/chart2/source/view/axes/VCartesianGrid.cxx @@ -29,7 +29,7 @@ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_chart2.hxx" #include "VCartesianGrid.hxx" -#include "TickmarkHelper.hxx" +#include "Tickmarks.hxx" #include "PlottingPositionHelper.hxx" #include "ShapeFactory.hxx" #include "ObjectIdentifier.hxx" @@ -211,7 +211,7 @@ void VCartesianGrid::fillLinePropertiesFromGridModel( ::std::vector<VLinePropert } }; -void SAL_CALL VCartesianGrid::createShapes() +void VCartesianGrid::createShapes() { if(!m_aGridPropertiesList.getLength()) return; @@ -231,13 +231,10 @@ void SAL_CALL VCartesianGrid::createShapes() //----------------------------------------- //create all scaled tickmark values - std::auto_ptr< TickmarkHelper > apTickmarkHelper( this->createTickmarkHelper() ); - TickmarkHelper& aTickmarkHelper = *apTickmarkHelper.get(); + std::auto_ptr< TickFactory > apTickFactory( this->createTickFactory() ); + TickFactory& aTickFactory = *apTickFactory.get(); ::std::vector< ::std::vector< TickInfo > > aAllTickInfos; - if( m_aIncrement.ShiftedPosition ) - aTickmarkHelper.getAllTicksShifted( aAllTickInfos ); - else - aTickmarkHelper.getAllTicks( aAllTickInfos ); + aTickFactory.getAllTicks( aAllTickInfos ); //----------------------------------------- //create tick mark line shapes diff --git a/chart2/source/view/axes/VCartesianGrid.hxx b/chart2/source/view/axes/VCartesianGrid.hxx index 851008a503d4..a2d7e1d1ddac 100644 --- a/chart2/source/view/axes/VCartesianGrid.hxx +++ b/chart2/source/view/axes/VCartesianGrid.hxx @@ -53,7 +53,7 @@ public: ); virtual ~VCartesianGrid(); - virtual void SAL_CALL createShapes(); + virtual void createShapes(); static void fillLinePropertiesFromGridModel( ::std::vector<VLineProperties>& rLinePropertiesList , const ::com::sun::star::uno::Sequence< diff --git a/chart2/source/view/axes/VCoordinateSystem.cxx b/chart2/source/view/axes/VCoordinateSystem.cxx index 8d136ee2b325..dc273328e45a 100644 --- a/chart2/source/view/axes/VCoordinateSystem.cxx +++ b/chart2/source/view/axes/VCoordinateSystem.cxx @@ -98,8 +98,8 @@ VCoordinateSystem::VCoordinateSystem( const Reference< XCoordinateSystem >& xCoo { if( !m_xCooSysModel.is() || m_xCooSysModel->getDimension()<3 ) { - m_aExplicitScales[2].Minimum = -0.5; - m_aExplicitScales[2].Maximum = 0.5; + m_aExplicitScales[2].Minimum = 1.0; + m_aExplicitScales[2].Maximum = 2.0; m_aExplicitScales[2].Orientation = AxisOrientation_MATHEMATICAL; } } @@ -107,7 +107,7 @@ VCoordinateSystem::~VCoordinateSystem() { } -void SAL_CALL VCoordinateSystem::initPlottingTargets( const Reference< drawing::XShapes >& xLogicTarget +void VCoordinateSystem::initPlottingTargets( const Reference< drawing::XShapes >& xLogicTarget , const Reference< drawing::XShapes >& xFinalTarget , const Reference< lang::XMultiServiceFactory >& xShapeFactory , Reference< drawing::XShapes >& xLogicTargetForSeriesBehindAxis ) @@ -271,9 +271,9 @@ ExplicitCategoriesProvider* VCoordinateSystem::getExplicitCategoriesProvider() return m_apExplicitCategoriesProvider.get(); } -Sequence< ExplicitScaleData > VCoordinateSystem::getExplicitScales( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) const +std::vector< ExplicitScaleData > VCoordinateSystem::getExplicitScales( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) const { - Sequence< ExplicitScaleData > aRet(m_aExplicitScales); + std::vector< ExplicitScaleData > aRet(m_aExplicitScales); impl_adjustDimensionAndIndex( nDimensionIndex, nAxisIndex ); aRet[nDimensionIndex]=this->getExplicitScale( nDimensionIndex, nAxisIndex ); @@ -281,9 +281,9 @@ Sequence< ExplicitScaleData > VCoordinateSystem::getExplicitScales( sal_Int32 nD return aRet; } -Sequence< ExplicitIncrementData > VCoordinateSystem::getExplicitIncrements( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) const +std::vector< ExplicitIncrementData > VCoordinateSystem::getExplicitIncrements( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) const { - Sequence< ExplicitIncrementData > aRet(m_aExplicitIncrements); + std::vector< ExplicitIncrementData > aRet(m_aExplicitIncrements); impl_adjustDimensionAndIndex( nDimensionIndex, nAxisIndex ); aRet[nDimensionIndex]=this->getExplicitIncrement( nDimensionIndex, nAxisIndex ); @@ -382,6 +382,17 @@ void VCoordinateSystem::updateScalesAndIncrementsOnAxes() void VCoordinateSystem::prepareScaleAutomatismForDimensionAndIndex( ScaleAutomatism& rScaleAutomatism, sal_Int32 nDimIndex, sal_Int32 nAxisIndex ) { + if( rScaleAutomatism.getScale().AxisType==AxisType::DATE && nDimIndex==0 ) + { + sal_Int32 nTimeResolution = ::com::sun::star::chart::TimeUnit::MONTH; + if( !(rScaleAutomatism.getScale().TimeIncrement.TimeResolution >>= nTimeResolution) ) + { + nTimeResolution = m_aMergedMinimumAndMaximumSupplier.calculateTimeResolutionOnXAxis(); + rScaleAutomatism.setAutomaticTimeResolution( nTimeResolution ); + } + m_aMergedMinimumAndMaximumSupplier.setTimeResolutionOnXAxis( nTimeResolution, rScaleAutomatism.getNullDate() ); + } + double fMin = 0.0; double fMax = 0.0; ::rtl::math::setInf(&fMin, false); @@ -403,11 +414,6 @@ void VCoordinateSystem::prepareScaleAutomatismForDimensionAndIndex( ScaleAutomat fMax = m_aMergedMinimumAndMaximumSupplier.getMaximumZ(); } - this->prepareScaleAutomatism( rScaleAutomatism, fMin, fMax, nDimIndex, nAxisIndex ); -} - -void VCoordinateSystem::prepareScaleAutomatism( ScaleAutomatism& rScaleAutomatism, double fMin, double fMax, sal_Int32 nDimIndex, sal_Int32 nAxisIndex ) -{ //merge our values with those already contained in rScaleAutomatism rScaleAutomatism.expandValueRange( fMin, fMax ); diff --git a/chart2/source/view/axes/VPolarAngleAxis.cxx b/chart2/source/view/axes/VPolarAngleAxis.cxx index a45cf6977f11..f5469c366358 100644 --- a/chart2/source/view/axes/VPolarAngleAxis.cxx +++ b/chart2/source/view/axes/VPolarAngleAxis.cxx @@ -34,7 +34,7 @@ #include "VPolarGrid.hxx" #include "ShapeFactory.hxx" #include "macros.hxx" -#include "chartview/NumberFormatterWrapper.hxx" +#include "NumberFormatterWrapper.hxx" #include "PolarLabelPositionHelper.hxx" #include <tools/color.hxx> @@ -121,17 +121,17 @@ bool VPolarAngleAxis::createTextShapes_ForAngleAxis( rtl::OUString aLabel; if(pLabels) { - sal_Int32 nIndex = static_cast< sal_Int32 >(pTickInfo->fUnscaledTickValue) - 1; //first category (index 0) matches with real number 1.0 + sal_Int32 nIndex = static_cast< sal_Int32 >(pTickInfo->getUnscaledTickValue()) - 1; //first category (index 0) matches with real number 1.0 if( nIndex>=0 && nIndex<pLabels->getLength() ) aLabel = (*pLabels)[nIndex]; } else - aLabel = aFixedNumberFormatter.getFormattedString( pTickInfo->fUnscaledTickValue, nExtraColor, bHasExtraColor ); + aLabel = aFixedNumberFormatter.getFormattedString( pTickInfo->getUnscaledTickValue(), nExtraColor, bHasExtraColor ); if(pColorAny) *pColorAny = uno::makeAny(bHasExtraColor?nExtraColor:nColor); - double fLogicAngle = pTickInfo->fUnscaledTickValue; + double fLogicAngle = pTickInfo->getUnscaledTickValue(); LabelAlignment eLabelAlignment(LABEL_ALIGN_CENTER); PolarLabelPositionHelper aPolarLabelPositionHelper(m_pPosHelper,nDimensionCount,xTarget,&aShapeFactory); @@ -155,7 +155,7 @@ bool VPolarAngleAxis::createTextShapes_ForAngleAxis( return true; } -void SAL_CALL VPolarAngleAxis::createMaximumLabels() +void VPolarAngleAxis::createMaximumLabels() { if( !prepareShapeCreation() ) return; @@ -163,7 +163,7 @@ void SAL_CALL VPolarAngleAxis::createMaximumLabels() createLabels(); } -void SAL_CALL VPolarAngleAxis::updatePositions() +void VPolarAngleAxis::updatePositions() { //todo: really only update the positions @@ -173,18 +173,19 @@ void SAL_CALL VPolarAngleAxis::updatePositions() createLabels(); } -void SAL_CALL VPolarAngleAxis::createLabels() +void VPolarAngleAxis::createLabels() { if( !prepareShapeCreation() ) return; double fLogicRadius = m_pPosHelper->getOuterLogicRadius(); + double fLogicZ = 1.0;//as defined if( m_aAxisProperties.m_bDisplayLabels ) { //----------------------------------------- //get the transformed screen values for all tickmarks in aAllTickInfos - std::auto_ptr< TickmarkHelper > apTickmarkHelper( this->createTickmarkHelper() ); + std::auto_ptr< TickFactory > apTickFactory( this->createTickFactory() ); //create tick mark text shapes //@todo: iterate through all tick depth wich should be labeled @@ -208,13 +209,13 @@ void SAL_CALL VPolarAngleAxis::createLabels() } } -void SAL_CALL VPolarAngleAxis::createShapes() +void VPolarAngleAxis::createShapes() { if( !prepareShapeCreation() ) return; double fLogicRadius = m_pPosHelper->getOuterLogicRadius(); - double fLogicZ = -0.5;//as defined + double fLogicZ = 1.0;//as defined //----------------------------------------- //create axis main lines diff --git a/chart2/source/view/axes/VPolarAngleAxis.hxx b/chart2/source/view/axes/VPolarAngleAxis.hxx index 034cb36e690c..97cb7bf7463b 100644 --- a/chart2/source/view/axes/VPolarAngleAxis.hxx +++ b/chart2/source/view/axes/VPolarAngleAxis.hxx @@ -29,6 +29,7 @@ #define _CHART2_VPOLARANGLEAXIS_HXX #include "VPolarAxis.hxx" +#include "Tickmarks_Equidistant.hxx" //............................................................................. namespace chart @@ -47,11 +48,11 @@ public: , sal_Int32 nDimensionCount ); virtual ~VPolarAngleAxis(); - virtual void SAL_CALL createMaximumLabels(); - virtual void SAL_CALL createLabels(); - virtual void SAL_CALL updatePositions(); + virtual void createMaximumLabels(); + virtual void createLabels(); + virtual void updatePositions(); - virtual void SAL_CALL createShapes(); + virtual void createShapes(); private: //methods bool createTextShapes_ForAngleAxis( diff --git a/chart2/source/view/axes/VPolarAxis.cxx b/chart2/source/view/axes/VPolarAxis.cxx index 5caee2fff67a..687ac8fe8780 100644 --- a/chart2/source/view/axes/VPolarAxis.cxx +++ b/chart2/source/view/axes/VPolarAxis.cxx @@ -32,7 +32,7 @@ #include "VPolarAngleAxis.hxx" #include "VPolarRadiusAxis.hxx" #include "macros.hxx" -#include "TickmarkHelper.hxx" +#include "Tickmarks.hxx" #include "ShapeFactory.hxx" #include <memory> @@ -69,12 +69,12 @@ VPolarAxis::~VPolarAxis() m_pPosHelper = NULL; } -void VPolarAxis::setIncrements( const uno::Sequence< ExplicitIncrementData >& rIncrements ) +void VPolarAxis::setIncrements( const std::vector< ExplicitIncrementData >& rIncrements ) { m_aIncrements = rIncrements; } -sal_Bool SAL_CALL VPolarAxis::isAnythingToDraw() +sal_Bool VPolarAxis::isAnythingToDraw() { return ( 2==m_nDimension && VAxisBase::isAnythingToDraw() ); } diff --git a/chart2/source/view/axes/VPolarAxis.hxx b/chart2/source/view/axes/VPolarAxis.hxx index 20d8b2805ea6..5d4d667297e9 100644 --- a/chart2/source/view/axes/VPolarAxis.hxx +++ b/chart2/source/view/axes/VPolarAxis.hxx @@ -48,10 +48,9 @@ public: , const ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier >& xNumberFormatsSupplier , sal_Int32 nDimensionIndex, sal_Int32 nDimensionCount ); - void setIncrements( const ::com::sun::star::uno::Sequence< - ::com::sun::star::chart2::ExplicitIncrementData >& rIncrements ); + void setIncrements( const std::vector< ExplicitIncrementData >& rIncrements ); - virtual sal_Bool SAL_CALL isAnythingToDraw(); + virtual sal_Bool isAnythingToDraw(); virtual ~VPolarAxis(); @@ -62,8 +61,7 @@ protected: protected: //member PolarPlottingPositionHelper* m_pPosHelper; - ::com::sun::star::uno::Sequence< - ::com::sun::star::chart2::ExplicitIncrementData > m_aIncrements; + ::std::vector< ExplicitIncrementData > m_aIncrements; }; //............................................................................. diff --git a/chart2/source/view/axes/VPolarCoordinateSystem.cxx b/chart2/source/view/axes/VPolarCoordinateSystem.cxx index 278a99f6fcdd..7e13c26477cd 100644 --- a/chart2/source/view/axes/VPolarCoordinateSystem.cxx +++ b/chart2/source/view/axes/VPolarCoordinateSystem.cxx @@ -101,6 +101,7 @@ void VPolarCoordinateSystem::createVAxisList( ::boost::shared_ptr< VAxisBase > apVAxis( VPolarAxis::createAxis( aAxisProperties,xNumberFormatsSupplier,nDimensionIndex,nDimensionCount) ); tFullAxisIndex aFullAxisIndex( nDimensionIndex, nAxisIndex ); m_aAxisMap[aFullAxisIndex] = apVAxis; + apVAxis->initAxisLabelProperties(rFontReferenceSize,rMaximumSpaceForLabels); } } diff --git a/chart2/source/view/axes/VPolarGrid.cxx b/chart2/source/view/axes/VPolarGrid.cxx index f9ae00f779a1..7c8a26d75857 100644 --- a/chart2/source/view/axes/VPolarGrid.cxx +++ b/chart2/source/view/axes/VPolarGrid.cxx @@ -30,12 +30,13 @@ #include "precompiled_chart2.hxx" #include "VPolarGrid.hxx" #include "VCartesianGrid.hxx" -#include "TickmarkHelper.hxx" +#include "Tickmarks.hxx" #include "PlottingPositionHelper.hxx" #include "ShapeFactory.hxx" #include "ObjectIdentifier.hxx" #include "macros.hxx" #include "CommonConverters.hxx" +#include "Tickmarks_Equidistant.hxx" #include <com/sun/star/drawing/LineStyle.hpp> #include <vector> @@ -65,16 +66,16 @@ VPolarGrid::~VPolarGrid() m_pPosHelper = NULL; } -void VPolarGrid::setIncrements( const uno::Sequence< ExplicitIncrementData >& rIncrements ) +void VPolarGrid::setIncrements( const std::vector< ExplicitIncrementData >& rIncrements ) { m_aIncrements = rIncrements; } void VPolarGrid::getAllTickInfos( sal_Int32 nDimensionIndex, ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ) const { - TickmarkHelper aTickmarkHelper( + TickFactory aTickFactory( m_pPosHelper->getScales()[nDimensionIndex], m_aIncrements[nDimensionIndex] ); - aTickmarkHelper.getAllTicks( rAllTickInfos ); + aTickFactory.getAllTicks( rAllTickInfos ); } void VPolarGrid::createLinePointSequence_ForAngleAxis( @@ -98,8 +99,8 @@ void VPolarGrid::createLinePointSequence_ForAngleAxis( if(nTick>=rPoints[0].getLength()) rPoints[0].realloc(rPoints[0].getLength()+30); - pTickInfo->updateUnscaledValue( xInverseScaling ); - double fLogicAngle = pTickInfo->fUnscaledTickValue; + //xxxxx pTickInfo->updateUnscaledValue( xInverseScaling ); + double fLogicAngle = pTickInfo->getUnscaledTickValue(); drawing::Position3D aScenePosition3D( pPosHelper->transformAngleRadiusToScene( fLogicAngle, fLogicRadius, fLogicZ ) ); rPoints[0][nTick].X = static_cast<sal_Int32>(aScenePosition3D.PositionX); @@ -114,6 +115,66 @@ void VPolarGrid::createLinePointSequence_ForAngleAxis( else rPoints[0].realloc(0); } +#ifdef NOTYET +void VPolarGrid::create2DAngleGrid( const Reference< drawing::XShapes >& xLogicTarget + , ::std::vector< ::std::vector< TickInfo > >& /* rRadiusTickInfos */ + , ::std::vector< ::std::vector< TickInfo > >& rAngleTickInfos + , const ::std::vector<VLineProperties>& rLinePropertiesList ) +{ + Reference< drawing::XShapes > xMainTarget( + this->createGroupShape( xLogicTarget, m_aCID ) ); + + const ExplicitScaleData& rAngleScale = m_pPosHelper->getScales()[0]; + Reference< XScaling > xInverseScaling( NULL ); + if( rAngleScale.Scaling.is() ) + xInverseScaling = rAngleScale.Scaling->getInverseScaling(); + + double fLogicInnerRadius = m_pPosHelper->getInnerLogicRadius(); + double fLogicOuterRadius = m_pPosHelper->getOuterLogicRadius(); + double fLogicZ = 1.0;//as defined + + sal_Int32 nLinePropertiesCount = rLinePropertiesList.size(); + ::std::vector< ::std::vector< TickInfo > >::iterator aDepthIter = rAngleTickInfos.begin(); + sal_Int32 nDepth=0; + /* + //no subgrids so far for polar angle grid (need different radii) + const ::std::vector< ::std::vector< TickInfo > >::const_iterator aDepthEnd = rAngleTickInfos.end(); + for( ; aDepthIter != aDepthEnd && nDepth < nLinePropertiesCount + ; aDepthIter++, nDepth++ ) + */ + if(nLinePropertiesCount) + { + //create axis main lines + drawing::PointSequenceSequence aAllPoints; + ::std::vector< TickInfo >::iterator aTickIter = (*aDepthIter).begin(); + const ::std::vector< TickInfo >::const_iterator aTickEnd = (*aDepthIter).end(); + for( ; aTickIter != aTickEnd; aTickIter++ ) + { + TickInfo& rTickInfo = *aTickIter; + if( !rTickInfo.bPaintIt ) + continue; + + //xxxxx rTickInfo.updateUnscaledValue( xInverseScaling ); + double fLogicAngle = rTickInfo.getUnscaledTickValue(); + + drawing::PointSequenceSequence aPoints(1); + aPoints[0].realloc(2); + drawing::Position3D aScenePositionStart( m_pPosHelper->transformAngleRadiusToScene( fLogicAngle, fLogicInnerRadius, fLogicZ ) ); + drawing::Position3D aScenePositionEnd( m_pPosHelper->transformAngleRadiusToScene( fLogicAngle, fLogicOuterRadius, fLogicZ ) ); + aPoints[0][0].X = static_cast<sal_Int32>(aScenePositionStart.PositionX); + aPoints[0][0].Y = static_cast<sal_Int32>(aScenePositionStart.PositionY); + aPoints[0][1].X = static_cast<sal_Int32>(aScenePositionEnd.PositionX); + aPoints[0][1].Y = static_cast<sal_Int32>(aScenePositionEnd.PositionY); + appendPointSequence( aAllPoints, aPoints ); + } + + Reference< drawing::XShape > xShape = m_pShapeFactory->createLine2D( + xMainTarget, aAllPoints, &rLinePropertiesList[nDepth] ); + //because of this name this line will be used for marking + m_pShapeFactory->setShapeName( xShape, C2U("MarkHandles") ); + } +} +#endif void VPolarGrid::create2DRadiusGrid( const Reference< drawing::XShapes >& xLogicTarget , ::std::vector< ::std::vector< TickInfo > >& rRadiusTickInfos @@ -160,9 +221,9 @@ void VPolarGrid::create2DRadiusGrid( const Reference< drawing::XShapes >& xLogic if( !rTickInfo.bPaintIt ) continue; - rTickInfo.updateUnscaledValue( xInverseRadiusScaling ); - double fLogicRadius = rTickInfo.fUnscaledTickValue; - double fLogicZ = -0.5;//as defined + //xxxxx rTickInfo.updateUnscaledValue( xInverseRadiusScaling ); + double fLogicRadius = rTickInfo.getUnscaledTickValue(); + double fLogicZ = 1.0;//as defined drawing::PointSequenceSequence aPoints(1); VPolarGrid::createLinePointSequence_ForAngleAxis( aPoints, rAngleTickInfos @@ -178,7 +239,7 @@ void VPolarGrid::create2DRadiusGrid( const Reference< drawing::XShapes >& xLogic } } -void SAL_CALL VPolarGrid::createShapes() +void VPolarGrid::createShapes() { DBG_ASSERT(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is(),"Axis is not proper initialized"); if(!(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is())) diff --git a/chart2/source/view/axes/VPolarGrid.hxx b/chart2/source/view/axes/VPolarGrid.hxx index 79050ed7da8f..29882792cabf 100644 --- a/chart2/source/view/axes/VPolarGrid.hxx +++ b/chart2/source/view/axes/VPolarGrid.hxx @@ -29,7 +29,7 @@ #define _CHART2_VPOLARGRID_HXX #include "VAxisOrGridBase.hxx" -#include "TickmarkHelper.hxx" +#include "Tickmarks.hxx" #include "VLineProperties.hxx" #include <com/sun/star/drawing/PointSequenceSequence.hpp> @@ -56,16 +56,15 @@ public: ); virtual ~VPolarGrid(); - virtual void SAL_CALL createShapes(); + virtual void createShapes(); - void setIncrements( const ::com::sun::star::uno::Sequence< - ::com::sun::star::chart2::ExplicitIncrementData >& rIncrements ); + void setIncrements( const std::vector< ExplicitIncrementData >& rIncrements ); static void createLinePointSequence_ForAngleAxis( ::com::sun::star::drawing::PointSequenceSequence& rPoints , ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos - , const ::com::sun::star::chart2::ExplicitIncrementData& rIncrement - , const ::com::sun::star::chart2::ExplicitScaleData& rScale + , const ExplicitIncrementData& rIncrement + , const ExplicitScaleData& rScale , PolarPlottingPositionHelper* pPosHelper , double fLogicRadius, double fLogicZ ); @@ -74,8 +73,7 @@ private: //member ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > > m_aGridPropertiesList;//main grid, subgrid, subsubgrid etc PolarPlottingPositionHelper* m_pPosHelper; - ::com::sun::star::uno::Sequence< - ::com::sun::star::chart2::ExplicitIncrementData > m_aIncrements; + ::std::vector< ExplicitIncrementData > m_aIncrements; void getAllTickInfos( sal_Int32 nDimensionIndex, ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ) const; diff --git a/chart2/source/view/axes/VPolarRadiusAxis.cxx b/chart2/source/view/axes/VPolarRadiusAxis.cxx index b7792a783138..92abb0af8bbe 100644 --- a/chart2/source/view/axes/VPolarRadiusAxis.cxx +++ b/chart2/source/view/axes/VPolarRadiusAxis.cxx @@ -33,6 +33,7 @@ #include "VCartesianAxis.hxx" #include "PlottingPositionHelper.hxx" #include "CommonConverters.hxx" +#include "Tickmarks_Equidistant.hxx" #include <rtl/math.hxx> //............................................................................. @@ -71,7 +72,7 @@ void VPolarRadiusAxis::setTransformationSceneToScreen( const drawing::HomogenMat m_apAxisWithLabels->setTransformationSceneToScreen( rMatrix ); } -void SAL_CALL VPolarRadiusAxis::setExplicitScaleAndIncrement( +void VPolarRadiusAxis::setExplicitScaleAndIncrement( const ExplicitScaleData& rScale , const ExplicitIncrementData& rIncrement ) throw (uno::RuntimeException) @@ -80,7 +81,7 @@ void SAL_CALL VPolarRadiusAxis::setExplicitScaleAndIncrement( m_apAxisWithLabels->setExplicitScaleAndIncrement( rScale, rIncrement ); } -void SAL_CALL VPolarRadiusAxis::initPlotter( const uno::Reference< drawing::XShapes >& xLogicTarget +void VPolarRadiusAxis::initPlotter( const uno::Reference< drawing::XShapes >& xLogicTarget , const uno::Reference< drawing::XShapes >& xFinalTarget , const uno::Reference< lang::XMultiServiceFactory >& xShapeFactory , const rtl::OUString& rCID ) @@ -90,15 +91,13 @@ void SAL_CALL VPolarRadiusAxis::initPlotter( const uno::Reference< drawing::XSh m_apAxisWithLabels->initPlotter( xLogicTarget, xFinalTarget, xShapeFactory, rCID ); } -void SAL_CALL VPolarRadiusAxis::setScales( const uno::Sequence< ExplicitScaleData >& rScales - , sal_Bool bSwapXAndYAxis ) - throw (uno::RuntimeException) +void VPolarRadiusAxis::setScales( const std::vector< ExplicitScaleData >& rScales, bool bSwapXAndYAxis ) { VPolarAxis::setScales( rScales, bSwapXAndYAxis ); m_apAxisWithLabels->setScales( rScales, bSwapXAndYAxis ); } -void SAL_CALL VPolarRadiusAxis::initAxisLabelProperties( const ::com::sun::star::awt::Size& rFontReferenceSize +void VPolarRadiusAxis::initAxisLabelProperties( const ::com::sun::star::awt::Size& rFontReferenceSize , const ::com::sun::star::awt::Rectangle& rMaximumSpaceForLabels ) { VPolarAxis::initAxisLabelProperties( rFontReferenceSize, rMaximumSpaceForLabels ); @@ -122,22 +121,22 @@ bool VPolarRadiusAxis::prepareShapeCreation() return true; } -void SAL_CALL VPolarRadiusAxis::createMaximumLabels() +void VPolarRadiusAxis::createMaximumLabels() { m_apAxisWithLabels->createMaximumLabels(); } -void SAL_CALL VPolarRadiusAxis::updatePositions() +void VPolarRadiusAxis::updatePositions() { m_apAxisWithLabels->updatePositions(); } -void SAL_CALL VPolarRadiusAxis::createLabels() +void VPolarRadiusAxis::createLabels() { m_apAxisWithLabels->createLabels(); } -void SAL_CALL VPolarRadiusAxis::createShapes() +void VPolarRadiusAxis::createShapes() { if( !prepareShapeCreation() ) return; @@ -146,8 +145,8 @@ void SAL_CALL VPolarRadiusAxis::createShapes() const ExplicitIncrementData& rAngleIncrement = m_aIncrements[0]; ::std::vector< ::std::vector< TickInfo > > aAngleTickInfos; - TickmarkHelper aAngleTickmarkHelper( rAngleScale, rAngleIncrement ); - aAngleTickmarkHelper.getAllTicks( aAngleTickInfos ); + TickFactory aAngleTickFactory( rAngleScale, rAngleIncrement ); + aAngleTickFactory.getAllTicks( aAngleTickInfos ); uno::Reference< XScaling > xInverseScaling( NULL ); if( rAngleScale.Scaling.is() ) @@ -166,8 +165,8 @@ void SAL_CALL VPolarRadiusAxis::createShapes() continue; } - pTickInfo->updateUnscaledValue( xInverseScaling ); - aAxisProperties.m_pfMainLinePositionAtOtherAxis = new double( pTickInfo->fUnscaledTickValue ); + //xxxxx pTickInfo->updateUnscaledValue( xInverseScaling ); + aAxisProperties.m_pfMainLinePositionAtOtherAxis = new double( pTickInfo->getUnscaledTickValue() ); aAxisProperties.m_bDisplayLabels=false; //------------------- diff --git a/chart2/source/view/axes/VPolarRadiusAxis.hxx b/chart2/source/view/axes/VPolarRadiusAxis.hxx index 91f9a40b83ee..70482b403283 100644 --- a/chart2/source/view/axes/VPolarRadiusAxis.hxx +++ b/chart2/source/view/axes/VPolarRadiusAxis.hxx @@ -51,7 +51,7 @@ public: , sal_Int32 nDimensionCount ); virtual ~VPolarRadiusAxis(); - virtual void SAL_CALL initPlotter( + virtual void initPlotter( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& xLogicTarget , const ::com::sun::star::uno::Reference< @@ -63,28 +63,24 @@ public: virtual void setTransformationSceneToScreen( const ::com::sun::star::drawing::HomogenMatrix& rMatrix ); - virtual void SAL_CALL setScales( - const ::com::sun::star::uno::Sequence< - ::com::sun::star::chart2::ExplicitScaleData >& rScales - , sal_Bool bSwapXAndYAxis ) - throw (::com::sun::star::uno::RuntimeException); + virtual void setScales( const ::std::vector< ExplicitScaleData >& rScales, bool bSwapXAndYAxis ); - virtual void SAL_CALL setExplicitScaleAndIncrement( - const ::com::sun::star::chart2::ExplicitScaleData& rScale - , const ::com::sun::star::chart2::ExplicitIncrementData& rIncrement ) + virtual void setExplicitScaleAndIncrement( + const ExplicitScaleData& rScale + , const ExplicitIncrementData& rIncrement ) throw (::com::sun::star::uno::RuntimeException); - virtual void SAL_CALL initAxisLabelProperties( + virtual void initAxisLabelProperties( const ::com::sun::star::awt::Size& rFontReferenceSize , const ::com::sun::star::awt::Rectangle& rMaximumSpaceForLabels ); virtual sal_Int32 estimateMaximumAutoMainIncrementCount(); - virtual void SAL_CALL createMaximumLabels(); - virtual void SAL_CALL createLabels(); - virtual void SAL_CALL updatePositions(); + virtual void createMaximumLabels(); + virtual void createLabels(); + virtual void updatePositions(); - virtual void SAL_CALL createShapes(); + virtual void createShapes(); protected: //methods virtual bool prepareShapeCreation(); diff --git a/chart2/source/view/axes/makefile.mk b/chart2/source/view/axes/makefile.mk index 9e1d6ca38f7d..9704dc0b14bc 100644 --- a/chart2/source/view/axes/makefile.mk +++ b/chart2/source/view/axes/makefile.mk @@ -43,7 +43,11 @@ ENABLE_EXCEPTIONS= TRUE SLOFILES = \ $(SLO)$/VAxisOrGridBase.obj \ $(SLO)$/VAxisBase.obj \ - $(SLO)$/TickmarkHelper.obj \ + $(SLO)$/DateHelper.obj \ + $(SLO)$/DateScaling.obj \ + $(SLO)$/Tickmarks.obj \ + $(SLO)$/Tickmarks_Equidistant.obj \ + $(SLO)$/Tickmarks_Dates.obj \ $(SLO)$/MinimumAndMaximumSupplier.obj \ $(SLO)$/ScaleAutomatism.obj \ $(SLO)$/VAxisProperties.obj \ |