summaryrefslogtreecommitdiff
path: root/chart2/source/view/axes/Tickmarks.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'chart2/source/view/axes/Tickmarks.cxx')
-rw-r--r--chart2/source/view/axes/Tickmarks.cxx333
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
+//.............................................................................