summaryrefslogtreecommitdiff
path: root/chart2/source/view/axes
diff options
context:
space:
mode:
Diffstat (limited to 'chart2/source/view/axes')
-rw-r--r--chart2/source/view/axes/MinimumAndMaximumSupplier.cxx204
-rw-r--r--chart2/source/view/axes/ScaleAutomatism.cxx763
-rw-r--r--chart2/source/view/axes/TickmarkHelper.cxx925
-rw-r--r--chart2/source/view/axes/TickmarkHelper.hxx254
-rw-r--r--chart2/source/view/axes/TickmarkProperties.hxx56
-rw-r--r--chart2/source/view/axes/VAxisBase.cxx237
-rw-r--r--chart2/source/view/axes/VAxisBase.hxx109
-rw-r--r--chart2/source/view/axes/VAxisOrGridBase.cxx101
-rw-r--r--chart2/source/view/axes/VAxisOrGridBase.hxx86
-rw-r--r--chart2/source/view/axes/VAxisProperties.cxx476
-rw-r--r--chart2/source/view/axes/VAxisProperties.hxx171
-rw-r--r--chart2/source/view/axes/VCartesianAxis.cxx1342
-rw-r--r--chart2/source/view/axes/VCartesianAxis.hxx138
-rw-r--r--chart2/source/view/axes/VCartesianCoordinateSystem.cxx245
-rw-r--r--chart2/source/view/axes/VCartesianCoordinateSystem.hxx67
-rw-r--r--chart2/source/view/axes/VCartesianGrid.cxx342
-rw-r--r--chart2/source/view/axes/VCartesianGrid.hxx74
-rw-r--r--chart2/source/view/axes/VCoordinateSystem.cxx597
-rw-r--r--chart2/source/view/axes/VPolarAngleAxis.cxx238
-rw-r--r--chart2/source/view/axes/VPolarAngleAxis.hxx69
-rw-r--r--chart2/source/view/axes/VPolarAxis.cxx86
-rw-r--r--chart2/source/view/axes/VPolarAxis.hxx74
-rw-r--r--chart2/source/view/axes/VPolarCoordinateSystem.cxx214
-rw-r--r--chart2/source/view/axes/VPolarCoordinateSystem.hxx71
-rw-r--r--chart2/source/view/axes/VPolarGrid.cxx276
-rw-r--r--chart2/source/view/axes/VPolarGrid.hxx99
-rw-r--r--chart2/source/view/axes/VPolarRadiusAxis.cxx190
-rw-r--r--chart2/source/view/axes/VPolarRadiusAxis.hxx101
-rw-r--r--chart2/source/view/axes/makefile.mk70
29 files changed, 7675 insertions, 0 deletions
diff --git a/chart2/source/view/axes/MinimumAndMaximumSupplier.cxx b/chart2/source/view/axes/MinimumAndMaximumSupplier.cxx
new file mode 100644
index 000000000000..a17bb5e5c15d
--- /dev/null
+++ b/chart2/source/view/axes/MinimumAndMaximumSupplier.cxx
@@ -0,0 +1,204 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: MinimumAndMaximumSupplier.cxx,v $
+ * $Revision: 1.3 $
+ *
+ * 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 "MinimumAndMaximumSupplier.hxx"
+#include <rtl/math.hxx>
+#include <com/sun/star/awt/Size.hpp>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+using namespace ::com::sun::star;
+
+MergedMinimumAndMaximumSupplier::MergedMinimumAndMaximumSupplier()
+{
+}
+
+MergedMinimumAndMaximumSupplier::~MergedMinimumAndMaximumSupplier()
+{
+}
+
+void MergedMinimumAndMaximumSupplier::addMinimumAndMaximumSupplier( MinimumAndMaximumSupplier* pMinimumAndMaximumSupplier )
+{
+ m_aMinimumAndMaximumSupplierList.insert( pMinimumAndMaximumSupplier );
+}
+
+bool MergedMinimumAndMaximumSupplier::hasMinimumAndMaximumSupplier( MinimumAndMaximumSupplier* pMinimumAndMaximumSupplier )
+{
+ return m_aMinimumAndMaximumSupplierList.count( pMinimumAndMaximumSupplier ) != 0;
+}
+
+double MergedMinimumAndMaximumSupplier::getMinimumX()
+{
+ double fGlobalExtremum;
+ ::rtl::math::setInf(&fGlobalExtremum, false);
+ for( MinimumAndMaximumSupplierSet::iterator aIt = begin(), aEnd = end(); aIt != aEnd; ++aIt )
+ {
+ double fLocalExtremum = (*aIt)->getMinimumX();
+ if(fLocalExtremum<fGlobalExtremum)
+ fGlobalExtremum=fLocalExtremum;
+ }
+ if(::rtl::math::isInf(fGlobalExtremum))
+ ::rtl::math::setNan(&fGlobalExtremum);
+ return fGlobalExtremum;
+}
+
+double MergedMinimumAndMaximumSupplier::getMaximumX()
+{
+ double fGlobalExtremum;
+ ::rtl::math::setInf(&fGlobalExtremum, true);
+ for( MinimumAndMaximumSupplierSet::iterator aIt = begin(), aEnd = end(); aIt != aEnd; ++aIt )
+ {
+ double fLocalExtremum = (*aIt)->getMaximumX();
+ if(fLocalExtremum>fGlobalExtremum)
+ fGlobalExtremum=fLocalExtremum;
+ }
+ if(::rtl::math::isInf(fGlobalExtremum))
+ ::rtl::math::setNan(&fGlobalExtremum);
+ return fGlobalExtremum;
+}
+
+double MergedMinimumAndMaximumSupplier::getMinimumYInRange( double fMinimumX, double fMaximumX, sal_Int32 nAxisIndex )
+{
+ double fGlobalExtremum;
+ ::rtl::math::setInf(&fGlobalExtremum, false);
+ for( MinimumAndMaximumSupplierSet::iterator aIt = begin(), aEnd = end(); aIt != aEnd; ++aIt )
+ {
+ double fLocalExtremum = (*aIt)->getMinimumYInRange( fMinimumX, fMaximumX, nAxisIndex );
+ if(fLocalExtremum<fGlobalExtremum)
+ fGlobalExtremum=fLocalExtremum;
+ }
+ if(::rtl::math::isInf(fGlobalExtremum))
+ ::rtl::math::setNan(&fGlobalExtremum);
+ return fGlobalExtremum;
+}
+
+double MergedMinimumAndMaximumSupplier::getMaximumYInRange( double fMinimumX, double fMaximumX, sal_Int32 nAxisIndex )
+{
+ double fGlobalExtremum;
+ ::rtl::math::setInf(&fGlobalExtremum, true);
+ for( MinimumAndMaximumSupplierSet::iterator aIt = begin(), aEnd = end(); aIt != aEnd; ++aIt )
+ {
+ double fLocalExtremum = (*aIt)->getMaximumYInRange( fMinimumX, fMaximumX, nAxisIndex );
+ if(fLocalExtremum>fGlobalExtremum)
+ fGlobalExtremum=fLocalExtremum;
+ }
+ if(::rtl::math::isInf(fGlobalExtremum))
+ ::rtl::math::setNan(&fGlobalExtremum);
+ return fGlobalExtremum;
+}
+
+double MergedMinimumAndMaximumSupplier::getMinimumZ()
+{
+ double fGlobalExtremum;
+ ::rtl::math::setInf(&fGlobalExtremum, false);
+ for( MinimumAndMaximumSupplierSet::iterator aIt = begin(), aEnd = end(); aIt != aEnd; ++aIt )
+ {
+ double fLocalExtremum = (*aIt)->getMinimumZ();
+ if(fLocalExtremum<fGlobalExtremum)
+ fGlobalExtremum=fLocalExtremum;
+ }
+ if(::rtl::math::isInf(fGlobalExtremum))
+ ::rtl::math::setNan(&fGlobalExtremum);
+ return fGlobalExtremum;
+}
+
+double MergedMinimumAndMaximumSupplier::getMaximumZ()
+{
+ double fGlobalExtremum;
+ ::rtl::math::setInf(&fGlobalExtremum, true);
+ for( MinimumAndMaximumSupplierSet::iterator aIt = begin(), aEnd = end(); aIt != aEnd; ++aIt )
+ {
+ double fLocalExtremum = (*aIt)->getMaximumZ();
+ if(fLocalExtremum>fGlobalExtremum)
+ fGlobalExtremum=fLocalExtremum;
+ }
+ if(::rtl::math::isInf(fGlobalExtremum))
+ ::rtl::math::setNan(&fGlobalExtremum);
+ return fGlobalExtremum;
+}
+
+bool MergedMinimumAndMaximumSupplier::isExpandBorderToIncrementRhythm( sal_Int32 nDimensionIndex )
+{
+ // only return true, if *all* suppliers want to scale to the main tick marks
+ for( MinimumAndMaximumSupplierSet::iterator aIt = begin(), aEnd = end(); aIt != aEnd; ++aIt )
+ if( !(*aIt)->isExpandBorderToIncrementRhythm( nDimensionIndex ) )
+ return false;
+ return true;
+}
+
+bool MergedMinimumAndMaximumSupplier::isExpandIfValuesCloseToBorder( sal_Int32 nDimensionIndex )
+{
+ // only return true, if *all* suppliers want to expand the range
+ for( MinimumAndMaximumSupplierSet::iterator aIt = begin(), aEnd = end(); aIt != aEnd; ++aIt )
+ if( !(*aIt)->isExpandIfValuesCloseToBorder( nDimensionIndex ) )
+ return false;
+ return true;
+}
+
+bool MergedMinimumAndMaximumSupplier::isExpandWideValuesToZero( sal_Int32 nDimensionIndex )
+{
+ // already return true, if at least one supplier wants to expand the range
+ for( MinimumAndMaximumSupplierSet::iterator aIt = begin(), aEnd = end(); aIt != aEnd; ++aIt )
+ if( (*aIt)->isExpandWideValuesToZero( nDimensionIndex ) )
+ return true;
+ return false;
+}
+
+bool MergedMinimumAndMaximumSupplier::isExpandNarrowValuesTowardZero( sal_Int32 nDimensionIndex )
+{
+ // already return true, if at least one supplier wants to expand the range
+ for( MinimumAndMaximumSupplierSet::iterator aIt = begin(), aEnd = end(); aIt != aEnd; ++aIt )
+ if( (*aIt)->isExpandNarrowValuesTowardZero( nDimensionIndex ) )
+ return true;
+ return false;
+}
+
+bool MergedMinimumAndMaximumSupplier::isSeperateStackingForDifferentSigns( sal_Int32 nDimensionIndex )
+{
+ // should not be called
+ for( MinimumAndMaximumSupplierSet::iterator aIt = begin(), aEnd = end(); aIt != aEnd; ++aIt )
+ if( (*aIt)->isSeperateStackingForDifferentSigns( nDimensionIndex ) )
+ return true;
+ return false;
+}
+
+void MergedMinimumAndMaximumSupplier::clearMinimumAndMaximumSupplierList()
+{
+ m_aMinimumAndMaximumSupplierList.clear();
+}
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
diff --git a/chart2/source/view/axes/ScaleAutomatism.cxx b/chart2/source/view/axes/ScaleAutomatism.cxx
new file mode 100644
index 000000000000..5287ecbcdc13
--- /dev/null
+++ b/chart2/source/view/axes/ScaleAutomatism.cxx
@@ -0,0 +1,763 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: ScaleAutomatism.cxx,v $
+ * $Revision: 1.12.24.1 $
+ *
+ * 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 "ScaleAutomatism.hxx"
+#include "macros.hxx"
+#include "TickmarkHelper.hxx"
+#include "AxisHelper.hxx"
+#include <rtl/math.hxx>
+#include <tools/debug.hxx>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+const sal_Int32 MAXIMUM_MANUAL_INCREMENT_COUNT = 500;
+const sal_Int32 MAXIMUM_AUTO_INCREMENT_COUNT = 10;
+const sal_Int32 MAXIMUM_SUB_INCREMENT_COUNT = 100;
+
+namespace
+{
+
+void lcl_ensureMaximumSubIncrementCount( sal_Int32& rnSubIntervalCount )
+{
+ if( rnSubIntervalCount > MAXIMUM_SUB_INCREMENT_COUNT )
+ rnSubIntervalCount = MAXIMUM_SUB_INCREMENT_COUNT;
+}
+
+}//end anonymous namespace
+
+ScaleAutomatism::ScaleAutomatism( const ScaleData& rSourceScale )
+ : m_aSourceScale( rSourceScale )
+ , m_fValueMinimum( 0.0 )
+ , m_fValueMaximum( 0.0 )
+ , m_nMaximumAutoMainIncrementCount( MAXIMUM_AUTO_INCREMENT_COUNT )
+ , m_bExpandBorderToIncrementRhythm( false )
+ , m_bExpandIfValuesCloseToBorder( false )
+ , m_bExpandWideValuesToZero( false )
+ , m_bExpandNarrowValuesTowardZero( false )
+{
+ ::rtl::math::setNan( &m_fValueMinimum );
+ ::rtl::math::setNan( &m_fValueMaximum );
+
+ double fExplicitOrigin = 0.0;
+ if( m_aSourceScale.Origin >>= fExplicitOrigin )
+ expandValueRange( fExplicitOrigin, fExplicitOrigin);
+}
+ScaleAutomatism::~ScaleAutomatism()
+{
+}
+
+void ScaleAutomatism::expandValueRange( double fMinimum, double fMaximum )
+{
+ if( (fMinimum < m_fValueMinimum) || ::rtl::math::isNan( m_fValueMinimum ) )
+ m_fValueMinimum = fMinimum;
+ if( (fMaximum > m_fValueMaximum) || ::rtl::math::isNan( m_fValueMaximum ) )
+ m_fValueMaximum = fMaximum;
+}
+
+void ScaleAutomatism::setAutoScalingOptions(
+ bool bExpandBorderToIncrementRhythm,
+ bool bExpandIfValuesCloseToBorder,
+ bool bExpandWideValuesToZero,
+ bool bExpandNarrowValuesTowardZero )
+{
+ // if called multiple times, enable an option, if it is set in at least one call
+ m_bExpandBorderToIncrementRhythm |= bExpandBorderToIncrementRhythm;
+ m_bExpandIfValuesCloseToBorder |= bExpandIfValuesCloseToBorder;
+ m_bExpandWideValuesToZero |= bExpandWideValuesToZero;
+ m_bExpandNarrowValuesTowardZero |= bExpandNarrowValuesTowardZero;
+
+ if( m_aSourceScale.AxisType==AxisType::PERCENT )
+ m_bExpandIfValuesCloseToBorder = false;
+}
+
+void ScaleAutomatism::setMaximumAutoMainIncrementCount( sal_Int32 nMaximumAutoMainIncrementCount )
+{
+ if( nMaximumAutoMainIncrementCount < 2 )
+ m_nMaximumAutoMainIncrementCount = 2; //#i82006
+ else if( nMaximumAutoMainIncrementCount > MAXIMUM_AUTO_INCREMENT_COUNT )
+ m_nMaximumAutoMainIncrementCount = MAXIMUM_AUTO_INCREMENT_COUNT;
+ else
+ m_nMaximumAutoMainIncrementCount = nMaximumAutoMainIncrementCount;
+}
+
+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;
+
+ bool bAutoMinimum = !(m_aSourceScale.Minimum >>= rExplicitScale.Minimum);
+ bool bAutoMaximum = !(m_aSourceScale.Maximum >>= rExplicitScale.Maximum);
+ bool bAutoOrigin = !(m_aSourceScale.Origin >>= rExplicitScale.Origin);
+
+ // automatic scale minimum
+ if( bAutoMinimum )
+ {
+ 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????
+ else
+ rExplicitScale.Minimum = m_fValueMinimum;
+ }
+
+ // automatic scale maximum
+ if( bAutoMaximum )
+ {
+ 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????
+ else
+ rExplicitScale.Maximum = m_fValueMaximum;
+ }
+
+ //---------------------------------------------------------------
+ //fill explicit increment
+
+ rExplicitIncrement.ShiftedPosition = (m_aSourceScale.AxisType==AxisType::SERIES) ? true : false;
+ 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 )
+ {
+ calculateExplicitIncrementAndScaleForCategory( rExplicitScale, rExplicitIncrement, bAutoMinimum, bAutoMaximum );
+ }
+ else
+ {
+ bIsLogarithm = AxisHelper::isLogarithmic( rExplicitScale.Scaling );
+ if( bIsLogarithm )
+ calculateExplicitIncrementAndScaleForLogarithmic( rExplicitScale, rExplicitIncrement, bAutoMinimum, bAutoMaximum );
+ else
+ calculateExplicitIncrementAndScaleForLinear( rExplicitScale, rExplicitIncrement, bAutoMinimum, bAutoMaximum );
+ }
+
+ // automatic origin
+ if( bAutoOrigin )
+ {
+ // #i71415# automatic origin for logarithmic axis
+ double fDefaulOrigin = bIsLogarithm ? 1.0 : 0.0;
+
+ if( fDefaulOrigin < rExplicitScale.Minimum )
+ fDefaulOrigin = rExplicitScale.Minimum;
+ else if( fDefaulOrigin > rExplicitScale.Maximum )
+ fDefaulOrigin = rExplicitScale.Maximum;
+
+ rExplicitScale.Origin = fDefaulOrigin;
+ }
+}
+
+ScaleData ScaleAutomatism::getScale() const
+{
+ return m_aSourceScale;
+}
+
+// private --------------------------------------------------------------------
+
+void ScaleAutomatism::calculateExplicitIncrementAndScaleForCategory(
+ ExplicitScaleData& rExplicitScale,
+ ExplicitIncrementData& rExplicitIncrement,
+ bool bAutoMinimum, bool bAutoMaximum ) const
+{
+ // no scaling for categories
+ rExplicitScale.Scaling.clear();
+
+ // ensure that at least one category is visible
+ if( rExplicitScale.Maximum <= rExplicitScale.Minimum )
+ rExplicitScale.Maximum = rExplicitScale.Minimum + 1.0;
+
+ // default increment settings
+ rExplicitIncrement.PostEquidistant = sal_True; // does not matter anyhow
+ rExplicitIncrement.Distance = 1.0; // category axis always have a main increment of 1
+ rExplicitIncrement.BaseValue = 0.0; // category axis always have a base of 0
+
+ // automatic minimum and maximum
+ if( bAutoMinimum && m_bExpandBorderToIncrementRhythm )
+ rExplicitScale.Minimum = TickmarkHelper::getMinimumAtIncrement( rExplicitScale.Minimum, rExplicitIncrement );
+ if( bAutoMaximum && m_bExpandBorderToIncrementRhythm )
+ rExplicitScale.Maximum = TickmarkHelper::getMaximumAtIncrement( rExplicitScale.Maximum, rExplicitIncrement );
+
+ //prevent performace killover
+ double fDistanceCount = ::rtl::math::approxFloor( (rExplicitScale.Maximum-rExplicitScale.Minimum) / rExplicitIncrement.Distance );
+ if( static_cast< sal_Int32 >( fDistanceCount ) > MAXIMUM_MANUAL_INCREMENT_COUNT )
+ {
+ double fMinimumFloor = ::rtl::math::approxFloor( rExplicitScale.Minimum );
+ double fMaximumCeil = ::rtl::math::approxCeil( rExplicitScale.Maximum );
+ rExplicitIncrement.Distance = ::rtl::math::approxCeil( (fMaximumCeil - fMinimumFloor) / MAXIMUM_MANUAL_INCREMENT_COUNT );
+ }
+
+ //---------------------------------------------------------------
+ //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))
+ {
+ //scaling dependent
+ //@todo autocalculate IntervalCount dependent on MainIncrement and scaling
+ rExplicitSubIncrement.IntervalCount = 2;
+ }
+ lcl_ensureMaximumSubIncrementCount( rExplicitSubIncrement.IntervalCount );
+ if(!(rSubIncrement.PostEquidistant>>=rExplicitSubIncrement.PostEquidistant))
+ {
+ //scaling dependent
+ rExplicitSubIncrement.PostEquidistant = sal_False;
+ }
+ }
+}
+
+//@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,
+ bool bAutoMinimum, bool bAutoMaximum ) const
+{
+ // *** STEP 1: initialize the range data ***
+
+ const double fInputMinimum = rExplicitScale.Minimum;
+ const double fInputMaximum = rExplicitScale.Maximum;
+
+ double fSourceMinimum = rExplicitScale.Minimum;
+ double fSourceMaximum = rExplicitScale.Maximum;
+
+ // set automatic PostEquidistant to true (maybe scaling dependent?)
+ // Note: scaling with PostEquidistant==false is untested and needs review
+ if( !(m_aSourceScale.IncrementData.PostEquidistant >>= rExplicitIncrement.PostEquidistant) )
+ rExplicitIncrement.PostEquidistant = sal_True;
+
+ /* All following scaling code will operate on the logarithms of the source
+ values. In the last step, the original values will be restored. */
+ uno::Reference< XScaling > xScaling = rExplicitScale.Scaling;
+ if( !xScaling.is() )
+ xScaling.set( AxisHelper::createLogarithmicScaling() );
+ uno::Reference< XScaling > xInverseScaling = xScaling->getInverseScaling();
+
+ fSourceMinimum = xScaling->doScaling( fSourceMinimum );
+ if( !::rtl::math::isFinite( fSourceMinimum ) )
+ fSourceMinimum = 0.0;
+ else if( ::rtl::math::approxEqual( fSourceMinimum, ::rtl::math::approxFloor( fSourceMinimum ) ) )
+ fSourceMinimum = ::rtl::math::approxFloor( fSourceMinimum );
+
+ fSourceMaximum = xScaling->doScaling( fSourceMaximum );
+ if( !::rtl::math::isFinite( fSourceMaximum ) )
+ fSourceMaximum = 0.0;
+ else if( ::rtl::math::approxEqual( fSourceMaximum, ::rtl::math::approxFloor( fSourceMaximum ) ) )
+ fSourceMaximum = ::rtl::math::approxFloor( fSourceMaximum );
+
+ /* If range is invalid (minimum greater than maximum), change one of the
+ variable limits to validate the range. In this step, a zero-sized range
+ is still allowed. */
+ if( fSourceMinimum > fSourceMaximum )
+ {
+ // force changing the maximum, if both limits are fixed
+ if( bAutoMaximum || !bAutoMinimum )
+ fSourceMaximum = fSourceMinimum;
+ else
+ fSourceMinimum = fSourceMaximum;
+ }
+
+ /* If maximum is less than 0 (and therefore minimum too), minimum and
+ maximum will be negated and swapped to make the following algorithms
+ easier. Example: Both ranges [2,5] and [-5,-2] will be processed as
+ [2,5], and the latter will be swapped back later. The range [0,0] is
+ explicitly excluded from swapping (this would result in [-1,0] instead
+ of the expected [0,1]). */
+ bool bSwapAndNegateRange = (fSourceMinimum < 0.0) && (fSourceMaximum <= 0.0);
+ if( bSwapAndNegateRange )
+ {
+ double fTempValue = fSourceMinimum;
+ fSourceMinimum = -fSourceMaximum;
+ fSourceMaximum = -fTempValue;
+ ::std::swap( bAutoMinimum, bAutoMaximum );
+ }
+
+ // *** STEP 2: find temporary (unrounded) axis minimum and maximum ***
+
+ double fTempMinimum = fSourceMinimum;
+ double fTempMaximum = fSourceMaximum;
+
+ /* If minimum is variable and greater than 0 (and therefore maximum too),
+ means all original values are greater than 1 (or all values are less
+ than 1, and the range has been swapped above), then: */
+ if( bAutoMinimum && (fTempMinimum > 0.0) )
+ {
+ /* If minimum is less than 5 (i.e. original source values less than
+ B^5, B being the base of the scaling), or if minimum and maximum
+ are in different increment intervals (means, if minimum and maximum
+ are not both in the range [B^n,B^(n+1)] for a whole number n), set
+ minimum to 0, which results in B^0=1 on the axis. */
+ double fMinimumFloor = ::rtl::math::approxFloor( fTempMinimum );
+ double fMaximumFloor = ::rtl::math::approxFloor( fTempMaximum );
+ // handle the exact value B^(n+1) to be in the range [B^n,B^(n+1)]
+ if( ::rtl::math::approxEqual( fTempMaximum, fMaximumFloor ) )
+ fMaximumFloor -= 1.0;
+
+ if( (fMinimumFloor < 5.0) || (fMinimumFloor < fMaximumFloor) )
+ {
+ if( m_bExpandWideValuesToZero )
+ fTempMinimum = 0.0;
+ }
+ /* Else (minimum and maximum are in one increment interval), expand
+ minimum toward 0 to make the 'shorter' data points visible. */
+ else
+ {
+ if( m_bExpandNarrowValuesTowardZero )
+ fTempMinimum -= 1.0;
+ }
+ }
+
+ /* If range is still zero-sized (e.g. when minimum is fixed), set minimum
+ to 0, which makes the axis start/stop at the value 1. */
+ if( fTempMinimum == fTempMaximum )
+ {
+ if( bAutoMinimum && (fTempMaximum > 0.0) )
+ fTempMinimum = 0.0;
+ else
+ fTempMaximum += 1.0; // always add one interval, even if maximum is fixed
+ }
+
+ // *** STEP 3: calculate main interval size ***
+
+ // base value (anchor position of the intervals), already scaled
+ if( !(m_aSourceScale.IncrementData.BaseValue >>= rExplicitIncrement.BaseValue) )
+ {
+ //scaling dependent
+ //@maybe todo is this default also plotter dependent ??
+ if( !bAutoMinimum )
+ rExplicitIncrement.BaseValue = fTempMinimum;
+ else if( !bAutoMaximum )
+ rExplicitIncrement.BaseValue = fTempMaximum;
+ else
+ rExplicitIncrement.BaseValue = 0.0;
+ }
+
+ // calculate automatic interval
+ bool bAutoDistance = !(m_aSourceScale.IncrementData.Distance >>= rExplicitIncrement.Distance);
+ if( bAutoDistance )
+ rExplicitIncrement.Distance = 0.0;
+
+ /* Restrict number of allowed intervals with user-defined distance to
+ MAXIMUM_MANUAL_INCREMENT_COUNT. */
+ sal_Int32 nMaxMainIncrementCount = bAutoDistance ?
+ m_nMaximumAutoMainIncrementCount : MAXIMUM_MANUAL_INCREMENT_COUNT;
+
+ // repeat calculation until number of intervals are valid
+ bool bNeedIteration = true;
+ bool bHasCalculatedDistance = false;
+ while( bNeedIteration )
+ {
+ if( bAutoDistance )
+ {
+ // first iteration: calculate interval size from axis limits
+ if( !bHasCalculatedDistance )
+ {
+ double fMinimumFloor = ::rtl::math::approxFloor( fTempMinimum );
+ double fMaximumCeil = ::rtl::math::approxCeil( fTempMaximum );
+ rExplicitIncrement.Distance = ::rtl::math::approxCeil( (fMaximumCeil - fMinimumFloor) / nMaxMainIncrementCount );
+ }
+ else
+ {
+ // following iterations: increase distance
+ rExplicitIncrement.Distance += 1.0;
+ }
+
+ // for next iteration: distance calculated -> use else path to increase
+ bHasCalculatedDistance = true;
+ }
+
+ // *** STEP 4: additional space above or below the data points ***
+
+ double fAxisMinimum = fTempMinimum;
+ double fAxisMaximum = fTempMaximum;
+
+ // round to entire multiples of the distance and add additional space
+ if( bAutoMinimum && m_bExpandBorderToIncrementRhythm )
+ {
+ fAxisMinimum = TickmarkHelper::getMinimumAtIncrement( fAxisMinimum, rExplicitIncrement );
+
+ //ensure valid values after scaling #i100995#
+ if( !bAutoDistance )
+ {
+ double fCheck = xInverseScaling->doScaling( fAxisMinimum );
+ if( !::rtl::math::isFinite( fCheck ) || fCheck <= 0 )
+ {
+ bAutoDistance = true;
+ bHasCalculatedDistance = false;
+ continue;
+ }
+ }
+ }
+ if( bAutoMaximum && m_bExpandBorderToIncrementRhythm )
+ {
+ fAxisMaximum = TickmarkHelper::getMaximumAtIncrement( fAxisMaximum, rExplicitIncrement );
+
+ //ensure valid values after scaling #i100995#
+ if( !bAutoDistance )
+ {
+ double fCheck = xInverseScaling->doScaling( fAxisMaximum );
+ if( !::rtl::math::isFinite( fCheck ) || fCheck <= 0 )
+ {
+ bAutoDistance = true;
+ bHasCalculatedDistance = false;
+ continue;
+ }
+ }
+ }
+
+ // set the resulting limits (swap back to negative range if needed)
+ if( bSwapAndNegateRange )
+ {
+ rExplicitScale.Minimum = -fAxisMaximum;
+ rExplicitScale.Maximum = -fAxisMinimum;
+ }
+ else
+ {
+ rExplicitScale.Minimum = fAxisMinimum;
+ rExplicitScale.Maximum = fAxisMaximum;
+ }
+
+ /* If the number of intervals is too high (e.g. due to invalid fixed
+ distance or due to added space above or below data points),
+ calculate again with increased distance. */
+ double fDistanceCount = ::rtl::math::approxFloor( (fAxisMaximum - fAxisMinimum) / rExplicitIncrement.Distance );
+ bNeedIteration = static_cast< sal_Int32 >( fDistanceCount ) > nMaxMainIncrementCount;
+ // if manual distance is invalid, trigger automatic calculation
+ if( bNeedIteration )
+ bAutoDistance = true;
+
+ // convert limits back to logarithmic scale
+ rExplicitScale.Minimum = xInverseScaling->doScaling( rExplicitScale.Minimum );
+ rExplicitScale.Maximum = xInverseScaling->doScaling( rExplicitScale.Maximum );
+
+ //ensure valid values after scaling #i100995#
+ if( !::rtl::math::isFinite( rExplicitScale.Minimum ) || rExplicitScale.Minimum <= 0)
+ {
+ rExplicitScale.Minimum = fInputMinimum;
+ if( !::rtl::math::isFinite( rExplicitScale.Minimum ) || rExplicitScale.Minimum <= 0 )
+ rExplicitScale.Minimum = 1.0;
+ }
+ if( !::rtl::math::isFinite( rExplicitScale.Maximum) || rExplicitScale.Maximum <= 0 )
+ {
+ rExplicitScale.Maximum= fInputMaximum;
+ if( !::rtl::math::isFinite( rExplicitScale.Maximum) || rExplicitScale.Maximum <= 0 )
+ rExplicitScale.Maximum = 10.0;
+ }
+ if( rExplicitScale.Maximum < rExplicitScale.Minimum )
+ ::std::swap( rExplicitScale.Maximum, rExplicitScale.Minimum );
+ }
+
+ //---------------------------------------------------------------
+ //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))
+ {
+ //scaling dependent
+ //@todo autocalculate IntervalCount dependent on MainIncrement and scaling
+ rExplicitSubIncrement.IntervalCount = 5;
+ }
+ lcl_ensureMaximumSubIncrementCount( rExplicitSubIncrement.IntervalCount );
+ if(!(rSubIncrement.PostEquidistant>>=rExplicitSubIncrement.PostEquidistant))
+ {
+ //scaling dependent
+ rExplicitSubIncrement.PostEquidistant = sal_False;
+ }
+ }
+}
+
+void ScaleAutomatism::calculateExplicitIncrementAndScaleForLinear(
+ ExplicitScaleData& rExplicitScale,
+ ExplicitIncrementData& rExplicitIncrement,
+ bool bAutoMinimum, bool bAutoMaximum ) const
+{
+ // *** STEP 1: initialize the range data ***
+
+ double fSourceMinimum = rExplicitScale.Minimum;
+ double fSourceMaximum = rExplicitScale.Maximum;
+
+ // set automatic PostEquidistant to true (maybe scaling dependent?)
+ if( !(m_aSourceScale.IncrementData.PostEquidistant >>= rExplicitIncrement.PostEquidistant) )
+ rExplicitIncrement.PostEquidistant = sal_True;
+
+ /* If range is invalid (minimum greater than maximum), change one of the
+ variable limits to validate the range. In this step, a zero-sized range
+ is still allowed. */
+ if( fSourceMinimum > fSourceMaximum )
+ {
+ // force changing the maximum, if both limits are fixed
+ if( bAutoMaximum || !bAutoMinimum )
+ fSourceMaximum = fSourceMinimum;
+ else
+ fSourceMinimum = fSourceMaximum;
+ }
+
+ /* If maximum is zero or negative (and therefore minimum too), minimum and
+ maximum will be negated and swapped to make the following algorithms
+ easier. Example: Both ranges [2,5] and [-5,-2] will be processed as
+ [2,5], and the latter will be swapped back later. The range [0,0] is
+ explicitly excluded from swapping (this would result in [-1,0] instead
+ of the expected [0,1]). */
+ bool bSwapAndNegateRange = (fSourceMinimum < 0.0) && (fSourceMaximum <= 0.0);
+ if( bSwapAndNegateRange )
+ {
+ double fTempValue = fSourceMinimum;
+ fSourceMinimum = -fSourceMaximum;
+ fSourceMaximum = -fTempValue;
+ ::std::swap( bAutoMinimum, bAutoMaximum );
+ }
+
+ // *** STEP 2: find temporary (unrounded) axis minimum and maximum ***
+
+ double fTempMinimum = fSourceMinimum;
+ double fTempMaximum = fSourceMaximum;
+
+ /* If minimum is variable and greater than 0 (and therefore maximum too),
+ means all values are positive (or all values are negative, and the
+ range has been swapped above), then: */
+ if( bAutoMinimum && (fTempMinimum > 0.0) )
+ {
+ /* If minimum equals maximum, or if minimum is less than 5/6 of
+ maximum, set minimum to 0. */
+ if( (fTempMinimum == fTempMaximum) || (fTempMinimum / fTempMaximum < 5.0 / 6.0) )
+ {
+ if( m_bExpandWideValuesToZero )
+ fTempMinimum = 0.0;
+ }
+ /* Else (minimum is greater than or equal to 5/6 of maximum), add half
+ of the visible range (expand minimum toward 0) to make the
+ 'shorter' data points visible. */
+ else
+ {
+ if( m_bExpandNarrowValuesTowardZero )
+ fTempMinimum -= (fTempMaximum - fTempMinimum) / 2.0;
+ }
+ }
+
+ /* If range is still zero-sized (e.g. when minimum is fixed), add some
+ space to a variable limit. */
+ if( fTempMinimum == fTempMaximum )
+ {
+ if( bAutoMaximum || !bAutoMinimum )
+ {
+ // change 0 to 1, otherwise double the value
+ if( fTempMaximum == 0.0 )
+ fTempMaximum = 1.0;
+ else
+ fTempMaximum *= 2.0;
+ }
+ else
+ {
+ // change 0 to -1, otherwise halve the value
+ if( fTempMinimum == 0.0 )
+ fTempMinimum = -1.0;
+ else
+ fTempMinimum /= 2.0;
+ }
+ }
+
+ // *** STEP 3: calculate main interval size ***
+
+ // base value (anchor position of the intervals)
+ if( !(m_aSourceScale.IncrementData.BaseValue >>= rExplicitIncrement.BaseValue) )
+ {
+ if( !bAutoMinimum )
+ rExplicitIncrement.BaseValue = fTempMinimum;
+ else if( !bAutoMaximum )
+ rExplicitIncrement.BaseValue = fTempMaximum;
+ else
+ rExplicitIncrement.BaseValue = 0.0;
+ }
+
+ // calculate automatic interval
+ bool bAutoDistance = !(m_aSourceScale.IncrementData.Distance >>= rExplicitIncrement.Distance);
+ /* Restrict number of allowed intervals with user-defined distance to
+ MAXIMUM_MANUAL_INCREMENT_COUNT. */
+ sal_Int32 nMaxMainIncrementCount = bAutoDistance ?
+ m_nMaximumAutoMainIncrementCount : MAXIMUM_MANUAL_INCREMENT_COUNT;
+
+ double fDistanceMagnitude = 0.0;
+ double fDistanceNormalized = 0.0;
+ bool bHasNormalizedDistance = false;
+
+ // repeat calculation until number of intervals are valid
+ bool bNeedIteration = true;
+ while( bNeedIteration )
+ {
+ if( bAutoDistance )
+ {
+ // first iteration: calculate interval size from axis limits
+ if( !bHasNormalizedDistance )
+ {
+ // raw size of an interval
+ double fDistance = (fTempMaximum - fTempMinimum) / nMaxMainIncrementCount;
+
+ // if distance of is less than 1e-307, do not do anything
+ if( fDistance <= 1.0e-307 )
+ {
+ fDistanceNormalized = 1.0;
+ fDistanceMagnitude = 1.0e-307;
+ }
+ else
+ {
+ // distance magnitude (a power of 10)
+ int nExponent = static_cast< int >( ::rtl::math::approxFloor( log10( fDistance ) ) );
+ fDistanceMagnitude = ::rtl::math::pow10Exp( 1.0, nExponent );
+
+ // stick normalized distance to a few predefined values
+ fDistanceNormalized = fDistance / fDistanceMagnitude;
+ if( fDistanceNormalized <= 1.0 )
+ fDistanceNormalized = 1.0;
+ else if( fDistanceNormalized <= 2.0 )
+ fDistanceNormalized = 2.0;
+ else if( fDistanceNormalized <= 5.0 )
+ fDistanceNormalized = 5.0;
+ else
+ {
+ fDistanceNormalized = 1.0;
+ fDistanceMagnitude *= 10;
+ }
+ }
+ // for next iteration: distance is normalized -> use else path to increase distance
+ bHasNormalizedDistance = true;
+ }
+ // following iterations: increase distance, use only allowed values
+ else
+ {
+ if( fDistanceNormalized == 1.0 )
+ fDistanceNormalized = 2.0;
+ else if( fDistanceNormalized == 2.0 )
+ fDistanceNormalized = 5.0;
+ else
+ {
+ fDistanceNormalized = 1.0;
+ fDistanceMagnitude *= 10;
+ }
+ }
+
+ // set the resulting distance
+ rExplicitIncrement.Distance = fDistanceNormalized * fDistanceMagnitude;
+ }
+
+ // *** STEP 4: additional space above or below the data points ***
+
+ double fAxisMinimum = fTempMinimum;
+ double fAxisMaximum = fTempMaximum;
+
+ // round to entire multiples of the distance and add additional space
+ if( bAutoMinimum )
+ {
+ // round to entire multiples of the distance, based on the base value
+ if( m_bExpandBorderToIncrementRhythm )
+ fAxisMinimum = TickmarkHelper::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) )
+ fAxisMinimum -= rExplicitIncrement.Distance;
+ }
+ if( bAutoMaximum )
+ {
+ // round to entire multiples of the distance, based on the base value
+ if( m_bExpandBorderToIncrementRhythm )
+ fAxisMaximum = TickmarkHelper::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) )
+ fAxisMaximum += rExplicitIncrement.Distance;
+ }
+
+ // set the resulting limits (swap back to negative range if needed)
+ if( bSwapAndNegateRange )
+ {
+ rExplicitScale.Minimum = -fAxisMaximum;
+ rExplicitScale.Maximum = -fAxisMinimum;
+ }
+ else
+ {
+ rExplicitScale.Minimum = fAxisMinimum;
+ rExplicitScale.Maximum = fAxisMaximum;
+ }
+
+ /* If the number of intervals is too high (e.g. due to invalid fixed
+ distance or due to added space above or below data points),
+ calculate again with increased distance. */
+ double fDistanceCount = ::rtl::math::approxFloor( (fAxisMaximum - fAxisMinimum) / rExplicitIncrement.Distance );
+ bNeedIteration = static_cast< sal_Int32 >( fDistanceCount ) > nMaxMainIncrementCount;
+ // if manual distance is invalid, trigger automatic calculation
+ if( bNeedIteration )
+ bAutoDistance = true;
+ }
+
+ //---------------------------------------------------------------
+ //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))
+ {
+ //scaling dependent
+ //@todo autocalculate IntervalCount dependent on MainIncrement and scaling
+ rExplicitSubIncrement.IntervalCount = 2;
+ }
+ lcl_ensureMaximumSubIncrementCount( rExplicitSubIncrement.IntervalCount );
+ if(!(rSubIncrement.PostEquidistant>>=rExplicitSubIncrement.PostEquidistant))
+ {
+ //scaling dependent
+ rExplicitSubIncrement.PostEquidistant = sal_False;
+ }
+ }
+}
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
diff --git a/chart2/source/view/axes/TickmarkHelper.cxx b/chart2/source/view/axes/TickmarkHelper.cxx
new file mode 100644
index 000000000000..81dc5786653e
--- /dev/null
+++ b/chart2/source/view/axes/TickmarkHelper.cxx
@@ -0,0 +1,925 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: TickmarkHelper.cxx,v $
+ * $Revision: 1.15.8.1 $
+ *
+ * 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 "TickmarkHelper.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()
+: fScaledTickValue( 0.0 )
+, fUnscaledTickValue( 0.0 )
+, aTickScreenPosition(0.0,0.0)
+, bPaintIt( true )
+, xTextShape( NULL )
+{
+}
+
+void TickInfo::updateUnscaledValue( const uno::Reference< XScaling >& xInverseScaling )
+{
+ if( xInverseScaling.is() )
+ this->fUnscaledTickValue = xInverseScaling->doScaling( this->fScaledTickValue );
+ else
+ this->fUnscaledTickValue = this->fScaledTickValue;
+}
+
+TickIter::TickIter( const uno::Sequence< uno::Sequence< double > >& rTicks
+ , const ExplicitIncrementData& rIncrement
+ , sal_Int32 nMinDepth, sal_Int32 nMaxDepth )
+ : m_pSimpleTicks(&rTicks), m_pInfoTicks(NULL)
+ , 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 );
+}
+
+TickIter::TickIter( ::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 TickIter::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;
+ }
+ }
+}
+
+TickIter::~TickIter()
+{
+ delete[] m_pnPositions;
+ delete[] m_pnPreParentCount;
+ delete[] m_pbIntervalFinished;
+}
+
+sal_Int32 TickIter::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* TickIter::firstValue()
+{
+ if( gotoFirst() )
+ {
+ m_fCurrentValue = getTickValue(m_nCurrentDepth, m_pnPositions[m_nCurrentDepth]);
+ return &m_fCurrentValue;
+ }
+ return NULL;
+}
+
+TickInfo* TickIter::firstInfo()
+{
+ if( m_pInfoTicks && gotoFirst() )
+ return &(*m_pInfoTicks)[m_nCurrentDepth][m_pnPositions[m_nCurrentDepth]];
+ return NULL;
+}
+
+sal_Int32 TickIter::getIntervalCount( sal_Int32 nDepth )
+{
+ if(nDepth>m_rIncrement.SubIncrements.getLength() || nDepth<0)
+ return 0;
+
+ if(!nDepth)
+ return m_nTickCount;
+
+ return m_rIncrement.SubIncrements[nDepth-1].IntervalCount;
+}
+
+bool TickIter::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 TickIter::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 TickIter::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 TickIter::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 TickIter::getCurrentIndex() const
+{
+ return m_nCurrentPos;
+}
+sal_Int32 TickIter::getMaxIndex() const
+{
+ return m_nTickCount-1;
+}
+
+double* TickIter::nextValue()
+{
+ if( gotoNext() )
+ {
+ m_fCurrentValue = getTickValue(m_nCurrentDepth, m_pnPositions[m_nCurrentDepth]);
+ return &m_fCurrentValue;
+ }
+ return NULL;
+}
+
+TickInfo* TickIter::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;
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+//static
+double TickmarkHelper::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 TickmarkHelper::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;
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+TickmarkHelper::TickmarkHelper(
+ 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 = TickmarkHelper::getMinimumAtIncrement( fMin, m_rIncrement );
+ m_fOuterMajorTickBorderMax = TickmarkHelper::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);
+ }
+ }
+}
+
+TickmarkHelper* TickmarkHelper::createShiftedTickmarkHelper() const
+{
+ ExplicitIncrementData aShiftedIncrement( m_rIncrement );
+ aShiftedIncrement.BaseValue = m_rIncrement.BaseValue-m_rIncrement.Distance/2.0;
+ return new TickmarkHelper( m_rScale, aShiftedIncrement );
+}
+
+TickmarkHelper::~TickmarkHelper()
+{
+ delete[] m_pfCurrentValues;
+}
+
+sal_Int32 TickmarkHelper::getTickDepth() const
+{
+ return m_rIncrement.SubIncrements.getLength() + 1;
+}
+
+sal_Int32 TickmarkHelper::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;
+
+ sal_Int32 nIntervalCount;
+ if(m_rIncrement.PostEquidistant )
+ nIntervalCount = static_cast<sal_Int32>
+ ( approxSub( m_fScaledVisibleMax, m_fScaledVisibleMin )
+ / m_rIncrement.Distance );
+ else
+ nIntervalCount = static_cast<sal_Int32>
+ ( approxSub( m_rScale.Maximum, m_rScale.Minimum )
+ / 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* TickmarkHelper::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* TickmarkHelper::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>m_rIncrement.SubIncrements.getLength() || 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 TickmarkHelper::isWithinOuterBorder( double fScaledValue ) const
+{
+ if(fScaledValue>m_fOuterMajorTickBorderMax_Scaled)
+ return false;
+ if(fScaledValue<m_fOuterMajorTickBorderMin_Scaled)
+ return false;
+
+ return true;
+}
+
+
+bool TickmarkHelper::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 TickmarkHelper::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();
+ rAllTickInfos[nDepth].resize( nCount );
+ for(sal_Int32 nN = 0; nN<nCount; nN++)
+ {
+ rAllTickInfos[nDepth][nN].fScaledTickValue = aAllTicks[nDepth][nN];
+ }
+ }
+}
+
+void TickmarkHelper::getAllTicksShifted( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ) const
+{
+ std::auto_ptr< TickmarkHelper > apShiftedTickmarkHelper( createShiftedTickmarkHelper() );
+ apShiftedTickmarkHelper->getAllTicks( rAllTickInfos );
+}
+
+void TickmarkHelper::addSubTicks( sal_Int32 nDepth, uno::Sequence< uno::Sequence< double > >& rParentTicks ) const
+{
+ TickIter 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(m_rIncrement.SubIncrements.getLength()>nDepth)
+ addSubTicks( nDepth+1, rParentTicks );
+}
+
+//-----------------------------------------------------------------------------
+// ___TickmarkHelper_2D___
+//-----------------------------------------------------------------------------
+TickmarkHelper_2D::TickmarkHelper_2D(
+ const ExplicitScaleData& rScale, const ExplicitIncrementData& rIncrement
+ //, double fStrech_SceneToScreen, double fOffset_SceneToScreen )
+ , const B2DVector& rStartScreenPos, const B2DVector& rEndScreenPos
+ , const B2DVector& rAxisLineToLabelLineShift )
+ : TickmarkHelper( 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;
+ }
+}
+
+TickmarkHelper* TickmarkHelper_2D::createShiftedTickmarkHelper() const
+{
+ ExplicitIncrementData aShiftedIncrement( m_rIncrement );
+ aShiftedIncrement.BaseValue = m_rIncrement.BaseValue-m_rIncrement.Distance/2.0;
+
+ ::basegfx::B2DVector aStart( m_aAxisStartScreenPosition2D );
+ ::basegfx::B2DVector aEnd( m_aAxisEndScreenPosition2D );
+ if( AxisOrientation_MATHEMATICAL==m_rScale.Orientation )
+ std::swap( aStart, aEnd );
+
+ return new TickmarkHelper_2D( m_rScale, aShiftedIncrement, aStart, aEnd, m_aAxisLineToLabelLineShift );
+}
+
+TickmarkHelper_2D::~TickmarkHelper_2D()
+{
+}
+
+bool TickmarkHelper_2D::isHorizontalAxis() const
+{
+ return ( m_aAxisStartScreenPosition2D.getY() == m_aAxisEndScreenPosition2D.getY() );
+}
+bool TickmarkHelper_2D::isVerticalAxis() const
+{
+ return ( m_aAxisStartScreenPosition2D.getX() == m_aAxisEndScreenPosition2D.getX() );
+}
+
+//static
+sal_Int32 TickmarkHelper_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;
+
+ B2DVector aDistance = pSecondTickInfo->aTickScreenPosition-pFirstTickInfo->aTickScreenPosition;
+ sal_Int32 nRet = static_cast<sal_Int32>(aDistance.getLength());
+ if(nRet<0)
+ nRet *= -1;
+ return nRet;
+}
+
+B2DVector TickmarkHelper_2D::getTickScreenPosition2D( double fScaledLogicTickValue ) const
+{
+ B2DVector aRet(m_aAxisStartScreenPosition2D);
+ aRet += (m_aAxisEndScreenPosition2D-m_aAxisStartScreenPosition2D)
+ *((fScaledLogicTickValue+m_fOffset_LogicToScreen)*m_fStrech_LogicToScreen);
+ return aRet;
+}
+
+void TickmarkHelper_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 TickmarkHelper_2D::getDistanceAxisTickToText( const AxisProperties& rAxisProperties ) 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();
+ aLabelDirection += aOrthoLabelDirection*AXIS2D_TICKLABELSPACING;
+ if( bFarAwayLabels )
+ aLabelDirection += m_aAxisLineToLabelLineShift;
+ return aLabelDirection;
+}
+
+void TickmarkHelper_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 TickmarkHelper_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 );
+ }
+ }
+}
+
+//'hide' tickmarks with identical screen values in aAllTickInfos
+void TickmarkHelper_2D::hideIdenticalScreenValues(
+ ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ) const
+{
+ TickIter aIter( rAllTickInfos, m_rIncrement );
+
+ TickInfo* pPreviousTickInfo = aIter.firstInfo();
+ if(!pPreviousTickInfo)
+ return;
+ pPreviousTickInfo->bPaintIt = true;
+ for( TickInfo* pTickInfo = aIter.nextInfo(); pTickInfo; pTickInfo = aIter.nextInfo())
+ {
+ pTickInfo->bPaintIt =
+ ( static_cast<sal_Int32>(pTickInfo->aTickScreenPosition.getX())
+ != static_cast<sal_Int32>(pPreviousTickInfo->aTickScreenPosition.getX()) )
+ ||
+ ( static_cast<sal_Int32>(pTickInfo->aTickScreenPosition.getY())
+ != static_cast<sal_Int32>(pPreviousTickInfo->aTickScreenPosition.getY()) );
+ pPreviousTickInfo = pTickInfo;
+ }
+}
+//-----------------------------------------------------------------------------
+// ___TickmarkHelper_3D___
+//-----------------------------------------------------------------------------
+TickmarkHelper_3D::TickmarkHelper_3D(
+ const ExplicitScaleData& rScale, const ExplicitIncrementData& rIncrement )
+ : TickmarkHelper( rScale, rIncrement )
+{
+}
+
+TickmarkHelper* TickmarkHelper_3D::createShiftedTickmarkHelper() const
+{
+ ExplicitIncrementData aShiftedIncrement( m_rIncrement );
+ aShiftedIncrement.BaseValue = m_rIncrement.BaseValue-m_rIncrement.Distance/2.0;
+ return new TickmarkHelper_3D( m_rScale, aShiftedIncrement );
+}
+
+TickmarkHelper_3D::~TickmarkHelper_3D()
+{
+}
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
diff --git a/chart2/source/view/axes/TickmarkHelper.hxx b/chart2/source/view/axes/TickmarkHelper.hxx
new file mode 100644
index 000000000000..a5749a074582
--- /dev/null
+++ b/chart2/source/view/axes/TickmarkHelper.hxx
@@ -0,0 +1,254 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: TickmarkHelper.hxx,v $
+ * $Revision: 1.7.24.1 $
+ *
+ * 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_TICKMARKHELPER_HXX
+#define _CHART2_TICKMARKHELPER_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>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+
+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;
+
+//methods:
+ TickInfo();
+ void updateUnscaledValue( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::chart2::XScaling >& xInverseScaling );
+};
+
+class TickIter
+{
+public:
+ TickIter( const ::com::sun::star::uno::Sequence<
+ ::com::sun::star::uno::Sequence< double > >& rTicks
+ , const ::com::sun::star::chart2::ExplicitIncrementData& rIncrement
+ , sal_Int32 nMinDepth=0, sal_Int32 nMaxDepth=-1 );
+ TickIter( ::std::vector< ::std::vector< TickInfo > >& rTickInfos
+ , const ::com::sun::star::chart2::ExplicitIncrementData& rIncrement
+ , sal_Int32 nMinDepth=0, sal_Int32 nMaxDepth=-1 );
+ virtual ~TickIter();
+
+ virtual double* firstValue();
+ virtual double* nextValue();
+
+ virtual TickInfo* firstInfo();
+ virtual TickInfo* nextInfo();
+
+ sal_Int32 getCurrentDepth() const { return m_nCurrentDepth; }
+
+protected:
+ bool gotoIndex( sal_Int32 nTickIndex );
+ sal_Int32 getCurrentIndex() const;
+ sal_Int32 getMaxIndex() const;
+
+private: //methods
+ sal_Int32 getIntervalCount( sal_Int32 nDepth );
+ bool isAtLastPartTick();
+
+ void initIter( sal_Int32 nMinDepth, sal_Int32 nMaxDepth );
+ sal_Int32 getStartDepth() const;
+
+ bool gotoFirst();
+ bool gotoNext();
+
+
+ double getTickValue(sal_Int32 nDepth, sal_Int32 nIndex) const
+ {
+ if(m_pSimpleTicks)
+ return (*m_pSimpleTicks)[nDepth][nIndex];
+ else
+ return (((*m_pInfoTicks)[nDepth])[nIndex]).fScaledTickValue;
+ }
+ sal_Int32 getTickCount( sal_Int32 nDepth ) const
+ {
+ if(m_pSimpleTicks)
+ return (*m_pSimpleTicks)[nDepth].getLength();
+ else
+ return (*m_pInfoTicks)[nDepth].size();
+ }
+ sal_Int32 getMaxDepth() const
+ {
+ if(m_pSimpleTicks)
+ return (*m_pSimpleTicks).getLength()-1;
+ else
+ return (*m_pInfoTicks).size()-1;
+ }
+
+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;
+ //iteration from m_nMinDepth to m_nMaxDepth
+ sal_Int32 m_nMinDepth;
+ sal_Int32 m_nMaxDepth;
+ sal_Int32 m_nTickCount;
+ sal_Int32* m_pnPositions; //current positions in the different sequences
+ sal_Int32* m_pnPreParentCount; //the tickmarks do not start with a major tick always,
+ //the PreParentCount states for each depth how many subtickmarks are available in front of the first parent tickmark
+ bool* m_pbIntervalFinished;
+ sal_Int32 m_nCurrentDepth;
+ sal_Int32 m_nCurrentPos;
+ double m_fCurrentValue;
+};
+
+class TickmarkHelper
+{
+public:
+ TickmarkHelper(
+ const ::com::sun::star::chart2::ExplicitScaleData& rScale
+ , const ::com::sun::star::chart2::ExplicitIncrementData& rIncrement );
+ virtual ~TickmarkHelper();
+
+ virtual TickmarkHelper* createShiftedTickmarkHelper() 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 ::com::sun::star::chart2::ExplicitIncrementData& rIncrement );
+ static double getMaximumAtIncrement( double fMax, const ::com::sun::star::chart2::ExplicitIncrementData& rIncrement );
+
+protected: //methods
+ void addSubTicks( sal_Int32 nDepth,
+ ::com::sun::star::uno::Sequence<
+ ::com::sun::star::uno::Sequence< double > >& rParentTicks ) const;
+ double* getMajorTick( sal_Int32 nTick ) const;
+ double* getMinorTick( sal_Int32 nTick, sal_Int32 nDepth
+ , 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 {}
+ virtual void hideIdenticalScreenValues( ::std::vector< ::std::vector< TickInfo > >& /*rAllTickInfos*/ ) const {}
+
+protected: //member
+ ::com::sun::star::chart2::ExplicitScaleData m_rScale;
+ ::com::sun::star::chart2::ExplicitIncrementData m_rIncrement;
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XScaling >
+ m_xInverseScaling;
+ 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 ) const;
+
+ virtual void updateScreenValues( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ) const;
+ virtual void hideIdenticalScreenValues( ::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
diff --git a/chart2/source/view/axes/TickmarkProperties.hxx b/chart2/source/view/axes/TickmarkProperties.hxx
new file mode 100644
index 000000000000..92c0d5e79400
--- /dev/null
+++ b/chart2/source/view/axes/TickmarkProperties.hxx
@@ -0,0 +1,56 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: TickmarkProperties.hxx,v $
+ * $Revision: 1.3 $
+ *
+ * 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_VTICKMARKPROPERTIES_HXX
+#define _CHART2_VTICKMARKPROPERTIES_HXX
+
+#include "VLineProperties.hxx"
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+
+//-----------------------------------------------------------------------------
+/**
+*/
+
+struct TickmarkProperties
+{
+ sal_Int32 RelativePos;//Position in screen values relative to the axis where the tickmark line starts
+ sal_Int32 Length;//Length of the tickmark line in screen values
+
+ VLineProperties aLineProperties;
+};
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
+#endif
diff --git a/chart2/source/view/axes/VAxisBase.cxx b/chart2/source/view/axes/VAxisBase.cxx
new file mode 100644
index 000000000000..da2f01523a97
--- /dev/null
+++ b/chart2/source/view/axes/VAxisBase.cxx
@@ -0,0 +1,237 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: VAxisBase.cxx,v $
+ * $Revision: 1.3 $
+ *
+ * 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 "VAxisBase.hxx"
+#include "ShapeFactory.hxx"
+#include "CommonConverters.hxx"
+#include "TickmarkHelper.hxx"
+#include "macros.hxx"
+
+// header for define DBG_ASSERT
+#include <tools/debug.hxx>
+
+#include <memory>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+using ::com::sun::star::uno::Reference;
+
+VAxisBase::VAxisBase( sal_Int32 nDimensionIndex, sal_Int32 nDimensionCount
+ , const AxisProperties& rAxisProperties
+ , const uno::Reference< util::XNumberFormatsSupplier >& xNumberFormatsSupplier )
+ : VAxisOrGridBase( nDimensionIndex, nDimensionCount )
+ , m_xNumberFormatsSupplier( xNumberFormatsSupplier )
+ , m_aAxisProperties( rAxisProperties )
+ , m_bUseTextLabels( false )
+ , m_bReCreateAllTickInfos( true )
+ , m_bRecordMaximumTextSize(false)
+ , m_nMaximumTextWidthSoFar(0)
+ , m_nMaximumTextHeightSoFar(0)
+{
+}
+
+VAxisBase::~VAxisBase()
+{
+}
+
+sal_Int32 VAxisBase::getDimensionCount()
+{
+ return m_nDimension;
+}
+
+void SAL_CALL VAxisBase::initAxisLabelProperties( const ::com::sun::star::awt::Size& rFontReferenceSize
+ , const ::com::sun::star::awt::Rectangle& rMaximumSpaceForLabels )
+{
+ m_aAxisLabelProperties.m_aFontReferenceSize = rFontReferenceSize;
+ m_aAxisLabelProperties.m_aMaximumSpaceForLabels = rMaximumSpaceForLabels;
+
+ if( !m_aAxisProperties.m_bDisplayLabels )
+ return;
+
+ if( AxisType::CATEGORY==m_aAxisProperties.m_nAxisType
+ || AxisType::SERIES==m_aAxisProperties.m_nAxisType )
+ {
+ if( m_aAxisProperties.m_xAxisTextProvider.is() )
+ m_aTextLabels = m_aAxisProperties.m_xAxisTextProvider->getTextualData();
+
+ m_bUseTextLabels = true;
+ if( m_aTextLabels.getLength() == 1 && AxisType::SERIES==m_aAxisProperties.m_nAxisType )
+ {
+ //don't show a single series name
+ m_aAxisProperties.m_bDisplayLabels = false;
+ return;
+ }
+ }
+
+ m_aAxisLabelProperties.nNumberFormatKey = m_aAxisProperties.m_nNumberFormatKey;
+ m_aAxisLabelProperties.init(m_aAxisProperties.m_xAxisModel);
+}
+
+void VAxisBase::recordMaximumTextSize( const Reference< drawing::XShape >& xShape, double fRotationAngleDegree )
+{
+ if( m_bRecordMaximumTextSize && xShape.is() )
+ {
+ awt::Size aSize( ShapeFactory::getSizeAfterRotation(
+ xShape, fRotationAngleDegree ) );
+
+ m_nMaximumTextWidthSoFar = std::max( m_nMaximumTextWidthSoFar, aSize.Width );
+ m_nMaximumTextHeightSoFar = std::max( m_nMaximumTextHeightSoFar, aSize.Height );
+ }
+}
+
+sal_Int32 VAxisBase::estimateMaximumAutoMainIncrementCount()
+{
+ return 10;
+}
+
+void VAxisBase::setExrtaLinePositionAtOtherAxis( const double& fCrossingAt )
+{
+ if( m_aAxisProperties.m_pfExrtaLinePositionAtOtherAxis )
+ delete m_aAxisProperties.m_pfExrtaLinePositionAtOtherAxis;
+ m_aAxisProperties.m_pfExrtaLinePositionAtOtherAxis = new double(fCrossingAt);
+}
+
+sal_Bool SAL_CALL VAxisBase::isAnythingToDraw()
+{
+ if( !m_aAxisProperties.m_xAxisModel.is() )
+ return false;
+
+ DBG_ASSERT(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is(),"Axis is not proper initialized");
+ if(!(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is()))
+ return false;
+
+ uno::Reference< beans::XPropertySet > xProps( m_aAxisProperties.m_xAxisModel, uno::UNO_QUERY );
+ if( xProps.is() )
+ {
+ sal_Bool bShow = sal_False;
+ xProps->getPropertyValue( C2U( "Show" ) ) >>= bShow;
+ if( !bShow )
+ return false;
+ }
+ return true;
+}
+
+void SAL_CALL VAxisBase::setExplicitScaleAndIncrement(
+ const ExplicitScaleData& rScale
+ , const ExplicitIncrementData& rIncrement )
+ throw (uno::RuntimeException)
+{
+ m_bReCreateAllTickInfos = true;
+ m_aScale = rScale;
+ m_aIncrement = rIncrement;
+}
+
+bool VAxisBase::prepareShapeCreation()
+{
+ //returns true if all is ready for further shape creation and any shapes need to be created
+ if( !isAnythingToDraw() )
+ return false;
+
+ if( m_bReCreateAllTickInfos )
+ {
+ //-----------------------------------------
+ //create all scaled tickmark values
+ if( m_xTextTarget.is() )
+ {
+ TickIter aRemoveIter( m_aAllTickInfos, m_aIncrement, 0, 0 );
+ removeTextShapesFromTicks( aRemoveIter, m_xTextTarget );
+ }
+
+ std::auto_ptr< TickmarkHelper > apTickmarkHelper( this->createTickmarkHelper() );
+ apTickmarkHelper->getAllTicks( m_aAllTickInfos );
+ m_bReCreateAllTickInfos = false;
+ }
+
+ if( m_xGroupShape_Shapes.is() )
+ return true;
+
+ //-----------------------------------------
+ //create named group shape
+ m_xGroupShape_Shapes = this->createGroupShape( m_xLogicTarget, m_nDimension==2 ? m_aCID : C2U(""));
+
+ if( m_aAxisProperties.m_bDisplayLabels )
+ m_xTextTarget = m_pShapeFactory->createGroup2D( m_xFinalTarget, m_aCID );
+
+ return true;
+}
+
+sal_Int32 VAxisBase::getIndexOfLongestLabel( const uno::Sequence< rtl::OUString >& rLabels )
+{
+ sal_Int32 nRet = 0;
+ sal_Int32 nLength = 0;
+ sal_Int32 nN = 0;
+ for( nN=0; nN<rLabels.getLength(); nN++ )
+ {
+ //todo: get real text width (without creating shape) instead of character count
+ if( rLabels[nN].getLength() > nLength )
+ {
+ nLength = rLabels[nN].getLength();
+ nRet = nN;
+ }
+ }
+ return nRet;
+}
+
+void VAxisBase::removeTextShapesFromTicks( TickIter& rIter, const Reference< drawing::XShapes >& xTarget )
+{
+ for( TickInfo* pTickInfo = rIter.firstInfo()
+ ; pTickInfo; pTickInfo = rIter.nextInfo() )
+ {
+ if(pTickInfo->xTextShape.is())
+ {
+ xTarget->remove(pTickInfo->xTextShape);
+ pTickInfo->xTextShape = NULL;
+ }
+ }
+}
+
+void VAxisBase::updateUnscaledValuesAtTicks( TickIter& rIter )
+{
+ Reference< XScaling > xInverseScaling( NULL );
+ if( m_aScale.Scaling.is() )
+ xInverseScaling = m_aScale.Scaling->getInverseScaling();
+
+ for( TickInfo* pTickInfo = rIter.firstInfo()
+ ; pTickInfo; pTickInfo = rIter.nextInfo() )
+ {
+ pTickInfo->updateUnscaledValue( xInverseScaling );
+ }
+}
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
diff --git a/chart2/source/view/axes/VAxisBase.hxx b/chart2/source/view/axes/VAxisBase.hxx
new file mode 100644
index 000000000000..ab826caca2ff
--- /dev/null
+++ b/chart2/source/view/axes/VAxisBase.hxx
@@ -0,0 +1,109 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: VAxisBase.hxx,v $
+ * $Revision: 1.3 $
+ *
+ * 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_VAXISBASE_HXX
+#define _CHART2_VAXISBASE_HXX
+
+#include "VAxisOrGridBase.hxx"
+#include "VAxisProperties.hxx"
+#include "TickmarkHelper.hxx"
+#include <com/sun/star/util/XNumberFormatsSupplier.hpp>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+
+//-----------------------------------------------------------------------------
+/**
+*/
+
+class VAxisBase : public VAxisOrGridBase
+{
+public:
+ VAxisBase( sal_Int32 nDimensionIndex, sal_Int32 nDimensionCount
+ , const AxisProperties& rAxisProperties
+ , const ::com::sun::star::uno::Reference<
+ ::com::sun::star::util::XNumberFormatsSupplier >& xNumberFormatsSupplier );
+ virtual ~VAxisBase();
+
+ sal_Int32 getDimensionCount();
+
+ virtual void SAL_CALL createMaximumLabels()=0;
+ virtual void SAL_CALL createLabels()=0;
+ virtual void SAL_CALL updatePositions()=0;
+
+ virtual sal_Bool SAL_CALL isAnythingToDraw();
+ virtual void SAL_CALL 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 )
+ throw (::com::sun::star::uno::RuntimeException);
+
+ virtual sal_Int32 estimateMaximumAutoMainIncrementCount();
+
+ void setExrtaLinePositionAtOtherAxis( const double& fCrossingAt );
+
+ //-------------------------------------------------------------------------
+ //-------------------------------------------------------------------------
+protected: //methods
+ sal_Int32 getIndexOfLongestLabel( const ::com::sun::star::uno::Sequence< rtl::OUString >& rLabels );
+ void removeTextShapesFromTicks( TickIter& rIter, const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& xTarget );
+ void updateUnscaledValuesAtTicks( TickIter& rIter );
+
+ virtual bool prepareShapeCreation();
+ void recordMaximumTextSize( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShape >& xShape
+ , double fRotationAngleDegree );
+
+protected: //member
+ ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier > m_xNumberFormatsSupplier;
+ AxisProperties m_aAxisProperties;
+ AxisLabelProperties m_aAxisLabelProperties;
+ ::com::sun::star::uno::Sequence< rtl::OUString > m_aTextLabels;
+ bool m_bUseTextLabels;
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes > m_xGroupShape_Shapes;
+ ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes > m_xTextTarget;
+
+ ::std::vector< ::std::vector< TickInfo > > m_aAllTickInfos;
+ bool m_bReCreateAllTickInfos;
+
+ bool m_bRecordMaximumTextSize;
+ sal_Int32 m_nMaximumTextWidthSoFar;
+ sal_Int32 m_nMaximumTextHeightSoFar;
+};
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
+#endif
diff --git a/chart2/source/view/axes/VAxisOrGridBase.cxx b/chart2/source/view/axes/VAxisOrGridBase.cxx
new file mode 100644
index 000000000000..472349088584
--- /dev/null
+++ b/chart2/source/view/axes/VAxisOrGridBase.cxx
@@ -0,0 +1,101 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: VAxisOrGridBase.cxx,v $
+ * $Revision: 1.4 $
+ *
+ * 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 "VAxisOrGridBase.hxx"
+#include "ShapeFactory.hxx"
+#include "CommonConverters.hxx"
+#include "TickmarkHelper.hxx"
+
+// header for define DBG_ASSERT
+#include <tools/debug.hxx>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+using ::com::sun::star::uno::Reference;
+
+VAxisOrGridBase::VAxisOrGridBase( sal_Int32 nDimensionIndex, sal_Int32 nDimensionCount )
+ : PlotterBase( nDimensionCount )
+ , m_nDimensionIndex( nDimensionIndex )
+ , m_eLeftWallPos(CuboidPlanePosition_Left)
+ , m_eBackWallPos(CuboidPlanePosition_Back)
+ , m_eBottomPos(CuboidPlanePosition_Bottom)
+{
+}
+
+VAxisOrGridBase::~VAxisOrGridBase()
+{
+}
+
+void SAL_CALL VAxisOrGridBase::setExplicitScaleAndIncrement(
+ const ExplicitScaleData& rScale
+ , const ExplicitIncrementData& rIncrement )
+ throw (uno::RuntimeException)
+{
+ m_aScale = rScale;
+ m_aIncrement = rIncrement;
+}
+
+void VAxisOrGridBase::setTransformationSceneToScreen( const drawing::HomogenMatrix& rMatrix )
+{
+ m_aMatrixScreenToScene = HomogenMatrixToB3DHomMatrix(rMatrix);
+ PlotterBase::setTransformationSceneToScreen( rMatrix);
+}
+
+void VAxisOrGridBase::set3DWallPositions( CuboidPlanePosition eLeftWallPos, CuboidPlanePosition eBackWallPos, CuboidPlanePosition eBottomPos )
+{
+ m_eLeftWallPos = eLeftWallPos;
+ m_eBackWallPos = eBackWallPos;
+ m_eBottomPos = eBottomPos;
+}
+
+TickmarkHelper* VAxisOrGridBase::createTickmarkHelper()
+{
+ 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;
+}
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
diff --git a/chart2/source/view/axes/VAxisOrGridBase.hxx b/chart2/source/view/axes/VAxisOrGridBase.hxx
new file mode 100644
index 000000000000..0809fc9d4f0d
--- /dev/null
+++ b/chart2/source/view/axes/VAxisOrGridBase.hxx
@@ -0,0 +1,86 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: VAxisOrGridBase.hxx,v $
+ * $Revision: 1.4 $
+ *
+ * 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_VAXISORGRIDBASE_HXX
+#define _CHART2_VAXISORGRIDBASE_HXX
+
+#include "PlotterBase.hxx"
+#include "ThreeDHelper.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>
+#include <basegfx/matrix/b3dhommatrix.hxx>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+
+//-----------------------------------------------------------------------------
+/**
+*/
+class ShapeFactory;
+class TickmarkHelper;
+
+class VAxisOrGridBase : public PlotterBase
+{
+public:
+ VAxisOrGridBase( sal_Int32 nDimensionIndex, sal_Int32 nDimensionCount );
+ 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 )
+ throw (::com::sun::star::uno::RuntimeException);
+ void set3DWallPositions( CuboidPlanePosition eLeftWallPos, CuboidPlanePosition eBackWallPos, CuboidPlanePosition eBottomPos );
+
+ virtual TickmarkHelper* createTickmarkHelper();
+
+ //-------------------------------------------------------------------------
+ //-------------------------------------------------------------------------
+protected: //member
+ ::com::sun::star::chart2::ExplicitScaleData m_aScale;
+ ::com::sun::star::chart2::ExplicitIncrementData m_aIncrement;
+ sal_Int32 m_nDimensionIndex;
+
+ ::basegfx::B3DHomMatrix m_aMatrixScreenToScene;
+
+ CuboidPlanePosition m_eLeftWallPos;
+ CuboidPlanePosition m_eBackWallPos;
+ CuboidPlanePosition m_eBottomPos;
+};
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
+#endif
diff --git a/chart2/source/view/axes/VAxisProperties.cxx b/chart2/source/view/axes/VAxisProperties.cxx
new file mode 100644
index 000000000000..27ca8d2188e3
--- /dev/null
+++ b/chart2/source/view/axes/VAxisProperties.cxx
@@ -0,0 +1,476 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: VAxisProperties.cxx,v $
+ * $Revision: 1.13 $
+ *
+ * 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 "VAxisProperties.hxx"
+#include "macros.hxx"
+#include "ViewDefines.hxx"
+#include "CommonConverters.hxx"
+#include "AxisHelper.hxx"
+#include "DiagramHelper.hxx"
+
+#include <tools/color.hxx>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/chart/ChartAxisArrangeOrderType.hpp>
+#include <com/sun/star/drawing/LineStyle.hpp>
+#include <com/sun/star/text/WritingMode2.hpp>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+sal_Int32 lcl_calcTickLengthForDepth(sal_Int32 nDepth,sal_Int32 nTickmarkStyle)
+{
+ sal_Int32 nWidth = AXIS2D_TICKLENGTH; //@maybefuturetodo this length could be offered by the model
+ double fPercent = 1.0;
+ switch(nDepth)
+ {
+ case 0:
+ fPercent = 1.0;
+ break;
+ case 1:
+ fPercent = 0.75;//percentage like in the old chart
+ break;
+ case 2:
+ fPercent = 0.5;
+ break;
+ default:
+ fPercent = 0.3;
+ break;
+ }
+ if(nTickmarkStyle==3)//inner and outer tickmarks
+ fPercent*=2.0;
+ return static_cast<sal_Int32>(nWidth*fPercent);
+}
+
+double lcl_getTickOffset(sal_Int32 nLength,sal_Int32 nTickmarkStyle)
+{
+ double fPercent = 0.0; //0<=fPercent<=1
+ //0.0: completly inner
+ //1.0: completly outer
+ //0.5: half and half
+
+ /*
+ nTickmarkStyle:
+ 1: inner tickmarks
+ 2: outer tickmarks
+ 3: inner and outer tickmarks
+ */
+ switch(nTickmarkStyle)
+ {
+ case 1:
+ fPercent = 0.0;
+ break;
+ case 2:
+ fPercent = 1.0;
+ break;
+ default:
+ fPercent = 0.5;
+ break;
+ }
+ return fPercent*nLength;
+}
+
+VLineProperties AxisProperties::makeLinePropertiesForDepth( sal_Int32 /* nDepth */ ) const
+{
+ //@todo get this from somewhere; maybe for each subincrement
+ //so far the model does not offer different settings for each tick depth
+ return m_aLineProperties;
+}
+
+TickmarkProperties AxisProperties::makeTickmarkProperties(
+ sal_Int32 nDepth ) const
+{
+ /*
+ nTickmarkStyle:
+ 1: inner tickmarks
+ 2: outer tickmarks
+ 3: inner and outer tickmarks
+ */
+ sal_Int32 nTickmarkStyle = 1;
+ if(nDepth==0)
+ {
+ nTickmarkStyle = m_nMajorTickmarks;
+ if(!nTickmarkStyle)
+ {
+ //create major tickmarks as if they were minor tickmarks
+ nDepth = 1;
+ nTickmarkStyle = m_nMinorTickmarks;
+ }
+ }
+ else if( nDepth==1)
+ {
+ nTickmarkStyle = m_nMinorTickmarks;
+ }
+
+ if( m_fInnerDirectionSign == 0.0 )
+ {
+ if( nTickmarkStyle != 0 )
+ nTickmarkStyle = 3; //inner and outer tickmarks
+ }
+
+ TickmarkProperties aTickmarkProperties;
+ aTickmarkProperties.Length = lcl_calcTickLengthForDepth(nDepth,nTickmarkStyle);
+ aTickmarkProperties.RelativePos = static_cast<sal_Int32>(lcl_getTickOffset(aTickmarkProperties.Length,nTickmarkStyle));
+ aTickmarkProperties.aLineProperties = this->makeLinePropertiesForDepth( nDepth );
+ return aTickmarkProperties;
+}
+
+//static
+TickmarkProperties AxisProperties::getBiggestTickmarkProperties()
+{
+ TickmarkProperties aTickmarkProperties;
+ sal_Int32 nDepth = 0;
+ sal_Int32 nTickmarkStyle = 3;//inner and outer tickmarks
+ aTickmarkProperties.Length = lcl_calcTickLengthForDepth( nDepth,nTickmarkStyle );
+ aTickmarkProperties.RelativePos = static_cast<sal_Int32>( lcl_getTickOffset( aTickmarkProperties.Length, nTickmarkStyle ) );
+ return aTickmarkProperties;
+}
+
+//--------------------------------------------------------------------------
+
+AxisProperties::AxisProperties( const uno::Reference< XAxis >& xAxisModel
+ , const uno::Reference< data::XTextualDataSequence >& xAxisTextProvider )
+ : m_xAxisModel(xAxisModel)
+ , m_nDimensionIndex(0)
+ , m_bIsMainAxis(true)
+ , m_bSwapXAndY(false)
+ , m_eCrossoverType( ::com::sun::star::chart::ChartAxisPosition_ZERO )
+ , m_eLabelPos( ::com::sun::star::chart::ChartAxisLabelPosition_NEAR_AXIS )
+ , m_eTickmarkPos( ::com::sun::star::chart::ChartAxisMarkPosition_AT_LABELS_AND_AXIS )
+ , m_pfMainLinePositionAtOtherAxis(NULL)
+ , m_pfExrtaLinePositionAtOtherAxis(NULL)
+ , m_bCrossingAxisHasReverseDirection(false)
+ , m_bCrossingAxisIsCategoryAxes(false)
+ , m_bAxisBetweenCategories(false)
+ , m_fLabelDirectionSign(1.0)
+ , m_fInnerDirectionSign(1.0)
+ , m_bLabelsOutside(true)
+ , m_aLabelAlignment(LABEL_ALIGN_RIGHT_TOP)
+ , m_bDisplayLabels( true )
+ , m_nNumberFormatKey(0)
+ , m_nMajorTickmarks(1)
+ , m_nMinorTickmarks(1)
+ , m_aTickmarkPropertiesList()
+ , m_aLineProperties()
+ //for category axes
+ , m_nAxisType(AxisType::REALNUMBER)
+ , m_xAxisTextProvider(xAxisTextProvider)
+ , m_bTickmarksAtIndicatedValue(false)
+{
+}
+
+AxisProperties::AxisProperties( const AxisProperties& rAxisProperties )
+ : m_xAxisModel( rAxisProperties.m_xAxisModel )
+ , m_nDimensionIndex( m_nDimensionIndex )
+ , m_bIsMainAxis( rAxisProperties.m_bIsMainAxis )
+ , m_bSwapXAndY( rAxisProperties.m_bSwapXAndY )
+ , m_eCrossoverType( rAxisProperties.m_eCrossoverType )
+ , m_eLabelPos( rAxisProperties.m_eLabelPos )
+ , m_eTickmarkPos( rAxisProperties.m_eTickmarkPos )
+ , m_pfMainLinePositionAtOtherAxis( NULL )
+ , 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_bLabelsOutside( rAxisProperties.m_bLabelsOutside )
+ , m_aLabelAlignment( rAxisProperties.m_aLabelAlignment )
+ , m_bDisplayLabels( rAxisProperties.m_bDisplayLabels )
+ , m_nNumberFormatKey( rAxisProperties.m_nNumberFormatKey )
+ , m_nMajorTickmarks( rAxisProperties.m_nMajorTickmarks )
+ , m_nMinorTickmarks( rAxisProperties.m_nMinorTickmarks )
+ , m_aTickmarkPropertiesList( rAxisProperties.m_aTickmarkPropertiesList )
+ , m_aLineProperties( rAxisProperties.m_aLineProperties )
+ //for category axes
+ , m_nAxisType( rAxisProperties.m_nAxisType )
+ , m_xAxisTextProvider( rAxisProperties.m_xAxisTextProvider )
+ , m_bTickmarksAtIndicatedValue( rAxisProperties.m_bTickmarksAtIndicatedValue )
+{
+ if( rAxisProperties.m_pfMainLinePositionAtOtherAxis )
+ m_pfMainLinePositionAtOtherAxis = new double(*rAxisProperties.m_pfMainLinePositionAtOtherAxis);
+ if( rAxisProperties.m_pfExrtaLinePositionAtOtherAxis )
+ m_pfExrtaLinePositionAtOtherAxis = new double (*rAxisProperties.m_pfExrtaLinePositionAtOtherAxis);
+}
+
+AxisProperties::~AxisProperties()
+{
+ delete m_pfMainLinePositionAtOtherAxis;
+ delete m_pfExrtaLinePositionAtOtherAxis;
+}
+
+LabelAlignment lcl_getLabelAlignmentForZAxis( const AxisProperties& rAxisProperties )
+{
+ LabelAlignment aRet( LABEL_ALIGN_RIGHT );
+ if( rAxisProperties.m_fLabelDirectionSign<0 )
+ aRet = LABEL_ALIGN_LEFT;
+ return aRet;
+}
+
+LabelAlignment lcl_getLabelAlignmentForYAxis( const AxisProperties& rAxisProperties )
+{
+ LabelAlignment aRet( LABEL_ALIGN_RIGHT );
+ if( rAxisProperties.m_fLabelDirectionSign<0 )
+ aRet = LABEL_ALIGN_LEFT;
+ return aRet;
+}
+
+LabelAlignment lcl_getLabelAlignmentForXAxis( const AxisProperties& rAxisProperties )
+{
+ LabelAlignment aRet( LABEL_ALIGN_BOTTOM );
+ if( rAxisProperties.m_fLabelDirectionSign<0 )
+ aRet = LABEL_ALIGN_TOP;
+ return aRet;
+}
+
+void AxisProperties::initAxisPositioning( const uno::Reference< beans::XPropertySet >& xAxisProp )
+{
+ if( !xAxisProp.is() )
+ return;
+ try
+ {
+ if( AxisHelper::isAxisPositioningEnabled() )
+ {
+ xAxisProp->getPropertyValue(C2U( "CrossoverPosition" )) >>= m_eCrossoverType;
+ if( ::com::sun::star::chart::ChartAxisPosition_VALUE == m_eCrossoverType )
+ {
+ double fValue = 0.0;
+ 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 )
+ m_pfMainLinePositionAtOtherAxis = new double(0.0);
+
+ xAxisProp->getPropertyValue(C2U( "LabelPosition" )) >>= m_eLabelPos;
+ xAxisProp->getPropertyValue(C2U( "MarkPosition" )) >>= m_eTickmarkPos;
+ }
+ else
+ {
+ m_eCrossoverType = ::com::sun::star::chart::ChartAxisPosition_START;
+ if( m_bIsMainAxis == m_bCrossingAxisHasReverseDirection )
+ m_eCrossoverType = ::com::sun::star::chart::ChartAxisPosition_END;
+ m_eLabelPos = ::com::sun::star::chart::ChartAxisLabelPosition_NEAR_AXIS;
+ m_eTickmarkPos = ::com::sun::star::chart::ChartAxisMarkPosition_AT_LABELS;
+ }
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+}
+
+void AxisProperties::init( bool bCartesian )
+{
+ uno::Reference< beans::XPropertySet > xProp =
+ uno::Reference<beans::XPropertySet>::query( this->m_xAxisModel );
+ if( !xProp.is() )
+ return;
+
+ if( m_nDimensionIndex<2 )
+ initAxisPositioning( xProp );
+
+ if( bCartesian )
+ {
+ if( ::com::sun::star::chart::ChartAxisPosition_END == m_eCrossoverType )
+ m_fInnerDirectionSign = m_bCrossingAxisHasReverseDirection ? 1 : -1;
+ else
+ m_fInnerDirectionSign = m_bCrossingAxisHasReverseDirection ? -1 : 1;
+
+ if( ::com::sun::star::chart::ChartAxisLabelPosition_NEAR_AXIS == m_eLabelPos )
+ m_fLabelDirectionSign = m_fInnerDirectionSign;
+ else if( ::com::sun::star::chart::ChartAxisLabelPosition_NEAR_AXIS_OTHER_SIDE == m_eLabelPos )
+ m_fLabelDirectionSign = -m_fInnerDirectionSign;
+ else if( ::com::sun::star::chart::ChartAxisLabelPosition_OUTSIDE_START == m_eLabelPos )
+ m_fLabelDirectionSign = m_bCrossingAxisHasReverseDirection ? -1 : 1;
+ else if( ::com::sun::star::chart::ChartAxisLabelPosition_OUTSIDE_END == m_eLabelPos )
+ m_fLabelDirectionSign = m_bCrossingAxisHasReverseDirection ? 1 : -1;
+
+ if( m_nDimensionIndex==2 )
+ m_aLabelAlignment = lcl_getLabelAlignmentForZAxis(*this);
+ else
+ {
+ bool bIsYAxisPosition = (m_nDimensionIndex==1 && !m_bSwapXAndY)
+ || (m_nDimensionIndex==0 && m_bSwapXAndY);
+ if( bIsYAxisPosition )
+ {
+ m_fLabelDirectionSign*=-1;
+ m_fInnerDirectionSign*=-1;
+ }
+
+ if( bIsYAxisPosition )
+ m_aLabelAlignment = lcl_getLabelAlignmentForYAxis(*this);
+ else
+ m_aLabelAlignment = lcl_getLabelAlignmentForXAxis(*this);
+ }
+ }
+
+ try
+ {
+ //init LineProperties
+ m_aLineProperties.initFromPropertySet( xProp );
+
+ //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;
+
+ sal_Int32 nMaxDepth = 0;
+ if(m_nMinorTickmarks!=0)
+ nMaxDepth=2;
+ else if(m_nMajorTickmarks!=0)
+ nMaxDepth=1;
+
+ this->m_aTickmarkPropertiesList.clear();
+ for( sal_Int32 nDepth=0; nDepth<nMaxDepth; nDepth++ )
+ {
+ TickmarkProperties aTickmarkProperties = this->makeTickmarkProperties( nDepth );
+ this->m_aTickmarkPropertiesList.push_back( aTickmarkProperties );
+ }
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+}
+
+//-----------------------------------------------------------------------------
+
+AxisLabelProperties::AxisLabelProperties()
+ : m_aFontReferenceSize( 8000, 7000 )
+ , m_aMaximumSpaceForLabels( 0 , 0, 8000, 7000 )
+ , nNumberFormatKey(0)
+ , eStaggering( SIDE_BY_SIDE )
+ , bLineBreakAllowed( false )
+ , bOverlapAllowed( false )
+ , bStackCharacters( false )
+ , fRotationAngleDegree( 0.0 )
+ , nRhythm( 1 )
+ , bRhythmIsFix(false)
+{
+ /*
+ aLocale.Language = C2U( "en" );
+ aLocale.Country = C2U( "US" );
+
+ //aLocale.Language = C2U( "ar" );
+ //aLocale.Country = C2U( "IR" );
+
+ //aLocale.Language = C2U( "ja" );
+ //aLocale.Country = C2U( "JP" );
+ */
+}
+
+void AxisLabelProperties::init( const uno::Reference< XAxis >& xAxisModel )
+{
+ uno::Reference< beans::XPropertySet > xProp =
+ uno::Reference<beans::XPropertySet>::query( xAxisModel );
+ if(xProp.is())
+ {
+ try
+ {
+ xProp->getPropertyValue( C2U( "TextBreak" ) ) >>= this->bLineBreakAllowed;
+ xProp->getPropertyValue( C2U( "TextOverlap" ) ) >>= this->bOverlapAllowed;
+ xProp->getPropertyValue( C2U( "StackCharacters" ) ) >>= this->bStackCharacters;
+ xProp->getPropertyValue( C2U( "TextRotation" ) ) >>= this->fRotationAngleDegree;
+
+ ::com::sun::star::chart::ChartAxisArrangeOrderType eArrangeOrder;
+ xProp->getPropertyValue( C2U( "ArrangeOrder" ) ) >>= eArrangeOrder;
+ switch(eArrangeOrder)
+ {
+ case ::com::sun::star::chart::ChartAxisArrangeOrderType_SIDE_BY_SIDE:
+ this->eStaggering = SIDE_BY_SIDE;
+ break;
+ case ::com::sun::star::chart::ChartAxisArrangeOrderType_STAGGER_EVEN:
+ this->eStaggering = STAGGER_EVEN;
+ break;
+ case ::com::sun::star::chart::ChartAxisArrangeOrderType_STAGGER_ODD:
+ this->eStaggering = STAGGER_ODD;
+ break;
+ default:
+ this->eStaggering = STAGGER_AUTO;
+ break;
+ }
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+ }
+}
+
+/*
+sal_Int16 getSwappedWritingMode( sal_Int16 nWritingMode )
+{
+ //LR_TB == LT
+ //RL_TB == RT (Arabic, Hebrew)
+ //TB_RL == TR (Japanese, Chinese, Korean)
+ // ?? TL (Mongolian) see also text::WritingMode2
+
+ switch(nWritingMode)
+ {
+ case text::WritingMode2::RL_TB:
+ return text::WritingMode2::TB_RL;
+ case text::WritingMode2::TB_RL:
+ return text::WritingMode2::RL_TB;
+ case text::WritingMode2::LR_TB:
+ return text::WritingMode2::TB_LR;
+ default:
+ return text::WritingMode2::LR_TB;
+ }
+}
+*/
+
+sal_Bool AxisLabelProperties::getIsStaggered() const
+{
+ if( STAGGER_ODD == eStaggering || STAGGER_EVEN == eStaggering )
+ return sal_True;
+ return sal_False;
+}
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
diff --git a/chart2/source/view/axes/VAxisProperties.hxx b/chart2/source/view/axes/VAxisProperties.hxx
new file mode 100644
index 000000000000..61f2477c7681
--- /dev/null
+++ b/chart2/source/view/axes/VAxisProperties.hxx
@@ -0,0 +1,171 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: VAxisProperties.hxx,v $
+ * $Revision: 1.7 $
+ *
+ * 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_VAXIS_PROPERTIES_HXX
+#define _CHART2_VAXIS_PROPERTIES_HXX
+
+#include "TickmarkProperties.hxx"
+#include "PlottingPositionHelper.hxx"
+#include "LabelAlignment.hxx"
+
+#include <com/sun/star/chart/ChartAxisLabelPosition.hpp>
+#include <com/sun/star/chart/ChartAxisMarkPosition.hpp>
+#include <com/sun/star/chart/ChartAxisPosition.hpp>
+#include <com/sun/star/chart2/XAxis.hpp>
+#include <com/sun/star/chart2/AxisType.hpp>
+#include <com/sun/star/chart2/data/XTextualDataSequence.hpp>
+#include <com/sun/star/awt/Rectangle.hpp>
+#include <com/sun/star/awt/Size.hpp>
+#include <com/sun/star/drawing/TextVerticalAdjust.hpp>
+#include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
+#include <com/sun/star/lang/Locale.hpp>
+
+#include <vector>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+
+//-----------------------------------------------------------------------------
+/**
+*/
+
+//These properties describe how a couple of labels are arranged one to another.
+//The couple can contain all labels for all tickmark depth or just the labels for one single depth or
+//the labels from an coherent range of tick depths (e.g. the major and first minor tickmarks should be handled together).
+//... only allow side by side for different tick depth
+enum AxisLabelStaggering
+{
+ SIDE_BY_SIDE
+ , STAGGER_EVEN
+ , STAGGER_ODD
+ , STAGGER_AUTO
+};
+
+struct AxisLabelProperties
+{
+ AxisLabelProperties();
+
+ ::com::sun::star::awt::Size m_aFontReferenceSize;//reference size to calculate the font height
+ ::com::sun::star::awt::Rectangle m_aMaximumSpaceForLabels;//Labels need to be clipped in order to fit into this rectangle
+
+ sal_Int32 nNumberFormatKey;
+
+ AxisLabelStaggering eStaggering;
+
+ sal_Bool bLineBreakAllowed;
+ sal_Bool bOverlapAllowed;
+
+ sal_Bool bStackCharacters;
+ double fRotationAngleDegree;
+
+ sal_Int32 nRhythm; //show only each nth label with n==nRhythm
+ bool bRhythmIsFix; //states wether the given rythm is fix or may be changed
+
+ //methods:
+ void init( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::chart2::XAxis >& xAxisModel );
+
+ sal_Bool getIsStaggered() const;
+};
+
+struct AxisProperties
+{
+ ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XAxis > m_xAxisModel;
+
+ sal_Int32 m_nDimensionIndex;
+ bool m_bIsMainAxis;//not secondary axis
+ bool m_bSwapXAndY;
+
+ ::com::sun::star::chart::ChartAxisPosition m_eCrossoverType;
+ ::com::sun::star::chart::ChartAxisLabelPosition m_eLabelPos;
+ ::com::sun::star::chart::ChartAxisMarkPosition m_eTickmarkPos;
+
+ double* m_pfMainLinePositionAtOtherAxis;
+ double* m_pfExrtaLinePositionAtOtherAxis;
+
+ 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;
+ //this direction is used to indicate in which direction inner tickmarks are to be drawn
+ double m_fInnerDirectionSign;
+ bool m_bLabelsOutside;
+ LabelAlignment m_aLabelAlignment;
+ sal_Bool m_bDisplayLabels;
+
+ sal_Int32 m_nNumberFormatKey;
+
+ /*
+ 0: no tickmarks 1: inner tickmarks
+ 2: outer tickmarks 3: inner and outer tickmarks
+ */
+ sal_Int32 m_nMajorTickmarks;
+ sal_Int32 m_nMinorTickmarks;
+ ::std::vector<TickmarkProperties> m_aTickmarkPropertiesList;
+
+ VLineProperties m_aLineProperties;
+
+ //for category axes ->
+ sal_Int32 m_nAxisType;//REALNUMBER, CATEGORY etc. type ::com::sun::star::chart2::AxisType
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::chart2::data::XTextualDataSequence >
+ m_xAxisTextProvider; //for categries or series names
+ //position of main tickmarks in respect to the indicated value: at value or between neighboured indicated values
+ bool m_bTickmarksAtIndicatedValue;
+ //<- category axes
+
+ //methods:
+
+ AxisProperties( const ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XAxis >& xAxisModel
+ , const ::com::sun::star::uno::Reference<
+ ::com::sun::star::chart2::data::XTextualDataSequence >& xAxisTextProvider );
+ AxisProperties( const AxisProperties& rAxisProperties );
+ virtual ~AxisProperties();
+ virtual void init(bool bCartesian=false);//init from model data (m_xAxisModel)
+
+ void initAxisPositioning( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& xAxisProp );
+
+ static TickmarkProperties getBiggestTickmarkProperties();
+
+private:
+ AxisProperties();
+
+protected:
+ virtual TickmarkProperties makeTickmarkProperties( sal_Int32 nDepth ) const;
+ VLineProperties makeLinePropertiesForDepth( sal_Int32 nDepth ) const;
+};
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
+#endif
diff --git a/chart2/source/view/axes/VCartesianAxis.cxx b/chart2/source/view/axes/VCartesianAxis.cxx
new file mode 100644
index 000000000000..0f18029254ef
--- /dev/null
+++ b/chart2/source/view/axes/VCartesianAxis.cxx
@@ -0,0 +1,1342 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: VCartesianAxis.cxx,v $
+ * $Revision: 1.12 $
+ *
+ * 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 <basegfx/numeric/ftools.hxx>
+
+#include "VCartesianAxis.hxx"
+#include "PlottingPositionHelper.hxx"
+#include "ShapeFactory.hxx"
+#include "CommonConverters.hxx"
+#include "macros.hxx"
+#include "ViewDefines.hxx"
+#include "PropertyMapper.hxx"
+#include "chartview/NumberFormatterWrapper.hxx"
+#include "LabelPositionHelper.hxx"
+#include "TrueGuard.hxx"
+#include "BaseGFXHelper.hxx"
+#include "AxisHelper.hxx"
+
+#include <rtl/math.hxx>
+#include <tools/color.hxx>
+#include <tools/debug.hxx>
+#include <com/sun/star/text/XText.hpp>
+#include <com/sun/star/text/WritingMode2.hpp>
+#include <svx/unoprnms.hxx>
+
+#include <algorithm>
+#include <memory>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+using namespace ::rtl::math;
+using ::com::sun::star::uno::Reference;
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+VCartesianAxis::VCartesianAxis( const AxisProperties& rAxisProperties
+ , const Reference< util::XNumberFormatsSupplier >& xNumberFormatsSupplier
+ , sal_Int32 nDimensionIndex, sal_Int32 nDimensionCount
+ , PlottingPositionHelper* pPosHelper )//takes ownership
+ : VAxisBase( nDimensionIndex, nDimensionCount, rAxisProperties, xNumberFormatsSupplier )
+{
+ if( pPosHelper )
+ m_pPosHelper = pPosHelper;
+ else
+ m_pPosHelper = new PlottingPositionHelper();
+}
+
+VCartesianAxis::~VCartesianAxis()
+{
+ delete m_pPosHelper;
+ m_pPosHelper = NULL;
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+Reference< drawing::XShape > createSingleLabel(
+ const Reference< lang::XMultiServiceFactory>& xShapeFactory
+ , const Reference< drawing::XShapes >& xTarget
+ , const awt::Point& rAnchorScreenPosition2D
+ , const rtl::OUString& rLabel
+ , const AxisLabelProperties& rAxisLabelProperties
+ , const AxisProperties& rAxisProperties
+ , const tNameSequence& rPropNames
+ , const tAnySequence& rPropValues
+ )
+{
+ if(!rLabel.getLength())
+ return 0;
+
+ // #i78696# use mathematically correct rotation now
+ const double fRotationAnglePi(rAxisLabelProperties.fRotationAngleDegree * (F_PI / -180.0));
+ uno::Any aATransformation = ShapeFactory::makeTransformation( rAnchorScreenPosition2D, fRotationAnglePi );
+ rtl::OUString aLabel = ShapeFactory::getStackedString( rLabel, rAxisLabelProperties.bStackCharacters );
+
+ Reference< drawing::XShape > xShape2DText = ShapeFactory(xShapeFactory)
+ .createText( xTarget, aLabel, rPropNames, rPropValues, aATransformation );
+
+ //correctPositionForRotation
+ LabelPositionHelper::correctPositionForRotation( xShape2DText
+ , rAxisProperties.m_aLabelAlignment, rAxisLabelProperties.fRotationAngleDegree, false );
+
+ return xShape2DText;
+}
+
+bool lcl_doesShapeOverlapWithTickmark( const Reference< drawing::XShape >& xShape
+ , double fRotationAngleDegree
+ , const basegfx::B2DVector& rTickScreenPosition
+ , TickmarkHelper_2D* pTickmarkHelper )
+{
+ if(!xShape.is())
+ return false;
+
+ ::basegfx::B2IRectangle aShapeRect = BaseGFXHelper::makeRectangle(xShape->getPosition(),ShapeFactory::getSizeAfterRotation( xShape, fRotationAngleDegree ));
+
+ if( pTickmarkHelper->isVerticalAxis() )
+ {
+ return ( (rTickScreenPosition.getY() >= aShapeRect.getMinY())
+ && (rTickScreenPosition.getY() <= aShapeRect.getMaxY()) );
+ }
+ if( pTickmarkHelper->isHorizontalAxis() )
+ {
+ return ( (rTickScreenPosition.getX() >= aShapeRect.getMinX())
+ && (rTickScreenPosition.getX() <= aShapeRect.getMaxX()) );
+ }
+
+ basegfx::B2IVector aPosition(
+ static_cast<sal_Int32>( rTickScreenPosition.getX() )
+ , static_cast<sal_Int32>( rTickScreenPosition.getY() ) );
+ return aShapeRect.isInside(aPosition);
+}
+
+bool doesOverlap( const Reference< drawing::XShape >& xShape1
+ , const Reference< drawing::XShape >& xShape2
+ , double fRotationAngleDegree )
+{
+ if( !xShape1.is() || !xShape2.is() )
+ return false;
+
+ ::basegfx::B2IRectangle aRect1( BaseGFXHelper::makeRectangle(xShape1->getPosition(),ShapeFactory::getSizeAfterRotation( xShape1, fRotationAngleDegree )));
+ ::basegfx::B2IRectangle aRect2( BaseGFXHelper::makeRectangle(xShape2->getPosition(),ShapeFactory::getSizeAfterRotation( xShape2, fRotationAngleDegree )));
+ return aRect1.overlaps(aRect2);
+}
+
+void removeShapesAtWrongRythm( TickIter& rIter
+ , sal_Int32 nCorrectRhythm
+ , sal_Int32 nMaxTickToCheck
+ , const Reference< drawing::XShapes >& xTarget )
+{
+ sal_Int32 nTick = 0;
+ for( TickInfo* pTickInfo = rIter.firstInfo()
+ ; pTickInfo && nTick <= nMaxTickToCheck
+ ; pTickInfo = rIter.nextInfo(), nTick++ )
+ {
+ //remove labels which does not fit into the rythm
+ if( nTick%nCorrectRhythm != 0)
+ {
+ if(pTickInfo->xTextShape.is())
+ {
+ xTarget->remove(pTickInfo->xTextShape);
+ pTickInfo->xTextShape = NULL;
+ }
+ }
+ }
+}
+
+class LabelIterator : private TickIter
+{
+ //this Iterator iterates over existing text labels
+
+ //if the labels are staggered and bInnerLine is true
+ //we iterate only through the labels which are lying more inside the diagram
+
+ //if the labels are staggered and bInnerLine is false
+ //we iterate only through the labels which are lying more outside the diagram
+
+ //if the labels are not staggered
+ //we iterate through all labels
+
+public:
+ LabelIterator( ::std::vector< ::std::vector< TickInfo > >& rTickInfos
+ , const ::com::sun::star::chart2::ExplicitIncrementData& rIncrement
+ , const AxisLabelStaggering eAxisLabelStaggering
+ , bool bInnerLine
+ , sal_Int32 nMinDepth=0, sal_Int32 nMaxDepth=-1 );
+
+ virtual TickInfo* firstInfo();
+ virtual TickInfo* nextInfo();
+
+private: //methods
+ LabelIterator();
+
+private: //member
+ const AxisLabelStaggering m_eAxisLabelStaggering;
+ bool m_bInnerLine;
+};
+
+LabelIterator::LabelIterator( ::std::vector< ::std::vector< TickInfo > >& rTickInfos
+ , const ::com::sun::star::chart2::ExplicitIncrementData& rIncrement
+ , const AxisLabelStaggering eAxisLabelStaggering
+ , bool bInnerLine
+ , sal_Int32 nMinDepth, sal_Int32 nMaxDepth )
+ : TickIter( rTickInfos, rIncrement, nMinDepth, nMaxDepth )
+ , m_eAxisLabelStaggering(eAxisLabelStaggering)
+ , m_bInnerLine(bInnerLine)
+{
+}
+
+TickInfo* LabelIterator::firstInfo()
+{
+ TickInfo* pTickInfo = TickIter::firstInfo();
+ while( pTickInfo && !pTickInfo->xTextShape.is() )
+ pTickInfo = TickIter::nextInfo();
+ if(!pTickInfo)
+ return NULL;
+ if( (STAGGER_EVEN==m_eAxisLabelStaggering && m_bInnerLine)
+ ||
+ (STAGGER_ODD==m_eAxisLabelStaggering && !m_bInnerLine)
+ )
+ {
+ //skip first label
+ do
+ pTickInfo = TickIter::nextInfo();
+ while( pTickInfo && !pTickInfo->xTextShape.is() );
+ }
+ if(!pTickInfo)
+ return NULL;
+ return pTickInfo;
+}
+
+TickInfo* LabelIterator::nextInfo()
+{
+ TickInfo* pTickInfo = NULL;
+ //get next label
+ do
+ pTickInfo = TickIter::nextInfo();
+ while( pTickInfo && !pTickInfo->xTextShape.is() );
+
+ if( STAGGER_EVEN==m_eAxisLabelStaggering
+ || STAGGER_ODD==m_eAxisLabelStaggering )
+ {
+ //skip one label
+ do
+ pTickInfo = TickIter::nextInfo();
+ while( pTickInfo && !pTickInfo->xTextShape.is() );
+ }
+ return pTickInfo;
+}
+
+B2DVector lcl_getStaggerDistance( LabelIterator& rIter, const B2DVector& rDistanceTickToText )
+{
+ //calculates the height or width of the first line of labels
+ //thus the second line of labels needs to be shifted for that distance
+
+ B2DVector aRet(0,0);
+
+ sal_Int32 nDistanceTickToText = static_cast<sal_Int32>( rDistanceTickToText.getLength() );
+ if( nDistanceTickToText==0.0)
+ return aRet;
+
+ B2DVector aStaggerDirection(rDistanceTickToText);
+ aStaggerDirection.normalize();
+
+ sal_Int32 nDistance=0;
+ Reference< drawing::XShape > xShape2DText(NULL);
+ for( TickInfo* pTickInfo = rIter.firstInfo()
+ ; pTickInfo
+ ; pTickInfo = rIter.nextInfo() )
+ {
+ xShape2DText = pTickInfo->xTextShape;
+ DBG_ASSERT(xShape2DText.is(),"LabelIterator does not work correctly");
+
+ awt::Size aSize = xShape2DText->getSize();
+ if(fabs(aStaggerDirection.getX())>fabs(aStaggerDirection.getY()))
+ nDistance = ::std::max(nDistance,aSize.Width);
+ else
+ nDistance = ::std::max(nDistance,aSize.Height);
+ }
+
+ aRet = aStaggerDirection*nDistance;
+
+ //add extra distance for vertical distance
+ if(fabs(aStaggerDirection.getX())>fabs(aStaggerDirection.getY()))
+ aRet += rDistanceTickToText;
+
+ return aRet;
+}
+
+void lcl_correctPositionForStaggering( LabelIterator& rIter, const B2DVector& rStaggerDistance )
+{
+ if(rStaggerDistance.getLength()==0.0)
+ return;
+ Reference< drawing::XShape > xShape2DText(NULL);
+ for( TickInfo* pTickInfo = rIter.firstInfo()
+ ; pTickInfo
+ ; pTickInfo = rIter.nextInfo() )
+ {
+ xShape2DText = pTickInfo->xTextShape;
+ DBG_ASSERT(xShape2DText.is(),"LabelIterator does not work correctly");
+
+ awt::Point aPos = xShape2DText->getPosition();
+ aPos.X += static_cast<sal_Int32>(rStaggerDistance.getX());
+ aPos.Y += static_cast<sal_Int32>(rStaggerDistance.getY());
+ xShape2DText->setPosition( aPos );
+ }
+}
+
+class MaxLabelTickIter : public TickIter
+{
+ //iterate over first two and last two labels and the longest label
+public:
+ MaxLabelTickIter( ::std::vector< ::std::vector< TickInfo > >& rTickInfos
+ , const ::com::sun::star::chart2::ExplicitIncrementData& rIncrement
+ , sal_Int32 nLongestLabelIndex );
+ virtual ~MaxLabelTickIter();
+
+ virtual TickInfo* nextInfo();
+
+private:
+ sal_Int32 m_nLongestLabelIndex;
+};
+
+MaxLabelTickIter::MaxLabelTickIter( ::std::vector< ::std::vector< TickInfo > >& rTickInfos
+ , const ::com::sun::star::chart2::ExplicitIncrementData& rIncrement
+ , sal_Int32 nLongestLabelIndex )
+ : TickIter( rTickInfos, rIncrement, 0//nMinDepth
+ , 0//nMaxDepth
+ )
+ , m_nLongestLabelIndex( nLongestLabelIndex )
+{
+ 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;
+}
+MaxLabelTickIter::~MaxLabelTickIter()
+{
+}
+
+TickInfo* MaxLabelTickIter::nextInfo()
+{
+ 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 );
+ }
+ }
+
+ return TickIter::nextInfo();
+}
+
+bool VCartesianAxis::isBreakOfLabelsAllowed( const AxisLabelProperties& rAxisLabelProperties
+ , TickmarkHelper_2D* pTickmarkHelper )
+{
+ if( m_aTextLabels.getLength() > 100 )
+ return false;
+ if( !rAxisLabelProperties.bLineBreakAllowed )
+ return false;
+ if( rAxisLabelProperties.bStackCharacters )
+ return false;
+ //no break for value axis
+ if( !m_bUseTextLabels )
+ return false;
+ if( !::rtl::math::approxEqual( rAxisLabelProperties.fRotationAngleDegree, 0.0 ) )
+ return false;
+ //break only for horizontal axis
+ if( pTickmarkHelper )
+ return pTickmarkHelper->isHorizontalAxis();
+ return false;
+}
+
+bool VCartesianAxis::isAutoStaggeringOfLabelsAllowed( const AxisLabelProperties& rAxisLabelProperties
+ , TickmarkHelper_2D* pTickmarkHelper )
+{
+ if( rAxisLabelProperties.eStaggering != STAGGER_AUTO )
+ return false;
+ if( rAxisLabelProperties.bOverlapAllowed )
+ return false;
+ if( rAxisLabelProperties.bLineBreakAllowed ) //auto line break or auto staggering, doing both automatisms they may conflict...
+ return false;
+ if( !::rtl::math::approxEqual( rAxisLabelProperties.fRotationAngleDegree, 0.0 ) )
+ return false;
+ //automatic staggering only for horizontal axis with horizontal text
+ //or vertical axis with vertical text
+ if( pTickmarkHelper )
+ {
+ if( pTickmarkHelper->isHorizontalAxis() )
+ return !rAxisLabelProperties.bStackCharacters;
+ if( pTickmarkHelper->isVerticalAxis() )
+ return rAxisLabelProperties.bStackCharacters;
+ }
+ return false;
+}
+
+bool VCartesianAxis::createTextShapes(
+ const Reference< drawing::XShapes >& xTarget
+ , TickIter& rTickIter
+ , AxisLabelProperties& rAxisLabelProperties
+ , TickmarkHelper_2D* pTickmarkHelper )
+{
+ //returns true if the text shapes have been created succesfully
+ //otherwise false - in this case the AxisLabelProperties have changed
+ //and contain new instructions for the next try for text shape creation
+
+ uno::Sequence< rtl::OUString >* pCategories = m_bUseTextLabels? &m_aTextLabels : 0;
+
+ Reference< XScaling > xInverseScaling( NULL );
+ if( m_aScale.Scaling.is() )
+ xInverseScaling = m_aScale.Scaling->getInverseScaling();
+
+ FixedNumberFormatter aFixedNumberFormatter(
+ m_xNumberFormatsSupplier, rAxisLabelProperties.nNumberFormatKey );
+
+ B2DVector aTextToTickDistance( pTickmarkHelper->getDistanceAxisTickToText( m_aAxisProperties ) );
+
+ TickInfo* pPreviousVisibleTickInfo = NULL;
+ TickInfo* pPREPreviousVisibleTickInfo = NULL;
+ TickInfo* pLastVisibleNeighbourTickInfo = NULL;
+ bool bIsStaggered = rAxisLabelProperties.getIsStaggered();
+ sal_Int32 nLimitedSpace = -1;
+ if( isBreakOfLabelsAllowed( rAxisLabelProperties, pTickmarkHelper ) )
+ {
+ nLimitedSpace = TickmarkHelper_2D::getTickScreenDistance( rTickIter );
+ if( bIsStaggered )
+ nLimitedSpace *= 2;
+
+ if( nLimitedSpace > 0 )
+ { //reduce space for a small amount to have a visible distance between the labels:
+ sal_Int32 nReduce = (nLimitedSpace*5)/100;
+ if(!nReduce)
+ nReduce = 1;
+ nLimitedSpace -= nReduce;
+ }
+ //maybe @todo in future:
+ //if the labeled tickmarks are not equidistant [this is not considered to be a relevant case so far]
+ //the limited space maybe needs to be calculated for each tickmark seperatly
+ //or the staggering could be ignored in that case
+ }
+
+ //------------------------------------------------
+ //prepare properties for multipropertyset-interface of shape
+ tNameSequence aPropNames;
+ tAnySequence aPropValues;
+
+ Reference< beans::XPropertySet > xProps( m_aAxisProperties.m_xAxisModel, uno::UNO_QUERY );
+ PropertyMapper::getTextLabelMultiPropertyLists( xProps, aPropNames, aPropValues, false
+ , nLimitedSpace, fabs(aTextToTickDistance.getX()) > fabs(aTextToTickDistance.getY()) );
+ LabelPositionHelper::doDynamicFontResize( aPropValues, aPropNames, xProps
+ , m_aAxisLabelProperties.m_aFontReferenceSize );
+ LabelPositionHelper::changeTextAdjustment( aPropValues, aPropNames, m_aAxisProperties.m_aLabelAlignment );
+
+ uno::Any* pColorAny = PropertyMapper::getValuePointer(aPropValues,aPropNames,C2U("CharColor"));
+ sal_Int32 nColor = Color( COL_AUTO ).GetColor();
+ if(pColorAny)
+ *pColorAny >>= nColor;
+ //------------------------------------------------
+
+ sal_Int32 nTick = 0;
+ for( TickInfo* pTickInfo = rTickIter.firstInfo()
+ ; pTickInfo
+ ; pTickInfo = rTickIter.nextInfo(), nTick++ )
+ {
+ pLastVisibleNeighbourTickInfo = bIsStaggered ?
+ pPREPreviousVisibleTickInfo : pPreviousVisibleTickInfo;
+
+ //don't create labels which does not fit into the rythm
+ if( nTick%rAxisLabelProperties.nRhythm != 0)
+ continue;
+
+ //don't create labels for invisible ticks
+ if( !pTickInfo->bPaintIt )
+ continue;
+
+ //if NO OVERLAP -> don't create labels where the tick overlaps
+ //with the text of the last neighbour tickmark
+ if( pLastVisibleNeighbourTickInfo && !rAxisLabelProperties.bOverlapAllowed )
+ {
+ if( lcl_doesShapeOverlapWithTickmark( pLastVisibleNeighbourTickInfo->xTextShape
+ , rAxisLabelProperties.fRotationAngleDegree
+ , pTickInfo->aTickScreenPosition, pTickmarkHelper ) )
+ {
+ bool bOverlapAlsoAfterSwitchingOnAutoStaggering = true;
+ if( !bIsStaggered && isAutoStaggeringOfLabelsAllowed( rAxisLabelProperties, pTickmarkHelper ) )
+ {
+ bIsStaggered = true;
+ rAxisLabelProperties.eStaggering = STAGGER_EVEN;
+ pLastVisibleNeighbourTickInfo = pPREPreviousVisibleTickInfo;
+ if( !pLastVisibleNeighbourTickInfo ||
+ !lcl_doesShapeOverlapWithTickmark( pLastVisibleNeighbourTickInfo->xTextShape
+ , rAxisLabelProperties.fRotationAngleDegree
+ , pTickInfo->aTickScreenPosition, pTickmarkHelper ) )
+ bOverlapAlsoAfterSwitchingOnAutoStaggering = false;
+ }
+ if( bOverlapAlsoAfterSwitchingOnAutoStaggering )
+ {
+ if( rAxisLabelProperties.bRhythmIsFix )
+ continue;
+ rAxisLabelProperties.nRhythm++;
+ TickIter aRemoveIter( m_aAllTickInfos, m_aIncrement, 0, 0 );
+ removeShapesAtWrongRythm( aRemoveIter, rAxisLabelProperties.nRhythm, nTick, xTarget );
+ return false;
+ }
+ }
+ }
+
+ pTickInfo->updateUnscaledValue( xInverseScaling );
+
+ bool bHasExtraColor=false;
+ sal_Int32 nExtraColor=0;
+
+ 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
+ if( nIndex>=0 && nIndex<pCategories->getLength() )
+ aLabel = (*pCategories)[nIndex];
+ }
+ else
+ aLabel = aFixedNumberFormatter.getFormattedString( pTickInfo->fUnscaledTickValue, nExtraColor, bHasExtraColor );
+
+ if(pColorAny)
+ *pColorAny = uno::makeAny(bHasExtraColor?nExtraColor:nColor);
+
+ B2DVector aTickScreenPos2D( pTickInfo->aTickScreenPosition );
+ aTickScreenPos2D += aTextToTickDistance;
+ awt::Point aAnchorScreenPosition2D(
+ static_cast<sal_Int32>(aTickScreenPos2D.getX())
+ ,static_cast<sal_Int32>(aTickScreenPos2D.getY()));
+
+ //create single label
+ if(!pTickInfo->xTextShape.is())
+ pTickInfo->xTextShape = createSingleLabel( m_xShapeFactory, xTarget
+ , aAnchorScreenPosition2D, aLabel
+ , rAxisLabelProperties, m_aAxisProperties
+ , aPropNames, aPropValues );
+ if(!pTickInfo->xTextShape.is())
+ continue;
+
+ recordMaximumTextSize( pTickInfo->xTextShape, rAxisLabelProperties.fRotationAngleDegree );
+
+ //if NO OVERLAP -> remove overlapping shapes
+ if( pLastVisibleNeighbourTickInfo && !rAxisLabelProperties.bOverlapAllowed )
+ {
+ if( doesOverlap( pLastVisibleNeighbourTickInfo->xTextShape, pTickInfo->xTextShape, m_aAxisLabelProperties.fRotationAngleDegree ) )
+ {
+ bool bOverlapAlsoAfterSwitchingOnAutoStaggering = true;
+ if( !bIsStaggered && isAutoStaggeringOfLabelsAllowed( rAxisLabelProperties, pTickmarkHelper ) )
+ {
+ bIsStaggered = true;
+ rAxisLabelProperties.eStaggering = STAGGER_EVEN;
+ pLastVisibleNeighbourTickInfo = pPREPreviousVisibleTickInfo;
+ if( !pLastVisibleNeighbourTickInfo ||
+ !lcl_doesShapeOverlapWithTickmark( pLastVisibleNeighbourTickInfo->xTextShape
+ , rAxisLabelProperties.fRotationAngleDegree
+ , pTickInfo->aTickScreenPosition, pTickmarkHelper ) )
+ bOverlapAlsoAfterSwitchingOnAutoStaggering = false;
+ }
+ if( bOverlapAlsoAfterSwitchingOnAutoStaggering )
+ {
+ if( rAxisLabelProperties.bRhythmIsFix )
+ {
+ xTarget->remove(pTickInfo->xTextShape);
+ pTickInfo->xTextShape = NULL;
+ continue;
+ }
+ rAxisLabelProperties.nRhythm++;
+ TickIter aRemoveIter( m_aAllTickInfos, m_aIncrement, 0, 0 );
+ removeShapesAtWrongRythm( aRemoveIter, rAxisLabelProperties.nRhythm, nTick, xTarget );
+ return false;
+ }
+ }
+ }
+
+ pPREPreviousVisibleTickInfo = pPreviousVisibleTickInfo;
+ pPreviousVisibleTickInfo = pTickInfo;
+ }
+ return true;
+}
+
+drawing::PointSequenceSequence lcl_makePointSequence( B2DVector& rStart, B2DVector& rEnd )
+{
+ drawing::PointSequenceSequence aPoints(1);
+ aPoints[0].realloc(2);
+ aPoints[0][0].X = static_cast<sal_Int32>(rStart.getX());
+ aPoints[0][0].Y = static_cast<sal_Int32>(rStart.getY());
+ aPoints[0][1].X = static_cast<sal_Int32>(rEnd.getX());
+ aPoints[0][1].Y = static_cast<sal_Int32>(rEnd.getY());
+ return aPoints;
+}
+
+double VCartesianAxis::getLogicValueWhereMainLineCrossesOtherAxis() const
+{
+ double fMin = (m_nDimensionIndex==1) ? m_pPosHelper->getLogicMinX() : m_pPosHelper->getLogicMinY();
+ double fMax = (m_nDimensionIndex==1) ? m_pPosHelper->getLogicMaxX() : m_pPosHelper->getLogicMaxY();
+
+ double fCrossesOtherAxis;
+ if(m_aAxisProperties.m_pfMainLinePositionAtOtherAxis)
+ fCrossesOtherAxis = *m_aAxisProperties.m_pfMainLinePositionAtOtherAxis;
+ else
+ {
+ if( ::com::sun::star::chart::ChartAxisPosition_END == m_aAxisProperties.m_eCrossoverType )
+ fCrossesOtherAxis = fMax;
+ else
+ fCrossesOtherAxis = fMin;
+ }
+ return fCrossesOtherAxis;
+}
+
+double VCartesianAxis::getLogicValueWhereLabelLineCrossesOtherAxis() const
+{
+ double fMin = (m_nDimensionIndex==1) ? m_pPosHelper->getLogicMinX() : m_pPosHelper->getLogicMinY();
+ double fMax = (m_nDimensionIndex==1) ? m_pPosHelper->getLogicMaxX() : m_pPosHelper->getLogicMaxY();
+
+ double fCrossesOtherAxis;
+ if( ::com::sun::star::chart::ChartAxisLabelPosition_OUTSIDE_START == m_aAxisProperties.m_eLabelPos )
+ fCrossesOtherAxis = fMin;
+ else if( ::com::sun::star::chart::ChartAxisLabelPosition_OUTSIDE_END == m_aAxisProperties.m_eLabelPos )
+ fCrossesOtherAxis = fMax;
+ else
+ fCrossesOtherAxis = getLogicValueWhereMainLineCrossesOtherAxis();
+ return fCrossesOtherAxis;
+}
+
+bool VCartesianAxis::getLogicValueWhereExtraLineCrossesOtherAxis( double& fCrossesOtherAxis ) const
+{
+ if( !m_aAxisProperties.m_pfExrtaLinePositionAtOtherAxis )
+ return false;
+ double fMin = (m_nDimensionIndex==1) ? m_pPosHelper->getLogicMinX() : m_pPosHelper->getLogicMinY();
+ double fMax = (m_nDimensionIndex==1) ? m_pPosHelper->getLogicMaxX() : m_pPosHelper->getLogicMaxY();
+ if( *m_aAxisProperties.m_pfExrtaLinePositionAtOtherAxis <= fMin
+ || *m_aAxisProperties.m_pfExrtaLinePositionAtOtherAxis >= fMax )
+ return false;
+ fCrossesOtherAxis = *m_aAxisProperties.m_pfExrtaLinePositionAtOtherAxis;
+ return true;
+}
+
+B2DVector VCartesianAxis::getScreenPosition( double fLogicX, double fLogicY, double fLogicZ ) const
+{
+ B2DVector aRet(0,0);
+
+ if( m_pPosHelper )
+ {
+ drawing::Position3D aScenePos = m_pPosHelper->transformLogicToScene( fLogicX, fLogicY, fLogicZ, true );
+ if(3==m_nDimension)
+ {
+ if( m_xLogicTarget.is() && m_pPosHelper && m_pShapeFactory )
+ {
+ tPropertyNameMap aDummyPropertyNameMap;
+ Reference< drawing::XShape > xShape3DAnchor = m_pShapeFactory->createCube( m_xLogicTarget
+ , aScenePos,drawing::Direction3D(1,1,1), 0, 0, aDummyPropertyNameMap);
+ awt::Point a2DPos = xShape3DAnchor->getPosition(); //get 2D position from xShape3DAnchor
+ m_xLogicTarget->remove(xShape3DAnchor);
+ aRet.setX( a2DPos.X );
+ aRet.setY( a2DPos.Y );
+ }
+ else
+ {
+ DBG_ERROR("cannot calculate scrren position in VCartesianAxis::getScreenPosition");
+ }
+ }
+ else
+ {
+ aRet.setX( aScenePos.PositionX );
+ aRet.setY( aScenePos.PositionY );
+ }
+ }
+
+ return aRet;
+}
+
+VCartesianAxis::ScreenPosAndLogicPos VCartesianAxis::getScreenPosAndLogicPos( double fLogicX_, double fLogicY_, double fLogicZ_ ) const
+{
+ ScreenPosAndLogicPos aRet;
+ aRet.fLogicX = fLogicX_;
+ aRet.fLogicY = fLogicY_;
+ aRet.fLogicZ = fLogicZ_;
+ aRet.aScreenPos = getScreenPosition( fLogicX_, fLogicY_, fLogicZ_ );
+ return aRet;
+}
+
+typedef ::std::vector< VCartesianAxis::ScreenPosAndLogicPos > tScreenPosAndLogicPosList;
+struct lcl_LessXPos : ::std::binary_function< VCartesianAxis::ScreenPosAndLogicPos, VCartesianAxis::ScreenPosAndLogicPos, bool >
+{
+ inline bool operator() ( const VCartesianAxis::ScreenPosAndLogicPos& rPos1, const VCartesianAxis::ScreenPosAndLogicPos& rPos2 )
+ {
+ return ( rPos1.aScreenPos.getX() < rPos2.aScreenPos.getX() );
+ }
+};
+
+struct lcl_GreaterYPos : ::std::binary_function< VCartesianAxis::ScreenPosAndLogicPos, VCartesianAxis::ScreenPosAndLogicPos, bool >
+{
+ inline bool operator() ( const VCartesianAxis::ScreenPosAndLogicPos& rPos1, const VCartesianAxis::ScreenPosAndLogicPos& rPos2 )
+ {
+ return ( rPos1.aScreenPos.getY() > rPos2.aScreenPos.getY() );
+ }
+};
+
+void VCartesianAxis::get2DAxisMainLine( B2DVector& rStart, B2DVector& rEnd, double fCrossesOtherAxis )
+{
+ //m_aAxisProperties might get updated and changed here because
+ // the label alignmant and inner direction sign depends exactly of the choice of the axis line position which is made here in this method
+
+ double fMinX = m_pPosHelper->getLogicMinX();
+ double fMinY = m_pPosHelper->getLogicMinY();
+ double fMinZ = m_pPosHelper->getLogicMinZ();
+ double fMaxX = m_pPosHelper->getLogicMaxX();
+ double fMaxY = m_pPosHelper->getLogicMaxY();
+ double fMaxZ = m_pPosHelper->getLogicMaxZ();
+
+ double fXStart = fMinX;
+ double fYStart = fMinY;
+ double fZStart = fMinZ;
+ double fXEnd = fXStart;
+ double fYEnd = fYStart;
+ double fZEnd = fZStart;
+
+ double fXOnXPlane = fMinX;
+ double fXOther = fMaxX;
+ int nDifferentValue = !m_pPosHelper->isMathematicalOrientationX() ? -1 : 1;
+ if( !m_pPosHelper->isSwapXAndY() )
+ nDifferentValue *= (CuboidPlanePosition_Left != m_eLeftWallPos) ? -1 : 1;
+ else
+ nDifferentValue *= (CuboidPlanePosition_Bottom != m_eBottomPos) ? -1 : 1;
+ if( nDifferentValue<0 )
+ {
+ fXOnXPlane = fMaxX;
+ fXOther = fMinX;
+ }
+
+ double fYOnYPlane = fMinY;
+ double fYOther = fMaxY;
+ nDifferentValue = !m_pPosHelper->isMathematicalOrientationY() ? -1 : 1;
+ if( !m_pPosHelper->isSwapXAndY() )
+ nDifferentValue *= (CuboidPlanePosition_Bottom != m_eBottomPos) ? -1 : 1;
+ else
+ nDifferentValue *= (CuboidPlanePosition_Left != m_eLeftWallPos) ? -1 : 1;
+ if( nDifferentValue<0 )
+ {
+ fYOnYPlane = fMaxY;
+ fYOther = fMinY;
+ }
+
+ double fZOnZPlane = fMaxZ;
+ double fZOther = fMinZ;
+ nDifferentValue = !m_pPosHelper->isMathematicalOrientationZ() ? -1 : 1;
+ nDifferentValue *= (CuboidPlanePosition_Back != m_eBackWallPos) ? -1 : 1;
+ if( nDifferentValue<0 )
+ {
+ fZOnZPlane = fMinZ;
+ fZOther = fMaxZ;
+ }
+
+ if( 0==m_nDimensionIndex ) //x-axis
+ {
+ if( fCrossesOtherAxis < fMinY )
+ fCrossesOtherAxis = fMinY;
+ else if( fCrossesOtherAxis > fMaxY )
+ fCrossesOtherAxis = fMaxY;
+
+ fYStart = fYEnd = fCrossesOtherAxis;
+ fXEnd=m_pPosHelper->getLogicMaxX();
+
+ if(3==m_nDimension)
+ {
+ if( AxisHelper::isAxisPositioningEnabled() )
+ {
+ if( ::rtl::math::approxEqual( fYOther, fYStart) )
+ fZStart = fZEnd = fZOnZPlane;
+ else
+ fZStart = fZEnd = fZOther;
+ }
+ else
+ {
+ rStart = getScreenPosition( fXStart, fYStart, fZStart );
+ rEnd = getScreenPosition( fXEnd, fYEnd, fZEnd );
+
+ double fDeltaX = rEnd.getX() - rStart.getX();
+ double fDeltaY = rEnd.getY() - rStart.getY();
+
+ //only those points are candidates which are lying on exactly one wall as these are outer edges
+ tScreenPosAndLogicPosList aPosList;
+ aPosList.push_back( getScreenPosAndLogicPos( fMinX, fYOnYPlane, fZOther ) );
+ aPosList.push_back( getScreenPosAndLogicPos( fMinX, fYOther, fZOnZPlane ) );
+
+ if( fabs(fDeltaY) > fabs(fDeltaX) )
+ {
+ m_aAxisProperties.m_aLabelAlignment = LABEL_ALIGN_LEFT;
+ //choose most left positions
+ ::std::sort( aPosList.begin(), aPosList.end(), lcl_LessXPos() );
+ m_aAxisProperties.m_fLabelDirectionSign = fDeltaY<0 ? -1 : 1;
+ }
+ else
+ {
+ m_aAxisProperties.m_aLabelAlignment = LABEL_ALIGN_BOTTOM;
+ //choose most bottom positions
+ ::std::sort( aPosList.begin(), aPosList.end(), lcl_GreaterYPos() );
+ m_aAxisProperties.m_fLabelDirectionSign = fDeltaX<0 ? -1 : 1;
+ }
+ ScreenPosAndLogicPos aBestPos( aPosList[0] );
+ fYStart = fYEnd = aBestPos.fLogicY;
+ fZStart = fZEnd = aBestPos.fLogicZ;
+ if( !m_pPosHelper->isMathematicalOrientationX() )
+ m_aAxisProperties.m_fLabelDirectionSign *= -1;
+ }
+ }//end 3D x axis
+ }
+ else if( 1==m_nDimensionIndex ) //y-axis
+ {
+ if( fCrossesOtherAxis < fMinX )
+ fCrossesOtherAxis = fMinX;
+ else if( fCrossesOtherAxis > fMaxX )
+ fCrossesOtherAxis = fMaxX;
+
+ fXStart = fXEnd = fCrossesOtherAxis;
+ fYEnd=m_pPosHelper->getLogicMaxY();
+
+ if(3==m_nDimension)
+ {
+ if( AxisHelper::isAxisPositioningEnabled() )
+ {
+ if( ::rtl::math::approxEqual( fXOther, fXStart) )
+ fZStart = fZEnd = fZOnZPlane;
+ else
+ fZStart = fZEnd = fZOther;
+ }
+ else
+ {
+ rStart = getScreenPosition( fXStart, fYStart, fZStart );
+ rEnd = getScreenPosition( fXEnd, fYEnd, fZEnd );
+
+ double fDeltaX = rEnd.getX() - rStart.getX();
+ double fDeltaY = rEnd.getY() - rStart.getY();
+
+ //only those points are candidates which are lying on exactly one wall as these are outer edges
+ tScreenPosAndLogicPosList aPosList;
+ aPosList.push_back( getScreenPosAndLogicPos( fXOnXPlane, fMinY, fZOther ) );
+ aPosList.push_back( getScreenPosAndLogicPos( fXOther, fMinY, fZOnZPlane ) );
+
+ if( fabs(fDeltaY) > fabs(fDeltaX) )
+ {
+ m_aAxisProperties.m_aLabelAlignment = LABEL_ALIGN_LEFT;
+ //choose most left positions
+ ::std::sort( aPosList.begin(), aPosList.end(), lcl_LessXPos() );
+ m_aAxisProperties.m_fLabelDirectionSign = fDeltaY<0 ? -1 : 1;
+ }
+ else
+ {
+ m_aAxisProperties.m_aLabelAlignment = LABEL_ALIGN_BOTTOM;
+ //choose most bottom positions
+ ::std::sort( aPosList.begin(), aPosList.end(), lcl_GreaterYPos() );
+ m_aAxisProperties.m_fLabelDirectionSign = fDeltaX<0 ? -1 : 1;
+ }
+ ScreenPosAndLogicPos aBestPos( aPosList[0] );
+ fXStart = fXEnd = aBestPos.fLogicX;
+ fZStart = fZEnd = aBestPos.fLogicZ;
+ if( !m_pPosHelper->isMathematicalOrientationY() )
+ m_aAxisProperties.m_fLabelDirectionSign *= -1;
+ }
+ }//end 3D y axis
+ }
+ else //z-axis
+ {
+ fZEnd = m_pPosHelper->getLogicMaxZ();
+ if( AxisHelper::isAxisPositioningEnabled() )
+ {
+ if( !m_aAxisProperties.m_bSwapXAndY )
+ {
+ if( fCrossesOtherAxis < fMinY )
+ fCrossesOtherAxis = fMinY;
+ else if( fCrossesOtherAxis > fMaxY )
+ fCrossesOtherAxis = fMaxY;
+ fYStart = fYEnd = fCrossesOtherAxis;
+
+ if( ::rtl::math::approxEqual( fYOther, fYStart) )
+ fXStart = fXEnd = fXOnXPlane;
+ else
+ fXStart = fXEnd = fXOther;
+ }
+ else
+ {
+ if( fCrossesOtherAxis < fMinX )
+ fCrossesOtherAxis = fMinX;
+ else if( fCrossesOtherAxis > fMaxX )
+ fCrossesOtherAxis = fMaxX;
+ fXStart = fXEnd = fCrossesOtherAxis;
+
+ if( ::rtl::math::approxEqual( fXOther, fXStart) )
+ fYStart = fYEnd = fYOnYPlane;
+ else
+ fYStart = fYEnd = fYOther;
+ }
+ }
+ else
+ {
+ if( !m_pPosHelper->isSwapXAndY() )
+ {
+ fXStart = fXEnd = m_pPosHelper->isMathematicalOrientationX() ? m_pPosHelper->getLogicMaxX() : m_pPosHelper->getLogicMinX();
+ fYStart = fYEnd = m_pPosHelper->isMathematicalOrientationY() ? m_pPosHelper->getLogicMinY() : m_pPosHelper->getLogicMaxY();
+ }
+ else
+ {
+ fXStart = fXEnd = m_pPosHelper->isMathematicalOrientationX() ? m_pPosHelper->getLogicMinX() : m_pPosHelper->getLogicMaxX();
+ fYStart = fYEnd = m_pPosHelper->isMathematicalOrientationY() ? m_pPosHelper->getLogicMaxY() : m_pPosHelper->getLogicMinY();
+ }
+
+ if(3==m_nDimension)
+ {
+ rStart = getScreenPosition( fXStart, fYStart, fZStart );
+ rEnd = getScreenPosition( fXEnd, fYEnd, fZEnd );
+
+ double fDeltaX = rEnd.getX() - rStart.getX();
+
+ //only those points are candidates which are lying on exactly one wall as these are outer edges
+ tScreenPosAndLogicPosList aPosList;
+ aPosList.push_back( getScreenPosAndLogicPos( fXOther, fYOnYPlane, fMinZ ) );
+ aPosList.push_back( getScreenPosAndLogicPos( fXOnXPlane, fYOther, fMinZ ) );
+
+ ::std::sort( aPosList.begin(), aPosList.end(), lcl_GreaterYPos() );
+ ScreenPosAndLogicPos aBestPos( aPosList[0] );
+ ScreenPosAndLogicPos aNotSoGoodPos( aPosList[1] );
+
+ //choose most bottom positions
+ if( !::rtl::math::approxEqual( fDeltaX, 0.0 ) ) // prefere left-right algnments
+ {
+ if( aBestPos.aScreenPos.getX() > aNotSoGoodPos.aScreenPos.getX() )
+ m_aAxisProperties.m_aLabelAlignment = LABEL_ALIGN_RIGHT;
+ else
+ m_aAxisProperties.m_aLabelAlignment = LABEL_ALIGN_LEFT;
+ }
+ else
+ {
+ if( aBestPos.aScreenPos.getY() > aNotSoGoodPos.aScreenPos.getY() )
+ m_aAxisProperties.m_aLabelAlignment = LABEL_ALIGN_BOTTOM;
+ else
+ m_aAxisProperties.m_aLabelAlignment = LABEL_ALIGN_TOP;
+ }
+
+ m_aAxisProperties.m_fLabelDirectionSign = fDeltaX<0 ? -1 : 1;
+ if( !m_pPosHelper->isMathematicalOrientationZ() )
+ m_aAxisProperties.m_fLabelDirectionSign *= -1;
+
+ fXStart = fXEnd = aBestPos.fLogicX;
+ fYStart = fYEnd = aBestPos.fLogicY;
+ }
+ }//end 3D z axis
+ }
+
+ rStart = getScreenPosition( fXStart, fYStart, fZStart );
+ rEnd = getScreenPosition( fXEnd, fYEnd, fZEnd );
+
+ if(3==m_nDimension && !AxisHelper::isAxisPositioningEnabled() )
+ m_aAxisProperties.m_fInnerDirectionSign = m_aAxisProperties.m_fLabelDirectionSign;//to behave like before
+
+ if(3==m_nDimension && AxisHelper::isAxisPositioningEnabled() )
+ {
+ double fDeltaX = rEnd.getX() - rStart.getX();
+ double fDeltaY = rEnd.getY() - rStart.getY();
+
+ if( 2==m_nDimensionIndex )
+ {
+ if( m_eLeftWallPos != CuboidPlanePosition_Left )
+ {
+ m_aAxisProperties.m_fLabelDirectionSign *= -1.0;
+ m_aAxisProperties.m_fInnerDirectionSign *= -1.0;
+ }
+
+ m_aAxisProperties.m_aLabelAlignment =
+ ( m_aAxisProperties.m_fLabelDirectionSign<0 ) ?
+ LABEL_ALIGN_LEFT : LABEL_ALIGN_RIGHT;
+
+ if( ( fDeltaY<0 && m_aScale.Orientation == AxisOrientation_REVERSE ) ||
+ ( fDeltaY>0 && m_aScale.Orientation == AxisOrientation_MATHEMATICAL ) )
+ m_aAxisProperties.m_aLabelAlignment =
+ ( m_aAxisProperties.m_aLabelAlignment==LABEL_ALIGN_RIGHT ) ?
+ LABEL_ALIGN_LEFT : LABEL_ALIGN_RIGHT;
+ }
+ else if( fabs(fDeltaY) > fabs(fDeltaX) )
+ {
+ if( m_eBackWallPos != CuboidPlanePosition_Back )
+ {
+ m_aAxisProperties.m_fLabelDirectionSign *= -1.0;
+ m_aAxisProperties.m_fInnerDirectionSign *= -1.0;
+ }
+
+ m_aAxisProperties.m_aLabelAlignment =
+ ( m_aAxisProperties.m_fLabelDirectionSign<0 ) ?
+ LABEL_ALIGN_LEFT : LABEL_ALIGN_RIGHT;
+
+ if( ( fDeltaY<0 && m_aScale.Orientation == AxisOrientation_REVERSE ) ||
+ ( fDeltaY>0 && m_aScale.Orientation == AxisOrientation_MATHEMATICAL ) )
+ m_aAxisProperties.m_aLabelAlignment =
+ ( m_aAxisProperties.m_aLabelAlignment==LABEL_ALIGN_RIGHT ) ?
+ LABEL_ALIGN_LEFT : LABEL_ALIGN_RIGHT;
+ }
+ else
+ {
+ if( m_eBackWallPos != CuboidPlanePosition_Back )
+ {
+ m_aAxisProperties.m_fLabelDirectionSign *= -1.0;
+ m_aAxisProperties.m_fInnerDirectionSign *= -1.0;
+ }
+
+ m_aAxisProperties.m_aLabelAlignment =
+ ( m_aAxisProperties.m_fLabelDirectionSign<0 ) ?
+ LABEL_ALIGN_TOP : LABEL_ALIGN_BOTTOM;
+
+ if( ( fDeltaX>0 && m_aScale.Orientation == AxisOrientation_REVERSE ) ||
+ ( fDeltaX<0 && m_aScale.Orientation == AxisOrientation_MATHEMATICAL ) )
+ m_aAxisProperties.m_aLabelAlignment =
+ ( m_aAxisProperties.m_aLabelAlignment==LABEL_ALIGN_TOP ) ?
+ LABEL_ALIGN_BOTTOM : LABEL_ALIGN_TOP;
+ }
+ }
+}
+
+TickmarkHelper* VCartesianAxis::createTickmarkHelper()
+{
+ return createTickmarkHelper2D();
+}
+
+TickmarkHelper_2D* VCartesianAxis::createTickmarkHelper2D()
+{
+ B2DVector aStart, aEnd;
+ this->get2DAxisMainLine( aStart, aEnd, this->getLogicValueWhereMainLineCrossesOtherAxis() );
+
+ B2DVector aLabelLineStart, aLabelLineEnd;
+ this->get2DAxisMainLine( aLabelLineStart, aLabelLineEnd, this->getLogicValueWhereLabelLineCrossesOtherAxis() );
+
+ return new TickmarkHelper_2D( m_aScale, m_aIncrement, aStart, aEnd, aLabelLineStart-aStart );
+}
+
+sal_Int32 VCartesianAxis::estimateMaximumAutoMainIncrementCount()
+{
+ sal_Int32 nRet = 10;
+
+ if( m_nMaximumTextWidthSoFar==0 && m_nMaximumTextHeightSoFar==0 )
+ return nRet;
+
+ B2DVector aStart, aEnd;
+ this->get2DAxisMainLine( aStart, aEnd, this->getLogicValueWhereMainLineCrossesOtherAxis() );
+
+ sal_Int32 nMaxHeight = static_cast<sal_Int32>(fabs(aEnd.getY()-aStart.getY()));
+ sal_Int32 nMaxWidth = static_cast<sal_Int32>(fabs(aEnd.getX()-aStart.getX()));
+
+ sal_Int32 nTotalAvailable = nMaxHeight;
+ sal_Int32 nSingleNeeded = m_nMaximumTextHeightSoFar;
+
+ //for horizontal axis:
+ if( (m_nDimensionIndex == 0 && !m_aAxisProperties.m_bSwapXAndY)
+ || (m_nDimensionIndex == 1 && m_aAxisProperties.m_bSwapXAndY) )
+ {
+ nTotalAvailable = nMaxWidth;
+ nSingleNeeded = m_nMaximumTextWidthSoFar;
+ }
+
+ if( nSingleNeeded>0 )
+ nRet = nTotalAvailable/nSingleNeeded;
+
+ return nRet;
+}
+
+void VCartesianAxis::doStaggeringOfLabels( const AxisLabelProperties& rAxisLabelProperties, TickmarkHelper_2D* pTickmarkHelper2D )
+{
+ if( !pTickmarkHelper2D )
+ return;
+
+ if( rAxisLabelProperties.getIsStaggered() )
+ {
+ LabelIterator aInnerIter( m_aAllTickInfos, m_aIncrement
+ , rAxisLabelProperties.eStaggering, true, 0, 0 );
+ LabelIterator aOuterIter( m_aAllTickInfos, m_aIncrement
+ , rAxisLabelProperties.eStaggering, false, 0, 0 );
+
+ lcl_correctPositionForStaggering( aOuterIter
+ , lcl_getStaggerDistance( aInnerIter
+ , pTickmarkHelper2D->getDistanceAxisTickToText( m_aAxisProperties ) ) );
+ }
+}
+
+void SAL_CALL VCartesianAxis::createLabels()
+{
+ if( !prepareShapeCreation() )
+ return;
+
+ //-----------------------------------------
+ //create labels
+ if( m_aAxisProperties.m_bDisplayLabels )
+ {
+ std::auto_ptr< TickmarkHelper_2D > apTickmarkHelper2D( this->createTickmarkHelper2D() );
+ TickmarkHelper_2D* pTickmarkHelper2D = apTickmarkHelper2D.get();
+ if( !pTickmarkHelper2D )
+ return;
+
+ //-----------------------------------------
+ //get the transformed screen values for all tickmarks in aAllTickInfos
+ pTickmarkHelper2D->updateScreenValues( m_aAllTickInfos );
+ //-----------------------------------------
+ //'hide' tickmarks with identical screen values in aAllTickInfos
+ pTickmarkHelper2D->hideIdenticalScreenValues( m_aAllTickInfos );
+
+ TickIter aRemoveIter( m_aAllTickInfos, m_aIncrement, 0, 0 );
+ removeTextShapesFromTicks( aRemoveIter, m_xTextTarget );
+
+ //create tick mark text shapes
+ TickIter aTickIter( m_aAllTickInfos, m_aIncrement, 0, 0 );
+ while( !createTextShapes( m_xTextTarget, aTickIter
+ , m_aAxisLabelProperties, pTickmarkHelper2D ) )
+ {
+ };
+
+ doStaggeringOfLabels( m_aAxisLabelProperties, pTickmarkHelper2D );
+ }
+}
+
+void SAL_CALL VCartesianAxis::createMaximumLabels()
+{
+ TrueGuard aRecordMaximumTextSize(m_bRecordMaximumTextSize);
+
+ if( !prepareShapeCreation() )
+ return;
+
+ //-----------------------------------------
+ //create labels
+ if( m_aAxisProperties.m_bDisplayLabels )
+ {
+ std::auto_ptr< TickmarkHelper_2D > apTickmarkHelper2D( this->createTickmarkHelper2D() );
+ TickmarkHelper_2D* pTickmarkHelper2D = apTickmarkHelper2D.get();
+ if( !pTickmarkHelper2D )
+ return;
+
+ //-----------------------------------------
+ //get the transformed screen values for all tickmarks in aAllTickInfos
+ pTickmarkHelper2D->updateScreenValues( m_aAllTickInfos );
+
+ //create tick mark text shapes
+ //@todo: iterate through all tick depth wich should be labeled
+
+ sal_Int32 nLongestLabelIndex = m_bUseTextLabels
+ ? this->getIndexOfLongestLabel( m_aTextLabels ) : 0;
+ MaxLabelTickIter aTickIter( m_aAllTickInfos, m_aIncrement, nLongestLabelIndex );
+ AxisLabelProperties aAxisLabelProperties( m_aAxisLabelProperties );
+ if( isAutoStaggeringOfLabelsAllowed( aAxisLabelProperties, pTickmarkHelper2D ) )
+ aAxisLabelProperties.eStaggering = STAGGER_EVEN;
+ aAxisLabelProperties.bOverlapAllowed = true;
+ aAxisLabelProperties.bLineBreakAllowed = false;
+ while( !createTextShapes( m_xTextTarget, aTickIter
+ , aAxisLabelProperties, pTickmarkHelper2D ) )
+ {
+ };
+
+ doStaggeringOfLabels( aAxisLabelProperties, pTickmarkHelper2D );
+ }
+}
+
+void SAL_CALL 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 )
+ return;
+
+ //-----------------------------------------
+ //update positions of all existing text shapes
+ pTickmarkHelper2D->updateScreenValues( m_aAllTickInfos );
+
+ TickIter aTickIter( m_aAllTickInfos, m_aIncrement, 0, 0 );
+
+ Reference< drawing::XShape > xShape2DText;
+ for( TickInfo* pTickInfo = aTickIter.firstInfo()
+ ; pTickInfo; pTickInfo = aTickIter.nextInfo() )
+ {
+ if( !pTickInfo )
+ continue;
+
+ xShape2DText = pTickInfo->xTextShape;
+ if( xShape2DText.is() )
+ {
+ B2DVector aTextToTickDistance( pTickmarkHelper2D->getDistanceAxisTickToText( m_aAxisProperties ) );
+ B2DVector aTickScreenPos2D( pTickInfo->aTickScreenPosition );
+ aTickScreenPos2D += aTextToTickDistance;
+ awt::Point aAnchorScreenPosition2D(
+ static_cast<sal_Int32>(aTickScreenPos2D.getX())
+ ,static_cast<sal_Int32>(aTickScreenPos2D.getY()));
+
+ // #i78696# use mathematically correct rotation now
+ const double fRotationAnglePi(m_aAxisLabelProperties.fRotationAngleDegree * (F_PI / -180.0));
+ uno::Any aATransformation = ShapeFactory::makeTransformation(aAnchorScreenPosition2D, fRotationAnglePi);
+
+ //set new position
+ uno::Reference< beans::XPropertySet > xProp( xShape2DText, uno::UNO_QUERY );
+ if( xProp.is() )
+ {
+ try
+ {
+ xProp->setPropertyValue( C2U( "Transformation" ), aATransformation );
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+ }
+
+ //correctPositionForRotation
+ LabelPositionHelper::correctPositionForRotation( xShape2DText
+ , m_aAxisProperties.m_aLabelAlignment, m_aAxisLabelProperties.fRotationAngleDegree, false );
+ }
+ }
+
+ doStaggeringOfLabels( m_aAxisLabelProperties, pTickmarkHelper2D );
+ }
+}
+
+void SAL_CALL VCartesianAxis::createShapes()
+{
+ if( !prepareShapeCreation() )
+ return;
+
+ std::auto_ptr< TickmarkHelper_2D > apTickmarkHelper2D( this->createTickmarkHelper2D() );
+ TickmarkHelper_2D* pTickmarkHelper2D = apTickmarkHelper2D.get();
+ if( !pTickmarkHelper2D )
+ return;
+
+ //-----------------------------------------
+ //create tick mark line shapes
+ if(2==m_nDimension)
+ {
+ ::std::vector< ::std::vector< TickInfo > > aAllShiftedTickInfos;
+ if( m_aIncrement.ShiftedPosition )
+ {
+ pTickmarkHelper2D->getAllTicksShifted( aAllShiftedTickInfos );
+ pTickmarkHelper2D->updateScreenValues( aAllShiftedTickInfos );
+ pTickmarkHelper2D->hideIdenticalScreenValues( aAllShiftedTickInfos );
+ }
+ ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos = m_aIncrement.ShiftedPosition ? aAllShiftedTickInfos : m_aAllTickInfos;
+
+ ::std::vector< ::std::vector< TickInfo > >::iterator aDepthIter = rAllTickInfos.begin();
+ const ::std::vector< ::std::vector< TickInfo > >::const_iterator aDepthEnd = rAllTickInfos.end();
+
+ if(aDepthIter == aDepthEnd)//no tickmarks at all
+ return;
+
+ sal_Int32 nTickmarkPropertiesCount = m_aAxisProperties.m_aTickmarkPropertiesList.size();
+ for( sal_Int32 nDepth=0
+ ; aDepthIter != aDepthEnd && nDepth < nTickmarkPropertiesCount
+ ; aDepthIter++, nDepth++ )
+ {
+ const TickmarkProperties& rTickmarkProperties = m_aAxisProperties.m_aTickmarkPropertiesList[nDepth];
+
+ sal_Int32 nPointCount = (*aDepthIter).size();
+ drawing::PointSequenceSequence aPoints(2*nPointCount);
+
+ ::std::vector< TickInfo >::const_iterator aTickIter = (*aDepthIter).begin();
+ const ::std::vector< TickInfo >::const_iterator aTickEnd = (*aDepthIter).end();
+ sal_Int32 nN = 0;
+ for( ; aTickIter != aTickEnd; aTickIter++ )
+ {
+ if( !(*aTickIter).bPaintIt )
+ continue;
+
+ bool bTicksAtLabels = ( m_aAxisProperties.m_eTickmarkPos != ::com::sun::star::chart::ChartAxisMarkPosition_AT_AXIS );
+ double fInnerDirectionSign = m_aAxisProperties.m_fInnerDirectionSign;
+ if( bTicksAtLabels && m_aAxisProperties.m_eLabelPos == ::com::sun::star::chart::ChartAxisLabelPosition_OUTSIDE_END )
+ fInnerDirectionSign *= -1.0;
+ apTickmarkHelper2D->addPointSequenceForTickLine( aPoints, nN++, (*aTickIter).fScaledTickValue
+ , fInnerDirectionSign , rTickmarkProperties, bTicksAtLabels );
+ if( m_aAxisProperties.m_eTickmarkPos == ::com::sun::star::chart::ChartAxisMarkPosition_AT_LABELS_AND_AXIS )
+ apTickmarkHelper2D->addPointSequenceForTickLine( aPoints, nN++, (*aTickIter).fScaledTickValue
+ , m_aAxisProperties.m_fInnerDirectionSign, rTickmarkProperties, !bTicksAtLabels );
+ }
+ aPoints.realloc(nN);
+ m_pShapeFactory->createLine2D( m_xGroupShape_Shapes, aPoints
+ , &rTickmarkProperties.aLineProperties );
+ }
+ //-----------------------------------------
+ //create axis main lines
+ //it serves also as the handle shape for the axis selection
+ {
+ drawing::PointSequenceSequence aPoints(1);
+ apTickmarkHelper2D->createPointSequenceForAxisMainLine( aPoints );
+ Reference< drawing::XShape > xShape = m_pShapeFactory->createLine2D(
+ m_xGroupShape_Shapes, aPoints
+ , &m_aAxisProperties.m_aLineProperties );
+ //because of this name this line will be used for marking the axis
+ m_pShapeFactory->setShapeName( xShape, C2U("MarkHandles") );
+ }
+ //-----------------------------------------
+ //create an additional line at NULL
+ if( !AxisHelper::isAxisPositioningEnabled() )
+ {
+ double fExtraLineCrossesOtherAxis;
+ if( getLogicValueWhereExtraLineCrossesOtherAxis(fExtraLineCrossesOtherAxis) )
+ {
+ B2DVector aStart, aEnd;
+ this->get2DAxisMainLine( aStart, aEnd, fExtraLineCrossesOtherAxis );
+ drawing::PointSequenceSequence aPoints( lcl_makePointSequence(aStart,aEnd) );
+ Reference< drawing::XShape > xShape = m_pShapeFactory->createLine2D(
+ m_xGroupShape_Shapes, aPoints, &m_aAxisProperties.m_aLineProperties );
+ }
+ }
+ }
+
+ //createLabels();
+}
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
diff --git a/chart2/source/view/axes/VCartesianAxis.hxx b/chart2/source/view/axes/VCartesianAxis.hxx
new file mode 100644
index 000000000000..ef5c8a0bf613
--- /dev/null
+++ b/chart2/source/view/axes/VCartesianAxis.hxx
@@ -0,0 +1,138 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: VCartesianAxis.hxx,v $
+ * $Revision: 1.7 $
+ *
+ * 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_VCARTESIANAXIS_HXX
+#define _CHART2_VCARTESIANAXIS_HXX
+
+#include "VAxisBase.hxx"
+#include <basegfx/vector/b2dvector.hxx>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+
+//-----------------------------------------------------------------------------
+/**
+*/
+
+class VCartesianAxis : public VAxisBase
+{
+ //-------------------------------------------------------------------------
+ // public methods
+ //-------------------------------------------------------------------------
+public:
+ VCartesianAxis( const AxisProperties& rAxisProperties
+ , const ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier >& xNumberFormatsSupplier
+ , sal_Int32 nDimensionIndex, sal_Int32 nDimensionCount
+ , PlottingPositionHelper* pPosHelper = NULL //takes ownership
+ );
+
+ 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 SAL_CALL createShapes();
+
+ virtual sal_Int32 estimateMaximumAutoMainIncrementCount();
+
+ //-------------------------------------------------------------------------
+ virtual TickmarkHelper* createTickmarkHelper();
+
+ //-------------------------------------------------------------------------
+ double getLogicValueWhereMainLineCrossesOtherAxis() const;
+ double getLogicValueWhereLabelLineCrossesOtherAxis() const;
+ bool getLogicValueWhereExtraLineCrossesOtherAxis( double& fCrossesOtherAxis) const;
+ void get2DAxisMainLine( ::basegfx::B2DVector& rStart, ::basegfx::B2DVector& rEnd, double fCrossesOtherAxis );
+
+ //-------------------------------------------------------------------------
+ //Layout interface for cartesian axes:
+
+ //the returned value describes the minimum size that is necessary
+ //for the text labels in the direction orthogonal to the axis
+ //(for an y-axis a width is returned; in case of an x-axis the value describes a height)
+ //the return value is measured in screen dimension
+ //As an example the MinimumOrthogonalSize of an x-axis equals the
+ //Font Height if the label properties allow for labels parallel to the axis.
+// sal_Int32 calculateMinimumOrthogonalSize( /*... parallel...*/ );
+ //Minimum->Preferred
+
+ //returns true if the MinimumOrthogonalSize can be calculated
+ //with the creation of at most one text shape
+ //(this is e.g. true if the parameters allow for labels parallel to the axis.)
+// sal_bool canQuicklyCalculateMinimumOrthogonalSize();
+
+
+ //-------------------------------------------------------------------------
+ //-------------------------------------------------------------------------
+
+ struct ScreenPosAndLogicPos
+ {
+ double fLogicX;
+ double fLogicY;
+ double fLogicZ;
+
+ B2DVector aScreenPos;
+ };
+
+protected: //methods
+ bool createTextShapes( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShapes >& xTarget
+ , TickIter& rTickIter
+ , AxisLabelProperties& rAxisLabelProperties
+ , TickmarkHelper_2D* pTickmarkHelper );
+
+ TickmarkHelper_2D* createTickmarkHelper2D();
+
+ void doStaggeringOfLabels( const AxisLabelProperties& rAxisLabelProperties
+ , TickmarkHelper_2D* pTickmarkHelper2D );
+ bool isAutoStaggeringOfLabelsAllowed( const AxisLabelProperties& rAxisLabelProperties
+ , TickmarkHelper_2D* pTickmarkHelper);
+ bool isBreakOfLabelsAllowed( const AxisLabelProperties& rAxisLabelProperties
+ , TickmarkHelper_2D* pTickmarkHelper );
+
+ ::basegfx::B2DVector getScreenPosition( double fLogicX, double fLogicY, double fLogicZ ) const;
+ ScreenPosAndLogicPos getScreenPosAndLogicPos( double fLogicX, double fLogicY, double fLogicZ ) const;
+};
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
+#endif
diff --git a/chart2/source/view/axes/VCartesianCoordinateSystem.cxx b/chart2/source/view/axes/VCartesianCoordinateSystem.cxx
new file mode 100644
index 000000000000..e6e77ebea57a
--- /dev/null
+++ b/chart2/source/view/axes/VCartesianCoordinateSystem.cxx
@@ -0,0 +1,245 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: VCartesianCoordinateSystem.cxx,v $
+ * $Revision: 1.9 $
+ *
+ * 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 "VCartesianCoordinateSystem.hxx"
+#include "VCartesianGrid.hxx"
+#include "VCartesianAxis.hxx"
+#include "macros.hxx"
+#include "AxisIndexDefines.hxx"
+#include "AxisHelper.hxx"
+#include "ChartTypeHelper.hxx"
+
+//for auto_ptr
+#include <memory>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+using ::com::sun::star::uno::Reference;
+
+//.............................................................................
+
+class TextualDataProvider : public ::cppu::WeakImplHelper1<
+ ::com::sun::star::chart2::data::XTextualDataSequence
+ >
+{
+public:
+ TextualDataProvider( const uno::Sequence< ::rtl::OUString >& rTextSequence )
+ : m_aTextSequence( rTextSequence )
+ {
+ }
+ virtual ~TextualDataProvider()
+ {
+ }
+
+ //XTextualDataSequence
+ virtual uno::Sequence< ::rtl::OUString > SAL_CALL getTextualData()
+ throw ( uno::RuntimeException)
+ {
+ return m_aTextSequence;
+ }
+
+private: //member
+ uno::Sequence< ::rtl::OUString > m_aTextSequence;
+};
+
+//.............................................................................
+
+VCartesianCoordinateSystem::VCartesianCoordinateSystem( const Reference< XCoordinateSystem >& xCooSys )
+ : VCoordinateSystem(xCooSys)
+{
+}
+
+VCartesianCoordinateSystem::~VCartesianCoordinateSystem()
+{
+}
+
+void VCartesianCoordinateSystem::createGridShapes()
+{
+ if(!m_xLogicTargetForGrids.is() || !m_xFinalTarget.is() )
+ return;
+
+ sal_Int32 nDimensionCount = m_xCooSysModel->getDimension();
+ bool bSwapXAndY = this->getPropertySwapXAndYAxis();
+
+ for( sal_Int32 nDimensionIndex=0; nDimensionIndex<3; nDimensionIndex++)
+ {
+ sal_Int32 nAxisIndex = MAIN_AXIS_INDEX;
+ Reference< XAxis > xAxis( AxisHelper::getAxis( nDimensionIndex, nAxisIndex, m_xCooSysModel ) );
+ if(!xAxis.is() || !AxisHelper::shouldAxisBeDisplayed( xAxis, m_xCooSysModel ))
+ continue;
+
+ VCartesianGrid aGrid(nDimensionIndex,nDimensionCount,this->getGridListFromAxis( xAxis ));
+ aGrid.setExplicitScaleAndIncrement( this->getExplicitScale(nDimensionIndex,nAxisIndex)
+ , this->getExplicitIncrement(nDimensionIndex,nAxisIndex) );
+ aGrid.set3DWallPositions( m_eLeftWallPos, m_eBackWallPos, m_eBottomPos );
+
+ aGrid.initPlotter(m_xLogicTargetForGrids,m_xFinalTarget,m_xShapeFactory
+ , this->createCIDForGrid( xAxis,nDimensionIndex,nAxisIndex ) );
+ if(2==nDimensionCount)
+ aGrid.setTransformationSceneToScreen( m_aMatrixSceneToScreen );
+ aGrid.setScales( this->getExplicitScales(nDimensionIndex,nAxisIndex), bSwapXAndY );
+ aGrid.createShapes();
+ }
+}
+
+void VCartesianCoordinateSystem::createVAxisList(
+ const uno::Reference< util::XNumberFormatsSupplier > & xNumberFormatsSupplier
+ , const awt::Size& rFontReferenceSize
+ , const awt::Rectangle& rMaximumSpaceForLabels
+ )
+{
+ m_aAxisMap.clear();
+
+ //if(!m_xLogicTargetForAxes.is() || !m_xFinalTarget.is() || !m_xCooSysModel.is() )
+ // return;
+
+ sal_Int32 nDimensionCount = m_xCooSysModel->getDimension();
+ bool bSwapXAndY = this->getPropertySwapXAndYAxis();
+
+ if(nDimensionCount<=0)
+ return;
+
+ sal_Int32 nDimensionIndex = 0;
+
+ for( nDimensionIndex = 0; nDimensionIndex < nDimensionCount; nDimensionIndex++ )
+ {
+ sal_Int32 nMaxAxisIndex = m_xCooSysModel->getMaximumAxisIndexByDimension(nDimensionIndex);
+ for( sal_Int32 nAxisIndex = 0; nAxisIndex <= nMaxAxisIndex; nAxisIndex++ )
+ {
+ Reference< XAxis > xAxis = this->getAxisByDimension(nDimensionIndex,nAxisIndex);
+ if(!xAxis.is() || !AxisHelper::shouldAxisBeDisplayed( xAxis, m_xCooSysModel ))
+ continue;
+
+ AxisProperties aAxisProperties(xAxis,this->getExplicitCategoriesProvider());
+ aAxisProperties.m_nDimensionIndex = nDimensionIndex;
+ aAxisProperties.m_bSwapXAndY = bSwapXAndY;
+ aAxisProperties.m_bIsMainAxis = (nAxisIndex==0);
+ Reference< XAxis > xCrossingMainAxis( AxisHelper::getCrossingMainAxis( xAxis, m_xCooSysModel ) );
+ if( xCrossingMainAxis.is() )
+ {
+ ScaleData aCrossingScale( xCrossingMainAxis->getScaleData() );
+ 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 ) );
+ }
+ }
+
+ if( nDimensionIndex == 2 )
+ {
+ aAxisProperties.m_xAxisTextProvider = new TextualDataProvider( m_aSeriesNamesForZAxis );
+
+ //for the z axis copy the positioning properties from the x axis (or from the y axis for swapped coordinate systems)
+ Reference< XAxis > xSisterAxis( AxisHelper::getCrossingMainAxis( xCrossingMainAxis, m_xCooSysModel ) );
+ aAxisProperties.initAxisPositioning( Reference< beans::XPropertySet >( xSisterAxis, uno::UNO_QUERY) );
+ }
+ aAxisProperties.init(true);
+ if(aAxisProperties.m_bDisplayLabels)
+ aAxisProperties.m_nNumberFormatKey = this->getNumberFormatKeyForAxis( xAxis, xNumberFormatsSupplier );
+ //-------------------
+ ::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->setExplicitScaleAndIncrement( this->getExplicitScale( nDimensionIndex, nAxisIndex ), this->getExplicitIncrement( nDimensionIndex, nAxisIndex ) );
+ //apVAxis->initPlotter(m_xLogicTargetForAxes,m_xFinalTarget,m_xShapeFactory
+ // , this->createCIDForAxis( xAxis, nDimensionIndex, nAxisIndex ) );
+ //if(2==nDimensionCount)
+ // apVAxis->setTransformationSceneToScreen( m_aMatrixSceneToScreen );
+ //apVAxis->setScales( this->getExplicitScales(nDimensionIndex,nAxisIndex), bSwapXAndY );
+ apVAxis->initAxisLabelProperties(rFontReferenceSize,rMaximumSpaceForLabels);
+ }
+ }
+}
+
+void VCartesianCoordinateSystem::initVAxisInList()
+{
+ if(!m_xLogicTargetForAxes.is() || !m_xFinalTarget.is() || !m_xCooSysModel.is() )
+ return;
+
+ sal_Int32 nDimensionCount = m_xCooSysModel->getDimension();
+ bool bSwapXAndY = this->getPropertySwapXAndYAxis();
+
+ tVAxisMap::iterator aIt( m_aAxisMap.begin() );
+ tVAxisMap::const_iterator aEnd( m_aAxisMap.end() );
+ for( ; aIt != aEnd; ++aIt )
+ {
+ VAxisBase* pVAxis = aIt->second.get();
+ if( pVAxis )
+ {
+ sal_Int32 nDimensionIndex = aIt->first.first;
+ sal_Int32 nAxisIndex = aIt->first.second;
+ pVAxis->setExplicitScaleAndIncrement( this->getExplicitScale( nDimensionIndex, nAxisIndex ), this->getExplicitIncrement( nDimensionIndex, nAxisIndex ) );
+ pVAxis->initPlotter(m_xLogicTargetForAxes,m_xFinalTarget,m_xShapeFactory
+ , this->createCIDForAxis( getAxisByDimension( nDimensionIndex, nAxisIndex ), nDimensionIndex, nAxisIndex ) );
+ if(2==nDimensionCount)
+ pVAxis->setTransformationSceneToScreen( m_aMatrixSceneToScreen );
+ pVAxis->setScales( this->getExplicitScales(nDimensionIndex,nAxisIndex), bSwapXAndY );
+ }
+ }
+}
+
+void VCartesianCoordinateSystem::updateScalesAndIncrementsOnAxes()
+{
+ if(!m_xLogicTargetForAxes.is() || !m_xFinalTarget.is() || !m_xCooSysModel.is() )
+ return;
+
+ sal_Int32 nDimensionCount = m_xCooSysModel->getDimension();
+ bool bSwapXAndY = this->getPropertySwapXAndYAxis();
+
+ tVAxisMap::iterator aIt( m_aAxisMap.begin() );
+ tVAxisMap::const_iterator aEnd( m_aAxisMap.end() );
+ for( ; aIt != aEnd; ++aIt )
+ {
+ VAxisBase* pVAxis = aIt->second.get();
+ if( pVAxis )
+ {
+ sal_Int32 nDimensionIndex = aIt->first.first;
+ sal_Int32 nAxisIndex = aIt->first.second;
+ pVAxis->setExplicitScaleAndIncrement( this->getExplicitScale( nDimensionIndex, nAxisIndex ), this->getExplicitIncrement( nDimensionIndex, nAxisIndex ) );
+ if(2==nDimensionCount)
+ pVAxis->setTransformationSceneToScreen( m_aMatrixSceneToScreen );
+ pVAxis->setScales( this->getExplicitScales(nDimensionIndex,nAxisIndex), bSwapXAndY );
+ }
+ }
+}
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
diff --git a/chart2/source/view/axes/VCartesianCoordinateSystem.hxx b/chart2/source/view/axes/VCartesianCoordinateSystem.hxx
new file mode 100644
index 000000000000..267794ac54b2
--- /dev/null
+++ b/chart2/source/view/axes/VCartesianCoordinateSystem.hxx
@@ -0,0 +1,67 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: VCartesianCoordinateSystem.hxx,v $
+ * $Revision: 1.5 $
+ *
+ * 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_VCARTESIAN_COORDINATESYSTEM_HXX
+#define _CHART2_VCARTESIAN_COORDINATESYSTEM_HXX
+
+#include "VCoordinateSystem.hxx"
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+
+//-----------------------------------------------------------------------------
+/**
+*/
+class VCartesianCoordinateSystem : public VCoordinateSystem
+{
+public:
+ VCartesianCoordinateSystem( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::chart2::XCoordinateSystem >& xCooSys );
+ virtual ~VCartesianCoordinateSystem();
+
+ virtual void createVAxisList(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier > & xNumberFormatsSupplier
+ , const ::com::sun::star::awt::Size& rFontReferenceSize
+ , const ::com::sun::star::awt::Rectangle& rMaximumSpaceForLabels );
+
+ virtual void initVAxisInList();
+ virtual void updateScalesAndIncrementsOnAxes();
+
+ virtual void createGridShapes();
+
+private:
+ VCartesianCoordinateSystem();
+};
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
+#endif
diff --git a/chart2/source/view/axes/VCartesianGrid.cxx b/chart2/source/view/axes/VCartesianGrid.cxx
new file mode 100644
index 000000000000..84ebd4c11f91
--- /dev/null
+++ b/chart2/source/view/axes/VCartesianGrid.cxx
@@ -0,0 +1,342 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: VCartesianGrid.cxx,v $
+ * $Revision: 1.9 $
+ *
+ * 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 "VCartesianGrid.hxx"
+#include "TickmarkHelper.hxx"
+#include "PlottingPositionHelper.hxx"
+#include "ShapeFactory.hxx"
+#include "ObjectIdentifier.hxx"
+#include "macros.hxx"
+#include "CommonConverters.hxx"
+#include "AxisHelper.hxx"
+#include <com/sun/star/drawing/PointSequenceSequence.hpp>
+#include <com/sun/star/drawing/LineStyle.hpp>
+
+#include <vector>
+#include <memory>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+
+struct GridLinePoints
+{
+ Sequence< double > P0;
+ Sequence< double > P1;
+ Sequence< double > P2;
+
+ GridLinePoints( const PlottingPositionHelper* pPosHelper, sal_Int32 nDimensionIndex
+ , CuboidPlanePosition eLeftWallPos=CuboidPlanePosition_Left
+ , CuboidPlanePosition eBackWallPos=CuboidPlanePosition_Back
+ , CuboidPlanePosition eBottomPos=CuboidPlanePosition_Bottom );
+ void update( double fScaledTickValue );
+
+ sal_Int32 m_nDimensionIndex;
+};
+
+GridLinePoints::GridLinePoints( const PlottingPositionHelper* pPosHelper, sal_Int32 nDimensionIndex
+ , CuboidPlanePosition eLeftWallPos
+ , CuboidPlanePosition eBackWallPos
+ , CuboidPlanePosition eBottomPos )
+ : m_nDimensionIndex(nDimensionIndex)
+{
+ double MinX = pPosHelper->getLogicMinX();
+ double MinY = pPosHelper->getLogicMinY();
+ double MinZ = pPosHelper->getLogicMinZ();
+ double MaxX = pPosHelper->getLogicMaxX();
+ double MaxY = pPosHelper->getLogicMaxY();
+ double MaxZ = pPosHelper->getLogicMaxZ();
+
+ pPosHelper->doLogicScaling( &MinX,&MinY,&MinZ );
+ pPosHelper->doLogicScaling( &MaxX,&MaxY,&MaxZ );
+
+ if(!pPosHelper->isMathematicalOrientationX())
+ {
+ double fHelp = MinX;
+ MinX = MaxX;
+ MaxX = fHelp;
+ }
+ if(!pPosHelper->isMathematicalOrientationY())
+ {
+ double fHelp = MinY;
+ MinY = MaxY;
+ MaxY = fHelp;
+ }
+ if(pPosHelper->isMathematicalOrientationZ())//z axis in draw is reverse to mathematical
+ {
+ double fHelp = MinZ;
+ MinZ = MaxZ;
+ MaxZ = fHelp;
+ }
+ bool bSwapXY = pPosHelper->isSwapXAndY();
+
+ P0.realloc(3);
+ P1.realloc(3);
+ P2.realloc(3);
+
+ //P0: point on 'back' wall, not on 'left' wall
+ //P1: point on both walls
+ //P2: point on 'left' wall not on 'back' wall
+
+ P0[0]=P1[0]=P2[0]= (CuboidPlanePosition_Left == eLeftWallPos || bSwapXY) ? MinX : MaxX;
+ P0[1]=P1[1]=P2[1]= (CuboidPlanePosition_Left == eLeftWallPos || !bSwapXY) ? MinY : MaxY;
+ P0[2]=P1[2]=P2[2]= (CuboidPlanePosition_Back == eBackWallPos) ? MinZ : MaxZ;
+
+ if(m_nDimensionIndex==0)
+ {
+ P0[1]= (CuboidPlanePosition_Left == eLeftWallPos || !bSwapXY) ? MaxY : MinY;
+ P2[2]= (CuboidPlanePosition_Back == eBackWallPos) ? MaxZ : MinZ;
+ if( CuboidPlanePosition_Bottom != eBottomPos && !bSwapXY )
+ P2=P1;
+ }
+ else if(m_nDimensionIndex==1)
+ {
+ P0[0]= (CuboidPlanePosition_Left == eLeftWallPos || bSwapXY) ? MaxX : MinX;
+ P2[2]= (CuboidPlanePosition_Back == eBackWallPos) ? MaxZ : MinZ;
+ if( CuboidPlanePosition_Bottom != eBottomPos && bSwapXY )
+ P2=P1;
+ }
+ else if(m_nDimensionIndex==2)
+ {
+ P0[0]= (CuboidPlanePosition_Left == eLeftWallPos || bSwapXY) ? MaxX : MinX;
+ P2[1]= (CuboidPlanePosition_Left == eLeftWallPos || !bSwapXY) ? MaxY : MinY;
+ if( CuboidPlanePosition_Bottom != eBottomPos )
+ {
+ if( !bSwapXY )
+ P0=P1;
+ else
+ P2=P1;
+ }
+ }
+}
+
+void GridLinePoints::update( double fScaledTickValue )
+{
+ P0[m_nDimensionIndex] = P1[m_nDimensionIndex] = P2[m_nDimensionIndex] = fScaledTickValue;
+}
+
+void addLine2D( drawing::PointSequenceSequence& rPoints, sal_Int32 nIndex
+ , const GridLinePoints& rScaledLogicPoints
+ , const Reference< XTransformation > & xTransformation
+ )
+{
+ drawing::Position3D aPA = SequenceToPosition3D( xTransformation->transform( rScaledLogicPoints.P0 ) );
+ drawing::Position3D aPB = SequenceToPosition3D( xTransformation->transform( rScaledLogicPoints.P1 ) );
+
+ rPoints[nIndex].realloc(2);
+ rPoints[nIndex][0].X = static_cast<sal_Int32>(aPA.PositionX);
+ rPoints[nIndex][0].Y = static_cast<sal_Int32>(aPA.PositionY);
+ rPoints[nIndex][1].X = static_cast<sal_Int32>(aPB.PositionX);
+ rPoints[nIndex][1].Y = static_cast<sal_Int32>(aPB.PositionY);
+}
+
+void addLine3D( drawing::PolyPolygonShape3D& rPoints, sal_Int32 nIndex
+ , const GridLinePoints& rBasePoints
+ , const Reference< XTransformation > & xTransformation )
+{
+ drawing::Position3D aPoint = SequenceToPosition3D( xTransformation->transform( rBasePoints.P0 ) );
+ AddPointToPoly( rPoints, aPoint, nIndex );
+ aPoint = SequenceToPosition3D( xTransformation->transform( rBasePoints.P1 ) );
+ AddPointToPoly( rPoints, aPoint, nIndex );
+ aPoint = SequenceToPosition3D( xTransformation->transform( rBasePoints.P2 ) );
+ AddPointToPoly( rPoints, aPoint, nIndex );
+}
+
+//---------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------
+
+VCartesianGrid::VCartesianGrid( sal_Int32 nDimensionIndex, sal_Int32 nDimensionCount
+ , const Sequence< Reference< beans::XPropertySet > > & rGridPropertiesList )
+ : VAxisOrGridBase( nDimensionIndex, nDimensionCount )
+ , m_aGridPropertiesList( rGridPropertiesList )
+{
+ m_pPosHelper = new PlottingPositionHelper();
+}
+
+VCartesianGrid::~VCartesianGrid()
+{
+ delete m_pPosHelper;
+ m_pPosHelper = NULL;
+}
+
+//static
+void VCartesianGrid::fillLinePropertiesFromGridModel( ::std::vector<VLineProperties>& rLinePropertiesList
+ , const Sequence< Reference< beans::XPropertySet > > & rGridPropertiesList )
+{
+ rLinePropertiesList.clear();
+ if( !rGridPropertiesList.getLength() )
+ return;
+
+ VLineProperties aLineProperties;
+ for( sal_Int32 nN=0; nN < rGridPropertiesList.getLength(); nN++ )
+ {
+ if(!AxisHelper::isGridVisible( rGridPropertiesList[nN] ))
+ aLineProperties.LineStyle = uno::makeAny( drawing::LineStyle_NONE );
+ else
+ aLineProperties.initFromPropertySet( rGridPropertiesList[nN] );
+ rLinePropertiesList.push_back(aLineProperties);
+ }
+};
+
+void SAL_CALL VCartesianGrid::createShapes()
+{
+ if(!m_aGridPropertiesList.getLength())
+ return;
+ //somehow equal to axis tickmarks
+
+ //-----------------------------------------
+ //create named group shape
+ Reference< drawing::XShapes > xGroupShape_Shapes(
+ this->createGroupShape( m_xLogicTarget, m_aCID ) );
+
+ if(!xGroupShape_Shapes.is())
+ return;
+ //-----------------------------------------
+
+ ::std::vector<VLineProperties> aLinePropertiesList;
+ fillLinePropertiesFromGridModel( aLinePropertiesList, m_aGridPropertiesList );
+
+ //-----------------------------------------
+ //create all scaled tickmark values
+ std::auto_ptr< TickmarkHelper > apTickmarkHelper( this->createTickmarkHelper() );
+ TickmarkHelper& aTickmarkHelper = *apTickmarkHelper.get();
+ ::std::vector< ::std::vector< TickInfo > > aAllTickInfos;
+ if( m_aIncrement.ShiftedPosition )
+ aTickmarkHelper.getAllTicksShifted( aAllTickInfos );
+ else
+ aTickmarkHelper.getAllTicks( aAllTickInfos );
+
+ //-----------------------------------------
+ //create tick mark line shapes
+ ::std::vector< ::std::vector< TickInfo > >::iterator aDepthIter = aAllTickInfos.begin();
+ const ::std::vector< ::std::vector< TickInfo > >::const_iterator aDepthEnd = aAllTickInfos.end();
+
+ if(aDepthIter == aDepthEnd)//no tickmarks at all
+ return;
+
+
+ sal_Int32 nLinePropertiesCount = aLinePropertiesList.size();
+ for( sal_Int32 nDepth=0
+ ; aDepthIter != aDepthEnd && nDepth < nLinePropertiesCount
+ ; aDepthIter++, nDepth++ )
+ {
+ if( !aLinePropertiesList[nDepth].isLineVisible() )
+ continue;
+
+ Reference< drawing::XShapes > xTarget( xGroupShape_Shapes );
+ if( nDepth > 0 )
+ {
+ xTarget.set( this->createGroupShape( m_xLogicTarget
+ , ObjectIdentifier::addChildParticle( m_aCID, ObjectIdentifier::createChildParticleWithIndex( OBJECTTYPE_SUBGRID, nDepth-1 ) )
+ ) );
+ if(!xTarget.is())
+ xTarget.set( xGroupShape_Shapes );
+ }
+
+ if(2==m_nDimension)
+ {
+
+ GridLinePoints aGridLinePoints( m_pPosHelper, m_nDimensionIndex );
+
+ sal_Int32 nPointCount = (*aDepthIter).size();
+ drawing::PointSequenceSequence aPoints(nPointCount);
+
+ ::std::vector< TickInfo >::const_iterator aTickIter = (*aDepthIter).begin();
+ const ::std::vector< TickInfo >::const_iterator aTickEnd = (*aDepthIter).end();
+ sal_Int32 nRealPointCount = 0;
+ for( ; aTickIter != aTickEnd; aTickIter++ )
+ {
+ if( !(*aTickIter).bPaintIt )
+ continue;
+ aGridLinePoints.update( (*aTickIter).fScaledTickValue );
+ addLine2D( aPoints, nRealPointCount, aGridLinePoints, m_pPosHelper->getTransformationScaledLogicToScene() );
+ nRealPointCount++;
+ }
+ aPoints.realloc(nRealPointCount);
+ m_pShapeFactory->createLine2D( xTarget, aPoints, &aLinePropertiesList[nDepth] );
+
+ //prepare polygon for handle shape:
+ drawing::PointSequenceSequence aHandlesPoints(1);
+ sal_Int32 nOldHandleCount = aHandlesPoints[0].getLength();
+ aHandlesPoints[0].realloc(nOldHandleCount+nRealPointCount);
+ for( sal_Int32 nN = 0; nN<nRealPointCount; nN++)
+ aHandlesPoints[0][nOldHandleCount+nN] = aPoints[nN][1];
+
+ //create handle shape:
+ VLineProperties aHandleLineProperties;
+ aHandleLineProperties.LineStyle = uno::makeAny( drawing::LineStyle_NONE );
+ Reference< drawing::XShape > xHandleShape =
+ m_pShapeFactory->createLine2D( xTarget, aHandlesPoints, &aHandleLineProperties );
+ m_pShapeFactory->setShapeName( xHandleShape, C2U("HandlesOnly") );
+ }
+ //-----------------------------------------
+ else //if(2!=m_nDimension)
+ {
+ GridLinePoints aGridLinePoints( m_pPosHelper, m_nDimensionIndex, m_eLeftWallPos, m_eBackWallPos, m_eBottomPos );
+
+ sal_Int32 nPointCount = (*aDepthIter).size();
+ drawing::PolyPolygonShape3D aPoints;
+ aPoints.SequenceX.realloc(nPointCount);
+ aPoints.SequenceY.realloc(nPointCount);
+ aPoints.SequenceZ.realloc(nPointCount);
+
+ ::std::vector< TickInfo >::const_iterator aTickIter = (*aDepthIter).begin();
+ const ::std::vector< TickInfo >::const_iterator aTickEnd = (*aDepthIter).end();
+ sal_Int32 nRealPointCount = 0;
+ sal_Int32 nPolyIndex = 0;
+ for( ; aTickIter != aTickEnd; aTickIter++, nPolyIndex++ )
+ {
+ if( !(*aTickIter).bPaintIt )
+ continue;
+
+ aGridLinePoints.update( (*aTickIter).fScaledTickValue );
+ addLine3D( aPoints, nPolyIndex, aGridLinePoints, m_pPosHelper->getTransformationScaledLogicToScene() );
+ nRealPointCount+=3;
+ }
+ aPoints.SequenceX.realloc(nRealPointCount);
+ aPoints.SequenceY.realloc(nRealPointCount);
+ aPoints.SequenceZ.realloc(nRealPointCount);
+ m_pShapeFactory->createLine3D( xTarget, aPoints, aLinePropertiesList[nDepth] );
+ }
+ }
+}
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
diff --git a/chart2/source/view/axes/VCartesianGrid.hxx b/chart2/source/view/axes/VCartesianGrid.hxx
new file mode 100644
index 000000000000..6774b3081100
--- /dev/null
+++ b/chart2/source/view/axes/VCartesianGrid.hxx
@@ -0,0 +1,74 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: VCartesianGrid.hxx,v $
+ * $Revision: 1.5 $
+ *
+ * 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_VCARTESIANGRID_HXX
+#define _CHART2_VCARTESIANGRID_HXX
+
+#include "VAxisOrGridBase.hxx"
+#include "VLineProperties.hxx"
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+
+//-----------------------------------------------------------------------------
+/**
+*/
+
+class VCartesianGrid : public VAxisOrGridBase
+{
+//-------------------------------------------------------------------------
+// public methods
+//-------------------------------------------------------------------------
+public:
+ VCartesianGrid( sal_Int32 nDimensionIndex, sal_Int32 nDimensionCount
+ , const ::com::sun::star::uno::Sequence<
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::beans::XPropertySet > >& rGridPropertiesList //main grid, subgrid, subsubgrid etc
+ );
+ virtual ~VCartesianGrid();
+
+ virtual void SAL_CALL createShapes();
+
+ static void fillLinePropertiesFromGridModel( ::std::vector<VLineProperties>& rLinePropertiesList
+ , const ::com::sun::star::uno::Sequence<
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::beans::XPropertySet > >& rGridPropertiesList );
+
+private:
+ ::com::sun::star::uno::Sequence<
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::beans::XPropertySet > > m_aGridPropertiesList; //main grid, subgrid, subsubgrid etc
+};
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
+#endif
diff --git a/chart2/source/view/axes/VCoordinateSystem.cxx b/chart2/source/view/axes/VCoordinateSystem.cxx
new file mode 100644
index 000000000000..47cc6de405f7
--- /dev/null
+++ b/chart2/source/view/axes/VCoordinateSystem.cxx
@@ -0,0 +1,597 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: VCoordinateSystem.cxx,v $
+ * $Revision: 1.11.36.1 $
+ *
+ * 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 "VCoordinateSystem.hxx"
+#include "VCartesianCoordinateSystem.hxx"
+#include "VPolarCoordinateSystem.hxx"
+#include "ScaleAutomatism.hxx"
+#include "VSeriesPlotter.hxx"
+#include "ShapeFactory.hxx"
+#include "servicenames_coosystems.hxx"
+#include "macros.hxx"
+#include "AxisIndexDefines.hxx"
+#include "ObjectIdentifier.hxx"
+#include "ExplicitCategoriesProvider.hxx"
+#include "AxisHelper.hxx"
+#include "ContainerHelper.hxx"
+#include "VAxisBase.hxx"
+#include "ViewDefines.hxx"
+#include "DataSeriesHelper.hxx"
+#include "chartview/ExplicitValueProvider.hxx"
+#include <com/sun/star/chart2/AxisType.hpp>
+#include <com/sun/star/chart2/XChartTypeContainer.hpp>
+#include <com/sun/star/chart2/XDataSeriesContainer.hpp>
+
+// header for define DBG_ASSERT
+#include <tools/debug.hxx>
+#include <rtl/math.hxx>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+
+//static
+VCoordinateSystem* VCoordinateSystem::createCoordinateSystem(
+ const Reference< XCoordinateSystem >& xCooSysModel )
+{
+ if( !xCooSysModel.is() )
+ return 0;
+
+ rtl::OUString aViewServiceName = xCooSysModel->getViewServiceName();
+
+ //@todo: in future the coordinatesystems should be instanciated via service factory
+ VCoordinateSystem* pRet=NULL;
+ if( aViewServiceName.equals( CHART2_COOSYSTEM_CARTESIAN_VIEW_SERVICE_NAME ) )
+ pRet = new VCartesianCoordinateSystem(xCooSysModel);
+ else if( aViewServiceName.equals( CHART2_COOSYSTEM_POLAR_VIEW_SERVICE_NAME ) )
+ pRet = new VPolarCoordinateSystem(xCooSysModel);
+ if(!pRet)
+ pRet = new VCoordinateSystem(xCooSysModel);
+ return pRet;
+}
+
+VCoordinateSystem::VCoordinateSystem( const Reference< XCoordinateSystem >& xCooSys )
+ : m_xCooSysModel(xCooSys)
+ , m_xLogicTargetForGrids(0)
+ , m_xLogicTargetForAxes(0)
+ , m_xFinalTarget(0)
+ , m_xShapeFactory(0)
+ , m_aMatrixSceneToScreen()
+ , m_eLeftWallPos(CuboidPlanePosition_Left)
+ , m_eBackWallPos(CuboidPlanePosition_Back)
+ , m_eBottomPos(CuboidPlanePosition_Bottom)
+ , m_aMergedMinimumAndMaximumSupplier()
+ , m_aExplicitScales(3)
+ , m_aExplicitIncrements(3)
+ , m_aExplicitCategoriesProvider( new ExplicitCategoriesProvider( m_xCooSysModel ) )
+{
+ if( !m_xCooSysModel.is() || m_xCooSysModel->getDimension()<3 )
+ {
+ m_aExplicitScales[2].Minimum = -0.5;
+ m_aExplicitScales[2].Maximum = 0.5;
+ m_aExplicitScales[2].Orientation = AxisOrientation_MATHEMATICAL;
+ }
+}
+VCoordinateSystem::~VCoordinateSystem()
+{
+}
+
+void SAL_CALL VCoordinateSystem::initPlottingTargets( const Reference< drawing::XShapes >& xLogicTarget
+ , const Reference< drawing::XShapes >& xFinalTarget
+ , const Reference< lang::XMultiServiceFactory >& xShapeFactory
+ , Reference< drawing::XShapes >& xLogicTargetForSeriesBehindAxis )
+ throw (uno::RuntimeException)
+{
+ DBG_ASSERT(xLogicTarget.is()&&xFinalTarget.is()&&xShapeFactory.is(),"no proper initialization parameters");
+ //is only allowed to be called once
+
+ sal_Int32 nDimensionCount = m_xCooSysModel->getDimension();
+ //create group shape for grids first thus axes are always painted above grids
+ ShapeFactory aShapeFactory(xShapeFactory);
+ if(nDimensionCount==2)
+ {
+ //create and add to target
+ m_xLogicTargetForGrids = aShapeFactory.createGroup2D( xLogicTarget );
+ xLogicTargetForSeriesBehindAxis = aShapeFactory.createGroup2D( xLogicTarget );
+ m_xLogicTargetForAxes = aShapeFactory.createGroup2D( xLogicTarget );
+ }
+ else
+ {
+ //create and added to target
+ m_xLogicTargetForGrids = aShapeFactory.createGroup3D( xLogicTarget );
+ xLogicTargetForSeriesBehindAxis = aShapeFactory.createGroup3D( xLogicTarget );
+ m_xLogicTargetForAxes = aShapeFactory.createGroup3D( xLogicTarget );
+ }
+ m_xFinalTarget = xFinalTarget;
+ m_xShapeFactory = xShapeFactory;
+}
+
+void VCoordinateSystem::setParticle( const rtl::OUString& rCooSysParticle )
+{
+ m_aCooSysParticle = rCooSysParticle;
+}
+
+void VCoordinateSystem::setTransformationSceneToScreen(
+ const drawing::HomogenMatrix& rMatrix )
+{
+ m_aMatrixSceneToScreen = rMatrix;
+
+ //correct transformation for axis
+ tVAxisMap::iterator aIt( m_aAxisMap.begin() );
+ tVAxisMap::const_iterator aEnd( m_aAxisMap.end() );
+ for( ; aIt != aEnd; ++aIt )
+ {
+ VAxisBase* pVAxis = aIt->second.get();
+ if( pVAxis )
+ {
+ if(2==pVAxis->getDimensionCount())
+ pVAxis->setTransformationSceneToScreen( m_aMatrixSceneToScreen );
+ }
+ }
+}
+
+drawing::HomogenMatrix VCoordinateSystem::getTransformationSceneToScreen()
+{
+ return m_aMatrixSceneToScreen;
+}
+
+//better performance for big data
+uno::Sequence< sal_Int32 > VCoordinateSystem::getCoordinateSystemResolution(
+ const awt::Size& rPageSize, const awt::Size& rPageResolution )
+{
+ uno::Sequence< sal_Int32 > aResolution(2);
+
+ sal_Int32 nDimensionCount = m_xCooSysModel->getDimension();
+ if(nDimensionCount>2)
+ aResolution.realloc(nDimensionCount);
+ sal_Int32 nN = 0;
+ for( nN = 0 ;nN<aResolution.getLength(); nN++ )
+ aResolution[nN]=1000;
+
+ ::basegfx::B3DTuple aScale( BaseGFXHelper::GetScaleFromMatrix(
+ BaseGFXHelper::HomogenMatrixToB3DHomMatrix(
+ m_aMatrixSceneToScreen ) ) );
+
+ double fCoosysWidth = static_cast< double >( fabs(aScale.getX()*FIXED_SIZE_FOR_3D_CHART_VOLUME));
+ double fCoosysHeight = static_cast< double >( fabs(aScale.getY()*FIXED_SIZE_FOR_3D_CHART_VOLUME));
+
+ double fPageWidth = rPageSize.Width;
+ double fPageHeight = rPageSize.Height;
+
+ //factor 2 to avoid rounding problems
+ sal_Int32 nXResolution = static_cast<sal_Int32>(2.0*static_cast<double>(rPageResolution.Width)*fCoosysWidth/fPageWidth);
+ sal_Int32 nYResolution = static_cast<sal_Int32>(2.0*static_cast<double>(rPageResolution.Height)*fCoosysHeight/fPageHeight);
+
+ if( nXResolution < 10 )
+ nXResolution = 10;
+ if( nYResolution < 10 )
+ nYResolution = 10;
+
+ if( this->getPropertySwapXAndYAxis() )
+ std::swap(nXResolution,nYResolution);
+
+ //2D
+ if( 2 == aResolution.getLength() )
+ {
+ aResolution[0]=nXResolution;
+ aResolution[1]=nYResolution;
+ }
+ else
+ {
+ //this maybe can be optimized further ...
+ sal_Int32 nMaxResolution = std::max( nXResolution, nYResolution );
+ nMaxResolution*=2;
+ for( nN = 0 ;nN<aResolution.getLength(); nN++ )
+ aResolution[nN]=nMaxResolution;
+ }
+
+ return aResolution;
+}
+
+Reference< XCoordinateSystem > VCoordinateSystem::getModel() const
+{
+ return m_xCooSysModel;
+}
+
+Reference< XAxis > VCoordinateSystem::getAxisByDimension( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) const
+{
+ if( m_xCooSysModel.is() )
+ return m_xCooSysModel->getAxisByDimension( nDimensionIndex, nAxisIndex );
+ return 0;
+}
+
+Sequence< Reference< beans::XPropertySet > > VCoordinateSystem::getGridListFromAxis( const Reference< XAxis >& xAxis )
+{
+ std::vector< Reference< beans::XPropertySet > > aRet;
+
+ if( xAxis.is() )
+ {
+ aRet.push_back( xAxis->getGridProperties() );
+ std::vector< Reference< beans::XPropertySet > > aSubGrids( ContainerHelper::SequenceToVector( xAxis->getSubGridProperties() ) );
+ aRet.insert( aRet.end(), aSubGrids.begin(), aSubGrids.end() );
+ }
+
+ return ContainerHelper::ContainerToSequence( aRet );
+}
+
+void VCoordinateSystem::impl_adjustDimension( sal_Int32& rDimensionIndex ) const
+{
+ if( rDimensionIndex<0 )
+ rDimensionIndex=0;
+ if( rDimensionIndex>2 )
+ rDimensionIndex=2;
+}
+
+void VCoordinateSystem::impl_adjustDimensionAndIndex( sal_Int32& rDimensionIndex, sal_Int32& rAxisIndex ) const
+{
+ impl_adjustDimension( rDimensionIndex );
+
+ if( rAxisIndex < 0 || rAxisIndex > this->getMaximumAxisIndexByDimension(rDimensionIndex) )
+ rAxisIndex = 0;
+}
+
+
+Reference< data::XTextualDataSequence > VCoordinateSystem::getExplicitCategoriesProvider()
+{
+ return m_aExplicitCategoriesProvider.getRef();
+}
+
+Sequence< ExplicitScaleData > VCoordinateSystem::getExplicitScales( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) const
+{
+ Sequence< ExplicitScaleData > aRet(m_aExplicitScales);
+
+ impl_adjustDimensionAndIndex( nDimensionIndex, nAxisIndex );
+ aRet[nDimensionIndex]=this->getExplicitScale( nDimensionIndex, nAxisIndex );
+
+ return aRet;
+}
+
+Sequence< ExplicitIncrementData > VCoordinateSystem::getExplicitIncrements( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) const
+{
+ Sequence< ExplicitIncrementData > aRet(m_aExplicitIncrements);
+
+ impl_adjustDimensionAndIndex( nDimensionIndex, nAxisIndex );
+ aRet[nDimensionIndex]=this->getExplicitIncrement( nDimensionIndex, nAxisIndex );
+
+ return aRet;
+}
+
+ExplicitScaleData VCoordinateSystem::getExplicitScale( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) const
+{
+ ExplicitScaleData aRet;
+
+ impl_adjustDimensionAndIndex( nDimensionIndex, nAxisIndex );
+
+ if( nAxisIndex == 0)
+ {
+ aRet = m_aExplicitScales[nDimensionIndex];
+ }
+ else
+ {
+ tFullAxisIndex aFullAxisIndex( nDimensionIndex, nAxisIndex );
+ tFullExplicitScaleMap::const_iterator aIt = m_aSecondaryExplicitScales.find( aFullAxisIndex );
+ if( aIt != m_aSecondaryExplicitScales.end() )
+ aRet = aIt->second;
+ else
+ aRet = m_aExplicitScales[nDimensionIndex];
+ }
+
+ return aRet;
+}
+
+ExplicitIncrementData VCoordinateSystem::getExplicitIncrement( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) const
+{
+ ExplicitIncrementData aRet;
+
+ impl_adjustDimensionAndIndex( nDimensionIndex, nAxisIndex );
+
+ if( nAxisIndex == 0)
+ {
+ aRet = m_aExplicitIncrements[nDimensionIndex];
+ }
+ else
+ {
+ tFullAxisIndex aFullAxisIndex( nDimensionIndex, nAxisIndex );
+ tFullExplicitIncrementMap::const_iterator aIt = m_aSecondaryExplicitIncrements.find( aFullAxisIndex );
+ if( aIt != m_aSecondaryExplicitIncrements.end() )
+ aRet = aIt->second;
+ else
+ aRet = m_aExplicitIncrements[nDimensionIndex];
+ }
+
+ return aRet;
+}
+
+rtl::OUString VCoordinateSystem::createCIDForAxis( const Reference< chart2::XAxis >& /* xAxis */, sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex )
+{
+ rtl::OUString aAxisParticle( ObjectIdentifier::createParticleForAxis( nDimensionIndex, nAxisIndex ) );
+ return ObjectIdentifier::createClassifiedIdentifierForParticles( m_aCooSysParticle, aAxisParticle );
+}
+rtl::OUString VCoordinateSystem::createCIDForGrid( const Reference< chart2::XAxis >& /* xAxis */, sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex )
+{
+ rtl::OUString aGridParticle( ObjectIdentifier::createParticleForGrid( nDimensionIndex, nAxisIndex ) );
+ return ObjectIdentifier::createClassifiedIdentifierForParticles( m_aCooSysParticle, aGridParticle );
+}
+
+sal_Int32 VCoordinateSystem::getMaximumAxisIndexByDimension( sal_Int32 nDimensionIndex ) const
+{
+ sal_Int32 nRet = 0;
+ tFullExplicitScaleMap::const_iterator aIt = m_aSecondaryExplicitScales.begin();
+ tFullExplicitScaleMap::const_iterator aEnd = m_aSecondaryExplicitScales.end();
+ for(; aIt!=aEnd; ++aIt)
+ {
+ if(aIt->first.first==nDimensionIndex)
+ {
+ sal_Int32 nLocalIdx = aIt->first.second;
+ if( nRet < nLocalIdx )
+ nRet = nLocalIdx;
+ }
+ }
+ return nRet;
+}
+
+void VCoordinateSystem::createVAxisList(
+ const uno::Reference< util::XNumberFormatsSupplier > & /* xNumberFormatsSupplier */
+ , const awt::Size& /* rFontReferenceSize */
+ , const awt::Rectangle& /* rMaximumSpaceForLabels */
+ )
+{
+}
+
+void VCoordinateSystem::initVAxisInList()
+{
+}
+void VCoordinateSystem::updateScalesAndIncrementsOnAxes()
+{
+}
+
+void VCoordinateSystem::prepareScaleAutomatismForDimensionAndIndex( ScaleAutomatism& rScaleAutomatism, sal_Int32 nDimIndex, sal_Int32 nAxisIndex )
+{
+ double fMin = 0.0;
+ double fMax = 0.0;
+ ::rtl::math::setInf(&fMin, false);
+ ::rtl::math::setInf(&fMax, true);
+ if( 0 == nDimIndex )
+ {
+ fMin = m_aMergedMinimumAndMaximumSupplier.getMinimumX();
+ fMax = m_aMergedMinimumAndMaximumSupplier.getMaximumX();
+ }
+ else if( 1 == nDimIndex )
+ {
+ ExplicitScaleData aScale = getExplicitScale( 0, 0 );
+ fMin = m_aMergedMinimumAndMaximumSupplier.getMinimumYInRange(aScale.Minimum,aScale.Maximum, nAxisIndex);
+ fMax = m_aMergedMinimumAndMaximumSupplier.getMaximumYInRange(aScale.Minimum,aScale.Maximum, nAxisIndex);
+ }
+ else if( 2 == nDimIndex )
+ {
+ fMin = m_aMergedMinimumAndMaximumSupplier.getMinimumZ();
+ 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 );
+
+ rScaleAutomatism.setAutoScalingOptions(
+ m_aMergedMinimumAndMaximumSupplier.isExpandBorderToIncrementRhythm( nDimIndex ),
+ m_aMergedMinimumAndMaximumSupplier.isExpandIfValuesCloseToBorder( nDimIndex ),
+ m_aMergedMinimumAndMaximumSupplier.isExpandWideValuesToZero( nDimIndex ),
+ m_aMergedMinimumAndMaximumSupplier.isExpandNarrowValuesTowardZero( nDimIndex ) );
+
+ VAxisBase* pVAxis( this->getVAxis( nDimIndex, nAxisIndex ) );
+ if( pVAxis )
+ rScaleAutomatism.setMaximumAutoMainIncrementCount( pVAxis->estimateMaximumAutoMainIncrementCount() );
+}
+
+VAxisBase* VCoordinateSystem::getVAxis( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex )
+{
+ VAxisBase* pRet = 0;
+
+ tFullAxisIndex aFullAxisIndex( nDimensionIndex, nAxisIndex );
+
+ tVAxisMap::const_iterator aIt = m_aAxisMap.find( aFullAxisIndex );
+ if( aIt != m_aAxisMap.end() )
+ pRet = aIt->second.get();
+
+ return pRet;
+}
+
+void VCoordinateSystem::setExplicitScaleAndIncrement(
+ sal_Int32 nDimensionIndex
+ , sal_Int32 nAxisIndex
+ , const ExplicitScaleData& rExplicitScale
+ , const ExplicitIncrementData& rExplicitIncrement )
+{
+ impl_adjustDimension( nDimensionIndex );
+
+ if( nAxisIndex==0 )
+ {
+ m_aExplicitScales[nDimensionIndex]=rExplicitScale;
+ m_aExplicitIncrements[nDimensionIndex]=rExplicitIncrement;
+ }
+ else
+ {
+ tFullAxisIndex aFullAxisIndex( nDimensionIndex, nAxisIndex );
+ m_aSecondaryExplicitScales[aFullAxisIndex] = rExplicitScale;
+ m_aSecondaryExplicitIncrements[aFullAxisIndex] = rExplicitIncrement;
+ }
+}
+
+void VCoordinateSystem::set3DWallPositions( CuboidPlanePosition eLeftWallPos, CuboidPlanePosition eBackWallPos, CuboidPlanePosition eBottomPos )
+{
+ m_eLeftWallPos = eLeftWallPos;
+ m_eBackWallPos = eBackWallPos;
+ m_eBottomPos = eBottomPos;
+}
+
+void VCoordinateSystem::createMaximumAxesLabels()
+{
+ tVAxisMap::iterator aIt( m_aAxisMap.begin() );
+ tVAxisMap::const_iterator aEnd( m_aAxisMap.end() );
+ for( ; aIt != aEnd; ++aIt )
+ {
+ VAxisBase* pVAxis = aIt->second.get();
+ if( pVAxis )
+ {
+ if(2==pVAxis->getDimensionCount())
+ pVAxis->setTransformationSceneToScreen( m_aMatrixSceneToScreen );
+ pVAxis->createMaximumLabels();
+ }
+ }
+}
+void VCoordinateSystem::createAxesLabels()
+{
+ tVAxisMap::iterator aIt( m_aAxisMap.begin() );
+ tVAxisMap::const_iterator aEnd( m_aAxisMap.end() );
+ for( ; aIt != aEnd; ++aIt )
+ {
+ VAxisBase* pVAxis = aIt->second.get();
+ if( pVAxis )
+ {
+ if(2==pVAxis->getDimensionCount())
+ pVAxis->setTransformationSceneToScreen( m_aMatrixSceneToScreen );
+ pVAxis->createLabels();
+ }
+ }
+}
+
+void VCoordinateSystem::updatePositions()
+{
+ tVAxisMap::iterator aIt( m_aAxisMap.begin() );
+ tVAxisMap::const_iterator aEnd( m_aAxisMap.end() );
+ for( ; aIt != aEnd; ++aIt )
+ {
+ VAxisBase* pVAxis = aIt->second.get();
+ if( pVAxis )
+ {
+ if(2==pVAxis->getDimensionCount())
+ pVAxis->setTransformationSceneToScreen( m_aMatrixSceneToScreen );
+ pVAxis->updatePositions();
+ }
+ }
+}
+
+void VCoordinateSystem::createAxesShapes()
+{
+ tVAxisMap::iterator aIt( m_aAxisMap.begin() );
+ tVAxisMap::const_iterator aEnd( m_aAxisMap.end() );
+ for( ; aIt != aEnd; ++aIt )
+ {
+ VAxisBase* pVAxis = aIt->second.get();
+ if( pVAxis )
+ {
+ if(2==pVAxis->getDimensionCount())
+ pVAxis->setTransformationSceneToScreen( m_aMatrixSceneToScreen );
+
+ tFullAxisIndex aFullAxisIndex = aIt->first;
+ if( aFullAxisIndex.second == 0 )
+ {
+ if( aFullAxisIndex.first == 0 )
+ {
+ if( AxisType::CATEGORY!=m_aExplicitScales[1].AxisType )
+ pVAxis->setExrtaLinePositionAtOtherAxis(
+ m_aExplicitScales[1].Origin );
+ }
+ else if( aFullAxisIndex.first == 1 )
+ {
+ if( AxisType::CATEGORY!=m_aExplicitScales[0].AxisType )
+ pVAxis->setExrtaLinePositionAtOtherAxis(
+ m_aExplicitScales[0].Origin );
+ }
+ }
+
+ pVAxis->createShapes();
+ }
+ }
+}
+void VCoordinateSystem::createGridShapes()
+{
+}
+void VCoordinateSystem::addMinimumAndMaximumSupplier( MinimumAndMaximumSupplier* pMinimumAndMaximumSupplier )
+{
+ m_aMergedMinimumAndMaximumSupplier.addMinimumAndMaximumSupplier(pMinimumAndMaximumSupplier);
+}
+
+bool VCoordinateSystem::hasMinimumAndMaximumSupplier( MinimumAndMaximumSupplier* pMinimumAndMaximumSupplier )
+{
+ return m_aMergedMinimumAndMaximumSupplier.hasMinimumAndMaximumSupplier(pMinimumAndMaximumSupplier);
+}
+
+void VCoordinateSystem::clearMinimumAndMaximumSupplierList()
+{
+ m_aMergedMinimumAndMaximumSupplier.clearMinimumAndMaximumSupplierList();
+}
+
+bool VCoordinateSystem::getPropertySwapXAndYAxis() const
+{
+ Reference<beans::XPropertySet> xProp(m_xCooSysModel, uno::UNO_QUERY );
+ sal_Bool bSwapXAndY = false;
+ if( xProp.is()) try
+ {
+ xProp->getPropertyValue( C2U( "SwapXAndYAxis" ) ) >>= bSwapXAndY;
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+ return bSwapXAndY;
+}
+
+bool VCoordinateSystem::needSeriesNamesForAxis() const
+{
+ return ( m_xCooSysModel.is() && m_xCooSysModel->getDimension() == 3 );
+}
+void VCoordinateSystem::setSeriesNamesForAxis( const Sequence< rtl::OUString >& rSeriesNames )
+{
+ m_aSeriesNamesForZAxis = rSeriesNames;
+}
+
+sal_Int32 VCoordinateSystem::getNumberFormatKeyForAxis(
+ const Reference< chart2::XAxis >& xAxis
+ , const Reference< util::XNumberFormatsSupplier >& xNumberFormatsSupplier )
+{
+ return ExplicitValueProvider::getExplicitNumberFormatKeyForAxis(
+ xAxis, m_xCooSysModel, xNumberFormatsSupplier );
+}
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
diff --git a/chart2/source/view/axes/VPolarAngleAxis.cxx b/chart2/source/view/axes/VPolarAngleAxis.cxx
new file mode 100644
index 000000000000..1aa56efbca78
--- /dev/null
+++ b/chart2/source/view/axes/VPolarAngleAxis.cxx
@@ -0,0 +1,238 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: VPolarAngleAxis.cxx,v $
+ * $Revision: 1.4 $
+ *
+ * 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 <basegfx/numeric/ftools.hxx>
+
+#include "VPolarAngleAxis.hxx"
+#include "VPolarGrid.hxx"
+#include "ShapeFactory.hxx"
+#include "macros.hxx"
+#include "chartview/NumberFormatterWrapper.hxx"
+#include "PolarLabelPositionHelper.hxx"
+#include <tools/color.hxx>
+
+#include <memory>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+using namespace ::rtl::math;
+
+VPolarAngleAxis::VPolarAngleAxis( const AxisProperties& rAxisProperties
+ , const uno::Reference< util::XNumberFormatsSupplier >& xNumberFormatsSupplier
+ , sal_Int32 nDimensionCount )
+ : VPolarAxis( rAxisProperties, xNumberFormatsSupplier, 0/*nDimensionIndex*/, nDimensionCount )
+{
+}
+
+VPolarAngleAxis::~VPolarAngleAxis()
+{
+ delete m_pPosHelper;
+ m_pPosHelper = NULL;
+}
+
+bool VPolarAngleAxis::createTextShapes_ForAngleAxis(
+ const uno::Reference< drawing::XShapes >& xTarget
+ , TickIter& rTickIter
+ , AxisLabelProperties& rAxisLabelProperties
+ , double fLogicRadius
+ , double fLogicZ )
+{
+ sal_Int32 nDimensionCount = 2;
+ ShapeFactory aShapeFactory(m_xShapeFactory);
+
+ FixedNumberFormatter aFixedNumberFormatter(
+ m_xNumberFormatsSupplier, rAxisLabelProperties.nNumberFormatKey );
+
+ //------------------------------------------------
+ //prepare text properties for multipropertyset-interface of shape
+ tNameSequence aPropNames;
+ tAnySequence aPropValues;
+
+ uno::Reference< beans::XPropertySet > xProps( m_aAxisProperties.m_xAxisModel, uno::UNO_QUERY );
+ PropertyMapper::getTextLabelMultiPropertyLists( xProps, aPropNames, aPropValues, false );
+ LabelPositionHelper::doDynamicFontResize( aPropValues, aPropNames, xProps
+ , rAxisLabelProperties.m_aFontReferenceSize );
+
+ uno::Any* pColorAny = PropertyMapper::getValuePointer(aPropValues,aPropNames,C2U("CharColor"));
+ sal_Int32 nColor = Color( COL_AUTO ).GetColor();
+ if(pColorAny)
+ *pColorAny >>= nColor;
+
+ const uno::Sequence< rtl::OUString >* pLabels = m_bUseTextLabels? &m_aTextLabels : 0;
+
+ //------------------------------------------------
+
+ //TickInfo* pLastVisibleNeighbourTickInfo = NULL;
+ sal_Int32 nTick = 0;
+
+ for( TickInfo* pTickInfo = rTickIter.firstInfo()
+ ; pTickInfo
+ ; pTickInfo = rTickIter.nextInfo(), nTick++ )
+ {
+ //don't create labels which does not fit into the rythm
+ if( nTick%rAxisLabelProperties.nRhythm != 0)
+ continue;
+
+ //don't create labels for invisible ticks
+ if( !pTickInfo->bPaintIt )
+ continue;
+
+ //if NO OVERLAP -> don't create labels where the
+ //anchor position is the same as for the last label
+ //@todo
+
+ if(!pTickInfo->xTextShape.is())
+ {
+ //create single label
+ bool bHasExtraColor=false;
+ sal_Int32 nExtraColor=0;
+
+ 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
+ if( nIndex>=0 && nIndex<pLabels->getLength() )
+ aLabel = (*pLabels)[nIndex];
+ }
+ else
+ aLabel = aFixedNumberFormatter.getFormattedString( pTickInfo->fUnscaledTickValue, nExtraColor, bHasExtraColor );
+
+ if(pColorAny)
+ *pColorAny = uno::makeAny(bHasExtraColor?nExtraColor:nColor);
+
+ double fLogicAngle = pTickInfo->fUnscaledTickValue;
+
+ LabelAlignment eLabelAlignment(LABEL_ALIGN_CENTER);
+ PolarLabelPositionHelper aPolarLabelPositionHelper(m_pPosHelper,nDimensionCount,xTarget,&aShapeFactory);
+ sal_Int32 nScreenValueOffsetInRadiusDirection = m_aAxisLabelProperties.m_aMaximumSpaceForLabels.Height/15;
+ awt::Point aAnchorScreenPosition2D( aPolarLabelPositionHelper.getLabelScreenPositionAndAlignmentForLogicValues(
+ eLabelAlignment, fLogicAngle, fLogicRadius, fLogicZ, nScreenValueOffsetInRadiusDirection ));
+ LabelPositionHelper::changeTextAdjustment( aPropValues, aPropNames, eLabelAlignment );
+
+ // #i78696# use mathematically correct rotation now
+ const double fRotationAnglePi(rAxisLabelProperties.fRotationAngleDegree * (F_PI / -180.0));
+
+ uno::Any aATransformation = ShapeFactory::makeTransformation( aAnchorScreenPosition2D, fRotationAnglePi );
+ rtl::OUString aStackedLabel = ShapeFactory::getStackedString( aLabel, rAxisLabelProperties.bStackCharacters );
+
+ pTickInfo->xTextShape = aShapeFactory.createText( xTarget, aStackedLabel, aPropNames, aPropValues, aATransformation );
+ }
+
+ //if NO OVERLAP -> remove overlapping shapes
+ //@todo
+ }
+ return true;
+}
+
+void SAL_CALL VPolarAngleAxis::createMaximumLabels()
+{
+ if( !prepareShapeCreation() )
+ return;
+
+ createLabels();
+}
+
+void SAL_CALL VPolarAngleAxis::updatePositions()
+{
+ //todo: really only update the positions
+
+ if( !prepareShapeCreation() )
+ return;
+
+ createLabels();
+}
+
+void SAL_CALL VPolarAngleAxis::createLabels()
+{
+ if( !prepareShapeCreation() )
+ return;
+
+ double fLogicRadius = m_pPosHelper->getOuterLogicRadius();
+ double fLogicZ = -0.5;//as defined
+
+ if( m_aAxisProperties.m_bDisplayLabels )
+ {
+ //-----------------------------------------
+ //get the transformed screen values for all tickmarks in aAllTickInfos
+ std::auto_ptr< TickmarkHelper > apTickmarkHelper( this->createTickmarkHelper() );
+
+ //create tick mark text shapes
+ //@todo: iterate through all tick depth wich should be labeled
+
+ TickIter aTickIter( m_aAllTickInfos, m_aIncrement, 0, 0 );
+ this->updateUnscaledValuesAtTicks( aTickIter );
+
+ TickIter aRemoveIter( m_aAllTickInfos, m_aIncrement, 0, 0 );
+ removeTextShapesFromTicks( aRemoveIter, m_xTextTarget );
+
+ AxisLabelProperties aAxisLabelProperties( m_aAxisLabelProperties );
+ aAxisLabelProperties.bOverlapAllowed = true;
+ while( !createTextShapes_ForAngleAxis( m_xTextTarget, aTickIter
+ , aAxisLabelProperties
+ , fLogicRadius, fLogicZ
+ ) )
+ {
+ };
+
+ //no staggering for polar angle axis
+ }
+}
+
+void SAL_CALL VPolarAngleAxis::createShapes()
+{
+ if( !prepareShapeCreation() )
+ return;
+
+ double fLogicRadius = m_pPosHelper->getOuterLogicRadius();
+ double fLogicZ = -0.5;//as defined
+
+ //-----------------------------------------
+ //create axis main lines
+ drawing::PointSequenceSequence aPoints(1);
+ VPolarGrid::createLinePointSequence_ForAngleAxis( aPoints, m_aAllTickInfos, m_aIncrement, m_aScale, m_pPosHelper, fLogicRadius, fLogicZ );
+ uno::Reference< drawing::XShape > xShape = m_pShapeFactory->createLine2D(
+ m_xGroupShape_Shapes, aPoints, &m_aAxisProperties.m_aLineProperties );
+ //because of this name this line will be used for marking the axis
+ m_pShapeFactory->setShapeName( xShape, C2U("MarkHandles") );
+
+ //-----------------------------------------
+ //create labels
+ createLabels();
+}
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
diff --git a/chart2/source/view/axes/VPolarAngleAxis.hxx b/chart2/source/view/axes/VPolarAngleAxis.hxx
new file mode 100644
index 000000000000..a04318b70ee1
--- /dev/null
+++ b/chart2/source/view/axes/VPolarAngleAxis.hxx
@@ -0,0 +1,69 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: VPolarAngleAxis.hxx,v $
+ * $Revision: 1.3 $
+ *
+ * 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_VPOLARANGLEAXIS_HXX
+#define _CHART2_VPOLARANGLEAXIS_HXX
+
+#include "VPolarAxis.hxx"
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+
+//-----------------------------------------------------------------------------
+/**
+*/
+
+class VPolarAngleAxis : public VPolarAxis
+{
+public:
+ VPolarAngleAxis( const AxisProperties& rAxisProperties
+ , const ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier >& xNumberFormatsSupplier
+ , sal_Int32 nDimensionCount );
+ virtual ~VPolarAngleAxis();
+
+ virtual void SAL_CALL createMaximumLabels();
+ virtual void SAL_CALL createLabels();
+ virtual void SAL_CALL updatePositions();
+
+ virtual void SAL_CALL createShapes();
+
+private: //methods
+ bool createTextShapes_ForAngleAxis(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& xTarget
+ , TickIter& rTickIter
+ , AxisLabelProperties& rAxisLabelProperties
+ , double fLogicRadius, double fLogicZ );
+};
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
+#endif
diff --git a/chart2/source/view/axes/VPolarAxis.cxx b/chart2/source/view/axes/VPolarAxis.cxx
new file mode 100644
index 000000000000..9ab8c4f2d98c
--- /dev/null
+++ b/chart2/source/view/axes/VPolarAxis.cxx
@@ -0,0 +1,86 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: VPolarAxis.cxx,v $
+ * $Revision: 1.9 $
+ *
+ * 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 "VPolarAxis.hxx"
+#include "VPolarAngleAxis.hxx"
+#include "VPolarRadiusAxis.hxx"
+#include "macros.hxx"
+#include "TickmarkHelper.hxx"
+#include "ShapeFactory.hxx"
+
+#include <memory>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+VPolarAxis* VPolarAxis::createAxis( const AxisProperties& rAxisProperties
+ , const uno::Reference< util::XNumberFormatsSupplier >& xNumberFormatsSupplier
+ , sal_Int32 nDimensionIndex, sal_Int32 nDimensionCount )
+{
+ if( 0==nDimensionIndex )
+ return new VPolarAngleAxis( rAxisProperties, xNumberFormatsSupplier, nDimensionCount );
+ return new VPolarRadiusAxis( rAxisProperties, xNumberFormatsSupplier, nDimensionCount );
+}
+
+VPolarAxis::VPolarAxis( const AxisProperties& rAxisProperties
+ , const uno::Reference< util::XNumberFormatsSupplier >& xNumberFormatsSupplier
+ , sal_Int32 nDimensionIndex, sal_Int32 nDimensionCount )
+ : VAxisBase( nDimensionIndex, nDimensionCount, rAxisProperties, xNumberFormatsSupplier )
+ , m_pPosHelper( new PolarPlottingPositionHelper() )
+ , m_aIncrements()
+{
+ PlotterBase::m_pPosHelper = m_pPosHelper;
+}
+
+VPolarAxis::~VPolarAxis()
+{
+ delete m_pPosHelper;
+ m_pPosHelper = NULL;
+}
+
+void VPolarAxis::setIncrements( const uno::Sequence< ExplicitIncrementData >& rIncrements )
+{
+ m_aIncrements = rIncrements;
+}
+
+sal_Bool SAL_CALL VPolarAxis::isAnythingToDraw()
+{
+ return ( 2==m_nDimension && VAxisBase::isAnythingToDraw() );
+}
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
diff --git a/chart2/source/view/axes/VPolarAxis.hxx b/chart2/source/view/axes/VPolarAxis.hxx
new file mode 100644
index 000000000000..6491c2bcc884
--- /dev/null
+++ b/chart2/source/view/axes/VPolarAxis.hxx
@@ -0,0 +1,74 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: VPolarAxis.hxx,v $
+ * $Revision: 1.6 $
+ *
+ * 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_VPOLARAXIS_HXX
+#define _CHART2_VPOLARAXIS_HXX
+
+#include "VAxisBase.hxx"
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+
+//-----------------------------------------------------------------------------
+/**
+*/
+
+class PolarPlottingPositionHelper;
+
+class VPolarAxis : public VAxisBase
+{
+public:
+ static VPolarAxis* createAxis( const AxisProperties& rAxisProperties
+ , 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 );
+
+ virtual sal_Bool SAL_CALL isAnythingToDraw();
+
+ virtual ~VPolarAxis();
+
+protected:
+ VPolarAxis( const AxisProperties& rAxisProperties
+ , const ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier >& xNumberFormatsSupplier
+ , sal_Int32 nDimensionIndex, sal_Int32 nDimensionCount );
+
+protected: //member
+ PolarPlottingPositionHelper* m_pPosHelper;
+ ::com::sun::star::uno::Sequence<
+ ::com::sun::star::chart2::ExplicitIncrementData > m_aIncrements;
+};
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
+#endif
diff --git a/chart2/source/view/axes/VPolarCoordinateSystem.cxx b/chart2/source/view/axes/VPolarCoordinateSystem.cxx
new file mode 100644
index 000000000000..35468a3b6c2f
--- /dev/null
+++ b/chart2/source/view/axes/VPolarCoordinateSystem.cxx
@@ -0,0 +1,214 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: VPolarCoordinateSystem.cxx,v $
+ * $Revision: 1.10 $
+ *
+ * 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 "VPolarCoordinateSystem.hxx"
+#include "VPolarGrid.hxx"
+#include "VPolarAxis.hxx"
+#include "AxisIndexDefines.hxx"
+#include "AxisHelper.hxx"
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+using ::com::sun::star::uno::Reference;
+
+VPolarCoordinateSystem::VPolarCoordinateSystem( const Reference< XCoordinateSystem >& xCooSys )
+ : VCoordinateSystem(xCooSys)
+{
+}
+
+VPolarCoordinateSystem::~VPolarCoordinateSystem()
+{
+}
+
+//better performance for big data
+uno::Sequence< sal_Int32 > VPolarCoordinateSystem::getCoordinateSystemResolution(
+ const awt::Size& rPageSize, const awt::Size& rPageResolution )
+{
+ uno::Sequence< sal_Int32 > aResolution( VCoordinateSystem::getCoordinateSystemResolution( rPageSize, rPageResolution) );
+
+ if( aResolution.getLength() >= 2 )
+ {
+ if( this->getPropertySwapXAndYAxis() )
+ {
+ aResolution[0]/=2;//radius
+ aResolution[1]*=4;//outer circle resolution
+ }
+ else
+ {
+ aResolution[0]*=4;//outer circle resolution
+ aResolution[1]/=2;//radius
+ }
+ }
+
+ return aResolution;
+}
+
+void VPolarCoordinateSystem::createVAxisList(
+ const uno::Reference< util::XNumberFormatsSupplier > & xNumberFormatsSupplier
+ , const awt::Size& rFontReferenceSize
+ , const awt::Rectangle& rMaximumSpaceForLabels
+ )
+{
+ m_aAxisMap.clear();
+
+ //if(!m_xLogicTargetForAxes.is() || !m_xFinalTarget.is() || !m_xCooSysModel.is() )
+ // return;
+
+ sal_Int32 nDimensionCount = m_xCooSysModel->getDimension();
+// bool bSwapXAndY = this->getPropertySwapXAndYAxis();
+
+ sal_Int32 nDimensionIndex = 0;
+
+ //create angle axis (dimension index 0)
+ for( nDimensionIndex = 0; nDimensionIndex < nDimensionCount; nDimensionIndex++ )
+ {
+ sal_Int32 nMaxAxisIndex = m_xCooSysModel->getMaximumAxisIndexByDimension(nDimensionIndex);
+ for( sal_Int32 nAxisIndex = 0; nAxisIndex <= nMaxAxisIndex; nAxisIndex++ )
+ {
+ Reference< XAxis > xAxis( this->getAxisByDimension(nDimensionIndex,nAxisIndex) );
+ if(!xAxis.is() || !AxisHelper::shouldAxisBeDisplayed( xAxis, m_xCooSysModel ))
+ continue;
+ AxisProperties aAxisProperties(xAxis,this->getExplicitCategoriesProvider());
+ aAxisProperties.init();
+ if(aAxisProperties.m_bDisplayLabels)
+ aAxisProperties.m_nNumberFormatKey = this->getNumberFormatKeyForAxis( xAxis, xNumberFormatsSupplier );
+ //-------------------
+ ::boost::shared_ptr< VAxisBase > apVAxis( VPolarAxis::createAxis( aAxisProperties,xNumberFormatsSupplier,nDimensionIndex,nDimensionCount) );
+ tFullAxisIndex aFullAxisIndex( nDimensionIndex, nAxisIndex );
+ m_aAxisMap[aFullAxisIndex] = apVAxis;
+
+ //apVAxis->setExplicitScaleAndIncrement( this->getExplicitScale( nDimensionIndex, nAxisIndex ), this->getExplicitIncrement(nDimensionIndex, nAxisIndex) );
+ //apVAxis->initPlotter(m_xLogicTargetForAxes,m_xFinalTarget,m_xShapeFactory
+ // , this->createCIDForAxis( xAxis, nDimensionIndex, nAxisIndex ) );
+ //VPolarAxis* pVPolarAxis = dynamic_cast< VPolarAxis* >( apVAxis.get() );
+ //if( pVPolarAxis )
+ // pVPolarAxis->setIncrements( this->getExplicitIncrements( nDimensionIndex, nAxisIndex ) );
+ //if(2==nDimensionCount)
+ // apVAxis->setTransformationSceneToScreen( m_aMatrixSceneToScreen );
+ //apVAxis->setScales( this->getExplicitScales( nDimensionIndex, nAxisIndex ), bSwapXAndY );
+ apVAxis->initAxisLabelProperties(rFontReferenceSize,rMaximumSpaceForLabels);
+ }
+ }
+}
+
+void VPolarCoordinateSystem::initVAxisInList()
+{
+ if(!m_xLogicTargetForAxes.is() || !m_xFinalTarget.is() || !m_xCooSysModel.is() )
+ return;
+
+ sal_Int32 nDimensionCount = m_xCooSysModel->getDimension();
+ bool bSwapXAndY = this->getPropertySwapXAndYAxis();
+
+ tVAxisMap::iterator aIt( m_aAxisMap.begin() );
+ tVAxisMap::const_iterator aEnd( m_aAxisMap.end() );
+ for( ; aIt != aEnd; ++aIt )
+ {
+ VAxisBase* pVAxis = aIt->second.get();
+ if( pVAxis )
+ {
+ sal_Int32 nDimensionIndex = aIt->first.first;
+ sal_Int32 nAxisIndex = aIt->first.second;
+ pVAxis->setExplicitScaleAndIncrement( this->getExplicitScale( nDimensionIndex, nAxisIndex ), this->getExplicitIncrement(nDimensionIndex, nAxisIndex) );
+ pVAxis->initPlotter(m_xLogicTargetForAxes,m_xFinalTarget,m_xShapeFactory
+ , this->createCIDForAxis( getAxisByDimension( nDimensionIndex, nAxisIndex ), nDimensionIndex, nAxisIndex ) );
+ VPolarAxis* pVPolarAxis = dynamic_cast< VPolarAxis* >( pVAxis );
+ if( pVPolarAxis )
+ pVPolarAxis->setIncrements( this->getExplicitIncrements( nDimensionIndex, nAxisIndex ) );
+ if(2==nDimensionCount)
+ pVAxis->setTransformationSceneToScreen( m_aMatrixSceneToScreen );
+ pVAxis->setScales( this->getExplicitScales( nDimensionIndex, nAxisIndex ), bSwapXAndY );
+ }
+ }
+}
+
+void VPolarCoordinateSystem::updateScalesAndIncrementsOnAxes()
+{
+ if(!m_xLogicTargetForAxes.is() || !m_xFinalTarget.is() || !m_xCooSysModel.is() )
+ return;
+
+ sal_Int32 nDimensionCount = m_xCooSysModel->getDimension();
+ bool bSwapXAndY = this->getPropertySwapXAndYAxis();
+
+ tVAxisMap::iterator aIt( m_aAxisMap.begin() );
+ tVAxisMap::const_iterator aEnd( m_aAxisMap.end() );
+ for( ; aIt != aEnd; ++aIt )
+ {
+ VAxisBase* pVAxis = aIt->second.get();
+ if( pVAxis )
+ {
+ sal_Int32 nDimensionIndex = aIt->first.first;
+ sal_Int32 nAxisIndex = aIt->first.second;
+ pVAxis->setExplicitScaleAndIncrement( this->getExplicitScale( nDimensionIndex, nAxisIndex ), this->getExplicitIncrement(nDimensionIndex, nAxisIndex) );
+ VPolarAxis* pVPolarAxis = dynamic_cast< VPolarAxis* >( pVAxis );
+ if( pVPolarAxis )
+ pVPolarAxis->setIncrements( this->getExplicitIncrements( nDimensionIndex, nAxisIndex ) );
+ if(2==nDimensionCount)
+ pVAxis->setTransformationSceneToScreen( m_aMatrixSceneToScreen );
+ pVAxis->setScales( this->getExplicitScales( nDimensionIndex, nAxisIndex ), bSwapXAndY );
+ }
+ }
+}
+
+void VPolarCoordinateSystem::createGridShapes()
+{
+ if(!m_xLogicTargetForGrids.is() || !m_xFinalTarget.is() )
+ return;
+
+ sal_Int32 nDimensionCount = m_xCooSysModel->getDimension();
+ bool bSwapXAndY = this->getPropertySwapXAndYAxis();
+
+ for( sal_Int32 nDimensionIndex=0; nDimensionIndex<3; nDimensionIndex++)
+ {
+ sal_Int32 nAxisIndex = MAIN_AXIS_INDEX;
+
+ Reference< XAxis > xAxis( AxisHelper::getAxis( nDimensionIndex, nAxisIndex, m_xCooSysModel ) );
+ if(!xAxis.is() || !AxisHelper::shouldAxisBeDisplayed( xAxis, m_xCooSysModel ))
+ continue;
+
+ VPolarGrid aGrid(nDimensionIndex,nDimensionCount,this->getGridListFromAxis( xAxis ));
+ aGrid.setIncrements( this->getExplicitIncrements( nDimensionIndex, nAxisIndex ) );
+ aGrid.initPlotter(m_xLogicTargetForGrids,m_xFinalTarget,m_xShapeFactory
+ , this->createCIDForGrid( xAxis, nDimensionIndex, nAxisIndex ) );
+ if(2==nDimensionCount)
+ aGrid.setTransformationSceneToScreen( m_aMatrixSceneToScreen );
+ aGrid.setScales( this->getExplicitScales( nDimensionIndex, nAxisIndex), bSwapXAndY );
+ aGrid.createShapes();
+ }
+}
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
diff --git a/chart2/source/view/axes/VPolarCoordinateSystem.hxx b/chart2/source/view/axes/VPolarCoordinateSystem.hxx
new file mode 100644
index 000000000000..e5606ae771b4
--- /dev/null
+++ b/chart2/source/view/axes/VPolarCoordinateSystem.hxx
@@ -0,0 +1,71 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: VPolarCoordinateSystem.hxx,v $
+ * $Revision: 1.5 $
+ *
+ * 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_VPOLAR_COORDINATESYSTEM_HXX
+#define _CHART2_VPOLAR_COORDINATESYSTEM_HXX
+
+#include "VCoordinateSystem.hxx"
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+
+//-----------------------------------------------------------------------------
+/**
+*/
+class VPolarCoordinateSystem : public VCoordinateSystem
+{
+public:
+ VPolarCoordinateSystem( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::chart2::XCoordinateSystem >& xCooSys );
+ virtual ~VPolarCoordinateSystem();
+
+ //better performance for big data
+ virtual ::com::sun::star::uno::Sequence< sal_Int32 > getCoordinateSystemResolution( const ::com::sun::star::awt::Size& rPageSize
+ , const ::com::sun::star::awt::Size& rPageResolution );
+
+ virtual void createVAxisList(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier > & xNumberFormatsSupplier
+ , const ::com::sun::star::awt::Size& rFontReferenceSize
+ , const ::com::sun::star::awt::Rectangle& rMaximumSpaceForLabels );
+
+ virtual void initVAxisInList();
+ virtual void updateScalesAndIncrementsOnAxes();
+
+ virtual void createGridShapes();
+
+private:
+ VPolarCoordinateSystem();
+};
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
+#endif
diff --git a/chart2/source/view/axes/VPolarGrid.cxx b/chart2/source/view/axes/VPolarGrid.cxx
new file mode 100644
index 000000000000..f9278b94b245
--- /dev/null
+++ b/chart2/source/view/axes/VPolarGrid.cxx
@@ -0,0 +1,276 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: VPolarGrid.cxx,v $
+ * $Revision: 1.10.44.1 $
+ *
+ * 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 "VPolarGrid.hxx"
+#include "VCartesianGrid.hxx"
+#include "TickmarkHelper.hxx"
+#include "PlottingPositionHelper.hxx"
+#include "ShapeFactory.hxx"
+#include "ObjectIdentifier.hxx"
+#include "macros.hxx"
+#include "CommonConverters.hxx"
+#include <com/sun/star/drawing/LineStyle.hpp>
+
+#include <vector>
+#include <memory>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+using ::com::sun::star::uno::Reference;
+
+VPolarGrid::VPolarGrid( sal_Int32 nDimensionIndex, sal_Int32 nDimensionCount
+ , const uno::Sequence< Reference< beans::XPropertySet > > & rGridPropertiesList )
+ : VAxisOrGridBase( nDimensionIndex, nDimensionCount )
+ , m_aGridPropertiesList( rGridPropertiesList )
+ , m_pPosHelper( new PolarPlottingPositionHelper() )
+ , m_aIncrements()
+{
+ PlotterBase::m_pPosHelper = m_pPosHelper;
+}
+
+VPolarGrid::~VPolarGrid()
+{
+ delete m_pPosHelper;
+ m_pPosHelper = NULL;
+}
+
+void VPolarGrid::setIncrements( const uno::Sequence< ExplicitIncrementData >& rIncrements )
+{
+ m_aIncrements = rIncrements;
+}
+
+void VPolarGrid::getAllTickInfos( sal_Int32 nDimensionIndex, ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ) const
+{
+ TickmarkHelper aTickmarkHelper(
+ m_pPosHelper->getScales()[nDimensionIndex], m_aIncrements[nDimensionIndex] );
+ aTickmarkHelper.getAllTicks( rAllTickInfos );
+}
+
+//static
+void VPolarGrid::createLinePointSequence_ForAngleAxis(
+ drawing::PointSequenceSequence& rPoints
+ , ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos
+ , const ExplicitIncrementData& rIncrement
+ , const ExplicitScaleData& rScale
+ , PolarPlottingPositionHelper* pPosHelper
+ , double fLogicRadius, double fLogicZ )
+{
+ Reference< XScaling > xInverseScaling( NULL );
+ if( rScale.Scaling.is() )
+ xInverseScaling = rScale.Scaling->getInverseScaling();
+
+ sal_Int32 nTick = 0;
+ TickIter aIter( rAllTickInfos, rIncrement, 0, 0 );
+ for( TickInfo* pTickInfo = aIter.firstInfo()
+ ; pTickInfo
+ ; pTickInfo = aIter.nextInfo(), nTick++ )
+ {
+ if(nTick>=rPoints[0].getLength())
+ rPoints[0].realloc(rPoints[0].getLength()+30);
+
+ pTickInfo->updateUnscaledValue( xInverseScaling );
+ double fLogicAngle = pTickInfo->fUnscaledTickValue;
+
+ drawing::Position3D aScenePosition3D( pPosHelper->transformAngleRadiusToScene( fLogicAngle, fLogicRadius, fLogicZ ) );
+ rPoints[0][nTick].X = static_cast<sal_Int32>(aScenePosition3D.PositionX);
+ rPoints[0][nTick].Y = static_cast<sal_Int32>(aScenePosition3D.PositionY);
+ }
+ if(rPoints[0].getLength()>1)
+ {
+ rPoints[0].realloc(nTick+1);
+ rPoints[0][nTick].X = rPoints[0][0].X;
+ rPoints[0][nTick].Y = rPoints[0][0].Y;
+ }
+ 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 = -0.5;//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;
+
+ rTickInfo.updateUnscaledValue( xInverseScaling );
+ double fLogicAngle = rTickInfo.fUnscaledTickValue;
+
+ 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
+ , ::std::vector< ::std::vector< TickInfo > >& rAngleTickInfos
+ , const ::std::vector<VLineProperties>& rLinePropertiesList )
+{
+ Reference< drawing::XShapes > xMainTarget(
+ this->createGroupShape( xLogicTarget, m_aCID ) );
+
+ const ExplicitScaleData& rRadiusScale = m_pPosHelper->getScales()[1];
+ const ExplicitScaleData& rAngleScale = m_pPosHelper->getScales()[0];
+ const ExplicitIncrementData& rAngleIncrement = m_aIncrements[0];
+ Reference< XScaling > xInverseRadiusScaling( NULL );
+ if( rRadiusScale.Scaling.is() )
+ xInverseRadiusScaling = rRadiusScale.Scaling->getInverseScaling();
+
+ sal_Int32 nLinePropertiesCount = rLinePropertiesList.size();
+ ::std::vector< ::std::vector< TickInfo > >::iterator aDepthIter = rRadiusTickInfos.begin();
+ const ::std::vector< ::std::vector< TickInfo > >::const_iterator aDepthEnd = rRadiusTickInfos.end();
+ for( sal_Int32 nDepth=0
+ ; aDepthIter != aDepthEnd && nDepth < nLinePropertiesCount
+ ; aDepthIter++, nDepth++ )
+ {
+ if( !rLinePropertiesList[nDepth].isLineVisible() )
+ continue;
+
+ Reference< drawing::XShapes > xTarget( xMainTarget );
+ if( nDepth > 0 )
+ {
+ xTarget.set( this->createGroupShape( xLogicTarget
+ , ObjectIdentifier::addChildParticle( m_aCID, ObjectIdentifier::createChildParticleWithIndex( OBJECTTYPE_SUBGRID, nDepth-1 ) )
+ ) );
+ if(!xTarget.is())
+ xTarget.set( xMainTarget );
+ }
+
+ //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;
+
+ rTickInfo.updateUnscaledValue( xInverseRadiusScaling );
+ double fLogicRadius = rTickInfo.fUnscaledTickValue;
+ double fLogicZ = -0.5;//as defined
+
+ drawing::PointSequenceSequence aPoints(1);
+ VPolarGrid::createLinePointSequence_ForAngleAxis( aPoints, rAngleTickInfos
+ , rAngleIncrement, rAngleScale, m_pPosHelper, fLogicRadius, fLogicZ );
+ if(aPoints[0].getLength())
+ appendPointSequence( aAllPoints, aPoints );
+ }
+
+ Reference< drawing::XShape > xShape = m_pShapeFactory->createLine2D(
+ xTarget, aAllPoints, &rLinePropertiesList[nDepth] );
+ //because of this name this line will be used for marking
+ m_pShapeFactory->setShapeName( xShape, C2U("MarkHandles") );
+ }
+}
+
+void SAL_CALL 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()))
+ return;
+ if(!m_aGridPropertiesList.getLength())
+ return;
+
+ //-----------------------------------------
+ //create all scaled tickmark values
+ ::std::vector< ::std::vector< TickInfo > > aAngleTickInfos;
+ ::std::vector< ::std::vector< TickInfo > > aRadiusTickInfos;
+ getAllTickInfos( 0, aAngleTickInfos );
+ getAllTickInfos( 1, aRadiusTickInfos );
+
+ //-----------------------------------------
+ ::std::vector<VLineProperties> aLinePropertiesList;
+ VCartesianGrid::fillLinePropertiesFromGridModel( aLinePropertiesList, m_aGridPropertiesList );
+
+ //-----------------------------------------
+ //create tick mark line shapes
+ if(2==m_nDimension)
+ {
+ if(m_nDimensionIndex==1)
+ this->create2DRadiusGrid( m_xLogicTarget, aRadiusTickInfos, aAngleTickInfos, aLinePropertiesList );
+ //else //no Angle Grid so far as this equals exactly the y axis positions
+ // this->create2DAngleGrid( m_xLogicTarget, aRadiusTickInfos, aAngleTickInfos, aLinePropertiesList );
+ }
+}
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
diff --git a/chart2/source/view/axes/VPolarGrid.hxx b/chart2/source/view/axes/VPolarGrid.hxx
new file mode 100644
index 000000000000..74cd7fac27ed
--- /dev/null
+++ b/chart2/source/view/axes/VPolarGrid.hxx
@@ -0,0 +1,99 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: VPolarGrid.hxx,v $
+ * $Revision: 1.5.44.1 $
+ *
+ * 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_VPOLARGRID_HXX
+#define _CHART2_VPOLARGRID_HXX
+
+#include "VAxisOrGridBase.hxx"
+#include "TickmarkHelper.hxx"
+#include "VLineProperties.hxx"
+#include <com/sun/star/drawing/PointSequenceSequence.hpp>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+
+//-----------------------------------------------------------------------------
+/**
+*/
+class PolarPlottingPositionHelper;
+
+class VPolarGrid : public VAxisOrGridBase
+{
+//-------------------------------------------------------------------------
+// public methods
+//-------------------------------------------------------------------------
+public:
+ VPolarGrid( sal_Int32 nDimensionIndex, sal_Int32 nDimensionCount
+ , const ::com::sun::star::uno::Sequence<
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::beans::XPropertySet > > & rGridPropertiesList //main grid, subgrid, subsubgrid etc
+ );
+ virtual ~VPolarGrid();
+
+ virtual void SAL_CALL createShapes();
+
+ void setIncrements( const ::com::sun::star::uno::Sequence<
+ ::com::sun::star::chart2::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
+ , PolarPlottingPositionHelper* pPosHelper
+ , double fLogicRadius, double fLogicZ );
+
+private: //member
+ ::com::sun::star::uno::Sequence<
+ ::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;
+
+ void getAllTickInfos( sal_Int32 nDimensionIndex, ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ) const;
+
+ void create2DRadiusGrid( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& xLogicTarget
+ , ::std::vector< ::std::vector< TickInfo > >& rRadiusTickInfos
+ , ::std::vector< ::std::vector< TickInfo > >& rAngleTickInfos
+ , const ::std::vector<VLineProperties>& rLinePropertiesList );
+#if NOTYET
+ void create2DAngleGrid( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& xLogicTarget
+ , ::std::vector< ::std::vector< TickInfo > >& rRadiusTickInfos
+ , ::std::vector< ::std::vector< TickInfo > >& rAngleTickInfos
+ , const ::std::vector<VLineProperties>& rLinePropertiesList );
+#endif
+};
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
+#endif
diff --git a/chart2/source/view/axes/VPolarRadiusAxis.cxx b/chart2/source/view/axes/VPolarRadiusAxis.cxx
new file mode 100644
index 000000000000..2b3fdf5c327c
--- /dev/null
+++ b/chart2/source/view/axes/VPolarRadiusAxis.cxx
@@ -0,0 +1,190 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: VPolarRadiusAxis.cxx,v $
+ * $Revision: 1.3 $
+ *
+ * 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 "VPolarRadiusAxis.hxx"
+#include "VCartesianAxis.hxx"
+#include "PlottingPositionHelper.hxx"
+#include "CommonConverters.hxx"
+#include <rtl/math.hxx>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+using namespace ::rtl::math;
+
+VPolarRadiusAxis::VPolarRadiusAxis( const AxisProperties& rAxisProperties
+ , const uno::Reference< util::XNumberFormatsSupplier >& xNumberFormatsSupplier
+ , sal_Int32 nDimensionCount )
+ : VPolarAxis( rAxisProperties, xNumberFormatsSupplier, 1/*nDimensionIndex*/, nDimensionCount )
+{
+ m_aAxisProperties.m_fLabelDirectionSign=0.0;
+ m_aAxisProperties.m_fInnerDirectionSign=0.0;
+ m_aAxisProperties.m_bLabelsOutside=true;
+ m_aAxisProperties.m_bIsMainAxis=false;
+ m_aAxisProperties.m_aLabelAlignment=LABEL_ALIGN_RIGHT;
+ m_aAxisProperties.init();
+
+ m_apAxisWithLabels = std::auto_ptr<VCartesianAxis>( new VCartesianAxis(
+ m_aAxisProperties,xNumberFormatsSupplier,1/*nDimensionIndex*/,nDimensionCount
+ ,new PolarPlottingPositionHelper() ) );
+}
+
+VPolarRadiusAxis::~VPolarRadiusAxis()
+{
+ delete m_pPosHelper;
+ m_pPosHelper = NULL;
+}
+
+void VPolarRadiusAxis::setTransformationSceneToScreen( const drawing::HomogenMatrix& rMatrix)
+{
+ VPolarAxis::setTransformationSceneToScreen( rMatrix );
+ m_apAxisWithLabels->setTransformationSceneToScreen( rMatrix );
+}
+
+void SAL_CALL VPolarRadiusAxis::setExplicitScaleAndIncrement(
+ const ExplicitScaleData& rScale
+ , const ExplicitIncrementData& rIncrement )
+ throw (uno::RuntimeException)
+{
+ VPolarAxis::setExplicitScaleAndIncrement( rScale, rIncrement );
+ m_apAxisWithLabels->setExplicitScaleAndIncrement( rScale, rIncrement );
+}
+
+void SAL_CALL VPolarRadiusAxis::initPlotter( const uno::Reference< drawing::XShapes >& xLogicTarget
+ , const uno::Reference< drawing::XShapes >& xFinalTarget
+ , const uno::Reference< lang::XMultiServiceFactory >& xShapeFactory
+ , const rtl::OUString& rCID )
+ throw (uno::RuntimeException)
+{
+ VPolarAxis::initPlotter( xLogicTarget, xFinalTarget, xShapeFactory, rCID );
+ m_apAxisWithLabels->initPlotter( xLogicTarget, xFinalTarget, xShapeFactory, rCID );
+}
+
+void SAL_CALL VPolarRadiusAxis::setScales( const uno::Sequence< ExplicitScaleData >& rScales
+ , sal_Bool bSwapXAndYAxis )
+ throw (uno::RuntimeException)
+{
+ VPolarAxis::setScales( rScales, bSwapXAndYAxis );
+ m_apAxisWithLabels->setScales( rScales, bSwapXAndYAxis );
+}
+
+void SAL_CALL VPolarRadiusAxis::initAxisLabelProperties( const ::com::sun::star::awt::Size& rFontReferenceSize
+ , const ::com::sun::star::awt::Rectangle& rMaximumSpaceForLabels )
+{
+ VPolarAxis::initAxisLabelProperties( rFontReferenceSize, rMaximumSpaceForLabels );
+ m_apAxisWithLabels->initAxisLabelProperties( rFontReferenceSize, rMaximumSpaceForLabels );
+}
+
+sal_Int32 VPolarRadiusAxis::estimateMaximumAutoMainIncrementCount()
+{
+ return 2;
+}
+
+bool VPolarRadiusAxis::prepareShapeCreation()
+{
+ //returns true if all is ready for further shape creation and any shapes need to be created
+ if( !isAnythingToDraw() )
+ return false;
+
+ if( m_xGroupShape_Shapes.is() )
+ return true;
+
+ return true;
+}
+
+void SAL_CALL VPolarRadiusAxis::createMaximumLabels()
+{
+ m_apAxisWithLabels->createMaximumLabels();
+}
+
+void SAL_CALL VPolarRadiusAxis::updatePositions()
+{
+ m_apAxisWithLabels->updatePositions();
+}
+
+void SAL_CALL VPolarRadiusAxis::createLabels()
+{
+ m_apAxisWithLabels->createLabels();
+}
+
+void SAL_CALL VPolarRadiusAxis::createShapes()
+{
+ if( !prepareShapeCreation() )
+ return;
+
+ const ExplicitScaleData& rAngleScale = m_pPosHelper->getScales()[0];
+ const ExplicitIncrementData& rAngleIncrement = m_aIncrements[0];
+
+ ::std::vector< ::std::vector< TickInfo > > aAngleTickInfos;
+ TickmarkHelper aAngleTickmarkHelper( rAngleScale, rAngleIncrement );
+ aAngleTickmarkHelper.getAllTicks( aAngleTickInfos );
+
+ uno::Reference< XScaling > xInverseScaling( NULL );
+ if( rAngleScale.Scaling.is() )
+ xInverseScaling = rAngleScale.Scaling->getInverseScaling();
+
+ AxisProperties aAxisProperties(m_aAxisProperties);
+
+ sal_Int32 nTick = 0;
+ TickIter aIter( aAngleTickInfos, rAngleIncrement, 0, 0 );
+ for( TickInfo* pTickInfo = aIter.firstInfo()
+ ; pTickInfo; pTickInfo = aIter.nextInfo(), nTick++ )
+ {
+ if( nTick == 0 )
+ {
+ m_apAxisWithLabels->createShapes();
+ continue;
+ }
+
+ pTickInfo->updateUnscaledValue( xInverseScaling );
+ aAxisProperties.m_pfMainLinePositionAtOtherAxis = new double( pTickInfo->fUnscaledTickValue );
+ aAxisProperties.m_bDisplayLabels=false;
+
+ //-------------------
+ VCartesianAxis aAxis(aAxisProperties,m_xNumberFormatsSupplier
+ ,1,2,new PolarPlottingPositionHelper());
+ aAxis.setExplicitScaleAndIncrement( m_aScale, m_aIncrement );
+ aAxis.initPlotter(m_xLogicTarget,m_xFinalTarget,m_xShapeFactory, m_aCID );
+ aAxis.setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix( m_aMatrixScreenToScene ) );
+ aAxis.setScales( m_pPosHelper->getScales(), false );
+ aAxis.initAxisLabelProperties(m_aAxisLabelProperties.m_aFontReferenceSize,m_aAxisLabelProperties.m_aMaximumSpaceForLabels);
+ aAxis.createShapes();
+ }
+}
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
diff --git a/chart2/source/view/axes/VPolarRadiusAxis.hxx b/chart2/source/view/axes/VPolarRadiusAxis.hxx
new file mode 100644
index 000000000000..7d68f64e6b5b
--- /dev/null
+++ b/chart2/source/view/axes/VPolarRadiusAxis.hxx
@@ -0,0 +1,101 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: VPolarRadiusAxis.hxx,v $
+ * $Revision: 1.3 $
+ *
+ * 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_VPOLARRADIUSAXIS_HXX
+#define _CHART2_VPOLARRADIUSAXIS_HXX
+
+#include "VPolarAxis.hxx"
+
+#include <memory>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+
+//-----------------------------------------------------------------------------
+/**
+*/
+
+class VCartesianAxis;
+
+class VPolarRadiusAxis : public VPolarAxis
+{
+public:
+ VPolarRadiusAxis( const AxisProperties& rAxisProperties
+ , const ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier >& xNumberFormatsSupplier
+ , sal_Int32 nDimensionCount );
+ virtual ~VPolarRadiusAxis();
+
+ virtual void SAL_CALL initPlotter(
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShapes >& xLogicTarget
+ , const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShapes >& xFinalTarget
+ , const ::com::sun::star::uno::Reference<
+ ::com::sun::star::lang::XMultiServiceFactory >& xFactory
+ , const rtl::OUString& rCID
+ ) throw (::com::sun::star::uno::RuntimeException );
+
+ 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 SAL_CALL setExplicitScaleAndIncrement(
+ const ::com::sun::star::chart2::ExplicitScaleData& rScale
+ , const ::com::sun::star::chart2::ExplicitIncrementData& rIncrement )
+ throw (::com::sun::star::uno::RuntimeException);
+
+ virtual void SAL_CALL 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 SAL_CALL createShapes();
+
+protected: //methods
+ virtual bool prepareShapeCreation();
+
+private: //member
+ std::auto_ptr<VCartesianAxis> m_apAxisWithLabels;
+};
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
+#endif
diff --git a/chart2/source/view/axes/makefile.mk b/chart2/source/view/axes/makefile.mk
new file mode 100644
index 000000000000..52996a78c8cd
--- /dev/null
+++ b/chart2/source/view/axes/makefile.mk
@@ -0,0 +1,70 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2008 by Sun Microsystems, Inc.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.5 $
+#
+# 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.
+#
+#*************************************************************************
+
+PRJ= ..$/..$/..
+PRJINC= $(PRJ)$/source
+PRJNAME= chart2
+TARGET= chvaxes
+
+ENABLE_EXCEPTIONS= TRUE
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE: settings.mk
+.INCLUDE: $(PRJ)$/chartview.pmk
+
+#.IF "$(GUI)" == "WNT"
+#CFLAGS+=-GR
+#.ENDIF
+
+# --- export library -------------------------------------------------
+
+#object files to build and link together to lib $(SLB)$/$(TARGET).lib
+SLOFILES = \
+ $(SLO)$/VAxisOrGridBase.obj \
+ $(SLO)$/VAxisBase.obj \
+ $(SLO)$/TickmarkHelper.obj \
+ $(SLO)$/MinimumAndMaximumSupplier.obj \
+ $(SLO)$/ScaleAutomatism.obj \
+ $(SLO)$/VAxisProperties.obj \
+ $(SLO)$/VCartesianAxis.obj \
+ $(SLO)$/VCartesianGrid.obj \
+ $(SLO)$/VCartesianCoordinateSystem.obj \
+ $(SLO)$/VPolarAxis.obj \
+ $(SLO)$/VPolarAngleAxis.obj \
+ $(SLO)$/VPolarRadiusAxis.obj \
+ $(SLO)$/VPolarGrid.obj \
+ $(SLO)$/VPolarCoordinateSystem.obj \
+ $(SLO)$/VCoordinateSystem.obj
+
+# --- Targets -----------------------------------------------------------------
+
+.INCLUDE: target.mk