diff options
Diffstat (limited to 'chart2/source/view/axes/Tickmarks.cxx')
-rw-r--r-- | chart2/source/view/axes/Tickmarks.cxx | 333 |
1 files changed, 333 insertions, 0 deletions
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 +//............................................................................. |