summaryrefslogtreecommitdiff
path: root/chart2/source/view
diff options
context:
space:
mode:
Diffstat (limited to 'chart2/source/view')
-rw-r--r--chart2/source/view/axes/MinimumAndMaximumSupplier.cxx201
-rw-r--r--chart2/source/view/axes/ScaleAutomatism.cxx760
-rw-r--r--chart2/source/view/axes/TickmarkHelper.cxx937
-rw-r--r--chart2/source/view/axes/TickmarkHelper.hxx276
-rw-r--r--chart2/source/view/axes/TickmarkProperties.hxx53
-rw-r--r--chart2/source/view/axes/VAxisBase.cxx253
-rw-r--r--chart2/source/view/axes/VAxisBase.hxx107
-rw-r--r--chart2/source/view/axes/VAxisOrGridBase.cxx98
-rw-r--r--chart2/source/view/axes/VAxisOrGridBase.hxx83
-rw-r--r--chart2/source/view/axes/VAxisProperties.cxx486
-rw-r--r--chart2/source/view/axes/VAxisProperties.hxx168
-rw-r--r--chart2/source/view/axes/VCartesianAxis.cxx1600
-rw-r--r--chart2/source/view/axes/VCartesianAxis.hxx146
-rw-r--r--chart2/source/view/axes/VCartesianCoordinateSystem.cxx250
-rw-r--r--chart2/source/view/axes/VCartesianCoordinateSystem.hxx64
-rw-r--r--chart2/source/view/axes/VCartesianGrid.cxx339
-rw-r--r--chart2/source/view/axes/VCartesianGrid.hxx71
-rw-r--r--chart2/source/view/axes/VCoordinateSystem.cxx598
-rw-r--r--chart2/source/view/axes/VPolarAngleAxis.cxx234
-rw-r--r--chart2/source/view/axes/VPolarAngleAxis.hxx66
-rw-r--r--chart2/source/view/axes/VPolarAxis.cxx83
-rw-r--r--chart2/source/view/axes/VPolarAxis.hxx71
-rw-r--r--chart2/source/view/axes/VPolarCoordinateSystem.cxx211
-rw-r--r--chart2/source/view/axes/VPolarCoordinateSystem.hxx68
-rw-r--r--chart2/source/view/axes/VPolarGrid.cxx273
-rw-r--r--chart2/source/view/axes/VPolarGrid.hxx96
-rw-r--r--chart2/source/view/axes/VPolarRadiusAxis.cxx186
-rw-r--r--chart2/source/view/axes/VPolarRadiusAxis.hxx98
-rw-r--r--chart2/source/view/axes/makefile.mk66
-rw-r--r--chart2/source/view/charttypes/AreaChart.cxx1005
-rw-r--r--chart2/source/view/charttypes/AreaChart.hxx134
-rwxr-xr-xchart2/source/view/charttypes/BarChart.cxx1019
-rw-r--r--chart2/source/view/charttypes/BarChart.hxx110
-rw-r--r--chart2/source/view/charttypes/BarPositionHelper.cxx138
-rw-r--r--chart2/source/view/charttypes/BarPositionHelper.hxx76
-rw-r--r--chart2/source/view/charttypes/BubbleChart.cxx417
-rw-r--r--chart2/source/view/charttypes/BubbleChart.hxx94
-rw-r--r--chart2/source/view/charttypes/CandleStickChart.cxx398
-rw-r--r--chart2/source/view/charttypes/CandleStickChart.hxx89
-rw-r--r--chart2/source/view/charttypes/CategoryPositionHelper.cxx100
-rw-r--r--chart2/source/view/charttypes/CategoryPositionHelper.hxx68
-rw-r--r--chart2/source/view/charttypes/PieChart.cxx897
-rw-r--r--chart2/source/view/charttypes/PieChart.hxx145
-rw-r--r--chart2/source/view/charttypes/Splines.cxx545
-rw-r--r--chart2/source/view/charttypes/Splines.hxx61
-rw-r--r--chart2/source/view/charttypes/VSeriesPlotter.cxx2110
-rw-r--r--chart2/source/view/charttypes/makefile.mk55
-rw-r--r--chart2/source/view/diagram/VDiagram.cxx811
-rw-r--r--chart2/source/view/diagram/makefile.mk48
-rw-r--r--chart2/source/view/exports.flt4
-rw-r--r--chart2/source/view/inc/Clipping.hxx70
-rw-r--r--chart2/source/view/inc/LabelAlignment.hxx41
-rw-r--r--chart2/source/view/inc/LabelPositionHelper.hxx86
-rw-r--r--chart2/source/view/inc/LegendEntryProvider.hxx63
-rw-r--r--chart2/source/view/inc/Linear3DTransformation.hxx67
-rw-r--r--chart2/source/view/inc/MinimumAndMaximumSupplier.hxx100
-rw-r--r--chart2/source/view/inc/PlotterBase.hxx126
-rw-r--r--chart2/source/view/inc/PlottingPositionHelper.hxx406
-rw-r--r--chart2/source/view/inc/PolarLabelPositionHelper.hxx76
-rw-r--r--chart2/source/view/inc/PropertyMapper.hxx133
-rw-r--r--chart2/source/view/inc/ScaleAutomatism.hxx119
-rw-r--r--chart2/source/view/inc/ShapeFactory.hxx254
-rw-r--r--chart2/source/view/inc/Stripe.hxx89
-rw-r--r--chart2/source/view/inc/VCoordinateSystem.hxx212
-rw-r--r--chart2/source/view/inc/VDataSeries.hxx264
-rw-r--r--chart2/source/view/inc/VDiagram.hxx136
-rw-r--r--chart2/source/view/inc/VLegendSymbolFactory.hxx77
-rw-r--r--chart2/source/view/inc/VLineProperties.hxx61
-rw-r--r--chart2/source/view/inc/VPolarTransformation.hxx67
-rw-r--r--chart2/source/view/inc/VSeriesPlotter.hxx453
-rw-r--r--chart2/source/view/inc/ViewDefines.hxx47
-rw-r--r--chart2/source/view/main/ChartItemPool.cxx258
-rw-r--r--chart2/source/view/main/ChartItemPool.hxx58
-rw-r--r--chart2/source/view/main/ChartView.cxx3187
-rw-r--r--chart2/source/view/main/ChartView.hxx261
-rw-r--r--chart2/source/view/main/Clipping.cxx304
-rw-r--r--chart2/source/view/main/DataPointSymbolSupplier.cxx66
-rw-r--r--chart2/source/view/main/DrawModelWrapper.cxx411
-rw-r--r--chart2/source/view/main/LabelPositionHelper.cxx488
-rw-r--r--chart2/source/view/main/Linear3DTransformation.cxx107
-rw-r--r--chart2/source/view/main/NumberFormatterWrapper.cxx169
-rw-r--r--chart2/source/view/main/PlotterBase.cxx135
-rw-r--r--chart2/source/view/main/PlottingPositionHelper.cxx667
-rw-r--r--chart2/source/view/main/PolarLabelPositionHelper.cxx188
-rw-r--r--chart2/source/view/main/PropertyMapper.cxx539
-rw-r--r--chart2/source/view/main/ShapeFactory.cxx2111
-rw-r--r--chart2/source/view/main/Stripe.cxx360
-rw-r--r--chart2/source/view/main/VDataSeries.cxx986
-rw-r--r--chart2/source/view/main/VLegend.cxx834
-rw-r--r--chart2/source/view/main/VLegend.hxx111
-rw-r--r--chart2/source/view/main/VLegendSymbolFactory.cxx374
-rw-r--r--chart2/source/view/main/VLineProperties.cxx109
-rw-r--r--chart2/source/view/main/VPolarTransformation.cxx94
-rw-r--r--chart2/source/view/main/VTitle.cxx299
-rw-r--r--chart2/source/view/main/VTitle.hxx83
-rw-r--r--chart2/source/view/main/_serviceregistration_view.cxx71
-rw-r--r--chart2/source/view/main/makefile.mk68
-rw-r--r--chart2/source/view/makefile.mk120
98 files changed, 31671 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..88f99b493144
--- /dev/null
+++ b/chart2/source/view/axes/MinimumAndMaximumSupplier.cxx
@@ -0,0 +1,201 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_chart2.hxx"
+
+#include "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..890bf87df96e
--- /dev/null
+++ b/chart2/source/view/axes/ScaleAutomatism.cxx
@@ -0,0 +1,760 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_chart2.hxx"
+#include "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 = 9;
+ }
+ 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..9e2e2707c035
--- /dev/null
+++ b/chart2/source/view/axes/TickmarkHelper.cxx
@@ -0,0 +1,937 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_chart2.hxx"
+#include "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 )
+, nFactorForLimitedTextWidth(1)
+{
+}
+
+void TickInfo::updateUnscaledValue( const uno::Reference< XScaling >& xInverseScaling )
+{
+ if( xInverseScaling.is() )
+ this->fUnscaledTickValue = xInverseScaling->doScaling( this->fScaledTickValue );
+ else
+ this->fUnscaledTickValue = this->fScaledTickValue;
+}
+
+sal_Int32 TickInfo::getScreenDistanceBetweenTicks( const TickInfo& rOherTickInfo ) const
+{
+ //return the positive distance between the two first tickmarks in screen values
+
+ B2DVector aDistance = rOherTickInfo.aTickScreenPosition - aTickScreenPosition;
+ sal_Int32 nRet = static_cast<sal_Int32>(aDistance.getLength());
+ if(nRet<0)
+ nRet *= -1;
+ return nRet;
+}
+
+PureTickIter::PureTickIter( ::std::vector< TickInfo >& rTickInfoVector )
+ : m_rTickVector(rTickInfoVector)
+ , m_aTickIter(m_rTickVector.begin())
+{
+}
+PureTickIter::~PureTickIter()
+{
+}
+TickInfo* PureTickIter::firstInfo()
+{
+ m_aTickIter = m_rTickVector.begin();
+ if(m_aTickIter!=m_rTickVector.end())
+ return &*m_aTickIter;
+ return 0;
+}
+TickInfo* PureTickIter::nextInfo()
+{
+ m_aTickIter++;
+ if(m_aTickIter!=m_rTickVector.end())
+ return &*m_aTickIter;
+ return 0;
+}
+
+EquidistantTickIter::EquidistantTickIter( const uno::Sequence< uno::Sequence< double > >& rTicks
+ , const ExplicitIncrementData& rIncrement
+ , sal_Int32 nMinDepth, sal_Int32 nMaxDepth )
+ : m_pSimpleTicks(&rTicks)
+ , m_pInfoTicks(0)
+ , m_rIncrement(rIncrement)
+ , m_nMinDepth(0), m_nMaxDepth(0)
+ , m_nTickCount(0), m_pnPositions(NULL)
+ , m_pnPreParentCount(NULL), m_pbIntervalFinished(NULL)
+ , m_nCurrentDepth(-1), m_nCurrentPos(-1), m_fCurrentValue( 0.0 )
+{
+ initIter( nMinDepth, nMaxDepth );
+}
+
+EquidistantTickIter::EquidistantTickIter( ::std::vector< ::std::vector< TickInfo > >& rTicks
+ , const ExplicitIncrementData& rIncrement
+ , sal_Int32 nMinDepth, sal_Int32 nMaxDepth )
+ : m_pSimpleTicks(NULL)
+ , m_pInfoTicks(&rTicks)
+ , m_rIncrement(rIncrement)
+ , m_nMinDepth(0), m_nMaxDepth(0)
+ , m_nTickCount(0), m_pnPositions(NULL)
+ , m_pnPreParentCount(NULL), m_pbIntervalFinished(NULL)
+ , m_nCurrentDepth(-1), m_nCurrentPos(-1), m_fCurrentValue( 0.0 )
+{
+ initIter( nMinDepth, nMaxDepth );
+}
+
+void EquidistantTickIter::initIter( sal_Int32 /*nMinDepth*/, sal_Int32 nMaxDepth )
+{
+ m_nMaxDepth = nMaxDepth;
+ if(nMaxDepth<0 || m_nMaxDepth>getMaxDepth())
+ m_nMaxDepth=getMaxDepth();
+
+ sal_Int32 nDepth = 0;
+ for( nDepth = 0; nDepth<=m_nMaxDepth ;nDepth++ )
+ m_nTickCount += getTickCount(nDepth);
+
+ if(!m_nTickCount)
+ return;
+
+ m_pnPositions = new sal_Int32[m_nMaxDepth+1];
+
+ m_pnPreParentCount = new sal_Int32[m_nMaxDepth+1];
+ m_pbIntervalFinished = new bool[m_nMaxDepth+1];
+ m_pnPreParentCount[0] = 0;
+ m_pbIntervalFinished[0] = false;
+ double fParentValue = getTickValue(0,0);
+ for( nDepth = 1; nDepth<=m_nMaxDepth ;nDepth++ )
+ {
+ m_pbIntervalFinished[nDepth] = false;
+
+ sal_Int32 nPreParentCount = 0;
+ sal_Int32 nCount = getTickCount(nDepth);
+ for(sal_Int32 nN = 0; nN<nCount; nN++)
+ {
+ if(getTickValue(nDepth,nN) < fParentValue)
+ nPreParentCount++;
+ else
+ break;
+ }
+ m_pnPreParentCount[nDepth] = nPreParentCount;
+ if(nCount)
+ {
+ double fNextParentValue = getTickValue(nDepth,0);
+ if( fNextParentValue < fParentValue )
+ fParentValue = fNextParentValue;
+ }
+ }
+}
+
+EquidistantTickIter::~EquidistantTickIter()
+{
+ delete[] m_pnPositions;
+ delete[] m_pnPreParentCount;
+ delete[] m_pbIntervalFinished;
+}
+
+sal_Int32 EquidistantTickIter::getStartDepth() const
+{
+ //find the depth of the first visible tickmark:
+ //it is the depth of the smallest value
+ sal_Int32 nReturnDepth=0;
+ double fMinValue = DBL_MAX;
+ for(sal_Int32 nDepth = 0; nDepth<=m_nMaxDepth ;nDepth++ )
+ {
+ sal_Int32 nCount = getTickCount(nDepth);
+ if( !nCount )
+ continue;
+ double fThisValue = getTickValue(nDepth,0);
+ if(fThisValue<fMinValue)
+ {
+ nReturnDepth = nDepth;
+ fMinValue = fThisValue;
+ }
+ }
+ return nReturnDepth;
+}
+
+double* EquidistantTickIter::firstValue()
+{
+ if( gotoFirst() )
+ {
+ m_fCurrentValue = getTickValue(m_nCurrentDepth, m_pnPositions[m_nCurrentDepth]);
+ return &m_fCurrentValue;
+ }
+ return NULL;
+}
+
+TickInfo* EquidistantTickIter::firstInfo()
+{
+ if( m_pInfoTicks && gotoFirst() )
+ return &(*m_pInfoTicks)[m_nCurrentDepth][m_pnPositions[m_nCurrentDepth]];
+ return NULL;
+}
+
+sal_Int32 EquidistantTickIter::getIntervalCount( sal_Int32 nDepth )
+{
+ if(nDepth>m_rIncrement.SubIncrements.getLength() || nDepth<0)
+ return 0;
+
+ if(!nDepth)
+ return m_nTickCount;
+
+ return m_rIncrement.SubIncrements[nDepth-1].IntervalCount;
+}
+
+bool EquidistantTickIter::isAtLastPartTick()
+{
+ if(!m_nCurrentDepth)
+ return false;
+ sal_Int32 nIntervalCount = getIntervalCount( m_nCurrentDepth );
+ if(!nIntervalCount || nIntervalCount == 1)
+ return true;
+ if( m_pbIntervalFinished[m_nCurrentDepth] )
+ return false;
+ sal_Int32 nPos = m_pnPositions[m_nCurrentDepth]+1;
+ if(m_pnPreParentCount[m_nCurrentDepth])
+ nPos += nIntervalCount-1 - m_pnPreParentCount[m_nCurrentDepth];
+ bool bRet = nPos && nPos % (nIntervalCount-1) == 0;
+ if(!nPos && !m_pnPreParentCount[m_nCurrentDepth]
+ && m_pnPositions[m_nCurrentDepth-1]==-1 )
+ bRet = true;
+ return bRet;
+}
+
+bool EquidistantTickIter::gotoFirst()
+{
+ if( m_nMaxDepth<0 )
+ return false;
+ if( !m_nTickCount )
+ return false;
+
+ for(sal_Int32 nDepth = 0; nDepth<=m_nMaxDepth ;nDepth++ )
+ m_pnPositions[nDepth] = -1;
+
+ m_nCurrentPos = 0;
+ m_nCurrentDepth = getStartDepth();
+ m_pnPositions[m_nCurrentDepth] = 0;
+ return true;
+}
+
+bool EquidistantTickIter::gotoNext()
+{
+ if( m_nCurrentPos < 0 )
+ return false;
+ m_nCurrentPos++;
+
+ if( m_nCurrentPos >= m_nTickCount )
+ return false;
+
+ if( m_nCurrentDepth==m_nMaxDepth && isAtLastPartTick() )
+ {
+ do
+ {
+ m_pbIntervalFinished[m_nCurrentDepth] = true;
+ m_nCurrentDepth--;
+ }
+ while( m_nCurrentDepth && isAtLastPartTick() );
+ }
+ else if( m_nCurrentDepth<m_nMaxDepth )
+ {
+ do
+ {
+ m_nCurrentDepth++;
+ }
+ while( m_nCurrentDepth<m_nMaxDepth );
+ }
+ m_pbIntervalFinished[m_nCurrentDepth] = false;
+ m_pnPositions[m_nCurrentDepth] = m_pnPositions[m_nCurrentDepth]+1;
+ return true;
+}
+
+bool EquidistantTickIter::gotoIndex( sal_Int32 nTickIndex )
+{
+ if( nTickIndex < 0 )
+ return false;
+ if( nTickIndex >= m_nTickCount )
+ return false;
+
+ if( nTickIndex < m_nCurrentPos )
+ if( !gotoFirst() )
+ return false;
+
+ while( nTickIndex > m_nCurrentPos )
+ if( !gotoNext() )
+ return false;
+
+ return true;
+}
+
+sal_Int32 EquidistantTickIter::getCurrentIndex() const
+{
+ return m_nCurrentPos;
+}
+sal_Int32 EquidistantTickIter::getMaxIndex() const
+{
+ return m_nTickCount-1;
+}
+
+double* EquidistantTickIter::nextValue()
+{
+ if( gotoNext() )
+ {
+ m_fCurrentValue = getTickValue(m_nCurrentDepth, m_pnPositions[m_nCurrentDepth]);
+ return &m_fCurrentValue;
+ }
+ return NULL;
+}
+
+TickInfo* EquidistantTickIter::nextInfo()
+{
+ if( m_pInfoTicks && gotoNext() &&
+ static_cast< sal_Int32 >(
+ (*m_pInfoTicks)[m_nCurrentDepth].size()) > m_pnPositions[m_nCurrentDepth] )
+ {
+ return &(*m_pInfoTicks)[m_nCurrentDepth][m_pnPositions[m_nCurrentDepth]];
+ }
+ return NULL;
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+//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;
+
+ double fSub;
+ if(m_rIncrement.PostEquidistant )
+ fSub = approxSub( m_fScaledVisibleMax, m_fScaledVisibleMin );
+ else
+ fSub = approxSub( m_rScale.Maximum, m_rScale.Minimum );
+
+ if (!isFinite(fSub))
+ return 0;
+
+ sal_Int32 nIntervalCount = static_cast<sal_Int32>( fSub / m_rIncrement.Distance );
+
+ nIntervalCount+=3;
+ for(sal_Int32 nN=0; nN<nDepth-1; nN++)
+ {
+ if( m_rIncrement.SubIncrements[nN].IntervalCount>1 )
+ nIntervalCount *= m_rIncrement.SubIncrements[nN].IntervalCount;
+ }
+
+ sal_Int32 nTickCount = nIntervalCount;
+ if(nDepth>0 && m_rIncrement.SubIncrements[nDepth-1].IntervalCount>1)
+ nTickCount = nIntervalCount * (m_rIncrement.SubIncrements[nDepth-1].IntervalCount-1);
+
+ return nTickCount;
+}
+
+double* 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
+{
+ EquidistantTickIter aIter( rParentTicks, m_rIncrement, 0, nDepth-1 );
+ double* pfNextParentTick = aIter.firstValue();
+ if(!pfNextParentTick)
+ return;
+ double fLastParentTick = *pfNextParentTick;
+ pfNextParentTick = aIter.nextValue();
+ if(!pfNextParentTick)
+ return;
+
+ sal_Int32 nMaxSubTickCount = this->getMaxTickCount( nDepth );
+ if(!nMaxSubTickCount)
+ return;
+
+ uno::Sequence< double > aSubTicks(nMaxSubTickCount);
+ sal_Int32 nRealSubTickCount = 0;
+ sal_Int32 nIntervalCount = m_rIncrement.SubIncrements[nDepth-1].IntervalCount;
+
+ double* pValue = NULL;
+ for(; pfNextParentTick; fLastParentTick=*pfNextParentTick, pfNextParentTick = aIter.nextValue())
+ {
+ for( sal_Int32 nPartTick = 1; nPartTick<nIntervalCount; nPartTick++ )
+ {
+ pValue = this->getMinorTick( nPartTick, nDepth
+ , fLastParentTick, *pfNextParentTick );
+ if(!pValue)
+ continue;
+
+ aSubTicks[nRealSubTickCount] = *pValue;
+ nRealSubTickCount++;
+ }
+ }
+
+ aSubTicks.realloc(nRealSubTickCount);
+ rParentTicks[nDepth] = aSubTicks;
+ if(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;
+
+ return pFirstTickInfo->getScreenDistanceBetweenTicks( *pSecondTickInfo );
+}
+
+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, bool bIncludeFarAwayDistanceIfSo, bool bIncludeSpaceBetweenTickAndText ) const
+{
+ bool bFarAwayLabels = false;
+ if( ::com::sun::star::chart::ChartAxisLabelPosition_OUTSIDE_START == rAxisProperties.m_eLabelPos
+ || ::com::sun::star::chart::ChartAxisLabelPosition_OUTSIDE_END == rAxisProperties.m_eLabelPos )
+ bFarAwayLabels = true;
+
+ double fInnerDirectionSign = rAxisProperties.m_fInnerDirectionSign;
+ if( fInnerDirectionSign==0.0 )
+ fInnerDirectionSign = 1.0;
+
+ B2DVector aMainDirection = m_aAxisEndScreenPosition2D-m_aAxisStartScreenPosition2D;
+ aMainDirection.normalize();
+ B2DVector aOrthoDirection(-aMainDirection.getY(),aMainDirection.getX());
+ aOrthoDirection *= fInnerDirectionSign;
+ aOrthoDirection.normalize();
+
+ B2DVector aStart(0,0), aEnd(0,0);
+ if( bFarAwayLabels )
+ {
+ TickmarkProperties aProps( AxisProperties::getBiggestTickmarkProperties() );
+ aStart = aOrthoDirection*aProps.RelativePos;
+ aEnd = aStart - aOrthoDirection*aProps.Length;
+ }
+ else
+ {
+ for( sal_Int32 nN=rAxisProperties.m_aTickmarkPropertiesList.size();nN--;)
+ {
+ const TickmarkProperties& rProps = rAxisProperties.m_aTickmarkPropertiesList[nN];
+ B2DVector aNewStart = aOrthoDirection*rProps.RelativePos;
+ B2DVector aNewEnd = aNewStart - aOrthoDirection*rProps.Length;
+ if(aNewStart.getLength()>aStart.getLength())
+ aStart=aNewStart;
+ if(aNewEnd.getLength()>aEnd.getLength())
+ aEnd=aNewEnd;
+ }
+ }
+
+ B2DVector aLabelDirection(aStart);
+ if( rAxisProperties.m_fInnerDirectionSign != rAxisProperties.m_fLabelDirectionSign )
+ aLabelDirection = aEnd;
+
+ B2DVector aOrthoLabelDirection(aOrthoDirection);
+ if( rAxisProperties.m_fInnerDirectionSign != rAxisProperties.m_fLabelDirectionSign )
+ aOrthoLabelDirection*=-1.0;
+ aOrthoLabelDirection.normalize();
+ if( bIncludeSpaceBetweenTickAndText )
+ aLabelDirection += aOrthoLabelDirection*AXIS2D_TICKLABELSPACING;
+ if( bFarAwayLabels && bIncludeFarAwayDistanceIfSo )
+ aLabelDirection += m_aAxisLineToLabelLineShift;
+ return aLabelDirection;
+}
+
+void 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 );
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// ___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..78fc2fe1c502
--- /dev/null
+++ b/chart2/source/view/axes/TickmarkHelper.hxx
@@ -0,0 +1,276 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _CHART2_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;
+
+ rtl::OUString aText;//used only for complex categories so far
+ sal_Int32 nFactorForLimitedTextWidth;//categories in higher levels of complex categories can have more place than a single simple category
+
+//methods:
+ TickInfo();
+ void updateUnscaledValue( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::chart2::XScaling >& xInverseScaling );
+
+ sal_Int32 getScreenDistanceBetweenTicks( const TickInfo& rOherTickInfo ) const;
+};
+class TickIter
+{
+public:
+ virtual ~TickIter(){};
+ virtual TickInfo* firstInfo()=0;
+ virtual TickInfo* nextInfo()=0;
+};
+
+class PureTickIter : public TickIter
+{
+public:
+ PureTickIter( ::std::vector< TickInfo >& rTickInfoVector );
+ virtual ~PureTickIter();
+ virtual TickInfo* firstInfo();
+ virtual TickInfo* nextInfo();
+
+private:
+ ::std::vector< TickInfo >& m_rTickVector;
+ ::std::vector< TickInfo >::iterator m_aTickIter;
+};
+
+class EquidistantTickIter : public TickIter
+{
+public:
+ EquidistantTickIter( const ::com::sun::star::uno::Sequence<
+ ::com::sun::star::uno::Sequence< double > >& rTicks
+ , const ::com::sun::star::chart2::ExplicitIncrementData& rIncrement
+ , sal_Int32 nMinDepth=0, sal_Int32 nMaxDepth=-1 );
+ EquidistantTickIter( ::std::vector< ::std::vector< TickInfo > >& rTickInfos
+ , const ::com::sun::star::chart2::ExplicitIncrementData& rIncrement
+ , sal_Int32 nMinDepth=0, sal_Int32 nMaxDepth=-1 );
+ virtual ~EquidistantTickIter();
+
+ 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 {}
+
+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
+ , bool bIncludeFarAwayDistanceIfSo = false
+ , bool bIncludeSpaceBetweenTickAndText = true ) const;
+
+ virtual void updateScreenValues( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ) const;
+
+ bool isHorizontalAxis() const;
+ bool isVerticalAxis() const;
+
+protected: //methods
+ ::basegfx::B2DVector getTickScreenPosition2D( double fScaledLogicTickValue ) const;
+
+private: //member
+ ::basegfx::B2DVector m_aAxisStartScreenPosition2D;
+ ::basegfx::B2DVector m_aAxisEndScreenPosition2D;
+
+ //labels might be posioned high or low on the border of the diagram far away from the axis
+ //add this vector to go from the axis line to the label line (border of the diagram)
+ ::basegfx::B2DVector m_aAxisLineToLabelLineShift;
+
+ double m_fStrech_LogicToScreen;
+ double m_fOffset_LogicToScreen;
+};
+
+class TickmarkHelper_3D : public TickmarkHelper
+{
+public:
+ TickmarkHelper_3D(
+ const ::com::sun::star::chart2::ExplicitScaleData& rScale
+ , const ::com::sun::star::chart2::ExplicitIncrementData& rIncrement );
+ virtual ~TickmarkHelper_3D();
+
+ virtual TickmarkHelper* createShiftedTickmarkHelper() const;
+};
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
+#endif
diff --git a/chart2/source/view/axes/TickmarkProperties.hxx b/chart2/source/view/axes/TickmarkProperties.hxx
new file mode 100644
index 000000000000..09c0179d3698
--- /dev/null
+++ b/chart2/source/view/axes/TickmarkProperties.hxx
@@ -0,0 +1,53 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CHART2_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..0159fb20cad6
--- /dev/null
+++ b/chart2/source/view/axes/VAxisBase.cxx
@@ -0,0 +1,253 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_chart2.hxx"
+
+#include "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::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 )
+ {
+ //don't show a single series name
+ m_aAxisProperties.m_bDisplayLabels = false;
+ return;
+ }
+ }
+ else if( AxisType::CATEGORY==m_aAxisProperties.m_nAxisType )
+ {
+ if( m_aAxisProperties.m_pExplicitCategoriesProvider )
+ m_aTextLabels = m_aAxisProperties.m_pExplicitCategoriesProvider->getSimpleCategories();
+
+ m_bUseTextLabels = true;
+ }
+
+ m_aAxisLabelProperties.nNumberFormatKey = m_aAxisProperties.m_nNumberFormatKey;
+ m_aAxisLabelProperties.init(m_aAxisProperties.m_xAxisModel);
+ if( m_aAxisProperties.m_bComplexCategories && AxisType::CATEGORY == m_aAxisProperties.m_nAxisType )
+ m_aAxisLabelProperties.eStaggering = SIDE_BY_SIDE;
+}
+
+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;
+}
+
+void VAxisBase::createAllTickInfos( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos )
+{
+ std::auto_ptr< TickmarkHelper > apTickmarkHelper( this->createTickmarkHelper() );
+ apTickmarkHelper->getAllTicks( rAllTickInfos );
+}
+
+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
+ removeTextShapesFromTicks();
+
+ createAllTickInfos(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()
+{
+ if( m_xTextTarget.is() )
+ {
+ ::std::vector< ::std::vector< TickInfo > >::iterator aDepthIter = m_aAllTickInfos.begin();
+ const ::std::vector< ::std::vector< TickInfo > >::const_iterator aDepthEnd = m_aAllTickInfos.end();
+ for( ; aDepthIter != aDepthEnd; aDepthIter++ )
+ {
+ ::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.xTextShape.is())
+ {
+ m_xTextTarget->remove(rTickInfo.xTextShape);
+ rTickInfo.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..ba7e94b2070c
--- /dev/null
+++ b/chart2/source/view/axes/VAxisBase.hxx
@@ -0,0 +1,107 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _CHART2_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();
+ virtual void createAllTickInfos( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos );
+
+ void setExrtaLinePositionAtOtherAxis( const double& fCrossingAt );
+
+ //-------------------------------------------------------------------------
+ //-------------------------------------------------------------------------
+protected: //methods
+ sal_Int32 getIndexOfLongestLabel( const ::com::sun::star::uno::Sequence< rtl::OUString >& rLabels );
+ void removeTextShapesFromTicks();
+ 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..f2e2e90c1045
--- /dev/null
+++ b/chart2/source/view/axes/VAxisOrGridBase.cxx
@@ -0,0 +1,98 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_chart2.hxx"
+
+#include "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..35b32b2b1c03
--- /dev/null
+++ b/chart2/source/view/axes/VAxisOrGridBase.hxx
@@ -0,0 +1,83 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _CHART2_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..1e3e62894741
--- /dev/null
+++ b/chart2/source/view/axes/VAxisProperties.cxx
@@ -0,0 +1,486 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_chart2.hxx"
+#include "VAxisProperties.hxx"
+#include "macros.hxx"
+#include "ViewDefines.hxx"
+#include "CommonConverters.hxx"
+#include "AxisHelper.hxx"
+#include "DiagramHelper.hxx"
+#include "ChartModelHelper.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;
+}
+
+TickmarkProperties AxisProperties::makeTickmarkPropertiesForComplexCategories(
+ sal_Int32 nTickLength, sal_Int32 nTickStartDistanceToAxis, sal_Int32 /*nTextLevel*/ ) const
+{
+ sal_Int32 nTickmarkStyle = (m_fLabelDirectionSign==m_fInnerDirectionSign) ? 2/*outside*/ : 1/*inside*/;
+
+ TickmarkProperties aTickmarkProperties;
+ aTickmarkProperties.Length = nTickLength;// + nTextLevel*( lcl_calcTickLengthForDepth(0,nTickmarkStyle) );
+ aTickmarkProperties.RelativePos = static_cast<sal_Int32>(lcl_getTickOffset(aTickmarkProperties.Length+nTickStartDistanceToAxis,nTickmarkStyle));
+ aTickmarkProperties.aLineProperties = this->makeLinePropertiesForDepth( 0 );
+ 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
+ , ExplicitCategoriesProvider* pExplicitCategoriesProvider )
+ : 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_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_bComplexCategories(false)
+ , m_pExplicitCategoriesProvider(pExplicitCategoriesProvider)
+ , m_xAxisTextProvider(0)
+{
+}
+
+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_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_bComplexCategories( rAxisProperties.m_bComplexCategories )
+ , m_pExplicitCategoriesProvider( rAxisProperties.m_pExplicitCategoriesProvider )
+ , m_xAxisTextProvider( rAxisProperties.m_xAxisTextProvider )
+{
+ 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( ChartModelHelper::getDefaultPageSize() )
+ , m_aMaximumSpaceForLabels( 0 , 0, m_aFontReferenceSize.Width, m_aFontReferenceSize.Height )
+ , 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..5b6bfe98f777
--- /dev/null
+++ b/chart2/source/view/axes/VAxisProperties.hxx
@@ -0,0 +1,168 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _CHART2_VAXIS_PROPERTIES_HXX
+#define _CHART2_VAXIS_PROPERTIES_HXX
+
+#include "TickmarkProperties.hxx"
+#include "PlottingPositionHelper.hxx"
+#include "LabelAlignment.hxx"
+#include "ExplicitCategoriesProvider.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 rhythm 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;
+ 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
+ bool m_bComplexCategories;
+ ExplicitCategoriesProvider* m_pExplicitCategoriesProvider;/*no ownership here*/
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::chart2::data::XTextualDataSequence >
+ m_xAxisTextProvider; //for categries or series names
+ //<- category axes
+
+ //methods:
+
+ AxisProperties( const ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XAxis >& xAxisModel
+ , ExplicitCategoriesProvider* pExplicitCategoriesProvider );
+ 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();
+ TickmarkProperties makeTickmarkPropertiesForComplexCategories( sal_Int32 nTickLength, sal_Int32 nTickStartDistanceToAxis, sal_Int32 nTextLevel ) const;
+
+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..8ec895fbd452
--- /dev/null
+++ b/chart2/source/view/axes/VCartesianAxis.cxx
@@ -0,0 +1,1600 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_chart2.hxx"
+#include <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 <editeng/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
+ , bool bIsHorizontalAxis, bool bIsVerticalAxis )
+{
+ if(!xShape.is())
+ return false;
+
+ ::basegfx::B2IRectangle aShapeRect = BaseGFXHelper::makeRectangle(xShape->getPosition(),ShapeFactory::getSizeAfterRotation( xShape, fRotationAngleDegree ));
+
+ if( bIsVerticalAxis )
+ {
+ return ( (rTickScreenPosition.getY() >= aShapeRect.getMinY())
+ && (rTickScreenPosition.getY() <= aShapeRect.getMaxY()) );
+ }
+ if( bIsHorizontalAxis )
+ {
+ 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 removeShapesAtWrongRhythm( 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 rhythm
+ if( nTick%nCorrectRhythm != 0)
+ {
+ if(pTickInfo->xTextShape.is())
+ {
+ xTarget->remove(pTickInfo->xTextShape);
+ pTickInfo->xTextShape = NULL;
+ }
+ }
+ }
+}
+
+class EquidistantLabelIterator : public EquidistantTickIter
+{
+ //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:
+ EquidistantLabelIterator( ::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
+ EquidistantLabelIterator();
+
+private: //member
+ const AxisLabelStaggering m_eAxisLabelStaggering;
+ bool m_bInnerLine;
+};
+
+EquidistantLabelIterator::EquidistantLabelIterator( ::std::vector< ::std::vector< TickInfo > >& rTickInfos
+ , const ::com::sun::star::chart2::ExplicitIncrementData& rIncrement
+ , const AxisLabelStaggering eAxisLabelStaggering
+ , bool bInnerLine
+ , sal_Int32 nMinDepth, sal_Int32 nMaxDepth )
+ : EquidistantTickIter( rTickInfos, rIncrement, nMinDepth, nMaxDepth )
+ , m_eAxisLabelStaggering(eAxisLabelStaggering)
+ , m_bInnerLine(bInnerLine)
+{
+}
+
+TickInfo* EquidistantLabelIterator::firstInfo()
+{
+ TickInfo* pTickInfo = EquidistantTickIter::firstInfo();
+ while( pTickInfo && !pTickInfo->xTextShape.is() )
+ pTickInfo = EquidistantTickIter::nextInfo();
+ if(!pTickInfo)
+ return NULL;
+ if( (STAGGER_EVEN==m_eAxisLabelStaggering && m_bInnerLine)
+ ||
+ (STAGGER_ODD==m_eAxisLabelStaggering && !m_bInnerLine)
+ )
+ {
+ //skip first label
+ do
+ pTickInfo = EquidistantTickIter::nextInfo();
+ while( pTickInfo && !pTickInfo->xTextShape.is() );
+ }
+ if(!pTickInfo)
+ return NULL;
+ return pTickInfo;
+}
+
+TickInfo* EquidistantLabelIterator::nextInfo()
+{
+ TickInfo* pTickInfo = NULL;
+ //get next label
+ do
+ pTickInfo = EquidistantTickIter::nextInfo();
+ while( pTickInfo && !pTickInfo->xTextShape.is() );
+
+ if( STAGGER_EVEN==m_eAxisLabelStaggering
+ || STAGGER_ODD==m_eAxisLabelStaggering )
+ {
+ //skip one label
+ do
+ pTickInfo = EquidistantTickIter::nextInfo();
+ while( pTickInfo && !pTickInfo->xTextShape.is() );
+ }
+ return pTickInfo;
+}
+
+B2DVector lcl_getLabelsDistance( TickIter& rIter, const B2DVector& rDistanceTickToText )
+{
+ //calculates the height or width of a line of labels
+ //thus a following line of labels can 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;
+ if( xShape2DText.is() )
+ {
+ 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_shiftLables( TickIter& 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;
+ if( xShape2DText.is() )
+ {
+ 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 MaxLabelEquidistantTickIter : public EquidistantTickIter
+{
+ //iterate over first two and last two labels and the longest label
+public:
+ MaxLabelEquidistantTickIter( ::std::vector< ::std::vector< TickInfo > >& rTickInfos
+ , const ::com::sun::star::chart2::ExplicitIncrementData& rIncrement
+ , sal_Int32 nLongestLabelIndex );
+ virtual ~MaxLabelEquidistantTickIter();
+
+ virtual TickInfo* nextInfo();
+
+private:
+ sal_Int32 m_nLongestLabelIndex;
+};
+
+MaxLabelEquidistantTickIter::MaxLabelEquidistantTickIter( ::std::vector< ::std::vector< TickInfo > >& rTickInfos
+ , const ::com::sun::star::chart2::ExplicitIncrementData& rIncrement
+ , sal_Int32 nLongestLabelIndex )
+ : EquidistantTickIter( 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;
+}
+MaxLabelEquidistantTickIter::~MaxLabelEquidistantTickIter()
+{
+}
+
+TickInfo* MaxLabelEquidistantTickIter::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 EquidistantTickIter::nextInfo();
+}
+
+bool VCartesianAxis::isBreakOfLabelsAllowed( const AxisLabelProperties& rAxisLabelProperties
+ , bool bIsHorizontalAxis )
+{
+ 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
+ return bIsHorizontalAxis;
+}
+
+bool VCartesianAxis::isAutoStaggeringOfLabelsAllowed( const AxisLabelProperties& rAxisLabelProperties
+ , bool bIsHorizontalAxis, bool bIsVerticalAxis )
+{
+ 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( bIsHorizontalAxis )
+ return !rAxisLabelProperties.bStackCharacters;
+ if( bIsVerticalAxis )
+ return rAxisLabelProperties.bStackCharacters;
+ return false;
+}
+
+struct ComplexCategoryPlacement
+{
+ rtl::OUString Text;
+ sal_Int32 Count;
+ double TickValue;
+
+ ComplexCategoryPlacement( const rtl::OUString& rText, sal_Int32 nCount, double fTickValue )
+ : Text(rText), Count(nCount), TickValue(fTickValue)
+ {}
+};
+
+void VCartesianAxis::createAllTickInfosFromComplexCategories( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos, bool bShiftedPosition )
+{
+ //no minor tickmarks will be generated!
+ //order is: inner labels first , outer labels last (that is different to all other TickIter cases)
+ if(!bShiftedPosition)
+ {
+ rAllTickInfos.clear();
+ sal_Int32 nLevel=0;
+ sal_Int32 nLevelCount = m_aAxisProperties.m_pExplicitCategoriesProvider->getCategoryLevelCount();
+ for( ; nLevel<nLevelCount; nLevel++ )
+ {
+ ::std::vector< TickInfo > aTickInfoVector;
+ std::vector< ComplexCategory > aComplexCategories( m_aAxisProperties.m_pExplicitCategoriesProvider->getCategoriesByLevel( nLevel ) );
+ sal_Int32 nCatIndex = 0;
+ std::vector< ComplexCategory >::const_iterator aIt(aComplexCategories.begin());
+ std::vector< ComplexCategory >::const_iterator aEnd(aComplexCategories.end());
+ for(;aIt!=aEnd;++aIt)
+ {
+ TickInfo aTickInfo;
+ ComplexCategory aCat(*aIt);
+ sal_Int32 nCount = aCat.Count;
+ if( nCatIndex + 0.5 + nCount >= m_aScale.Maximum )
+ {
+ nCount = static_cast<sal_Int32>(m_aScale.Maximum - 0.5 - nCatIndex);
+ if( nCount <= 0 )
+ nCount = 1;
+ }
+ aTickInfo.fScaledTickValue = nCatIndex + 0.5 + nCount/2.0;
+ aTickInfo.nFactorForLimitedTextWidth = nCount;
+ aTickInfo.aText = aCat.Text;
+ aTickInfoVector.push_back(aTickInfo);
+ nCatIndex += nCount;
+ if( nCatIndex + 0.5 >= m_aScale.Maximum )
+ break;
+ }
+ rAllTickInfos.push_back(aTickInfoVector);
+ }
+ }
+ else //bShiftedPosition==true
+ {
+ rAllTickInfos.clear();
+ sal_Int32 nLevel=0;
+ sal_Int32 nLevelCount = m_aAxisProperties.m_pExplicitCategoriesProvider->getCategoryLevelCount();
+ for( ; nLevel<nLevelCount; nLevel++ )
+ {
+ ::std::vector< TickInfo > aTickInfoVector;
+ std::vector< ComplexCategory > aComplexCategories( m_aAxisProperties.m_pExplicitCategoriesProvider->getCategoriesByLevel( nLevel ) );
+ sal_Int32 nCatIndex = 0;
+ std::vector< ComplexCategory >::const_iterator aIt(aComplexCategories.begin());
+ std::vector< ComplexCategory >::const_iterator aEnd(aComplexCategories.end());
+ for(;aIt!=aEnd;++aIt)
+ {
+ TickInfo aTickInfo;
+ ComplexCategory aCat(*aIt);
+ aTickInfo.fScaledTickValue = nCatIndex + 0.5;
+ aTickInfoVector.push_back(aTickInfo);
+ nCatIndex += aCat.Count;
+ if( nCatIndex + 0.5 > m_aScale.Maximum )
+ break;
+ }
+ //fill up with single ticks until maximum scale
+ while( nCatIndex + 0.5 < m_aScale.Maximum )
+ {
+ TickInfo aTickInfo;
+ aTickInfo.fScaledTickValue = nCatIndex + 0.5;
+ aTickInfoVector.push_back(aTickInfo);
+ nCatIndex ++;
+ if( nLevel>0 )
+ break;
+ }
+ //add an additional tick at the end
+ {
+ TickInfo aTickInfo;
+ aTickInfo.fScaledTickValue = m_aScale.Maximum;
+ aTickInfoVector.push_back(aTickInfo);
+ }
+ rAllTickInfos.push_back(aTickInfoVector);
+ }
+ }
+}
+
+void VCartesianAxis::createAllTickInfos( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos )
+{
+ if( m_aAxisProperties.m_bComplexCategories && m_bUseTextLabels )
+ createAllTickInfosFromComplexCategories( rAllTickInfos, false );
+ else
+ VAxisBase::createAllTickInfos(rAllTickInfos);
+}
+
+::std::auto_ptr< TickIter > VCartesianAxis::createLabelTickIterator( sal_Int32 nTextLevel )
+{
+ if( m_aAxisProperties.m_bComplexCategories && m_bUseTextLabels )
+ {
+ if( nTextLevel>=0 && nTextLevel < static_cast< sal_Int32 >(m_aAllTickInfos.size()) )
+ return ::std::auto_ptr< TickIter >( new PureTickIter( m_aAllTickInfos[nTextLevel] ) );
+ }
+ else
+ {
+ if(nTextLevel==0)
+ return ::std::auto_ptr< TickIter >( new EquidistantTickIter( m_aAllTickInfos, m_aIncrement, 0, 0 ) );
+ }
+ return ::std::auto_ptr< TickIter >();
+}
+::std::auto_ptr< TickIter > VCartesianAxis::createMaximumLabelTickIterator( sal_Int32 nTextLevel )
+{
+ if( m_aAxisProperties.m_bComplexCategories && m_bUseTextLabels )
+ {
+ return createLabelTickIterator( nTextLevel ); //mmmm maybe todo: create less than all texts here
+ }
+ else
+ {
+ if(nTextLevel==0)
+ {
+ sal_Int32 nLongestLabelIndex = m_bUseTextLabels ? this->getIndexOfLongestLabel( m_aTextLabels ) : 0;
+ return ::std::auto_ptr< TickIter >( new MaxLabelEquidistantTickIter( m_aAllTickInfos, m_aIncrement, nLongestLabelIndex ) );
+ }
+ }
+ return ::std::auto_ptr< TickIter >();
+}
+
+sal_Int32 VCartesianAxis::getTextLevelCount() const
+{
+ sal_Int32 nTextLevelCount = 1;
+ if( m_aAxisProperties.m_bComplexCategories && m_bUseTextLabels )
+ nTextLevelCount = m_aAxisProperties.m_pExplicitCategoriesProvider->getCategoryLevelCount();
+ return nTextLevelCount;
+}
+
+bool VCartesianAxis::createTextShapes(
+ const Reference< drawing::XShapes >& xTarget
+ , TickIter& rTickIter
+ , AxisLabelProperties& rAxisLabelProperties
+ , TickmarkHelper_2D* pTickmarkHelper
+ , sal_Int32 nScreenDistanceBetweenTicks )
+{
+ //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
+
+ Reference< XScaling > xInverseScaling( NULL );
+ if( m_aScale.Scaling.is() )
+ xInverseScaling = m_aScale.Scaling->getInverseScaling();
+
+ FixedNumberFormatter aFixedNumberFormatter(
+ m_xNumberFormatsSupplier, rAxisLabelProperties.nNumberFormatKey );
+
+ const bool bIsHorizontalAxis = pTickmarkHelper->isHorizontalAxis();
+ const bool bIsVerticalAxis = pTickmarkHelper->isVerticalAxis();
+ bool bIsStaggered = rAxisLabelProperties.getIsStaggered();
+ B2DVector aTextToTickDistance( pTickmarkHelper->getDistanceAxisTickToText( m_aAxisProperties, true ) );
+ sal_Int32 nLimitedSpaceForText = -1;
+ if( isBreakOfLabelsAllowed( rAxisLabelProperties, bIsHorizontalAxis ) )
+ {
+ nLimitedSpaceForText = nScreenDistanceBetweenTicks;
+ if( bIsStaggered )
+ nLimitedSpaceForText *= 2;
+
+ if( nLimitedSpaceForText > 0 )
+ { //reduce space for a small amount to have a visible distance between the labels:
+ sal_Int32 nReduce = (nLimitedSpaceForText*5)/100;
+ if(!nReduce)
+ nReduce = 1;
+ nLimitedSpaceForText -= nReduce;
+ }
+ }
+
+ std::vector< ComplexCategoryPlacement > aComplexCategoryPlacements;
+ uno::Sequence< rtl::OUString >* pCategories = 0;
+ if( m_bUseTextLabels && !m_aAxisProperties.m_bComplexCategories )
+ pCategories = &m_aTextLabels;
+
+ TickInfo* pPreviousVisibleTickInfo = NULL;
+ TickInfo* pPREPreviousVisibleTickInfo = NULL;
+ TickInfo* pLastVisibleNeighbourTickInfo = NULL;
+
+ //------------------------------------------------
+ //prepare properties for multipropertyset-interface of shape
+ tNameSequence aPropNames;
+ tAnySequence aPropValues;
+
+ bool bLimitedHeight = fabs(aTextToTickDistance.getX()) > fabs(aTextToTickDistance.getY());
+ Reference< beans::XPropertySet > xProps( m_aAxisProperties.m_xAxisModel, uno::UNO_QUERY );
+ PropertyMapper::getTextLabelMultiPropertyLists( xProps, aPropNames, aPropValues, false
+ , nLimitedSpaceForText, bLimitedHeight );
+ 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;
+
+ uno::Any* pLimitedSpaceAny = PropertyMapper::getValuePointerForLimitedSpace(aPropValues,aPropNames,bLimitedHeight);
+ //------------------------------------------------
+
+ 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 rhythm
+ 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
+ , bIsHorizontalAxis, bIsVerticalAxis ) )
+ {
+ bool bOverlapAlsoAfterSwitchingOnAutoStaggering = true;
+ if( !bIsStaggered && isAutoStaggeringOfLabelsAllowed( rAxisLabelProperties, bIsHorizontalAxis, bIsVerticalAxis ) )
+ {
+ bIsStaggered = true;
+ rAxisLabelProperties.eStaggering = STAGGER_EVEN;
+ pLastVisibleNeighbourTickInfo = pPREPreviousVisibleTickInfo;
+ if( !pLastVisibleNeighbourTickInfo ||
+ !lcl_doesShapeOverlapWithTickmark( pLastVisibleNeighbourTickInfo->xTextShape
+ , rAxisLabelProperties.fRotationAngleDegree
+ , pTickInfo->aTickScreenPosition
+ , bIsHorizontalAxis, bIsVerticalAxis ) )
+ bOverlapAlsoAfterSwitchingOnAutoStaggering = false;
+ }
+ if( bOverlapAlsoAfterSwitchingOnAutoStaggering )
+ {
+ if( rAxisLabelProperties.bRhythmIsFix )
+ continue;
+ rAxisLabelProperties.nRhythm++;
+ removeShapesAtWrongRhythm( rTickIter, 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 if( m_aAxisProperties.m_bComplexCategories )
+ {
+ aLabel = pTickInfo->aText;
+ }
+ else
+ aLabel = aFixedNumberFormatter.getFormattedString( pTickInfo->fUnscaledTickValue, nExtraColor, bHasExtraColor );
+
+ if(pColorAny)
+ *pColorAny = uno::makeAny(bHasExtraColor?nExtraColor:nColor);
+ if(pLimitedSpaceAny)
+ *pLimitedSpaceAny = uno::makeAny(sal_Int32(nLimitedSpaceForText*pTickInfo->nFactorForLimitedTextWidth));
+
+ 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, bIsHorizontalAxis, bIsVerticalAxis ) )
+ {
+ bIsStaggered = true;
+ rAxisLabelProperties.eStaggering = STAGGER_EVEN;
+ pLastVisibleNeighbourTickInfo = pPREPreviousVisibleTickInfo;
+ if( !pLastVisibleNeighbourTickInfo ||
+ !lcl_doesShapeOverlapWithTickmark( pLastVisibleNeighbourTickInfo->xTextShape
+ , rAxisLabelProperties.fRotationAngleDegree
+ , pTickInfo->aTickScreenPosition
+ , bIsHorizontalAxis, bIsVerticalAxis ) )
+ bOverlapAlsoAfterSwitchingOnAutoStaggering = false;
+ }
+ if( bOverlapAlsoAfterSwitchingOnAutoStaggering )
+ {
+ if( rAxisLabelProperties.bRhythmIsFix )
+ {
+ xTarget->remove(pTickInfo->xTextShape);
+ pTickInfo->xTextShape = NULL;
+ continue;
+ }
+ rAxisLabelProperties.nRhythm++;
+ removeShapesAtWrongRhythm( rTickIter, 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 );
+}
+
+void lcl_hideIdenticalScreenValues( TickIter& rTickIter )
+{
+ TickInfo* pPreviousTickInfo = rTickIter.firstInfo();
+ if(!pPreviousTickInfo)
+ return;
+ pPreviousTickInfo->bPaintIt = true;
+ for( TickInfo* pTickInfo = rTickIter.nextInfo(); pTickInfo; pTickInfo = rTickIter.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;
+ }
+}
+
+//'hide' tickmarks with identical screen values in aAllTickInfos
+void VCartesianAxis::hideIdenticalScreenValues( ::std::vector< ::std::vector< TickInfo > >& rTickInfos ) const
+{
+ if( m_aAxisProperties.m_bComplexCategories && m_bUseTextLabels )
+ {
+ sal_Int32 nCount = rTickInfos.size();
+ for( sal_Int32 nN=0; nN<nCount; nN++ )
+ {
+ PureTickIter aTickIter( rTickInfos[nN] );
+ lcl_hideIdenticalScreenValues( aTickIter );
+ }
+ }
+ else
+ {
+ EquidistantTickIter aTickIter( rTickInfos, m_aIncrement, 0, -1 );
+ lcl_hideIdenticalScreenValues( aTickIter );
+ }
+}
+
+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( m_aAxisProperties.m_bComplexCategories && m_bUseTextLabels )
+ {
+ sal_Int32 nTextLevelCount = getTextLevelCount();
+ B2DVector aCummulatedLabelsDistance(0,0);
+ for( sal_Int32 nTextLevel=0; nTextLevel<nTextLevelCount; nTextLevel++ )
+ {
+ ::std::auto_ptr< TickIter > apTickIter = createLabelTickIterator( nTextLevel );
+ if(apTickIter.get())
+ {
+ if( nTextLevel>0 )
+ lcl_shiftLables( *apTickIter.get(), aCummulatedLabelsDistance );
+ aCummulatedLabelsDistance += lcl_getLabelsDistance( *apTickIter.get()
+ , pTickmarkHelper2D->getDistanceAxisTickToText( m_aAxisProperties ) );
+ }
+ }
+ }
+ else if( rAxisLabelProperties.getIsStaggered() )
+ {
+ EquidistantLabelIterator aInnerIter( m_aAllTickInfos, m_aIncrement
+ , rAxisLabelProperties.eStaggering, true, 0, 0 );
+ EquidistantLabelIterator aOuterIter( m_aAllTickInfos, m_aIncrement
+ , rAxisLabelProperties.eStaggering, false, 0, 0 );
+
+ lcl_shiftLables( aOuterIter
+ , lcl_getLabelsDistance( aInnerIter
+ , pTickmarkHelper2D->getDistanceAxisTickToText( m_aAxisProperties ) ) );
+ }
+}
+
+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
+ hideIdenticalScreenValues( m_aAllTickInfos );
+
+ removeTextShapesFromTicks();
+
+ //create tick mark text shapes
+ sal_Int32 nTextLevelCount = getTextLevelCount();
+ sal_Int32 nScreenDistanceBetweenTicks = -1;
+ for( sal_Int32 nTextLevel=0; nTextLevel<nTextLevelCount; nTextLevel++ )
+ {
+ ::std::auto_ptr< TickIter > apTickIter = createLabelTickIterator( nTextLevel );
+ if(apTickIter.get())
+ {
+ if(nTextLevel==0)
+ {
+ nScreenDistanceBetweenTicks = TickmarkHelper_2D::getTickScreenDistance( *apTickIter.get() );
+ if( nTextLevelCount>1 )
+ nScreenDistanceBetweenTicks*=2; //the above used tick iter does contain also the sub ticks -> thus the given distance is only the half
+ }
+
+ AxisLabelProperties aCopy(m_aAxisLabelProperties);
+ aCopy.bRhythmIsFix = true;
+ aCopy.nRhythm = 1;
+ AxisLabelProperties& rAxisLabelProperties = nTextLevel==0 ? m_aAxisLabelProperties : aCopy;
+ while( !createTextShapes( m_xTextTarget, *apTickIter.get(), rAxisLabelProperties, pTickmarkHelper2D, nScreenDistanceBetweenTicks ) )
+ {
+ };
+ }
+ }
+ 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
+
+ AxisLabelProperties aAxisLabelProperties( m_aAxisLabelProperties );
+ if( isAutoStaggeringOfLabelsAllowed( aAxisLabelProperties, pTickmarkHelper2D->isHorizontalAxis(), pTickmarkHelper2D->isVerticalAxis() ) )
+ aAxisLabelProperties.eStaggering = STAGGER_EVEN;
+ aAxisLabelProperties.bOverlapAllowed = true;
+ aAxisLabelProperties.bLineBreakAllowed = false;
+ sal_Int32 nTextLevelCount = getTextLevelCount();
+ for( sal_Int32 nTextLevel=0; nTextLevel<nTextLevelCount; nTextLevel++ )
+ {
+ ::std::auto_ptr< TickIter > apTickIter = createMaximumLabelTickIterator( nTextLevel );
+ if(apTickIter.get())
+ {
+ while( !createTextShapes( m_xTextTarget, *apTickIter.get(), aAxisLabelProperties, pTickmarkHelper2D, -1 ) )
+ {
+ };
+ }
+ }
+ 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 );
+
+ ::std::vector< ::std::vector< TickInfo > >::iterator aDepthIter = m_aAllTickInfos.begin();
+ const ::std::vector< ::std::vector< TickInfo > >::const_iterator aDepthEnd = m_aAllTickInfos.end();
+ for( ; aDepthIter != aDepthEnd; aDepthIter++ )
+ {
+ ::std::vector< TickInfo >::iterator aTickIter = aDepthIter->begin();
+ const ::std::vector< TickInfo >::const_iterator aTickEnd = aDepthIter->end();
+ for( ; aTickIter != aTickEnd; aTickIter++ )
+ {
+ TickInfo& rTickInfo = (*aTickIter);
+ Reference< drawing::XShape > xShape2DText( rTickInfo.xTextShape );
+ if( xShape2DText.is() )
+ {
+ B2DVector aTextToTickDistance( pTickmarkHelper2D->getDistanceAxisTickToText( m_aAxisProperties, true ) );
+ B2DVector aTickScreenPos2D( rTickInfo.aTickScreenPosition );
+ aTickScreenPos2D += aTextToTickDistance;
+ awt::Point aAnchorScreenPosition2D(
+ static_cast<sal_Int32>(aTickScreenPos2D.getX())
+ ,static_cast<sal_Int32>(aTickScreenPos2D.getY()));
+
+ // #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 VCartesianAxis::createTickMarkLineShapes( ::std::vector< TickInfo >& rTickInfos, const TickmarkProperties& rTickmarkProperties, TickmarkHelper_2D& rTickmarkHelper2D, bool bOnlyAtLabels )
+{
+ sal_Int32 nPointCount = rTickInfos.size();
+ drawing::PointSequenceSequence aPoints(2*nPointCount);
+
+ ::std::vector< TickInfo >::const_iterator aTickIter = rTickInfos.begin();
+ const ::std::vector< TickInfo >::const_iterator aTickEnd = rTickInfos.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;
+ bTicksAtLabels = bTicksAtLabels || bOnlyAtLabels;
+ //add ticks at labels:
+ rTickmarkHelper2D.addPointSequenceForTickLine( aPoints, nN++, (*aTickIter).fScaledTickValue
+ , fInnerDirectionSign , rTickmarkProperties, bTicksAtLabels );
+ //add ticks at axis (without lables):
+ if( !bOnlyAtLabels && m_aAxisProperties.m_eTickmarkPos == ::com::sun::star::chart::ChartAxisMarkPosition_AT_LABELS_AND_AXIS )
+ rTickmarkHelper2D.addPointSequenceForTickLine( aPoints, nN++, (*aTickIter).fScaledTickValue
+ , m_aAxisProperties.m_fInnerDirectionSign, rTickmarkProperties, !bTicksAtLabels );
+ }
+ aPoints.realloc(nN);
+ m_pShapeFactory->createLine2D( m_xGroupShape_Shapes, aPoints
+ , &rTickmarkProperties.aLineProperties );
+}
+
+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 line shapes
+ if(2==m_nDimension)
+ {
+ //-----------------------------------------
+ //create extra long ticks to separate complex categories (create them only there where the labels are)
+ if( m_aAxisProperties.m_bComplexCategories && m_bUseTextLabels )
+ {
+ ::std::vector< ::std::vector< TickInfo > > aComplexTickInfos;
+ createAllTickInfosFromComplexCategories( aComplexTickInfos, true );
+ pTickmarkHelper2D->updateScreenValues( aComplexTickInfos );
+ hideIdenticalScreenValues( aComplexTickInfos );
+
+ ::std::vector<TickmarkProperties> aTickmarkPropertiesList;
+ static bool bIncludeSpaceBetweenTickAndText = false;
+ sal_Int32 nOffset = static_cast<sal_Int32>(pTickmarkHelper2D->getDistanceAxisTickToText( m_aAxisProperties, false, bIncludeSpaceBetweenTickAndText ).getLength());
+ sal_Int32 nTextLevelCount = getTextLevelCount();
+ for( sal_Int32 nTextLevel=0; nTextLevel<nTextLevelCount; nTextLevel++ )
+ {
+ ::std::auto_ptr< TickIter > apTickIter = createLabelTickIterator( nTextLevel );
+ if( apTickIter.get() )
+ {
+ B2DVector aLabelsDistance( lcl_getLabelsDistance( *apTickIter.get(), pTickmarkHelper2D->getDistanceAxisTickToText( m_aAxisProperties, false ) ) );
+ sal_Int32 nCurrentLength = static_cast<sal_Int32>(aLabelsDistance.getLength());
+ aTickmarkPropertiesList.push_back( m_aAxisProperties.makeTickmarkPropertiesForComplexCategories( nOffset + nCurrentLength, 0, nTextLevel ) );
+ nOffset += nCurrentLength;
+ }
+ }
+
+ sal_Int32 nTickmarkPropertiesCount = aTickmarkPropertiesList.size();
+ ::std::vector< ::std::vector< TickInfo > >::iterator aDepthIter = aComplexTickInfos.begin();
+ const ::std::vector< ::std::vector< TickInfo > >::const_iterator aDepthEnd = aComplexTickInfos.end();
+ for( sal_Int32 nDepth=0; aDepthIter != aDepthEnd && nDepth < nTickmarkPropertiesCount; aDepthIter++, nDepth++ )
+ {
+ if(nDepth==0 && !m_aAxisProperties.m_nMajorTickmarks)
+ continue;
+ createTickMarkLineShapes( *aDepthIter, aTickmarkPropertiesList[nDepth], *pTickmarkHelper2D, true /*bOnlyAtLabels*/ );
+ }
+ }
+ //-----------------------------------------
+ //create normal ticks for major and minor intervals
+ {
+ ::std::vector< ::std::vector< TickInfo > > aAllShiftedTickInfos;
+ if( m_aIncrement.ShiftedPosition || ( m_aAxisProperties.m_bComplexCategories && m_bUseTextLabels ) )
+ {
+ pTickmarkHelper2D->getAllTicksShifted( aAllShiftedTickInfos );
+ pTickmarkHelper2D->updateScreenValues( aAllShiftedTickInfos );
+ 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++ )
+ createTickMarkLineShapes( *aDepthIter, m_aAxisProperties.m_aTickmarkPropertiesList[nDepth], *pTickmarkHelper2D, false /*bOnlyAtLabels*/ );
+ }
+ //-----------------------------------------
+ //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..4fbcd2409196
--- /dev/null
+++ b/chart2/source/view/axes/VCartesianAxis.hxx
@@ -0,0 +1,146 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _CHART2_VCARTESIANAXIS_HXX
+#define _CHART2_VCARTESIANAXIS_HXX
+
+#include "VAxisBase.hxx"
+#include <basegfx/vector/b2dvector.hxx>
+
+#include <memory>
+
+//.............................................................................
+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 void createAllTickInfos( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos );
+ void createAllTickInfosFromComplexCategories( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos, bool bShiftedPosition );
+
+ ::std::auto_ptr< TickIter > createLabelTickIterator( sal_Int32 nTextLevel );
+ ::std::auto_ptr< TickIter > createMaximumLabelTickIterator( sal_Int32 nTextLevel );
+ sal_Int32 getTextLevelCount() const;
+
+ //-------------------------------------------------------------------------
+ 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
+ , sal_Int32 nScreenDistanceBetweenTicks );
+
+ void createTickMarkLineShapes( ::std::vector< TickInfo >& rTickInfos, const TickmarkProperties& rTickmarkProperties, TickmarkHelper_2D& rTickmarkHelper2D, bool bOnlyAtLabels );
+
+ TickmarkHelper_2D* createTickmarkHelper2D();
+ void hideIdenticalScreenValues( ::std::vector< ::std::vector< TickInfo > >& rTickInfos ) const;
+
+ void doStaggeringOfLabels( const AxisLabelProperties& rAxisLabelProperties
+ , TickmarkHelper_2D* pTickmarkHelper2D );
+ bool isAutoStaggeringOfLabelsAllowed( const AxisLabelProperties& rAxisLabelProperties
+ , bool bIsHorizontalAxis, bool bIsVerticalAxis );
+ bool isBreakOfLabelsAllowed( const AxisLabelProperties& rAxisLabelProperties, bool bIsHorizontalAxis );
+
+ ::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..a196397e0e9f
--- /dev/null
+++ b/chart2/source/view/axes/VCartesianCoordinateSystem.cxx
@@ -0,0 +1,250 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_chart2.hxx"
+#include "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 ) )
+ || ( aAxisProperties.m_pExplicitCategoriesProvider && aAxisProperties.m_pExplicitCategoriesProvider->hasComplexCategories() );
+ }
+ }
+
+ 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 );
+
+ if( nDimensionIndex == 0 && aAxisProperties.m_nAxisType == AxisType::CATEGORY
+ && aAxisProperties.m_pExplicitCategoriesProvider )
+ {
+ if( aAxisProperties.m_pExplicitCategoriesProvider->hasComplexCategories() )
+ aAxisProperties.m_bComplexCategories = true;
+ }
+ //-------------------
+ ::boost::shared_ptr< VAxisBase > apVAxis( new VCartesianAxis(aAxisProperties,xNumberFormatsSupplier,nDimensionIndex,nDimensionCount) );
+ tFullAxisIndex aFullAxisIndex( nDimensionIndex, nAxisIndex );
+ m_aAxisMap[aFullAxisIndex] = apVAxis;
+ apVAxis->set3DWallPositions( m_eLeftWallPos, m_eBackWallPos, m_eBottomPos );
+
+ //apVAxis->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..b28400c6f906
--- /dev/null
+++ b/chart2/source/view/axes/VCartesianCoordinateSystem.hxx
@@ -0,0 +1,64 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _CHART2_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..7fe6b9937ca6
--- /dev/null
+++ b/chart2/source/view/axes/VCartesianGrid.cxx
@@ -0,0 +1,339 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_chart2.hxx"
+#include "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..274b543900e3
--- /dev/null
+++ b/chart2/source/view/axes/VCartesianGrid.hxx
@@ -0,0 +1,71 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _CHART2_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..bc908acdf85a
--- /dev/null
+++ b/chart2/source/view/axes/VCoordinateSystem.cxx
@@ -0,0 +1,598 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_chart2.hxx"
+#include "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_apExplicitCategoriesProvider(NULL)
+{
+ 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;
+}
+
+void VCoordinateSystem::setExplicitCategoriesProvider( ExplicitCategoriesProvider* pExplicitCategoriesProvider /*takes ownership*/ )
+{
+ m_apExplicitCategoriesProvider = ::std::auto_ptr< ExplicitCategoriesProvider >(pExplicitCategoriesProvider);
+}
+
+ExplicitCategoriesProvider* VCoordinateSystem::getExplicitCategoriesProvider()
+{
+ return m_apExplicitCategoriesProvider.get();
+}
+
+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..865a7848aa9a
--- /dev/null
+++ b/chart2/source/view/axes/VPolarAngleAxis.cxx
@@ -0,0 +1,234 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_chart2.hxx"
+#include <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
+ , EquidistantTickIter& 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 rhythm
+ 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
+
+ EquidistantTickIter aTickIter( m_aAllTickInfos, m_aIncrement, 0, 0 );
+ this->updateUnscaledValuesAtTicks( aTickIter );
+
+ removeTextShapesFromTicks();
+
+ 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..c03cf533e22c
--- /dev/null
+++ b/chart2/source/view/axes/VPolarAngleAxis.hxx
@@ -0,0 +1,66 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _CHART2_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
+ , EquidistantTickIter& 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..23908585ec3a
--- /dev/null
+++ b/chart2/source/view/axes/VPolarAxis.cxx
@@ -0,0 +1,83 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_chart2.hxx"
+#include "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..8d4c14188258
--- /dev/null
+++ b/chart2/source/view/axes/VPolarAxis.hxx
@@ -0,0 +1,71 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _CHART2_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..76e057a2b32d
--- /dev/null
+++ b/chart2/source/view/axes/VPolarCoordinateSystem.cxx
@@ -0,0 +1,211 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_chart2.hxx"
+#include "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..f1ba84c5469e
--- /dev/null
+++ b/chart2/source/view/axes/VPolarCoordinateSystem.hxx
@@ -0,0 +1,68 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _CHART2_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..0bd98b642acb
--- /dev/null
+++ b/chart2/source/view/axes/VPolarGrid.cxx
@@ -0,0 +1,273 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_chart2.hxx"
+#include "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;
+ EquidistantTickIter 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..3289d6c88be8
--- /dev/null
+++ b/chart2/source/view/axes/VPolarGrid.hxx
@@ -0,0 +1,96 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _CHART2_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..2206d4d8f559
--- /dev/null
+++ b/chart2/source/view/axes/VPolarRadiusAxis.cxx
@@ -0,0 +1,186 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_chart2.hxx"
+
+#include "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_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;
+ EquidistantTickIter 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..b5c5191e4c98
--- /dev/null
+++ b/chart2/source/view/axes/VPolarRadiusAxis.hxx
@@ -0,0 +1,98 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _CHART2_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..96191a3a3a25
--- /dev/null
+++ b/chart2/source/view/axes/makefile.mk
@@ -0,0 +1,66 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+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
diff --git a/chart2/source/view/charttypes/AreaChart.cxx b/chart2/source/view/charttypes/AreaChart.cxx
new file mode 100644
index 000000000000..fd1aaa81c3a0
--- /dev/null
+++ b/chart2/source/view/charttypes/AreaChart.cxx
@@ -0,0 +1,1005 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_chart2.hxx"
+
+#include "AreaChart.hxx"
+#include "PlottingPositionHelper.hxx"
+#include "ShapeFactory.hxx"
+//#include "chartview/servicenames_charttypes.hxx"
+#include "CommonConverters.hxx"
+#include "macros.hxx"
+#include "ViewDefines.hxx"
+#include "ObjectIdentifier.hxx"
+#include "Splines.hxx"
+#include "ChartTypeHelper.hxx"
+#include "LabelPositionHelper.hxx"
+#include "Clipping.hxx"
+#include "Stripe.hxx"
+#include "PolarLabelPositionHelper.hxx"
+
+#include <com/sun/star/chart2/Symbol.hpp>
+#include <com/sun/star/chart/DataLabelPlacement.hpp>
+#include <com/sun/star/chart/MissingValueTreatment.hpp>
+#include <tools/debug.hxx>
+#include <editeng/unoprnms.hxx>
+#include <rtl/math.hxx>
+#include <com/sun/star/drawing/DoubleSequence.hpp>
+#include <com/sun/star/drawing/NormalsKind.hpp>
+#include <com/sun/star/lang/XServiceName.hpp>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+using namespace ::com::sun::star;
+using namespace ::rtl::math;
+using namespace ::com::sun::star::chart2;
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+AreaChart::AreaChart( const uno::Reference<XChartType>& xChartTypeModel
+ , sal_Int32 nDimensionCount
+ , bool bCategoryXAxis
+ , bool bNoArea
+ , PlottingPositionHelper* pPlottingPositionHelper
+ , bool bConnectLastToFirstPoint
+ , bool bExpandIfValuesCloseToBorder
+ , sal_Int32 nKeepAspectRatio
+ , const drawing::Direction3D& rAspectRatio
+ )
+ : VSeriesPlotter( xChartTypeModel, nDimensionCount, bCategoryXAxis )
+ , m_pMainPosHelper(pPlottingPositionHelper)
+ , m_bArea(!bNoArea)
+ , m_bLine(bNoArea)
+ , m_bSymbol( ChartTypeHelper::isSupportingSymbolProperties(xChartTypeModel,nDimensionCount) )
+ , m_bIsPolarCooSys( bConnectLastToFirstPoint )
+ , m_bConnectLastToFirstPoint( bConnectLastToFirstPoint )
+ , m_bExpandIfValuesCloseToBorder( bExpandIfValuesCloseToBorder )
+ , m_nKeepAspectRatio(nKeepAspectRatio)
+ , m_aGivenAspectRatio(rAspectRatio)
+ , m_eCurveStyle(CurveStyle_LINES)
+ , m_nCurveResolution(20)
+ , m_nSplineOrder(3)
+ , m_xSeriesTarget(0)
+ , m_xErrorBarTarget(0)
+ , m_xTextTarget(0)
+ , m_xRegressionCurveEquationTarget(0)
+{
+ if( !m_pMainPosHelper )
+ m_pMainPosHelper = new PlottingPositionHelper();
+ PlotterBase::m_pPosHelper = m_pMainPosHelper;
+ VSeriesPlotter::m_pMainPosHelper = m_pMainPosHelper;
+
+ try
+ {
+ if( m_xChartTypeModelProps.is() )
+ {
+ m_xChartTypeModelProps->getPropertyValue( C2U( "CurveStyle" ) ) >>= m_eCurveStyle;
+ m_xChartTypeModelProps->getPropertyValue( C2U( "CurveResolution" ) ) >>= m_nCurveResolution;
+ m_xChartTypeModelProps->getPropertyValue( C2U( "SplineOrder" ) ) >>= m_nSplineOrder;
+ }
+ }
+ catch( uno::Exception& e )
+ {
+ //the above properties are not supported by all charttypes supported by this class (e.g. area or net chart)
+ //in that cases this exception is ok
+ e.Context.is();//to have debug information without compilation warnings
+ }
+}
+
+AreaChart::~AreaChart()
+{
+ delete m_pMainPosHelper;
+}
+
+double AreaChart::getMinimumX()
+{
+ if( m_bCategoryXAxis && m_bIsPolarCooSys )//the angle axis in net charts needs a different autoscaling
+ return 1.0;//first category (index 0) matches with real number 1.0
+ return VSeriesPlotter::getMinimumX();
+}
+
+double AreaChart::getMaximumX()
+{
+ if( m_bCategoryXAxis && m_bIsPolarCooSys )//the angle axis in net charts needs a different autoscaling
+ return getPointCount()+1;
+ return VSeriesPlotter::getMaximumX();
+}
+
+bool AreaChart::isExpandIfValuesCloseToBorder( sal_Int32 nDimensionIndex )
+{
+ return m_bExpandIfValuesCloseToBorder &&
+ VSeriesPlotter::isExpandIfValuesCloseToBorder( nDimensionIndex );
+}
+
+bool AreaChart::isSeperateStackingForDifferentSigns( sal_Int32 /*nDimensionIndex*/ )
+{
+ // no separate stacking in all types of line/area charts
+ return false;
+}
+
+//-----------------------------------------------------------------
+
+LegendSymbolStyle AreaChart::getLegendSymbolStyle()
+{
+ if( m_bArea || m_nDimension == 3 )
+ return chart2::LegendSymbolStyle_BOX;
+ return chart2::LegendSymbolStyle_LINE_WITH_SYMBOL;
+}
+
+uno::Any AreaChart::getExplicitSymbol( const VDataSeries& rSeries, sal_Int32 nPointIndex )
+{
+ uno::Any aRet;
+
+ Symbol* pSymbolProperties = rSeries.getSymbolProperties( nPointIndex );
+ if( pSymbolProperties )
+ {
+ aRet = uno::makeAny(*pSymbolProperties);
+ }
+
+ return aRet;
+}
+
+//-----------------------------------------------------------------
+// lang::XServiceInfo
+//-----------------------------------------------------------------
+/*
+APPHELPER_XSERVICEINFO_IMPL(AreaChart,CHART2_VIEW_AREACHART_SERVICE_IMPLEMENTATION_NAME)
+
+ uno::Sequence< rtl::OUString > AreaChart
+::getSupportedServiceNames_Static()
+{
+ uno::Sequence< rtl::OUString > aSNS( 1 );
+ aSNS.getArray()[ 0 ] = CHART2_VIEW_AREACHART_SERVICE_NAME;
+ return aSNS;
+}
+*/
+/*
+//-----------------------------------------------------------------
+// chart2::XPlotter
+//-----------------------------------------------------------------
+
+ ::rtl::OUString SAL_CALL AreaChart
+::getCoordinateSystemTypeID()
+ throw (uno::RuntimeException)
+{
+ return CHART2_COOSYSTEM_CARTESIAN_SERVICE_NAME;
+}
+*/
+drawing::Direction3D AreaChart::getPreferredDiagramAspectRatio() const
+{
+ if( m_nKeepAspectRatio == 1 )
+ return m_aGivenAspectRatio;
+ drawing::Direction3D aRet(1,-1,1);
+ if( m_nDimension == 2 )
+ aRet = drawing::Direction3D(-1,-1,-1);
+ else
+ {
+ drawing::Direction3D aScale( m_pPosHelper->getScaledLogicWidth() );
+ aRet.DirectionZ = aScale.DirectionZ*0.2;
+ if(aRet.DirectionZ>1.0)
+ aRet.DirectionZ=1.0;
+ if(aRet.DirectionZ>10)
+ aRet.DirectionZ=10;
+ }
+ return aRet;
+}
+
+bool AreaChart::keepAspectRatio() const
+{
+ if( m_nKeepAspectRatio == 0 )
+ return false;
+ if( m_nKeepAspectRatio == 1 )
+ return true;
+ if( m_nDimension == 2 )
+ {
+ if( !m_bSymbol )
+ return false;
+ }
+ return true;
+}
+
+void AreaChart::addSeries( VDataSeries* pSeries, sal_Int32 zSlot, sal_Int32 xSlot, sal_Int32 ySlot )
+{
+ if( m_bArea && !m_bIsPolarCooSys && pSeries )
+ {
+ sal_Int32 nMissingValueTreatment = pSeries->getMissingValueTreatment();
+ if( nMissingValueTreatment == ::com::sun::star::chart::MissingValueTreatment::LEAVE_GAP )
+ pSeries->setMissingValueTreatment( ::com::sun::star::chart::MissingValueTreatment::USE_ZERO );
+ }
+ if( m_nDimension == 3 && !m_bCategoryXAxis )
+ {
+ //3D xy always deep
+ DBG_ASSERT( zSlot==-1,"3D xy charts should be deep stacked in model also" );
+ zSlot=-1;
+ xSlot=0;
+ ySlot=0;
+ }
+ VSeriesPlotter::addSeries( pSeries, zSlot, xSlot, ySlot );
+}
+
+void lcl_removeDuplicatePoints( drawing::PolyPolygonShape3D& rPolyPoly, PlottingPositionHelper& rPosHelper )
+{
+ sal_Int32 nPolyCount = rPolyPoly.SequenceX.getLength();
+ if(!nPolyCount)
+ return;
+
+ drawing::PolyPolygonShape3D aTmp;
+ aTmp.SequenceX.realloc(nPolyCount);
+ aTmp.SequenceY.realloc(nPolyCount);
+ aTmp.SequenceZ.realloc(nPolyCount);
+
+ for( sal_Int32 nPolygonIndex = 0; nPolygonIndex<nPolyCount; nPolygonIndex++ )
+ {
+ drawing::DoubleSequence* pOuterSourceX = &rPolyPoly.SequenceX.getArray()[nPolygonIndex];
+ drawing::DoubleSequence* pOuterSourceY = &rPolyPoly.SequenceY.getArray()[nPolygonIndex];
+ drawing::DoubleSequence* pOuterSourceZ = &rPolyPoly.SequenceZ.getArray()[nPolygonIndex];
+
+ drawing::DoubleSequence* pOuterTargetX = &aTmp.SequenceX.getArray()[nPolygonIndex];
+ drawing::DoubleSequence* pOuterTargetY = &aTmp.SequenceY.getArray()[nPolygonIndex];
+ drawing::DoubleSequence* pOuterTargetZ = &aTmp.SequenceZ.getArray()[nPolygonIndex];
+
+ sal_Int32 nPointCount = pOuterSourceX->getLength();
+ if( !nPointCount )
+ continue;
+
+ pOuterTargetX->realloc(nPointCount);
+ pOuterTargetY->realloc(nPointCount);
+ pOuterTargetZ->realloc(nPointCount);
+
+ double* pSourceX = pOuterSourceX->getArray();
+ double* pSourceY = pOuterSourceY->getArray();
+ double* pSourceZ = pOuterSourceZ->getArray();
+
+ double* pTargetX = pOuterTargetX->getArray();
+ double* pTargetY = pOuterTargetY->getArray();
+ double* pTargetZ = pOuterTargetZ->getArray();
+
+ //copy first point
+ *pTargetX=*pSourceX++;
+ *pTargetY=*pSourceY++;
+ *pTargetZ=*pSourceZ++;
+ sal_Int32 nTargetPointCount=1;
+
+ for( sal_Int32 nSource=1; nSource<nPointCount; nSource++ )
+ {
+ if( !rPosHelper.isSameForGivenResolution( *pTargetX, *pTargetY, *pTargetZ
+ , *pSourceX, *pSourceY, *pSourceZ ) )
+ {
+ pTargetX++; pTargetY++; pTargetZ++;
+ *pTargetX=*pSourceX;
+ *pTargetY=*pSourceY;
+ *pTargetZ=*pSourceZ;
+ nTargetPointCount++;
+ }
+ pSourceX++; pSourceY++; pSourceZ++;
+ }
+
+ //free unused space
+ if( nTargetPointCount<nPointCount )
+ {
+ pOuterTargetX->realloc(nTargetPointCount);
+ pOuterTargetY->realloc(nTargetPointCount);
+ pOuterTargetZ->realloc(nTargetPointCount);
+ }
+
+ pOuterSourceX->realloc(0);
+ pOuterSourceY->realloc(0);
+ pOuterSourceZ->realloc(0);
+ }
+
+ //free space
+ rPolyPoly.SequenceX.realloc(nPolyCount);
+ rPolyPoly.SequenceY.realloc(nPolyCount);
+ rPolyPoly.SequenceZ.realloc(nPolyCount);
+
+ rPolyPoly=aTmp;
+}
+
+bool AreaChart::impl_createLine( VDataSeries* pSeries
+ , drawing::PolyPolygonShape3D* pSeriesPoly
+ , PlottingPositionHelper* pPosHelper )
+{
+ //return true if a line was created successfully
+ uno::Reference< drawing::XShapes > xSeriesGroupShape_Shapes = getSeriesGroupShapeBackChild(pSeries, m_xSeriesTarget);
+
+ drawing::PolyPolygonShape3D aPoly;
+ if(CurveStyle_CUBIC_SPLINES==m_eCurveStyle)
+ {
+ drawing::PolyPolygonShape3D aSplinePoly;
+ SplineCalculater::CalculateCubicSplines( *pSeriesPoly, aSplinePoly, m_nCurveResolution );
+ lcl_removeDuplicatePoints( aSplinePoly, *pPosHelper );
+ Clipping::clipPolygonAtRectangle( aSplinePoly, pPosHelper->getScaledLogicClipDoubleRect(), aPoly );
+ }
+ else if(CurveStyle_B_SPLINES==m_eCurveStyle)
+ {
+ drawing::PolyPolygonShape3D aSplinePoly;
+ SplineCalculater::CalculateBSplines( *pSeriesPoly, aSplinePoly, m_nCurveResolution, m_nSplineOrder );
+ lcl_removeDuplicatePoints( aSplinePoly, *pPosHelper );
+ Clipping::clipPolygonAtRectangle( aSplinePoly, pPosHelper->getScaledLogicClipDoubleRect(), aPoly );
+ }
+ else
+ {
+ bool bIsClipped = false;
+ if( m_bConnectLastToFirstPoint && !ShapeFactory::isPolygonEmptyOrSinglePoint(*pSeriesPoly) )
+ {
+ // do NOT connect last and first point, if one is NAN, and NAN handling is NAN_AS_GAP
+ double fFirstY = pSeries->getYValue( 0 );
+ double fLastY = pSeries->getYValue( VSeriesPlotter::getPointCount() - 1 );
+ if( (pSeries->getMissingValueTreatment() != ::com::sun::star::chart::MissingValueTreatment::LEAVE_GAP)
+ || (::rtl::math::isFinite( fFirstY ) && ::rtl::math::isFinite( fLastY )) )
+ {
+ // connect last point in last polygon with first point in first polygon
+ ::basegfx::B2DRectangle aScaledLogicClipDoubleRect( pPosHelper->getScaledLogicClipDoubleRect() );
+ drawing::PolyPolygonShape3D aTmpPoly(*pSeriesPoly);
+ drawing::Position3D aLast(aScaledLogicClipDoubleRect.getMaxX(),aTmpPoly.SequenceY[0][0],aTmpPoly.SequenceZ[0][0]);
+ // add connector line to last polygon
+ AddPointToPoly( aTmpPoly, aLast, pSeriesPoly->SequenceX.getLength() - 1 );
+ Clipping::clipPolygonAtRectangle( aTmpPoly, aScaledLogicClipDoubleRect, aPoly );
+ bIsClipped = true;
+ }
+ }
+
+ if( !bIsClipped )
+ Clipping::clipPolygonAtRectangle( *pSeriesPoly, pPosHelper->getScaledLogicClipDoubleRect(), aPoly );
+ }
+
+ if(!ShapeFactory::hasPolygonAnyLines(aPoly))
+ return false;
+
+ //transformation 3) -> 4)
+ pPosHelper->transformScaledLogicToScene( aPoly );
+
+ //create line:
+ uno::Reference< drawing::XShape > xShape(NULL);
+ if(m_nDimension==3)
+ {
+ double fDepth = this->getTransformedDepth();
+ sal_Int32 nPolyCount = aPoly.SequenceX.getLength();
+ for(sal_Int32 nPoly=0;nPoly<nPolyCount;nPoly++)
+ {
+ sal_Int32 nPointCount = aPoly.SequenceX[nPoly].getLength();
+ for(sal_Int32 nPoint=0;nPoint<nPointCount-1;nPoint++)
+ {
+ drawing::Position3D aPoint1, aPoint2;
+ aPoint1.PositionX = aPoly.SequenceX[nPoly][nPoint+1];
+ aPoint1.PositionY = aPoly.SequenceY[nPoly][nPoint+1];
+ aPoint1.PositionZ = aPoly.SequenceZ[nPoly][nPoint+1];
+
+ aPoint2.PositionX = aPoly.SequenceX[nPoly][nPoint];
+ aPoint2.PositionY = aPoly.SequenceY[nPoly][nPoint];
+ aPoint2.PositionZ = aPoly.SequenceZ[nPoly][nPoint];
+
+ Stripe aStripe( aPoint1, aPoint2, fDepth );
+
+ m_pShapeFactory->createStripe(xSeriesGroupShape_Shapes
+ , Stripe( aPoint1, aPoint2, fDepth )
+ , pSeries->getPropertiesOfSeries(), PropertyMapper::getPropertyNameMapForFilledSeriesProperties(), true, 1 );
+ }
+ }
+ }
+ else //m_nDimension!=3
+ {
+ xShape = m_pShapeFactory->createLine2D( xSeriesGroupShape_Shapes
+ , PolyToPointSequence( aPoly ) );
+ this->setMappedProperties( xShape
+ , pSeries->getPropertiesOfSeries()
+ , PropertyMapper::getPropertyNameMapForLineSeriesProperties() );
+ //because of this name this line will be used for marking
+ m_pShapeFactory->setShapeName( xShape, C2U("MarkHandles") );
+ }
+ return true;
+}
+
+bool AreaChart::impl_createArea( VDataSeries* pSeries
+ , drawing::PolyPolygonShape3D* pSeriesPoly
+ , drawing::PolyPolygonShape3D* pPreviousSeriesPoly
+ , PlottingPositionHelper* pPosHelper )
+{
+ //return true if an area was created successfully
+
+ uno::Reference< drawing::XShapes > xSeriesGroupShape_Shapes = getSeriesGroupShapeBackChild(pSeries, m_xSeriesTarget);
+ double zValue = pSeries->m_fLogicZPos;
+
+ drawing::PolyPolygonShape3D aPoly( *pSeriesPoly );
+ //add second part to the polygon (grounding points or previous series points)
+ if( m_bConnectLastToFirstPoint && !ShapeFactory::isPolygonEmptyOrSinglePoint(*pSeriesPoly) )
+ {
+ if( pPreviousSeriesPoly )
+ addPolygon( aPoly, *pPreviousSeriesPoly );
+ }
+ else if(!pPreviousSeriesPoly)
+ {
+ double fMinX = pSeries->m_fLogicMinX;
+ double fMaxX = pSeries->m_fLogicMaxX;
+ double fY = pPosHelper->getBaseValueY();//logic grounding
+ if( m_nDimension==3 )
+ fY = pPosHelper->getLogicMinY();
+
+ //clip to scale
+ if(fMaxX<pPosHelper->getLogicMinX() || fMinX>pPosHelper->getLogicMaxX())
+ return false;//no visible shape needed
+ pPosHelper->clipLogicValues( &fMinX, &fY, 0 );
+ pPosHelper->clipLogicValues( &fMaxX, 0, 0 );
+
+ //apply scaling
+ {
+ pPosHelper->doLogicScaling( &fMinX, &fY, &zValue );
+ pPosHelper->doLogicScaling( &fMaxX, 0, 0 );
+ }
+
+ AddPointToPoly( aPoly, drawing::Position3D( fMaxX,fY,zValue) );
+ AddPointToPoly( aPoly, drawing::Position3D( fMinX,fY,zValue) );
+ }
+ else
+ {
+ appendPoly( aPoly, *pPreviousSeriesPoly );
+ }
+ ShapeFactory::closePolygon(aPoly);
+
+ //apply clipping
+ {
+ drawing::PolyPolygonShape3D aClippedPoly;
+ Clipping::clipPolygonAtRectangle( aPoly, pPosHelper->getScaledLogicClipDoubleRect(), aClippedPoly, false );
+ ShapeFactory::closePolygon(aClippedPoly); //again necessary after clipping
+ aPoly = aClippedPoly;
+ }
+
+ if(!ShapeFactory::hasPolygonAnyLines(aPoly))
+ return false;
+
+ //transformation 3) -> 4)
+ pPosHelper->transformScaledLogicToScene( aPoly );
+
+ //create area:
+ uno::Reference< drawing::XShape > xShape(NULL);
+ if(m_nDimension==3)
+ {
+ xShape = m_pShapeFactory->createArea3D( xSeriesGroupShape_Shapes
+ , aPoly, this->getTransformedDepth() );
+ }
+ else //m_nDimension!=3
+ {
+ xShape = m_pShapeFactory->createArea2D( xSeriesGroupShape_Shapes
+ , aPoly );
+ }
+ this->setMappedProperties( xShape
+ , pSeries->getPropertiesOfSeries()
+ , PropertyMapper::getPropertyNameMapForFilledSeriesProperties() );
+ //because of this name this line will be used for marking
+ m_pShapeFactory->setShapeName( xShape, C2U("MarkHandles") );
+ return true;
+}
+
+void AreaChart::impl_createSeriesShapes()
+{
+ //the polygon shapes for each series need to be created before
+
+ //iterate through all series again to create the series shapes
+ ::std::vector< ::std::vector< VDataSeriesGroup > >::iterator aZSlotIter = m_aZSlots.begin();
+ const ::std::vector< ::std::vector< VDataSeriesGroup > >::const_iterator aZSlotEnd = m_aZSlots.end();
+//=============================================================================
+ for( sal_Int32 nZ=1; aZSlotIter != aZSlotEnd; aZSlotIter++, nZ++ )
+ {
+ ::std::vector< VDataSeriesGroup >::iterator aXSlotIter = aZSlotIter->begin();
+ const ::std::vector< VDataSeriesGroup >::const_iterator aXSlotEnd = aZSlotIter->end();
+
+ //=============================================================================
+ for( ; aXSlotIter != aXSlotEnd; aXSlotIter++ )
+ {
+ ::std::vector< VDataSeries* >* pSeriesList = &(aXSlotIter->m_aSeriesVector);
+
+ ::std::vector< VDataSeries* >::const_iterator aSeriesIter = pSeriesList->begin();
+ const ::std::vector< VDataSeries* >::const_iterator aSeriesEnd = pSeriesList->end();
+ //=============================================================================
+
+ std::map< sal_Int32, drawing::PolyPolygonShape3D* > aPreviousSeriesPolyMap;//a PreviousSeriesPoly for each different nAttachedAxisIndex
+ drawing::PolyPolygonShape3D* pSeriesPoly = NULL;
+
+ //iterate through all series
+ for( ; aSeriesIter != aSeriesEnd; aSeriesIter++ )
+ {
+ sal_Int32 nAttachedAxisIndex = (*aSeriesIter)->getAttachedAxisIndex();
+ PlottingPositionHelper* pPosHelper = &(this->getPlottingPositionHelper( nAttachedAxisIndex ));
+ if(!pPosHelper)
+ pPosHelper = m_pMainPosHelper;
+ PlotterBase::m_pPosHelper = pPosHelper;
+
+ createRegressionCurvesShapes( **aSeriesIter, m_xErrorBarTarget, m_xRegressionCurveEquationTarget,
+ m_pPosHelper->maySkipPointsInRegressionCalculation());
+
+ pSeriesPoly = &(*aSeriesIter)->m_aPolyPolygonShape3D;
+ if( m_bArea )
+ {
+ if( !impl_createArea( *aSeriesIter, pSeriesPoly, aPreviousSeriesPolyMap[nAttachedAxisIndex], pPosHelper ) )
+ continue;
+ }
+ if( m_bLine )
+ {
+ if( !impl_createLine( *aSeriesIter, pSeriesPoly, pPosHelper ) )
+ continue;
+ }
+ aPreviousSeriesPolyMap[nAttachedAxisIndex] = pSeriesPoly;
+ }//next series in x slot (next y slot)
+ }//next x slot
+ }//next z slot
+}
+
+namespace
+{
+
+void lcl_reorderSeries( ::std::vector< ::std::vector< VDataSeriesGroup > >& rZSlots )
+{
+ ::std::vector< ::std::vector< VDataSeriesGroup > > aRet( rZSlots.size() );
+
+ ::std::vector< ::std::vector< VDataSeriesGroup > >::reverse_iterator aZIt( rZSlots.rbegin() );
+ ::std::vector< ::std::vector< VDataSeriesGroup > >::reverse_iterator aZEnd( rZSlots.rend() );
+ for( ; aZIt != aZEnd; ++aZIt )
+ {
+ ::std::vector< VDataSeriesGroup > aXSlot( aZIt->size() );
+
+ ::std::vector< VDataSeriesGroup >::reverse_iterator aXIt( aZIt->rbegin() );
+ ::std::vector< VDataSeriesGroup >::reverse_iterator aXEnd( aZIt->rend() );
+ for( ; aXIt != aXEnd; ++aXIt )
+ aXSlot.push_back(*aXIt);
+
+ aRet.push_back(aXSlot);
+ }
+
+ rZSlots.clear();
+ rZSlots = aRet;
+}
+
+}//anonymous namespace
+
+//better performance for big data
+struct FormerPoint
+{
+ FormerPoint( double fX, double fY, double fZ )
+ : m_fX(fX), m_fY(fY), m_fZ(fZ)
+ {}
+ FormerPoint()
+ {
+ ::rtl::math::setNan( &m_fX );
+ ::rtl::math::setNan( &m_fY );
+ ::rtl::math::setNan( &m_fZ );
+ }
+
+ double m_fX;
+ double m_fY;
+ double m_fZ;
+};
+
+void AreaChart::createShapes()
+{
+ if( m_aZSlots.begin() == m_aZSlots.end() ) //no series
+ return;
+
+ if( m_nDimension == 2 && ( m_bArea || !m_bCategoryXAxis ) )
+ lcl_reorderSeries( m_aZSlots );
+
+ DBG_ASSERT(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is(),"AreaChart is not proper initialized");
+ if(!(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is()))
+ return;
+
+ //the text labels should be always on top of the other series shapes
+ //for area chart the error bars should be always on top of the other series shapes
+
+ //therefore create an own group for the texts and the error bars to move them to front
+ //(because the text group is created after the series group the texts are displayed on top)
+ m_xSeriesTarget = createGroupShape( m_xLogicTarget,rtl::OUString() );
+ if( m_bArea )
+ m_xErrorBarTarget = createGroupShape( m_xLogicTarget,rtl::OUString() );
+ else
+ m_xErrorBarTarget = m_xSeriesTarget;
+ m_xTextTarget = m_pShapeFactory->createGroup2D( m_xFinalTarget,rtl::OUString() );
+ m_xRegressionCurveEquationTarget = m_pShapeFactory->createGroup2D( m_xFinalTarget,rtl::OUString() );
+
+ //---------------------------------------------
+ //check necessary here that different Y axis can not be stacked in the same group? ... hm?
+
+ //update/create information for current group
+ double fLogicZ = 0.5;//as defined
+
+ sal_Int32 nStartIndex = 0; // inclusive ;..todo get somehow from x scale
+ sal_Int32 nEndIndex = VSeriesPlotter::getPointCount();
+ if(nEndIndex<=0)
+ nEndIndex=1;
+
+ //better performance for big data
+ std::map< VDataSeries*, FormerPoint > aSeriesFormerPointMap;
+ m_bPointsWereSkipped = false;
+ sal_Int32 nSkippedPoints = 0;
+ sal_Int32 nCreatedPoints = 0;
+ //
+
+//=============================================================================
+ //iterate through all x values per indices
+ for( sal_Int32 nIndex = nStartIndex; nIndex < nEndIndex; nIndex++ )
+ {
+ ::std::vector< ::std::vector< VDataSeriesGroup > >::iterator aZSlotIter = m_aZSlots.begin();
+ const ::std::vector< ::std::vector< VDataSeriesGroup > >::const_iterator aZSlotEnd = m_aZSlots.end();
+
+ std::map< sal_Int32, double > aLogicYSumMap;//one for each different nAttachedAxisIndex
+ for( ; aZSlotIter != aZSlotEnd; aZSlotIter++ )
+ {
+ ::std::vector< VDataSeriesGroup >::iterator aXSlotIter = aZSlotIter->begin();
+ const ::std::vector< VDataSeriesGroup >::const_iterator aXSlotEnd = aZSlotIter->end();
+
+ //iterate through all x slots in this category to get 100percent sum
+ for( ; aXSlotIter != aXSlotEnd; aXSlotIter++ )
+ {
+ ::std::vector< VDataSeries* >* pSeriesList = &(aXSlotIter->m_aSeriesVector);
+ ::std::vector< VDataSeries* >::const_iterator aSeriesIter = pSeriesList->begin();
+ const ::std::vector< VDataSeries* >::const_iterator aSeriesEnd = pSeriesList->end();
+
+ for( ; aSeriesIter != aSeriesEnd; aSeriesIter++ )
+ {
+ VDataSeries* pSeries( *aSeriesIter );
+ if(!pSeries)
+ continue;
+
+ sal_Int32 nAttachedAxisIndex = pSeries->getAttachedAxisIndex();
+ if( aLogicYSumMap.find(nAttachedAxisIndex)==aLogicYSumMap.end() )
+ aLogicYSumMap[nAttachedAxisIndex]=0.0;
+
+ PlottingPositionHelper* pPosHelper = &(this->getPlottingPositionHelper( nAttachedAxisIndex ));
+ if(!pPosHelper)
+ pPosHelper = m_pMainPosHelper;
+ PlotterBase::m_pPosHelper = pPosHelper;
+
+ double fAdd = pSeries->getYValue( nIndex );
+ if( !::rtl::math::isNan(fAdd) && !::rtl::math::isInf(fAdd) )
+ aLogicYSumMap[nAttachedAxisIndex] += fabs( fAdd );
+ }
+ }
+ }
+
+//=============================================================================
+ aZSlotIter = m_aZSlots.begin();
+ for( sal_Int32 nZ=1; aZSlotIter != aZSlotEnd; aZSlotIter++, nZ++ )
+ {
+ ::std::vector< VDataSeriesGroup >::iterator aXSlotIter = aZSlotIter->begin();
+ const ::std::vector< VDataSeriesGroup >::const_iterator aXSlotEnd = aZSlotIter->end();
+
+ //for the area chart there should be at most one x slot (no side by side stacking available)
+ //attention different: xSlots are always interpreted as independent areas one behind the other: @todo this doesn't work why not???
+ aXSlotIter = aZSlotIter->begin();
+ for( sal_Int32 nX=0; aXSlotIter != aXSlotEnd; aXSlotIter++, nX++ )
+ {
+ ::std::vector< VDataSeries* >* pSeriesList = &(aXSlotIter->m_aSeriesVector);
+ ::std::vector< VDataSeries* >::const_iterator aSeriesIter = pSeriesList->begin();
+ const ::std::vector< VDataSeries* >::const_iterator aSeriesEnd = pSeriesList->end();
+
+ std::map< sal_Int32, double > aLogicYForNextSeriesMap;//one for each different nAttachedAxisIndex
+ //=============================================================================
+ //iterate through all series
+ for( sal_Int32 nSeriesIndex = 0; aSeriesIter != aSeriesEnd; aSeriesIter++, nSeriesIndex++ )
+ {
+ VDataSeries* pSeries( *aSeriesIter );
+ if(!pSeries)
+ continue;
+
+ /* #i70133# ignore points outside of series length in standard area
+ charts. Stacked area charts will use missing points as zeros. In
+ standard charts, pSeriesList contains only one series. */
+ if( m_bArea && (pSeriesList->size() == 1) && (nIndex >= (*aSeriesIter)->getTotalPointCount()) )
+ continue;
+
+ uno::Reference< drawing::XShapes > xSeriesGroupShape_Shapes = getSeriesGroupShapeFrontChild(*aSeriesIter, m_xSeriesTarget);
+
+ sal_Int32 nAttachedAxisIndex = (*aSeriesIter)->getAttachedAxisIndex();
+ PlottingPositionHelper* pPosHelper = &(this->getPlottingPositionHelper( nAttachedAxisIndex ));
+ if(!pPosHelper)
+ pPosHelper = m_pMainPosHelper;
+ PlotterBase::m_pPosHelper = pPosHelper;
+
+ if(m_nDimension==3)
+ fLogicZ = nZ+0.5;
+ (*aSeriesIter)->m_fLogicZPos = fLogicZ;
+
+ //collect data point information (logic coordinates, style ):
+ double fLogicX = (*aSeriesIter)->getXValue(nIndex);
+ double fLogicY = (*aSeriesIter)->getYValue(nIndex);
+
+ if( m_bIsPolarCooSys && m_bArea &&
+ ( ::rtl::math::isNan(fLogicY) || ::rtl::math::isInf(fLogicY) ) )
+ {
+ if( (*aSeriesIter)->getMissingValueTreatment() == ::com::sun::star::chart::MissingValueTreatment::LEAVE_GAP )
+ {
+ if( pSeriesList->size() == 1 || nSeriesIndex == 0 )
+ {
+ fLogicY = pPosHelper->getLogicMinY();
+ if( !pPosHelper->isMathematicalOrientationY() )
+ fLogicY = pPosHelper->getLogicMaxY();
+ }
+ else
+ fLogicY = 0.0;
+ }
+ }
+
+ if( m_nDimension==3 && m_bArea && pSeriesList->size()!=1 )
+ fLogicY = fabs( fLogicY );
+
+ if( pPosHelper->isPercentY() && !::rtl::math::approxEqual( aLogicYSumMap[nAttachedAxisIndex], 0.0 ) )
+ {
+ fLogicY = fabs( fLogicY )/aLogicYSumMap[nAttachedAxisIndex];
+ }
+
+ if( ::rtl::math::isNan(fLogicX) || ::rtl::math::isInf(fLogicX)
+ || ::rtl::math::isNan(fLogicY) || ::rtl::math::isInf(fLogicY)
+ || ::rtl::math::isNan(fLogicZ) || ::rtl::math::isInf(fLogicZ) )
+ {
+ if( (*aSeriesIter)->getMissingValueTreatment() == ::com::sun::star::chart::MissingValueTreatment::LEAVE_GAP )
+ {
+ drawing::PolyPolygonShape3D& rPolygon = (*aSeriesIter)->m_aPolyPolygonShape3D;
+ sal_Int32& rIndex = (*aSeriesIter)->m_nPolygonIndex;
+ if( 0<= rIndex && rIndex < rPolygon.SequenceX.getLength() )
+ {
+ if( rPolygon.SequenceX[ rIndex ].getLength() )
+ rIndex++; //start a new polygon for the next point if the current poly is not empty
+ }
+ }
+ continue;
+ }
+
+ if( aLogicYForNextSeriesMap.find(nAttachedAxisIndex) == aLogicYForNextSeriesMap.end() )
+ aLogicYForNextSeriesMap[nAttachedAxisIndex] = 0.0;
+
+ double fLogicValueForLabeDisplay = fLogicY;
+
+ fLogicY += aLogicYForNextSeriesMap[nAttachedAxisIndex];
+ aLogicYForNextSeriesMap[nAttachedAxisIndex] = fLogicY;
+
+ bool bIsVisible = pPosHelper->isLogicVisible( fLogicX, fLogicY, fLogicZ );
+
+ //remind minimal and maximal x values for area 'grounding' points
+ //only for filled area
+ {
+ double& rfMinX = (*aSeriesIter)->m_fLogicMinX;
+ if(!nIndex||fLogicX<rfMinX)
+ rfMinX=fLogicX;
+ double& rfMaxX = (*aSeriesIter)->m_fLogicMaxX;
+ if(!nIndex||fLogicX>rfMaxX)
+ rfMaxX=fLogicX;
+ }
+
+ drawing::Position3D aUnscaledLogicPosition( fLogicX, fLogicY, fLogicZ );
+ drawing::Position3D aScaledLogicPosition(aUnscaledLogicPosition);
+ pPosHelper->doLogicScaling( aScaledLogicPosition );
+
+ //transformation 3) -> 4)
+ drawing::Position3D aScenePosition( pPosHelper->transformLogicToScene( fLogicX,fLogicY,fLogicZ, false ) );
+
+ //better performance for big data
+ FormerPoint aFormerPoint( aSeriesFormerPointMap[pSeries] );
+ pPosHelper->setCoordinateSystemResolution( m_aCoordinateSystemResolution );
+ if( !pSeries->isAttributedDataPoint(nIndex)
+ &&
+ pPosHelper->isSameForGivenResolution( aFormerPoint.m_fX, aFormerPoint.m_fY, aFormerPoint.m_fZ
+ , aScaledLogicPosition.PositionX, aScaledLogicPosition.PositionY, aScaledLogicPosition.PositionZ ) )
+ {
+ nSkippedPoints++;
+ m_bPointsWereSkipped = true;
+ continue;
+ }
+ aSeriesFormerPointMap[pSeries] = FormerPoint(aScaledLogicPosition.PositionX, aScaledLogicPosition.PositionY, aScaledLogicPosition.PositionZ);
+ //
+
+ //store point information for series polygon
+ //for area and/or line (symbols only do not need this)
+ if( isValidPosition(aScaledLogicPosition) )
+ {
+ AddPointToPoly( (*aSeriesIter)->m_aPolyPolygonShape3D, aScaledLogicPosition, (*aSeriesIter)->m_nPolygonIndex );
+
+ //prepare clipping for filled net charts
+ if( !bIsVisible && m_bIsPolarCooSys && m_bArea )
+ {
+ drawing::Position3D aClippedPos(aScaledLogicPosition);
+ pPosHelper->clipScaledLogicValues( 0, &aClippedPos.PositionY, 0 );
+ if( pPosHelper->isLogicVisible( aClippedPos.PositionX, aClippedPos.PositionY, aClippedPos.PositionZ ) )
+ {
+ AddPointToPoly( (*aSeriesIter)->m_aPolyPolygonShape3D, aClippedPos, (*aSeriesIter)->m_nPolygonIndex );
+ AddPointToPoly( (*aSeriesIter)->m_aPolyPolygonShape3D, aScaledLogicPosition, (*aSeriesIter)->m_nPolygonIndex );
+ }
+ }
+ }
+
+ //create a single datapoint if point is visible
+ //apply clipping:
+ if( !bIsVisible )
+ continue;
+
+ bool bCreateErrorBar = false;
+ {
+ uno::Reference< beans::XPropertySet > xErrorBarProp(pSeries->getYErrorBarProperties(nIndex));
+ if( xErrorBarProp.is() )
+ {
+ bool bShowPositive = false;
+ bool bShowNegative = false;
+ xErrorBarProp->getPropertyValue( C2U( "ShowPositiveError" )) >>= bShowPositive;
+ xErrorBarProp->getPropertyValue( C2U( "ShowNegativeError" )) >>= bShowNegative;
+ bCreateErrorBar = bShowPositive || bShowNegative;
+ }
+ }
+
+ Symbol* pSymbolProperties = m_bSymbol ? (*aSeriesIter)->getSymbolProperties( nIndex ) : 0;
+ bool bCreateSymbol = pSymbolProperties && (pSymbolProperties->Style != SymbolStyle_NONE);
+
+ if( !bCreateSymbol && !bCreateErrorBar && !pSeries->getDataPointLabelIfLabel(nIndex) )
+ continue;
+
+ //create a group shape for this point and add to the series shape:
+ rtl::OUString aPointCID = ObjectIdentifier::createPointCID(
+ (*aSeriesIter)->getPointCID_Stub(), nIndex );
+ uno::Reference< drawing::XShapes > xPointGroupShape_Shapes(
+ createGroupShape(xSeriesGroupShape_Shapes,aPointCID) );
+ uno::Reference<drawing::XShape> xPointGroupShape_Shape =
+ uno::Reference<drawing::XShape>( xPointGroupShape_Shapes, uno::UNO_QUERY );
+
+ {
+ nCreatedPoints++;
+
+ //create data point
+ drawing::Direction3D aSymbolSize(0,0,0);
+ if( bCreateSymbol )
+ {
+ if(m_nDimension!=3)
+ {
+ if( pSymbolProperties )
+ {
+ if( pSymbolProperties->Style != SymbolStyle_NONE )
+ {
+ aSymbolSize.DirectionX = pSymbolProperties->Size.Width;
+ aSymbolSize.DirectionY = pSymbolProperties->Size.Height;
+ }
+
+ if( pSymbolProperties->Style == SymbolStyle_STANDARD )
+ {
+ sal_Int32 nSymbol = pSymbolProperties->StandardSymbol;
+ m_pShapeFactory->createSymbol2D( xPointGroupShape_Shapes
+ , aScenePosition, aSymbolSize
+ , nSymbol
+ , pSymbolProperties->BorderColor
+ , pSymbolProperties->FillColor );
+ }
+ else if( pSymbolProperties->Style == SymbolStyle_GRAPHIC )
+ {
+ m_pShapeFactory->createGraphic2D( xPointGroupShape_Shapes
+ , aScenePosition , aSymbolSize
+ , pSymbolProperties->Graphic );
+ }
+ //@todo other symbol styles
+ }
+ }
+ }
+ //create error bar
+ createErrorBar_Y( aUnscaledLogicPosition, **aSeriesIter, nIndex, m_xErrorBarTarget );
+
+ //create data point label
+ if( (**aSeriesIter).getDataPointLabelIfLabel(nIndex) )
+ {
+ LabelAlignment eAlignment = LABEL_ALIGN_TOP;
+ drawing::Position3D aScenePosition3D( aScenePosition.PositionX
+ , aScenePosition.PositionY
+ , aScenePosition.PositionZ+this->getTransformedDepth() );
+
+ sal_Int32 nLabelPlacement = pSeries->getLabelPlacement( nIndex, m_xChartTypeModel, m_nDimension, pPosHelper->isSwapXAndY() );
+
+ switch(nLabelPlacement)
+ {
+ case ::com::sun::star::chart::DataLabelPlacement::TOP:
+ aScenePosition3D.PositionY -= (aSymbolSize.DirectionY/2+1);
+ eAlignment = LABEL_ALIGN_TOP;
+ break;
+ case ::com::sun::star::chart::DataLabelPlacement::BOTTOM:
+ aScenePosition3D.PositionY += (aSymbolSize.DirectionY/2+1);
+ eAlignment = LABEL_ALIGN_BOTTOM;
+ break;
+ case ::com::sun::star::chart::DataLabelPlacement::LEFT:
+ aScenePosition3D.PositionX -= (aSymbolSize.DirectionX/2+1);
+ eAlignment = LABEL_ALIGN_LEFT;
+ break;
+ case ::com::sun::star::chart::DataLabelPlacement::RIGHT:
+ aScenePosition3D.PositionX += (aSymbolSize.DirectionX/2+1);
+ eAlignment = LABEL_ALIGN_RIGHT;
+ break;
+ case ::com::sun::star::chart::DataLabelPlacement::CENTER:
+ eAlignment = LABEL_ALIGN_CENTER;
+ //todo implement this different for area charts
+ break;
+ default:
+ DBG_ERROR("this label alignment is not implemented yet");
+ aScenePosition3D.PositionY -= (aSymbolSize.DirectionY/2+1);
+ eAlignment = LABEL_ALIGN_TOP;
+ break;
+ }
+
+ awt::Point aScreenPosition2D;//get the screen position for the labels
+ sal_Int32 nOffset = 100; //todo maybe calculate this font height dependent
+ if( m_bIsPolarCooSys && nLabelPlacement == ::com::sun::star::chart::DataLabelPlacement::OUTSIDE )
+ {
+ PolarPlottingPositionHelper* pPolarPosHelper = dynamic_cast<PolarPlottingPositionHelper*>(pPosHelper);
+ if( pPolarPosHelper )
+ {
+ PolarLabelPositionHelper aPolarLabelPositionHelper(pPolarPosHelper,m_nDimension,m_xLogicTarget,m_pShapeFactory);
+ aScreenPosition2D = awt::Point( aPolarLabelPositionHelper.getLabelScreenPositionAndAlignmentForLogicValues(
+ eAlignment, fLogicX, fLogicY, fLogicZ, nOffset ));
+ }
+ }
+ else
+ {
+ if(LABEL_ALIGN_CENTER==eAlignment || m_nDimension == 3 )
+ nOffset = 0;
+ aScreenPosition2D = awt::Point( LabelPositionHelper(pPosHelper,m_nDimension,m_xLogicTarget,m_pShapeFactory)
+ .transformSceneToScreenPosition( aScenePosition3D ) );
+ }
+
+ this->createDataLabel( m_xTextTarget, **aSeriesIter, nIndex
+ , fLogicValueForLabeDisplay
+ , aLogicYSumMap[nAttachedAxisIndex], aScreenPosition2D, eAlignment, nOffset );
+ }
+ }
+
+ //remove PointGroupShape if empty
+ if(!xPointGroupShape_Shapes->getCount())
+ xSeriesGroupShape_Shapes->remove(xPointGroupShape_Shape);
+
+ }//next series in x slot (next y slot)
+ }//next x slot
+ }//next z slot
+ }//next category
+//=============================================================================
+//=============================================================================
+//=============================================================================
+
+ impl_createSeriesShapes();
+
+ /* @todo remove series shapes if empty
+ //remove and delete point-group-shape if empty
+ if(!xSeriesGroupShape_Shapes->getCount())
+ {
+ (*aSeriesIter)->m_xShape.set(NULL);
+ m_xLogicTarget->remove(xSeriesGroupShape_Shape);
+ }
+ */
+
+ //remove and delete series-group-shape if empty
+
+ //... todo
+
+ OSL_TRACE( "\nPPPPPPPPP<<<<<<<<<<<< area chart :: createShapes():: skipped points: %d created points: %d", nSkippedPoints, nCreatedPoints );
+}
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
diff --git a/chart2/source/view/charttypes/AreaChart.hxx b/chart2/source/view/charttypes/AreaChart.hxx
new file mode 100644
index 000000000000..6924509a62a1
--- /dev/null
+++ b/chart2/source/view/charttypes/AreaChart.hxx
@@ -0,0 +1,134 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CHART2_AREACHART_HXX
+#define _CHART2_AREACHART_HXX
+
+#include "VSeriesPlotter.hxx"
+#include <com/sun/star/chart2/CurveStyle.hpp>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+class AreaPositionHelper;
+
+class AreaChart : public VSeriesPlotter
+{
+ //-------------------------------------------------------------------------
+ // public methods
+ //-------------------------------------------------------------------------
+public:
+ AreaChart( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::chart2::XChartType >& xChartTypeModel
+ , sal_Int32 nDimensionCount
+ , bool bCategoryXAxis, bool bNoArea=false
+ , PlottingPositionHelper* pPlottingPositionHelper=NULL //takes owner ship
+ , bool bConnectLastToFirstPoint=false
+ , bool bExpandIfValuesCloseToBorder=true
+ , sal_Int32 nKeepAspectRatio=-1 //0->no 1->yes other value->automatic
+ , const ::com::sun::star::drawing::Direction3D& rAspectRatio=::com::sun::star::drawing::Direction3D(1,1,1)//only taken into account if nKeepAspectRatio==1
+ );
+ virtual ~AreaChart();
+
+ //-------------------------------------------------------------------------
+ // chart2::XPlotter
+ //-------------------------------------------------------------------------
+
+ virtual void SAL_CALL createShapes();
+ /*
+ virtual ::rtl::OUString SAL_CALL getCoordinateSystemTypeID( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL setScales( const ::com::sun::star::uno::Sequence< ::com::sun::star::chart2::ExplicitScaleData >& rScales ) 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 addSeries( VDataSeries* pSeries, sal_Int32 zSlot = -1, sal_Int32 xSlot = -1,sal_Int32 ySlot = -1 );
+
+ //-------------------
+ virtual ::com::sun::star::drawing::Direction3D getPreferredDiagramAspectRatio() const;
+ virtual bool keepAspectRatio() const;
+
+ //-------------------------------------------------------------------------
+ // MinimumAndMaximumSupplier
+ //-------------------------------------------------------------------------
+ virtual double getMinimumX();
+ virtual double getMaximumX();
+ virtual bool isExpandIfValuesCloseToBorder( sal_Int32 nDimensionIndex );
+ virtual bool isSeperateStackingForDifferentSigns( sal_Int32 nDimensionIndex );
+
+ //-------------------------------------------------------------------------
+
+ virtual ::com::sun::star::chart2::LegendSymbolStyle getLegendSymbolStyle();
+ virtual ::com::sun::star::uno::Any getExplicitSymbol( const VDataSeries& rSeries, sal_Int32 nPointIndex=-1/*-1 for series symbol*/ );
+
+ //-------------------------------------------------------------------------
+ //-------------------------------------------------------------------------
+ //-------------------------------------------------------------------------
+private: //methods
+ //no default constructor
+ AreaChart();
+
+ void impl_createSeriesShapes();
+ bool impl_createArea( VDataSeries* pSeries
+ , ::com::sun::star::drawing::PolyPolygonShape3D* pSeriesPoly
+ , ::com::sun::star::drawing::PolyPolygonShape3D* pPreviousSeriesPoly
+ , PlottingPositionHelper* pPosHelper );
+ bool impl_createLine( VDataSeries* pSeries
+ , ::com::sun::star::drawing::PolyPolygonShape3D* pSeriesPoly
+ , PlottingPositionHelper* pPosHelper );
+
+private: //member
+ PlottingPositionHelper* m_pMainPosHelper;
+
+ bool m_bArea;//false -> line or symbol only
+ bool m_bLine;
+ bool m_bSymbol;
+ bool m_bIsPolarCooSys;//used e.g. for net chart (the data labels need to be placed different)
+ bool m_bConnectLastToFirstPoint;//used e.g. for net chart
+ bool m_bExpandIfValuesCloseToBorder; // e.g. false for net charts
+
+ sal_Int32 m_nKeepAspectRatio; //0->no 1->yes other value->automatic
+ ::com::sun::star::drawing::Direction3D m_aGivenAspectRatio; //only used if nKeepAspectRatio==1
+
+ //Properties for splines:
+ ::com::sun::star::chart2::CurveStyle m_eCurveStyle;
+ sal_Int32 m_nCurveResolution;
+ sal_Int32 m_nSplineOrder;
+
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShapes > m_xSeriesTarget;
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShapes > m_xErrorBarTarget;
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShapes > m_xTextTarget;
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShapes > m_xRegressionCurveEquationTarget;
+};
+//.............................................................................
+} //namespace chart
+//.............................................................................
+#endif
diff --git a/chart2/source/view/charttypes/BarChart.cxx b/chart2/source/view/charttypes/BarChart.cxx
new file mode 100755
index 000000000000..0d7ef403f87d
--- /dev/null
+++ b/chart2/source/view/charttypes/BarChart.cxx
@@ -0,0 +1,1019 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_chart2.hxx"
+
+#include "BarChart.hxx"
+#include "ShapeFactory.hxx"
+//#include "chartview/servicenames_charttypes.hxx"
+//#include "servicenames_coosystems.hxx"
+#include "CommonConverters.hxx"
+#include "ObjectIdentifier.hxx"
+#include "LabelPositionHelper.hxx"
+#include "BarPositionHelper.hxx"
+#include "macros.hxx"
+#include "AxisIndexDefines.hxx"
+#include "Clipping.hxx"
+
+#include <com/sun/star/chart/DataLabelPlacement.hpp>
+
+#include <com/sun/star/chart2/DataPointGeometry3D.hpp>
+#include <tools/debug.hxx>
+#include <rtl/math.hxx>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+using namespace ::com::sun::star;
+using namespace ::rtl::math;
+using namespace ::com::sun::star::chart2;
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+BarChart::BarChart( const uno::Reference<XChartType>& xChartTypeModel
+ , sal_Int32 nDimensionCount )
+ : VSeriesPlotter( xChartTypeModel, nDimensionCount )
+ , m_pMainPosHelper( new BarPositionHelper() )
+{
+ PlotterBase::m_pPosHelper = m_pMainPosHelper;
+ VSeriesPlotter::m_pMainPosHelper = m_pMainPosHelper;
+
+ try
+ {
+ if( m_xChartTypeModelProps.is() )
+ {
+ m_xChartTypeModelProps->getPropertyValue( C2U( "OverlapSequence" ) ) >>= m_aOverlapSequence;
+ m_xChartTypeModelProps->getPropertyValue( C2U( "GapwidthSequence" ) ) >>= m_aGapwidthSequence;
+ }
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+}
+
+BarChart::~BarChart()
+{
+ delete m_pMainPosHelper;
+}
+
+//-------------------------------------------------------------------------
+
+PlottingPositionHelper& BarChart::getPlottingPositionHelper( sal_Int32 nAxisIndex ) const
+{
+ PlottingPositionHelper& rPosHelper = VSeriesPlotter::getPlottingPositionHelper( nAxisIndex );
+
+ BarPositionHelper* pBarPosHelper = dynamic_cast<BarPositionHelper*>(&rPosHelper);
+ if( pBarPosHelper && nAxisIndex >= 0 )
+ {
+ if( nAxisIndex < m_aOverlapSequence.getLength() )
+ pBarPosHelper->setInnerDistance( -m_aOverlapSequence[nAxisIndex]/100.0 );
+ if( nAxisIndex < m_aGapwidthSequence.getLength() )
+ pBarPosHelper->setOuterDistance( m_aGapwidthSequence[nAxisIndex]/100.0 );
+ }
+
+ return rPosHelper;
+}
+
+drawing::Direction3D BarChart::getPreferredDiagramAspectRatio() const
+{
+ drawing::Direction3D aRet(1.0,1.0,1.0);
+ if( m_nDimension == 3 )
+ {
+ aRet = drawing::Direction3D(1.0,-1.0,1.0);
+ BarPositionHelper* pPosHelper = dynamic_cast<BarPositionHelper*>(&( this->getPlottingPositionHelper( MAIN_AXIS_INDEX) ) );
+ drawing::Direction3D aScale( pPosHelper->getScaledLogicWidth() );
+ if(aScale.DirectionX!=0.0)
+ {
+ double fXSlotCount = 1.0;
+ if(!m_aZSlots.empty())
+ fXSlotCount = m_aZSlots.begin()->size();
+
+ aRet.DirectionZ = aScale.DirectionZ/(aScale.DirectionX + aScale.DirectionX*(fXSlotCount-1.0)*pPosHelper->getSlotWidth());
+ }
+ else
+ return VSeriesPlotter::getPreferredDiagramAspectRatio();
+ if(aRet.DirectionZ<0.05)
+ aRet.DirectionZ=0.05;
+ if(aRet.DirectionZ>10)
+ aRet.DirectionZ=10;
+
+ if( m_pMainPosHelper && m_pMainPosHelper->isSwapXAndY() )
+ {
+ double fTemp = aRet.DirectionX;
+ aRet.DirectionX = aRet.DirectionY;
+ aRet.DirectionY = fTemp;
+ }
+ }
+ else
+ aRet = drawing::Direction3D(-1,-1,-1);
+ return aRet;
+}
+
+bool BarChart::keepAspectRatio() const
+{
+ if( m_nDimension == 3 )
+ return true;
+ return true;
+}
+
+//-------------------------------------------------------------------------
+// MinimumAndMaximumSupplier
+//-------------------------------------------------------------------------
+
+double BarChart::getMinimumX()
+{
+ if( m_bCategoryXAxis )
+ return 0.5;//first category (index 0) matches with real number 1.0
+ return VSeriesPlotter::getMinimumX();
+}
+double BarChart::getMaximumX()
+{
+ if( m_bCategoryXAxis )
+ {
+ //return category count
+ sal_Int32 nPointCount = getPointCount();
+ return nPointCount+0.5;//first category (index 0) matches with real number 1.0
+ }
+ return VSeriesPlotter::getMaximumX();
+}
+
+//-----------------------------------------------------------------
+// lang::XServiceInfo
+//-----------------------------------------------------------------
+/*
+APPHELPER_XSERVICEINFO_IMPL(BarChart,CHART2_VIEW_BARCHART_SERVICE_IMPLEMENTATION_NAME)
+
+ uno::Sequence< rtl::OUString > BarChart
+::getSupportedServiceNames_Static()
+{
+ uno::Sequence< rtl::OUString > aSNS( 1 );
+ aSNS.getArray()[ 0 ] = CHART2_VIEW_BARCHART_SERVICE_NAME;
+ return aSNS;
+}
+*/
+/*
+//-----------------------------------------------------------------
+// chart2::XPlotter
+//-----------------------------------------------------------------
+
+ ::rtl::OUString SAL_CALL BarChart
+::getCoordinateSystemTypeID()
+ throw (uno::RuntimeException)
+{
+ return CHART2_COOSYSTEM_CARTESIAN_SERVICE_NAME;
+}
+*/
+
+awt::Point BarChart::getLabelScreenPositionAndAlignment(
+ LabelAlignment& rAlignment, sal_Int32 nLabelPlacement
+ , double fScaledX, double fScaledLowerYValue, double fScaledUpperYValue, double fScaledZ
+ , double fScaledLowerBarDepth, double fScaledUpperBarDepth, double fBaseValue
+ , BarPositionHelper* pPosHelper
+ ) const
+{
+ double fX = fScaledX;
+ double fY = fScaledUpperYValue;
+ double fZ = fScaledZ;
+ bool bReverse = !pPosHelper->isMathematicalOrientationY();
+ bool bNormalOutside = (!bReverse == !!(fBaseValue < fScaledUpperYValue));
+ double fDepth = fScaledUpperBarDepth;
+
+ switch(nLabelPlacement)
+ {
+ case ::com::sun::star::chart::DataLabelPlacement::TOP:
+ {
+ if( !pPosHelper->isSwapXAndY() )
+ {
+ fY = bReverse ? fScaledLowerYValue : fScaledUpperYValue;
+ rAlignment = LABEL_ALIGN_TOP;
+ if(3==m_nDimension)
+ fDepth = bReverse ? fabs(fScaledLowerBarDepth) : fabs(fScaledUpperBarDepth);
+ }
+ else
+ {
+ fY -= (fScaledUpperYValue-fScaledLowerYValue)/2.0;
+ rAlignment = LABEL_ALIGN_CENTER;
+ DBG_ERROR( "top label placement is not really supported by horizontal bar charts" );
+ }
+ }
+ break;
+ case ::com::sun::star::chart::DataLabelPlacement::BOTTOM:
+ {
+ if(!pPosHelper->isSwapXAndY())
+ {
+ fY = bReverse ? fScaledUpperYValue : fScaledLowerYValue;
+ rAlignment = LABEL_ALIGN_BOTTOM;
+ if(3==m_nDimension)
+ fDepth = bReverse ? fabs(fScaledUpperBarDepth) : fabs(fScaledLowerBarDepth);
+ }
+ else
+ {
+ fY -= (fScaledUpperYValue-fScaledLowerYValue)/2.0;
+ rAlignment = LABEL_ALIGN_CENTER;
+ DBG_ERROR( "bottom label placement is not supported by horizontal bar charts" );
+ }
+ }
+ break;
+ case ::com::sun::star::chart::DataLabelPlacement::LEFT:
+ {
+ if( pPosHelper->isSwapXAndY() )
+ {
+ fY = bReverse ? fScaledUpperYValue : fScaledLowerYValue;
+ rAlignment = LABEL_ALIGN_LEFT;
+ if(3==m_nDimension)
+ fDepth = bReverse ? fabs(fScaledUpperBarDepth) : fabs(fScaledLowerBarDepth);
+ }
+ else
+ {
+ fY -= (fScaledUpperYValue-fScaledLowerYValue)/2.0;
+ rAlignment = LABEL_ALIGN_CENTER;
+ DBG_ERROR( "left label placement is not supported by column charts" );
+ }
+ }
+ break;
+ case ::com::sun::star::chart::DataLabelPlacement::RIGHT:
+ {
+ if( pPosHelper->isSwapXAndY() )
+ {
+ fY = bReverse ? fScaledLowerYValue : fScaledUpperYValue;
+ rAlignment = LABEL_ALIGN_RIGHT;
+ if(3==m_nDimension)
+ fDepth = bReverse ? fabs(fScaledLowerBarDepth) : fabs(fScaledUpperBarDepth);
+ }
+ else
+ {
+ fY -= (fScaledUpperYValue-fScaledLowerYValue)/2.0;
+ rAlignment = LABEL_ALIGN_CENTER;
+ DBG_ERROR( "right label placement is not supported by column charts" );
+ }
+ }
+ break;
+ case ::com::sun::star::chart::DataLabelPlacement::OUTSIDE:
+ {
+ fY = (fBaseValue < fScaledUpperYValue) ? fScaledUpperYValue : fScaledLowerYValue;
+ if( pPosHelper->isSwapXAndY() )
+ rAlignment = bNormalOutside ? LABEL_ALIGN_RIGHT : LABEL_ALIGN_LEFT;
+ else
+ rAlignment = bNormalOutside ? LABEL_ALIGN_TOP : LABEL_ALIGN_BOTTOM;
+ if(3==m_nDimension)
+ fDepth = (fBaseValue < fScaledUpperYValue) ? fabs(fScaledUpperBarDepth) : fabs(fScaledLowerBarDepth);
+ }
+ break;
+ case ::com::sun::star::chart::DataLabelPlacement::INSIDE:
+ {
+ fY = (fBaseValue < fScaledUpperYValue) ? fScaledUpperYValue : fScaledLowerYValue;
+ if( pPosHelper->isSwapXAndY() )
+ rAlignment = bNormalOutside ? LABEL_ALIGN_LEFT : LABEL_ALIGN_RIGHT;
+ else
+ rAlignment = bNormalOutside ? LABEL_ALIGN_BOTTOM : LABEL_ALIGN_TOP;
+ if(3==m_nDimension)
+ fDepth = (fBaseValue < fScaledUpperYValue) ? fabs(fScaledUpperBarDepth) : fabs(fScaledLowerBarDepth);
+ }
+ break;
+ case ::com::sun::star::chart::DataLabelPlacement::NEAR_ORIGIN:
+ {
+ fY = (fBaseValue < fScaledUpperYValue) ? fScaledLowerYValue : fScaledUpperYValue;
+ if( pPosHelper->isSwapXAndY() )
+ rAlignment = bNormalOutside ? LABEL_ALIGN_RIGHT : LABEL_ALIGN_LEFT;
+ else
+ rAlignment = bNormalOutside ? LABEL_ALIGN_TOP : LABEL_ALIGN_BOTTOM;
+ if(3==m_nDimension)
+ fDepth = (fBaseValue < fScaledUpperYValue) ? fabs(fScaledLowerBarDepth) : fabs(fScaledUpperBarDepth);
+ }
+ break;
+ case ::com::sun::star::chart::DataLabelPlacement::CENTER:
+ fY -= (fScaledUpperYValue-fScaledLowerYValue)/2.0;
+ rAlignment = LABEL_ALIGN_CENTER;
+ if(3==m_nDimension)
+ fDepth = fabs(fScaledUpperBarDepth-fScaledLowerBarDepth)/2.0;
+ break;
+ default:
+ DBG_ERROR("this label alignment is not implemented yet");
+
+ break;
+ }
+ if(3==m_nDimension)
+ fZ -= fDepth/2.0;
+
+ drawing::Position3D aScenePosition3D( pPosHelper->
+ transformScaledLogicToScene( fX, fY, fZ, true ) );
+ return LabelPositionHelper(pPosHelper,m_nDimension,m_xLogicTarget,m_pShapeFactory)
+ .transformSceneToScreenPosition( aScenePosition3D );
+}
+
+uno::Reference< drawing::XShape > BarChart::createDataPoint3D_Bar(
+ const uno::Reference< drawing::XShapes >& xTarget
+ , const drawing::Position3D& rPosition, const drawing::Direction3D& rSize
+ , double fTopHeight, sal_Int32 nRotateZAngleHundredthDegree
+ , const uno::Reference< beans::XPropertySet >& xObjectProperties
+ , sal_Int32 nGeometry3D )
+{
+ bool bRoundedEdges = true;
+ try
+ {
+ if( xObjectProperties.is() )
+ {
+ sal_Int16 nPercentDiagonal = 0;
+ xObjectProperties->getPropertyValue( C2U( "PercentDiagonal" ) ) >>= nPercentDiagonal;
+ if( nPercentDiagonal < 5 )
+ bRoundedEdges = false;
+ }
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+
+ uno::Reference< drawing::XShape > xShape(NULL);
+ switch( nGeometry3D )
+ {
+ case DataPointGeometry3D::CYLINDER:
+ xShape = m_pShapeFactory->createCylinder( xTarget, rPosition, rSize, nRotateZAngleHundredthDegree );
+ break;
+ case DataPointGeometry3D::CONE:
+ xShape = m_pShapeFactory->createCone( xTarget, rPosition, rSize, fTopHeight, nRotateZAngleHundredthDegree );
+ break;
+ case DataPointGeometry3D::PYRAMID:
+ xShape = m_pShapeFactory->createPyramid( xTarget, rPosition, rSize, fTopHeight, nRotateZAngleHundredthDegree>0
+ , xObjectProperties, PropertyMapper::getPropertyNameMapForFilledSeriesProperties() );
+ break;
+ case DataPointGeometry3D::CUBOID:
+ default:
+ xShape = m_pShapeFactory->createCube( xTarget, rPosition, rSize
+ , nRotateZAngleHundredthDegree, xObjectProperties
+ , PropertyMapper::getPropertyNameMapForFilledSeriesProperties(), bRoundedEdges );
+ return xShape;
+ }
+ if( nGeometry3D != DataPointGeometry3D::PYRAMID )
+ this->setMappedProperties( xShape, xObjectProperties, PropertyMapper::getPropertyNameMapForFilledSeriesProperties() );
+ return xShape;
+}
+
+namespace
+{
+bool lcl_hasGeometry3DVariableWidth( sal_Int32 nGeometry3D )
+{
+ bool bRet = false;
+ switch( nGeometry3D )
+ {
+ case DataPointGeometry3D::PYRAMID:
+ case DataPointGeometry3D::CONE:
+ bRet = true;
+ break;
+ case DataPointGeometry3D::CUBOID:
+ case DataPointGeometry3D::CYLINDER:
+ default:
+ bRet = false;
+ break;
+ }
+ return bRet;
+}
+}// end anonymous namespace
+
+void BarChart::addSeries( VDataSeries* pSeries, sal_Int32 zSlot, sal_Int32 xSlot, sal_Int32 ySlot )
+{
+ if( !pSeries )
+ return;
+ if(m_nDimension==2)
+ {
+ //2ND_AXIS_IN_BARS put series on second scales to different z slot as temporary workaround
+ //this needs to be redesigned if 3d bars are also able to display secondary axes
+
+ sal_Int32 nAxisIndex = pSeries->getAttachedAxisIndex();
+ zSlot = nAxisIndex;
+
+ if( !pSeries->getGroupBarsPerAxis() )
+ zSlot = 0;
+ if(zSlot>=static_cast<sal_Int32>(m_aZSlots.size()))
+ m_aZSlots.resize(zSlot+1);
+ }
+ VSeriesPlotter::addSeries( pSeries, zSlot, xSlot, ySlot );
+}
+
+//better performance for big data
+struct FormerBarPoint
+{
+ FormerBarPoint( double fX, double fUpperY, double fLowerY, double fZ )
+ : m_fX(fX), m_fUpperY(fUpperY), m_fLowerY(fLowerY), m_fZ(fZ)
+ {}
+ FormerBarPoint()
+ {
+ ::rtl::math::setNan( &m_fX );
+ ::rtl::math::setNan( &m_fUpperY );
+ ::rtl::math::setNan( &m_fLowerY );
+ ::rtl::math::setNan( &m_fZ );
+ }
+
+ double m_fX;
+ double m_fUpperY;
+ double m_fLowerY;
+ double m_fZ;
+};
+
+void BarChart::adaptOverlapAndGapwidthForGroupBarsPerAxis()
+{
+ //adapt m_aOverlapSequence and m_aGapwidthSequence for the groupBarsPerAxis feature
+ //thus the different series use the same settings
+
+ VDataSeries* pFirstSeries = getFirstSeries();
+ if(pFirstSeries && !pFirstSeries->getGroupBarsPerAxis() )
+ {
+ sal_Int32 nAxisIndex = pFirstSeries->getAttachedAxisIndex();
+ sal_Int32 nN = 0;
+ sal_Int32 nUseThisIndex = nAxisIndex;
+ if( nUseThisIndex < 0 || nUseThisIndex >= m_aOverlapSequence.getLength() )
+ nUseThisIndex = 0;
+ for( nN = 0; nN < m_aOverlapSequence.getLength(); nN++ )
+ {
+ if(nN!=nUseThisIndex)
+ m_aOverlapSequence[nN] = m_aOverlapSequence[nUseThisIndex];
+ }
+
+ nUseThisIndex = nAxisIndex;
+ if( nUseThisIndex < 0 || nUseThisIndex >= m_aGapwidthSequence.getLength() )
+ nUseThisIndex = 0;
+ for( nN = 0; nN < m_aGapwidthSequence.getLength(); nN++ )
+ {
+ if(nN!=nUseThisIndex)
+ m_aGapwidthSequence[nN] = m_aGapwidthSequence[nUseThisIndex];
+ }
+ }
+}
+
+void BarChart::createShapes()
+{
+ if( m_aZSlots.begin() == m_aZSlots.end() ) //no series
+ return;
+
+ DBG_ASSERT(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is(),"BarChart is not proper initialized");
+ if(!(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is()))
+ return;
+
+ //the text labels should be always on top of the other series shapes
+ //therefore create an own group for the texts to move them to front
+ //(because the text group is created after the series group the texts are displayed on top)
+
+ //the regression curves should always be on top of the bars but beneath the text labels
+ //to achieve this the regression curve target is created after the series target and before the text target
+
+ uno::Reference< drawing::XShapes > xSeriesTarget(
+ createGroupShape( m_xLogicTarget,rtl::OUString() ));
+ uno::Reference< drawing::XShapes > xRegressionCurveTarget(
+ createGroupShape( m_xLogicTarget,rtl::OUString() ));
+ uno::Reference< drawing::XShapes > xTextTarget(
+ m_pShapeFactory->createGroup2D( m_xFinalTarget,rtl::OUString() ));
+
+
+ //---------------------------------------------
+ uno::Reference< drawing::XShapes > xRegressionCurveEquationTarget(
+ m_pShapeFactory->createGroup2D( m_xFinalTarget,rtl::OUString() ));
+ //check necessary here that different Y axis can not be stacked in the same group? ... hm?
+
+ double fLogicZ = 0.0;//as defined
+
+ bool bDrawConnectionLines = false;
+ bool bDrawConnectionLinesInited = false;
+ bool bOnlyConnectionLinesForThisPoint = false;
+
+ adaptOverlapAndGapwidthForGroupBarsPerAxis();
+
+ //better performance for big data
+ std::map< VDataSeries*, FormerBarPoint > aSeriesFormerPointMap;
+ m_bPointsWereSkipped = false;
+ sal_Int32 nSkippedPoints = 0;
+ sal_Int32 nCreatedPoints = 0;
+ //
+
+ //(@todo maybe different iteration for breaks in axis ?)
+ sal_Int32 nStartCategoryIndex = m_pMainPosHelper->getStartCategoryIndex(); // inclusive
+ sal_Int32 nEndCategoryIndex = m_pMainPosHelper->getEndCategoryIndex(); //inclusive
+//=============================================================================
+ //iterate through all shown categories
+ for( sal_Int32 nCatIndex = nStartCategoryIndex; nCatIndex < nEndCategoryIndex; nCatIndex++ )
+ {
+ ::std::vector< ::std::vector< VDataSeriesGroup > >::iterator aZSlotIter = m_aZSlots.begin();
+ const ::std::vector< ::std::vector< VDataSeriesGroup > >::const_iterator aZSlotEnd = m_aZSlots.end();
+
+ //sum up the values for all series in a complete z zlot per attached axis
+ ::std::map< sal_Int32, double > aLogicYSumMap;
+ for( ; aZSlotIter != aZSlotEnd; aZSlotIter++ )
+ {
+ ::std::vector< VDataSeriesGroup >::iterator aXSlotIter = aZSlotIter->begin();
+ const ::std::vector< VDataSeriesGroup >::const_iterator aXSlotEnd = aZSlotIter->end();
+
+ for( aXSlotIter = aZSlotIter->begin(); aXSlotIter != aXSlotEnd; aXSlotIter++ )
+ {
+ sal_Int32 nAttachedAxisIndex = aXSlotIter->getAttachedAxisIndexForFirstSeries();
+ if( aLogicYSumMap.find(nAttachedAxisIndex)==aLogicYSumMap.end() )
+ aLogicYSumMap[nAttachedAxisIndex]=0.0;
+
+ double fMinimumY = 0.0, fMaximumY = 0.0;
+ aXSlotIter->calculateYMinAndMaxForCategory( nCatIndex
+ , isSeperateStackingForDifferentSigns( 1 ), fMinimumY, fMaximumY, nAttachedAxisIndex );
+
+ if( !::rtl::math::isNan( fMaximumY ) && fMaximumY > 0)
+ aLogicYSumMap[nAttachedAxisIndex] += fMaximumY;
+ if( !::rtl::math::isNan( fMinimumY ) && fMinimumY < 0)
+ aLogicYSumMap[nAttachedAxisIndex] += fabs(fMinimumY);
+ }
+ }
+
+//=============================================================================
+ aZSlotIter = m_aZSlots.begin();
+ for( sal_Int32 nZ=1; aZSlotIter != aZSlotEnd; aZSlotIter++, nZ++ )
+ {
+ ::std::vector< VDataSeriesGroup >::iterator aXSlotIter = aZSlotIter->begin();
+ const ::std::vector< VDataSeriesGroup >::const_iterator aXSlotEnd = aZSlotIter->end();
+
+//=============================================================================
+ //iterate through all x slots in this category
+ double fSlotX=0;
+ for( aXSlotIter = aZSlotIter->begin(); aXSlotIter != aXSlotEnd; aXSlotIter++, fSlotX+=1.0 )
+ {
+ sal_Int32 nAttachedAxisIndex = 0;
+ BarPositionHelper* pPosHelper = m_pMainPosHelper;
+ if( aXSlotIter != aXSlotEnd )
+ {
+ nAttachedAxisIndex = aXSlotIter->getAttachedAxisIndexForFirstSeries();
+ //2ND_AXIS_IN_BARS so far one can assume to have the same plotter for each z slot
+ pPosHelper = dynamic_cast<BarPositionHelper*>(&( this->getPlottingPositionHelper( nAttachedAxisIndex ) ) );
+ if(!pPosHelper)
+ pPosHelper = m_pMainPosHelper;
+ }
+ PlotterBase::m_pPosHelper = pPosHelper;
+
+ //update/create information for current group
+ pPosHelper->updateSeriesCount( aZSlotIter->size() );
+ double fLogicBaseWidth = pPosHelper->getSlotWidth();
+
+ ::std::vector< VDataSeries* >* pSeriesList = &(aXSlotIter->m_aSeriesVector);
+
+ // get distance from base value to maximum and minimum
+
+ double fMinimumY = 0.0, fMaximumY = 0.0;
+ aXSlotIter->calculateYMinAndMaxForCategory( nCatIndex
+ , isSeperateStackingForDifferentSigns( 1 ), fMinimumY, fMaximumY, nAttachedAxisIndex );
+
+ double fLogicPositiveYSum = 0.0;
+ if( !::rtl::math::isNan( fMaximumY ) )
+ fLogicPositiveYSum = fMaximumY;
+
+ double fLogicNegativeYSum = 0.0;
+ if( !::rtl::math::isNan( fMinimumY ) )
+ fLogicNegativeYSum = fMinimumY;
+
+ if( pPosHelper->isPercentY() )
+ {
+ /* #i70395# fLogicPositiveYSum contains sum of all positive
+ values, if any, otherwise the highest negative value.
+ fLogicNegativeYSum contains sum of all negative values,
+ if any, otherwise the lowest positive value.
+ Afterwards, fLogicPositiveYSum will contain the maximum
+ (positive) value that is related to 100%. */
+
+ // do nothing if there are positive values only
+ if( fLogicNegativeYSum < 0.0 )
+ {
+ // fLogicPositiveYSum<0 => negative values only, use absolute of negative sum
+ if( fLogicPositiveYSum < 0.0 )
+ fLogicPositiveYSum = -fLogicNegativeYSum;
+ // otherwise there are positive and negative values, calculate total distance
+ else
+ fLogicPositiveYSum -= fLogicNegativeYSum;
+ }
+ fLogicNegativeYSum = 0.0;
+ }
+
+ double fBaseValue = 0.0;
+ if( !pPosHelper->isPercentY() && pSeriesList->size()<=1 )
+ fBaseValue = pPosHelper->getBaseValueY();
+ double fPositiveLogicYForNextSeries = fBaseValue;
+ double fNegativeLogicYForNextSeries = fBaseValue;
+
+ ::std::vector< VDataSeries* >::const_iterator aSeriesIter = pSeriesList->begin();
+ const ::std::vector< VDataSeries* >::const_iterator aSeriesEnd = pSeriesList->end();
+ aSeriesIter = pSeriesList->begin();
+ //=============================================================================
+ //iterate through all series in this x slot
+ for( ; aSeriesIter != aSeriesEnd; aSeriesIter++ )
+ {
+ VDataSeries* pSeries( *aSeriesIter );
+ if(!pSeries)
+ continue;
+
+ bOnlyConnectionLinesForThisPoint = false;
+
+ if(nCatIndex==nStartCategoryIndex)//do not create a regression line for each point
+ createRegressionCurvesShapes( **aSeriesIter, xRegressionCurveTarget, xRegressionCurveEquationTarget,
+ m_pPosHelper->maySkipPointsInRegressionCalculation());
+
+ if( !bDrawConnectionLinesInited )
+ {
+ bDrawConnectionLines = pSeries->getConnectBars();
+ if( m_nDimension==3 )
+ bDrawConnectionLines = false;
+ if( bDrawConnectionLines && pSeriesList->size()==1 )
+ {
+ //detect wether we have a stacked chart or not:
+ StackingDirection eDirection = pSeries->getStackingDirection();
+ if( eDirection != StackingDirection_Y_STACKING )
+ bDrawConnectionLines = false;
+ }
+ bDrawConnectionLinesInited = true;
+ }
+
+ //------------
+
+ uno::Reference< drawing::XShapes > xSeriesGroupShape_Shapes(
+ getSeriesGroupShape(*aSeriesIter, xSeriesTarget) );
+
+ //collect data point information (logic coordinates, style ):
+ double fLogicX = pPosHelper->getSlotPos( (*aSeriesIter)->getXValue( nCatIndex ), fSlotX );
+ double fLogicBarHeight = (*aSeriesIter)->getYValue( nCatIndex );
+ if( ::rtl::math::isNan( fLogicBarHeight )) //no value at this category
+ continue;
+
+ double fLogicValueForLabeDisplay = fLogicBarHeight;
+ fLogicBarHeight-=fBaseValue;
+
+ if( pPosHelper->isPercentY() )
+ {
+ if(fLogicPositiveYSum!=0.0)
+ fLogicBarHeight = fabs( fLogicBarHeight )/fLogicPositiveYSum;
+ else
+ fLogicBarHeight = 0.0;
+ }
+
+ //sort negative and positive values, to display them on different sides of the x axis
+ bool bPositive = fLogicBarHeight >= 0.0;
+ double fLowerYValue = bPositive ? fPositiveLogicYForNextSeries : fNegativeLogicYForNextSeries;
+ double fUpperYValue = fLowerYValue+fLogicBarHeight;
+ if( bPositive )
+ fPositiveLogicYForNextSeries += fLogicBarHeight;
+ else
+ fNegativeLogicYForNextSeries += fLogicBarHeight;
+
+ if(m_nDimension==3)
+ fLogicZ = nZ;
+
+ drawing::Position3D aUnscaledLogicPosition( fLogicX, fUpperYValue, fLogicZ );
+
+ //@todo ... start an iteration over the different breaks of the axis
+ //each subsystem may add an additional shape to form the whole point
+ //create a group shape for this point and add to the series shape:
+ // uno::Reference< drawing::XShapes > xPointGroupShape_Shapes( createGroupShape(xSeriesGroupShape_Shapes) );
+ // uno::Reference<drawing::XShape> xPointGroupShape_Shape =
+ // uno::Reference<drawing::XShape>( xPointGroupShape_Shapes, uno::UNO_QUERY );
+ //as long as we do not iterate we do not need to create an additional group for each point
+ uno::Reference< drawing::XShapes > xPointGroupShape_Shapes = xSeriesGroupShape_Shapes;
+ uno::Reference< beans::XPropertySet > xDataPointProperties( (*aSeriesIter)->getPropertiesOfPoint( nCatIndex ) );
+ sal_Int32 nGeometry3D = DataPointGeometry3D::CUBOID;
+ if(m_nDimension==3) try
+ {
+ xDataPointProperties->getPropertyValue( C2U( "Geometry3D" )) >>= nGeometry3D;
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+
+ //@todo iterate through all subsystems to create partial points
+ {
+ //@todo select a suiteable PositionHelper for this subsystem
+ BarPositionHelper* pSubPosHelper = pPosHelper;
+
+ double fUnclippedUpperYValue = fUpperYValue;
+
+ //apply clipping to Y
+ if( !pPosHelper->clipYRange(fLowerYValue,fUpperYValue) )
+ {
+ if( bDrawConnectionLines )
+ bOnlyConnectionLinesForThisPoint = true;
+ else
+ continue;
+ }
+ //@todo clipping of X and Z is not fully integrated so far, as there is a need to create different objects
+
+ //apply scaling to Y before calculating width (necessary to maintain gradient in clipped objects)
+ pSubPosHelper->doLogicScaling(NULL,&fLowerYValue,NULL);
+ pSubPosHelper->doLogicScaling(NULL,&fUpperYValue,NULL);
+ //scaling of X and Z is not provided as the created objects should be symmetric in that dimensions
+
+ pSubPosHelper->doLogicScaling(NULL,&fUnclippedUpperYValue,NULL);
+
+ //calculate resulting width
+ double fCompleteHeight = bPositive ? fLogicPositiveYSum : fLogicNegativeYSum;
+ if( pPosHelper->isPercentY() )
+ fCompleteHeight = 1.0;
+ double fLogicBarWidth = fLogicBaseWidth;
+ double fTopHeight=approxSub(fCompleteHeight,fUpperYValue);
+ if(!bPositive)
+ fTopHeight=approxSub(fCompleteHeight,fLowerYValue);
+ double fLogicYStart = bPositive ? fLowerYValue : fUpperYValue;
+ double fMiddleHeight = fUpperYValue-fLowerYValue;
+ if(!bPositive)
+ fMiddleHeight*=-1.0;
+ double fLogicBarDepth = 0.5;
+ if(m_nDimension==3)
+ {
+ if( lcl_hasGeometry3DVariableWidth(nGeometry3D) && fCompleteHeight!=0.0 )
+ {
+ double fHeight = fCompleteHeight-fLowerYValue;
+ if(!bPositive)
+ fHeight = fCompleteHeight-fUpperYValue;
+ fLogicBarWidth = fLogicBaseWidth*fHeight/(fCompleteHeight);
+ if(fLogicBarWidth<=0.0)
+ fLogicBarWidth=fLogicBaseWidth;
+ fLogicBarDepth = fLogicBarDepth*fHeight/(fCompleteHeight);
+ if(fLogicBarDepth<=0.0)
+ fLogicBarDepth*=-1.0;
+ }
+ }
+
+ //better performance for big data
+ FormerBarPoint aFormerPoint( aSeriesFormerPointMap[pSeries] );
+ pPosHelper->setCoordinateSystemResolution( m_aCoordinateSystemResolution );
+ if( !pSeries->isAttributedDataPoint(nCatIndex)
+ &&
+ pPosHelper->isSameForGivenResolution( aFormerPoint.m_fX, aFormerPoint.m_fUpperY, aFormerPoint.m_fZ
+ , fLogicX, fUpperYValue, fLogicZ )
+ &&
+ pPosHelper->isSameForGivenResolution( aFormerPoint.m_fX, aFormerPoint.m_fLowerY, aFormerPoint.m_fZ
+ , fLogicX, fLowerYValue, fLogicZ )
+ )
+ {
+ nSkippedPoints++;
+ m_bPointsWereSkipped = true;
+ continue;
+ }
+ aSeriesFormerPointMap[pSeries] = FormerBarPoint(fLogicX,fUpperYValue,fLowerYValue,fLogicZ);
+ //
+
+ //
+ if( bDrawConnectionLines )
+ {
+ //store point information for connection lines
+
+ drawing::Position3D aLeftUpperPoint( fLogicX-fLogicBarWidth/2.0,fUnclippedUpperYValue,fLogicZ );
+ drawing::Position3D aRightUpperPoint( fLogicX+fLogicBarWidth/2.0,fUnclippedUpperYValue,fLogicZ );
+
+ if( isValidPosition(aLeftUpperPoint) )
+ AddPointToPoly( (*aSeriesIter)->m_aPolyPolygonShape3D, aLeftUpperPoint );
+ if( isValidPosition(aRightUpperPoint) )
+ AddPointToPoly( (*aSeriesIter)->m_aPolyPolygonShape3D, aRightUpperPoint );
+ }
+
+ if( bOnlyConnectionLinesForThisPoint )
+ continue;
+
+ //maybe additional possibility for performance improvement
+ //bool bCreateLineInsteadOfComplexGeometryDueToMissingSpace = false;
+ //pPosHelper->isSameForGivenResolution( fLogicX-fLogicBarWidth/2.0, fLowerYValue, fLogicZ
+ // , fLogicX+fLogicBarWidth/2.0, fLowerYValue, fLogicZ );
+
+ nCreatedPoints++;
+ //create partial point
+ if( !approxEqual(fLowerYValue,fUpperYValue) )
+ {
+ uno::Reference< drawing::XShape > xShape;
+ if( m_nDimension==3 )
+ {
+ drawing::Position3D aLogicBottom (fLogicX,fLogicYStart,fLogicZ);
+ drawing::Position3D aLogicLeftBottomFront (fLogicX+fLogicBarWidth/2.0,fLogicYStart,fLogicZ-fLogicBarDepth/2.0);
+ drawing::Position3D aLogicRightDeepTop (fLogicX-fLogicBarWidth/2.0,fLogicYStart+fMiddleHeight,fLogicZ+fLogicBarDepth/2.0);
+ drawing::Position3D aLogicTopTop (fLogicX,fLogicYStart+fMiddleHeight+fTopHeight,fLogicZ);
+
+ uno::Reference< XTransformation > xTransformation = pSubPosHelper->getTransformationScaledLogicToScene();
+
+ //transformation 3) -> 4)
+ drawing::Position3D aTransformedBottom ( SequenceToPosition3D( xTransformation->transform( Position3DToSequence(aLogicBottom) ) ) );
+ drawing::Position3D aTransformedLeftBottomFront ( SequenceToPosition3D( xTransformation->transform( Position3DToSequence(aLogicLeftBottomFront) ) ) );
+ drawing::Position3D aTransformedRightDeepTop ( SequenceToPosition3D( xTransformation->transform( Position3DToSequence(aLogicRightDeepTop) ) ) );
+ drawing::Position3D aTransformedTopTop ( SequenceToPosition3D( xTransformation->transform( Position3DToSequence(aLogicTopTop) ) ) );
+
+ drawing::Direction3D aSize = aTransformedRightDeepTop - aTransformedLeftBottomFront;
+ drawing::Direction3D aTopSize( aTransformedTopTop - aTransformedRightDeepTop );
+ fTopHeight = aTopSize.DirectionY;
+
+ sal_Int32 nRotateZAngleHundredthDegree = 0;
+ if( pPosHelper->isSwapXAndY() )
+ {
+ fTopHeight = aTopSize.DirectionX;
+ nRotateZAngleHundredthDegree = 90*100;
+ aSize = drawing::Direction3D(aSize.DirectionY,aSize.DirectionX,aSize.DirectionZ);
+ }
+
+ if( aSize.DirectionX < 0 )
+ aSize.DirectionX *= -1.0;
+ if( aSize.DirectionZ < 0 )
+ aSize.DirectionZ *= -1.0;
+ if( fTopHeight < 0 )
+ fTopHeight *= -1.0;
+
+ xShape = createDataPoint3D_Bar(
+ xPointGroupShape_Shapes, aTransformedBottom, aSize, fTopHeight, nRotateZAngleHundredthDegree
+ , xDataPointProperties, nGeometry3D );
+ }
+ else //m_nDimension!=3
+ {
+ //if( bCreateLineInsteadOfComplexGeometryDueToMissingSpace )
+ //{
+ // drawing::PolyPolygonShape3D aPoly;
+ // drawing::Position3D aUpperPoint( fLogicX,fUpperYValue,fLogicZ );
+ // drawing::Position3D aLowerPoint( fLogicX,fLowerYValue,fLogicZ );
+
+ // AddPointToPoly( aPoly, aUpperPoint );
+ // AddPointToPoly( aPoly, aLowerPoint );
+
+ // VLineProperties aLineProperties;
+ // aLineProperties.initFromPropertySet( xDataPointProperties, true /*bUseSeriesPropertyNames*/ );
+ // if( !aLineProperties.isLineVisible() )
+ // {
+ // //todo
+ // //aLineProperties.Color =
+ // }
+
+ // xShape = m_pShapeFactory->createLine2D( xPointGroupShape_Shapes
+ // , PolyToPointSequence(aPoly), &aLineProperties );
+ //}
+
+ drawing::PolyPolygonShape3D aPoly;
+ drawing::Position3D aLeftUpperPoint( fLogicX-fLogicBarWidth/2.0,fUpperYValue,fLogicZ );
+ drawing::Position3D aRightUpperPoint( fLogicX+fLogicBarWidth/2.0,fUpperYValue,fLogicZ );
+
+ AddPointToPoly( aPoly, drawing::Position3D( fLogicX-fLogicBarWidth/2.0,fLowerYValue,fLogicZ) );
+ AddPointToPoly( aPoly, drawing::Position3D( fLogicX+fLogicBarWidth/2.0,fLowerYValue,fLogicZ) );
+ AddPointToPoly( aPoly, aRightUpperPoint );
+ AddPointToPoly( aPoly, aLeftUpperPoint );
+ AddPointToPoly( aPoly, drawing::Position3D( fLogicX-fLogicBarWidth/2.0,fLowerYValue,fLogicZ) );
+ pPosHelper->transformScaledLogicToScene( aPoly );
+ xShape = m_pShapeFactory->createArea2D( xPointGroupShape_Shapes, aPoly );
+ this->setMappedProperties( xShape, xDataPointProperties, PropertyMapper::getPropertyNameMapForFilledSeriesProperties() );
+ }
+ //set name/classified ObjectID (CID)
+ ShapeFactory::setShapeName(xShape
+ , ObjectIdentifier::createPointCID(
+ (*aSeriesIter)->getPointCID_Stub(),nCatIndex) );
+ }
+
+ //create error bar
+ createErrorBar_Y( aUnscaledLogicPosition, **aSeriesIter, nCatIndex, m_xLogicTarget );
+
+ //------------
+ //create data point label
+ if( (**aSeriesIter).getDataPointLabelIfLabel(nCatIndex) )
+ {
+ double fLogicSum = aLogicYSumMap[nAttachedAxisIndex];
+
+ LabelAlignment eAlignment(LABEL_ALIGN_CENTER);
+ sal_Int32 nLabelPlacement = pSeries->getLabelPlacement( nCatIndex, m_xChartTypeModel, m_nDimension, pPosHelper->isSwapXAndY() );
+
+ double fLowerBarDepth = fLogicBarDepth;
+ double fUpperBarDepth = fLogicBarDepth;
+ {
+ double fOuterBarDepth = fLogicBarDepth;
+ if( lcl_hasGeometry3DVariableWidth(nGeometry3D) && fCompleteHeight!=0.0 )
+ {
+ fOuterBarDepth = fLogicBarDepth * (fTopHeight)/(fabs(fCompleteHeight));
+ fLowerBarDepth = (fBaseValue < fUpperYValue) ? fabs(fLogicBarDepth) : fabs(fOuterBarDepth);
+ fUpperBarDepth = (fBaseValue < fUpperYValue) ? fabs(fOuterBarDepth) : fabs(fLogicBarDepth);
+ }
+ }
+
+ awt::Point aScreenPosition2D( this->getLabelScreenPositionAndAlignment(
+ eAlignment, nLabelPlacement
+ , fLogicX, fLowerYValue, fUpperYValue, fLogicZ
+ , fLowerBarDepth, fUpperBarDepth, fBaseValue, pPosHelper ));
+ sal_Int32 nOffset = 0;
+ if(LABEL_ALIGN_CENTER!=eAlignment)
+ {
+ nOffset = 100;//add some spacing //@todo maybe get more intelligent values
+ if( m_nDimension == 3 )
+ nOffset = 260;
+ }
+ this->createDataLabel( xTextTarget, **aSeriesIter, nCatIndex
+ , fLogicValueForLabeDisplay, fLogicSum, aScreenPosition2D, eAlignment, nOffset );
+ }
+
+ }//end iteration through partial points
+
+ //remove PointGroupShape if empty
+ // if(!xPointGroupShape_Shapes->getCount())
+ // xSeriesGroupShape_Shapes->remove(xPointGroupShape_Shape);
+ }//next series in x slot (next y slot)
+ }//next x slot
+ }//next z slot
+ }//next category
+//=============================================================================
+//=============================================================================
+//=============================================================================
+ if( bDrawConnectionLines )
+ {
+ ::std::vector< ::std::vector< VDataSeriesGroup > >::iterator aZSlotIter = m_aZSlots.begin();
+ const ::std::vector< ::std::vector< VDataSeriesGroup > >::const_iterator aZSlotEnd = m_aZSlots.end();
+//=============================================================================
+ for( sal_Int32 nZ=1; aZSlotIter != aZSlotEnd; aZSlotIter++, nZ++ )
+ {
+ ::std::vector< VDataSeriesGroup >::iterator aXSlotIter = aZSlotIter->begin();
+ const ::std::vector< VDataSeriesGroup >::const_iterator aXSlotEnd = aZSlotIter->end();
+
+ BarPositionHelper* pPosHelper = m_pMainPosHelper;
+ if( aXSlotIter != aXSlotEnd )
+ {
+ sal_Int32 nAttachedAxisIndex = aXSlotIter->getAttachedAxisIndexForFirstSeries();
+ //2ND_AXIS_IN_BARS so far one can assume to have the same plotter for each z slot
+ pPosHelper = dynamic_cast<BarPositionHelper*>(&( this->getPlottingPositionHelper( nAttachedAxisIndex ) ) );
+ if(!pPosHelper)
+ pPosHelper = m_pMainPosHelper;
+ }
+ PlotterBase::m_pPosHelper = pPosHelper;
+
+//=============================================================================
+ //iterate through all x slots in this category
+ for( double fSlotX=0; aXSlotIter != aXSlotEnd; aXSlotIter++, fSlotX+=1.0 )
+ {
+ ::std::vector< VDataSeries* >* pSeriesList = &(aXSlotIter->m_aSeriesVector);
+
+ ::std::vector< VDataSeries* >::const_iterator aSeriesIter = pSeriesList->begin();
+ const ::std::vector< VDataSeries* >::const_iterator aSeriesEnd = pSeriesList->end();
+ aSeriesIter = pSeriesList->begin();
+//=============================================================================
+ //iterate through all series in this x slot
+ for( ; aSeriesIter != aSeriesEnd; aSeriesIter++ )
+ {
+ VDataSeries* pSeries( *aSeriesIter );
+ if(!pSeries)
+ continue;
+ drawing::PolyPolygonShape3D* pSeriesPoly = &pSeries->m_aPolyPolygonShape3D;
+ if(!ShapeFactory::hasPolygonAnyLines(*pSeriesPoly))
+ continue;
+
+ drawing::PolyPolygonShape3D aPoly;
+ Clipping::clipPolygonAtRectangle( *pSeriesPoly, pPosHelper->getScaledLogicClipDoubleRect(), aPoly );
+
+ if(!ShapeFactory::hasPolygonAnyLines(aPoly))
+ continue;
+
+ //transformation 3) -> 4)
+ pPosHelper->transformScaledLogicToScene( aPoly );
+
+ uno::Reference< drawing::XShapes > xSeriesGroupShape_Shapes(
+ getSeriesGroupShape(*aSeriesIter, xSeriesTarget) );
+ uno::Reference< drawing::XShape > xShape( m_pShapeFactory->createLine2D(
+ xSeriesGroupShape_Shapes, PolyToPointSequence( aPoly ) ) );
+ this->setMappedProperties( xShape, pSeries->getPropertiesOfSeries()
+ , PropertyMapper::getPropertyNameMapForFilledSeriesProperties() );
+ }
+ }
+ }
+ }
+
+ /* @todo remove series shapes if empty
+ //remove and delete point-group-shape if empty
+ if(!xSeriesGroupShape_Shapes->getCount())
+ {
+ (*aSeriesIter)->m_xShape.set(NULL);
+ m_xLogicTarget->remove(xSeriesGroupShape_Shape);
+ }
+ */
+
+ //remove and delete series-group-shape if empty
+
+ //... todo
+
+ OSL_TRACE( "\nPPPPPPPPP<<<<<<<<<<<< bar chart :: createShapes():: skipped points: %d created points: %d", nSkippedPoints, nCreatedPoints );
+}
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
diff --git a/chart2/source/view/charttypes/BarChart.hxx b/chart2/source/view/charttypes/BarChart.hxx
new file mode 100644
index 000000000000..403628f7fc43
--- /dev/null
+++ b/chart2/source/view/charttypes/BarChart.hxx
@@ -0,0 +1,110 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CHART2_BARCHART_HXX
+#define _CHART2_BARCHART_HXX
+
+#include "VSeriesPlotter.hxx"
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+class BarPositionHelper;
+
+class BarChart : public VSeriesPlotter
+{
+ //-------------------------------------------------------------------------
+ // public methods
+ //-------------------------------------------------------------------------
+public:
+ BarChart( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::chart2::XChartType >& xChartTypeModel
+ , sal_Int32 nDimensionCount );
+ virtual ~BarChart();
+
+ //-------------------------------------------------------------------------
+ // chart2::XPlotter
+ //-------------------------------------------------------------------------
+
+ virtual void SAL_CALL createShapes();
+ /*
+ virtual ::rtl::OUString SAL_CALL getCoordinateSystemTypeID( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL setScales( const ::com::sun::star::uno::Sequence< ::com::sun::star::chart2::ExplicitScaleData >& rScales ) 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 addSeries( VDataSeries* pSeries, sal_Int32 zSlot = -1, sal_Int32 xSlot = -1,sal_Int32 ySlot = -1 );
+
+ //-------------------
+ virtual ::com::sun::star::drawing::Direction3D getPreferredDiagramAspectRatio() const;
+ virtual bool keepAspectRatio() const;
+
+ //-------------------------------------------------------------------------
+ // MinimumAndMaximumSupplier
+ //-------------------------------------------------------------------------
+ virtual double getMinimumX();
+ virtual double getMaximumX();
+
+ //-------------------------------------------------------------------------
+ //-------------------------------------------------------------------------
+ //-------------------------------------------------------------------------
+
+private: //methods
+ //no default constructor
+ BarChart();
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >
+ createDataPoint3D_Bar(
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShapes >& xTarget
+ , const ::com::sun::star::drawing::Position3D& rPosition
+ , const ::com::sun::star::drawing::Direction3D& rSize
+ , double fTopHeight, sal_Int32 nRotateZAngleHundredthDegree
+ , const ::com::sun::star::uno::Reference<
+ ::com::sun::star::beans::XPropertySet >& xObjectProperties
+ , sal_Int32 nGeometry3D );
+
+ ::com::sun::star::awt::Point getLabelScreenPositionAndAlignment(
+ LabelAlignment& rAlignment, sal_Int32 nLabelPlacement
+ , double fScaledX, double fScaledLowerYValue, double fScaledUpperYValue, double fScaledZ
+ , double fScaledLowerBarDepth, double fScaledUpperBarDepth, double fBaseValue
+ , BarPositionHelper* pPosHelper ) const;
+
+ virtual PlottingPositionHelper& getPlottingPositionHelper( sal_Int32 nAxisIndex ) const;//nAxisIndex indicates wether the position belongs to the main axis ( nAxisIndex==0 ) or secondary axis ( nAxisIndex==1 )
+
+ void adaptOverlapAndGapwidthForGroupBarsPerAxis();
+
+private: //member
+ BarPositionHelper* m_pMainPosHelper;
+ ::com::sun::star::uno::Sequence< sal_Int32 > m_aOverlapSequence;
+ ::com::sun::star::uno::Sequence< sal_Int32 > m_aGapwidthSequence;
+};
+//.............................................................................
+} //namespace chart
+//.............................................................................
+#endif
diff --git a/chart2/source/view/charttypes/BarPositionHelper.cxx b/chart2/source/view/charttypes/BarPositionHelper.cxx
new file mode 100644
index 000000000000..b1735e99de5d
--- /dev/null
+++ b/chart2/source/view/charttypes/BarPositionHelper.cxx
@@ -0,0 +1,138 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_chart2.hxx"
+
+#include "BarPositionHelper.hxx"
+#include "Linear3DTransformation.hxx"
+#include "ViewDefines.hxx"
+#include "CommonConverters.hxx"
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+BarPositionHelper::BarPositionHelper( bool /* bSwapXAndY */ )
+ : CategoryPositionHelper( 1 )
+{
+}
+
+BarPositionHelper::BarPositionHelper( const BarPositionHelper& rSource )
+ : CategoryPositionHelper( rSource )
+ , PlottingPositionHelper( rSource )
+{
+}
+
+BarPositionHelper::~BarPositionHelper()
+{
+}
+
+PlottingPositionHelper* BarPositionHelper::clone() const
+{
+ BarPositionHelper* pRet = new BarPositionHelper(*this);
+ return pRet;
+}
+
+void BarPositionHelper::updateSeriesCount( double fSeriesCount )
+{
+ m_fSeriesCount = fSeriesCount;
+}
+
+uno::Reference< XTransformation > BarPositionHelper::getTransformationScaledLogicToScene() const
+{
+ //transformation from 2) to 4) //@todo 2) and 4) need a link to a document
+
+ //we need to apply this transformation to each geometric object because of a bug/problem
+ //of the old drawing layer (the UNO_NAME_3D_EXTRUDE_DEPTH is an integer value instead of an double )
+
+ if( !m_xTransformationLogicToScene.is() )
+ {
+ ::basegfx::B3DHomMatrix aMatrix;
+
+ double MinX = getLogicMinX();
+ double MinY = getLogicMinY();
+ double MinZ = getLogicMinZ();
+ double MaxX = getLogicMaxX();
+ double MaxY = getLogicMaxY();
+ double MaxZ = getLogicMaxZ();
+
+ AxisOrientation nXAxisOrientation = m_aScales[0].Orientation;
+ AxisOrientation nYAxisOrientation = m_aScales[1].Orientation;
+ AxisOrientation nZAxisOrientation = m_aScales[2].Orientation;
+
+ //apply scaling
+ //scaling of x axis is refused/ignored
+ doLogicScaling( NULL, &MinY, &MinZ );
+ doLogicScaling( NULL, &MaxY, &MaxZ);
+
+ if(m_bSwapXAndY)
+ {
+ std::swap(MinX,MinY);
+ std::swap(MaxX,MaxY);
+ std::swap(nXAxisOrientation,nYAxisOrientation);
+ }
+
+ if( AxisOrientation_MATHEMATICAL==nXAxisOrientation )
+ aMatrix.translate(-MinX,0.0,0.0);
+ else
+ aMatrix.translate(-MaxX,0.0,0.0);
+ if( AxisOrientation_MATHEMATICAL==nYAxisOrientation )
+ aMatrix.translate(0.0,-MinY,0.0);
+ else
+ aMatrix.translate(0.0,-MaxY,0.0);
+ if( AxisOrientation_MATHEMATICAL==nZAxisOrientation )
+ aMatrix.translate(0.0,0.0,-MaxZ);//z direction in draw is reverse mathematical direction
+ else
+ aMatrix.translate(0.0,0.0,-MinZ);
+
+ double fWidthX = MaxX - MinX;
+ double fWidthY = MaxY - MinY;
+ double fWidthZ = MaxZ - MinZ;
+
+ double fScaleDirectionX = AxisOrientation_MATHEMATICAL==nXAxisOrientation ? 1.0 : -1.0;
+ double fScaleDirectionY = AxisOrientation_MATHEMATICAL==nYAxisOrientation ? 1.0 : -1.0;
+ double fScaleDirectionZ = AxisOrientation_MATHEMATICAL==nZAxisOrientation ? -1.0 : 1.0;
+
+ aMatrix.scale(fScaleDirectionX*FIXED_SIZE_FOR_3D_CHART_VOLUME/fWidthX
+ , fScaleDirectionY*FIXED_SIZE_FOR_3D_CHART_VOLUME/fWidthY
+ , fScaleDirectionZ*FIXED_SIZE_FOR_3D_CHART_VOLUME/fWidthZ);
+
+ //if(nDim==2)
+ aMatrix = m_aMatrixScreenToScene*aMatrix;
+
+ m_xTransformationLogicToScene = new Linear3DTransformation(B3DHomMatrixToHomogenMatrix( aMatrix ),m_bSwapXAndY);
+ }
+ return m_xTransformationLogicToScene;
+}
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
diff --git a/chart2/source/view/charttypes/BarPositionHelper.hxx b/chart2/source/view/charttypes/BarPositionHelper.hxx
new file mode 100644
index 000000000000..32899de62aef
--- /dev/null
+++ b/chart2/source/view/charttypes/BarPositionHelper.hxx
@@ -0,0 +1,76 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CHART2_BARPOSITIONHELPER_HXX
+#define _CHART2_BARPOSITIONHELPER_HXX
+
+#include "PlottingPositionHelper.hxx"
+#include "CategoryPositionHelper.hxx"
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+
+//-----------------------------------------------------------------------------
+/**
+*/
+
+class BarPositionHelper : public CategoryPositionHelper, public PlottingPositionHelper
+{
+public:
+ BarPositionHelper( bool bSwapXAndY=true );
+ BarPositionHelper( const BarPositionHelper& rSource );
+ virtual ~BarPositionHelper();
+
+ virtual PlottingPositionHelper* clone() const;
+
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XTransformation >
+ getTransformationScaledLogicToScene() const;
+
+ void updateSeriesCount( double fSeriesCount ); /*only enter the size of x stacked series*/
+
+ sal_Int32 getStartCategoryIndex() const {
+ //first category (index 0) matches with real number 1.0
+ sal_Int32 nStart = static_cast<sal_Int32>(getLogicMinX() - 0.5);
+ if( nStart < 0 )
+ nStart = 0;
+ return nStart;
+ }
+ sal_Int32 getEndCategoryIndex() const {
+ //first category (index 0) matches with real number 1.0
+ sal_Int32 nEnd = static_cast<sal_Int32>(getLogicMaxX() - 0.5);
+ if( nEnd < 0 )
+ nEnd = 0;
+ return nEnd;
+ }
+};
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
+#endif
diff --git a/chart2/source/view/charttypes/BubbleChart.cxx b/chart2/source/view/charttypes/BubbleChart.cxx
new file mode 100644
index 000000000000..c5454edcc6fd
--- /dev/null
+++ b/chart2/source/view/charttypes/BubbleChart.cxx
@@ -0,0 +1,417 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_chart2.hxx"
+
+#include "BubbleChart.hxx"
+#include "PlottingPositionHelper.hxx"
+#include "ShapeFactory.hxx"
+#include "CommonConverters.hxx"
+#include "macros.hxx"
+#include "ViewDefines.hxx"
+#include "ObjectIdentifier.hxx"
+#include "Splines.hxx"
+#include "LabelPositionHelper.hxx"
+#include "Clipping.hxx"
+#include "Stripe.hxx"
+
+#include <com/sun/star/chart2/Symbol.hpp>
+#include <com/sun/star/chart/DataLabelPlacement.hpp>
+#include <tools/debug.hxx>
+#include <editeng/unoprnms.hxx>
+#include <rtl/math.hxx>
+#include <com/sun/star/drawing/DoubleSequence.hpp>
+#include <com/sun/star/drawing/NormalsKind.hpp>
+#include <com/sun/star/lang/XServiceName.hpp>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+using namespace ::com::sun::star;
+using namespace ::rtl::math;
+using namespace ::com::sun::star::chart2;
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+BubbleChart::BubbleChart( const uno::Reference<XChartType>& xChartTypeModel
+ , sal_Int32 nDimensionCount )
+ : VSeriesPlotter( xChartTypeModel, nDimensionCount, false )
+ , m_bShowNegativeValues(false)
+ , m_bBubbleSizeAsArea(true)
+ , m_fBubbleSizeScaling(1.0)
+ , m_fMaxLogicBubbleSize( 0.0 )
+ , m_fBubbleSizeFactorToScreen( 1.0 )
+{
+ if( !m_pMainPosHelper )
+ m_pMainPosHelper = new PlottingPositionHelper();
+ PlotterBase::m_pPosHelper = m_pMainPosHelper;
+ VSeriesPlotter::m_pMainPosHelper = m_pMainPosHelper;
+}
+
+BubbleChart::~BubbleChart()
+{
+ delete m_pMainPosHelper;
+}
+
+void BubbleChart::calculateMaximumLogicBubbleSize()
+{
+ double fMaxSize = 0.0;
+
+ sal_Int32 nStartIndex = 0;
+ sal_Int32 nEndIndex = VSeriesPlotter::getPointCount();
+ for( sal_Int32 nIndex = nStartIndex; nIndex < nEndIndex; nIndex++ )
+ {
+ ::std::vector< ::std::vector< VDataSeriesGroup > >::iterator aZSlotIter = m_aZSlots.begin();
+ const ::std::vector< ::std::vector< VDataSeriesGroup > >::const_iterator aZSlotEnd = m_aZSlots.end();
+ for( ; aZSlotIter != aZSlotEnd; aZSlotIter++ )
+ {
+ ::std::vector< VDataSeriesGroup >::iterator aXSlotIter = aZSlotIter->begin();
+ const ::std::vector< VDataSeriesGroup >::const_iterator aXSlotEnd = aZSlotIter->end();
+ for( ; aXSlotIter != aXSlotEnd; aXSlotIter++ )
+ {
+ ::std::vector< VDataSeries* >* pSeriesList = &(aXSlotIter->m_aSeriesVector);
+ ::std::vector< VDataSeries* >::const_iterator aSeriesIter = pSeriesList->begin();
+ const ::std::vector< VDataSeries* >::const_iterator aSeriesEnd = pSeriesList->end();
+ for( ; aSeriesIter != aSeriesEnd; aSeriesIter++ )
+ {
+ VDataSeries* pSeries( *aSeriesIter );
+ if(!pSeries)
+ continue;
+
+ double fSize = pSeries->getBubble_Size( nIndex );
+ if( m_bShowNegativeValues )
+ fSize = fabs(fSize);
+ if( fSize > fMaxSize )
+ fMaxSize = fSize;
+ }
+ }
+ }
+ }
+
+ m_fMaxLogicBubbleSize = fMaxSize;
+}
+
+void BubbleChart::calculateBubbleSizeScalingFactor()
+{
+ double fLogicZ=0.5;
+ drawing::Position3D aSceneMinPos( m_pMainPosHelper->transformLogicToScene( m_pMainPosHelper->getLogicMinX(),m_pMainPosHelper->getLogicMinY(),fLogicZ, false ) );
+ drawing::Position3D aSceneMaxPos( m_pMainPosHelper->transformLogicToScene( m_pMainPosHelper->getLogicMaxX(),m_pMainPosHelper->getLogicMaxY(),fLogicZ, false ) );
+
+ awt::Point aScreenMinPos( LabelPositionHelper(m_pMainPosHelper,m_nDimension,m_xLogicTarget,m_pShapeFactory).transformSceneToScreenPosition( aSceneMinPos ) );
+ awt::Point aScreenMaxPos( LabelPositionHelper(m_pMainPosHelper,m_nDimension,m_xLogicTarget,m_pShapeFactory).transformSceneToScreenPosition( aSceneMaxPos ) );
+
+ sal_Int32 nWidth = abs( aScreenMaxPos.X - aScreenMinPos.X );
+ sal_Int32 nHeight = abs( aScreenMaxPos.Y - aScreenMinPos.Y );
+
+ sal_Int32 nMinExtend = std::min( nWidth, nHeight );
+ m_fBubbleSizeFactorToScreen = nMinExtend * 0.25;//max bubble size is 25 percent of diagram size
+}
+
+drawing::Direction3D BubbleChart::transformToScreenBubbleSize( double fLogicSize )
+{
+ drawing::Direction3D aRet(0,0,0);
+
+ if( ::rtl::math::isNan(fLogicSize) || ::rtl::math::isInf(fLogicSize) )
+ return aRet;
+
+ if( m_bShowNegativeValues )
+ fLogicSize = fabs(fLogicSize);
+
+ double fMaxSize = m_fMaxLogicBubbleSize;
+
+ double fMaxRadius = fMaxSize;
+ double fRaduis = fLogicSize;
+ if( m_bBubbleSizeAsArea )
+ {
+ fMaxRadius = sqrt( fMaxSize / F_PI );
+ fRaduis = sqrt( fLogicSize / F_PI );
+ }
+
+ aRet.DirectionX = m_fBubbleSizeScaling * m_fBubbleSizeFactorToScreen * fRaduis / fMaxRadius;
+ aRet.DirectionY = aRet.DirectionX;
+
+ return aRet;
+}
+
+bool BubbleChart::isExpandIfValuesCloseToBorder( sal_Int32 /*nDimensionIndex*/ )
+{
+ return true;
+}
+
+bool BubbleChart::isSeperateStackingForDifferentSigns( sal_Int32 /*nDimensionIndex*/ )
+{
+ return false;
+}
+
+//-----------------------------------------------------------------
+
+LegendSymbolStyle BubbleChart::getLegendSymbolStyle()
+{
+ return chart2::LegendSymbolStyle_CIRCLE;
+}
+
+drawing::Direction3D BubbleChart::getPreferredDiagramAspectRatio() const
+{
+ return drawing::Direction3D(-1,-1,-1);
+}
+
+void BubbleChart::addSeries( VDataSeries* pSeries, sal_Int32 zSlot, sal_Int32 xSlot, sal_Int32 ySlot )
+{
+ VSeriesPlotter::addSeries( pSeries, zSlot, xSlot, ySlot );
+}
+
+//better performance for big data
+struct FormerPoint
+{
+ FormerPoint( double fX, double fY, double fZ )
+ : m_fX(fX), m_fY(fY), m_fZ(fZ)
+ {}
+ FormerPoint()
+ {
+ ::rtl::math::setNan( &m_fX );
+ ::rtl::math::setNan( &m_fY );
+ ::rtl::math::setNan( &m_fZ );
+ }
+
+ double m_fX;
+ double m_fY;
+ double m_fZ;
+};
+
+void BubbleChart::createShapes()
+{
+ if( m_aZSlots.begin() == m_aZSlots.end() ) //no series
+ return;
+
+ DBG_ASSERT(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is(),"BubbleChart is not proper initialized");
+ if(!(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is()))
+ return;
+
+ //therefore create an own group for the texts and the error bars to move them to front
+ //(because the text group is created after the series group the texts are displayed on top)
+ uno::Reference< drawing::XShapes > xSeriesTarget(
+ createGroupShape( m_xLogicTarget,rtl::OUString() ));
+ uno::Reference< drawing::XShapes > xTextTarget(
+ m_pShapeFactory->createGroup2D( m_xFinalTarget,rtl::OUString() ));
+
+ //update/create information for current group
+ double fLogicZ = 0.5;//as defined
+
+ sal_Int32 nStartIndex = 0; // inclusive ;..todo get somehow from x scale
+ sal_Int32 nEndIndex = VSeriesPlotter::getPointCount();
+ if(nEndIndex<=0)
+ nEndIndex=1;
+
+ //better performance for big data
+ std::map< VDataSeries*, FormerPoint > aSeriesFormerPointMap;
+ m_bPointsWereSkipped = false;
+ sal_Int32 nSkippedPoints = 0;
+ sal_Int32 nCreatedPoints = 0;
+ //
+
+ calculateMaximumLogicBubbleSize();
+ calculateBubbleSizeScalingFactor();
+ if( m_fMaxLogicBubbleSize <= 0 || m_fBubbleSizeFactorToScreen <= 0 )
+ return;
+
+//=============================================================================
+ //iterate through all x values per indices
+ for( sal_Int32 nIndex = nStartIndex; nIndex < nEndIndex; nIndex++ )
+ {
+ ::std::vector< ::std::vector< VDataSeriesGroup > >::iterator aZSlotIter = m_aZSlots.begin();
+ const ::std::vector< ::std::vector< VDataSeriesGroup > >::const_iterator aZSlotEnd = m_aZSlots.end();
+
+ aZSlotIter = m_aZSlots.begin();
+ for( sal_Int32 nZ=1; aZSlotIter != aZSlotEnd; aZSlotIter++, nZ++ )
+ {
+ ::std::vector< VDataSeriesGroup >::iterator aXSlotIter = aZSlotIter->begin();
+ const ::std::vector< VDataSeriesGroup >::const_iterator aXSlotEnd = aZSlotIter->end();
+
+ aXSlotIter = aZSlotIter->begin();
+ for( sal_Int32 nX=0; aXSlotIter != aXSlotEnd; aXSlotIter++, nX++ )
+ {
+ ::std::vector< VDataSeries* >* pSeriesList = &(aXSlotIter->m_aSeriesVector);
+ ::std::vector< VDataSeries* >::const_iterator aSeriesIter = pSeriesList->begin();
+ const ::std::vector< VDataSeries* >::const_iterator aSeriesEnd = pSeriesList->end();
+
+ //=============================================================================
+ //iterate through all series
+ for( sal_Int32 nSeriesIndex = 0; aSeriesIter != aSeriesEnd; aSeriesIter++, nSeriesIndex++ )
+ {
+ VDataSeries* pSeries( *aSeriesIter );
+ if(!pSeries)
+ continue;
+
+ uno::Reference< drawing::XShapes > xSeriesGroupShape_Shapes = getSeriesGroupShape(*aSeriesIter, xSeriesTarget);
+
+ sal_Int32 nAttachedAxisIndex = pSeries->getAttachedAxisIndex();
+ PlottingPositionHelper* pPosHelper = &(this->getPlottingPositionHelper( nAttachedAxisIndex ));
+ if(!pPosHelper)
+ pPosHelper = m_pMainPosHelper;
+ PlotterBase::m_pPosHelper = pPosHelper;
+
+ if(m_nDimension==3)
+ fLogicZ = nZ+0.5;
+
+ //collect data point information (logic coordinates, style ):
+ double fLogicX = pSeries->getXValue(nIndex);
+ double fLogicY = pSeries->getYValue(nIndex);
+ double fBubbleSize = pSeries->getBubble_Size( nIndex );
+
+ if( !m_bShowNegativeValues && fBubbleSize<0.0 )
+ continue;
+
+ if( ::rtl::math::approxEqual( fBubbleSize, 0.0 ) || ::rtl::math::isNan(fBubbleSize) )
+ continue;
+
+ if( ::rtl::math::isNan(fLogicX) || ::rtl::math::isInf(fLogicX)
+ || ::rtl::math::isNan(fLogicY) || ::rtl::math::isInf(fLogicY) )
+ continue;
+
+ bool bIsVisible = pPosHelper->isLogicVisible( fLogicX, fLogicY, fLogicZ );
+
+ drawing::Position3D aUnscaledLogicPosition( fLogicX, fLogicY, fLogicZ );
+ drawing::Position3D aScaledLogicPosition(aUnscaledLogicPosition);
+ pPosHelper->doLogicScaling( aScaledLogicPosition );
+
+ //transformation 3) -> 4)
+ drawing::Position3D aScenePosition( pPosHelper->transformLogicToScene( fLogicX,fLogicY,fLogicZ, false ) );
+
+ //better performance for big data
+ FormerPoint aFormerPoint( aSeriesFormerPointMap[pSeries] );
+ pPosHelper->setCoordinateSystemResolution( m_aCoordinateSystemResolution );
+ if( !pSeries->isAttributedDataPoint(nIndex)
+ &&
+ pPosHelper->isSameForGivenResolution( aFormerPoint.m_fX, aFormerPoint.m_fY, aFormerPoint.m_fZ
+ , aScaledLogicPosition.PositionX, aScaledLogicPosition.PositionY, aScaledLogicPosition.PositionZ ) )
+ {
+ nSkippedPoints++;
+ m_bPointsWereSkipped = true;
+ continue;
+ }
+ aSeriesFormerPointMap[pSeries] = FormerPoint(aScaledLogicPosition.PositionX, aScaledLogicPosition.PositionY, aScaledLogicPosition.PositionZ);
+
+ //create a single datapoint if point is visible
+ if( !bIsVisible )
+ continue;
+
+ //create a group shape for this point and add to the series shape:
+ rtl::OUString aPointCID = ObjectIdentifier::createPointCID(
+ pSeries->getPointCID_Stub(), nIndex );
+ uno::Reference< drawing::XShapes > xPointGroupShape_Shapes(
+ createGroupShape(xSeriesGroupShape_Shapes,aPointCID) );
+ uno::Reference<drawing::XShape> xPointGroupShape_Shape =
+ uno::Reference<drawing::XShape>( xPointGroupShape_Shapes, uno::UNO_QUERY );
+
+ {
+ nCreatedPoints++;
+
+ //create data point
+ drawing::Direction3D aSymbolSize = transformToScreenBubbleSize( fBubbleSize );
+ if(m_nDimension!=3)
+ {
+ uno::Reference<drawing::XShape> xShape;
+ xShape = m_pShapeFactory->createCircle2D( xPointGroupShape_Shapes
+ , aScenePosition, aSymbolSize );
+
+ this->setMappedProperties( xShape
+ , pSeries->getPropertiesOfPoint( nIndex )
+ , PropertyMapper::getPropertyNameMapForFilledSeriesProperties() );
+
+ m_pShapeFactory->setShapeName( xShape, C2U("MarkHandles") );
+ }
+
+ //create data point label
+ if( (**aSeriesIter).getDataPointLabelIfLabel(nIndex) )
+ {
+ LabelAlignment eAlignment = LABEL_ALIGN_TOP;
+ drawing::Position3D aScenePosition3D( aScenePosition.PositionX
+ , aScenePosition.PositionY
+ , aScenePosition.PositionZ+this->getTransformedDepth() );
+
+ sal_Int32 nLabelPlacement = pSeries->getLabelPlacement( nIndex, m_xChartTypeModel, m_nDimension, pPosHelper->isSwapXAndY() );
+
+ switch(nLabelPlacement)
+ {
+ case ::com::sun::star::chart::DataLabelPlacement::TOP:
+ aScenePosition3D.PositionY -= (aSymbolSize.DirectionY/2+1);
+ eAlignment = LABEL_ALIGN_TOP;
+ break;
+ case ::com::sun::star::chart::DataLabelPlacement::BOTTOM:
+ aScenePosition3D.PositionY += (aSymbolSize.DirectionY/2+1);
+ eAlignment = LABEL_ALIGN_BOTTOM;
+ break;
+ case ::com::sun::star::chart::DataLabelPlacement::LEFT:
+ aScenePosition3D.PositionX -= (aSymbolSize.DirectionX/2+1);
+ eAlignment = LABEL_ALIGN_LEFT;
+ break;
+ case ::com::sun::star::chart::DataLabelPlacement::RIGHT:
+ aScenePosition3D.PositionX += (aSymbolSize.DirectionX/2+1);
+ eAlignment = LABEL_ALIGN_RIGHT;
+ break;
+ case ::com::sun::star::chart::DataLabelPlacement::CENTER:
+ eAlignment = LABEL_ALIGN_CENTER;
+ break;
+ default:
+ DBG_ERROR("this label alignment is not implemented yet");
+ aScenePosition3D.PositionY -= (aSymbolSize.DirectionY/2+1);
+ eAlignment = LABEL_ALIGN_TOP;
+ break;
+ }
+
+
+ awt::Point aScreenPosition2D( LabelPositionHelper(pPosHelper,m_nDimension,m_xLogicTarget,m_pShapeFactory)
+ .transformSceneToScreenPosition( aScenePosition3D ) );
+ sal_Int32 nOffset = 0;
+ if(LABEL_ALIGN_CENTER!=eAlignment)
+ nOffset = 100;//add some spacing //@todo maybe get more intelligent values
+ this->createDataLabel( xTextTarget, **aSeriesIter, nIndex
+ , fBubbleSize, fBubbleSize, aScreenPosition2D, eAlignment, nOffset );
+ }
+ }
+
+ //remove PointGroupShape if empty
+ if(!xPointGroupShape_Shapes->getCount())
+ xSeriesGroupShape_Shapes->remove(xPointGroupShape_Shape);
+
+ }//next series in x slot (next y slot)
+ }//next x slot
+ }//next z slot
+ }//next category
+//=============================================================================
+//=============================================================================
+//=============================================================================
+ OSL_TRACE( "\nPPPPPPPPP<<<<<<<<<<<< area chart :: createShapes():: skipped points: %d created points: %d", nSkippedPoints, nCreatedPoints );
+}
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
diff --git a/chart2/source/view/charttypes/BubbleChart.hxx b/chart2/source/view/charttypes/BubbleChart.hxx
new file mode 100644
index 000000000000..9c04ce8d3719
--- /dev/null
+++ b/chart2/source/view/charttypes/BubbleChart.hxx
@@ -0,0 +1,94 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _CHART2_BUBBLECHART_HXX
+#define _CHART2_BUBBLECHART_HXX
+
+#include "VSeriesPlotter.hxx"
+#include <com/sun/star/drawing/Direction3D.hpp>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+
+class BubbleChart : public VSeriesPlotter
+{
+ //-------------------------------------------------------------------------
+ // public methods
+ //-------------------------------------------------------------------------
+public:
+ BubbleChart( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::chart2::XChartType >& xChartTypeModel
+ , sal_Int32 nDimensionCount );
+ virtual ~BubbleChart();
+
+ //-------------------------------------------------------------------------
+ // chart2::XPlotter
+ //-------------------------------------------------------------------------
+
+ virtual void SAL_CALL createShapes();
+
+ virtual void addSeries( VDataSeries* pSeries, sal_Int32 zSlot = -1, sal_Int32 xSlot = -1,sal_Int32 ySlot = -1 );
+
+ //-------------------
+ virtual ::com::sun::star::drawing::Direction3D getPreferredDiagramAspectRatio() const;
+
+ //-------------------------------------------------------------------------
+ // MinimumAndMaximumSupplier
+ //-------------------------------------------------------------------------
+ virtual bool isExpandIfValuesCloseToBorder( sal_Int32 nDimensionIndex );
+ virtual bool isSeperateStackingForDifferentSigns( sal_Int32 nDimensionIndex );
+
+ //-------------------------------------------------------------------------
+
+ virtual ::com::sun::star::chart2::LegendSymbolStyle getLegendSymbolStyle();
+
+ //-------------------------------------------------------------------------
+ //-------------------------------------------------------------------------
+ //-------------------------------------------------------------------------
+private: //methods
+ //no default constructor
+ BubbleChart();
+
+ void calculateMaximumLogicBubbleSize();
+ void calculateBubbleSizeScalingFactor();
+
+ com::sun::star::drawing::Direction3D transformToScreenBubbleSize( double fLogicSize );
+
+private: //member
+
+ bool m_bShowNegativeValues;//input parameter
+ bool m_bBubbleSizeAsArea;//input parameter
+ double m_fBubbleSizeScaling;//input parameter
+
+ double m_fMaxLogicBubbleSize;//calculated values
+ double m_fBubbleSizeFactorToScreen;//calculated values
+};
+//.............................................................................
+} //namespace chart
+//.............................................................................
+#endif
diff --git a/chart2/source/view/charttypes/CandleStickChart.cxx b/chart2/source/view/charttypes/CandleStickChart.cxx
new file mode 100644
index 000000000000..ddfe50deed2f
--- /dev/null
+++ b/chart2/source/view/charttypes/CandleStickChart.cxx
@@ -0,0 +1,398 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_chart2.hxx"
+
+#include "CandleStickChart.hxx"
+#include "ShapeFactory.hxx"
+//#include "chartview/servicenames_charttypes.hxx"
+//#include "servicenames_coosystems.hxx"
+#include "CommonConverters.hxx"
+#include "ObjectIdentifier.hxx"
+#include "LabelPositionHelper.hxx"
+#include "BarPositionHelper.hxx"
+#include "macros.hxx"
+#include "VLegendSymbolFactory.hxx"
+#include "FormattedStringHelper.hxx"
+#include "DataSeriesHelper.hxx"
+#include <tools/debug.hxx>
+#include <rtl/math.hxx>
+#include <editeng/unoprnms.hxx>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+using namespace ::com::sun::star;
+using namespace ::rtl::math;
+using namespace ::com::sun::star::chart2;
+using ::com::sun::star::uno::Reference;
+using ::rtl::OUString;
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+CandleStickChart::CandleStickChart( const uno::Reference<XChartType>& xChartTypeModel
+ , sal_Int32 nDimensionCount )
+ : VSeriesPlotter( xChartTypeModel, nDimensionCount )
+ , m_pMainPosHelper( new BarPositionHelper() )
+{
+ PlotterBase::m_pPosHelper = m_pMainPosHelper;
+ VSeriesPlotter::m_pMainPosHelper = m_pMainPosHelper;
+}
+
+CandleStickChart::~CandleStickChart()
+{
+ delete m_pMainPosHelper;
+}
+
+//-------------------------------------------------------------------------
+// MinimumAndMaximumSupplier
+//-------------------------------------------------------------------------
+
+double CandleStickChart::getMinimumX()
+{
+ if( m_bCategoryXAxis )
+ return 0.5;//first category (index 0) matches with real number 1.0
+ return VSeriesPlotter::getMinimumX();
+}
+double CandleStickChart::getMaximumX()
+{
+ if( m_bCategoryXAxis )
+ {
+ //return category count
+ sal_Int32 nPointCount = getPointCount();
+ return nPointCount+0.5;//first category (index 0) matches with real number 1.0
+ }
+ return VSeriesPlotter::getMaximumX();
+}
+bool CandleStickChart::isSeperateStackingForDifferentSigns( sal_Int32 /* nDimensionIndex */ )
+{
+ return false;
+}
+
+//-----------------------------------------------------------------
+//-----------------------------------------------------------------
+//-----------------------------------------------------------------
+
+LegendSymbolStyle CandleStickChart::getLegendSymbolStyle()
+{
+ return chart2::LegendSymbolStyle_VERTICAL_LINE;
+}
+
+//-----------------------------------------------------------------
+// lang::XServiceInfo
+//-----------------------------------------------------------------
+/*
+APPHELPER_XSERVICEINFO_IMPL(CandleStickChart,CHART2_VIEW_CANDLESTICKCHART_SERVICE_IMPLEMENTATION_NAME)
+
+ uno::Sequence< rtl::OUString > CandleStickChart
+::getSupportedServiceNames_Static()
+{
+ uno::Sequence< rtl::OUString > aSNS( 1 );
+ aSNS.getArray()[ 0 ] = CHART2_VIEW_CANDLESTICKCHART_SERVICE_NAME;
+ return aSNS;
+}
+*/
+/*
+//-----------------------------------------------------------------
+// chart2::XPlotter
+//-----------------------------------------------------------------
+
+ ::rtl::OUString SAL_CALL CandleStickChart
+::getCoordinateSystemTypeID()
+ throw (uno::RuntimeException)
+{
+ return CHART2_COOSYSTEM_CARTESIAN_SERVICE_NAME;
+}
+*/
+
+drawing::Direction3D CandleStickChart::getPreferredDiagramAspectRatio() const
+{
+ return drawing::Direction3D(-1,-1,-1);
+}
+
+void CandleStickChart::addSeries( VDataSeries* pSeries, sal_Int32 /* zSlot */, sal_Int32 xSlot, sal_Int32 ySlot )
+{
+ //ignore y stacking for candle stick chart
+ VSeriesPlotter::addSeries( pSeries, 0, xSlot, ySlot );
+}
+
+void CandleStickChart::createShapes()
+{
+ if( m_aZSlots.begin() == m_aZSlots.end() ) //no series
+ return;
+
+ if( m_nDimension!=2 )
+ return;
+
+ DBG_ASSERT(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is(),"CandleStickChart is not proper initialized");
+ if(!(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is()))
+ return;
+
+ //the text labels should be always on top of the other series shapes
+ //therefore create an own group for the texts to move them to front
+ //(because the text group is created after the series group the texts are displayed on top)
+
+ uno::Reference< drawing::XShapes > xSeriesTarget(
+ createGroupShape( m_xLogicTarget,rtl::OUString() ));
+ uno::Reference< drawing::XShapes > xLossTarget(
+ createGroupShape( m_xLogicTarget, ObjectIdentifier::createClassifiedIdentifier(
+ OBJECTTYPE_DATA_STOCK_LOSS, rtl::OUString() )));
+ uno::Reference< drawing::XShapes > xGainTarget(
+ createGroupShape( m_xLogicTarget, ObjectIdentifier::createClassifiedIdentifier(
+ OBJECTTYPE_DATA_STOCK_GAIN, rtl::OUString() )));
+ uno::Reference< drawing::XShapes > xTextTarget(
+ m_pShapeFactory->createGroup2D( m_xFinalTarget,rtl::OUString() ));
+
+ //---------------------------------------------
+ //check necessary here that different Y axis can not be stacked in the same group? ... hm?
+
+ bool bJapaneseStyle=true;//@todo is this the correct default?
+ bool bShowFirst = true;//is only important if bJapaneseStyle == false
+ tNameSequence aWhiteBox_Names, aBlackBox_Names;
+ tAnySequence aWhiteBox_Values, aBlackBox_Values;
+ try
+ {
+ if( m_xChartTypeModelProps.is() )
+ {
+ m_xChartTypeModelProps->getPropertyValue( C2U( "ShowFirst" ) ) >>= bShowFirst;
+
+ uno::Reference< beans::XPropertySet > xWhiteDayProps(0);
+ uno::Reference< beans::XPropertySet > xBlackDayProps(0);
+ m_xChartTypeModelProps->getPropertyValue( C2U( "Japanese" ) ) >>= bJapaneseStyle;
+ m_xChartTypeModelProps->getPropertyValue( C2U( "WhiteDay" ) ) >>= xWhiteDayProps;
+ m_xChartTypeModelProps->getPropertyValue( C2U( "BlackDay" ) ) >>= xBlackDayProps;
+
+ tPropertyNameValueMap aWhiteBox_Map;
+ PropertyMapper::getValueMap( aWhiteBox_Map, PropertyMapper::getPropertyNameMapForFillAndLineProperties(), xWhiteDayProps );
+ PropertyMapper::getMultiPropertyListsFromValueMap( aWhiteBox_Names, aWhiteBox_Values, aWhiteBox_Map );
+
+ tPropertyNameValueMap aBlackBox_Map;
+ PropertyMapper::getValueMap( aBlackBox_Map, PropertyMapper::getPropertyNameMapForFillAndLineProperties(), xBlackDayProps );
+ PropertyMapper::getMultiPropertyListsFromValueMap( aBlackBox_Names, aBlackBox_Values, aBlackBox_Map );
+ }
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+
+ //(@todo maybe different iteration for breaks in axis ?)
+ sal_Int32 nStartCategoryIndex = m_pMainPosHelper->getStartCategoryIndex(); // inclusive
+ sal_Int32 nEndCategoryIndex = m_pMainPosHelper->getEndCategoryIndex(); //inclusive
+//=============================================================================
+ //iterate through all shown categories
+ for( sal_Int32 nIndex = nStartCategoryIndex; nIndex < nEndCategoryIndex; nIndex++ )
+ {
+ ::std::vector< ::std::vector< VDataSeriesGroup > >::iterator aZSlotIter = m_aZSlots.begin();
+ const ::std::vector< ::std::vector< VDataSeriesGroup > >::const_iterator aZSlotEnd = m_aZSlots.end();
+//=============================================================================
+ for( sal_Int32 nZ=0; aZSlotIter != aZSlotEnd; aZSlotIter++, nZ++ )
+ {
+ ::std::vector< VDataSeriesGroup >::iterator aXSlotIter = aZSlotIter->begin();
+ const ::std::vector< VDataSeriesGroup >::const_iterator aXSlotEnd = aZSlotIter->end();
+
+ sal_Int32 nAttachedAxisIndex = 0;
+ BarPositionHelper* pPosHelper = m_pMainPosHelper;
+ if( aXSlotIter != aXSlotEnd )
+ {
+ nAttachedAxisIndex = aXSlotIter->getAttachedAxisIndexForFirstSeries();
+ //2ND_AXIS_IN_BARS so far one can assume to have the same plotter for each z slot
+ pPosHelper = dynamic_cast<BarPositionHelper*>(&( this->getPlottingPositionHelper( nAttachedAxisIndex ) ) );
+ if(!pPosHelper)
+ pPosHelper = m_pMainPosHelper;
+ }
+ PlotterBase::m_pPosHelper = pPosHelper;
+
+ //update/create information for current group
+ pPosHelper->updateSeriesCount( aZSlotIter->size() );
+//=============================================================================
+ //iterate through all x slots in this category
+ for( double fSlotX=0; aXSlotIter != aXSlotEnd; aXSlotIter++, fSlotX+=1.0 )
+ {
+ ::std::vector< VDataSeries* >* pSeriesList = &(aXSlotIter->m_aSeriesVector);
+
+ ::std::vector< VDataSeries* >::const_iterator aSeriesIter = pSeriesList->begin();
+ const ::std::vector< VDataSeries* >::const_iterator aSeriesEnd = pSeriesList->end();
+ aSeriesIter = pSeriesList->begin();
+ //=============================================================================
+ //iterate through all series in this x slot
+ for( ; aSeriesIter != aSeriesEnd; aSeriesIter++ )
+ {
+ //collect data point information (logic coordinates, style ):
+ double fLogicX = pPosHelper->getSlotPos( (*aSeriesIter)->getXValue( nIndex ), fSlotX );
+ double fY_First = (*aSeriesIter)->getY_First( nIndex );
+ double fY_Last = (*aSeriesIter)->getY_Last( nIndex );
+ double fY_Min = (*aSeriesIter)->getY_Min( nIndex );
+ double fY_Max = (*aSeriesIter)->getY_Max( nIndex );
+
+ bool bBlack=false;
+ if(fY_Last<=fY_First)
+ {
+ std::swap(fY_First,fY_Last);
+ bBlack=true;
+ }
+ if(fY_Max<fY_Min)
+ std::swap(fY_Min,fY_Max);
+ //transformation 3) -> 4)
+ double fHalfWidth = pPosHelper->getSlotWidth()/2.0;
+ drawing::Position3D aPosLeftFirst( pPosHelper->transformLogicToScene( fLogicX-fHalfWidth, fY_First ,0 ,true ) );
+ drawing::Position3D aPosRightLast( pPosHelper->transformLogicToScene( fLogicX+fHalfWidth, fY_Last ,0 ,true ) );
+ drawing::Position3D aPosMiddleFirst( pPosHelper->transformLogicToScene( fLogicX, fY_First ,0 ,true ) );
+ drawing::Position3D aPosMiddleLast( pPosHelper->transformLogicToScene( fLogicX, fY_Last ,0 ,true ) );
+ drawing::Position3D aPosMiddleMinimum( pPosHelper->transformLogicToScene( fLogicX, fY_Min ,0 ,true ) );
+ drawing::Position3D aPosMiddleMaximum( pPosHelper->transformLogicToScene( fLogicX, fY_Max ,0 ,true ) );
+
+ uno::Reference< drawing::XShapes > xLossGainTarget( xGainTarget );
+ if(bBlack)
+ xLossGainTarget = xLossTarget;
+
+ uno::Reference< beans::XPropertySet > xPointProp( (*aSeriesIter)->getPropertiesOfPoint( nIndex ));
+ uno::Reference< drawing::XShapes > xPointGroupShape_Shapes(0);
+ {
+ rtl::OUString aPointCID = ObjectIdentifier::createPointCID( (*aSeriesIter)->getPointCID_Stub(), nIndex );
+ uno::Reference< drawing::XShapes > xSeriesGroupShape_Shapes( getSeriesGroupShape(*aSeriesIter, xSeriesTarget) );
+ xPointGroupShape_Shapes = createGroupShape(xSeriesGroupShape_Shapes,aPointCID);
+ }
+
+ //create min-max line
+ if( isValidPosition(aPosMiddleMinimum) && isValidPosition(aPosMiddleMaximum) )
+ {
+ uno::Reference< drawing::XShape > xShape( m_xShapeFactory->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.drawing.PolyLineShape" ) ) ), uno::UNO_QUERY );
+ xPointGroupShape_Shapes->add(xShape);
+ uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
+ if(xProp.is())
+ {
+ drawing::PolyPolygonShape3D aPoly;
+ sal_Int32 nLineIndex =0;
+ AddPointToPoly( aPoly, aPosMiddleMinimum, nLineIndex);
+ AddPointToPoly( aPoly, aPosMiddleMaximum, nLineIndex);
+ xProp->setPropertyValue( C2U( UNO_NAME_POLYPOLYGON ), uno::makeAny( PolyToPointSequence(aPoly) ) );
+ }
+ this->setMappedProperties( xShape, xPointProp, PropertyMapper::getPropertyNameMapForLineSeriesProperties() );
+ }
+
+ //create first-last shape
+ if(bJapaneseStyle && isValidPosition(aPosLeftFirst) && isValidPosition(aPosRightLast) )
+ {
+ uno::Reference< drawing::XShape > xShape( m_xShapeFactory->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.drawing.RectangleShape" ) ) ), uno::UNO_QUERY );
+ xLossGainTarget->add(xShape);
+
+ xShape->setPosition( Position3DToAWTPoint( aPosLeftFirst ) );
+ drawing::Direction3D aDiff = aPosRightLast-aPosLeftFirst;
+ awt::Size aAWTSize( Direction3DToAWTSize( aDiff ));
+ // workaround for bug in drawing: if height is 0 the box gets infinitely large
+ if( aAWTSize.Height == 0 )
+ aAWTSize.Height = 1;
+ xShape->setSize( aAWTSize );
+
+ uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
+ if(xProp.is())
+ {
+ if(bBlack)
+ PropertyMapper::setMultiProperties( aBlackBox_Names, aBlackBox_Values, xProp );
+ else
+ PropertyMapper::setMultiProperties( aWhiteBox_Names, aWhiteBox_Values, xProp );
+ }
+ }
+ else
+ {
+ drawing::PolyPolygonShape3D aPoly;
+
+ sal_Int32 nLineIndex = 0;
+ if( bShowFirst && pPosHelper->isLogicVisible( fLogicX, fY_First ,0 )
+ && isValidPosition(aPosLeftFirst) && isValidPosition(aPosMiddleFirst) )
+ {
+ AddPointToPoly( aPoly, aPosLeftFirst, nLineIndex );
+ AddPointToPoly( aPoly, aPosMiddleFirst, nLineIndex++ );
+ }
+ if( pPosHelper->isLogicVisible( fLogicX, fY_Last ,0 )
+ && isValidPosition(aPosMiddleLast) && isValidPosition(aPosRightLast) )
+ {
+ AddPointToPoly( aPoly, aPosMiddleLast, nLineIndex );
+ AddPointToPoly( aPoly, aPosRightLast, nLineIndex );
+ }
+
+ if( aPoly.SequenceX.getLength() )
+ {
+ uno::Reference< drawing::XShape > xShape( m_xShapeFactory->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.drawing.PolyLineShape" ) ) ), uno::UNO_QUERY );
+ xPointGroupShape_Shapes->add(xShape);
+ uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
+ if(xProp.is())
+ {
+ xProp->setPropertyValue( C2U( UNO_NAME_POLYPOLYGON ), uno::makeAny( PolyToPointSequence(aPoly) ) );
+ this->setMappedProperties( xShape, xPointProp, PropertyMapper::getPropertyNameMapForLineSeriesProperties() );
+ }
+ }
+ }
+
+ //create data point label
+ if( (**aSeriesIter).getDataPointLabelIfLabel(nIndex) )
+ {
+ if(isValidPosition(aPosMiddleFirst))
+ this->createDataLabel( xTextTarget, **aSeriesIter, nIndex
+ , fY_First, 1.0, Position3DToAWTPoint(aPosMiddleFirst), LABEL_ALIGN_LEFT_BOTTOM );
+ if(isValidPosition(aPosMiddleLast))
+ this->createDataLabel( xTextTarget, **aSeriesIter, nIndex
+ , fY_Last, 1.0, Position3DToAWTPoint(aPosMiddleLast), LABEL_ALIGN_RIGHT_TOP );
+ if(isValidPosition(aPosMiddleMinimum))
+ this->createDataLabel( xTextTarget, **aSeriesIter, nIndex
+ , fY_Min, 1.0, Position3DToAWTPoint(aPosMiddleMinimum), LABEL_ALIGN_BOTTOM );
+ if(isValidPosition(aPosMiddleMaximum))
+ this->createDataLabel( xTextTarget, **aSeriesIter, nIndex
+ , fY_Max, 1.0, Position3DToAWTPoint(aPosMiddleMaximum), LABEL_ALIGN_TOP );
+ }
+ }//next series in x slot (next y slot)
+ }//next x slot
+ }//next z slot
+ }//next category
+//=============================================================================
+//=============================================================================
+//=============================================================================
+ /* @todo remove series shapes if empty
+ //remove and delete point-group-shape if empty
+ if(!xSeriesGroupShape_Shapes->getCount())
+ {
+ (*aSeriesIter)->m_xShape.set(NULL);
+ m_xLogicTarget->remove(xSeriesGroupShape_Shape);
+ }
+ */
+
+ //remove and delete series-group-shape if empty
+
+ //... todo
+}
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
diff --git a/chart2/source/view/charttypes/CandleStickChart.hxx b/chart2/source/view/charttypes/CandleStickChart.hxx
new file mode 100644
index 000000000000..60018dbe8621
--- /dev/null
+++ b/chart2/source/view/charttypes/CandleStickChart.hxx
@@ -0,0 +1,89 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CHART2_CANDLESTICKCHART_HXX
+#define _CHART2_CANDLESTICKCHART_HXX
+
+#include "VSeriesPlotter.hxx"
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+class BarPositionHelper;
+
+class CandleStickChart : public VSeriesPlotter
+{
+ //-------------------------------------------------------------------------
+ // public methods
+ //-------------------------------------------------------------------------
+public:
+ CandleStickChart( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::chart2::XChartType >& xChartTypeModel
+ , sal_Int32 nDimensionCount );
+ virtual ~CandleStickChart();
+
+ //-------------------------------------------------------------------------
+ // chart2::XPlotter
+ //-------------------------------------------------------------------------
+
+ virtual void SAL_CALL createShapes();
+ /*
+ virtual ::rtl::OUString SAL_CALL getCoordinateSystemTypeID( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL setScales( const ::com::sun::star::uno::Sequence< ::com::sun::star::chart2::ExplicitScaleData >& rScales ) 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 addSeries( VDataSeries* pSeries, sal_Int32 zSlot = -1, sal_Int32 xSlot = -1,sal_Int32 ySlot = -1 );
+
+ virtual ::com::sun::star::drawing::Direction3D getPreferredDiagramAspectRatio() const;
+
+ //-------------------------------------------------------------------------
+ // MinimumAndMaximumSupplier
+ //-------------------------------------------------------------------------
+ virtual double getMinimumX();
+ virtual double getMaximumX();
+ virtual bool isSeperateStackingForDifferentSigns( sal_Int32 nDimensionIndex );
+
+ //-------------------------------------------------------------------------
+
+ virtual ::com::sun::star::chart2::LegendSymbolStyle getLegendSymbolStyle();
+
+ //-------------------------------------------------------------------------
+ //-------------------------------------------------------------------------
+ //-------------------------------------------------------------------------
+
+private: //methods
+ //no default constructor
+ CandleStickChart();
+
+private: //member
+ BarPositionHelper* m_pMainPosHelper;
+};
+//.............................................................................
+} //namespace chart
+//.............................................................................
+#endif
diff --git a/chart2/source/view/charttypes/CategoryPositionHelper.cxx b/chart2/source/view/charttypes/CategoryPositionHelper.cxx
new file mode 100644
index 000000000000..d43fd0856e02
--- /dev/null
+++ b/chart2/source/view/charttypes/CategoryPositionHelper.cxx
@@ -0,0 +1,100 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_chart2.hxx"
+#include "CategoryPositionHelper.hxx"
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+//using namespace ::com::sun::star;
+//using namespace ::com::sun::star::chart2;
+
+CategoryPositionHelper::CategoryPositionHelper( double fSeriesCount, double fCategoryWidth )
+ : m_fSeriesCount(fSeriesCount)
+ , m_fCategoryWidth(fCategoryWidth)
+ , m_fInnerDistance(0.0)
+ , m_fOuterDistance(1.0)
+{
+}
+
+CategoryPositionHelper::CategoryPositionHelper( const CategoryPositionHelper& rSource )
+ : m_fSeriesCount( rSource.m_fSeriesCount )
+ , m_fCategoryWidth( rSource.m_fCategoryWidth )
+ , m_fInnerDistance( rSource.m_fInnerDistance )
+ , m_fOuterDistance( rSource.m_fOuterDistance )
+{
+}
+
+CategoryPositionHelper::~CategoryPositionHelper()
+{
+}
+
+double CategoryPositionHelper::getSlotWidth() const
+{
+ double fWidth = m_fCategoryWidth /
+ ( m_fSeriesCount
+ + m_fOuterDistance
+ + m_fInnerDistance*( m_fSeriesCount - 1.0) );
+ return fWidth;
+}
+
+double CategoryPositionHelper::getSlotPos( double fCategoryX, double fSeriesNumber ) const
+{
+ //the returned position is in the middle of the rect
+ //fSeriesNumber 0...n-1
+ double fPos = fCategoryX - (m_fCategoryWidth/2.0)
+ + (m_fOuterDistance/2.0 + fSeriesNumber*(1.0+m_fInnerDistance)) * getSlotWidth()
+ + getSlotWidth()/2.0;
+
+ return fPos;
+}
+
+void CategoryPositionHelper::setInnerDistance( double fInnerDistance )
+{
+ if( fInnerDistance < -1.0 )
+ fInnerDistance = -1.0;
+ if( fInnerDistance > 1.0 )
+ fInnerDistance = 1.0;
+ m_fInnerDistance = fInnerDistance;
+}
+
+void CategoryPositionHelper::setOuterDistance( double fOuterDistance )
+{
+ if( fOuterDistance < 0.0 )
+ fOuterDistance = 0.0;
+ if( fOuterDistance > 6.0 )
+ fOuterDistance = 6.0;
+ m_fOuterDistance = fOuterDistance;
+}
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
diff --git a/chart2/source/view/charttypes/CategoryPositionHelper.hxx b/chart2/source/view/charttypes/CategoryPositionHelper.hxx
new file mode 100644
index 000000000000..08cb1978faa1
--- /dev/null
+++ b/chart2/source/view/charttypes/CategoryPositionHelper.hxx
@@ -0,0 +1,68 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CHART2_CATEGORYPOSITIONHELPER_HXX
+#define _CHART2_CATEGORYPOSITIONHELPER_HXX
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+
+//-----------------------------------------------------------------------------
+/**
+*/
+
+class CategoryPositionHelper
+{
+public:
+ CategoryPositionHelper( double fSeriesCount, double CategoryWidth = 1.0);
+ CategoryPositionHelper( const CategoryPositionHelper& rSource );
+ virtual ~CategoryPositionHelper();
+
+ double getSlotWidth() const;
+ double getSlotPos( double fCategoryX, double fSeriesNumber ) const;
+
+ //Distance between two neighboring bars in same category, seen relative to width of the bar
+ void setInnerDistance( double fInnerDistance );
+
+ //Distance between two neighboring bars in different category, seen relative to width of the bar:
+ void setOuterDistance( double fOuterDistance );
+
+protected:
+ double m_fSeriesCount;
+ double m_fCategoryWidth;
+ //Distance between two neighboring bars in same category, seen relative to width of the bar:
+ double m_fInnerDistance; //[-1,1] m_fInnerDistance=1 --> distance == width; m_fInnerDistance=-1-->all rects are painted on the same position
+ //Distance between two neighboring bars in different category, seen relative to width of the bar:
+ double m_fOuterDistance; //>=0 m_fOuterDistance=1 --> distance == width
+};
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
+#endif
diff --git a/chart2/source/view/charttypes/PieChart.cxx b/chart2/source/view/charttypes/PieChart.cxx
new file mode 100644
index 000000000000..eee13848b11b
--- /dev/null
+++ b/chart2/source/view/charttypes/PieChart.cxx
@@ -0,0 +1,897 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_chart2.hxx"
+
+#include "PieChart.hxx"
+#include "PlottingPositionHelper.hxx"
+#include "ShapeFactory.hxx"
+#include "PolarLabelPositionHelper.hxx"
+#include "macros.hxx"
+#include "CommonConverters.hxx"
+#include "ViewDefines.hxx"
+#include "ObjectIdentifier.hxx"
+
+#include <com/sun/star/chart/DataLabelPlacement.hpp>
+#include <com/sun/star/chart2/XColorScheme.hpp>
+
+#include <com/sun/star/container/XChild.hpp>
+
+//#include "chartview/servicenames_charttypes.hxx"
+//#include "servicenames_coosystems.hxx"
+#include <tools/debug.hxx>
+#include <rtl/math.hxx>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+class PiePositionHelper : public PolarPlottingPositionHelper
+{
+public:
+ PiePositionHelper( NormalAxis eNormalAxis, double fAngleDegreeOffset );
+ virtual ~PiePositionHelper();
+
+ bool getInnerAndOuterRadius( double fCategoryX, double& fLogicInnerRadius, double& fLogicOuterRadius, bool bUseRings, double fMaxOffset ) const;
+
+public:
+ //Distance between different category rings, seen relative to width of a ring:
+ double m_fRingDistance; //>=0 m_fRingDistance=1 --> distance == width
+};
+
+PiePositionHelper::PiePositionHelper( NormalAxis eNormalAxis, double fAngleDegreeOffset )
+ : PolarPlottingPositionHelper(eNormalAxis)
+ , m_fRingDistance(0.0)
+{
+ m_fRadiusOffset = 0.0;
+ m_fAngleDegreeOffset = fAngleDegreeOffset;
+}
+
+PiePositionHelper::~PiePositionHelper()
+{
+}
+
+bool PiePositionHelper::getInnerAndOuterRadius( double fCategoryX
+ , double& fLogicInnerRadius, double& fLogicOuterRadius
+ , bool bUseRings, double fMaxOffset ) const
+{
+ if( !bUseRings )
+ fCategoryX = 1.0;
+
+ bool bIsVisible = true;
+ double fLogicInner = fCategoryX -0.5+m_fRingDistance/2.0;
+ double fLogicOuter = fCategoryX +0.5-m_fRingDistance/2.0;
+
+ if( !isMathematicalOrientationRadius() )
+ {
+ //in this case the given getMaximumX() was not corrcect instead the minimum should have been smaller by fMaxOffset
+ //but during getMaximumX and getMimumX we do not know the axis orientation
+ fLogicInner += fMaxOffset;
+ fLogicOuter += fMaxOffset;
+ }
+
+ if( fLogicInner >= getLogicMaxX() )
+ return false;
+ if( fLogicOuter <= getLogicMinX() )
+ return false;
+
+ if( fLogicInner < getLogicMinX() )
+ fLogicInner = getLogicMinX();
+ if( fLogicOuter > getLogicMaxX() )
+ fLogicOuter = getLogicMaxX();
+
+ fLogicInnerRadius = fLogicInner;
+ fLogicOuterRadius = fLogicOuter;
+ if( !isMathematicalOrientationRadius() )
+ std::swap(fLogicInnerRadius,fLogicOuterRadius);
+ return bIsVisible;
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+PieChart::PieChart( const uno::Reference<XChartType>& xChartTypeModel
+ , sal_Int32 nDimensionCount
+ , bool bExcludingPositioning )
+ : VSeriesPlotter( xChartTypeModel, nDimensionCount )
+ , m_pPosHelper( new PiePositionHelper( NormalAxis_Z, (m_nDimension==3)?0.0:90.0 ) )
+ , m_bUseRings(false)
+ , m_bSizeExcludesLabelsAndExplodedSegments(bExcludingPositioning)
+{
+ ::rtl::math::setNan(&m_fMaxOffset);
+
+ PlotterBase::m_pPosHelper = m_pPosHelper;
+ VSeriesPlotter::m_pMainPosHelper = m_pPosHelper;
+ m_pPosHelper->m_fRadiusOffset = 0.0;
+ m_pPosHelper->m_fRingDistance = 0.0;
+
+ uno::Reference< beans::XPropertySet > xChartTypeProps( xChartTypeModel, uno::UNO_QUERY );
+ if( xChartTypeProps.is() ) try
+ {
+ xChartTypeProps->getPropertyValue( C2U( "UseRings" )) >>= m_bUseRings;
+ if( m_bUseRings )
+ {
+ m_pPosHelper->m_fRadiusOffset = 1.0;
+ if( nDimensionCount==3 )
+ m_pPosHelper->m_fRingDistance = 0.1;
+ }
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+}
+
+PieChart::~PieChart()
+{
+ delete m_pPosHelper;
+}
+
+//-----------------------------------------------------------------
+
+void SAL_CALL PieChart::setScales( const uno::Sequence< ExplicitScaleData >& rScales
+ , sal_Bool /* bSwapXAndYAxis */ )
+ throw (uno::RuntimeException)
+{
+ DBG_ASSERT(m_nDimension<=rScales.getLength(),"Dimension of Plotter does not fit two dimension of given scale sequence");
+ m_pPosHelper->setScales( rScales, true );
+}
+
+//-----------------------------------------------------------------
+
+drawing::Direction3D PieChart::getPreferredDiagramAspectRatio() const
+{
+ if( m_nDimension == 3 )
+ return drawing::Direction3D(1,1,0.25);
+ return drawing::Direction3D(1,1,1);
+}
+
+bool PieChart::keepAspectRatio() const
+{
+ if( m_nDimension == 3 )
+ return false;
+ return true;
+}
+
+bool PieChart::shouldSnapRectToUsedArea()
+{
+ return true;
+}
+
+//-----------------------------------------------------------------
+// lang::XServiceInfo
+//-----------------------------------------------------------------
+/*
+APPHELPER_XSERVICEINFO_IMPL(PieChart,CHART2_VIEW_PIECHART_SERVICE_IMPLEMENTATION_NAME)
+
+ uno::Sequence< rtl::OUString > PieChart
+::getSupportedServiceNames_Static()
+{
+ uno::Sequence< rtl::OUString > aSNS( 1 );
+ aSNS.getArray()[ 0 ] = CHART2_VIEW_PIECHART_SERVICE_NAME;
+ return aSNS;
+}
+*/
+
+uno::Reference< drawing::XShape > PieChart::createDataPoint(
+ const uno::Reference< drawing::XShapes >& xTarget
+ , const uno::Reference< beans::XPropertySet >& xObjectProperties
+ , double fUnitCircleStartAngleDegree, double fUnitCircleWidthAngleDegree
+ , double fUnitCircleInnerRadius, double fUnitCircleOuterRadius
+ , double fLogicZ, double fDepth, double fExplodePercentage
+ , tPropertyNameValueMap* pOverwritePropertiesMap )
+{
+ //---------------------------
+ //transform position:
+ drawing::Direction3D aOffset;
+ if( !::rtl::math::approxEqual( fExplodePercentage, 0.0 ) )
+ {
+ double fAngle = fUnitCircleStartAngleDegree + fUnitCircleWidthAngleDegree/2.0;
+ double fRadius = (fUnitCircleOuterRadius-fUnitCircleInnerRadius)*fExplodePercentage;
+ drawing::Position3D aOrigin = m_pPosHelper->transformUnitCircleToScene( 0, 0, fLogicZ );
+ drawing::Position3D aNewOrigin = m_pPosHelper->transformUnitCircleToScene( fAngle, fRadius, fLogicZ );
+ aOffset = aNewOrigin - aOrigin;
+ }
+
+ //---------------------------
+ //create point
+ uno::Reference< drawing::XShape > xShape(0);
+ if(m_nDimension==3)
+ {
+ xShape = m_pShapeFactory->createPieSegment( xTarget
+ , fUnitCircleStartAngleDegree, fUnitCircleWidthAngleDegree
+ , fUnitCircleInnerRadius, fUnitCircleOuterRadius
+ , aOffset, B3DHomMatrixToHomogenMatrix( m_pPosHelper->getUnitCartesianToScene() )
+ , fDepth );
+ }
+ else
+ {
+ xShape = m_pShapeFactory->createPieSegment2D( xTarget
+ , fUnitCircleStartAngleDegree, fUnitCircleWidthAngleDegree
+ , fUnitCircleInnerRadius, fUnitCircleOuterRadius
+ , aOffset, B3DHomMatrixToHomogenMatrix( m_pPosHelper->getUnitCartesianToScene() ) );
+ }
+ this->setMappedProperties( xShape, xObjectProperties, PropertyMapper::getPropertyNameMapForFilledSeriesProperties(), pOverwritePropertiesMap );
+ return xShape;
+}
+
+void PieChart::addSeries( VDataSeries* pSeries, sal_Int32 /* zSlot */, sal_Int32 /* xSlot */, sal_Int32 /* ySlot */ )
+{
+ VSeriesPlotter::addSeries( pSeries, 0, -1, 0 );
+}
+
+double PieChart::getMinimumX()
+{
+ return 0.5;
+}
+double PieChart::getMaxOffset()
+{
+ if (!::rtl::math::isNan(m_fMaxOffset))
+ // Value already cached. Use it.
+ return m_fMaxOffset;
+
+ m_fMaxOffset = 0.0;
+ if( m_aZSlots.size()<=0 )
+ return m_fMaxOffset;
+ if( m_aZSlots[0].size()<=0 )
+ return m_fMaxOffset;
+
+ const ::std::vector< VDataSeries* >& rSeriesList( m_aZSlots[0][0].m_aSeriesVector );
+ if( rSeriesList.size()<=0 )
+ return m_fMaxOffset;
+
+ VDataSeries* pSeries = rSeriesList[0];
+ uno::Reference< beans::XPropertySet > xSeriesProp( pSeries->getPropertiesOfSeries() );
+ if( !xSeriesProp.is() )
+ return m_fMaxOffset;
+
+ double fExplodePercentage=0.0;
+ xSeriesProp->getPropertyValue( C2U( "Offset" )) >>= fExplodePercentage;
+ if(fExplodePercentage>m_fMaxOffset)
+ m_fMaxOffset=fExplodePercentage;
+
+ if(!m_bSizeExcludesLabelsAndExplodedSegments)
+ {
+ uno::Sequence< sal_Int32 > aAttributedDataPointIndexList;
+ if( xSeriesProp->getPropertyValue( C2U( "AttributedDataPoints" ) ) >>= aAttributedDataPointIndexList )
+ {
+ for(sal_Int32 nN=aAttributedDataPointIndexList.getLength();nN--;)
+ {
+ uno::Reference< beans::XPropertySet > xPointProp( pSeries->getPropertiesOfPoint(aAttributedDataPointIndexList[nN]) );
+ if(xPointProp.is())
+ {
+ fExplodePercentage=0.0;
+ xPointProp->getPropertyValue( C2U( "Offset" )) >>= fExplodePercentage;
+ if(fExplodePercentage>m_fMaxOffset)
+ m_fMaxOffset=fExplodePercentage;
+ }
+ }
+ }
+ }
+ return m_fMaxOffset;
+}
+double PieChart::getMaximumX()
+{
+ double fMaxOffset = getMaxOffset();
+ if( m_aZSlots.size()>0 && m_bUseRings)
+ return m_aZSlots[0].size()+0.5+fMaxOffset;
+ return 1.5+fMaxOffset;
+}
+double PieChart::getMinimumYInRange( double /* fMinimumX */, double /* fMaximumX */, sal_Int32 /* nAxisIndex */ )
+{
+ return 0.0;
+}
+
+double PieChart::getMaximumYInRange( double /* fMinimumX */, double /* fMaximumX */, sal_Int32 /* nAxisIndex */ )
+{
+ return 1.0;
+}
+
+bool PieChart::isExpandBorderToIncrementRhythm( sal_Int32 /* nDimensionIndex */ )
+{
+ return false;
+}
+
+bool PieChart::isExpandIfValuesCloseToBorder( sal_Int32 /* nDimensionIndex */ )
+{
+ return false;
+}
+
+bool PieChart::isExpandWideValuesToZero( sal_Int32 /* nDimensionIndex */ )
+{
+ return false;
+}
+
+bool PieChart::isExpandNarrowValuesTowardZero( sal_Int32 /* nDimensionIndex */ )
+{
+ return false;
+}
+
+bool PieChart::isSeperateStackingForDifferentSigns( sal_Int32 /* nDimensionIndex */ )
+{
+ return false;
+}
+
+void PieChart::createShapes()
+{
+ if( m_aZSlots.begin() == m_aZSlots.end() ) //no series
+ return;
+
+ DBG_ASSERT(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is(),"PieChart is not proper initialized");
+ if(!(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is()))
+ return;
+
+ //the text labels should be always on top of the other series shapes
+ //therefore create an own group for the texts to move them to front
+ //(because the text group is created after the series group the texts are displayed on top)
+ uno::Reference< drawing::XShapes > xSeriesTarget(
+ createGroupShape( m_xLogicTarget,rtl::OUString() ));
+ uno::Reference< drawing::XShapes > xTextTarget(
+ m_pShapeFactory->createGroup2D( m_xFinalTarget,rtl::OUString() ));
+ //---------------------------------------------
+ //check necessary here that different Y axis can not be stacked in the same group? ... hm?
+
+//=============================================================================
+ ::std::vector< VDataSeriesGroup >::iterator aXSlotIter = m_aZSlots[0].begin();
+ const ::std::vector< VDataSeriesGroup >::const_iterator aXSlotEnd = m_aZSlots[0].end();
+
+ ::std::vector< VDataSeriesGroup >::size_type nExplodeableSlot = 0;
+ if( m_pPosHelper->isMathematicalOrientationRadius() && m_bUseRings )
+ nExplodeableSlot = m_aZSlots[0].size()-1;
+
+ m_aLabelInfoList.clear();
+ ::rtl::math::setNan(&m_fMaxOffset);
+
+//=============================================================================
+ for( double fSlotX=0; aXSlotIter != aXSlotEnd && (m_bUseRings||fSlotX<0.5 ); aXSlotIter++, fSlotX+=1.0 )
+ {
+ ::std::vector< VDataSeries* >* pSeriesList = &(aXSlotIter->m_aSeriesVector);
+ if( pSeriesList->size()<=0 )//there should be only one series in each x slot
+ continue;
+ VDataSeries* pSeries = (*pSeriesList)[0];
+ if(!pSeries)
+ continue;
+
+ m_pPosHelper->m_fAngleDegreeOffset = pSeries->getStartingAngle();
+
+ double fLogicYSum = 0.0;
+ //iterate through all points to get the sum
+ sal_Int32 nPointIndex=0;
+ sal_Int32 nPointCount=pSeries->getTotalPointCount();
+ for( nPointIndex = 0; nPointIndex < nPointCount; nPointIndex++ )
+ {
+ double fY = pSeries->getYValue( nPointIndex );
+ if(fY<0.0)
+ {
+ //@todo warn somehow that negative values are treated as positive
+ }
+ if( ::rtl::math::isNan(fY) )
+ continue;
+ fLogicYSum += fabs(fY);
+ }
+ if(fLogicYSum==0.0)
+ continue;
+ double fLogicYForNextPoint = 0.0;
+ //iterate through all points to create shapes
+ for( nPointIndex = 0; nPointIndex < nPointCount; nPointIndex++ )
+ {
+ double fLogicInnerRadius, fLogicOuterRadius;
+ double fOffset = getMaxOffset();
+ bool bIsVisible = m_pPosHelper->getInnerAndOuterRadius( fSlotX+1.0, fLogicInnerRadius, fLogicOuterRadius, m_bUseRings, fOffset );
+ if( !bIsVisible )
+ continue;
+
+ double fLogicZ = -0.5;//as defined
+ double fDepth = this->getTransformedDepth();
+//=============================================================================
+
+ uno::Reference< drawing::XShapes > xSeriesGroupShape_Shapes = getSeriesGroupShape(pSeries, xSeriesTarget);
+ //collect data point information (logic coordinates, style ):
+ double fLogicYValue = fabs(pSeries->getYValue( nPointIndex ));
+ if( ::rtl::math::isNan(fLogicYValue) )
+ continue;
+ if(fLogicYValue==0.0)//@todo: continue also if the resolution to small
+ continue;
+ double fLogicYPos = fLogicYForNextPoint;
+ fLogicYForNextPoint += fLogicYValue;
+
+ uno::Reference< beans::XPropertySet > xPointProperties = pSeries->getPropertiesOfPoint( nPointIndex );
+
+ //iterate through all subsystems to create partial points
+ {
+ //logic values on angle axis:
+ double fLogicStartAngleValue = fLogicYPos/fLogicYSum;
+ double fLogicEndAngleValue = (fLogicYPos+fLogicYValue)/fLogicYSum;
+
+ double fExplodePercentage=0.0;
+ bool bDoExplode = ( nExplodeableSlot == static_cast< ::std::vector< VDataSeriesGroup >::size_type >(fSlotX) );
+ if(bDoExplode) try
+ {
+ xPointProperties->getPropertyValue( C2U( "Offset" )) >>= fExplodePercentage;
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+
+ //---------------------------
+ //transforme to unit circle:
+ double fUnitCircleWidthAngleDegree = m_pPosHelper->getWidthAngleDegree( fLogicStartAngleValue, fLogicEndAngleValue );
+ double fUnitCircleStartAngleDegree = m_pPosHelper->transformToAngleDegree( fLogicStartAngleValue );
+ double fUnitCircleInnerRadius = m_pPosHelper->transformToRadius( fLogicInnerRadius );
+ double fUnitCircleOuterRadius = m_pPosHelper->transformToRadius( fLogicOuterRadius );
+
+ //---------------------------
+ //point color:
+ std::auto_ptr< tPropertyNameValueMap > apOverwritePropertiesMap(0);
+ {
+ if(!pSeries->hasPointOwnColor(nPointIndex) && m_xColorScheme.is())
+ {
+ apOverwritePropertiesMap = std::auto_ptr< tPropertyNameValueMap >( new tPropertyNameValueMap() );
+ (*apOverwritePropertiesMap)[C2U("FillColor")] = uno::makeAny(
+ m_xColorScheme->getColorByIndex( nPointIndex ));
+ }
+ }
+
+ //create data point
+ uno::Reference<drawing::XShape> xPointShape(
+ createDataPoint( xSeriesGroupShape_Shapes, xPointProperties
+ , fUnitCircleStartAngleDegree, fUnitCircleWidthAngleDegree
+ , fUnitCircleInnerRadius, fUnitCircleOuterRadius
+ , fLogicZ, fDepth, fExplodePercentage, apOverwritePropertiesMap.get() ) );
+
+ //create label
+ if( pSeries->getDataPointLabelIfLabel(nPointIndex) )
+ {
+ if( !::rtl::math::approxEqual( fExplodePercentage, 0.0 ) )
+ {
+ double fExplodeOffset = (fUnitCircleOuterRadius-fUnitCircleInnerRadius)*fExplodePercentage;
+ fUnitCircleInnerRadius += fExplodeOffset;
+ fUnitCircleOuterRadius += fExplodeOffset;
+ }
+
+ sal_Int32 nLabelPlacement = pSeries->getLabelPlacement( nPointIndex, m_xChartTypeModel, m_nDimension, m_pPosHelper->isSwapXAndY() );
+ bool bMovementAllowed = ( nLabelPlacement == ::com::sun::star::chart::DataLabelPlacement::AVOID_OVERLAP );
+ if( bMovementAllowed )
+ nLabelPlacement = ::com::sun::star::chart::DataLabelPlacement::OUTSIDE;
+
+ LabelAlignment eAlignment(LABEL_ALIGN_CENTER);
+ sal_Int32 nScreenValueOffsetInRadiusDirection = 0 ;
+ if( nLabelPlacement == ::com::sun::star::chart::DataLabelPlacement::OUTSIDE )
+ nScreenValueOffsetInRadiusDirection = (3!=m_nDimension) ? 150 : 0;//todo maybe calculate this font height dependent
+ else if( nLabelPlacement == ::com::sun::star::chart::DataLabelPlacement::INSIDE )
+ nScreenValueOffsetInRadiusDirection = (3!=m_nDimension) ? -150 : 0;//todo maybe calculate this font height dependent
+ PolarLabelPositionHelper aPolarPosHelper(m_pPosHelper,m_nDimension,m_xLogicTarget,m_pShapeFactory);
+ awt::Point aScreenPosition2D(
+ aPolarPosHelper.getLabelScreenPositionAndAlignmentForUnitCircleValues(eAlignment, nLabelPlacement
+ , fUnitCircleStartAngleDegree, fUnitCircleWidthAngleDegree
+ , fUnitCircleInnerRadius, fUnitCircleOuterRadius, 0.0, 0 ));
+
+ PieLabelInfo aPieLabelInfo;
+ aPieLabelInfo.aFirstPosition = basegfx::B2IVector( aScreenPosition2D.X, aScreenPosition2D.Y );
+ awt::Point aOrigin( aPolarPosHelper.transformSceneToScreenPosition( m_pPosHelper->transformUnitCircleToScene( 0.0, 0.0, 0.5 ) ) );
+ aPieLabelInfo.aOrigin = basegfx::B2IVector( aOrigin.X, aOrigin.Y );
+
+ //add a scaling independent Offset if requested
+ if( nScreenValueOffsetInRadiusDirection != 0)
+ {
+ basegfx::B2IVector aDirection( aScreenPosition2D.X- aOrigin.X, aScreenPosition2D.Y- aOrigin.Y );
+ aDirection.setLength(nScreenValueOffsetInRadiusDirection);
+ aScreenPosition2D.X += aDirection.getX();
+ aScreenPosition2D.Y += aDirection.getY();
+ }
+
+ aPieLabelInfo.xTextShape = this->createDataLabel( xTextTarget, *pSeries, nPointIndex
+ , fLogicYValue, fLogicYSum, aScreenPosition2D, eAlignment );
+
+ uno::Reference< container::XChild > xChild( aPieLabelInfo.xTextShape, uno::UNO_QUERY );
+ if( xChild.is() )
+ aPieLabelInfo.xLabelGroupShape = uno::Reference<drawing::XShape>( xChild->getParent(), uno::UNO_QUERY );
+ aPieLabelInfo.fValue = fLogicYValue;
+ aPieLabelInfo.bMovementAllowed = bMovementAllowed;
+ aPieLabelInfo.bMoved= false;
+ aPieLabelInfo.xTextTarget = xTextTarget;
+ m_aLabelInfoList.push_back(aPieLabelInfo);
+ }
+
+ if(!bDoExplode)
+ {
+ ShapeFactory::setShapeName( xPointShape
+ , ObjectIdentifier::createPointCID( pSeries->getPointCID_Stub(), nPointIndex ) );
+ }
+ else try
+ {
+ //enable dragging of outer segments
+
+ double fAngle = fUnitCircleStartAngleDegree + fUnitCircleWidthAngleDegree/2.0;
+ double fMaxDeltaRadius = fUnitCircleOuterRadius-fUnitCircleInnerRadius;
+ drawing::Position3D aOrigin = m_pPosHelper->transformUnitCircleToScene( fAngle, fUnitCircleOuterRadius, fLogicZ );
+ drawing::Position3D aNewOrigin = m_pPosHelper->transformUnitCircleToScene( fAngle, fUnitCircleOuterRadius + fMaxDeltaRadius, fLogicZ );
+
+ sal_Int32 nOffsetPercent( static_cast<sal_Int32>(fExplodePercentage * 100.0) );
+
+ awt::Point aMinimumPosition( PlottingPositionHelper::transformSceneToScreenPosition(
+ aOrigin, m_xLogicTarget, m_pShapeFactory, m_nDimension ) );
+ awt::Point aMaximumPosition( PlottingPositionHelper::transformSceneToScreenPosition(
+ aNewOrigin, m_xLogicTarget, m_pShapeFactory, m_nDimension ) );
+
+ //enable draging of piesegments
+ rtl::OUString aPointCIDStub( ObjectIdentifier::createSeriesSubObjectStub( OBJECTTYPE_DATA_POINT
+ , pSeries->getSeriesParticle()
+ , ObjectIdentifier::getPieSegmentDragMethodServiceName()
+ , ObjectIdentifier::createPieSegmentDragParameterString(
+ nOffsetPercent, aMinimumPosition, aMaximumPosition )
+ ) );
+
+ ShapeFactory::setShapeName( xPointShape
+ , ObjectIdentifier::createPointCID( aPointCIDStub, nPointIndex ) );
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+ }//next series in x slot (next y slot)
+ }//next category
+ }//next x slot
+//=============================================================================
+//=============================================================================
+//=============================================================================
+ /* @todo remove series shapes if empty
+ //remove and delete point-group-shape if empty
+ if(!xSeriesGroupShape_Shapes->getCount())
+ {
+ (*aSeriesIter)->m_xShape.set(NULL);
+ m_xLogicTarget->remove(xSeriesGroupShape_Shape);
+ }
+ */
+
+ //remove and delete series-group-shape if empty
+
+ //... todo
+}
+
+namespace
+{
+
+::basegfx::B2IRectangle lcl_getRect( const uno::Reference< drawing::XShape >& xShape )
+{
+ ::basegfx::B2IRectangle aRect;
+ if( xShape.is() )
+ aRect = BaseGFXHelper::makeRectangle(xShape->getPosition(),xShape->getSize() );
+ return aRect;
+}
+
+bool lcl_isInsidePage( const awt::Point& rPos, const awt::Size& rSize, const awt::Size& rPageSize )
+{
+ if( rPos.X < 0 || rPos.Y < 0 )
+ return false;
+ if( (rPos.X + rSize.Width) > rPageSize.Width )
+ return false;
+ if( (rPos.Y + rSize.Height) > rPageSize.Height )
+ return false;
+ return true;
+}
+
+}//end anonymous namespace
+
+PieChart::PieLabelInfo::PieLabelInfo()
+ : xTextShape(0), xLabelGroupShape(0), aFirstPosition(), aOrigin(), fValue(0.0)
+ , bMovementAllowed(false), bMoved(false), xTextTarget(0), pPrevious(0),pNext(0)
+{
+}
+
+bool PieChart::PieLabelInfo::moveAwayFrom( const PieChart::PieLabelInfo* pFix, const awt::Size& rPageSize, bool bMoveHalfWay, bool bMoveClockwise, bool bAlternativeMoveDirection )
+{
+ //return true if the move was successful
+ if(!this->bMovementAllowed)
+ return false;
+
+ const sal_Int32 nLabelDistanceX = rPageSize.Width/50;
+ const sal_Int32 nLabelDistanceY = rPageSize.Height/50;
+
+ ::basegfx::B2IRectangle aOverlap( lcl_getRect( this->xLabelGroupShape ) );
+ aOverlap.intersect( lcl_getRect( pFix->xLabelGroupShape ) );
+ if( !aOverlap.isEmpty() )
+ {
+ (void)bAlternativeMoveDirection;//todo
+
+ basegfx::B2IVector aRadiusDirection = this->aFirstPosition - this->aOrigin;
+ aRadiusDirection.setLength(1.0);
+ basegfx::B2IVector aTangentialDirection( -aRadiusDirection.getY(), aRadiusDirection.getX() );
+ bool bShiftHorizontal = abs(aTangentialDirection.getX()) > abs(aTangentialDirection.getY());
+
+ sal_Int32 nShift = bShiftHorizontal ? static_cast<sal_Int32>(aOverlap.getWidth()) : static_cast<sal_Int32>(aOverlap.getHeight());
+ nShift += (bShiftHorizontal ? nLabelDistanceX : nLabelDistanceY);
+ if( bMoveHalfWay )
+ nShift/=2;
+ if(!bMoveClockwise)
+ nShift*=-1;
+ awt::Point aOldPos( this->xLabelGroupShape->getPosition() );
+ basegfx::B2IVector aNewPos = basegfx::B2IVector( aOldPos.X, aOldPos.Y ) + nShift*aTangentialDirection;
+
+ //check whether the new position is ok
+ awt::Point aNewAWTPos( aNewPos.getX(), aNewPos.getY() );
+ if( !lcl_isInsidePage( aNewAWTPos, this->xLabelGroupShape->getSize(), rPageSize ) )
+ return false;
+
+ this->xLabelGroupShape->setPosition( aNewAWTPos );
+ this->bMoved = true;
+ }
+ return true;
+}
+
+void PieChart::resetLabelPositionsToPreviousState()
+{
+ std::vector< PieLabelInfo >::iterator aIt = m_aLabelInfoList.begin();
+ std::vector< PieLabelInfo >::const_iterator aEnd = m_aLabelInfoList.end();
+ for( ;aIt!=aEnd; ++aIt )
+ aIt->xLabelGroupShape->setPosition(aIt->aPreviousPosition);
+}
+
+bool PieChart::detectLabelOverlapsAndMove( const awt::Size& rPageSize )
+{
+ //returns true when there might be more to do
+
+ //find borders of a group of overlapping labels
+ bool bOverlapFound = false;
+ PieLabelInfo* pStart = &(*(m_aLabelInfoList.rbegin()));
+ PieLabelInfo* pFirstBorder = 0;
+ PieLabelInfo* pSecondBorder = 0;
+ PieLabelInfo* pCurrent = pStart;
+ do
+ {
+ ::basegfx::B2IRectangle aPreviousOverlap( lcl_getRect( pCurrent->xLabelGroupShape ) );
+ ::basegfx::B2IRectangle aNextOverlap( aPreviousOverlap );
+ aPreviousOverlap.intersect( lcl_getRect( pCurrent->pPrevious->xLabelGroupShape ) );
+ aNextOverlap.intersect( lcl_getRect( pCurrent->pNext->xLabelGroupShape ) );
+
+ bool bPreviousOverlap = !aPreviousOverlap.isEmpty();
+ bool bNextOverlap = !aNextOverlap.isEmpty();
+ if( bPreviousOverlap || bNextOverlap )
+ bOverlapFound = true;
+ if( !bPreviousOverlap && bNextOverlap )
+ {
+ pFirstBorder = pCurrent;
+ break;
+ }
+ pCurrent = pCurrent->pNext;
+ }
+ while( pCurrent != pStart );
+
+ if( !bOverlapFound )
+ return false;
+
+ if( pFirstBorder )
+ {
+ pCurrent = pFirstBorder;
+ do
+ {
+ ::basegfx::B2IRectangle aPreviousOverlap( lcl_getRect( pCurrent->xLabelGroupShape ) );
+ ::basegfx::B2IRectangle aNextOverlap( aPreviousOverlap );
+ aPreviousOverlap.intersect( lcl_getRect( pCurrent->pPrevious->xLabelGroupShape ) );
+ aNextOverlap.intersect( lcl_getRect( pCurrent->pNext->xLabelGroupShape ) );
+
+ if( !aPreviousOverlap.isEmpty() && aNextOverlap.isEmpty() )
+ {
+ pSecondBorder = pCurrent;
+ break;
+ }
+ pCurrent = pCurrent->pNext;
+ }
+ while( pCurrent != pFirstBorder );
+ }
+
+ if( !pFirstBorder || !pSecondBorder )
+ {
+ pFirstBorder = &(*(m_aLabelInfoList.rbegin()));
+ pSecondBorder = &(*(m_aLabelInfoList.begin()));
+ }
+
+ //find center
+ PieLabelInfo* pCenter = pFirstBorder;
+ sal_Int32 nOverlapGroupCount = 1;
+ for( pCurrent = pFirstBorder ;pCurrent != pSecondBorder; pCurrent = pCurrent->pNext )
+ nOverlapGroupCount++;
+ sal_Int32 nCenterPos = nOverlapGroupCount/2;
+ bool bSingleCenter = nOverlapGroupCount%2 != 0;
+ if( bSingleCenter )
+ nCenterPos++;
+ if(nCenterPos>1)
+ {
+ pCurrent = pFirstBorder;
+ while( --nCenterPos )
+ pCurrent = pCurrent->pNext;
+ pCenter = pCurrent;
+ }
+
+ //remind current positions
+ pCurrent = pStart;
+ do
+ {
+ pCurrent->aPreviousPosition = pCurrent->xLabelGroupShape->getPosition();
+ pCurrent = pCurrent->pNext;
+ }
+ while( pCurrent != pStart );
+
+ //
+ bool bAlternativeMoveDirection = false;
+ if( !tryMoveLabels( pFirstBorder, pSecondBorder, pCenter, bSingleCenter, bAlternativeMoveDirection, rPageSize ) )
+ tryMoveLabels( pFirstBorder, pSecondBorder, pCenter, bSingleCenter, bAlternativeMoveDirection, rPageSize );
+ return true;
+}
+
+bool PieChart::tryMoveLabels( PieLabelInfo* pFirstBorder, PieLabelInfo* pSecondBorder
+ , PieLabelInfo* pCenter
+ , bool bSingleCenter, bool& rbAlternativeMoveDirection, const awt::Size& rPageSize )
+{
+ PieLabelInfo* p1 = bSingleCenter ? pCenter->pPrevious : pCenter;
+ PieLabelInfo* p2 = pCenter->pNext;
+ //return true when successful
+
+ bool bLabelOrderIsAntiClockWise = m_pPosHelper->isMathematicalOrientationAngle();
+
+ PieLabelInfo* pCurrent = 0;
+ for( pCurrent = p2 ;pCurrent->pPrevious != pSecondBorder; pCurrent = pCurrent->pNext )
+ {
+ PieLabelInfo* pFix = 0;
+ for( pFix = p2->pPrevious ;pFix != pCurrent; pFix = pFix->pNext )
+ {
+ if( !pCurrent->moveAwayFrom( pFix, rPageSize, !bSingleCenter && pCurrent == p2, !bLabelOrderIsAntiClockWise, rbAlternativeMoveDirection ) )
+ {
+ if( !rbAlternativeMoveDirection )
+ {
+ rbAlternativeMoveDirection = true;
+ resetLabelPositionsToPreviousState();
+ return false;
+ }
+ }
+ }
+ }
+ for( pCurrent = p1 ;pCurrent->pNext != pFirstBorder; pCurrent = pCurrent->pPrevious )
+ {
+ PieLabelInfo* pFix = 0;
+ for( pFix = p2->pNext ;pFix != pCurrent; pFix = pFix->pPrevious )
+ {
+ if( !pCurrent->moveAwayFrom( pFix, rPageSize, false, bLabelOrderIsAntiClockWise, rbAlternativeMoveDirection ) )
+ {
+ if( !rbAlternativeMoveDirection )
+ {
+ rbAlternativeMoveDirection = true;
+ resetLabelPositionsToPreviousState();
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+}
+
+void PieChart::rearrangeLabelToAvoidOverlapIfRequested( const awt::Size& rPageSize )
+{
+ //------------------------------------------------------------------
+ //check whether there are any labels that should be moved
+ std::vector< PieLabelInfo >::iterator aIt1 = m_aLabelInfoList.begin();
+ std::vector< PieLabelInfo >::const_iterator aEnd = m_aLabelInfoList.end();
+ bool bMoveableFound = false;
+ for( ;aIt1!=aEnd; ++aIt1 )
+ {
+ if(aIt1->bMovementAllowed)
+ {
+ bMoveableFound = true;
+ break;
+ }
+ }
+ if(!bMoveableFound)
+ return;
+
+ double fPageDiagonaleLength = sqrt( double( rPageSize.Width*rPageSize.Width + rPageSize.Height*rPageSize.Height) );
+ if( ::rtl::math::approxEqual( fPageDiagonaleLength, 0.0 ) )
+ return;
+
+ //------------------------------------------------------------------
+ //init next and previous
+ aIt1 = m_aLabelInfoList.begin();
+ std::vector< PieLabelInfo >::iterator aIt2 = aIt1;
+ if( aIt1==aEnd )//no need to do anything when we only have one label
+ return;
+ aIt1->pPrevious = &(*(m_aLabelInfoList.rbegin()));
+ ++aIt2;
+ for( ;aIt2!=aEnd; ++aIt1, ++aIt2 )
+ {
+ PieLabelInfo& rInfo1( *aIt1 );
+ PieLabelInfo& rInfo2( *aIt2 );
+ rInfo1.pNext = &rInfo2;
+ rInfo2.pPrevious = &rInfo1;
+ }
+ aIt1->pNext = &(*(m_aLabelInfoList.begin()));
+
+
+ //------------------------------------------------------------------
+ //detect overlaps and move
+ sal_Int32 nMaxIterations = 50;
+ while( detectLabelOverlapsAndMove( rPageSize ) && nMaxIterations > 0 )
+ nMaxIterations--;
+
+ //------------------------------------------------------------------
+ //create connection lines for the moved labels
+ aEnd = m_aLabelInfoList.end();
+ VLineProperties aVLineProperties;
+ for( aIt1 = m_aLabelInfoList.begin(); aIt1!=aEnd; ++aIt1 )
+ {
+ PieLabelInfo& rInfo( *aIt1 );
+ if( rInfo.bMoved )
+ {
+ sal_Int32 nX1 = rInfo.aFirstPosition.getX();
+ sal_Int32 nY1 = rInfo.aFirstPosition.getY();
+ sal_Int32 nX2 = nX1;
+ sal_Int32 nY2 = nY1;
+ ::basegfx::B2IRectangle aRect( lcl_getRect( rInfo.xLabelGroupShape ) );
+ if( nX1 < aRect.getMinX() )
+ nX2 = aRect.getMinX();
+ else if( nX1 > aRect.getMaxX() )
+ nX2 = aRect.getMaxX();
+
+ if( nY1 < aRect.getMinY() )
+ nY2 = aRect.getMinY();
+ else if( nY1 > aRect.getMaxY() )
+ nY2 = aRect.getMaxY();
+
+
+ //when the line is very short compared to the page size don't create one
+ ::basegfx::B2DVector aLength(nX1-nX2, nY1-nY2);
+ if( (aLength.getLength()/fPageDiagonaleLength) < 0.01 )
+ continue;
+
+ drawing::PointSequenceSequence aPoints(1);
+ aPoints[0].realloc(2);
+ aPoints[0][0].X = nX1;
+ aPoints[0][0].Y = nY1;
+ aPoints[0][1].X = nX2;
+ aPoints[0][1].Y = nY2;
+
+ uno::Reference< beans::XPropertySet > xProp( rInfo.xTextShape, uno::UNO_QUERY);
+ if( xProp.is() )
+ {
+ sal_Int32 nColor = 0;
+ xProp->getPropertyValue(C2U("CharColor")) >>= nColor;
+ if( nColor != -1 )//automatic font color does not work for lines -> fallback to black
+ aVLineProperties.Color = uno::makeAny(nColor);
+ }
+ m_pShapeFactory->createLine2D( rInfo.xTextTarget, aPoints, &aVLineProperties );
+ }
+ }
+}
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
diff --git a/chart2/source/view/charttypes/PieChart.hxx b/chart2/source/view/charttypes/PieChart.hxx
new file mode 100644
index 000000000000..e6fedb05d52e
--- /dev/null
+++ b/chart2/source/view/charttypes/PieChart.hxx
@@ -0,0 +1,145 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CHART2_PIECHART_HXX
+#define _CHART2_PIECHART_HXX
+
+#include "VSeriesPlotter.hxx"
+#include <basegfx/vector/b2dvector.hxx>
+#include <basegfx/range/b2irectangle.hxx>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+class PiePositionHelper;
+
+class PieChart : public VSeriesPlotter
+{
+ //-------------------------------------------------------------------------
+ // public methods
+ //-------------------------------------------------------------------------
+public:
+ PieChart( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::chart2::XChartType >& xChartTypeModel
+ , sal_Int32 nDimensionCount, bool bExcludingPositioning );
+ virtual ~PieChart();
+
+ //-------------------------------------------------------------------------
+ // chart2::XPlotter
+ //-------------------------------------------------------------------------
+
+ virtual void SAL_CALL createShapes();
+ virtual void rearrangeLabelToAvoidOverlapIfRequested( const ::com::sun::star::awt::Size& rPageSize );
+
+ 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 ::rtl::OUString SAL_CALL getCoordinateSystemTypeID( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL setScales( const ::com::sun::star::uno::Sequence< ::com::sun::star::chart2::ExplicitScaleData >& rScales ) 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 addSeries( VDataSeries* pSeries, sal_Int32 zSlot = -1, sal_Int32 xSlot = -1,sal_Int32 ySlot = -1 );
+
+ //-------------------
+ virtual ::com::sun::star::drawing::Direction3D getPreferredDiagramAspectRatio() const;
+ virtual bool keepAspectRatio() const;
+ virtual bool shouldSnapRectToUsedArea();
+
+ //MinimumAndMaximumSupplier
+ virtual double getMinimumX();
+ virtual double getMaximumX();
+ virtual double getMinimumYInRange( double fMinimumX, double fMaximumX, sal_Int32 nAxisIndex );
+ virtual double getMaximumYInRange( double fMinimumX, double fMaximumX, sal_Int32 nAxisIndex );
+
+ virtual bool isExpandBorderToIncrementRhythm( sal_Int32 nDimensionIndex );
+ virtual bool isExpandIfValuesCloseToBorder( sal_Int32 nDimensionIndex );
+ virtual bool isExpandWideValuesToZero( sal_Int32 nDimensionIndex );
+ virtual bool isExpandNarrowValuesTowardZero( sal_Int32 nDimensionIndex );
+ virtual bool isSeperateStackingForDifferentSigns( sal_Int32 nDimensionIndex );
+
+ //-------------------------------------------------------------------------
+ //-------------------------------------------------------------------------
+ //-------------------------------------------------------------------------
+private: //methods
+ //no default constructor
+ PieChart();
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >
+ createDataPoint( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShapes >& xTarget
+ , const ::com::sun::star::uno::Reference<
+ ::com::sun::star::beans::XPropertySet >& xObjectProperties
+ , double fUnitCircleStartAngleDegree, double fWidthAngleDegree
+ , double fUnitCircleInnerRadius, double fUnitCircleOuterRadius
+ , double fLogicZ, double fDepth, double fExplodePercentage
+ , tPropertyNameValueMap* pOverWritePropertiesMap );
+
+ double getMaxOffset();
+ bool detectLabelOverlapsAndMove(const ::com::sun::star::awt::Size& rPageSize);//returns true when there might be more to do
+ void resetLabelPositionsToPreviousState();
+struct PieLabelInfo;
+ bool tryMoveLabels( PieLabelInfo* pFirstBorder, PieLabelInfo* pSecondBorder
+ , PieLabelInfo* pCenter, bool bSingleCenter, bool& rbAlternativeMoveDirection
+ , const ::com::sun::star::awt::Size& rPageSize );
+
+private: //member
+ PiePositionHelper* m_pPosHelper;
+ bool m_bUseRings;
+ bool m_bSizeExcludesLabelsAndExplodedSegments;
+
+ struct PieLabelInfo
+ {
+ PieLabelInfo();
+ bool moveAwayFrom( const PieLabelInfo* pFix, const ::com::sun::star::awt::Size& rPageSize
+ , bool bMoveHalfWay, bool bMoveClockwise, bool bAlternativeMoveDirection );
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > xTextShape;
+ ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > xLabelGroupShape;
+ ::basegfx::B2IVector aFirstPosition;
+ ::basegfx::B2IVector aOrigin;
+ double fValue;
+ bool bMovementAllowed;
+ bool bMoved;
+ ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes > xTextTarget;
+ PieLabelInfo* pPrevious;
+ PieLabelInfo* pNext;
+ ::com::sun::star::awt::Point aPreviousPosition;
+ };
+
+ ::std::vector< PieLabelInfo > m_aLabelInfoList;
+
+ double m_fMaxOffset; /// cached max offset value (init'ed to NaN)
+};
+//.............................................................................
+} //namespace chart
+//.............................................................................
+#endif
diff --git a/chart2/source/view/charttypes/Splines.cxx b/chart2/source/view/charttypes/Splines.cxx
new file mode 100644
index 000000000000..67ecac93b64c
--- /dev/null
+++ b/chart2/source/view/charttypes/Splines.cxx
@@ -0,0 +1,545 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_chart2.hxx"
+
+#include "Splines.hxx"
+#include <rtl/math.hxx>
+
+#include <vector>
+#include <algorithm>
+#include <functional>
+
+// header for DBG_ASSERT
+#include <tools/debug.hxx>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+using namespace ::com::sun::star;
+
+namespace
+{
+
+template< typename T >
+struct lcl_EqualsFirstDoubleOfPair : ::std::binary_function< ::std::pair< double, T >, ::std::pair< double, T >, bool >
+{
+ inline bool operator() ( const ::std::pair< double, T > & rOne, const ::std::pair< double, T > & rOther )
+ {
+ return ( ::rtl::math::approxEqual( rOne.first, rOther.first ) );
+ }
+};
+
+//-----------------------------------------------------------------------------
+
+typedef ::std::pair< double, double > tPointType;
+typedef ::std::vector< tPointType > tPointVecType;
+typedef tPointVecType::size_type lcl_tSizeType;
+
+class lcl_SplineCalculation
+{
+public:
+ /** @descr creates an object that calculates cublic splines on construction
+
+ @param rSortedPoints the points for which splines shall be calculated, they need to be sorted in x values
+ @param fY1FirstDerivation the resulting spline should have the first
+ derivation equal to this value at the x-value of the first point
+ of rSortedPoints. If fY1FirstDerivation is set to infinity, a natural
+ spline is calculated.
+ @param fYnFirstDerivation the resulting spline should have the first
+ derivation equal to this value at the x-value of the last point
+ of rSortedPoints
+ */
+ lcl_SplineCalculation( const tPointVecType & rSortedPoints,
+ double fY1FirstDerivation,
+ double fYnFirstDerivation );
+
+ /** @descr this function corresponds to the function splint in [1].
+
+ [1] Numerical Recipies in C, 2nd edition
+ William H. Press, et al.,
+ Section 3.3, page 116
+ */
+ double GetInterpolatedValue( double x );
+
+private:
+ /// a copy of the points given in the CTOR
+ tPointVecType m_aPoints;
+
+ /// the result of the Calculate() method
+ ::std::vector< double > m_aSecDerivY;
+
+ double m_fYp1;
+ double m_fYpN;
+
+ // these values are cached for performance reasons
+ tPointVecType::size_type m_nKLow;
+ tPointVecType::size_type m_nKHigh;
+ double m_fLastInterpolatedValue;
+
+ /** @descr this function corresponds to the function spline in [1].
+
+ [1] Numerical Recipies in C, 2nd edition
+ William H. Press, et al.,
+ Section 3.3, page 115
+ */
+ void Calculate();
+};
+
+//-----------------------------------------------------------------------------
+
+lcl_SplineCalculation::lcl_SplineCalculation(
+ const tPointVecType & rSortedPoints,
+ double fY1FirstDerivation,
+ double fYnFirstDerivation )
+ : m_aPoints( rSortedPoints ),
+ m_fYp1( fY1FirstDerivation ),
+ m_fYpN( fYnFirstDerivation ),
+ m_nKLow( 0 ),
+ m_nKHigh( rSortedPoints.size() - 1 )
+{
+ ::rtl::math::setInf( &m_fLastInterpolatedValue, sal_False );
+
+ // #108301# remove points that have equal x-values
+ m_aPoints.erase( ::std::unique( m_aPoints.begin(), m_aPoints.end(),
+ lcl_EqualsFirstDoubleOfPair< double >() ),
+ m_aPoints.end() );
+ Calculate();
+}
+
+void lcl_SplineCalculation::Calculate()
+{
+ if( m_aPoints.size() <= 1 )
+ return;
+
+ // n is the last valid index to m_aPoints
+ const tPointVecType::size_type n = m_aPoints.size() - 1;
+ ::std::vector< double > u( n );
+ m_aSecDerivY.resize( n + 1, 0.0 );
+
+ if( ::rtl::math::isInf( m_fYp1 ) )
+ {
+ // natural spline
+ m_aSecDerivY[ 0 ] = 0.0;
+ u[ 0 ] = 0.0;
+ }
+ else
+ {
+ m_aSecDerivY[ 0 ] = -0.5;
+ double xDiff = ( m_aPoints[ 1 ].first - m_aPoints[ 0 ].first );
+ u[ 0 ] = ( 3.0 / xDiff ) *
+ ((( m_aPoints[ 1 ].second - m_aPoints[ 0 ].second ) / xDiff ) - m_fYp1 );
+ }
+
+ for( tPointVecType::size_type i = 1; i < n; ++i )
+ {
+ ::std::pair< double, double >
+ p_i = m_aPoints[ i ],
+ p_im1 = m_aPoints[ i - 1 ],
+ p_ip1 = m_aPoints[ i + 1 ];
+
+ double sig = ( p_i.first - p_im1.first ) /
+ ( p_ip1.first - p_im1.first );
+ double p = sig * m_aSecDerivY[ i - 1 ] + 2.0;
+
+ m_aSecDerivY[ i ] = ( sig - 1.0 ) / p;
+ u[ i ] =
+ ( ( p_ip1.second - p_i.second ) /
+ ( p_ip1.first - p_i.first ) ) -
+ ( ( p_i.second - p_im1.second ) /
+ ( p_i.first - p_im1.first ) );
+ u[ i ] =
+ ( 6.0 * u[ i ] / ( p_ip1.first - p_im1.first )
+ - sig * u[ i - 1 ] ) / p;
+ }
+
+ // initialize to values for natural splines (used for m_fYpN equal to
+ // infinity)
+ double qn = 0.0;
+ double un = 0.0;
+
+ if( ! ::rtl::math::isInf( m_fYpN ) )
+ {
+ qn = 0.5;
+ double xDiff = ( m_aPoints[ n ].first - m_aPoints[ n - 1 ].first );
+ un = ( 3.0 / xDiff ) *
+ ( m_fYpN - ( m_aPoints[ n ].second - m_aPoints[ n - 1 ].second ) / xDiff );
+ }
+
+ m_aSecDerivY[ n ] = ( un - qn * u[ n - 1 ] ) * ( qn * m_aSecDerivY[ n - 1 ] + 1.0 );
+
+ // note: the algorithm in [1] iterates from n-1 to 0, but as size_type
+ // may be (usuall is) an unsigned type, we can not write k >= 0, as this
+ // is always true.
+ for( tPointVecType::size_type k = n; k > 0; --k )
+ {
+ ( m_aSecDerivY[ k - 1 ] *= m_aSecDerivY[ k ] ) += u[ k - 1 ];
+ }
+}
+
+double lcl_SplineCalculation::GetInterpolatedValue( double x )
+{
+ DBG_ASSERT( ( m_aPoints[ 0 ].first <= x ) &&
+ ( x <= m_aPoints[ m_aPoints.size() - 1 ].first ),
+ "Trying to extrapolate" );
+
+ const tPointVecType::size_type n = m_aPoints.size() - 1;
+ if( x < m_fLastInterpolatedValue )
+ {
+ m_nKLow = 0;
+ m_nKHigh = n;
+
+ // calculate m_nKLow and m_nKHigh
+ // first initialization is done in CTOR
+ while( m_nKHigh - m_nKLow > 1 )
+ {
+ tPointVecType::size_type k = ( m_nKHigh + m_nKLow ) / 2;
+ if( m_aPoints[ k ].first > x )
+ m_nKHigh = k;
+ else
+ m_nKLow = k;
+ }
+ }
+ else
+ {
+ while( ( m_aPoints[ m_nKHigh ].first < x ) &&
+ ( m_nKHigh <= n ) )
+ {
+ ++m_nKHigh;
+ ++m_nKLow;
+ }
+ DBG_ASSERT( m_nKHigh <= n, "Out of Bounds" );
+ }
+ m_fLastInterpolatedValue = x;
+
+ double h = m_aPoints[ m_nKHigh ].first - m_aPoints[ m_nKLow ].first;
+ DBG_ASSERT( h != 0, "Bad input to GetInterpolatedValue()" );
+
+ double a = ( m_aPoints[ m_nKHigh ].first - x ) / h;
+ double b = ( x - m_aPoints[ m_nKLow ].first ) / h;
+
+ return ( a * m_aPoints[ m_nKLow ].second +
+ b * m_aPoints[ m_nKHigh ].second +
+ (( a*a*a - a ) * m_aSecDerivY[ m_nKLow ] +
+ ( b*b*b - b ) * m_aSecDerivY[ m_nKHigh ] ) *
+ ( h*h ) / 6.0 );
+}
+
+//-----------------------------------------------------------------------------
+
+//create knot vector for B-spline
+double* createTVector( sal_Int32 n, sal_Int32 k )
+{
+ double* t = new double [n + k + 1];
+ for (sal_Int32 i=0; i<=n+k; i++ )
+ {
+ if(i < k)
+ t[i] = 0;
+ else if(i <= n)
+ t[i] = i-k+1;
+ else
+ t[i] = n-k+2;
+ }
+ return t;
+}
+
+//calculate left knot vector
+double TLeft (double x, sal_Int32 i, sal_Int32 k, const double *t )
+{
+ double deltaT = t[i + k - 1] - t[i];
+ return (deltaT == 0.0)
+ ? 0.0
+ : (x - t[i]) / deltaT;
+}
+
+//calculate right knot vector
+double TRight(double x, sal_Int32 i, sal_Int32 k, const double *t )
+{
+ double deltaT = t[i + k] - t[i + 1];
+ return (deltaT == 0.0)
+ ? 0.0
+ : (t[i + k] - x) / deltaT;
+}
+
+//calculate weight vector
+void BVector(double x, sal_Int32 n, sal_Int32 k, double *b, const double *t)
+{
+ sal_Int32 i = 0;
+ for( i=0; i<=n+k; i++ )
+ b[i]=0;
+
+ sal_Int32 i0 = (sal_Int32)floor(x) + k - 1;
+ b [i0] = 1;
+
+ for( sal_Int32 j=2; j<=k; j++ )
+ for( i=0; i<=i0; i++ )
+ b[i] = TLeft(x, i, j, t) * b[i] + TRight(x, i, j, t) * b [i + 1];
+}
+
+} // anonymous namespace
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+void SplineCalculater::CalculateCubicSplines(
+ const drawing::PolyPolygonShape3D& rInput
+ , drawing::PolyPolygonShape3D& rResult
+ , sal_Int32 nGranularity )
+{
+ DBG_ASSERT( nGranularity > 0, "Granularity is invalid" );
+
+ rResult.SequenceX.realloc(0);
+ rResult.SequenceY.realloc(0);
+ rResult.SequenceZ.realloc(0);
+
+ sal_Int32 nOuterCount = rInput.SequenceX.getLength();
+ if( !nOuterCount )
+ return;
+
+ rResult.SequenceX.realloc(nOuterCount);
+ rResult.SequenceY.realloc(nOuterCount);
+ rResult.SequenceZ.realloc(nOuterCount);
+
+ for( sal_Int32 nOuter = 0; nOuter < nOuterCount; ++nOuter )
+ {
+ if( rInput.SequenceX[nOuter].getLength() <= 1 )
+ continue; //we need at least two points
+
+ sal_Int32 nMaxIndexPoints = rInput.SequenceX[nOuter].getLength()-1; // is >=1
+ const double* pOldX = rInput.SequenceX[nOuter].getConstArray();
+ const double* pOldY = rInput.SequenceY[nOuter].getConstArray();
+ const double* pOldZ = rInput.SequenceZ[nOuter].getConstArray();
+
+ // #i13699# The curve gets a parameter and then for each coordinate a
+ // separate spline will be calculated using the parameter as first argument
+ // and the point coordinate as second argument. Therefore the points need
+ // not to be sorted in its x-coordinates. The parameter is sorted by
+ // construction.
+
+ ::std::vector < double > aParameter(nMaxIndexPoints+1);
+ aParameter[0]=0.0;
+ for( sal_Int32 nIndex=1; nIndex<=nMaxIndexPoints; nIndex++ )
+ {
+ // The euclidian distance leads to curve loops for functions having single extreme points
+ //aParameter[nIndex]=aParameter[nIndex-1]+
+ //sqrt( (pOldX[nIndex]-pOldX[nIndex-1])*(pOldX[nIndex]-pOldX[nIndex-1])+
+ //(pOldY[nIndex]-pOldY[nIndex-1])*(pOldY[nIndex]-pOldY[nIndex-1])+
+ //(pOldZ[nIndex]-pOldZ[nIndex-1])*(pOldZ[nIndex]-pOldZ[nIndex-1]));
+
+ // use increment of 1 instead
+ aParameter[nIndex]=aParameter[nIndex-1]+1;
+ }
+ // Split the calculation to X, Y and Z coordinate
+ tPointVecType aInputX;
+ aInputX.resize(nMaxIndexPoints+1);
+ tPointVecType aInputY;
+ aInputY.resize(nMaxIndexPoints+1);
+ tPointVecType aInputZ;
+ aInputZ.resize(nMaxIndexPoints+1);
+ for (sal_Int32 nN=0;nN<=nMaxIndexPoints; nN++ )
+ {
+ aInputX[ nN ].first=aParameter[nN];
+ aInputX[ nN ].second=pOldX[ nN ];
+ aInputY[ nN ].first=aParameter[nN];
+ aInputY[ nN ].second=pOldY[ nN ];
+ aInputZ[ nN ].first=aParameter[nN];
+ aInputZ[ nN ].second=pOldZ[ nN ];
+ }
+
+ // generate a spline for each coordinate. It holds the complete
+ // information to calculate each point of the curve
+ double fXDerivation;
+ double fYDerivation;
+ double fZDerivation;
+ if( pOldX[ 0 ] == pOldX[nMaxIndexPoints] &&
+ pOldY[ 0 ] == pOldY[nMaxIndexPoints] &&
+ pOldZ[ 0 ] == pOldZ[nMaxIndexPoints] )
+ {
+ // #i101050# avoid a corner in closed lines, which are smoothed by spline
+ // This derivation are special for parameter of kind 0,1,2,3... If you
+ // change generating parameters (see above), then adapt derivations too.)
+ fXDerivation = 0.5 * (pOldX[1]-pOldX[nMaxIndexPoints-1]);
+ fYDerivation = 0.5 * (pOldY[1]-pOldY[nMaxIndexPoints-1]);
+ fZDerivation = 0.5 * (pOldZ[1]-pOldZ[nMaxIndexPoints-1]);
+ }
+ else // generate the kind "natural spline"
+ {
+ double fInfty;
+ ::rtl::math::setInf( &fInfty, sal_False );
+ fXDerivation = fInfty;
+ fYDerivation = fInfty;
+ fZDerivation = fInfty;
+ }
+ lcl_SplineCalculation aSplineX( aInputX, fXDerivation, fXDerivation );
+ lcl_SplineCalculation aSplineY( aInputY, fYDerivation, fYDerivation );
+ lcl_SplineCalculation aSplineZ( aInputZ, fZDerivation, fZDerivation );
+
+ // fill result polygon with calculated values
+ rResult.SequenceX[nOuter].realloc( nMaxIndexPoints*nGranularity + 1);
+ rResult.SequenceY[nOuter].realloc( nMaxIndexPoints*nGranularity + 1);
+ rResult.SequenceZ[nOuter].realloc( nMaxIndexPoints*nGranularity + 1);
+
+ double* pNewX = rResult.SequenceX[nOuter].getArray();
+ double* pNewY = rResult.SequenceY[nOuter].getArray();
+ double* pNewZ = rResult.SequenceZ[nOuter].getArray();
+
+ sal_Int32 nNewPointIndex = 0; // Index in result points
+ // needed for inner loop
+ double fInc; // step for intermediate points
+ sal_Int32 nj; // for loop
+ double fParam; // a intermediate parameter value
+
+ for( sal_Int32 ni = 0; ni < nMaxIndexPoints; ni++ )
+ {
+ // given point is surely a curve point
+ pNewX[nNewPointIndex] = pOldX[ni];
+ pNewY[nNewPointIndex] = pOldY[ni];
+ pNewZ[nNewPointIndex] = pOldZ[ni];
+ nNewPointIndex++;
+
+ // calculate intermediate points
+ fInc = ( aParameter[ ni+1 ] - aParameter[ni] ) / static_cast< double >( nGranularity );
+ for(nj = 1; nj < nGranularity; nj++)
+ {
+ fParam = aParameter[ni] + ( fInc * static_cast< double >( nj ) );
+
+ pNewX[nNewPointIndex]=aSplineX.GetInterpolatedValue( fParam );
+ pNewY[nNewPointIndex]=aSplineY.GetInterpolatedValue( fParam );
+ pNewZ[nNewPointIndex]=aSplineZ.GetInterpolatedValue( fParam );
+ nNewPointIndex++;
+ }
+ }
+ // add last point
+ pNewX[nNewPointIndex] = pOldX[nMaxIndexPoints];
+ pNewY[nNewPointIndex] = pOldY[nMaxIndexPoints];
+ pNewZ[nNewPointIndex] = pOldZ[nMaxIndexPoints];
+ }
+}
+
+void SplineCalculater::CalculateBSplines(
+ const ::com::sun::star::drawing::PolyPolygonShape3D& rInput
+ , ::com::sun::star::drawing::PolyPolygonShape3D& rResult
+ , sal_Int32 nGranularity
+ , sal_Int32 nDegree )
+{
+ // #issue 72216#
+ // k is the order of the BSpline, nDegree is the degree of its polynoms
+ sal_Int32 k = nDegree + 1;
+
+ rResult.SequenceX.realloc(0);
+ rResult.SequenceY.realloc(0);
+ rResult.SequenceZ.realloc(0);
+
+ sal_Int32 nOuterCount = rInput.SequenceX.getLength();
+ if( !nOuterCount )
+ return; // no input
+
+ rResult.SequenceX.realloc(nOuterCount);
+ rResult.SequenceY.realloc(nOuterCount);
+ rResult.SequenceZ.realloc(nOuterCount);
+
+ for( sal_Int32 nOuter = 0; nOuter < nOuterCount; ++nOuter )
+ {
+ if( rInput.SequenceX[nOuter].getLength() <= 1 )
+ continue; // need at least 2 control points
+
+ sal_Int32 n = rInput.SequenceX[nOuter].getLength()-1; // maximum index of control points
+
+ double fCurveparam =0.0; // parameter for the curve
+ // 0<= fCurveparam < fMaxCurveparam
+ double fMaxCurveparam = 2.0+ n - k;
+ if (fMaxCurveparam <= 0.0)
+ return; // not enough control points for desired spline order
+
+ if (nGranularity < 1)
+ return; //need at least 1 line for each part beween the control points
+
+ const double* pOldX = rInput.SequenceX[nOuter].getConstArray();
+ const double* pOldY = rInput.SequenceY[nOuter].getConstArray();
+ const double* pOldZ = rInput.SequenceZ[nOuter].getConstArray();
+
+ // keep this amount of steps to go well with old version
+ sal_Int32 nNewSectorCount = nGranularity * n;
+ double fCurveStep = fMaxCurveparam/static_cast< double >(nNewSectorCount);
+
+ double *b = new double [n + k + 1]; // values of blending functions
+
+ const double* t = createTVector(n, k); // knot vector
+
+ rResult.SequenceX[nOuter].realloc(nNewSectorCount+1);
+ rResult.SequenceY[nOuter].realloc(nNewSectorCount+1);
+ rResult.SequenceZ[nOuter].realloc(nNewSectorCount+1);
+ double* pNewX = rResult.SequenceX[nOuter].getArray();
+ double* pNewY = rResult.SequenceY[nOuter].getArray();
+ double* pNewZ = rResult.SequenceZ[nOuter].getArray();
+
+ // variables needed inside loop, when calculating one point of output
+ sal_Int32 nPointIndex =0; //index of given contol points
+ double fX=0.0;
+ double fY=0.0;
+ double fZ=0.0; //coordinates of a new BSpline point
+
+ for(sal_Int32 nNewSector=0; nNewSector<nNewSectorCount; nNewSector++)
+ { // in first looping fCurveparam has value 0.0
+
+ // Calculate the values of the blending functions for actual curve parameter
+ BVector(fCurveparam, n, k, b, t);
+
+ // output point(fCurveparam) = sum over {input point * value of blending function}
+ fX = 0.0;
+ fY = 0.0;
+ fZ = 0.0;
+ for (nPointIndex=0;nPointIndex<=n;nPointIndex++)
+ {
+ fX +=pOldX[nPointIndex]*b[nPointIndex];
+ fY +=pOldY[nPointIndex]*b[nPointIndex];
+ fZ +=pOldZ[nPointIndex]*b[nPointIndex];
+ }
+ pNewX[nNewSector] = fX;
+ pNewY[nNewSector] = fY;
+ pNewZ[nNewSector] = fZ;
+
+ fCurveparam += fCurveStep; //for next looping
+ }
+ // add last control point to BSpline curve
+ pNewX[nNewSectorCount] = pOldX[n];
+ pNewY[nNewSectorCount] = pOldY[n];
+ pNewZ[nNewSectorCount] = pOldZ[n];
+
+ delete[] t;
+ delete[] b;
+ }
+}
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
+
diff --git a/chart2/source/view/charttypes/Splines.hxx b/chart2/source/view/charttypes/Splines.hxx
new file mode 100644
index 000000000000..642522f53ebe
--- /dev/null
+++ b/chart2/source/view/charttypes/Splines.hxx
@@ -0,0 +1,61 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CHART2_SPLINECALCULATOR_HXX
+#define _CHART2_SPLINECALCULATOR_HXX
+
+#include <com/sun/star/drawing/PolyPolygonShape3D.hpp>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+
+//-----------------------------------------------------------------------------
+/**
+*/
+
+class SplineCalculater
+{
+public:
+ static void CalculateCubicSplines(
+ const ::com::sun::star::drawing::PolyPolygonShape3D& rPoints
+ , ::com::sun::star::drawing::PolyPolygonShape3D& rResult
+ , sal_Int32 nGranularity );
+
+ static void CalculateBSplines(
+ const ::com::sun::star::drawing::PolyPolygonShape3D& rPoints
+ , ::com::sun::star::drawing::PolyPolygonShape3D& rResult
+ , sal_Int32 nGranularity
+ , sal_Int32 nSplineDepth );
+};
+
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
+#endif
diff --git a/chart2/source/view/charttypes/VSeriesPlotter.cxx b/chart2/source/view/charttypes/VSeriesPlotter.cxx
new file mode 100644
index 000000000000..840cbbe3e1e1
--- /dev/null
+++ b/chart2/source/view/charttypes/VSeriesPlotter.cxx
@@ -0,0 +1,2110 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_chart2.hxx"
+
+#include "VSeriesPlotter.hxx"
+#include "ShapeFactory.hxx"
+#include "chartview/ExplicitValueProvider.hxx"
+
+#include "CommonConverters.hxx"
+#include "macros.hxx"
+#include "ViewDefines.hxx"
+#include "ObjectIdentifier.hxx"
+#include "StatisticsHelper.hxx"
+#include "PlottingPositionHelper.hxx"
+#include "LabelPositionHelper.hxx"
+#include "ChartTypeHelper.hxx"
+#include "Clipping.hxx"
+#include "servicenames_charttypes.hxx"
+#include "chartview/NumberFormatterWrapper.hxx"
+#include "ContainerHelper.hxx"
+#include "DataSeriesHelper.hxx"
+#include "RegressionCurveHelper.hxx"
+#include "VLegendSymbolFactory.hxx"
+#include "FormattedStringHelper.hxx"
+#include "ResId.hxx"
+#include "Strings.hrc"
+#include "RelativePositionHelper.hxx"
+
+//only for creation: @todo remove if all plotter are uno components and instanciated via servicefactory
+#include "BarChart.hxx"
+#include "PieChart.hxx"
+#include "AreaChart.hxx"
+#include "CandleStickChart.hxx"
+#include "BubbleChart.hxx"
+//
+
+#include <com/sun/star/chart/ErrorBarStyle.hpp>
+#include <com/sun/star/chart2/XRegressionCurveContainer.hpp>
+#include <com/sun/star/container/XChild.hpp>
+#include <com/sun/star/chart2/RelativePosition.hpp>
+#include <editeng/unoprnms.hxx>
+#include <tools/color.hxx>
+// header for class OUStringBuffer
+#include <rtl/ustrbuf.hxx>
+#include <rtl/math.hxx>
+#include <tools/debug.hxx>
+#include <basegfx/vector/b2dvector.hxx>
+#include <com/sun/star/util/XCloneable.hpp>
+
+#include <svx/unoshape.hxx>
+
+#include <functional>
+
+//.............................................................................
+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;
+using rtl::OUString;
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+VDataSeriesGroup::CachedYValues::CachedYValues()
+ : m_bValuesDirty(true)
+ , m_fMinimumY(0.0)
+ , m_fMaximumY(0.0)
+{
+}
+
+VDataSeriesGroup::VDataSeriesGroup()
+ : m_aSeriesVector()
+ , m_bMaxPointCountDirty(true)
+ , m_nMaxPointCount(0)
+ , m_aListOfCachedYValues()
+
+{
+}
+
+VDataSeriesGroup::VDataSeriesGroup( VDataSeries* pSeries )
+ : m_aSeriesVector(1,pSeries)
+ , m_bMaxPointCountDirty(true)
+ , m_nMaxPointCount(0)
+ , m_aListOfCachedYValues()
+{
+}
+
+VDataSeriesGroup::~VDataSeriesGroup()
+{
+}
+
+void VDataSeriesGroup::deleteSeries()
+{
+ //delete all data series help objects:
+ ::std::vector< VDataSeries* >::const_iterator aIter = m_aSeriesVector.begin();
+ const ::std::vector< VDataSeries* >::const_iterator aEnd = m_aSeriesVector.end();
+ for( ; aIter != aEnd; aIter++ )
+ {
+ delete *aIter;
+ }
+ m_aSeriesVector.clear();
+}
+
+void VDataSeriesGroup::addSeries( VDataSeries* pSeries )
+{
+ m_aSeriesVector.push_back(pSeries);
+ m_bMaxPointCountDirty=true;
+}
+
+sal_Int32 VDataSeriesGroup::getSeriesCount() const
+{
+ return m_aSeriesVector.size();
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+VSeriesPlotter::VSeriesPlotter( const uno::Reference<XChartType>& xChartTypeModel
+ , sal_Int32 nDimensionCount, bool bCategoryXAxis )
+ : PlotterBase( nDimensionCount )
+ , m_pMainPosHelper( 0 )
+ , m_xChartTypeModel(xChartTypeModel)
+ , m_xChartTypeModelProps( uno::Reference< beans::XPropertySet >::query( xChartTypeModel ))
+ , m_aZSlots()
+ , m_bCategoryXAxis(bCategoryXAxis)
+ , m_xColorScheme()
+ , m_pExplicitCategoriesProvider(0)
+ , m_bPointsWereSkipped(false)
+{
+ DBG_ASSERT(m_xChartTypeModel.is(),"no XChartType available in view, fallback to default values may be wrong");
+}
+
+VSeriesPlotter::~VSeriesPlotter()
+{
+ //delete all data series help objects:
+ ::std::vector< ::std::vector< VDataSeriesGroup > >::iterator aZSlotIter = m_aZSlots.begin();
+ const ::std::vector< ::std::vector< VDataSeriesGroup > >::const_iterator aZSlotEnd = m_aZSlots.end();
+ for( ; aZSlotIter != aZSlotEnd; aZSlotIter++ )
+ {
+ ::std::vector< VDataSeriesGroup >::iterator aXSlotIter = aZSlotIter->begin();
+ const ::std::vector< VDataSeriesGroup >::const_iterator aXSlotEnd = aZSlotIter->end();
+ for( ; aXSlotIter != aXSlotEnd; aXSlotIter++ )
+ {
+ aXSlotIter->deleteSeries();
+ }
+ aZSlotIter->clear();
+ }
+ m_aZSlots.clear();
+
+ tSecondaryPosHelperMap::iterator aPosIt = m_aSecondaryPosHelperMap.begin();
+ while( aPosIt != m_aSecondaryPosHelperMap.end() )
+ {
+ PlottingPositionHelper* pPosHelper = aPosIt->second;
+ if( pPosHelper )
+ delete pPosHelper;
+ ++aPosIt;
+ }
+ m_aSecondaryPosHelperMap.clear();
+
+ m_aSecondaryValueScales.clear();
+}
+
+void VSeriesPlotter::addSeries( VDataSeries* pSeries, sal_Int32 zSlot, sal_Int32 xSlot, sal_Int32 ySlot )
+{
+ //take ownership of pSeries
+
+ DBG_ASSERT( pSeries, "series to add is NULL" );
+ if(!pSeries)
+ return;
+
+ if(m_bCategoryXAxis)
+ pSeries->setCategoryXAxis();
+
+ if(zSlot<0 || zSlot>=static_cast<sal_Int32>(m_aZSlots.size()))
+ {
+ //new z slot
+ ::std::vector< VDataSeriesGroup > aZSlot;
+ aZSlot.push_back( VDataSeriesGroup(pSeries) );
+ m_aZSlots.push_back( aZSlot );
+ }
+ else
+ {
+ //existing zslot
+ ::std::vector< VDataSeriesGroup >& rXSlots = m_aZSlots[zSlot];
+
+ if(xSlot<0 || xSlot>=static_cast<sal_Int32>(rXSlots.size()))
+ {
+ //append the series to already existing x series
+ rXSlots.push_back( VDataSeriesGroup(pSeries) );
+ }
+ else
+ {
+ //x slot is already occupied
+ //y slot decides what to do:
+
+ VDataSeriesGroup& rYSlots = rXSlots[xSlot];
+ sal_Int32 nYSlotCount = rYSlots.getSeriesCount();
+
+ if( ySlot < -1 )
+ {
+ //move all existing series in the xSlot to next slot
+ //@todo
+ OSL_ENSURE( false, "Not implemented yet");
+ }
+ else if( ySlot == -1 || ySlot >= nYSlotCount)
+ {
+ //append the series to already existing y series
+ rYSlots.addSeries(pSeries);
+ }
+ else
+ {
+ //y slot is already occupied
+ //insert at given y and x position
+
+ //@todo
+ OSL_ENSURE( false, "Not implemented yet");
+ }
+ }
+ }
+}
+
+drawing::Direction3D VSeriesPlotter::getPreferredDiagramAspectRatio() const
+{
+ drawing::Direction3D aRet(1.0,1.0,1.0);
+ drawing::Direction3D aScale( m_pPosHelper->getScaledLogicWidth() );
+ aRet.DirectionZ = aScale.DirectionZ*0.2;
+ if(aRet.DirectionZ>1.0)
+ aRet.DirectionZ=1.0;
+ if(aRet.DirectionZ>10)
+ aRet.DirectionZ=10;
+ return aRet;
+}
+
+bool VSeriesPlotter::keepAspectRatio() const
+{
+ return true;
+}
+
+void VSeriesPlotter::releaseShapes()
+{
+ ::std::vector< ::std::vector< VDataSeriesGroup > >::iterator aZSlotIter = m_aZSlots.begin();
+ const ::std::vector< ::std::vector< VDataSeriesGroup > >::const_iterator aZSlotEnd = m_aZSlots.end();
+ for( ; aZSlotIter != aZSlotEnd; aZSlotIter++ )
+ {
+ ::std::vector< VDataSeriesGroup >::iterator aXSlotIter = aZSlotIter->begin();
+ const ::std::vector< VDataSeriesGroup >::const_iterator aXSlotEnd = aZSlotIter->end();
+ for( ; aXSlotIter != aXSlotEnd; aXSlotIter++ )
+ {
+ ::std::vector< VDataSeries* >* pSeriesList = &(aXSlotIter->m_aSeriesVector);
+
+ ::std::vector< VDataSeries* >::iterator aSeriesIter = pSeriesList->begin();
+ const ::std::vector< VDataSeries* >::const_iterator aSeriesEnd = pSeriesList->end();
+
+ //iterate through all series in this x slot
+ for( ; aSeriesIter != aSeriesEnd; aSeriesIter++ )
+ {
+ VDataSeries* pSeries( *aSeriesIter );
+ pSeries->releaseShapes();
+ }
+ }
+ }
+}
+
+uno::Reference< drawing::XShapes > VSeriesPlotter::getSeriesGroupShape( VDataSeries* pDataSeries
+ , const uno::Reference< drawing::XShapes >& xTarget )
+{
+ uno::Reference< drawing::XShapes > xShapes( pDataSeries->m_xGroupShape );
+ if( !xShapes.is() )
+ {
+ //create a group shape for this series and add to logic target:
+ xShapes = createGroupShape( xTarget,pDataSeries->getCID() );
+ pDataSeries->m_xGroupShape = xShapes;
+ }
+ return xShapes;
+}
+
+uno::Reference< drawing::XShapes > VSeriesPlotter::getSeriesGroupShapeFrontChild( VDataSeries* pDataSeries
+ , const uno::Reference< drawing::XShapes >& xTarget )
+{
+ uno::Reference< drawing::XShapes > xShapes( pDataSeries->m_xFrontSubGroupShape );
+ if(!xShapes.is())
+ {
+ //ensure that the series group shape is already created
+ uno::Reference< drawing::XShapes > xSeriesShapes( this->getSeriesGroupShape( pDataSeries, xTarget ) );
+ //ensure that the back child is created first
+ this->getSeriesGroupShapeBackChild( pDataSeries, xTarget );
+ //use series group shape as parent for the new created front group shape
+ xShapes = createGroupShape( xSeriesShapes );
+ pDataSeries->m_xFrontSubGroupShape = xShapes;
+ }
+ return xShapes;
+}
+
+uno::Reference< drawing::XShapes > VSeriesPlotter::getSeriesGroupShapeBackChild( VDataSeries* pDataSeries
+ , const uno::Reference< drawing::XShapes >& xTarget )
+{
+ uno::Reference< drawing::XShapes > xShapes( pDataSeries->m_xBackSubGroupShape );
+ if(!xShapes.is())
+ {
+ //ensure that the series group shape is already created
+ uno::Reference< drawing::XShapes > xSeriesShapes( this->getSeriesGroupShape( pDataSeries, xTarget ) );
+ //use series group shape as parent for the new created back group shape
+ xShapes = createGroupShape( xSeriesShapes );
+ pDataSeries->m_xBackSubGroupShape = xShapes;
+ }
+ return xShapes;
+}
+
+uno::Reference< drawing::XShapes > VSeriesPlotter::getLabelsGroupShape( VDataSeries& rDataSeries
+ , const uno::Reference< drawing::XShapes >& xTextTarget )
+{
+ //xTextTarget needs to be a 2D shape container always!
+
+ uno::Reference< drawing::XShapes > xShapes( rDataSeries.m_xLabelsGroupShape );
+ if(!xShapes.is())
+ {
+ //create a 2D group shape for texts of this series and add to text target:
+ xShapes = m_pShapeFactory->createGroup2D( xTextTarget, rDataSeries.getLabelsCID() );
+ rDataSeries.m_xLabelsGroupShape = xShapes;
+ }
+ return xShapes;
+}
+
+uno::Reference< drawing::XShapes > VSeriesPlotter::getErrorBarsGroupShape( VDataSeries& rDataSeries
+ , const uno::Reference< drawing::XShapes >& xTarget )
+{
+ uno::Reference< drawing::XShapes > xShapes( rDataSeries.m_xErrorBarsGroupShape );
+ if(!xShapes.is())
+ {
+ //create a group shape for this series and add to logic target:
+ xShapes = this->createGroupShape( xTarget,rDataSeries.getErrorBarsCID() );
+ rDataSeries.m_xErrorBarsGroupShape = xShapes;
+ }
+ return xShapes;
+
+}
+
+OUString VSeriesPlotter::getLabelTextForValue( VDataSeries& rDataSeries
+ , sal_Int32 nPointIndex
+ , double fValue
+ , bool bAsPercentage )
+{
+ OUString aNumber;
+
+ if( m_apNumberFormatterWrapper.get())
+ {
+ sal_Int32 nNumberFormatKey = 0;
+ if( rDataSeries.hasExplicitNumberFormat(nPointIndex,bAsPercentage) )
+ nNumberFormatKey = rDataSeries.getExplicitNumberFormat(nPointIndex,bAsPercentage);
+ else if( bAsPercentage )
+ {
+ sal_Int32 nPercentFormat = ExplicitValueProvider::getPercentNumberFormat( m_apNumberFormatterWrapper->getNumberFormatsSupplier() );
+ if( nPercentFormat != -1 )
+ nNumberFormatKey = nPercentFormat;
+ }
+ else
+ {
+ if( rDataSeries.shouldLabelNumberFormatKeyBeDetectedFromYAxis() && m_aAxesNumberFormats.hasFormat(1,rDataSeries.getAttachedAxisIndex()) ) //y-axis
+ nNumberFormatKey = m_aAxesNumberFormats.getFormat(1,rDataSeries.getAttachedAxisIndex());
+ else
+ nNumberFormatKey = rDataSeries.detectNumberFormatKey( nPointIndex );
+ }
+ if(nNumberFormatKey<0)
+ nNumberFormatKey=0;
+
+ sal_Int32 nLabelCol = 0;
+ bool bColChanged;
+ aNumber = m_apNumberFormatterWrapper->getFormattedString(
+ nNumberFormatKey, fValue, nLabelCol, bColChanged );
+ //@todo: change color of label if bColChanged is true
+ }
+ else
+ {
+ sal_Unicode cDecSeparator = '.';//@todo get this locale dependent
+ aNumber = ::rtl::math::doubleToUString( fValue, rtl_math_StringFormat_G /*rtl_math_StringFormat*/
+ , 3/*DecPlaces*/ , cDecSeparator /*,sal_Int32 const * pGroups*/ /*,sal_Unicode cGroupSeparator*/ ,false /*bEraseTrailingDecZeros*/ );
+ }
+ return aNumber;
+}
+
+uno::Reference< drawing::XShape > VSeriesPlotter::createDataLabel( const uno::Reference< drawing::XShapes >& xTarget
+ , VDataSeries& rDataSeries
+ , sal_Int32 nPointIndex
+ , double fValue
+ , double fSumValue
+ , const awt::Point& rScreenPosition2D
+ , LabelAlignment eAlignment
+ , sal_Int32 nOffset )
+{
+ uno::Reference< drawing::XShape > xTextShape;
+
+ try
+ {
+ awt::Point aScreenPosition2D(rScreenPosition2D);
+ if(LABEL_ALIGN_LEFT==eAlignment)
+ aScreenPosition2D.X -= nOffset;
+ else if(LABEL_ALIGN_RIGHT==eAlignment)
+ aScreenPosition2D.X += nOffset;
+ else if(LABEL_ALIGN_TOP==eAlignment)
+ aScreenPosition2D.Y -= nOffset;
+ else if(LABEL_ALIGN_BOTTOM==eAlignment)
+ aScreenPosition2D.Y += nOffset;
+
+ uno::Reference< drawing::XShapes > xTarget_(
+ m_pShapeFactory->createGroup2D( this->getLabelsGroupShape(rDataSeries, xTarget)
+ , ObjectIdentifier::createPointCID( rDataSeries.getLabelCID_Stub(),nPointIndex ) ) );
+
+ //check wether the label needs to be created and how:
+ DataPointLabel* pLabel = rDataSeries.getDataPointLabelIfLabel( nPointIndex );
+
+ if( !pLabel )
+ return xTextShape;
+
+ //------------------------------------------------
+ //prepare legend symbol
+
+ Reference< drawing::XShape > xSymbol;
+ if(pLabel->ShowLegendSymbol)
+ {
+ if( rDataSeries.isVaryColorsByPoint() )
+ xSymbol.set( VSeriesPlotter::createLegendSymbolForPoint( rDataSeries, nPointIndex, xTarget_, m_xShapeFactory ) );
+ else
+ xSymbol.set( VSeriesPlotter::createLegendSymbolForSeries( rDataSeries, xTarget_, m_xShapeFactory ) );
+
+ }
+ //prepare text
+ ::rtl::OUStringBuffer aText;
+ ::rtl::OUString aSeparator(sal_Unicode(' '));
+ double fRotationDegrees = 0.0;
+ try
+ {
+ uno::Reference< beans::XPropertySet > xPointProps( rDataSeries.getPropertiesOfPoint( nPointIndex ) );
+ if(xPointProps.is())
+ {
+ xPointProps->getPropertyValue( C2U( "LabelSeparator" ) ) >>= aSeparator;
+ xPointProps->getPropertyValue( C2U( "TextRotation" ) ) >>= fRotationDegrees;
+ }
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+ bool bMultiLineLabel = aSeparator.equals(C2U("\n"));;
+ sal_Int32 nLineCountForSymbolsize = 0;
+ {
+ if(pLabel->ShowCategoryName)
+ {
+ if( m_pExplicitCategoriesProvider )
+ {
+ Sequence< OUString > aCategories( m_pExplicitCategoriesProvider->getSimpleCategories() );
+ if( nPointIndex >= 0 && nPointIndex < aCategories.getLength() )
+ {
+ aText.append( aCategories[nPointIndex] );
+ ++nLineCountForSymbolsize;
+ }
+ }
+ }
+
+ if(pLabel->ShowNumber)
+ {
+ OUString aNumber( this->getLabelTextForValue( rDataSeries
+ , nPointIndex, fValue, false /*bAsPercentage*/ ) );
+ if( aNumber.getLength() )
+ {
+ if(aText.getLength())
+ aText.append(aSeparator);
+ aText.append(aNumber);
+ ++nLineCountForSymbolsize;
+ }
+ }
+
+ if(pLabel->ShowNumberInPercent)
+ {
+ if(fSumValue==0.0)
+ fSumValue=1.0;
+ fValue /= fSumValue;
+ if( fValue < 0 )
+ fValue*=-1.0;
+
+ OUString aPercentage( this->getLabelTextForValue( rDataSeries
+ , nPointIndex, fValue, true /*bAsPercentage*/ ) );
+ if( aPercentage.getLength() )
+ {
+ if(aText.getLength())
+ aText.append(aSeparator);
+ aText.append(aPercentage);
+ ++nLineCountForSymbolsize;
+ }
+ }
+ }
+ //------------------------------------------------
+ //prepare properties for multipropertyset-interface of shape
+ tNameSequence* pPropNames;
+ tAnySequence* pPropValues;
+ if( !rDataSeries.getTextLabelMultiPropertyLists( nPointIndex, pPropNames, pPropValues ) )
+ return xTextShape;
+ LabelPositionHelper::changeTextAdjustment( *pPropValues, *pPropNames, eAlignment );
+
+ //------------------------------------------------
+ //create text shape
+ xTextShape = ShapeFactory(m_xShapeFactory).
+ createText( xTarget_, aText.makeStringAndClear()
+ , *pPropNames, *pPropValues, ShapeFactory::makeTransformation( aScreenPosition2D ) );
+
+ if( !xTextShape.is() )
+ return xTextShape;
+
+ const awt::Point aUnrotatedTextPos( xTextShape->getPosition() );
+ if( fRotationDegrees != 0.0 )
+ {
+ const double fDegreesPi( fRotationDegrees * ( F_PI / -180.0 ) );
+ uno::Reference< beans::XPropertySet > xProp( xTextShape, uno::UNO_QUERY );
+ if( xProp.is() )
+ xProp->setPropertyValue( C2U( "Transformation" ), ShapeFactory::makeTransformation( aScreenPosition2D, fDegreesPi ) );
+ LabelPositionHelper::correctPositionForRotation( xTextShape, eAlignment, fRotationDegrees, true /*bRotateAroundCenter*/ );
+ }
+
+ if( xSymbol.is() )
+ {
+ const awt::Point aOldTextPos( xTextShape->getPosition() );
+ awt::Point aNewTextPos( aOldTextPos );
+
+ awt::Size aSymbolSize( xSymbol->getSize() );
+ awt::Size aTextSize( xTextShape->getSize() );
+
+ if( !bMultiLineLabel || nLineCountForSymbolsize <= 0 )
+ nLineCountForSymbolsize = 1;
+ sal_Int32 nYDiff = aTextSize.Height/nLineCountForSymbolsize;
+ sal_Int32 nXDiff = aSymbolSize.Width * nYDiff/aSymbolSize.Height;
+
+ // #i109336# Improve auto positioning in chart
+ nXDiff = nXDiff * 80 / 100;
+ nYDiff = nYDiff * 80 / 100;
+
+ aSymbolSize.Width = nXDiff * 75/100;
+ aSymbolSize.Height = nYDiff * 75/100;
+
+ awt::Point aSymbolPosition( aUnrotatedTextPos );
+
+ // #i109336# Improve auto positioning in chart
+ aSymbolPosition.Y += ( nYDiff / 4 );
+
+ if(LABEL_ALIGN_LEFT==eAlignment
+ || LABEL_ALIGN_LEFT_TOP==eAlignment
+ || LABEL_ALIGN_LEFT_BOTTOM==eAlignment)
+ {
+ aSymbolPosition.X -= nXDiff;
+ }
+ else if(LABEL_ALIGN_RIGHT==eAlignment
+ || LABEL_ALIGN_RIGHT_TOP==eAlignment
+ || LABEL_ALIGN_RIGHT_BOTTOM==eAlignment )
+ {
+ aNewTextPos.X += nXDiff;
+ }
+ else if(LABEL_ALIGN_TOP==eAlignment
+ || LABEL_ALIGN_BOTTOM==eAlignment
+ || LABEL_ALIGN_CENTER==eAlignment )
+ {
+ aSymbolPosition.X -= nXDiff/2;
+ aNewTextPos.X += nXDiff/2;
+ }
+
+ xSymbol->setSize( aSymbolSize );
+ xSymbol->setPosition( aSymbolPosition );
+
+ //set position
+ xTextShape->setPosition( aNewTextPos );
+ }
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+
+ return xTextShape;
+}
+
+namespace
+{
+double lcl_getErrorBarLogicLength(
+ const uno::Sequence< double > & rData,
+ uno::Reference< beans::XPropertySet > xProp,
+ sal_Int32 nErrorBarStyle,
+ sal_Int32 nIndex,
+ bool bPositive )
+{
+ double fResult;
+ ::rtl::math::setNan( & fResult );
+ try
+ {
+ switch( nErrorBarStyle )
+ {
+ case ::com::sun::star::chart::ErrorBarStyle::NONE:
+ break;
+ case ::com::sun::star::chart::ErrorBarStyle::VARIANCE:
+ fResult = StatisticsHelper::getVariance( rData );
+ break;
+ case ::com::sun::star::chart::ErrorBarStyle::STANDARD_DEVIATION:
+ fResult = StatisticsHelper::getStandardDeviation( rData );
+ break;
+ case ::com::sun::star::chart::ErrorBarStyle::RELATIVE:
+ {
+ double fPercent = 0;
+ if( xProp->getPropertyValue( bPositive
+ ? C2U("PositiveError")
+ : C2U("NegativeError")) >>= fPercent )
+ {
+ if( nIndex >=0 && nIndex < rData.getLength() &&
+ ! ::rtl::math::isNan( rData[nIndex] ) &&
+ ! ::rtl::math::isNan( fPercent ))
+ {
+ fResult = rData[nIndex] * fPercent / 100.0;
+ }
+ }
+ }
+ break;
+ case ::com::sun::star::chart::ErrorBarStyle::ABSOLUTE:
+ xProp->getPropertyValue( bPositive
+ ? C2U("PositiveError")
+ : C2U("NegativeError")) >>= fResult;
+ break;
+ case ::com::sun::star::chart::ErrorBarStyle::ERROR_MARGIN:
+ {
+ // todo: check if this is really what's called error-margin
+ double fPercent = 0;
+ if( xProp->getPropertyValue( bPositive
+ ? C2U("PositiveError")
+ : C2U("NegativeError")) >>= fPercent )
+ {
+ double fMaxValue;
+ ::rtl::math::setInf(&fMaxValue, true);
+ const double* pValues = rData.getConstArray();
+ for(sal_Int32 i=0; i<rData.getLength(); ++i, ++pValues)
+ {
+ if(fMaxValue<*pValues)
+ fMaxValue=*pValues;
+ }
+ if( ::rtl::math::isFinite( fMaxValue ) &&
+ ::rtl::math::isFinite( fPercent ))
+ {
+ fResult = fMaxValue * fPercent / 100.0;
+ }
+ }
+ }
+ break;
+ case ::com::sun::star::chart::ErrorBarStyle::STANDARD_ERROR:
+ fResult = StatisticsHelper::getStandardError( rData );
+ break;
+ case ::com::sun::star::chart::ErrorBarStyle::FROM_DATA:
+ {
+ uno::Reference< chart2::data::XDataSource > xErrorBarData( xProp, uno::UNO_QUERY );
+ if( xErrorBarData.is())
+ fResult = StatisticsHelper::getErrorFromDataSource(
+ xErrorBarData, nIndex, bPositive /*, true */ /* y-error */ );
+ }
+ break;
+ }
+ }
+ catch( uno::Exception & e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+
+ return fResult;
+}
+
+void lcl_AddErrorBottomLine( const drawing::Position3D& rPosition, ::basegfx::B2DVector aMainDirection
+ , drawing::PolyPolygonShape3D& rPoly, sal_Int32 nSequenceIndex )
+{
+ double fFixedWidth = 200.0;
+
+ aMainDirection.normalize();
+ ::basegfx::B2DVector aOrthoDirection(-aMainDirection.getY(),aMainDirection.getX());
+ aOrthoDirection.normalize();
+
+ ::basegfx::B2DVector aAnchor( rPosition.PositionX, rPosition.PositionY );
+ ::basegfx::B2DVector aStart = aAnchor + aOrthoDirection*fFixedWidth/2.0;
+ ::basegfx::B2DVector aEnd = aAnchor - aOrthoDirection*fFixedWidth/2.0;
+
+ AddPointToPoly( rPoly, drawing::Position3D( aStart.getX(), aStart.getY(), rPosition.PositionZ), nSequenceIndex );
+ AddPointToPoly( rPoly, drawing::Position3D( aEnd.getX(), aEnd.getY(), rPosition.PositionZ), nSequenceIndex );
+}
+
+::basegfx::B2DVector lcl_getErrorBarMainDirection(
+ const drawing::Position3D& rStart
+ , const drawing::Position3D& rBottomEnd
+ , PlottingPositionHelper* pPosHelper
+ , const drawing::Position3D& rUnscaledLogicPosition
+ , bool bYError )
+{
+ ::basegfx::B2DVector aMainDirection = ::basegfx::B2DVector( rStart.PositionX - rBottomEnd.PositionX
+ , rStart.PositionY - rBottomEnd.PositionY );
+ if( !aMainDirection.getLength() )
+ {
+ //get logic clip values:
+ double MinX = pPosHelper->getLogicMinX();
+ double MinY = pPosHelper->getLogicMinY();
+ double MaxX = pPosHelper->getLogicMaxX();
+ double MaxY = pPosHelper->getLogicMaxY();
+ double fZ = pPosHelper->getLogicMinZ();
+
+
+ if( bYError )
+ {
+ //main direction has constant x value
+ MinX = rUnscaledLogicPosition.PositionX;
+ MaxX = rUnscaledLogicPosition.PositionX;
+ }
+ else
+ {
+ //main direction has constant y value
+ MinY = rUnscaledLogicPosition.PositionY;
+ MaxY = rUnscaledLogicPosition.PositionY;
+ }
+
+ drawing::Position3D aStart = pPosHelper->transformLogicToScene( MinX, MinY, fZ, false );
+ drawing::Position3D aEnd = pPosHelper->transformLogicToScene( MaxX, MaxY, fZ, false );
+
+ aMainDirection = ::basegfx::B2DVector( aStart.PositionX - aEnd.PositionX
+ , aStart.PositionY - aEnd.PositionY );
+ }
+ if( !aMainDirection.getLength() )
+ {
+ //@todo
+ }
+ return aMainDirection;
+}
+
+} // anonymous namespace
+
+// virtual
+void VSeriesPlotter::createErrorBar(
+ const uno::Reference< drawing::XShapes >& xTarget
+ , const drawing::Position3D& rUnscaledLogicPosition
+ , const uno::Reference< beans::XPropertySet > & xErrorBarProperties
+ , const VDataSeries& rVDataSeries
+ , sal_Int32 nIndex
+ , bool bYError /* = true */
+ )
+{
+ if( !ChartTypeHelper::isSupportingStatisticProperties( m_xChartTypeModel, m_nDimension ) )
+ return;
+
+ if( ! xErrorBarProperties.is())
+ return;
+
+ try
+ {
+ sal_Bool bShowPositive = sal_False;
+ sal_Bool bShowNegative = sal_False;
+ sal_Int32 nErrorBarStyle = ::com::sun::star::chart::ErrorBarStyle::VARIANCE;
+
+ xErrorBarProperties->getPropertyValue( C2U( "ShowPositiveError" )) >>= bShowPositive;
+ xErrorBarProperties->getPropertyValue( C2U( "ShowNegativeError" )) >>= bShowNegative;
+ xErrorBarProperties->getPropertyValue( C2U( "ErrorBarStyle" )) >>= nErrorBarStyle;
+
+ if(!bShowPositive && !bShowNegative)
+ return;
+
+ if(nErrorBarStyle==::com::sun::star::chart::ErrorBarStyle::NONE)
+ return;
+
+ drawing::Position3D aUnscaledLogicPosition(rUnscaledLogicPosition);
+ if(nErrorBarStyle==::com::sun::star::chart::ErrorBarStyle::STANDARD_DEVIATION)
+ aUnscaledLogicPosition.PositionY = rVDataSeries.getYMeanValue();
+
+ bool bCreateNegativeBorder = false;//make a vertical line at the negative end of the error bar
+ bool bCreatePositiveBorder = false;//make a vertical line at the positive end of the error bar
+ drawing::Position3D aMiddle(aUnscaledLogicPosition);
+ const double fX = aUnscaledLogicPosition.PositionX;
+ const double fY = aUnscaledLogicPosition.PositionY;
+ const double fZ = aUnscaledLogicPosition.PositionZ;
+ aMiddle = m_pPosHelper->transformLogicToScene( fX, fY, fZ, true );
+
+ drawing::Position3D aNegative(aMiddle);
+ drawing::Position3D aPositive(aMiddle);
+
+ uno::Sequence< double > aData( bYError ? rVDataSeries.getAllY() : rVDataSeries.getAllX() );
+
+ if( bShowPositive )
+ {
+ double fLength = lcl_getErrorBarLogicLength( aData, xErrorBarProperties, nErrorBarStyle, nIndex, true );
+ if( ::rtl::math::isFinite( fLength ) )
+ {
+ double fLocalX = fX;
+ double fLocalY = fY;
+ if( bYError )
+ fLocalY+=fLength;
+ else
+ fLocalX+=fLength;
+ bCreatePositiveBorder = m_pPosHelper->isLogicVisible(fLocalX, fLocalY, fZ);
+ aPositive = m_pPosHelper->transformLogicToScene( fLocalX, fLocalY, fZ, true );
+ }
+ else
+ bShowPositive = false;
+ }
+
+ if( bShowNegative )
+ {
+ double fLength = lcl_getErrorBarLogicLength( aData, xErrorBarProperties, nErrorBarStyle, nIndex, false );
+ if( ::rtl::math::isFinite( fLength ) )
+ {
+ double fLocalX = fX;
+ double fLocalY = fY;
+ if( bYError )
+ fLocalY-=fLength;
+ else
+ fLocalX-=fLength;
+
+ bCreateNegativeBorder = m_pPosHelper->isLogicVisible( fLocalX, fLocalY, fZ);
+ aNegative = m_pPosHelper->transformLogicToScene( fLocalX, fLocalY, fZ, true );
+ }
+ else
+ bShowNegative = false;
+ }
+
+ if(!bShowPositive && !bShowNegative)
+ return;
+
+ drawing::PolyPolygonShape3D aPoly;
+
+ sal_Int32 nSequenceIndex=0;
+ if( bShowNegative )
+ AddPointToPoly( aPoly, aNegative, nSequenceIndex );
+ AddPointToPoly( aPoly, aMiddle, nSequenceIndex );
+ if( bShowPositive )
+ AddPointToPoly( aPoly, aPositive, nSequenceIndex );
+
+ if( bShowNegative && bCreateNegativeBorder )
+ {
+ ::basegfx::B2DVector aMainDirection = lcl_getErrorBarMainDirection( aMiddle, aNegative, m_pPosHelper, aUnscaledLogicPosition, bYError );
+ nSequenceIndex++;
+ lcl_AddErrorBottomLine( aNegative, aMainDirection, aPoly, nSequenceIndex );
+ }
+ if( bShowPositive && bCreatePositiveBorder )
+ {
+ ::basegfx::B2DVector aMainDirection = lcl_getErrorBarMainDirection( aMiddle, aPositive, m_pPosHelper, aUnscaledLogicPosition, bYError );
+ nSequenceIndex++;
+ lcl_AddErrorBottomLine( aPositive, aMainDirection, aPoly, nSequenceIndex );
+ }
+
+ uno::Reference< drawing::XShape > xShape = m_pShapeFactory->createLine2D( xTarget, PolyToPointSequence( aPoly) );
+ this->setMappedProperties( xShape, xErrorBarProperties, PropertyMapper::getPropertyNameMapForLineProperties() );
+ }
+ catch( uno::Exception & e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+
+}
+
+// virtual
+void VSeriesPlotter::createErrorBar_Y( const drawing::Position3D& rUnscaledLogicPosition
+ , VDataSeries& rVDataSeries, sal_Int32 nPointIndex
+ , const uno::Reference< drawing::XShapes >& xTarget )
+{
+ if(m_nDimension!=2)
+ return;
+ // error bars
+ uno::Reference< beans::XPropertySet > xErrorBarProp(rVDataSeries.getYErrorBarProperties(nPointIndex));
+ if( xErrorBarProp.is())
+ {
+ uno::Reference< drawing::XShapes > xErrorBarsGroup_Shapes(
+ this->getErrorBarsGroupShape(rVDataSeries, xTarget) );
+
+ createErrorBar( xErrorBarsGroup_Shapes
+ , rUnscaledLogicPosition, xErrorBarProp
+ , rVDataSeries, nPointIndex
+ , true /* bYError */ );
+ }
+}
+
+void VSeriesPlotter::createRegressionCurvesShapes( VDataSeries& rVDataSeries
+ , const uno::Reference< drawing::XShapes >& xTarget
+ , const uno::Reference< drawing::XShapes >& xEquationTarget
+ , bool bMaySkipPointsInRegressionCalculation )
+{
+ if(m_nDimension!=2)
+ return;
+ uno::Reference< XRegressionCurveContainer > xRegressionContainer(
+ rVDataSeries.getModel(), uno::UNO_QUERY );
+ if(!xRegressionContainer.is())
+ return;
+ double fMinX = m_pPosHelper->getLogicMinX();
+ double fMaxX = m_pPosHelper->getLogicMaxX();
+
+ uno::Sequence< uno::Reference< XRegressionCurve > > aCurveList =
+ xRegressionContainer->getRegressionCurves();
+ for(sal_Int32 nN=0; nN<aCurveList.getLength(); nN++)
+ {
+ uno::Reference< XRegressionCurveCalculator > xRegressionCurveCalculator(
+ aCurveList[nN]->getCalculator() );
+ if( ! xRegressionCurveCalculator.is())
+ continue;
+ xRegressionCurveCalculator->recalculateRegression( rVDataSeries.getAllX(), rVDataSeries.getAllY() );
+
+ sal_Int32 nRegressionPointCount = 50;//@todo find a more optimal solution if more complicated curve types are introduced
+ drawing::PolyPolygonShape3D aRegressionPoly;
+ aRegressionPoly.SequenceX.realloc(1);
+ aRegressionPoly.SequenceY.realloc(1);
+ aRegressionPoly.SequenceZ.realloc(1);
+ aRegressionPoly.SequenceX[0].realloc(nRegressionPointCount);
+ aRegressionPoly.SequenceY[0].realloc(nRegressionPointCount);
+ aRegressionPoly.SequenceZ[0].realloc(nRegressionPointCount);
+ sal_Int32 nRealPointCount=0;
+
+ uno::Sequence< chart2::ExplicitScaleData > aScaleDataSeq( m_pPosHelper->getScales());
+ uno::Reference< chart2::XScaling > xScalingX;
+ uno::Reference< chart2::XScaling > xScalingY;
+ if( aScaleDataSeq.getLength() >= 2 )
+ {
+ xScalingX.set( aScaleDataSeq[0].Scaling );
+ xScalingY.set( aScaleDataSeq[1].Scaling );
+ }
+
+ uno::Sequence< geometry::RealPoint2D > aCalculatedPoints(
+ xRegressionCurveCalculator->getCurveValues(
+ fMinX, fMaxX, nRegressionPointCount, xScalingX, xScalingY, bMaySkipPointsInRegressionCalculation ));
+ nRegressionPointCount = aCalculatedPoints.getLength();
+ for(sal_Int32 nP=0; nP<nRegressionPointCount; nP++)
+ {
+ double fLogicX = aCalculatedPoints[nP].X;
+ double fLogicY = aCalculatedPoints[nP].Y;
+ double fLogicZ = 0.0;//dummy
+
+ m_pPosHelper->doLogicScaling( &fLogicX, &fLogicY, &fLogicZ );
+
+ if( !::rtl::math::isNan(fLogicX) && !::rtl::math::isInf(fLogicX)
+ && !::rtl::math::isNan(fLogicY) && !::rtl::math::isInf(fLogicY)
+ && !::rtl::math::isNan(fLogicZ) && !::rtl::math::isInf(fLogicZ) )
+ {
+ aRegressionPoly.SequenceX[0][nRealPointCount] = fLogicX;
+ aRegressionPoly.SequenceY[0][nRealPointCount] = fLogicY;
+ nRealPointCount++;
+ }
+ }
+ aRegressionPoly.SequenceX[0].realloc(nRealPointCount);
+ aRegressionPoly.SequenceY[0].realloc(nRealPointCount);
+ aRegressionPoly.SequenceZ[0].realloc(nRealPointCount);
+
+ drawing::PolyPolygonShape3D aClippedPoly;
+ Clipping::clipPolygonAtRectangle( aRegressionPoly, m_pPosHelper->getScaledLogicClipDoubleRect(), aClippedPoly );
+ aRegressionPoly = aClippedPoly;
+ m_pPosHelper->transformScaledLogicToScene( aRegressionPoly );
+
+ awt::Point aDefaultPos;
+ if( aRegressionPoly.SequenceX.getLength() && aRegressionPoly.SequenceX[0].getLength() )
+ {
+ uno::Reference< beans::XPropertySet > xCurveModelProp( aCurveList[nN], uno::UNO_QUERY );
+ VLineProperties aVLineProperties;
+ aVLineProperties.initFromPropertySet( xCurveModelProp );
+
+ //create an extra group shape for each curve for selection handling
+ bool bAverageLine = RegressionCurveHelper::isMeanValueLine( aCurveList[nN] );
+ uno::Reference< drawing::XShapes > xRegressionGroupShapes =
+ createGroupShape( xTarget, rVDataSeries.getDataCurveCID( nN, bAverageLine ) );
+ uno::Reference< drawing::XShape > xShape = m_pShapeFactory->createLine2D(
+ xRegressionGroupShapes, PolyToPointSequence( aRegressionPoly ), &aVLineProperties );
+ m_pShapeFactory->setShapeName( xShape, C2U("MarkHandles") );
+ aDefaultPos = xShape->getPosition();
+ }
+
+ // curve equation and correlation coefficient
+ uno::Reference< beans::XPropertySet > xEqProp( aCurveList[nN]->getEquationProperties());
+ if( xEqProp.is())
+ {
+ createRegressionCurveEquationShapes(
+ rVDataSeries.getDataCurveEquationCID( nN ),
+ xEqProp, xEquationTarget, xRegressionCurveCalculator,
+ aDefaultPos );
+ }
+ }
+}
+
+void VSeriesPlotter::createRegressionCurveEquationShapes(
+ const OUString & rEquationCID,
+ const uno::Reference< beans::XPropertySet > & xEquationProperties,
+ const uno::Reference< drawing::XShapes >& xEquationTarget,
+ const uno::Reference< chart2::XRegressionCurveCalculator > & xRegressionCurveCalculator,
+ awt::Point aDefaultPos )
+{
+ OSL_ASSERT( xEquationProperties.is());
+ if( !xEquationProperties.is())
+ return;
+
+ bool bShowEquation = false;
+ bool bShowCorrCoeff = false;
+ OUString aSep( sal_Unicode('\n'));
+ if(( xEquationProperties->getPropertyValue( C2U("ShowEquation")) >>= bShowEquation ) &&
+ ( xEquationProperties->getPropertyValue( C2U("ShowCorrelationCoefficient")) >>= bShowCorrCoeff ))
+ {
+ if( ! (bShowEquation || bShowCorrCoeff))
+ return;
+
+ ::rtl::OUStringBuffer aFormula;
+ sal_Int32 nNumberFormatKey = 0;
+ xEquationProperties->getPropertyValue( C2U("NumberFormat")) >>= nNumberFormatKey;
+
+ if( bShowEquation )
+ {
+ if( m_apNumberFormatterWrapper.get())
+ {
+ aFormula = xRegressionCurveCalculator->getFormattedRepresentation(
+ m_apNumberFormatterWrapper->getNumberFormatsSupplier(),
+ nNumberFormatKey );
+ }
+ else
+ {
+ aFormula = xRegressionCurveCalculator->getRepresentation();
+ }
+
+ if( bShowCorrCoeff )
+ {
+// xEquationProperties->getPropertyValue( C2U("Separator")) >>= aSep;
+ aFormula.append( aSep );
+ }
+ }
+ if( bShowCorrCoeff )
+ {
+ aFormula.append( sal_Unicode( 'R' ));
+ aFormula.append( sal_Unicode( 0x00b2 ));
+ aFormula.append( C2U( " = " ));
+ double fR( xRegressionCurveCalculator->getCorrelationCoefficient());
+ if( m_apNumberFormatterWrapper.get())
+ {
+ sal_Int32 nLabelCol = 0;
+ bool bColChanged;
+ aFormula.append(
+ m_apNumberFormatterWrapper->getFormattedString(
+ nNumberFormatKey, fR*fR, nLabelCol, bColChanged ));
+ //@todo: change color of label if bColChanged is true
+ }
+ else
+ {
+ sal_Unicode aDecimalSep( '.' );//@todo get this locale dependent
+ aFormula.append( ::rtl::math::doubleToUString(
+ fR*fR, rtl_math_StringFormat_G, 4, aDecimalSep, true ));
+ }
+ }
+
+ awt::Point aScreenPosition2D;
+ chart2::RelativePosition aRelativePosition;
+ if( xEquationProperties->getPropertyValue( C2U("RelativePosition")) >>= aRelativePosition )
+ {
+ //@todo decide wether x is primary or secondary
+ double fX = aRelativePosition.Primary*m_aPageReferenceSize.Width;
+ double fY = aRelativePosition.Secondary*m_aPageReferenceSize.Height;
+ aScreenPosition2D.X = static_cast< sal_Int32 >( ::rtl::math::round( fX ));
+ aScreenPosition2D.Y = static_cast< sal_Int32 >( ::rtl::math::round( fY ));
+ }
+ else
+ aScreenPosition2D = aDefaultPos;
+
+ if( aFormula.getLength())
+ {
+ // set fill and line properties on creation
+ tNameSequence aNames;
+ tAnySequence aValues;
+ PropertyMapper::getPreparedTextShapePropertyLists( xEquationProperties, aNames, aValues );
+
+ uno::Reference< drawing::XShape > xTextShape = m_pShapeFactory->createText(
+ xEquationTarget, aFormula.makeStringAndClear(),
+ aNames, aValues, ShapeFactory::makeTransformation( aScreenPosition2D ));
+
+// // adapt font sizes
+// awt::Size aOldRefSize;
+// if( xTitleProperties->getPropertyValue( C2U("ReferencePageSize")) >>= aOldRefSize )
+// {
+// uno::Reference< beans::XPropertySet > xShapeProp( xTextShape, uno::UNO_QUERY );
+// if( xShapeProp.is())
+// RelativeSizeHelper::adaptFontSizes( xShapeProp, aOldRefSize, m_aPageReferenceSize );
+// }
+
+ OSL_ASSERT( xTextShape.is());
+ if( xTextShape.is())
+ {
+ ShapeFactory::setShapeName( xTextShape, rEquationCID );
+ xTextShape->setPosition(
+ RelativePositionHelper::getUpperLeftCornerOfAnchoredObject(
+ aScreenPosition2D, xTextShape->getSize(), aRelativePosition.Anchor ));
+ }
+ }
+ }
+}
+
+
+void VSeriesPlotter::setMappedProperties(
+ const uno::Reference< drawing::XShape >& xTargetShape
+ , const uno::Reference< beans::XPropertySet >& xSource
+ , const tPropertyNameMap& rMap
+ , tPropertyNameValueMap* pOverwriteMap )
+{
+ uno::Reference< beans::XPropertySet > xTargetProp( xTargetShape, uno::UNO_QUERY );
+ PropertyMapper::setMappedProperties(xTargetProp,xSource,rMap,pOverwriteMap);
+}
+
+//-------------------------------------------------------------------------
+// MinimumAndMaximumSupplier
+//-------------------------------------------------------------------------
+
+double VSeriesPlotter::getMinimumX()
+{
+ if( m_bCategoryXAxis )
+ {
+ double fRet = 1.0;//first category (index 0) matches with real number 1.0
+ if( m_pExplicitCategoriesProvider && m_pExplicitCategoriesProvider->hasComplexCategories() )
+ fRet -= 0.5;
+ return fRet;
+ }
+
+ double fMinimum, fMaximum;
+ this->getMinimumAndMaximiumX( fMinimum, fMaximum );
+ return fMinimum;
+}
+double VSeriesPlotter::getMaximumX()
+{
+ if( m_bCategoryXAxis )
+ {
+ //return category count
+ double fRet = getPointCount();//first category (index 0) matches with real number 1.0
+ if( m_pExplicitCategoriesProvider && m_pExplicitCategoriesProvider->hasComplexCategories() )
+ fRet += 0.5;
+ return fRet;
+ }
+
+ double fMinimum, fMaximum;
+ this->getMinimumAndMaximiumX( fMinimum, fMaximum );
+ return fMaximum;
+}
+
+double VSeriesPlotter::getMinimumYInRange( double fMinimumX, double fMaximumX, sal_Int32 nAxisIndex )
+{
+ if( !m_bCategoryXAxis )
+ {
+ double fMinY, fMaxY;
+ this->getMinimumAndMaximiumYInContinuousXRange( fMinY, fMaxY, fMinimumX, fMaximumX, nAxisIndex );
+ return fMinY;
+ }
+
+ double fMinimum, fMaximum;
+ ::rtl::math::setInf(&fMinimum, false);
+ ::rtl::math::setInf(&fMaximum, true);
+ for(size_t nZ =0; nZ<m_aZSlots.size();nZ++ )
+ {
+ ::std::vector< VDataSeriesGroup >& rXSlots = m_aZSlots[nZ];
+ for(size_t nN =0; nN<rXSlots.size();nN++ )
+ {
+ double fLocalMinimum, fLocalMaximum;
+ rXSlots[nN].calculateYMinAndMaxForCategoryRange(
+ static_cast<sal_Int32>(fMinimumX-1.0) //first category (index 0) matches with real number 1.0
+ , static_cast<sal_Int32>(fMaximumX-1.0) //first category (index 0) matches with real number 1.0
+ , isSeperateStackingForDifferentSigns( 1 )
+ , fLocalMinimum, fLocalMaximum, nAxisIndex );
+ if(fMaximum<fLocalMaximum)
+ fMaximum=fLocalMaximum;
+ if(fMinimum>fLocalMinimum)
+ fMinimum=fLocalMinimum;
+ }
+ }
+ if(::rtl::math::isInf(fMinimum))
+ ::rtl::math::setNan(&fMinimum);
+ return fMinimum;
+}
+
+double VSeriesPlotter::getMaximumYInRange( double fMinimumX, double fMaximumX, sal_Int32 nAxisIndex )
+{
+ if( !m_bCategoryXAxis )
+ {
+ double fMinY, fMaxY;
+ this->getMinimumAndMaximiumYInContinuousXRange( fMinY, fMaxY, fMinimumX, fMaximumX, nAxisIndex );
+ return fMaxY;
+ }
+
+ double fMinimum, fMaximum;
+ ::rtl::math::setInf(&fMinimum, false);
+ ::rtl::math::setInf(&fMaximum, true);
+ for(size_t nZ =0; nZ<m_aZSlots.size();nZ++ )
+ {
+ ::std::vector< VDataSeriesGroup >& rXSlots = m_aZSlots[nZ];
+ for(size_t nN =0; nN<rXSlots.size();nN++ )
+ {
+ double fLocalMinimum, fLocalMaximum;
+ rXSlots[nN].calculateYMinAndMaxForCategoryRange(
+ static_cast<sal_Int32>(fMinimumX-1.0) //first category (index 0) matches with real number 1.0
+ , static_cast<sal_Int32>(fMaximumX-1.0) //first category (index 0) matches with real number 1.0
+ , isSeperateStackingForDifferentSigns( 1 )
+ , fLocalMinimum, fLocalMaximum, nAxisIndex );
+ if(fMaximum<fLocalMaximum)
+ fMaximum=fLocalMaximum;
+ if(fMinimum>fLocalMinimum)
+ fMinimum=fLocalMinimum;
+ }
+ }
+ if(::rtl::math::isInf(fMaximum))
+ ::rtl::math::setNan(&fMaximum);
+ return fMaximum;
+}
+
+double VSeriesPlotter::getMinimumZ()
+{
+ //this is the default for all charts without a meaningfull z axis
+ return 0.5;
+}
+double VSeriesPlotter::getMaximumZ()
+{
+ if( 3!=m_nDimension )
+ return 0.5;
+ return m_aZSlots.size()+0.5;
+}
+
+namespace
+{
+ bool lcl_isValueAxis( sal_Int32 nDimensionIndex, bool bCategoryXAxis )
+ {
+ // default implementation: true for Y axes, and for value X axis
+ if( nDimensionIndex == 0 )
+ return !bCategoryXAxis;
+ if( nDimensionIndex == 1 )
+ return true;
+ return false;
+ }
+}
+
+bool VSeriesPlotter::isExpandBorderToIncrementRhythm( sal_Int32 nDimensionIndex )
+{
+ return lcl_isValueAxis( nDimensionIndex, m_bCategoryXAxis );
+}
+
+bool VSeriesPlotter::isExpandIfValuesCloseToBorder( sal_Int32 nDimensionIndex )
+{
+ // do not expand axes in 3D charts
+ return (m_nDimension < 3) && lcl_isValueAxis( nDimensionIndex, m_bCategoryXAxis );
+}
+
+bool VSeriesPlotter::isExpandWideValuesToZero( sal_Int32 nDimensionIndex )
+{
+ // default implementation: only for Y axis
+ return nDimensionIndex == 1;
+}
+
+bool VSeriesPlotter::isExpandNarrowValuesTowardZero( sal_Int32 nDimensionIndex )
+{
+ // default implementation: only for Y axis
+ return nDimensionIndex == 1;
+}
+
+bool VSeriesPlotter::isSeperateStackingForDifferentSigns( sal_Int32 nDimensionIndex )
+{
+ // default implementation: only for Y axis
+ return nDimensionIndex == 1;
+}
+
+void VSeriesPlotter::getMinimumAndMaximiumX( double& rfMinimum, double& rfMaximum ) const
+{
+ ::rtl::math::setInf(&rfMinimum, false);
+ ::rtl::math::setInf(&rfMaximum, true);
+
+ ::std::vector< ::std::vector< VDataSeriesGroup > >::const_iterator aZSlotIter = m_aZSlots.begin();
+ const ::std::vector< ::std::vector< VDataSeriesGroup > >::const_iterator aZSlotEnd = m_aZSlots.end();
+ for( ; aZSlotIter != aZSlotEnd; aZSlotIter++ )
+ {
+ ::std::vector< VDataSeriesGroup >::const_iterator aXSlotIter = aZSlotIter->begin();
+ const ::std::vector< VDataSeriesGroup >::const_iterator aXSlotEnd = aZSlotIter->end();
+ for( ; aXSlotIter != aXSlotEnd; aXSlotIter++ )
+ {
+ double fLocalMinimum, fLocalMaximum;
+ aXSlotIter->getMinimumAndMaximiumX( fLocalMinimum, fLocalMaximum );
+ if( !::rtl::math::isNan(fLocalMinimum) && fLocalMinimum< rfMinimum )
+ rfMinimum = fLocalMinimum;
+ if( !::rtl::math::isNan(fLocalMaximum) && fLocalMaximum> rfMaximum )
+ rfMaximum = fLocalMaximum;
+ }
+ }
+ if(::rtl::math::isInf(rfMinimum))
+ ::rtl::math::setNan(&rfMinimum);
+ if(::rtl::math::isInf(rfMaximum))
+ ::rtl::math::setNan(&rfMaximum);
+}
+
+void VSeriesPlotter::getMinimumAndMaximiumYInContinuousXRange( double& rfMinY, double& rfMaxY, double fMinX, double fMaxX, sal_Int32 nAxisIndex ) const
+{
+ ::rtl::math::setInf(&rfMinY, false);
+ ::rtl::math::setInf(&rfMaxY, true);
+
+ ::std::vector< ::std::vector< VDataSeriesGroup > >::const_iterator aZSlotIter = m_aZSlots.begin();
+ const ::std::vector< ::std::vector< VDataSeriesGroup > >::const_iterator aZSlotEnd = m_aZSlots.end();
+ for( ; aZSlotIter != aZSlotEnd; aZSlotIter++ )
+ {
+ ::std::vector< VDataSeriesGroup >::const_iterator aXSlotIter = aZSlotIter->begin();
+ const ::std::vector< VDataSeriesGroup >::const_iterator aXSlotEnd = aZSlotIter->end();
+ for( ; aXSlotIter != aXSlotEnd; aXSlotIter++ )
+ {
+ double fLocalMinimum, fLocalMaximum;
+ aXSlotIter->getMinimumAndMaximiumYInContinuousXRange( fLocalMinimum, fLocalMaximum, fMinX, fMaxX, nAxisIndex );
+ if( !::rtl::math::isNan(fLocalMinimum) && fLocalMinimum< rfMinY )
+ rfMinY = fLocalMinimum;
+ if( !::rtl::math::isNan(fLocalMaximum) && fLocalMaximum> rfMaxY )
+ rfMaxY = fLocalMaximum;
+ }
+ }
+ if(::rtl::math::isInf(rfMinY))
+ ::rtl::math::setNan(&rfMinY);
+ if(::rtl::math::isInf(rfMaxY))
+ ::rtl::math::setNan(&rfMaxY);
+}
+
+sal_Int32 VSeriesPlotter::getPointCount() const
+{
+ sal_Int32 nRet = 0;
+
+ ::std::vector< ::std::vector< VDataSeriesGroup > >::const_iterator aZSlotIter = m_aZSlots.begin();
+ const ::std::vector< ::std::vector< VDataSeriesGroup > >::const_iterator aZSlotEnd = m_aZSlots.end();
+
+ for( ; aZSlotIter != aZSlotEnd; aZSlotIter++ )
+ {
+ ::std::vector< VDataSeriesGroup >::const_iterator aXSlotIter = aZSlotIter->begin();
+ const ::std::vector< VDataSeriesGroup >::const_iterator aXSlotEnd = aZSlotIter->end();
+
+ for( ; aXSlotIter != aXSlotEnd; aXSlotIter++ )
+ {
+ sal_Int32 nPointCount = aXSlotIter->getPointCount();
+ if( nPointCount>nRet )
+ nRet = nPointCount;
+ }
+ }
+ return nRet;
+}
+
+void VSeriesPlotter::setNumberFormatsSupplier(
+ const uno::Reference< util::XNumberFormatsSupplier > & xNumFmtSupplier )
+{
+ m_apNumberFormatterWrapper.reset( new NumberFormatterWrapper( xNumFmtSupplier ));
+}
+
+void VSeriesPlotter::setColorScheme( const uno::Reference< XColorScheme >& xColorScheme )
+{
+ m_xColorScheme = xColorScheme;
+}
+
+void VSeriesPlotter::setExplicitCategoriesProvider( ExplicitCategoriesProvider* pExplicitCategoriesProvider )
+{
+ m_pExplicitCategoriesProvider = pExplicitCategoriesProvider;
+}
+
+sal_Int32 VDataSeriesGroup::getPointCount() const
+{
+ if(!m_bMaxPointCountDirty)
+ return m_nMaxPointCount;
+
+ sal_Int32 nRet = 0;
+ ::std::vector< VDataSeries* >::const_iterator aSeriesIter = m_aSeriesVector.begin();
+ const ::std::vector< VDataSeries* >::const_iterator aSeriesEnd = m_aSeriesVector.end();
+
+ for( ; aSeriesIter != aSeriesEnd; aSeriesIter++ )
+ {
+ sal_Int32 nPointCount = (*aSeriesIter)->getTotalPointCount();
+ if( nPointCount>nRet )
+ nRet = nPointCount;
+ }
+ m_nMaxPointCount=nRet;
+ m_aListOfCachedYValues.clear();
+ m_aListOfCachedYValues.resize(m_nMaxPointCount);
+ m_bMaxPointCountDirty=false;
+ return nRet;
+}
+
+sal_Int32 VDataSeriesGroup::getAttachedAxisIndexForFirstSeries() const
+{
+ sal_Int32 nRet = 0;
+ ::std::vector< VDataSeries* >::const_iterator aSeriesIter = m_aSeriesVector.begin();
+ const ::std::vector< VDataSeries* >::const_iterator aSeriesEnd = m_aSeriesVector.end();
+
+ if( aSeriesIter != aSeriesEnd )
+ nRet = (*aSeriesIter)->getAttachedAxisIndex();
+
+ return nRet;
+}
+
+void VDataSeriesGroup::getMinimumAndMaximiumX( double& rfMinimum, double& rfMaximum ) const
+{
+ const ::std::vector< VDataSeries* >* pSeriesList = &this->m_aSeriesVector;
+
+ ::std::vector< VDataSeries* >::const_iterator aSeriesIter = pSeriesList->begin();
+ const ::std::vector< VDataSeries* >::const_iterator aSeriesEnd = pSeriesList->end();
+
+ ::rtl::math::setInf(&rfMinimum, false);
+ ::rtl::math::setInf(&rfMaximum, true);
+
+ for( ; aSeriesIter != aSeriesEnd; aSeriesIter++ )
+ {
+ sal_Int32 nPointCount = (*aSeriesIter)->getTotalPointCount();
+ for(sal_Int32 nN=0;nN<nPointCount;nN++)
+ {
+ double fX = (*aSeriesIter)->getXValue( nN );
+ if( ::rtl::math::isNan(fX) )
+ continue;
+ if(rfMaximum<fX)
+ rfMaximum=fX;
+ if(rfMinimum>fX)
+ rfMinimum=fX;
+ }
+ }
+ if(::rtl::math::isInf(rfMinimum))
+ ::rtl::math::setNan(&rfMinimum);
+ if(::rtl::math::isInf(rfMaximum))
+ ::rtl::math::setNan(&rfMaximum);
+}
+void VDataSeriesGroup::getMinimumAndMaximiumYInContinuousXRange( double& rfMinY, double& rfMaxY, double fMinX, double fMaxX, sal_Int32 nAxisIndex ) const
+{
+ const ::std::vector< VDataSeries* >* pSeriesList = &this->m_aSeriesVector;
+
+ ::std::vector< VDataSeries* >::const_iterator aSeriesIter = pSeriesList->begin();
+ const ::std::vector< VDataSeries* >::const_iterator aSeriesEnd = pSeriesList->end();
+
+ ::rtl::math::setInf(&rfMinY, false);
+ ::rtl::math::setInf(&rfMaxY, true);
+
+ for( ; aSeriesIter != aSeriesEnd; aSeriesIter++ )
+ {
+ sal_Int32 nPointCount = (*aSeriesIter)->getTotalPointCount();
+ for(sal_Int32 nN=0;nN<nPointCount;nN++)
+ {
+ if( nAxisIndex != (*aSeriesIter)->getAttachedAxisIndex() )
+ continue;
+
+ double fX = (*aSeriesIter)->getXValue( nN );
+ if( ::rtl::math::isNan(fX) )
+ continue;
+ if( fX < fMinX || fX > fMaxX )
+ continue;
+ double fY = (*aSeriesIter)->getYValue( nN );
+ if( ::rtl::math::isNan(fY) )
+ continue;
+ if(rfMaxY<fY)
+ rfMaxY=fY;
+ if(rfMinY>fY)
+ rfMinY=fY;
+ }
+ }
+ if(::rtl::math::isInf(rfMinY))
+ ::rtl::math::setNan(&rfMinY);
+ if(::rtl::math::isInf(rfMaxY))
+ ::rtl::math::setNan(&rfMaxY);
+}
+
+void VDataSeriesGroup::calculateYMinAndMaxForCategory( sal_Int32 nCategoryIndex
+ , bool bSeperateStackingForDifferentSigns
+ , double& rfMinimumY, double& rfMaximumY, sal_Int32 nAxisIndex )
+{
+ ::rtl::math::setInf(&rfMinimumY, false);
+ ::rtl::math::setInf(&rfMaximumY, true);
+
+ sal_Int32 nPointCount = getPointCount();//necessary to create m_aListOfCachedYValues
+ if(nCategoryIndex<0 || nCategoryIndex>=nPointCount || m_aSeriesVector.empty())
+ return;
+
+ CachedYValues aCachedYValues = m_aListOfCachedYValues[nCategoryIndex][nAxisIndex];
+ if( !aCachedYValues.m_bValuesDirty )
+ {
+ //return cached values
+ rfMinimumY = aCachedYValues.m_fMinimumY;
+ rfMaximumY = aCachedYValues.m_fMaximumY;
+ return;
+ }
+
+ double fTotalSum, fPositiveSum, fNegativeSum, fFirstPositiveY, fFirstNegativeY;
+ ::rtl::math::setNan( &fTotalSum );
+ ::rtl::math::setNan( &fPositiveSum );
+ ::rtl::math::setNan( &fNegativeSum );
+ ::rtl::math::setNan( &fFirstPositiveY );
+ ::rtl::math::setNan( &fFirstNegativeY );
+
+ ::std::vector< VDataSeries* >::const_iterator aSeriesIter = m_aSeriesVector.begin();
+ ::std::vector< VDataSeries* >::const_iterator aSeriesEnd = m_aSeriesVector.end();
+
+ if( bSeperateStackingForDifferentSigns )
+ {
+ for( ; aSeriesIter != aSeriesEnd; ++aSeriesIter )
+ {
+ if( nAxisIndex != (*aSeriesIter)->getAttachedAxisIndex() )
+ continue;
+
+ double fValueMinY = (*aSeriesIter)->getMinimumofAllDifferentYValues( nCategoryIndex );
+ double fValueMaxY = (*aSeriesIter)->getMaximumofAllDifferentYValues( nCategoryIndex );
+
+ if( fValueMaxY >= 0 )
+ {
+ if( ::rtl::math::isNan( fPositiveSum ) )
+ fPositiveSum = fFirstPositiveY = fValueMaxY;
+ else
+ fPositiveSum += fValueMaxY;
+ }
+ if( fValueMinY < 0 )
+ {
+ if(::rtl::math::isNan( fNegativeSum ))
+ fNegativeSum = fFirstNegativeY = fValueMinY;
+ else
+ fNegativeSum += fValueMinY;
+ }
+ }
+ rfMinimumY = ::rtl::math::isNan( fNegativeSum ) ? fFirstPositiveY : fNegativeSum;
+ rfMaximumY = ::rtl::math::isNan( fPositiveSum ) ? fFirstNegativeY : fPositiveSum;
+ }
+ else
+ {
+ for( ; aSeriesIter != aSeriesEnd; ++aSeriesIter )
+ {
+ if( nAxisIndex != (*aSeriesIter)->getAttachedAxisIndex() )
+ continue;
+
+ double fValueMinY = (*aSeriesIter)->getMinimumofAllDifferentYValues( nCategoryIndex );
+ double fValueMaxY = (*aSeriesIter)->getMaximumofAllDifferentYValues( nCategoryIndex );
+
+ if( ::rtl::math::isNan( fTotalSum ) )
+ {
+ rfMinimumY = fValueMinY;
+ rfMaximumY = fTotalSum = fValueMaxY;
+ }
+ else
+ {
+ fTotalSum += fValueMaxY;
+ if( rfMinimumY > fTotalSum )
+ rfMinimumY = fTotalSum;
+ if( rfMaximumY < fTotalSum )
+ rfMaximumY = fTotalSum;
+ }
+ }
+ }
+
+ aCachedYValues.m_fMinimumY = rfMinimumY;
+ aCachedYValues.m_fMaximumY = rfMaximumY;
+ aCachedYValues.m_bValuesDirty = false;
+ m_aListOfCachedYValues[nCategoryIndex][nAxisIndex]=aCachedYValues;
+}
+
+void VDataSeriesGroup::calculateYMinAndMaxForCategoryRange(
+ sal_Int32 nStartCategoryIndex, sal_Int32 nEndCategoryIndex
+ , bool bSeperateStackingForDifferentSigns
+ , double& rfMinimumY, double& rfMaximumY, sal_Int32 nAxisIndex )
+{
+ //@todo maybe cache these values
+ ::rtl::math::setInf(&rfMinimumY, false);
+ ::rtl::math::setInf(&rfMaximumY, true);
+
+ //iterate through the given categories
+ if(nStartCategoryIndex<0)
+ nStartCategoryIndex=0;
+ if(nEndCategoryIndex<0)
+ nEndCategoryIndex=0;
+ for( sal_Int32 nCatIndex = nStartCategoryIndex; nCatIndex <= nEndCategoryIndex; nCatIndex++ )
+ {
+ double fMinimumY; ::rtl::math::setNan(&fMinimumY);
+ double fMaximumY; ::rtl::math::setNan(&fMaximumY);
+
+ this->calculateYMinAndMaxForCategory( nCatIndex
+ , bSeperateStackingForDifferentSigns, fMinimumY, fMaximumY, nAxisIndex );
+
+ if(rfMinimumY > fMinimumY)
+ rfMinimumY = fMinimumY;
+ if(rfMaximumY < fMaximumY)
+ rfMaximumY = fMaximumY;
+ }
+}
+
+double VSeriesPlotter::getTransformedDepth() const
+{
+ double MinZ = m_pMainPosHelper->getLogicMinZ();
+ double MaxZ = m_pMainPosHelper->getLogicMaxZ();
+ m_pMainPosHelper->doLogicScaling( 0, 0, &MinZ );
+ m_pMainPosHelper->doLogicScaling( 0, 0, &MaxZ );
+ return FIXED_SIZE_FOR_3D_CHART_VOLUME/(MaxZ-MinZ);
+}
+
+void SAL_CALL VSeriesPlotter::addSecondaryValueScale( const ExplicitScaleData& rScale, sal_Int32 nAxisIndex )
+ throw (uno::RuntimeException)
+{
+ if( nAxisIndex<1 )
+ return;
+
+ m_aSecondaryValueScales[nAxisIndex]=rScale;
+}
+
+PlottingPositionHelper& VSeriesPlotter::getPlottingPositionHelper( sal_Int32 nAxisIndex ) const
+{
+ PlottingPositionHelper* pRet = 0;
+ if(nAxisIndex>0)
+ {
+ tSecondaryPosHelperMap::const_iterator aPosIt = m_aSecondaryPosHelperMap.find( nAxisIndex );
+ if( aPosIt != m_aSecondaryPosHelperMap.end() )
+ {
+ pRet = aPosIt->second;
+ }
+ else
+ {
+ tSecondaryValueScales::const_iterator aScaleIt = m_aSecondaryValueScales.find( nAxisIndex );
+ if( aScaleIt != m_aSecondaryValueScales.end() )
+ {
+ pRet = m_pPosHelper->createSecondaryPosHelper( aScaleIt->second );
+ m_aSecondaryPosHelperMap[nAxisIndex] = pRet;
+ }
+ }
+ }
+ if( !pRet )
+ {
+ pRet = m_pMainPosHelper;
+ }
+ return *pRet;
+}
+
+void VSeriesPlotter::rearrangeLabelToAvoidOverlapIfRequested( const awt::Size& /*rPageSize*/ )
+{
+}
+
+VDataSeries* VSeriesPlotter::getFirstSeries() const
+{
+ ::std::vector< ::std::vector< VDataSeriesGroup > >::const_iterator aZSlotIter( m_aZSlots.begin() );
+ ::std::vector< ::std::vector< VDataSeriesGroup > >::const_iterator aZSlotEnd( m_aZSlots.end() );
+ for( ; aZSlotIter != aZSlotEnd; ++aZSlotIter )
+ {
+ ::std::vector< VDataSeriesGroup >::const_iterator aXSlotIter = aZSlotIter->begin();
+ const ::std::vector< VDataSeriesGroup >::const_iterator aXSlotEnd = aZSlotIter->end();
+
+ if( aXSlotIter != aXSlotEnd )
+ {
+ VDataSeriesGroup aSeriesGroup( *aXSlotIter );
+ if( aSeriesGroup.m_aSeriesVector.size() )
+ {
+ VDataSeries* pSeries = aSeriesGroup.m_aSeriesVector[0];
+ if(pSeries)
+ return pSeries;
+ }
+ }
+ }
+ return 0;
+}
+
+uno::Sequence< rtl::OUString > VSeriesPlotter::getSeriesNames() const
+{
+ ::std::vector< rtl::OUString > aRetVector;
+
+ rtl::OUString aRole;
+ if( m_xChartTypeModel.is() )
+ aRole = m_xChartTypeModel->getRoleOfSequenceForSeriesLabel();
+
+ ::std::vector< ::std::vector< VDataSeriesGroup > >::const_iterator aZSlotIter( m_aZSlots.begin() );
+ ::std::vector< ::std::vector< VDataSeriesGroup > >::const_iterator aZSlotEnd( m_aZSlots.end() );
+ for( ; aZSlotIter != aZSlotEnd; ++aZSlotIter )
+ {
+ ::std::vector< VDataSeriesGroup >::const_iterator aXSlotIter = aZSlotIter->begin();
+ const ::std::vector< VDataSeriesGroup >::const_iterator aXSlotEnd = aZSlotIter->end();
+
+ if( aXSlotIter != aXSlotEnd )
+ {
+ VDataSeriesGroup aSeriesGroup( *aXSlotIter );
+ if( aSeriesGroup.m_aSeriesVector.size() )
+ {
+ VDataSeries* pSeries = aSeriesGroup.m_aSeriesVector[0];
+ uno::Reference< XDataSeries > xSeries( pSeries ? pSeries->getModel() : 0 );
+ if( xSeries.is() )
+ {
+ rtl::OUString aSeriesName( DataSeriesHelper::getDataSeriesLabel( xSeries, aRole ) );
+ aRetVector.push_back( aSeriesName );
+ }
+ }
+ }
+ }
+ return ContainerHelper::ContainerToSequence( aRetVector );
+}
+
+namespace
+{
+struct lcl_setRefSizeAtSeriesGroup : public ::std::unary_function< VDataSeriesGroup, void >
+{
+ lcl_setRefSizeAtSeriesGroup( awt::Size aRefSize ) : m_aRefSize( aRefSize ) {}
+ void operator()( VDataSeriesGroup & rGroup )
+ {
+ ::std::vector< VDataSeries* >::iterator aIt( rGroup.m_aSeriesVector.begin());
+ const ::std::vector< VDataSeries* >::iterator aEndIt( rGroup.m_aSeriesVector.end());
+ for( ; aIt != aEndIt; ++aIt )
+ (*aIt)->setPageReferenceSize( m_aRefSize );
+ }
+
+private:
+ awt::Size m_aRefSize;
+};
+} // anonymous namespace
+
+void VSeriesPlotter::setPageReferenceSize( const ::com::sun::star::awt::Size & rPageRefSize )
+{
+ m_aPageReferenceSize = rPageRefSize;
+
+ // set reference size also at all data series
+
+ ::std::vector< VDataSeriesGroup > aSeriesGroups( FlattenVector( m_aZSlots ));
+ ::std::for_each( aSeriesGroups.begin(), aSeriesGroups.end(),
+ lcl_setRefSizeAtSeriesGroup( m_aPageReferenceSize ));
+}
+
+//better performance for big data
+void VSeriesPlotter::setCoordinateSystemResolution( const Sequence< sal_Int32 >& rCoordinateSystemResolution )
+{
+ m_aCoordinateSystemResolution = rCoordinateSystemResolution;
+}
+
+bool VSeriesPlotter::PointsWereSkipped() const
+{
+ return m_bPointsWereSkipped;
+}
+
+bool VSeriesPlotter::WantToPlotInFrontOfAxisLine()
+{
+ return ChartTypeHelper::isSeriesInFrontOfAxisLine( m_xChartTypeModel );
+}
+
+bool VSeriesPlotter::shouldSnapRectToUsedArea()
+{
+ if( m_nDimension == 3 )
+ return false;
+ return true;
+}
+
+Sequence< ViewLegendEntry > SAL_CALL VSeriesPlotter::createLegendEntries(
+ LegendExpansion eLegendExpansion
+ , const Reference< beans::XPropertySet >& xTextProperties
+ , const Reference< drawing::XShapes >& xTarget
+ , const Reference< lang::XMultiServiceFactory >& xShapeFactory
+ , const Reference< uno::XComponentContext >& xContext
+ ) throw (uno::RuntimeException)
+{
+ std::vector< ViewLegendEntry > aResult;
+
+ if( xTarget.is() )
+ {
+ //iterate through all series
+ bool bBreak = false;
+ bool bFirstSeries = true;
+ ::std::vector< ::std::vector< VDataSeriesGroup > >::iterator aZSlotIter = m_aZSlots.begin();
+ const ::std::vector< ::std::vector< VDataSeriesGroup > >::const_iterator aZSlotEnd = m_aZSlots.end();
+ for( ; aZSlotIter!=aZSlotEnd && !bBreak; aZSlotIter++ )
+ {
+ ::std::vector< VDataSeriesGroup >::iterator aXSlotIter = aZSlotIter->begin();
+ const ::std::vector< VDataSeriesGroup >::const_iterator aXSlotEnd = aZSlotIter->end();
+ for( ; aXSlotIter!=aXSlotEnd && !bBreak; aXSlotIter++ )
+ {
+ ::std::vector< VDataSeries* >* pSeriesList = &(aXSlotIter->m_aSeriesVector);
+ ::std::vector< VDataSeries* >::const_iterator aSeriesIter = pSeriesList->begin();
+ const ::std::vector< VDataSeries* >::const_iterator aSeriesEnd = pSeriesList->end();
+ //iterate through all series in this x slot
+ for( ; aSeriesIter!=aSeriesEnd && !bBreak; ++aSeriesIter )
+ {
+ VDataSeries* pSeries( *aSeriesIter );
+ if(!pSeries)
+ continue;
+
+ std::vector< ViewLegendEntry > aSeriesEntries( this->createLegendEntriesForSeries(
+ *pSeries, xTextProperties, xTarget, xShapeFactory, xContext ) );
+
+ //add series entries to the result now
+
+ // use only the first series if VaryColorsByPoint is set for the first series
+ if( bFirstSeries && pSeries->isVaryColorsByPoint() )
+ bBreak = true;
+ bFirstSeries = false;
+
+ // add entries reverse if chart is stacked in y-direction and the legend is not wide.
+ // If the legend is wide and we have a stacked bar-chart the normal order
+ // is the correct one
+ bool bReverse = false;
+ if( eLegendExpansion != LegendExpansion_WIDE )
+ {
+ StackingDirection eStackingDirection( pSeries->getStackingDirection() );
+ bReverse = ( eStackingDirection == StackingDirection_Y_STACKING );
+
+ //todo: respect direction of axis in future
+ }
+
+ if(bReverse)
+ aResult.insert( aResult.begin(), aSeriesEntries.begin(), aSeriesEntries.end() );
+ else
+ aResult.insert( aResult.end(), aSeriesEntries.begin(), aSeriesEntries.end() );
+ }
+ }
+ }
+
+ //add charttype specific entries if any
+ {
+ std::vector< ViewLegendEntry > aChartTypeEntries( this->createLegendEntriesForChartType(
+ xTextProperties, xTarget, xShapeFactory, xContext ) );
+ aResult.insert( aResult.end(), aChartTypeEntries.begin(), aChartTypeEntries.end() );
+ }
+ }
+
+ return ::chart::ContainerHelper::ContainerToSequence( aResult );
+}
+
+
+LegendSymbolStyle VSeriesPlotter::getLegendSymbolStyle()
+{
+ return chart2::LegendSymbolStyle_BOX;
+}
+
+
+uno::Any VSeriesPlotter::getExplicitSymbol( const VDataSeries& /*rSeries*/, sal_Int32 /*nPointIndex*/ )
+{
+ return uno::Any();
+}
+
+Reference< drawing::XShape > VSeriesPlotter::createLegendSymbolForSeries(
+ const VDataSeries& rSeries
+ , const Reference< drawing::XShapes >& xTarget
+ , const Reference< lang::XMultiServiceFactory >& xShapeFactory )
+{
+
+ LegendSymbolStyle eLegendSymbolStyle = this->getLegendSymbolStyle();
+ uno::Any aExplicitSymbol( this->getExplicitSymbol( rSeries ) );
+
+ VLegendSymbolFactory::tPropertyType ePropType =
+ VLegendSymbolFactory::PROP_TYPE_FILLED_SERIES;
+
+ // todo: maybe the property-style does not solely depend on the
+ // legend-symbol type
+ switch( eLegendSymbolStyle )
+ {
+ case LegendSymbolStyle_HORIZONTAL_LINE:
+ case LegendSymbolStyle_VERTICAL_LINE:
+ case LegendSymbolStyle_DIAGONAL_LINE:
+ case LegendSymbolStyle_LINE_WITH_BOX:
+ case LegendSymbolStyle_LINE_WITH_SYMBOL:
+ ePropType = VLegendSymbolFactory::PROP_TYPE_LINE_SERIES;
+ break;
+ default:
+ break;
+ };
+ Reference< drawing::XShape > xShape( VLegendSymbolFactory::createSymbol(
+ xTarget, eLegendSymbolStyle, xShapeFactory
+ , rSeries.getPropertiesOfSeries(), ePropType, aExplicitSymbol ));
+
+ return xShape;
+}
+
+Reference< drawing::XShape > VSeriesPlotter::createLegendSymbolForPoint(
+ const VDataSeries& rSeries
+ , sal_Int32 nPointIndex
+ , const Reference< drawing::XShapes >& xTarget
+ , const Reference< lang::XMultiServiceFactory >& xShapeFactory )
+{
+
+ LegendSymbolStyle eLegendSymbolStyle = this->getLegendSymbolStyle();
+ uno::Any aExplicitSymbol( this->getExplicitSymbol(rSeries,nPointIndex) );
+
+ VLegendSymbolFactory::tPropertyType ePropType =
+ VLegendSymbolFactory::PROP_TYPE_FILLED_SERIES;
+
+ // todo: maybe the property-style does not solely depend on the
+ // legend-symbol type
+ switch( eLegendSymbolStyle )
+ {
+ case LegendSymbolStyle_HORIZONTAL_LINE:
+ case LegendSymbolStyle_VERTICAL_LINE:
+ case LegendSymbolStyle_DIAGONAL_LINE:
+ case LegendSymbolStyle_LINE_WITH_BOX:
+ case LegendSymbolStyle_LINE_WITH_SYMBOL:
+ ePropType = VLegendSymbolFactory::PROP_TYPE_LINE_SERIES;
+ break;
+ default:
+ break;
+ };
+
+ // the default properties for the data point are the data series properties.
+ // If a data point has own attributes overwrite them
+ Reference< beans::XPropertySet > xSeriesProps( rSeries.getPropertiesOfSeries() );
+ Reference< beans::XPropertySet > xPointSet( xSeriesProps );
+ if( rSeries.isAttributedDataPoint( nPointIndex ) )
+ xPointSet.set( rSeries.getPropertiesOfPoint( nPointIndex ));
+
+ // if a data point has no own color use a color fom the diagram's color scheme
+ if( ! rSeries.hasPointOwnColor( nPointIndex ))
+ {
+ Reference< util::XCloneable > xCloneable( xPointSet,uno::UNO_QUERY );
+ if( xCloneable.is() && m_xColorScheme.is() )
+ {
+ xPointSet.set( xCloneable->createClone(), uno::UNO_QUERY );
+ Reference< container::XChild > xChild( xPointSet, uno::UNO_QUERY );
+ if( xChild.is())
+ xChild->setParent( xSeriesProps );
+
+ OSL_ASSERT( xPointSet.is());
+ xPointSet->setPropertyValue(
+ C2U("Color"), uno::makeAny( m_xColorScheme->getColorByIndex( nPointIndex )));
+ }
+ }
+
+ Reference< drawing::XShape > xShape( VLegendSymbolFactory::createSymbol(
+ xTarget, eLegendSymbolStyle, xShapeFactory, xPointSet, ePropType, aExplicitSymbol ));
+
+ return xShape;
+}
+
+std::vector< ViewLegendEntry > SAL_CALL VSeriesPlotter::createLegendEntriesForSeries(
+ const VDataSeries& rSeries
+ , const Reference< beans::XPropertySet >& xTextProperties
+ , const Reference< drawing::XShapes >& xTarget
+ , const Reference< lang::XMultiServiceFactory >& xShapeFactory
+ , const Reference< uno::XComponentContext >& xContext
+ )
+{
+ std::vector< ViewLegendEntry > aResult;
+
+ if( ! ( xShapeFactory.is() && xTarget.is() && xContext.is() ) )
+ return aResult;
+
+ try
+ {
+ ViewLegendEntry aEntry;
+ OUString aLabelText;
+ bool bVaryColorsByPoint = rSeries.isVaryColorsByPoint();
+ if( bVaryColorsByPoint )
+ {
+ Sequence< OUString > aCategoryNames;
+ if( m_pExplicitCategoriesProvider )
+ aCategoryNames = m_pExplicitCategoriesProvider->getSimpleCategories();
+
+ for( sal_Int32 nIdx=0; nIdx<aCategoryNames.getLength(); ++nIdx )
+ {
+ // symbol
+ uno::Reference< drawing::XShapes > xSymbolGroup( ShapeFactory(xShapeFactory).createGroup2D( xTarget ));
+
+ // create the symbol
+ Reference< drawing::XShape > xShape( this->createLegendSymbolForPoint(
+ rSeries, nIdx, xSymbolGroup, xShapeFactory ) );
+
+ // set CID to symbol for selection
+ if( xShape.is() )
+ {
+ aEntry.aSymbol = uno::Reference< drawing::XShape >( xSymbolGroup, uno::UNO_QUERY );
+
+ OUString aChildParticle( ObjectIdentifier::createChildParticleWithIndex( OBJECTTYPE_DATA_POINT, nIdx ) );
+ aChildParticle = ObjectIdentifier::addChildParticle( aChildParticle, ObjectIdentifier::createChildParticleWithIndex( OBJECTTYPE_LEGEND_ENTRY, 0 ) );
+ OUString aCID = ObjectIdentifier::createClassifiedIdentifierForParticles( rSeries.getSeriesParticle(), aChildParticle );
+ ShapeFactory::setShapeName( xShape, aCID );
+ }
+
+ // label
+ aLabelText = aCategoryNames[nIdx];
+ if( xShape.is() || aLabelText.getLength() )
+ {
+ aEntry.aLabel = FormattedStringHelper::createFormattedStringSequence( xContext, aLabelText, xTextProperties );
+ aResult.push_back(aEntry);
+ }
+ }
+ }
+ else
+ {
+ // symbol
+ uno::Reference< drawing::XShapes > xSymbolGroup( ShapeFactory(xShapeFactory).createGroup2D( xTarget ));
+
+ // create the symbol
+ Reference< drawing::XShape > xShape( this->createLegendSymbolForSeries(
+ rSeries, xSymbolGroup, xShapeFactory ) );
+
+ // set CID to symbol for selection
+ if( xShape.is())
+ {
+ aEntry.aSymbol = uno::Reference< drawing::XShape >( xSymbolGroup, uno::UNO_QUERY );
+
+ OUString aChildParticle( ObjectIdentifier::createChildParticleWithIndex( OBJECTTYPE_LEGEND_ENTRY, 0 ) );
+ OUString aCID = ObjectIdentifier::createClassifiedIdentifierForParticles( rSeries.getSeriesParticle(), aChildParticle );
+ ShapeFactory::setShapeName( xShape, aCID );
+ }
+
+ // label
+ aLabelText = ( DataSeriesHelper::getDataSeriesLabel( rSeries.getModel(), m_xChartTypeModel.is() ? m_xChartTypeModel->getRoleOfSequenceForSeriesLabel() : C2U("values-y")) );
+ aEntry.aLabel = FormattedStringHelper::createFormattedStringSequence( xContext, aLabelText, xTextProperties );
+
+ aResult.push_back(aEntry);
+ }
+
+ // regression curves
+ if ( 3 == m_nDimension ) // #i63016#
+ return aResult;
+
+ Reference< XRegressionCurveContainer > xRegrCont( rSeries.getModel(), uno::UNO_QUERY );
+ if( xRegrCont.is())
+ {
+ Sequence< Reference< XRegressionCurve > > aCurves( xRegrCont->getRegressionCurves());
+ sal_Int32 i = 0, nCount = aCurves.getLength();
+ for( i=0; i<nCount; ++i )
+ {
+ if( aCurves[i].is() && !RegressionCurveHelper::isMeanValueLine( aCurves[i] ) )
+ {
+ //label
+ OUString aResStr( SchResId::getResString( STR_STATISTICS_IN_LEGEND ));
+ replaceParamterInString( aResStr, C2U("%REGRESSIONCURVE"), RegressionCurveHelper::getUINameForRegressionCurve( aCurves[i] ));
+ replaceParamterInString( aResStr, C2U("%SERIESNAME"), aLabelText );
+ aEntry.aLabel = FormattedStringHelper::createFormattedStringSequence( xContext, aResStr, xTextProperties );
+
+ // symbol
+ uno::Reference< drawing::XShapes > xSymbolGroup( ShapeFactory(xShapeFactory).createGroup2D( xTarget ));
+
+ // create the symbol
+ Reference< drawing::XShape > xShape( VLegendSymbolFactory::createSymbol(
+ xSymbolGroup, chart2::LegendSymbolStyle_DIAGONAL_LINE, xShapeFactory,
+ Reference< beans::XPropertySet >( aCurves[i], uno::UNO_QUERY ),
+ VLegendSymbolFactory::PROP_TYPE_LINE, uno::Any() ));
+
+ // set CID to symbol for selection
+ if( xShape.is())
+ {
+ aEntry.aSymbol = uno::Reference< drawing::XShape >( xSymbolGroup, uno::UNO_QUERY );
+
+ bool bAverageLine = false;//@todo find out wether this is an average line or a regression curve
+ ObjectType eObjectType = bAverageLine ? OBJECTTYPE_DATA_AVERAGE_LINE : OBJECTTYPE_DATA_CURVE;
+ OUString aChildParticle( ObjectIdentifier::createChildParticleWithIndex( eObjectType, i ) );
+ aChildParticle = ObjectIdentifier::addChildParticle( aChildParticle, ObjectIdentifier::createChildParticleWithIndex( OBJECTTYPE_LEGEND_ENTRY, 0 ) );
+ OUString aCID = ObjectIdentifier::createClassifiedIdentifierForParticles( rSeries.getSeriesParticle(), aChildParticle );
+ ShapeFactory::setShapeName( xShape, aCID );
+ }
+
+ aResult.push_back(aEntry);
+ }
+ }
+ }
+ }
+ catch( uno::Exception & ex )
+ {
+ ASSERT_EXCEPTION( ex );
+ }
+ return aResult;
+}
+
+std::vector< ViewLegendEntry > SAL_CALL VSeriesPlotter::createLegendEntriesForChartType(
+ const Reference< beans::XPropertySet >& /* xTextProperties */,
+ const Reference< drawing::XShapes >& /* xTarget */,
+ const Reference< lang::XMultiServiceFactory >& /* xShapeFactory */,
+ const Reference< uno::XComponentContext >& /* xContext */
+ )
+{
+ return std::vector< ViewLegendEntry >();
+}
+
+//static
+VSeriesPlotter* VSeriesPlotter::createSeriesPlotter(
+ const uno::Reference<XChartType>& xChartTypeModel
+ , sal_Int32 nDimensionCount
+ , bool bExcludingPositioning )
+{
+ rtl::OUString aChartType = xChartTypeModel->getChartType();
+
+ //@todo: in future the plotter should be instanciated via service factory
+ VSeriesPlotter* pRet=NULL;
+ if( aChartType.equalsIgnoreAsciiCase( CHART2_SERVICE_NAME_CHARTTYPE_COLUMN ) )
+ pRet = new BarChart(xChartTypeModel,nDimensionCount);
+ else if( aChartType.equalsIgnoreAsciiCase( CHART2_SERVICE_NAME_CHARTTYPE_BAR ) )
+ pRet = new BarChart(xChartTypeModel,nDimensionCount);
+ else if( aChartType.equalsIgnoreAsciiCase( CHART2_SERVICE_NAME_CHARTTYPE_AREA ) )
+ pRet = new AreaChart(xChartTypeModel,nDimensionCount,true);
+ else if( aChartType.equalsIgnoreAsciiCase( CHART2_SERVICE_NAME_CHARTTYPE_LINE ) )
+ pRet = new AreaChart(xChartTypeModel,nDimensionCount,true,true);
+ else if( aChartType.equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_SCATTER) )
+ pRet = new AreaChart(xChartTypeModel,nDimensionCount,false,true);
+ else if( aChartType.equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_BUBBLE) )
+ pRet = new BubbleChart(xChartTypeModel,nDimensionCount);
+ else if( aChartType.equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_PIE) )
+ pRet = new PieChart(xChartTypeModel,nDimensionCount, bExcludingPositioning );
+ else if( aChartType.equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_NET) )
+ pRet = new AreaChart(xChartTypeModel,nDimensionCount,true,true,new PolarPlottingPositionHelper(),true,false,1,drawing::Direction3D(1,1,1) );
+ else if( aChartType.equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_FILLED_NET) )
+ pRet = new AreaChart(xChartTypeModel,nDimensionCount,true,false,new PolarPlottingPositionHelper(),true,false,1,drawing::Direction3D(1,1,1) );
+ else if( aChartType.equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK) )
+ pRet = new CandleStickChart(xChartTypeModel,nDimensionCount);
+ else
+ pRet = new AreaChart(xChartTypeModel,nDimensionCount,false,true);
+ return pRet;
+}
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
diff --git a/chart2/source/view/charttypes/makefile.mk b/chart2/source/view/charttypes/makefile.mk
new file mode 100644
index 000000000000..b6cb14edbf14
--- /dev/null
+++ b/chart2/source/view/charttypes/makefile.mk
@@ -0,0 +1,55 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ= ..$/..$/..
+PRJINC= $(PRJ)$/source
+PRJNAME= chart2
+TARGET= chvtypes
+
+ENABLE_EXCEPTIONS= TRUE
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE: settings.mk
+.INCLUDE: $(PRJ)$/chartview.pmk
+
+# --- export library -------------------------------------------------
+
+#object files to build and link together to lib $(SLB)$/$(TARGET).lib
+SLOFILES = $(SLO)$/Splines.obj \
+ $(SLO)$/CategoryPositionHelper.obj \
+ $(SLO)$/BarPositionHelper.obj \
+ $(SLO)$/VSeriesPlotter.obj \
+ $(SLO)$/BarChart.obj \
+ $(SLO)$/PieChart.obj \
+ $(SLO)$/AreaChart.obj \
+ $(SLO)$/CandleStickChart.obj \
+ $(SLO)$/BubbleChart.obj
+
+# --- Targets -----------------------------------------------------------------
+
+.INCLUDE: target.mk
diff --git a/chart2/source/view/diagram/VDiagram.cxx b/chart2/source/view/diagram/VDiagram.cxx
new file mode 100644
index 000000000000..4174226b6f62
--- /dev/null
+++ b/chart2/source/view/diagram/VDiagram.cxx
@@ -0,0 +1,811 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_chart2.hxx"
+#include "VDiagram.hxx"
+#include "PropertyMapper.hxx"
+#include "ViewDefines.hxx"
+#include "Stripe.hxx"
+#include "macros.hxx"
+#include "ObjectIdentifier.hxx"
+#include "DiagramHelper.hxx"
+#include "BaseGFXHelper.hxx"
+#include "CommonConverters.hxx"
+#include "ChartTypeHelper.hxx"
+#include "ThreeDHelper.hxx"
+#include <editeng/unoprnms.hxx>
+#include <tools/color.hxx>
+#include <tools/debug.hxx>
+#include <com/sun/star/drawing/FillStyle.hpp>
+#include <com/sun/star/drawing/LineStyle.hpp>
+#include <com/sun/star/drawing/ProjectionMode.hpp>
+#include <com/sun/star/drawing/ShadeMode.hpp>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
+#include <com/sun/star/lang/XTypeProvider.hpp>
+// header for class SvxShape
+#include <svx/unoshape.hxx>
+// header for GetSdrObjectFromXShape
+#include <svx/unoapi.hxx>
+// header for class E3dScene
+#include <svx/scene3d.hxx>
+#include <rtl/math.hxx>
+#include <svx/e3dsceneupdater.hxx>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+VDiagram::VDiagram(
+ const uno::Reference< XDiagram > & xDiagram
+ , const drawing::Direction3D& rPreferredAspectRatio
+ , sal_Int32 nDimension, sal_Bool bPolar )
+ : m_xLogicTarget(NULL)
+ , m_xFinalTarget(NULL)
+ , m_xShapeFactory(NULL)
+ , m_pShapeFactory(NULL)
+ , m_xOuterGroupShape(NULL)
+ , m_xCoordinateRegionShape(NULL)
+ , m_xWall2D(NULL)
+ , m_nDimensionCount(nDimension)
+ , m_bPolar(bPolar)
+ , m_xDiagram(xDiagram)
+ , m_aPreferredAspectRatio(rPreferredAspectRatio)
+ , m_xAspectRatio3D()
+ , m_fXAnglePi(0)
+ , m_fYAnglePi(0)
+ , m_fZAnglePi(0)
+ , m_bRightAngledAxes(sal_False)
+{
+ if( m_nDimensionCount == 3)
+ {
+ uno::Reference< beans::XPropertySet > xSourceProp( m_xDiagram, uno::UNO_QUERY );
+ ThreeDHelper::getRotationAngleFromDiagram( xSourceProp, m_fXAnglePi, m_fYAnglePi, m_fZAnglePi );
+ if( ChartTypeHelper::isSupportingRightAngledAxes(
+ DiagramHelper::getChartTypeByIndex( m_xDiagram, 0 ) ) )
+ {
+ if(xSourceProp.is())
+ xSourceProp->getPropertyValue(C2U( "RightAngledAxes" )) >>= m_bRightAngledAxes;
+ if( m_bRightAngledAxes )
+ {
+ ThreeDHelper::adaptRadAnglesForRightAngledAxes( m_fXAnglePi, m_fYAnglePi );
+ m_fZAnglePi=0.0;
+ }
+ }
+ }
+}
+
+VDiagram::~VDiagram()
+{
+ delete m_pShapeFactory;
+}
+
+void SAL_CALL VDiagram::init(
+ const uno::Reference< drawing::XShapes >& xLogicTarget
+ , const uno::Reference< drawing::XShapes >& xFinalTarget
+ , const uno::Reference< lang::XMultiServiceFactory >& xFactory )
+{
+ DBG_ASSERT(xLogicTarget.is()&&xFinalTarget.is()&&xFactory.is(),"no proper initialization parameters");
+
+ m_xLogicTarget = xLogicTarget;
+ m_xFinalTarget = xFinalTarget;
+ m_xShapeFactory = xFactory;
+ m_pShapeFactory = new ShapeFactory(xFactory);
+}
+
+void VDiagram::createShapes( const awt::Point& rPos, const awt::Size& rSize )
+{
+ m_aAvailablePosIncludingAxes = rPos;
+ m_aAvailableSizeIncludingAxes = rSize;
+
+ if( m_nDimensionCount == 3 )
+ createShapes_3d();
+ else
+ createShapes_2d();
+}
+
+::basegfx::B2IRectangle VDiagram::adjustPosAndSize( const awt::Point& rPos, const awt::Size& rSize )
+{
+ ::basegfx::B2IRectangle aAllowedRect( BaseGFXHelper::makeRectangle(m_aAvailablePosIncludingAxes,m_aAvailableSizeIncludingAxes) );
+ ::basegfx::B2IRectangle aNewInnerRect( BaseGFXHelper::makeRectangle(rPos,rSize) );
+ aNewInnerRect.intersect( aAllowedRect );
+
+ if( m_nDimensionCount == 3 )
+ aNewInnerRect = adjustPosAndSize_3d( BaseGFXHelper::B2IRectangleToAWTPoint(aNewInnerRect), BaseGFXHelper::B2IRectangleToAWTSize(aNewInnerRect) );
+ else
+ aNewInnerRect = adjustPosAndSize_2d( BaseGFXHelper::B2IRectangleToAWTPoint(aNewInnerRect), BaseGFXHelper::B2IRectangleToAWTSize(aNewInnerRect) );
+
+ return aNewInnerRect;
+}
+
+::basegfx::B2IRectangle VDiagram::adjustPosAndSize_2d( const awt::Point& rPos, const awt::Size& rAvailableSize )
+{
+ m_aCurrentPosWithoutAxes = rPos;
+ m_aCurrentSizeWithoutAxes = rAvailableSize;
+ if( m_aPreferredAspectRatio.DirectionX > 0 && m_aPreferredAspectRatio.DirectionY > 0)
+ {
+ //do not change aspect ratio
+ awt::Size aAspectRatio( static_cast<sal_Int32>(m_aPreferredAspectRatio.DirectionX*FIXED_SIZE_FOR_3D_CHART_VOLUME),
+ static_cast<sal_Int32>(m_aPreferredAspectRatio.DirectionY*FIXED_SIZE_FOR_3D_CHART_VOLUME ));
+ m_aCurrentSizeWithoutAxes = awt::Size( ShapeFactory::calculateNewSizeRespectingAspectRatio(
+ rAvailableSize, aAspectRatio ) );
+ //center diagram position
+ m_aCurrentPosWithoutAxes = awt::Point( ShapeFactory::calculateTopLeftPositionToCenterObject(
+ rPos, rAvailableSize, m_aCurrentSizeWithoutAxes ) );
+
+ }
+
+ if( m_xWall2D.is() )
+ {
+ m_xWall2D->setSize( m_aCurrentSizeWithoutAxes);
+ m_xWall2D->setPosition(m_aCurrentPosWithoutAxes);
+ }
+
+ return ::basegfx::B2IRectangle( BaseGFXHelper::makeRectangle(m_aCurrentPosWithoutAxes,m_aCurrentSizeWithoutAxes) );
+}
+
+void VDiagram::createShapes_2d()
+{
+ DBG_ASSERT(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is()&&m_xShapeFactory.is(),"is not proper initialized");
+ if(!(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is()&&m_xShapeFactory.is()))
+ return;
+
+ //create group shape
+ uno::Reference< drawing::XShapes > xOuterGroup_Shapes = m_pShapeFactory->createGroup2D(m_xLogicTarget);
+ m_xOuterGroupShape = uno::Reference<drawing::XShape>( xOuterGroup_Shapes, uno::UNO_QUERY );
+
+ uno::Reference< drawing::XShapes > xGroupForWall( m_pShapeFactory->createGroup2D(xOuterGroup_Shapes,C2U("PlotAreaExcludingAxes")) );
+
+ //create independent group shape as container for datapoints and such things
+ {
+ uno::Reference< drawing::XShapes > xShapes = m_pShapeFactory->createGroup2D(xOuterGroup_Shapes,C2U("testonly;CooContainer=XXX_CID"));
+ m_xCoordinateRegionShape = uno::Reference<drawing::XShape>( xShapes, uno::UNO_QUERY );
+ }
+
+ //---------------------------
+ bool bAddFloorAndWall = DiagramHelper::isSupportingFloorAndWall( m_xDiagram );
+
+ //add back wall
+ {
+ m_xWall2D = uno::Reference< drawing::XShape >(
+ m_xShapeFactory->createInstance( C2U(
+ "com.sun.star.drawing.RectangleShape" ) ), uno::UNO_QUERY );
+ //m_xWall2D->setPosition(m_aAvailablePosIncludingAxes);
+ //m_xWall2D->setSize(m_aAvailableSizeIncludingAxes);
+ xGroupForWall->add(m_xWall2D);
+ uno::Reference< beans::XPropertySet > xProp( m_xWall2D, uno::UNO_QUERY );
+ if( xProp.is())
+ {
+ try
+ {
+ DBG_ASSERT( m_xDiagram.is(), "Invalid Diagram model" );
+ if( m_xDiagram.is() )
+ {
+ uno::Reference< beans::XPropertySet > xWallProp( m_xDiagram->getWall());
+ if( xWallProp.is())
+ PropertyMapper::setMappedProperties( xProp, xWallProp, PropertyMapper::getPropertyNameMapForFillAndLineProperties() );
+ }
+ if( !bAddFloorAndWall )
+ {
+ //we always need this object as dummy object for correct scene dimensions
+ //but it should not be visible in this case:
+ ShapeFactory::makeShapeInvisible( m_xWall2D );
+ }
+ else
+ {
+ //CID for selection handling
+ rtl::OUString aWallCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_WALL, rtl::OUString() ) );//@todo read CID from model
+ xProp->setPropertyValue( C2U( UNO_NAME_MISC_OBJ_NAME ), uno::makeAny( aWallCID ) );
+ }
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+ }
+
+ }
+
+ //---------------------------
+ //position and size for diagram
+ adjustPosAndSize_2d( m_aAvailablePosIncludingAxes, m_aAvailableSizeIncludingAxes );
+}
+
+E3dScene* lcl_getE3dScene( const uno::Reference< drawing::XShape >& xShape )
+{
+ E3dScene* pRet=NULL;
+ uno::Reference< lang::XUnoTunnel > xUnoTunnel( xShape, uno::UNO_QUERY );
+ uno::Reference< lang::XTypeProvider > xTypeProvider( xShape, uno::UNO_QUERY );
+ if(xUnoTunnel.is()&&xTypeProvider.is())
+ {
+ SvxShape* pSvxShape = reinterpret_cast<SvxShape*>(xUnoTunnel->getSomething( SvxShape::getUnoTunnelId() ));
+ if(pSvxShape)
+ {
+ SdrObject* pObj = pSvxShape->GetSdrObject();
+ if( pObj && pObj->ISA(E3dScene) )
+ pRet = (E3dScene*)pObj;
+ }
+ }
+ return pRet;
+}
+
+void lcl_setLightSources(
+ const uno::Reference< beans::XPropertySet > & xSource,
+ const uno::Reference< beans::XPropertySet > & xDest )
+{
+ xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_1 ),
+ xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_1 )));
+ xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_2 ),
+ xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_2 )));
+ xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_3 ),
+ xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_3 )));
+ xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_4 ),
+ xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_4 )));
+ xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_5 ),
+ xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_5 )));
+ xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_6 ),
+ xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_6 )));
+ xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_7 ),
+ xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_7 )));
+ xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_8 ),
+ xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_8 )));
+
+ xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_1 ),
+ xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_1 )));
+ xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_2 ),
+ xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_2 )));
+ xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_3 ),
+ xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_3 )));
+ xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_4 ),
+ xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_4 )));
+ xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_5 ),
+ xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_5 )));
+ xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_6 ),
+ xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_6 )));
+ xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_7 ),
+ xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_7 )));
+ xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_8 ),
+ xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_8 )));
+
+ xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_1 ),
+ xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_1 )));
+ xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_2 ),
+ xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_2 )));
+ xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_3 ),
+ xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_3 )));
+ xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_4 ),
+ xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_4 )));
+ xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_5 ),
+ xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_5 )));
+ xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_6 ),
+ xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_6 )));
+ xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_7 ),
+ xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_7 )));
+ xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_8 ),
+ xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_8 )));
+}
+
+namespace
+{
+
+void lcl_ensureScaleValue( double& rfScale )
+{
+ DBG_ASSERT(rfScale>0, "calculation error for automatic 3D height in chart");
+ if( rfScale<0 )
+ rfScale = 1.0;
+ else if( rfScale<0.2 )
+ rfScale = 0.2;
+ else if( rfScale>5.0 )
+ rfScale = 5.0;
+}
+
+}
+
+void VDiagram::adjustAspectRatio3d( const awt::Size& rAvailableSize )
+{
+ DBG_ASSERT(m_xAspectRatio3D.is(), "created shape offers no XPropertySet");
+ if( m_xAspectRatio3D.is())
+ {
+ try
+ {
+ double fScaleX = m_aPreferredAspectRatio.DirectionX;
+ double fScaleY = m_aPreferredAspectRatio.DirectionY;
+ double fScaleZ = m_aPreferredAspectRatio.DirectionZ;
+
+ //normalize scale factors
+ {
+ double fMax = std::max( std::max( fScaleX, fScaleY) , fScaleZ );
+ fScaleX/=fMax;
+ fScaleY/=fMax;
+ fScaleZ/=fMax;
+ }
+
+ if( fScaleX<0 || fScaleY<0 || fScaleZ<0 )
+ {
+ //calculate automatic 3D aspect ratio that fits good into the given 2D area
+ double fW = rAvailableSize.Width;
+ double fH = rAvailableSize.Height;
+
+// double cx = fabs(cos(m_fXAnglePi));
+ double sx = fabs(sin(m_fXAnglePi));
+// double cy = fabs(cos(m_fYAnglePi));
+ double sy = fabs(sin(m_fYAnglePi));
+ double cz = fabs(cos(m_fZAnglePi));
+ double sz = fabs(sin(m_fZAnglePi));
+
+ if(m_bRightAngledAxes)
+ {
+ //base equations:
+ //fH*zoomfactor == sx*fScaleZ + fScaleY;
+ //fW*zoomfactor == sy*fScaleZ + fScaleX;
+
+ if( fScaleX>0 && fScaleZ>0 )
+ {
+ //calculate fScaleY:
+ if( !::basegfx::fTools::equalZero(fW) )
+ {
+ fScaleY = (fH/fW)*(sy*fScaleZ+fScaleX)-(sx*fScaleZ);
+ lcl_ensureScaleValue( fScaleY );
+ }
+ else
+ fScaleY = 1.0;//looking from top or bottom the height is irrelevant
+ }
+ else if( fScaleY>0 && fScaleZ>0 )
+ {
+ //calculate fScaleX:
+ if( !::basegfx::fTools::equalZero(fH) )
+ {
+ fScaleX = (fW/fH)*(sx*fScaleZ+fScaleY)-(sy*fScaleZ);
+ lcl_ensureScaleValue(fScaleX);
+ }
+ else
+ fScaleX = 1.0;//looking from top or bottom hieght is irrelevant
+ }
+ else
+ {
+ //todo
+ DBG_ASSERT(false, "not implemented yet");
+
+ if( fScaleX<0 )
+ fScaleX = 1.0;
+ if( fScaleY<0 )
+ fScaleY = 1.0;
+ if( fScaleZ<0 )
+ fScaleZ = 1.0;
+ }
+ }
+ else
+ {
+ //base equations:
+ //fH*zoomfactor == cz*fScaleY + sz*fScaleX;
+ //fW*zoomfactor == cz*fScaleX + sz*fScaleY;
+ //==> fScaleY*(fH*sz-fW*cz) == fScaleX*(fW*sz-fH*cz);
+ if( fScaleX>0 && fScaleZ>0 )
+ {
+ //calculate fScaleY:
+ double fDivide = fH*sz-fW*cz;
+ if( !::basegfx::fTools::equalZero(fDivide) )
+ {
+ fScaleY = fScaleX*(fW*sz-fH*cz) / fDivide;
+ lcl_ensureScaleValue(fScaleY);
+ }
+ else
+ fScaleY = 1.0;//looking from top or bottom the height is irrelevant
+
+ /*
+ //fW*zoomfactor == fScaleX*cy*cz + fScaleY*sz*cy + fScaleZ*sy*cx;
+ //fH*zoomfactor == fScaleY*cx*cz + fScaleX*sz*cy + fScaleZ*sx*cz;
+ //==> fScaleY*(sz*cy*fH -cx*cz*fW) = fScaleX*(sz*cy*fW - cy*cz*fH) + fScaleZ*(sx*cz*fW - sy*cx*fH);
+ double fDivide = sz*cy*fH -cx*cz*fW;
+ if( !::basegfx::fTools::equalZero(fDivide) )
+ {
+ fScaleY = ( fScaleX*(sz*cy*fW - cy*cz*fH)
+ + fScaleZ*(sx*cz*fW - sy*cx*fH) ) / fDivide;
+ lcl_ensureScaleValue(fScaleY);
+ }
+ else
+ fScaleY = 1.0;//looking from top or bottom hieght is irrelevant
+ */
+ }
+ else if( fScaleY>0 && fScaleZ>0 )
+ {
+ //calculate fScaleX:
+ double fDivide = fW*sz-fH*cz;
+ if( !::basegfx::fTools::equalZero(fDivide) )
+ {
+ fScaleX = fScaleY*(fH*sz-fW*cz) / fDivide;
+ lcl_ensureScaleValue(fScaleX);
+ }
+ else
+ fScaleX = 1.0;//looking from top or bottom hieght is irrelevant
+ }
+ else
+ {
+ //todo
+ DBG_ASSERT(false, "not implemented yet");
+
+ if( fScaleX<0 )
+ fScaleX = 1.0;
+ if( fScaleY<0 )
+ fScaleY = 1.0;
+ if( fScaleZ<0 )
+ fScaleZ = 1.0;
+ }
+ }
+ }
+
+ //normalize scale factors
+ {
+ double fMax = std::max( std::max( fScaleX, fScaleY) , fScaleZ );
+ fScaleX/=fMax;
+ fScaleY/=fMax;
+ fScaleZ/=fMax;
+ }
+
+ // identity matrix
+ ::basegfx::B3DHomMatrix aResult;
+ aResult.translate( -FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0,
+ -FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0,
+ -FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0 );
+ aResult.scale( fScaleX, fScaleY, fScaleZ );
+ aResult.translate( FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0,
+ FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0,
+ FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0 );
+
+ // To get the 3D aspect ratio's effect on the 2D scene size, the scene's 2D size needs to be adapted to
+ // 3D content changes here. The tooling class remembers the current 3D transformation stack
+ // and in it's destructor, calculates a new 2D SnapRect for the scene and it's modified 3D geometry.
+ E3DModifySceneSnapRectUpdater aUpdater(lcl_getE3dScene( m_xOuterGroupShape ));
+
+ m_xAspectRatio3D->setPropertyValue( C2U( UNO_NAME_3D_TRANSFORM_MATRIX )
+ , uno::makeAny(BaseGFXHelper::B3DHomMatrixToHomogenMatrix( aResult )) );
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+ }
+}
+
+::basegfx::B2IRectangle VDiagram::adjustPosAndSize_3d( const awt::Point& rPos, const awt::Size& rAvailableSize )
+{
+ adjustAspectRatio3d( rAvailableSize );
+
+ //do not change aspect ratio of 3D scene with 2D bound rect
+ m_aCurrentSizeWithoutAxes = ShapeFactory::calculateNewSizeRespectingAspectRatio(
+ rAvailableSize, m_xOuterGroupShape->getSize() );
+ m_xOuterGroupShape->setSize( m_aCurrentSizeWithoutAxes );
+
+ //center diagram position
+ m_aCurrentPosWithoutAxes= ShapeFactory::calculateTopLeftPositionToCenterObject(
+ rPos, rAvailableSize, m_aCurrentSizeWithoutAxes );
+ m_xOuterGroupShape->setPosition(m_aCurrentPosWithoutAxes);
+
+ return ::basegfx::B2IRectangle( BaseGFXHelper::makeRectangle(m_aCurrentPosWithoutAxes,m_aCurrentSizeWithoutAxes) );
+}
+
+void VDiagram::createShapes_3d()
+{
+ DBG_ASSERT(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is()&&m_xShapeFactory.is(),"is not proper initialized");
+ if(!(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is()&&m_xShapeFactory.is()))
+ return;
+
+ //create shape
+ m_xOuterGroupShape = uno::Reference< drawing::XShape >(
+ m_xShapeFactory->createInstance( C2U(
+ "com.sun.star.drawing.Shape3DSceneObject" ) ), uno::UNO_QUERY );
+ ShapeFactory::setShapeName( m_xOuterGroupShape, C2U("PlotAreaExcludingAxes") );
+ m_xLogicTarget->add(m_xOuterGroupShape);
+
+ uno::Reference< drawing::XShapes > xOuterGroup_Shapes =
+ uno::Reference<drawing::XShapes>( m_xOuterGroupShape, uno::UNO_QUERY );
+
+
+ //-------------------------------------------------------------------------
+ //create additional group to manipulate the aspect ratio of the whole diagram:
+ xOuterGroup_Shapes = m_pShapeFactory->createGroup3D( xOuterGroup_Shapes, rtl::OUString() );
+
+ m_xAspectRatio3D = uno::Reference< beans::XPropertySet >( xOuterGroup_Shapes, uno::UNO_QUERY );
+
+ //---------------------------
+
+ bool bAddFloorAndWall = DiagramHelper::isSupportingFloorAndWall( m_xDiagram );
+
+ const bool bDoubleSided = false;
+ const bool bFlatNormals = true;
+
+ //add walls
+ {
+ uno::Reference< beans::XPropertySet > xWallProp( NULL );
+ if( m_xDiagram.is() )
+ xWallProp=uno::Reference< beans::XPropertySet >( m_xDiagram->getWall());
+
+ rtl::OUString aWallCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_WALL, rtl::OUString() ) );//@todo read CID from model
+ if( !bAddFloorAndWall )
+ aWallCID = rtl::OUString();
+ uno::Reference< drawing::XShapes > xWallGroup_Shapes( m_pShapeFactory->createGroup3D( xOuterGroup_Shapes, aWallCID ) );
+
+ CuboidPlanePosition eLeftWallPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardLeftWall( uno::Reference< beans::XPropertySet >( m_xDiagram, uno::UNO_QUERY ) ) );
+ CuboidPlanePosition eBackWallPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBackWall( uno::Reference< beans::XPropertySet >( m_xDiagram, uno::UNO_QUERY ) ) );
+
+ //add left wall
+ {
+ short nRotatedTexture = ( CuboidPlanePosition_Front==eBackWallPos ) ? 3 : 1;
+ double xPos = 0.0;
+ if( CuboidPlanePosition_Right==eLeftWallPos )
+ xPos = FIXED_SIZE_FOR_3D_CHART_VOLUME;
+ Stripe aStripe( drawing::Position3D(xPos,FIXED_SIZE_FOR_3D_CHART_VOLUME,0)
+ , drawing::Direction3D(0,0,FIXED_SIZE_FOR_3D_CHART_VOLUME)
+ , drawing::Direction3D(0,-FIXED_SIZE_FOR_3D_CHART_VOLUME,0) );
+ if( CuboidPlanePosition_Right==eLeftWallPos )
+ {
+ nRotatedTexture = ( CuboidPlanePosition_Front==eBackWallPos ) ? 2 : 0;
+ aStripe = Stripe( drawing::Position3D(xPos,FIXED_SIZE_FOR_3D_CHART_VOLUME,0)
+ , drawing::Direction3D(0,-FIXED_SIZE_FOR_3D_CHART_VOLUME,0)
+ , drawing::Direction3D(0,0,FIXED_SIZE_FOR_3D_CHART_VOLUME) );
+ }
+ aStripe.InvertNormal(true);
+
+ uno::Reference< drawing::XShape > xShape =
+ m_pShapeFactory->createStripe( xWallGroup_Shapes, aStripe
+ , xWallProp, PropertyMapper::getPropertyNameMapForFillAndLineProperties(), bDoubleSided, nRotatedTexture, bFlatNormals );
+ if( !bAddFloorAndWall )
+ {
+ //we always need this object as dummy object for correct scene dimensions
+ //but it should not be visible in this case:
+ ShapeFactory::makeShapeInvisible( xShape );
+ }
+ }
+ //add back wall
+ {
+ short nRotatedTexture = 0;
+ double zPos = 0.0;
+ if( CuboidPlanePosition_Front==eBackWallPos )
+ zPos = FIXED_SIZE_FOR_3D_CHART_VOLUME;
+ Stripe aStripe( drawing::Position3D(0,FIXED_SIZE_FOR_3D_CHART_VOLUME,zPos)
+ , drawing::Direction3D(0,-FIXED_SIZE_FOR_3D_CHART_VOLUME,0)
+ , drawing::Direction3D(FIXED_SIZE_FOR_3D_CHART_VOLUME,0,0) );
+ if( CuboidPlanePosition_Front==eBackWallPos )
+ {
+ aStripe = Stripe( drawing::Position3D(0,FIXED_SIZE_FOR_3D_CHART_VOLUME,zPos)
+ , drawing::Direction3D(FIXED_SIZE_FOR_3D_CHART_VOLUME,0,0)
+ , drawing::Direction3D(0,-FIXED_SIZE_FOR_3D_CHART_VOLUME,0) );
+ nRotatedTexture = 3;
+ }
+ aStripe.InvertNormal(true);
+
+ uno::Reference< drawing::XShape > xShape =
+ m_pShapeFactory->createStripe(xWallGroup_Shapes, aStripe
+ , xWallProp, PropertyMapper::getPropertyNameMapForFillAndLineProperties(), bDoubleSided, nRotatedTexture, bFlatNormals );
+ if( !bAddFloorAndWall )
+ {
+ //we always need this object as dummy object for correct scene dimensions
+ //but it should not be visible in this case:
+ ShapeFactory::makeShapeInvisible( xShape );
+ }
+ }
+ }
+
+ try
+ {
+ uno::Reference< beans::XPropertySet > xSourceProp( m_xDiagram, uno::UNO_QUERY_THROW );
+ uno::Reference< beans::XPropertySet > xDestProp( m_xOuterGroupShape, uno::UNO_QUERY_THROW );
+
+ //perspective
+ {
+ //ignore distance and focal length from file format and model comcpletely
+ //use vrp only to indicate the distance of the camera and thus influence the perspecitve
+ xDestProp->setPropertyValue( C2U( UNO_NAME_3D_SCENE_DISTANCE ), uno::makeAny(
+ static_cast<sal_Int32>(ThreeDHelper::getCameraDistance( xSourceProp ))));
+ xDestProp->setPropertyValue( C2U( UNO_NAME_3D_SCENE_PERSPECTIVE ),
+ xSourceProp->getPropertyValue( C2U( UNO_NAME_3D_SCENE_PERSPECTIVE )));
+ }
+
+ //light
+ {
+ xDestProp->setPropertyValue( C2U( UNO_NAME_3D_SCENE_SHADE_MODE ),
+ xSourceProp->getPropertyValue( C2U( UNO_NAME_3D_SCENE_SHADE_MODE )));
+ xDestProp->setPropertyValue( C2U( UNO_NAME_3D_SCENE_AMBIENTCOLOR ),
+ xSourceProp->getPropertyValue( C2U( UNO_NAME_3D_SCENE_AMBIENTCOLOR )));
+ xDestProp->setPropertyValue( C2U( UNO_NAME_3D_SCENE_TWO_SIDED_LIGHTING ),
+ xSourceProp->getPropertyValue( C2U( UNO_NAME_3D_SCENE_TWO_SIDED_LIGHTING )));
+ lcl_setLightSources( xSourceProp, xDestProp );
+ }
+
+ //rotation
+ {
+ //set diagrams rotation is set exclusively vie the transformation matrix
+ //don't set a camera at all!
+ //the cameras rotation is incorporated into this matrix
+
+ ::basegfx::B3DHomMatrix aEffectiveTranformation;
+ aEffectiveTranformation.translate(-FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0, -FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0, -FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0);
+
+ if(!m_bRightAngledAxes)
+ aEffectiveTranformation.rotate(m_fXAnglePi,m_fYAnglePi,m_fZAnglePi);
+ else
+ aEffectiveTranformation.shearXY(m_fYAnglePi,-m_fXAnglePi);
+
+ //#i98497# 3D charts are rendered with wrong size
+ E3DModifySceneSnapRectUpdater aUpdater(lcl_getE3dScene( m_xOuterGroupShape ));
+ xDestProp->setPropertyValue( C2U( UNO_NAME_3D_TRANSFORM_MATRIX ),
+ uno::makeAny( BaseGFXHelper::B3DHomMatrixToHomogenMatrix( aEffectiveTranformation ) ) );
+ }
+ }
+ catch( const uno::Exception & ex )
+ {
+ ASSERT_EXCEPTION( ex );
+ }
+
+ //add floor plate
+ {
+ uno::Reference< beans::XPropertySet > xFloorProp( NULL );
+ if( m_xDiagram.is() )
+ xFloorProp=uno::Reference< beans::XPropertySet >( m_xDiagram->getFloor());
+
+ Stripe aStripe( drawing::Position3D(0,0,0)
+ , drawing::Direction3D(0,0,FIXED_SIZE_FOR_3D_CHART_VOLUME)
+ , drawing::Direction3D(FIXED_SIZE_FOR_3D_CHART_VOLUME,0,0) );
+ aStripe.InvertNormal(true);
+
+ uno::Reference< drawing::XShape > xShape =
+ m_pShapeFactory->createStripe(xOuterGroup_Shapes, aStripe
+ , xFloorProp, PropertyMapper::getPropertyNameMapForFillAndLineProperties(), bDoubleSided, 0, bFlatNormals );
+
+ CuboidPlanePosition eBottomPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBottom( uno::Reference< beans::XPropertySet >( m_xDiagram, uno::UNO_QUERY ) ) );
+ if( !bAddFloorAndWall || (CuboidPlanePosition_Bottom!=eBottomPos) )
+ {
+ //we always need this object as dummy object for correct scene dimensions
+ //but it should not be visible in this case:
+ ShapeFactory::makeShapeInvisible( xShape );
+ }
+ else
+ {
+ rtl::OUString aFloorCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_FLOOR, rtl::OUString() ) );//@todo read CID from model
+ ShapeFactory::setShapeName( xShape, aFloorCID );
+ }
+ }
+ //---------------------------
+
+ //create an additional scene for the smaller inner coordinate region:
+ {
+ uno::Reference< drawing::XShapes > xShapes = m_pShapeFactory->createGroup3D( xOuterGroup_Shapes,C2U("testonly;CooContainer=XXX_CID") );
+ m_xCoordinateRegionShape = uno::Reference< drawing::XShape >( xShapes, uno::UNO_QUERY );
+
+ uno::Reference< beans::XPropertySet > xShapeProp( m_xCoordinateRegionShape, uno::UNO_QUERY );
+ DBG_ASSERT(xShapeProp.is(), "created shape offers no XPropertySet");
+ if( xShapeProp.is())
+ {
+ try
+ {
+ double fXScale = (FIXED_SIZE_FOR_3D_CHART_VOLUME -GRID_TO_WALL_DISTANCE) /FIXED_SIZE_FOR_3D_CHART_VOLUME;
+ double fYScale = (FIXED_SIZE_FOR_3D_CHART_VOLUME -GRID_TO_WALL_DISTANCE) /FIXED_SIZE_FOR_3D_CHART_VOLUME;
+ double fZScale = (FIXED_SIZE_FOR_3D_CHART_VOLUME -GRID_TO_WALL_DISTANCE) /FIXED_SIZE_FOR_3D_CHART_VOLUME;
+
+ ::basegfx::B3DHomMatrix aM;
+ aM.translate(GRID_TO_WALL_DISTANCE/fXScale, GRID_TO_WALL_DISTANCE/fYScale, GRID_TO_WALL_DISTANCE/fZScale);
+ aM.scale( fXScale, fYScale, fZScale );
+ E3DModifySceneSnapRectUpdater aUpdater(lcl_getE3dScene( m_xOuterGroupShape ));
+ xShapeProp->setPropertyValue( C2U( UNO_NAME_3D_TRANSFORM_MATRIX )
+ , uno::makeAny(BaseGFXHelper::B3DHomMatrixToHomogenMatrix(aM)) );
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+ }
+ }
+
+ m_aCurrentPosWithoutAxes = m_aAvailablePosIncludingAxes;
+ m_aCurrentSizeWithoutAxes = m_aAvailableSizeIncludingAxes;
+ adjustPosAndSize_3d( m_aAvailablePosIncludingAxes, m_aAvailableSizeIncludingAxes );
+}
+
+uno::Reference< drawing::XShapes > VDiagram::getCoordinateRegion()
+{
+ return uno::Reference<drawing::XShapes>( m_xCoordinateRegionShape, uno::UNO_QUERY );
+}
+
+::basegfx::B2IRectangle VDiagram::getCurrentRectangle()
+{
+ return BaseGFXHelper::makeRectangle(m_aCurrentPosWithoutAxes,m_aCurrentSizeWithoutAxes);
+}
+
+void VDiagram::reduceToMimimumSize()
+{
+ if( m_xOuterGroupShape.is() )
+ {
+ awt::Size aMaxSize( m_aAvailableSizeIncludingAxes );
+ awt::Point aMaxPos( m_aAvailablePosIncludingAxes );
+
+ sal_Int32 nNewWidth = aMaxSize.Width/3;
+ sal_Int32 nNewHeight = aMaxSize.Height/3;
+ awt::Size aNewSize( nNewWidth, nNewHeight );
+ awt::Point aNewPos( aMaxPos );
+ aNewPos.X += nNewWidth;
+ aNewPos.Y += nNewHeight;
+
+ adjustPosAndSize( aNewPos, aNewSize );
+ }
+}
+
+::basegfx::B2IRectangle VDiagram::adjustInnerSize( const ::basegfx::B2IRectangle& rConsumedOuterRect )
+{
+ awt::Point aNewPos( m_aCurrentPosWithoutAxes );
+ awt::Size aNewSize( m_aCurrentSizeWithoutAxes );
+
+ ::basegfx::B2IRectangle rAvailableOuterRect(
+ BaseGFXHelper::makeRectangle(m_aAvailablePosIncludingAxes,m_aAvailableSizeIncludingAxes) );
+
+ sal_Int32 nDeltaWidth = static_cast<sal_Int32>(rAvailableOuterRect.getWidth() - rConsumedOuterRect.getWidth());
+ sal_Int32 nDeltaHeight = static_cast<sal_Int32>(rAvailableOuterRect.getHeight() - rConsumedOuterRect.getHeight());
+ if( (aNewSize.Width + nDeltaWidth) < rAvailableOuterRect.getWidth()/3 )
+ nDeltaWidth = static_cast<sal_Int32>(rAvailableOuterRect.getWidth()/3 - aNewSize.Width);
+ aNewSize.Width += nDeltaWidth;
+
+ if( (aNewSize.Height + nDeltaHeight) < rAvailableOuterRect.getHeight()/3 )
+ nDeltaHeight = static_cast<sal_Int32>(rAvailableOuterRect.getHeight()/3 - aNewSize.Height);
+ aNewSize.Height += nDeltaHeight;
+
+ sal_Int32 nDiffLeft = rConsumedOuterRect.getMinX() - rAvailableOuterRect.getMinX();
+ sal_Int32 nDiffRight = rAvailableOuterRect.getMaxX() - rConsumedOuterRect.getMaxX();
+ if( nDiffLeft >= 0 )
+ aNewPos.X -= nDiffLeft;
+ else if( nDiffRight >= 0 )
+ {
+ if( nDiffRight > -nDiffLeft )
+ aNewPos.X += abs(nDiffLeft);
+ else if( nDiffRight > abs(nDeltaWidth) )
+ aNewPos.X += nDiffRight;
+ else
+ aNewPos.X += abs(nDeltaWidth);
+ }
+
+ sal_Int32 nDiffUp = rConsumedOuterRect.getMinY() - rAvailableOuterRect.getMinY();
+ sal_Int32 nDiffDown = rAvailableOuterRect.getMaxY() - rConsumedOuterRect.getMaxY();
+ if( nDiffUp >= 0 )
+ aNewPos.Y -= nDiffUp;
+ else if( nDiffDown >= 0 )
+ {
+ if( nDiffDown > -nDiffUp )
+ aNewPos.Y += abs(nDiffUp);
+ else if( nDiffDown > abs(nDeltaHeight) )
+ aNewPos.Y += nDiffDown;
+ else
+ aNewPos.Y += abs(nDeltaHeight);
+ }
+
+ return adjustPosAndSize( aNewPos, aNewSize );
+}
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
+
diff --git a/chart2/source/view/diagram/makefile.mk b/chart2/source/view/diagram/makefile.mk
new file mode 100644
index 000000000000..652f203b2267
--- /dev/null
+++ b/chart2/source/view/diagram/makefile.mk
@@ -0,0 +1,48 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ= ..$/..$/..
+PRJINC= $(PRJ)$/source
+PRJNAME= chart2
+TARGET= chvdiagram
+
+ENABLE_EXCEPTIONS= TRUE
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE: settings.mk
+.INCLUDE: $(PRJ)$/chartview.pmk
+
+# --- export library -------------------------------------------------
+
+#object files to build and link together to lib $(SLB)$/$(TARGET).lib
+SLOFILES = $(SLO)$/VDiagram.obj
+
+# --- Targets -----------------------------------------------------------------
+
+.INCLUDE: target.mk
+
diff --git a/chart2/source/view/exports.flt b/chart2/source/view/exports.flt
new file mode 100644
index 000000000000..56fa90f75bb1
--- /dev/null
+++ b/chart2/source/view/exports.flt
@@ -0,0 +1,4 @@
+lcl_
+_real@
+_TI1
+_TI2
diff --git a/chart2/source/view/inc/Clipping.hxx b/chart2/source/view/inc/Clipping.hxx
new file mode 100644
index 000000000000..d04a576737bf
--- /dev/null
+++ b/chart2/source/view/inc/Clipping.hxx
@@ -0,0 +1,70 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CHART2_CLIPPING_HXX
+#define _CHART2_CLIPPING_HXX
+
+#include <basegfx/range/b2drectangle.hxx>
+#include <com/sun/star/drawing/PolyPolygonShape3D.hpp>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+
+//-----------------------------------------------------------------------------
+/**
+*/
+
+class Clipping
+{
+ /** This class uses the Liang-Biarsky parametric line-clipping algorithm as described in:
+ Computer Graphics: principles and practice, 2nd ed.,
+ James D. Foley et al.,
+ Section 3.12.4 on page 117.
+ */
+
+public:
+ /** @descr The intersection between an open polygon and a rectangle is
+ calculated and the resulting lines are placed into the poly-polygon aResult.
+ @param rPolygon The polygon is required to be open, ie. it's start and end point
+ have different coordinates and that it is continuous, ie. has no holes.
+ @param rRectangle The clipping area.
+ @param aResult The resulting lines that are the parts of the given polygon lying inside
+ the clipping area are stored into aResult whose prior content is deleted first.
+ */
+ static void clipPolygonAtRectangle(
+ const ::com::sun::star::drawing::PolyPolygonShape3D& rPolygon
+ , const ::basegfx::B2DRectangle& rRectangle
+ , ::com::sun::star::drawing::PolyPolygonShape3D& aResult
+ , bool bSplitPiecesToDifferentPolygons = true );
+};
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
+#endif
diff --git a/chart2/source/view/inc/LabelAlignment.hxx b/chart2/source/view/inc/LabelAlignment.hxx
new file mode 100644
index 000000000000..26ec703db302
--- /dev/null
+++ b/chart2/source/view/inc/LabelAlignment.hxx
@@ -0,0 +1,41 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CHART2_VIEW_LabelAlignment_HXX
+#define _CHART2_VIEW_LabelAlignment_HXX
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+
+enum LabelAlignment { LABEL_ALIGN_CENTER, LABEL_ALIGN_LEFT, LABEL_ALIGN_TOP, LABEL_ALIGN_RIGHT, LABEL_ALIGN_BOTTOM, LABEL_ALIGN_LEFT_TOP, LABEL_ALIGN_LEFT_BOTTOM, LABEL_ALIGN_RIGHT_TOP, LABEL_ALIGN_RIGHT_BOTTOM };
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
+#endif
diff --git a/chart2/source/view/inc/LabelPositionHelper.hxx b/chart2/source/view/inc/LabelPositionHelper.hxx
new file mode 100644
index 000000000000..a240736018bc
--- /dev/null
+++ b/chart2/source/view/inc/LabelPositionHelper.hxx
@@ -0,0 +1,86 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CHART2_VIEW_LABELPOSITIONHELPER_HXX
+#define _CHART2_VIEW_LABELPOSITIONHELPER_HXX
+
+#include "LabelAlignment.hxx"
+#include "PropertyMapper.hxx"
+#include <com/sun/star/awt/Point.hpp>
+#include <com/sun/star/drawing/Position3D.hpp>
+#include <com/sun/star/drawing/XShapes.hpp>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+
+//-----------------------------------------------------------------------------
+/**
+*/
+class PlottingPositionHelper;
+class ShapeFactory;
+
+class LabelPositionHelper
+{
+public:
+ LabelPositionHelper(
+ PlottingPositionHelper* pPosHelper
+ , sal_Int32 nDimensionCount
+ , const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& xLogicTarget
+ , ShapeFactory* pShapeFactory );
+ virtual ~LabelPositionHelper();
+
+ ::com::sun::star::awt::Point transformSceneToScreenPosition(
+ const ::com::sun::star::drawing::Position3D& rScenePosition3D ) const;
+
+ static void changeTextAdjustment( tAnySequence& rPropValues, const tNameSequence& rPropNames, LabelAlignment eAlignment);
+ static void doDynamicFontResize( tAnySequence& rPropValues, const tNameSequence& rPropNames
+ , const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& xAxisModelProps
+ , const ::com::sun::star::awt::Size& rNewReferenceSize );
+
+ static void correctPositionForRotation( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >& xShape2DText
+ , LabelAlignment eLabelAlignment, const double fRotationAngle, bool bRotateAroundCenter );
+
+private:
+ LabelPositionHelper();
+
+protected:
+ PlottingPositionHelper* m_pPosHelper;
+ sal_Int32 m_nDimensionCount;
+
+private:
+ //these members are only necessary for transformation from 3D to 2D
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShapes > m_xLogicTarget;
+ ShapeFactory* m_pShapeFactory;
+};
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
+#endif
diff --git a/chart2/source/view/inc/LegendEntryProvider.hxx b/chart2/source/view/inc/LegendEntryProvider.hxx
new file mode 100644
index 000000000000..14b6cda47870
--- /dev/null
+++ b/chart2/source/view/inc/LegendEntryProvider.hxx
@@ -0,0 +1,63 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef CHART2_VIEW_LEGENDENTRYPROVIDER_HXX
+#define CHART2_VIEW_LEGENDENTRYPROVIDER_HXX
+
+#include <com/sun/star/chart2/LegendExpansion.hpp>
+
+#ifndef _COM_SUN_STAR_CHART2_VIEWLEGENDENTRYP_HPP_
+#include <com/sun/star/chart2/ViewLegendEntry.hpp>
+#endif
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+namespace chart
+{
+
+class LegendEntryProvider
+{
+public:
+ virtual ::com::sun::star::uno::Sequence<
+ ::com::sun::star::chart2::ViewLegendEntry > SAL_CALL createLegendEntries(
+ ::com::sun::star::chart2::LegendExpansion eLegendExpansion,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::beans::XPropertySet >& xTextProperties,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShapes >& xTarget,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::lang::XMultiServiceFactory >& xShapeFactory,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XComponentContext >& xContext
+ )
+ throw (::com::sun::star::uno::RuntimeException) = 0;
+
+private:
+};
+
+} // namespace chart
+
+// CHART2_VIEW_LEGENDENTRYPROVIDER_HXX
+#endif
diff --git a/chart2/source/view/inc/Linear3DTransformation.hxx b/chart2/source/view/inc/Linear3DTransformation.hxx
new file mode 100644
index 000000000000..71a728d2dc73
--- /dev/null
+++ b/chart2/source/view/inc/Linear3DTransformation.hxx
@@ -0,0 +1,67 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _CHART_LINEAR3DTRANSFORMATION_HXX
+#define _CHART_LINEAR3DTRANSFORMATION_HXX
+
+#include <cppuhelper/implbase1.hxx>
+#include <com/sun/star/chart2/XTransformation.hpp>
+#include <com/sun/star/drawing/HomogenMatrix.hpp>
+
+namespace chart
+{
+
+class Linear3DTransformation : public ::cppu::WeakImplHelper1<
+ ::com::sun::star::chart2::XTransformation
+ >
+{
+public:
+ Linear3DTransformation( const ::com::sun::star::drawing::HomogenMatrix& rHomMatrix, bool bSwapXAndY );
+ virtual ~Linear3DTransformation();
+
+ // ____ XTransformation ____
+ /// @see ::com::sun::star::chart2::XTransformation
+ virtual ::com::sun::star::uno::Sequence< double > SAL_CALL transform(
+ const ::com::sun::star::uno::Sequence< double >& rSourceValues )
+ throw (::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException);
+ /// @see ::com::sun::star::chart2::XTransformation
+ virtual sal_Int32 SAL_CALL getSourceDimension()
+ throw (::com::sun::star::uno::RuntimeException);
+ /// @see ::com::sun::star::chart2::XTransformation
+ virtual sal_Int32 SAL_CALL getTargetDimension()
+ throw (::com::sun::star::uno::RuntimeException);
+
+private:
+ ::com::sun::star::drawing::HomogenMatrix m_Matrix;
+ bool m_bSwapXAndY;
+};
+
+} // namespace chart
+
+// _CHART_LINEAR3DTRANSFORMATION_HXX
+#endif
+
diff --git a/chart2/source/view/inc/MinimumAndMaximumSupplier.hxx b/chart2/source/view/inc/MinimumAndMaximumSupplier.hxx
new file mode 100644
index 000000000000..1e53d5c144c5
--- /dev/null
+++ b/chart2/source/view/inc/MinimumAndMaximumSupplier.hxx
@@ -0,0 +1,100 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CHART2_MINIMUMANDMAXIMUMSUPPLIER_HXX
+#define _CHART2_MINIMUMANDMAXIMUMSUPPLIER_HXX
+
+#include <sal/types.h>
+
+#include <set>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+
+//-----------------------------------------------------------------------------
+/**
+*/
+
+class MinimumAndMaximumSupplier
+{
+public:
+ virtual double getMinimumX() = 0;
+ virtual double getMaximumX() = 0;
+
+ //problem y maybe not is always the second border to ask for
+ virtual double getMinimumYInRange( double fMinimumX, double fMaximumX, sal_Int32 nAxisIndex ) = 0;
+ virtual double getMaximumYInRange( double fMinimumX, double fMaximumX, sal_Int32 nAxisIndex ) = 0;
+
+ //problem: z maybe not independent in future
+ virtual double getMinimumZ() = 0;
+ virtual double getMaximumZ() = 0;
+
+ virtual bool isExpandBorderToIncrementRhythm( sal_Int32 nDimensionIndex ) = 0;
+ virtual bool isExpandIfValuesCloseToBorder( sal_Int32 nDimensionIndex ) = 0;
+ virtual bool isExpandWideValuesToZero( sal_Int32 nDimensionIndex ) = 0;
+ virtual bool isExpandNarrowValuesTowardZero( sal_Int32 nDimensionIndex ) = 0;
+ virtual bool isSeperateStackingForDifferentSigns( sal_Int32 nDimensionIndex ) = 0;
+};
+
+class MergedMinimumAndMaximumSupplier : public MinimumAndMaximumSupplier
+{
+public:
+ MergedMinimumAndMaximumSupplier();
+ virtual ~MergedMinimumAndMaximumSupplier();
+
+ void addMinimumAndMaximumSupplier( MinimumAndMaximumSupplier* pMinimumAndMaximumSupplier );
+ bool hasMinimumAndMaximumSupplier( MinimumAndMaximumSupplier* pMinimumAndMaximumSupplier );
+ void clearMinimumAndMaximumSupplierList();
+
+ //--MinimumAndMaximumSupplier
+ virtual double getMinimumX();
+ virtual double getMaximumX();
+ virtual double getMinimumYInRange( double fMinimumX, double fMaximumX, sal_Int32 nAxisIndex );
+ virtual double getMaximumYInRange( double fMinimumX, double fMaximumX, sal_Int32 nAxisIndex );
+ virtual double getMinimumZ();
+ virtual double getMaximumZ();
+
+ virtual bool isExpandBorderToIncrementRhythm( sal_Int32 nDimensionIndex );
+ virtual bool isExpandIfValuesCloseToBorder( sal_Int32 nDimensionIndex );
+ virtual bool isExpandWideValuesToZero( sal_Int32 nDimensionIndex );
+ virtual bool isExpandNarrowValuesTowardZero( sal_Int32 nDimensionIndex );
+ virtual bool isSeperateStackingForDifferentSigns( sal_Int32 nDimensionIndex );
+
+private:
+ typedef ::std::set< MinimumAndMaximumSupplier* > MinimumAndMaximumSupplierSet;
+ MinimumAndMaximumSupplierSet m_aMinimumAndMaximumSupplierList;
+
+ inline MinimumAndMaximumSupplierSet::iterator begin() { return m_aMinimumAndMaximumSupplierList.begin(); }
+ inline MinimumAndMaximumSupplierSet::iterator end() { return m_aMinimumAndMaximumSupplierList.end(); }
+};
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
+#endif
diff --git a/chart2/source/view/inc/PlotterBase.hxx b/chart2/source/view/inc/PlotterBase.hxx
new file mode 100644
index 000000000000..63e276b19e44
--- /dev/null
+++ b/chart2/source/view/inc/PlotterBase.hxx
@@ -0,0 +1,126 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _CHART2_PLOTTERBASE_HXX
+#define _CHART2_PLOTTERBASE_HXX
+
+#include <com/sun/star/drawing/HomogenMatrix.hpp>
+#include <com/sun/star/drawing/XShapes.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/drawing/Position3D.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+/*
+#include <com/sun/star/lang/XComponent.hpp>
+*/
+
+//----
+#include <vector>
+
+//---- chart2
+#include <com/sun/star/chart2/ExplicitScaleData.hpp>
+#include <com/sun/star/chart2/XTransformation.hpp>
+/*
+#include <com/sun/star/chart2/XPlotter.hpp>
+*/
+
+//----
+#include <cppuhelper/implbase1.hxx>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+
+class ShapeFactory;
+class PlottingPositionHelper;
+
+class PlotterBase
+{
+public:
+ PlotterBase( sal_Int32 nDimension );
+ virtual ~PlotterBase();
+
+ // ___chart2::XPlotter___
+ 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 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 setTransformationSceneToScreen( const ::com::sun::star::drawing::HomogenMatrix& rMatrix );
+
+ virtual void SAL_CALL createShapes() = 0;
+
+ static bool isValidPosition( const ::com::sun::star::drawing::Position3D& rPos );
+ /*
+ 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);
+ */
+
+ //-------------------------------------------------------------------------
+ //-------------------------------------------------------------------------
+ //-------------------------------------------------------------------------
+private: //methods
+ //no default constructor
+ PlotterBase();
+
+protected: //methods
+ ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >
+ createGroupShape( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShapes >& xTarget
+ , ::rtl::OUString rName=::rtl::OUString() );
+
+protected: //member
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShapes > m_xLogicTarget;
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShapes > m_xFinalTarget;
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::lang::XMultiServiceFactory> m_xShapeFactory;
+ ShapeFactory* m_pShapeFactory;
+ //::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext> m_xCC;
+
+ rtl::OUString m_aCID;
+
+ sal_Int32 m_nDimension;
+ // needs to be created and deleted by the derived class
+ PlottingPositionHelper* m_pPosHelper;
+};
+//.............................................................................
+} //namespace chart
+//.............................................................................
+#endif
diff --git a/chart2/source/view/inc/PlottingPositionHelper.hxx b/chart2/source/view/inc/PlottingPositionHelper.hxx
new file mode 100644
index 000000000000..a1f16883b779
--- /dev/null
+++ b/chart2/source/view/inc/PlottingPositionHelper.hxx
@@ -0,0 +1,406 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _CHART2_PLOTTINGPOSITIONHELPER_HXX
+#define _CHART2_PLOTTINGPOSITIONHELPER_HXX
+
+#include "LabelAlignment.hxx"
+#include <basegfx/range/b2drectangle.hxx>
+#include <rtl/math.hxx>
+#include <com/sun/star/chart2/ExplicitScaleData.hpp>
+#include <com/sun/star/chart2/XTransformation.hpp>
+#include <com/sun/star/drawing/Direction3D.hpp>
+#include <com/sun/star/drawing/HomogenMatrix.hpp>
+#include <com/sun/star/drawing/PolyPolygonShape3D.hpp>
+#include <com/sun/star/drawing/Position3D.hpp>
+#include <com/sun/star/drawing/XShapes.hpp>
+#include <basegfx/matrix/b3dhommatrix.hxx>
+
+/*
+//for WeakImplHelper1
+#include <cppuhelper/implbase1.hxx>
+*/
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+
+class ShapeFactory;
+
+//-----------------------------------------------------------------------------
+/**
+*/
+
+class PlottingPositionHelper
+{
+public:
+ PlottingPositionHelper();
+ PlottingPositionHelper( const PlottingPositionHelper& rSource );
+ virtual ~PlottingPositionHelper();
+
+ virtual PlottingPositionHelper* clone() const;
+ virtual PlottingPositionHelper* createSecondaryPosHelper( const ::com::sun::star::chart2::ExplicitScaleData& rSecondaryScale );
+
+ virtual void setTransformationSceneToScreen( const ::com::sun::star::drawing::HomogenMatrix& rMatrix);
+
+ virtual void setScales( const ::com::sun::star::uno::Sequence<
+ ::com::sun::star::chart2::ExplicitScaleData >& rScales
+ , sal_Bool bSwapXAndYAxis );
+ const ::com::sun::star::uno::Sequence<
+ ::com::sun::star::chart2::ExplicitScaleData >& getScales() const;
+
+ //better performance for big data
+ inline void setCoordinateSystemResolution( const ::com::sun::star::uno::Sequence< sal_Int32 >& rCoordinateSystemResolution );
+ inline bool isSameForGivenResolution( double fX, double fY, double fZ
+ , double fX2, double fY2, double fZ2 );
+
+ inline bool isLogicVisible( double fX, double fY, double fZ ) const;
+ inline void doLogicScaling( double* pX, double* pY, double* pZ, bool bClip=false ) const;
+ inline void clipLogicValues( double* pX, double* pY, double* pZ ) const;
+ void clipScaledLogicValues( double* pX, double* pY, double* pZ ) const;
+ inline bool clipYRange( double& rMin, double& rMax ) const;
+
+ inline void doLogicScaling( ::com::sun::star::drawing::Position3D& rPos, bool bClip=false ) const;
+
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XTransformation >
+ getTransformationScaledLogicToScene() const;
+
+ virtual ::com::sun::star::drawing::Position3D
+ transformLogicToScene( double fX, double fY, double fZ, bool bClip ) const;
+
+ virtual ::com::sun::star::drawing::Position3D
+ transformScaledLogicToScene( double fX, double fY, double fZ, bool bClip ) const;
+
+ void transformScaledLogicToScene( ::com::sun::star::drawing::PolyPolygonShape3D& rPoly ) const;
+
+ static com::sun::star::awt::Point transformSceneToScreenPosition(
+ const com::sun::star::drawing::Position3D& rScenePosition3D
+ , const com::sun::star::uno::Reference< com::sun::star::drawing::XShapes >& xSceneTarget
+ , ShapeFactory* pShapeFactory, sal_Int32 nDimensionCount );
+
+ inline double getLogicMinX() const;
+ inline double getLogicMinY() const;
+ inline double getLogicMinZ() const;
+ inline double getLogicMaxX() const;
+ inline double getLogicMaxY() const;
+ inline double getLogicMaxZ() const;
+
+ inline bool isMathematicalOrientationX() const;
+ inline bool isMathematicalOrientationY() const;
+ inline bool isMathematicalOrientationZ() const;
+
+ ::basegfx::B2DRectangle getScaledLogicClipDoubleRect() const;
+ ::com::sun::star::drawing::Direction3D getScaledLogicWidth() const;
+
+ inline bool isSwapXAndY() const;
+
+ bool isPercentY() const;
+
+ double getBaseValueY() const;
+
+ inline bool maySkipPointsInRegressionCalculation() const;
+
+protected: //member
+ ::com::sun::star::uno::Sequence<
+ ::com::sun::star::chart2::ExplicitScaleData > m_aScales;
+ ::basegfx::B3DHomMatrix m_aMatrixScreenToScene;
+
+ //this is calculated based on m_aScales and m_aMatrixScreenToScene
+ mutable ::com::sun::star::uno::Reference<
+ ::com::sun::star::chart2::XTransformation > m_xTransformationLogicToScene;
+
+ bool m_bSwapXAndY;//e.g. true for bar chart and false for column chart
+
+ sal_Int32 m_nXResolution;
+ sal_Int32 m_nYResolution;
+ sal_Int32 m_nZResolution;
+
+ bool m_bMaySkipPointsInRegressionCalculation;
+};
+
+//describes wich axis of the drawinglayer scene or sreen axis are the normal axis
+enum NormalAxis
+{
+ NormalAxis_X
+ , NormalAxis_Y
+ , NormalAxis_Z
+};
+
+class PolarPlottingPositionHelper : public PlottingPositionHelper
+ /*
+ , public ::cppu::WeakImplHelper1<
+ ::com::sun::star::chart2::XTransformation >
+ */
+{
+public:
+ PolarPlottingPositionHelper( NormalAxis eNormalAxis=NormalAxis_Z );
+ PolarPlottingPositionHelper( const PolarPlottingPositionHelper& rSource );
+ virtual ~PolarPlottingPositionHelper();
+
+ virtual PlottingPositionHelper* clone() const;
+
+ virtual void setTransformationSceneToScreen( const ::com::sun::star::drawing::HomogenMatrix& rMatrix);
+ virtual void setScales( const ::com::sun::star::uno::Sequence<
+ ::com::sun::star::chart2::ExplicitScaleData >& rScales
+ , sal_Bool bSwapXAndYAxis );
+
+ ::basegfx::B3DHomMatrix getUnitCartesianToScene() const;
+
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XTransformation >
+ getTransformationScaledLogicToScene() const;
+
+ //the resulting values should be used for input to the transformation
+ //received with 'getTransformationScaledLogicToScene'
+ double transformToRadius( double fLogicValueOnRadiusAxis, bool bDoScaling=true ) const;
+ double transformToAngleDegree( double fLogicValueOnAngleAxis, bool bDoScaling=true ) const;
+ double getWidthAngleDegree( double& fStartLogicValueOnAngleAxis, double& fEndLogicValueOnAngleAxis ) const;
+ //
+
+ virtual ::com::sun::star::drawing::Position3D
+ transformLogicToScene( double fX, double fY, double fZ, bool bClip ) const;
+ virtual ::com::sun::star::drawing::Position3D
+ transformScaledLogicToScene( double fX, double fY, double fZ, bool bClip ) const;
+ ::com::sun::star::drawing::Position3D
+ transformAngleRadiusToScene( double fLogicValueOnAngleAxis, double fLogicValueOnRadiusAxis, double fLogicZ, bool bDoScaling=true ) const;
+ ::com::sun::star::drawing::Position3D
+ transformUnitCircleToScene( double fUnitAngleDegree, double fUnitRadius, double fLogicZ, bool bDoScaling=true ) const;
+
+ using PlottingPositionHelper::transformScaledLogicToScene;
+
+#ifdef NOTYET
+ double getInnerLogicRadius() const;
+#endif
+ double getOuterLogicRadius() const;
+
+ inline bool isMathematicalOrientationAngle() const;
+ inline bool isMathematicalOrientationRadius() const;
+
+ /*
+ // ____ XTransformation ____
+ /// @see ::com::sun::star::chart2::XTransformation
+ virtual ::com::sun::star::uno::Sequence< double > SAL_CALL transform(
+ const ::com::sun::star::uno::Sequence< double >& rSourceValues )
+ throw (::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException);
+ /// @see ::com::sun::star::chart2::XTransformation
+ virtual sal_Int32 SAL_CALL getSourceDimension()
+ throw (::com::sun::star::uno::RuntimeException);
+ /// @see ::com::sun::star::chart2::XTransformation
+ virtual sal_Int32 SAL_CALL getTargetDimension()
+ throw (::com::sun::star::uno::RuntimeException);
+ */
+public:
+ //Offset for radius axis in absolute logic scaled values (1.0 == 1 category)
+ double m_fRadiusOffset;
+ //Offset for angle axis in real degree
+ double m_fAngleDegreeOffset;
+
+private:
+ ::basegfx::B3DHomMatrix m_aUnitCartesianToScene;
+ NormalAxis m_eNormalAxis;
+
+ ::basegfx::B3DHomMatrix impl_calculateMatrixUnitCartesianToScene( const ::basegfx::B3DHomMatrix& rMatrixScreenToScene ) const;
+};
+
+bool PolarPlottingPositionHelper::isMathematicalOrientationAngle() const
+{
+ const ::com::sun::star::chart2::ExplicitScaleData& rScale = m_bSwapXAndY ? m_aScales[1] : m_aScales[2];
+ if( ::com::sun::star::chart2::AxisOrientation_MATHEMATICAL==rScale.Orientation )
+ return true;
+ return false;
+}
+bool PolarPlottingPositionHelper::isMathematicalOrientationRadius() const
+{
+ const ::com::sun::star::chart2::ExplicitScaleData& rScale = m_bSwapXAndY ? m_aScales[0] : m_aScales[1];
+ if( ::com::sun::star::chart2::AxisOrientation_MATHEMATICAL==rScale.Orientation )
+ return true;
+ return false;
+}
+
+//better performance for big data
+void PlottingPositionHelper::setCoordinateSystemResolution( const ::com::sun::star::uno::Sequence< sal_Int32 >& rCoordinateSystemResolution )
+{
+ m_nXResolution = 1000;
+ m_nYResolution = 1000;
+ m_nZResolution = 1000;
+ if( rCoordinateSystemResolution.getLength() > 0 )
+ m_nXResolution = rCoordinateSystemResolution[0];
+ if( rCoordinateSystemResolution.getLength() > 1 )
+ m_nYResolution = rCoordinateSystemResolution[1];
+ if( rCoordinateSystemResolution.getLength() > 2 )
+ m_nZResolution = rCoordinateSystemResolution[2];
+}
+
+bool PlottingPositionHelper::isSameForGivenResolution( double fX, double fY, double fZ
+ , double fX2, double fY2, double fZ2 /*these values are all expected tp be scaled already*/ )
+{
+ if( !::rtl::math::isFinite(fX) || !::rtl::math::isFinite(fY) || !::rtl::math::isFinite(fZ)
+ || !::rtl::math::isFinite(fX2) || !::rtl::math::isFinite(fY2) || !::rtl::math::isFinite(fZ2) )
+ return false;
+
+ double fScaledMinX = getLogicMinX();
+ double fScaledMinY = getLogicMinY();
+ double fScaledMinZ = getLogicMinZ();
+ double fScaledMaxX = getLogicMaxX();
+ double fScaledMaxY = getLogicMaxY();
+ double fScaledMaxZ = getLogicMaxZ();
+
+ doLogicScaling( &fScaledMinX, &fScaledMinY, &fScaledMinZ );
+ doLogicScaling( &fScaledMaxX, &fScaledMaxY, &fScaledMaxZ);
+
+ bool bSameX = ( static_cast<sal_Int32>(m_nXResolution*(fX - fScaledMinX)/(fScaledMaxX-fScaledMinX))
+ == static_cast<sal_Int32>(m_nXResolution*(fX2 - fScaledMinX)/(fScaledMaxX-fScaledMinX)) );
+
+ bool bSameY = ( static_cast<sal_Int32>(m_nYResolution*(fY - fScaledMinY)/(fScaledMaxY-fScaledMinY))
+ == static_cast<sal_Int32>(m_nYResolution*(fY2 - fScaledMinY)/(fScaledMaxY-fScaledMinY)) );
+
+ bool bSameZ = ( static_cast<sal_Int32>(m_nZResolution*(fZ - fScaledMinZ)/(fScaledMaxZ-fScaledMinZ))
+ == static_cast<sal_Int32>(m_nZResolution*(fZ2 - fScaledMinZ)/(fScaledMaxZ-fScaledMinZ)) );
+
+ return (bSameX && bSameY && bSameZ);
+}
+
+bool PlottingPositionHelper::isLogicVisible(
+ double fX, double fY, double fZ ) const
+{
+ return fX >= m_aScales[0].Minimum && fX <= m_aScales[0].Maximum
+ && fY >= m_aScales[1].Minimum && fY <= m_aScales[1].Maximum
+ && fZ >= m_aScales[2].Minimum && fZ <= m_aScales[2].Maximum;
+}
+
+void PlottingPositionHelper::doLogicScaling( double* pX, double* pY, double* pZ, bool bClip ) const
+{
+ if(bClip)
+ this->clipLogicValues( pX,pY,pZ );
+
+ if(pX && m_aScales[0].Scaling.is())
+ *pX = m_aScales[0].Scaling->doScaling(*pX);
+ if(pY && m_aScales[1].Scaling.is())
+ *pY = m_aScales[1].Scaling->doScaling(*pY);
+ if(pZ && m_aScales[2].Scaling.is())
+ *pZ = m_aScales[2].Scaling->doScaling(*pZ);
+}
+
+void PlottingPositionHelper::doLogicScaling( ::com::sun::star::drawing::Position3D& rPos, bool bClip ) const
+{
+ doLogicScaling( &rPos.PositionX, &rPos.PositionY, &rPos.PositionZ, bClip );
+}
+
+void PlottingPositionHelper::clipLogicValues( double* pX, double* pY, double* pZ ) const
+{
+ if(pX)
+ {
+ if( *pX < m_aScales[0].Minimum )
+ *pX = m_aScales[0].Minimum;
+ else if( *pX > m_aScales[0].Maximum )
+ *pX = m_aScales[0].Maximum;
+ }
+ if(pY)
+ {
+ if( *pY < m_aScales[1].Minimum )
+ *pY = m_aScales[1].Minimum;
+ else if( *pY > m_aScales[1].Maximum )
+ *pY = m_aScales[1].Maximum;
+ }
+ if(pZ)
+ {
+ if( *pZ < m_aScales[2].Minimum )
+ *pZ = m_aScales[2].Minimum;
+ else if( *pZ > m_aScales[2].Maximum )
+ *pZ = m_aScales[2].Maximum;
+ }
+}
+
+inline bool PlottingPositionHelper::clipYRange( double& rMin, double& rMax ) const
+{
+ //returns true if something remains
+ if( rMin > rMax )
+ {
+ double fHelp = rMin;
+ rMin = rMax;
+ rMax = fHelp;
+ }
+ if( rMin > getLogicMaxY() )
+ return false;
+ if( rMax < getLogicMinY() )
+ return false;
+ if( rMin < getLogicMinY() )
+ rMin = getLogicMinY();
+ if( rMax > getLogicMaxY() )
+ rMax = getLogicMaxY();
+ return true;
+}
+
+inline double PlottingPositionHelper::getLogicMinX() const
+{
+ return m_aScales[0].Minimum;
+}
+inline double PlottingPositionHelper::getLogicMinY() const
+{
+ return m_aScales[1].Minimum;
+}
+inline double PlottingPositionHelper::getLogicMinZ() const
+{
+ return m_aScales[2].Minimum;
+}
+
+inline double PlottingPositionHelper::getLogicMaxX() const
+{
+ return m_aScales[0].Maximum;
+}
+inline double PlottingPositionHelper::getLogicMaxY() const
+{
+ return m_aScales[1].Maximum;
+}
+inline double PlottingPositionHelper::getLogicMaxZ() const
+{
+ return m_aScales[2].Maximum;
+}
+inline bool PlottingPositionHelper::isMathematicalOrientationX() const
+{
+ return ::com::sun::star::chart2::AxisOrientation_MATHEMATICAL == m_aScales[0].Orientation;
+}
+inline bool PlottingPositionHelper::isMathematicalOrientationY() const
+{
+ return ::com::sun::star::chart2::AxisOrientation_MATHEMATICAL == m_aScales[1].Orientation;
+}
+inline bool PlottingPositionHelper::isMathematicalOrientationZ() const
+{
+ return ::com::sun::star::chart2::AxisOrientation_MATHEMATICAL == m_aScales[2].Orientation;
+}
+inline bool PlottingPositionHelper::isSwapXAndY() const
+{
+ return m_bSwapXAndY;
+}
+inline bool PlottingPositionHelper::maySkipPointsInRegressionCalculation() const
+{
+ return m_bMaySkipPointsInRegressionCalculation;
+}
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
+#endif
diff --git a/chart2/source/view/inc/PolarLabelPositionHelper.hxx b/chart2/source/view/inc/PolarLabelPositionHelper.hxx
new file mode 100644
index 000000000000..b4fd1fdc8483
--- /dev/null
+++ b/chart2/source/view/inc/PolarLabelPositionHelper.hxx
@@ -0,0 +1,76 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CHART2_VIEW_POLARLABELPOSITIONHELPER_HXX
+#define _CHART2_VIEW_POLARLABELPOSITIONHELPER_HXX
+
+#include "LabelPositionHelper.hxx"
+#include <com/sun/star/awt/Point.hpp>
+#include <com/sun/star/drawing/Position3D.hpp>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+
+//-----------------------------------------------------------------------------
+/**
+*/
+class PolarPlottingPositionHelper;
+
+class PolarLabelPositionHelper : public LabelPositionHelper
+{
+public:
+ PolarLabelPositionHelper(
+ PolarPlottingPositionHelper* pPosHelper
+ , sal_Int32 nDimensionCount
+ , const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& xLogicTarget
+ , ShapeFactory* pShapeFactory );
+ virtual ~PolarLabelPositionHelper();
+
+ ::com::sun::star::awt::Point getLabelScreenPositionAndAlignmentForLogicValues(
+ LabelAlignment& rAlignment
+ , double fLogicValueOnAngleAxis
+ , double fLogicValueOnRadiusAxis
+ , double fLogicZ
+ , sal_Int32 nScreenValueOffsetInRadiusDirection=0 ) const;
+
+ ::com::sun::star::awt::Point getLabelScreenPositionAndAlignmentForUnitCircleValues(
+ LabelAlignment& rAlignment, sal_Int32 nLabelPlacement /*see ::com::sun::star::chart::DataLabelPlacement*/
+ , double fUnitCircleStartAngleDegree, double fUnitCircleWidthAngleDegree
+ , double fUnitCircleInnerRadius, double fUnitCircleOuterRadius
+ , double fLogicZ
+ , sal_Int32 nScreenValueOffsetInRadiusDirection=0 ) const;
+
+private:
+ PolarPlottingPositionHelper* m_pPosHelper;
+};
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
+#endif
diff --git a/chart2/source/view/inc/PropertyMapper.hxx b/chart2/source/view/inc/PropertyMapper.hxx
new file mode 100644
index 000000000000..c0871b94f835
--- /dev/null
+++ b/chart2/source/view/inc/PropertyMapper.hxx
@@ -0,0 +1,133 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _CHART2_PROPERTYMAPPER_HXX
+#define _CHART2_PROPERTYMAPPER_HXX
+
+#include <comphelper/InlineContainer.hxx>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/drawing/XShape.hpp>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+
+//-----------------------------------------------------------------------------
+/**
+*/
+
+typedef ::std::map< ::rtl::OUString, ::rtl::OUString > tPropertyNameMap;
+typedef ::comphelper::MakeMap< ::rtl::OUString, ::rtl::OUString > tMakePropertyNameMap;
+
+typedef ::std::map< ::rtl::OUString, ::com::sun::star::uno::Any > tPropertyNameValueMap;
+typedef ::comphelper::MakeMap< ::rtl::OUString, ::com::sun::star::uno::Any > tMakePropertyNameValueMap;
+
+typedef ::com::sun::star::uno::Sequence< rtl::OUString > tNameSequence;
+typedef ::comphelper::MakeSequence< rtl::OUString > tMakeNameSequence;
+
+typedef ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > tAnySequence;
+typedef ::comphelper::MakeSequence< ::com::sun::star::uno::Any > tMakeAnySequence;
+
+class PropertyMapper
+{
+public:
+ static void setMappedProperties(
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::beans::XPropertySet >& xTarget
+ , const ::com::sun::star::uno::Reference<
+ ::com::sun::star::beans::XPropertySet >& xSource
+ , const tPropertyNameMap& rMap
+ , tPropertyNameValueMap* pOverwriteMap=0 );
+
+ static void getValueMap(
+ tPropertyNameValueMap& rValueMap
+ , const tPropertyNameMap& rNameMap
+ , const ::com::sun::star::uno::Reference<
+ ::com::sun::star::beans::XPropertySet >& xSourceProp
+ );
+
+ static void getMultiPropertyLists(
+ tNameSequence& rNames
+ , tAnySequence& rValues
+ , const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& xProp
+ , const tPropertyNameMap& rMap
+ );
+
+ static void getMultiPropertyListsFromValueMap(
+ tNameSequence& rNames
+ , tAnySequence& rValues
+ , const tPropertyNameValueMap& rValueMap
+ );
+
+ static ::com::sun::star::uno::Any*
+ getValuePointer( tAnySequence& rPropValues
+ , const tNameSequence& rPropNames
+ , const rtl::OUString& rPropName );
+
+ static ::com::sun::star::uno::Any*
+ getValuePointerForLimitedSpace( tAnySequence& rPropValues
+ , const tNameSequence& rPropNames
+ , bool bLimitedHeight );
+
+ static void setMultiProperties(
+ const tNameSequence& rNames
+ , const tAnySequence& rValues
+ , const ::com::sun::star::uno::Reference<
+ ::com::sun::star::beans::XPropertySet >& xTarget );
+
+ static const tMakePropertyNameMap& getPropertyNameMapForCharacterProperties();
+ static const tMakePropertyNameMap& getPropertyNameMapForParagraphProperties();
+ static const tMakePropertyNameMap& getPropertyNameMapForFillProperties();
+ static const tMakePropertyNameMap& getPropertyNameMapForLineProperties();
+ static const tMakePropertyNameMap& getPropertyNameMapForFillAndLineProperties();
+ static const tMakePropertyNameMap& getPropertyNameMapForTextShapeProperties();
+
+ static const tMakePropertyNameMap& getPropertyNameMapForFilledSeriesProperties();
+ static const tMakePropertyNameMap& getPropertyNameMapForLineSeriesProperties();
+
+ static void getTextLabelMultiPropertyLists(
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::beans::XPropertySet >& xSourceProp
+ , tNameSequence& rPropNames, tAnySequence& rPropValues
+ , bool bName=true
+ , sal_Int32 nLimitedSpace=-1
+ , bool bLimitedHeight=false );
+
+ /** adds line-, fill- and character properties and sets some suitable
+ defaults for auto-grow properties
+ */
+ static void getPreparedTextShapePropertyLists(
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::beans::XPropertySet >& xSourceProp
+ , tNameSequence& rPropNames
+ , tAnySequence& rPropValues );
+};
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
+#endif
diff --git a/chart2/source/view/inc/ScaleAutomatism.hxx b/chart2/source/view/inc/ScaleAutomatism.hxx
new file mode 100644
index 000000000000..4440ad26ac5a
--- /dev/null
+++ b/chart2/source/view/inc/ScaleAutomatism.hxx
@@ -0,0 +1,119 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _CHART2_SCALEAUTOMATISM_HXX
+#define _CHART2_SCALEAUTOMATISM_HXX
+
+#include <com/sun/star/chart2/ExplicitIncrementData.hpp>
+#include <com/sun/star/chart2/ExplicitScaleData.hpp>
+#include <com/sun/star/chart2/ScaleData.hpp>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+
+//-----------------------------------------------------------------------------
+
+/** This class implements the calculation of automatic axis limits.
+*/
+class ScaleAutomatism
+{
+public:
+ explicit ScaleAutomatism(
+ const ::com::sun::star::chart2::ScaleData& rSourceScale );
+ virtual ~ScaleAutomatism();
+
+ /** Expands own value range with the passed minimum and maximum. */
+ void expandValueRange( double fMinimum, double fMaximum );
+
+ /** Sets additional auto scaling options.
+ @param bExpandBorderToIncrementRhythm If true, expands automatic
+ borders to the fixed or calculated increment rhythm.
+ @param bExpandIfValuesCloseToBorder If true, expands automatic borders
+ if values are too close (closer than 1/21 of visible area).
+ @param bExpandWideValuesToZero If true, expands automatic border to
+ zero, if source values are positive only or negative only, and if
+ the absolute values are wide spread (at least one value is less
+ than 5/6 of absolute maximum), or if all values are equal.
+ @param bExpandNarrowValuesTowardZero If true, expands automatic border
+ toward zero (50% of the visible range), if source values are
+ positive only or negative only, and if the absolute values are
+ close to the absolute maximum (no value is less than 5/6 of
+ absolute maximum). */
+ void setAutoScalingOptions(
+ bool bExpandBorderToIncrementRhythm,
+ bool bExpandIfValuesCloseToBorder,
+ bool bExpandWideValuesToZero,
+ bool bExpandNarrowValuesTowardZero );
+
+ /** Sets the maximum allowed number of automatic main increments.
+ @descr The number of main increments may be limited e.g. by the length
+ of the axis and the font size of the axis caption text. */
+ void setMaximumAutoMainIncrementCount( sal_Int32 nMaximumAutoMainIncrementCount );
+
+ /** Fills the passed scale data and increment data according to the own settings. */
+ void calculateExplicitScaleAndIncrement(
+ ::com::sun::star::chart2::ExplicitScaleData& rExplicitScale,
+ ::com::sun::star::chart2::ExplicitIncrementData& rExplicitIncrement ) const;
+
+ ::com::sun::star::chart2::ScaleData getScale() const;
+
+private:
+ /** Fills the passed scale data and increment data for category scaling. */
+ void calculateExplicitIncrementAndScaleForCategory(
+ ::com::sun::star::chart2::ExplicitScaleData& rExplicitScale,
+ ::com::sun::star::chart2::ExplicitIncrementData& rExplicitIncrement,
+ bool bAutoMinimum, bool bAutoMaximum ) const;
+
+ /** Fills the passed scale data and increment data for logarithmic scaling. */
+ void calculateExplicitIncrementAndScaleForLogarithmic(
+ ::com::sun::star::chart2::ExplicitScaleData& rExplicitScale,
+ ::com::sun::star::chart2::ExplicitIncrementData& rExplicitIncrement,
+ bool bAutoMinimum, bool bAutoMaximum ) const;
+
+ /** Fills the passed scale data and increment data for linear scaling. */
+ void calculateExplicitIncrementAndScaleForLinear(
+ ::com::sun::star::chart2::ExplicitScaleData& rExplicitScale,
+ ::com::sun::star::chart2::ExplicitIncrementData& rExplicitIncrement,
+ bool bAutoMinimum, bool bAutoMaximum ) const;
+
+private:
+ ::com::sun::star::chart2::ScaleData m_aSourceScale;
+
+ double m_fValueMinimum; /// Minimum of all source values.
+ double m_fValueMaximum; /// Maximum of all source values.
+ sal_Int32 m_nMaximumAutoMainIncrementCount; /// Maximum number of automatic main increments.
+ bool m_bExpandBorderToIncrementRhythm; /// true = Expand to main increments.
+ bool m_bExpandIfValuesCloseToBorder; /// true = Expand if values are too close to the borders.
+ bool m_bExpandWideValuesToZero; /// true = Expand wide spread values to zero.
+ bool m_bExpandNarrowValuesTowardZero; /// true = Expand narrow range toward zero (add half of range).
+};
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
+#endif
diff --git a/chart2/source/view/inc/ShapeFactory.hxx b/chart2/source/view/inc/ShapeFactory.hxx
new file mode 100644
index 000000000000..ef75f3a323af
--- /dev/null
+++ b/chart2/source/view/inc/ShapeFactory.hxx
@@ -0,0 +1,254 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _CHART2_VIEW_SHAPEFACTORY_HXX
+#define _CHART2_VIEW_SHAPEFACTORY_HXX
+
+#include "PropertyMapper.hxx"
+#include "VLineProperties.hxx"
+#include "BaseGFXHelper.hxx"
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/drawing/Direction3D.hpp>
+#include <com/sun/star/drawing/HomogenMatrix.hpp>
+#include <com/sun/star/drawing/PointSequenceSequence.hpp>
+#include <com/sun/star/drawing/PolyPolygonShape3D.hpp>
+#include <com/sun/star/drawing/Position3D.hpp>
+#include <com/sun/star/drawing/XDrawPage.hpp>
+#include <com/sun/star/drawing/XShapes.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/graphic/XGraphic.hpp>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+
+class Stripe;
+class ShapeFactory
+{
+public:
+ ShapeFactory(::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory> xFactory)
+ {m_xShapeFactory = xFactory;}
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >
+ createGroup2D(
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShapes >& xTarget
+ , ::rtl::OUString aName = ::rtl::OUString() );
+
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >
+ createGroup3D(
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShapes >& xTarget
+ , ::rtl::OUString aName = ::rtl::OUString() );
+
+ //------
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >
+ createCube( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShapes >& xTarget
+ , const ::com::sun::star::drawing::Position3D& rPosition
+ , const ::com::sun::star::drawing::Direction3D& rSize
+ , sal_Int32 nRotateZAngleHundredthDegree
+ , const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& xSourceProp
+ , const tPropertyNameMap& rPropertyNameMap
+ , bool bRounded = false);
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >
+ createCylinder( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShapes >& xTarget
+ , const ::com::sun::star::drawing::Position3D& rPosition
+ , const ::com::sun::star::drawing::Direction3D& rSize
+ , sal_Int32 nRotateZAngleHundredthDegree );
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >
+ createPyramid( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShapes >& xTarget
+ , const ::com::sun::star::drawing::Position3D& rPosition
+ , const ::com::sun::star::drawing::Direction3D& rSize
+ , double fTopHeight
+ , bool bRotateZ
+ , const ::com::sun::star::uno::Reference<
+ ::com::sun::star::beans::XPropertySet >& xSourceProp
+ , const tPropertyNameMap& rPropertyNameMap);
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >
+ createCone( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShapes >& xTarget
+ , const ::com::sun::star::drawing::Position3D& rPosition
+ , const ::com::sun::star::drawing::Direction3D& rSize
+ , double fTopHeight, sal_Int32 nRotateZAngleHundredthDegree );
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >
+ createPieSegment2D( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& xTarget
+ , double fUnitCircleStartAngleDegree, double fUnitCircleWidthAngleDegree
+ , double fUnitCircleInnerRadius, double fUnitCircleOuterRadius
+ , const ::com::sun::star::drawing::Direction3D& rOffset
+ , const ::com::sun::star::drawing::HomogenMatrix& rUnitCircleToScene );
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >
+ createPieSegment( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& xTarget
+ , double fUnitCircleStartAngleDegree, double fUnitCircleWidthAngleDegree
+ , double fUnitCircleInnerRadius, double fUnitCircleOuterRadius
+ , const ::com::sun::star::drawing::Direction3D& rOffset
+ , const ::com::sun::star::drawing::HomogenMatrix& rUnitCircleToScene
+ , double fDepth );
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >
+ createStripe( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& xTarget
+ , const Stripe& rStripe
+ , const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& xSourceProp
+ , const tPropertyNameMap& rPropertyNameMap
+ , sal_Bool bDoubleSided = true
+ , short nRotatedTexture = 0 //0 to 7 are the different possibilities
+ , bool bFlatNormals=true );
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >
+ createArea3D( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& xTarget
+ , const ::com::sun::star::drawing::PolyPolygonShape3D& rPolyPolygon
+ , double fDepth);
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >
+ createArea2D( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& xTarget
+ , const ::com::sun::star::drawing::PolyPolygonShape3D& rPolyPolygon);
+
+ static sal_Int32 getSymbolCount();
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >
+ createSymbol2D( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& xTarget
+ , const ::com::sun::star::drawing::Position3D& rPos
+ , const ::com::sun::star::drawing::Direction3D& rSize
+ , sal_Int32 nStandardSymbol
+ , sal_Int32 nBorderColor=0
+ , sal_Int32 nFillColor=0 );
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >
+ createGraphic2D( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& xTarget
+ , const ::com::sun::star::drawing::Position3D& rPos
+ , const ::com::sun::star::drawing::Direction3D& rSize
+ , const ::com::sun::star::uno::Reference< ::com::sun::star::graphic::XGraphic >& xGraphic );
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >
+ createLine2D( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& xTarget
+ , const ::com::sun::star::drawing::PointSequenceSequence& rPoints
+ , const VLineProperties* pLineProperties = NULL );
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >
+ createLine3D( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& xTarget
+ , const ::com::sun::star::drawing::PolyPolygonShape3D& rPoints
+ , const VLineProperties& rLineProperties );
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >
+ createCircle2D( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& xTarget
+ , const ::com::sun::star::drawing::Position3D& rPos
+ , const ::com::sun::star::drawing::Direction3D& rSize );
+
+ //------------------- create 2D elements:
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >
+ createText( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& xTarget2D
+ , const ::rtl::OUString& rText
+ , const tNameSequence& rPropNames
+ , const tAnySequence& rPropValues
+ , const ::com::sun::star::uno::Any& rATransformation
+ );
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >
+ createInvisibleRectangle(
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShapes >& xTarget
+ , const ::com::sun::star::awt::Size& rSize );
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >
+ getOrCreateChartRootShape( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XDrawPage>& xPage );
+
+ static ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >
+ getChartRootShape( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XDrawPage>& xPage );
+
+ //------
+ static void makeShapeInvisible( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShape >& xShape );
+
+ static void setShapeName( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShape >& xShape
+ , const rtl::OUString& rName );
+
+ static rtl::OUString getShapeName( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShape >& xShape );
+
+ static ::com::sun::star::uno::Any makeTransformation( const ::com::sun::star::awt::Point& rScreenPosition2D, double fRotationAnglePi=0.0 );
+
+ static rtl::OUString getStackedString( const rtl::OUString& rString, bool bStacked=true );
+
+ static bool hasPolygonAnyLines( ::com::sun::star::drawing::PolyPolygonShape3D& rPoly );
+ static bool isPolygonEmptyOrSinglePoint( ::com::sun::star::drawing::PolyPolygonShape3D& rPoly );
+ static void closePolygon( ::com::sun::star::drawing::PolyPolygonShape3D& rPoly );
+
+ static ::com::sun::star::awt::Size calculateNewSizeRespectingAspectRatio(
+ const ::com::sun::star::awt::Size& rTargetSize
+ , const ::com::sun::star::awt::Size& rSourceSizeWithCorrectAspectRatio );
+
+ static ::com::sun::star::awt::Point calculateTopLeftPositionToCenterObject(
+ const ::com::sun::star::awt::Point& rTargetAreaPosition
+ , const ::com::sun::star::awt::Size& rTargetAreaSize
+ , const ::com::sun::star::awt::Size& rObjectSize );
+
+ static ::basegfx::B2IRectangle getRectangleOfShape(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >& xShape );
+
+ static ::com::sun::star::awt::Size getSizeAfterRotation(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >& xShape, double fRotationAngleDegree );
+
+ static void removeSubShapes( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& xShapes );
+
+private:
+ ShapeFactory();
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >
+ impl_createCube( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& xTarget
+ , const ::com::sun::star::drawing::Position3D& rPosition
+ , const ::com::sun::star::drawing::Direction3D& rSize, sal_Int32 nRotateZAngleHundredthDegree
+ , bool bRounded );
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >
+ impl_createConeOrCylinder( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& xTarget
+ , const ::com::sun::star::drawing::Position3D& rPosition
+ , const ::com::sun::star::drawing::Direction3D& rSize
+ , double fTopHeight, sal_Int32 nRotateZAngleHundredthDegree
+ , bool bCylinder = false);
+
+ //member:
+ ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>
+ m_xShapeFactory;
+};
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
+#endif
diff --git a/chart2/source/view/inc/Stripe.hxx b/chart2/source/view/inc/Stripe.hxx
new file mode 100644
index 000000000000..ca1aaf155d1e
--- /dev/null
+++ b/chart2/source/view/inc/Stripe.hxx
@@ -0,0 +1,89 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _CHART_STRIPE_HXX
+#define _CHART_STRIPE_HXX
+
+#include <com/sun/star/drawing/Position3D.hpp>
+#include <com/sun/star/drawing/Direction3D.hpp>
+#include <com/sun/star/uno/Any.h>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+
+//-----------------------------------------------------------------------------
+/** A Stripe represents a 2 dimensional foursquare plane in a 3 dimaensional room.
+
+@todo could: it is not necessary to have 4 point members here; it would be sufficient to have one point and 2 directions
+*/
+
+class Stripe
+{
+public:
+ Stripe( const ::com::sun::star::drawing::Position3D& rPoint1
+ , const ::com::sun::star::drawing::Direction3D& rDirectionToPoint2
+ , const ::com::sun::star::drawing::Direction3D& rDirectionToPoint4 );
+
+ Stripe( const ::com::sun::star::drawing::Position3D& rPoint1
+ , const ::com::sun::star::drawing::Position3D& rPoint2
+ , double fDepth );
+
+ Stripe( const ::com::sun::star::drawing::Position3D& rPoint1
+ , const ::com::sun::star::drawing::Position3D& rPoint2
+ , const ::com::sun::star::drawing::Position3D& rPoint3
+ , const ::com::sun::star::drawing::Position3D& rPoint4 );
+
+ void SetManualNormal( const ::com::sun::star::drawing::Direction3D& rNormal );
+ ::com::sun::star::drawing::Direction3D getNormal() const;
+
+ void InvertNormal( bool bInvertNormal );
+
+ ::com::sun::star::uno::Any getPolyPolygonShape3D() const;
+ ::com::sun::star::uno::Any getNormalsPolygon() const;
+ ::com::sun::star::uno::Any getTexturePolygon( short nRotatedTexture ) const; //0 to 7 are the different possibilities
+
+ ::com::sun::star::drawing::Position3D GetPosition1() const { return m_aPoint1; }
+ ::com::sun::star::drawing::Position3D GetPosition2() const { return m_aPoint2; }
+ ::com::sun::star::drawing::Position3D GetPosition3() const { return m_aPoint3; }
+ ::com::sun::star::drawing::Position3D GetPosition4() const { return m_aPoint4; }
+
+private:
+ ::com::sun::star::drawing::Position3D m_aPoint1;
+ ::com::sun::star::drawing::Position3D m_aPoint2;
+ ::com::sun::star::drawing::Position3D m_aPoint3;
+ ::com::sun::star::drawing::Position3D m_aPoint4;
+
+ bool m_bInvertNormal;
+ bool m_bManualNormalSet;
+ ::com::sun::star::drawing::Direction3D m_aManualNormal;
+};
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
+#endif
diff --git a/chart2/source/view/inc/VCoordinateSystem.hxx b/chart2/source/view/inc/VCoordinateSystem.hxx
new file mode 100644
index 000000000000..e884af865d6e
--- /dev/null
+++ b/chart2/source/view/inc/VCoordinateSystem.hxx
@@ -0,0 +1,212 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _CHART2_VCOORDINATESYSTEM_HXX
+#define _CHART2_VCOORDINATESYSTEM_HXX
+
+#include "MinimumAndMaximumSupplier.hxx"
+#include "ScaleAutomatism.hxx"
+#include "ThreeDHelper.hxx"
+#include "ExplicitCategoriesProvider.hxx"
+
+#include <com/sun/star/chart2/ExplicitIncrementData.hpp>
+#include <com/sun/star/chart2/ExplicitScaleData.hpp>
+#include <com/sun/star/chart2/XCoordinateSystem.hpp>
+#include "comphelper/implementationreference.hxx"
+#include <com/sun/star/awt/Rectangle.hpp>
+#include <com/sun/star/drawing/HomogenMatrix.hpp>
+#include <com/sun/star/drawing/XShapes.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/util/XNumberFormatsSupplier.hpp>
+
+#include<map>
+#include <vector>
+#include <boost/shared_ptr.hpp>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+
+//-----------------------------------------------------------------------------
+/**
+*/
+class VAxisBase;
+class VCoordinateSystem
+{
+public:
+ virtual ~VCoordinateSystem();
+
+ static VCoordinateSystem* createCoordinateSystem( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::chart2::XCoordinateSystem >& xCooSysModel );
+
+ virtual void SAL_CALL initPlottingTargets(
+ 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
+ , ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShapes >& xLogicTargetForSeriesBehindAxis )
+ throw (::com::sun::star::uno::RuntimeException);
+
+ void setParticle( const rtl::OUString& rCooSysParticle );
+
+ virtual void setTransformationSceneToScreen( const ::com::sun::star::drawing::HomogenMatrix& rMatrix );
+ ::com::sun::star::drawing::HomogenMatrix getTransformationSceneToScreen();
+
+ //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 );
+
+ ::com::sun::star::chart2::ExplicitScaleData getExplicitScale( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) const;
+ ::com::sun::star::chart2::ExplicitIncrementData getExplicitIncrement( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) const;
+
+ void setExplicitCategoriesProvider( ExplicitCategoriesProvider* /*takes ownership*/ );
+ ExplicitCategoriesProvider* getExplicitCategoriesProvider();
+
+ // returns a coplete scale set for a given dimension and index; for example if nDimensionIndex==1 and nAxisIndex==2 you get returned the secondary x axis, main y axis and main z axis
+ ::com::sun::star::uno::Sequence< ::com::sun::star::chart2::ExplicitScaleData > getExplicitScales( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) const;
+ // returns a coplete increment set for a given dimension and index; for example if nDimensionIndex==1 and nAxisIndex==2 you get returned the secondary x axis, main y axis and main z axis
+ ::com::sun::star::uno::Sequence< ::com::sun::star::chart2::ExplicitIncrementData > getExplicitIncrements( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) const;
+
+ void addMinimumAndMaximumSupplier( MinimumAndMaximumSupplier* pMinimumAndMaximumSupplier );
+ bool hasMinimumAndMaximumSupplier( MinimumAndMaximumSupplier* pMinimumAndMaximumSupplier );
+ void clearMinimumAndMaximumSupplierList();
+
+ void prepareScaleAutomatismForDimensionAndIndex( ScaleAutomatism& rScaleAutomatism, sal_Int32 nDimIndex, sal_Int32 nAxisIndex );
+
+ void setExplicitScaleAndIncrement( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex
+ , const ::com::sun::star::chart2::ExplicitScaleData& rExplicitScale
+ , const ::com::sun::star::chart2::ExplicitIncrementData& rExplicitIncrement );
+
+ void set3DWallPositions( CuboidPlanePosition eLeftWallPos, CuboidPlanePosition eBackWallPos, CuboidPlanePosition eBottomPos );
+
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::chart2::XCoordinateSystem >
+ getModel() const;
+
+ 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 createMaximumAxesLabels();
+ virtual void createAxesLabels();
+ virtual void updatePositions();
+ virtual void createAxesShapes();
+
+ virtual void createGridShapes();
+
+ virtual bool getPropertySwapXAndYAxis() const;
+
+ sal_Int32 getMaximumAxisIndexByDimension( sal_Int32 nDimensionIndex ) const;
+
+ virtual bool needSeriesNamesForAxis() const;
+ void setSeriesNamesForAxis( const ::com::sun::star::uno::Sequence< rtl::OUString >& rSeriesNames );
+
+protected: //methods
+ VCoordinateSystem( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::chart2::XCoordinateSystem >& xCooSys );
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XAxis >
+ getAxisByDimension( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) const;
+ ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > >
+ getGridListFromAxis( const ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XAxis >& xAxis );
+
+ VAxisBase* getVAxis( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex );
+
+ void prepareScaleAutomatism( ScaleAutomatism& rScaleAutomatism, double fMin, double fMax, sal_Int32 nDimIndex, sal_Int32 nAxisIndex );
+
+ rtl::OUString createCIDForAxis( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::chart2::XAxis >& xAxis
+ , sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex );
+ rtl::OUString createCIDForGrid( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::chart2::XAxis >& xAxis
+ , sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex );
+
+ sal_Int32 getNumberFormatKeyForAxis( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::chart2::XAxis >& xAxis
+ , const ::com::sun::star::uno::Reference<
+ ::com::sun::star::util::XNumberFormatsSupplier >& xNumberFormatsSupplier );
+
+private: //methods
+ void impl_adjustDimension( sal_Int32& rDimensionIndex ) const;
+ void impl_adjustDimensionAndIndex( sal_Int32& rDimensionIndex, sal_Int32& rAxisIndex ) const;
+
+protected: //member
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::chart2::XCoordinateSystem > m_xCooSysModel;
+
+ rtl::OUString m_aCooSysParticle;
+
+ typedef std::pair< sal_Int32, sal_Int32 > tFullAxisIndex; //first index is the dimension, second index is the axis index that indicates wether this is a main or secondary axis
+
+ //
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShapes > m_xLogicTargetForGrids;
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShapes > m_xLogicTargetForAxes;
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShapes > m_xFinalTarget;
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::lang::XMultiServiceFactory> m_xShapeFactory;
+ ::com::sun::star::drawing::HomogenMatrix m_aMatrixSceneToScreen;
+
+ CuboidPlanePosition m_eLeftWallPos;
+ CuboidPlanePosition m_eBackWallPos;
+ CuboidPlanePosition m_eBottomPos;
+
+ //
+ MergedMinimumAndMaximumSupplier m_aMergedMinimumAndMaximumSupplier; //this is used only for autoscaling purpose
+
+ ::com::sun::star::uno::Sequence< rtl::OUString > m_aSeriesNamesForZAxis;
+
+ typedef std::map< tFullAxisIndex, ::boost::shared_ptr< VAxisBase > > tVAxisMap;
+
+ tVAxisMap m_aAxisMap;
+
+private:
+ ::com::sun::star::uno::Sequence< ::com::sun::star::chart2::ExplicitScaleData > m_aExplicitScales;
+ ::com::sun::star::uno::Sequence< ::com::sun::star::chart2::ExplicitIncrementData > m_aExplicitIncrements;
+
+ typedef std::map< tFullAxisIndex, ::com::sun::star::chart2::ExplicitScaleData > tFullExplicitScaleMap;
+ typedef std::map< tFullAxisIndex, ::com::sun::star::chart2::ExplicitIncrementData > tFullExplicitIncrementMap;
+
+ tFullExplicitScaleMap m_aSecondaryExplicitScales;
+ tFullExplicitIncrementMap m_aSecondaryExplicitIncrements;
+
+ ::std::auto_ptr< ExplicitCategoriesProvider > m_apExplicitCategoriesProvider;
+};
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
+#endif
diff --git a/chart2/source/view/inc/VDataSeries.hxx b/chart2/source/view/inc/VDataSeries.hxx
new file mode 100644
index 000000000000..93aba58dbec4
--- /dev/null
+++ b/chart2/source/view/inc/VDataSeries.hxx
@@ -0,0 +1,264 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _CHART2_VIEW_DATASERIES_HXX
+#define _CHART2_VIEW_DATASERIES_HXX
+
+#include "PropertyMapper.hxx"
+
+#include <vector>
+//for auto_ptr
+#include <memory>
+#include <com/sun/star/chart2/DataPointLabel.hpp>
+#include <com/sun/star/chart2/Symbol.hpp>
+#include <com/sun/star/chart2/StackingDirection.hpp>
+#include <com/sun/star/chart2/data/XLabeledDataSequence.hpp>
+#include <com/sun/star/chart2/XChartType.hpp>
+#include <com/sun/star/chart2/XDataSeries.hpp>
+#include <com/sun/star/drawing/HomogenMatrix.hpp>
+#include <com/sun/star/drawing/PolyPolygonShape3D.hpp>
+#include <com/sun/star/drawing/XShape.hpp>
+#include <com/sun/star/drawing/XShapes.hpp>
+#include <cppuhelper/weakref.hxx>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+
+//-----------------------------------------------------------------------------
+/**
+*/
+class VDataSequence
+{
+public:
+ void init( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::chart2::data::XDataSequence >& xModel );
+ bool is() const;
+ void clear();
+ double getValue( sal_Int32 index ) const;
+ sal_Int32 detectNumberFormatKey( sal_Int32 index ) const;
+ sal_Int32 getLength() const;
+
+
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::chart2::data::XDataSequence > Model;
+
+ mutable ::com::sun::star::uno::Sequence< double > Doubles;
+};
+
+class VDataSeries
+{
+public:
+ VDataSeries( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::chart2::XDataSeries >& xDataSeries );
+ virtual ~VDataSeries();
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XDataSeries >
+ getModel() const;
+
+ void setCategoryXAxis();
+ void setParticle( const rtl::OUString& rSeriesParticle );
+ void setGlobalSeriesIndex( sal_Int32 nGlobalSeriesIndex );
+ void setPageReferenceSize( const ::com::sun::star::awt::Size & rPageRefSize );
+
+ sal_Int32 getTotalPointCount() const;
+ double getXValue( sal_Int32 index ) const;
+ double getYValue( sal_Int32 index ) const;
+
+ double getY_Min( sal_Int32 index ) const;
+ double getY_Max( sal_Int32 index ) const;
+ double getY_First( sal_Int32 index ) const;
+ double getY_Last( sal_Int32 index ) const;
+
+ double getBubble_Size( sal_Int32 index ) const;
+
+ double getMinimumofAllDifferentYValues( sal_Int32 index ) const;
+ double getMaximumofAllDifferentYValues( sal_Int32 index ) const;
+
+ ::com::sun::star::uno::Sequence< double > getAllX() const;
+ ::com::sun::star::uno::Sequence< double > getAllY() const;
+
+ double getYMeanValue() const;
+
+ bool hasExplicitNumberFormat( sal_Int32 nPointIndex, bool bForPercentage ) const;
+ sal_Int32 getExplicitNumberFormat( sal_Int32 nPointIndex, bool bForPercentage ) const;
+ sal_Int32 detectNumberFormatKey( sal_Int32 nPointIndex ) const;
+ bool shouldLabelNumberFormatKeyBeDetectedFromYAxis() const;
+
+ sal_Int32 getLabelPlacement( sal_Int32 nPointIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XChartType >& xChartType
+ , sal_Int32 nDimensionCount, sal_Bool bSwapXAndY ) const;
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >
+ getPropertiesOfPoint( sal_Int32 index ) const;
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >
+ getPropertiesOfSeries() const;
+
+ ::com::sun::star::chart2::Symbol*
+ getSymbolProperties( sal_Int32 index ) const;
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >
+ getYErrorBarProperties( sal_Int32 index ) const;
+
+ bool hasPointOwnColor( sal_Int32 index ) const;
+
+ ::com::sun::star::chart2::StackingDirection getStackingDirection() const;
+ sal_Int32 getAttachedAxisIndex() const;
+ void setAttachedAxisIndex( sal_Int32 nAttachedAxisIndex );
+
+ void doSortByXValues();
+
+ void setConnectBars( sal_Bool bConnectBars );
+ sal_Bool getConnectBars() const;
+
+ void setGroupBarsPerAxis( sal_Bool bGroupBarsPerAxis );
+ sal_Bool getGroupBarsPerAxis() const;
+
+ void setStartingAngle( sal_Int32 nStartingAngle );
+ sal_Int32 getStartingAngle() const;
+
+ void setRoleOfSequenceForDataLabelNumberFormatDetection( const rtl::OUString& rRole );
+
+ //this is only temporarily here for area chart:
+ ::com::sun::star::drawing::PolyPolygonShape3D m_aPolyPolygonShape3D;
+ sal_Int32 m_nPolygonIndex;
+ double m_fLogicMinX;
+ double m_fLogicMaxX;
+ //
+ //this is here for deep stacking:
+ double m_fLogicZPos;//from 0 to series count -1
+ //
+
+ rtl::OUString getCID() const;
+ rtl::OUString getSeriesParticle() const;
+ rtl::OUString getPointCID_Stub() const;
+ rtl::OUString getErrorBarsCID() const;
+ rtl::OUString getLabelsCID() const;
+ rtl::OUString getLabelCID_Stub() const;
+ rtl::OUString getDataCurveCID( sal_Int32 nCurveIndex, bool bAverageLine ) const;
+
+ ::com::sun::star::chart2::DataPointLabel*
+ getDataPointLabelIfLabel( sal_Int32 index ) const;
+ bool getTextLabelMultiPropertyLists( sal_Int32 index, tNameSequence*& pPropNames, tAnySequence*& pPropValues ) const;
+
+ rtl::OUString getDataCurveEquationCID( sal_Int32 nCurveIndex ) const;
+ bool isAttributedDataPoint( sal_Int32 index ) const;
+
+ bool isVaryColorsByPoint() const;
+
+ void releaseShapes();
+
+ void setMissingValueTreatment( sal_Int32 nMissingValueTreatment );
+ sal_Int32 getMissingValueTreatment() const;
+
+private: //methods
+ ::com::sun::star::chart2::DataPointLabel*
+ getDataPointLabel( sal_Int32 index ) const;
+ void adaptPointCache( sal_Int32 nNewPointIndex ) const;
+
+public: //member
+ ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes > m_xGroupShape;
+ ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes > m_xLabelsGroupShape;
+ ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes > m_xErrorBarsGroupShape;
+
+ //the following group shapes will be created as children of m_xGroupShape on demand
+ //they can be used to assure that some parts of a series shape are always in front of others (e.g. symbols in front of lines)
+ ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes > m_xFrontSubGroupShape;
+ ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes > m_xBackSubGroupShape;
+
+private: //member
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::chart2::XDataSeries > m_xDataSeries;
+ ::com::sun::star::uno::Sequence<
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::chart2::data::XLabeledDataSequence > > m_aDataSequences;
+
+ //all points given by the model data (here are not only the visible points meant)
+ sal_Int32 m_nPointCount;
+
+ VDataSequence m_aValues_X;
+ VDataSequence m_aValues_Y;
+ VDataSequence m_aValues_Z;
+
+ VDataSequence m_aValues_Y_Min;
+ VDataSequence m_aValues_Y_Max;
+ VDataSequence m_aValues_Y_First;
+ VDataSequence m_aValues_Y_Last;
+
+ VDataSequence m_aValues_Bubble_Size;
+
+ VDataSequence* m_pValueSequenceForDataLabelNumberFormatDetection;
+
+ mutable double m_fYMeanValue;
+
+ ::com::sun::star::uno::Sequence< sal_Int32 > m_aAttributedDataPointIndexList;
+
+ ::com::sun::star::chart2::StackingDirection m_eStackingDirection;
+
+ sal_Int32 m_nAxisIndex;//indicates wether this is attached to a main or secondary axis
+
+ sal_Bool m_bConnectBars;
+
+ sal_Bool m_bGroupBarsPerAxis;
+
+ sal_Int32 m_nStartingAngle;
+
+ rtl::OUString m_aSeriesParticle;
+ rtl::OUString m_aCID;
+ rtl::OUString m_aPointCID_Stub;
+ rtl::OUString m_aLabelCID_Stub;
+
+ sal_Int32 m_nGlobalSeriesIndex;
+
+ //some cached values for data labels as they are very expensive
+ mutable ::std::auto_ptr< ::com::sun::star::chart2::DataPointLabel >
+ m_apLabel_Series;
+ mutable ::std::auto_ptr< tNameSequence > m_apLabelPropNames_Series;
+ mutable ::std::auto_ptr< tAnySequence > m_apLabelPropValues_Series;
+ mutable ::std::auto_ptr< ::com::sun::star::chart2::Symbol >
+ m_apSymbolProperties_Series;
+
+ mutable ::std::auto_ptr< ::com::sun::star::chart2::DataPointLabel >
+ m_apLabel_AttributedPoint;
+ mutable ::std::auto_ptr< tNameSequence > m_apLabelPropNames_AttributedPoint;
+ mutable ::std::auto_ptr< tAnySequence > m_apLabelPropValues_AttributedPoint;
+ mutable ::std::auto_ptr< ::com::sun::star::chart2::Symbol >
+ m_apSymbolProperties_AttributedPoint;
+ mutable ::std::auto_ptr< ::com::sun::star::chart2::Symbol >
+ m_apSymbolProperties_InvisibleSymbolForSelection;
+ mutable sal_Int32 m_nCurrentAttributedPoint;
+ ::com::sun::star::awt::Size m_aReferenceSize;
+ //
+
+ sal_Int32 m_nMissingValueTreatment;
+ bool m_bAllowPercentValueInDataLabel;
+};
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
+#endif
diff --git a/chart2/source/view/inc/VDiagram.hxx b/chart2/source/view/inc/VDiagram.hxx
new file mode 100644
index 000000000000..5df198c2f539
--- /dev/null
+++ b/chart2/source/view/inc/VDiagram.hxx
@@ -0,0 +1,136 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _CHART2_VDIAGRAM_HXX
+#define _CHART2_VDIAGRAM_HXX
+
+#include <com/sun/star/drawing/HomogenMatrix.hpp>
+#include <com/sun/star/drawing/XShapes.hpp>
+#include <com/sun/star/chart2/XDiagram.hpp>
+#include "ShapeFactory.hxx"
+#include <basegfx/range/b2irectangle.hxx>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+
+class ShapeFactory;
+
+//-----------------------------------------------------------------------------
+/** The VDiagram is responsible to generate the visible parts of the Diagram
+that is wall, floor, axes and data series.
+The axes and data series are subobjects which are created and managed by the
+diagram.
+*/
+
+class VDiagram
+{
+public: //methods
+ VDiagram( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::chart2::XDiagram > & xDiagram
+ , const ::com::sun::star::drawing::Direction3D& rPreferredAspectRatio
+ , sal_Int32 nDimension=3, sal_Bool bPolar=sal_False );
+ virtual ~VDiagram();
+
+ void SAL_CALL init( 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);
+
+ void createShapes( const ::com::sun::star::awt::Point& rPos
+ , const ::com::sun::star::awt::Size& rSize );
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >
+ getCoordinateRegion();
+
+ ::basegfx::B2IRectangle getCurrentRectangle();
+
+ void reduceToMimimumSize();
+
+ ::basegfx::B2IRectangle adjustPosAndSize( const ::com::sun::star::awt::Point& rPos
+ , const ::com::sun::star::awt::Size& rAvailableSize );
+
+ ::basegfx::B2IRectangle adjustInnerSize( const ::basegfx::B2IRectangle& rConsumedOuterRect );
+
+ // updateShapes(..);
+ // const awt::Point& rPos, const awt::Size& rSize );
+
+private: //methods
+ void createShapes_2d();
+ void createShapes_3d();
+
+ ::basegfx::B2IRectangle adjustPosAndSize_2d( const ::com::sun::star::awt::Point& rPos
+ , const ::com::sun::star::awt::Size& rAvailableSize );
+ ::basegfx::B2IRectangle adjustPosAndSize_3d( const ::com::sun::star::awt::Point& rPos
+ , const ::com::sun::star::awt::Size& rAvailableSize );
+
+ void adjustAspectRatio3d( const ::com::sun::star::awt::Size& rAvailableSize );
+
+private: //members
+ VDiagram(const VDiagram& rD);
+
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShapes > m_xLogicTarget;
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShapes > m_xFinalTarget;
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::lang::XMultiServiceFactory> m_xShapeFactory;
+ ShapeFactory* m_pShapeFactory;
+
+ // this is the surrounding shape which contains floor, wall and coordinate
+ ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > m_xOuterGroupShape;
+ // this is an additional inner shape that represents the coordinate region - that is - where to place data points
+ ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > m_xCoordinateRegionShape;
+ ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > m_xWall2D;
+
+ sal_Int32 m_nDimensionCount;
+ sal_Bool m_bPolar;
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::chart2::XDiagram > m_xDiagram;
+
+ ::com::sun::star::drawing::Direction3D m_aPreferredAspectRatio;
+ ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > m_xAspectRatio3D;
+
+ double m_fXAnglePi;
+ double m_fYAnglePi;
+ double m_fZAnglePi;
+ sal_Bool m_bRightAngledAxes;
+
+ ::com::sun::star::awt::Point m_aAvailablePosIncludingAxes;
+ ::com::sun::star::awt::Size m_aAvailableSizeIncludingAxes;
+
+ ::com::sun::star::awt::Point m_aCurrentPosWithoutAxes;
+ ::com::sun::star::awt::Size m_aCurrentSizeWithoutAxes;
+};
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
+#endif
+
+
diff --git a/chart2/source/view/inc/VLegendSymbolFactory.hxx b/chart2/source/view/inc/VLegendSymbolFactory.hxx
new file mode 100644
index 000000000000..a568a9ef4a85
--- /dev/null
+++ b/chart2/source/view/inc/VLegendSymbolFactory.hxx
@@ -0,0 +1,77 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef CHART2_VLEGENDSYMBOLFACTORY_HXX
+#define CHART2_VLEGENDSYMBOLFACTORY_HXX
+
+#include <com/sun/star/chart2/LegendSymbolStyle.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/drawing/XShapes.hpp>
+
+namespace chart
+{
+
+class VLegendSymbolFactory
+{
+public:
+ enum tPropertyType
+ {
+ PROP_TYPE_FILLED_SERIES,
+ PROP_TYPE_LINE_SERIES,
+ PROP_TYPE_FILL,
+ PROP_TYPE_LINE,
+ PROP_TYPE_FILL_AND_LINE
+ };
+
+ static ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShape >
+ createSymbol(
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShapes > xSymbolContainer,
+ ::com::sun::star::chart2::LegendSymbolStyle eStyle,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::lang::XMultiServiceFactory > & xShapeFactory,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::beans::XPropertySet > & xLegendEntryProperties,
+ tPropertyType ePropertyType,
+ const ::com::sun::star::uno::Any& rExplicitSymbol /*should contain a ::com::sun::star::chart2::Symbol without automatic symbol if the charttype does support symbols else empty*/);
+
+ enum tStockLineType
+ {
+ STOCK_LINE_TYPE_VERT,
+ STOCK_LINE_TYPE_OPEN,
+ STOCK_LINE_TYPE_CLOSE
+ };
+
+private:
+ VLegendSymbolFactory();
+};
+
+} // namespace chart
+
+// CHART2_VLEGENDSYMBOLFACTORY_HXX
+#endif
diff --git a/chart2/source/view/inc/VLineProperties.hxx b/chart2/source/view/inc/VLineProperties.hxx
new file mode 100644
index 000000000000..f6ec92d38cf8
--- /dev/null
+++ b/chart2/source/view/inc/VLineProperties.hxx
@@ -0,0 +1,61 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CHART2_VLINEPROPERTIES_HXX
+#define _CHART2_VLINEPROPERTIES_HXX
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+
+//-----------------------------------------------------------------------------
+/**
+*/
+
+struct VLineProperties
+{
+ com::sun::star::uno::Any Color; //type sal_Int32 UNO_NAME_LINECOLOR
+ com::sun::star::uno::Any LineStyle; //type drawing::LineStyle for property UNO_NAME_LINESTYLE
+ com::sun::star::uno::Any Transparence;//type sal_Int16 for property UNO_NAME_LINETRANSPARENCE
+ com::sun::star::uno::Any Width;//type sal_Int32 for property UNO_NAME_LINEWIDTH
+ com::sun::star::uno::Any DashName;//type OUString for property "LineDashName"
+
+ VLineProperties();
+ void initFromPropertySet( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::beans::XPropertySet >& xProp
+ , bool bUseSeriesPropertyNames=false );
+
+ bool isLineVisible() const;
+};
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
+#endif
diff --git a/chart2/source/view/inc/VPolarTransformation.hxx b/chart2/source/view/inc/VPolarTransformation.hxx
new file mode 100644
index 000000000000..f3da18ac92b6
--- /dev/null
+++ b/chart2/source/view/inc/VPolarTransformation.hxx
@@ -0,0 +1,67 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _CHART_VPOLARTRANSFORMATION_HXX
+#define _CHART_VPOLARTRANSFORMATION_HXX
+
+#include "PlottingPositionHelper.hxx"
+#include <cppuhelper/implbase1.hxx>
+#include <com/sun/star/chart2/XTransformation.hpp>
+
+namespace chart
+{
+
+class VPolarTransformation : public ::cppu::WeakImplHelper1<
+ ::com::sun::star::chart2::XTransformation
+ >
+{
+public:
+ VPolarTransformation( const PolarPlottingPositionHelper& rPositionHelper );
+ virtual ~VPolarTransformation();
+
+ // ____ XTransformation ____
+ /// @see ::com::sun::star::chart2::XTransformation
+ virtual ::com::sun::star::uno::Sequence< double > SAL_CALL transform(
+ const ::com::sun::star::uno::Sequence< double >& rSourceValues )
+ throw (::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException);
+ /// @see ::com::sun::star::chart2::XTransformation
+ virtual sal_Int32 SAL_CALL getSourceDimension()
+ throw (::com::sun::star::uno::RuntimeException);
+ /// @see ::com::sun::star::chart2::XTransformation
+ virtual sal_Int32 SAL_CALL getTargetDimension()
+ throw (::com::sun::star::uno::RuntimeException);
+
+private:
+ PolarPlottingPositionHelper m_aPositionHelper;
+ ::basegfx::B3DHomMatrix m_aUnitCartesianToScene;
+};
+
+} // namespace chart
+
+// _CHART_VPOLARTRANSFORMATION_HXX
+#endif
+
diff --git a/chart2/source/view/inc/VSeriesPlotter.hxx b/chart2/source/view/inc/VSeriesPlotter.hxx
new file mode 100644
index 000000000000..6b6b06437542
--- /dev/null
+++ b/chart2/source/view/inc/VSeriesPlotter.hxx
@@ -0,0 +1,453 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _CHART2_VSERIESPLOTTER_HXX
+#define _CHART2_VSERIESPLOTTER_HXX
+
+#include "PlotterBase.hxx"
+#include "VDataSeries.hxx"
+#include "LabelAlignment.hxx"
+#include "MinimumAndMaximumSupplier.hxx"
+#include "LegendEntryProvider.hxx"
+#include "ExplicitCategoriesProvider.hxx"
+#include <com/sun/star/chart2/LegendSymbolStyle.hpp>
+#include <com/sun/star/chart2/XChartType.hpp>
+#include <com/sun/star/drawing/Direction3D.hpp>
+
+
+namespace com { namespace sun { namespace star {
+ namespace util {
+ class XNumberFormatsSupplier;
+ }
+ namespace chart2 {
+ class XColorScheme;
+ class XRegressionCurveCalculator;
+ }
+}}}
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+
+class NumberFormatterWrapper;
+
+class AxesNumberFormats
+{
+public:
+ AxesNumberFormats() {};
+
+ void setFormat( sal_Int32 nFormatKey, sal_Int32 nDimIndex, sal_Int32 nAxisIndex )
+ {
+ m_aNumberFormatMap[tFullAxisIndex(nDimIndex,nAxisIndex)] = nFormatKey;
+ }
+ sal_Int32 hasFormat( sal_Int32 nDimIndex, sal_Int32 nAxisIndex ) const
+ {
+ return (m_aNumberFormatMap.find(tFullAxisIndex(nDimIndex,nAxisIndex)) !=m_aNumberFormatMap.end());
+ }
+ sal_Int32 getFormat( sal_Int32 nDimIndex, sal_Int32 nAxisIndex ) const
+ {
+ tNumberFormatMap::const_iterator aIt = m_aNumberFormatMap.find(tFullAxisIndex(nDimIndex,nAxisIndex));
+ if( aIt !=m_aNumberFormatMap.end() )
+ return aIt->second;
+ return 0;
+ }
+
+private:
+ typedef std::pair< sal_Int32, sal_Int32 > tFullAxisIndex;
+ typedef std::map< tFullAxisIndex, sal_Int32 > tNumberFormatMap;
+ tNumberFormatMap m_aNumberFormatMap;
+};
+
+//-----------------------------------------------------------------------------
+/**
+*/
+
+//enum StackType { STACK_NORMAL, STACK_NONE, STACK_BESIDES, STACK_ONTOP, STACK_BEHIND };
+
+class VDataSeriesGroup
+{
+ //a list of series that have the same CoordinateSystem
+ //they are used to be plotted maybe in a stacked manner by a plotter
+
+public:
+ VDataSeriesGroup();
+ VDataSeriesGroup( VDataSeries* pSeries );
+ virtual ~VDataSeriesGroup();
+
+ void addSeries( VDataSeries* pSeries );//takes ownership of pSeries
+ sal_Int32 getSeriesCount() const;
+ void deleteSeries();
+
+ sal_Int32 getPointCount() const;
+ sal_Int32 getAttachedAxisIndexForFirstSeries() const;
+
+ void getMinimumAndMaximiumX( double& rfMinimum, double& rfMaximum ) const;
+ void getMinimumAndMaximiumYInContinuousXRange( double& rfMinY, double& rfMaxY, double fMinX, double fMaxX, sal_Int32 nAxisIndex ) const;
+
+ void calculateYMinAndMaxForCategory( sal_Int32 nCategoryIndex
+ , bool bSeperateStackingForDifferentSigns
+ , double& rfMinimumY, double& rfMaximumY, sal_Int32 nAxisIndex );
+ void calculateYMinAndMaxForCategoryRange( sal_Int32 nStartCategoryIndex, sal_Int32 nEndCategoryIndex
+ , bool bSeperateStackingForDifferentSigns
+ , double& rfMinimumY, double& rfMaximumY, sal_Int32 nAxisIndex );
+
+ ::std::vector< VDataSeries* > m_aSeriesVector;
+
+private:
+ //cached values
+ struct CachedYValues
+ {
+ CachedYValues();
+
+ bool m_bValuesDirty;
+ double m_fMinimumY;
+ double m_fMaximumY;
+ };
+
+ mutable bool m_bMaxPointCountDirty;
+ mutable sal_Int32 m_nMaxPointCount;
+ typedef std::map< sal_Int32, CachedYValues > tCachedYValuesPerAxisIndexMap;
+ mutable ::std::vector< tCachedYValuesPerAxisIndexMap > m_aListOfCachedYValues;
+};
+
+class VSeriesPlotter : public PlotterBase, public MinimumAndMaximumSupplier, public LegendEntryProvider
+{
+ //-------------------------------------------------------------------------
+ // public methods
+ //-------------------------------------------------------------------------
+public:
+ virtual ~VSeriesPlotter();
+
+ /*
+ * A new series can be positioned relative to other series in a chart.
+ * This positioning has two dimensions. First a series can be placed
+ * next to each other on the category axis. This position is indicated by xSlot.
+ * Second a series can be stacked on top of another. This position is indicated by ySlot.
+ * The positions are counted from 0 on.
+ * xSlot < 0 : append the series to already existing x series
+ * xSlot > occupied : append the series to already existing x series
+ *
+ * If the xSlot is already occupied the given ySlot decides what should happen:
+ * ySlot < -1 : move all existing series in the xSlot to next slot
+ * ySlot == -1 : stack on top at given x position
+ * ySlot == already occupied : insert at given y and x position
+ * ySlot > occupied : stack on top at given x position
+ */
+ virtual void addSeries( VDataSeries* pSeries, sal_Int32 zSlot = -1, sal_Int32 xSlot = -1,sal_Int32 ySlot = -1 );
+
+ /** a value <= 0 for a directions means that this direction can be stretched arbitrary
+ */
+ virtual ::com::sun::star::drawing::Direction3D getPreferredDiagramAspectRatio() const;
+ virtual bool keepAspectRatio() const;
+
+ /** this enables you to handle series on the same x axis with different y axis
+ the property AttachedAxisIndex at a dataseries indicates which value scale is to use
+ (0==AttachedAxisIndex or a not set AttachedAxisIndex property indicates that this series should be scaled at the main y-axis;
+ 1==AttachedAxisIndex indicates that the series should be scaled at the first secondary axis if there is any otherwise at the main y axis
+ and so on.
+ The parameter nAxisIndex matches this DataSereis property 'AttachedAxisIndex'.
+ nAxisIndex must be greater than 0. nAxisIndex==1 referres to the first secondary axis.
+ )
+ */
+
+ virtual void SAL_CALL addSecondaryValueScale( const
+ ::com::sun::star::chart2::ExplicitScaleData& rScale, sal_Int32 nAxisIndex )
+ throw (::com::sun::star::uno::RuntimeException);
+
+ //-------------------------------------------------------------------------
+ // MinimumAndMaximumSupplier
+ //-------------------------------------------------------------------------
+
+ virtual double getMinimumX();
+ virtual double getMaximumX();
+
+ virtual double getMinimumYInRange( double fMinimumX, double fMaximumX, sal_Int32 nAxisIndex );
+ virtual double getMaximumYInRange( double fMinimumX, double fMaximumX, sal_Int32 nAxisIndex );
+
+ virtual double getMinimumZ();
+ virtual double getMaximumZ();
+
+ virtual bool isExpandBorderToIncrementRhythm( sal_Int32 nDimensionIndex );
+ virtual bool isExpandIfValuesCloseToBorder( sal_Int32 nDimensionIndex );
+ virtual bool isExpandWideValuesToZero( sal_Int32 nDimensionIndex );
+ virtual bool isExpandNarrowValuesTowardZero( sal_Int32 nDimensionIndex );
+ virtual bool isSeperateStackingForDifferentSigns( sal_Int32 nDimensionIndex );
+
+ //------
+
+ void getMinimumAndMaximiumX( double& rfMinimum, double& rfMaximum ) const;
+ void getMinimumAndMaximiumYInContinuousXRange( double& rfMinY, double& rfMaxY, double fMinX, double fMaxX, sal_Int32 nAxisIndex ) const;
+
+ //-------------------------------------------------------------------------
+ //-------------------------------------------------------------------------
+
+ virtual ::com::sun::star::uno::Sequence<
+ ::com::sun::star::chart2::ViewLegendEntry > SAL_CALL createLegendEntries(
+ ::com::sun::star::chart2::LegendExpansion eLegendExpansion,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::beans::XPropertySet >& xTextProperties,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShapes >& xTarget,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::lang::XMultiServiceFactory >& xShapeFactory,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XComponentContext >& xContext
+ )
+ throw (::com::sun::star::uno::RuntimeException);
+
+
+ virtual ::com::sun::star::chart2::LegendSymbolStyle getLegendSymbolStyle();
+ virtual ::com::sun::star::uno::Any getExplicitSymbol( const VDataSeries& rSeries, sal_Int32 nPointIndex=-1/*-1 for series symbol*/ );
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > createLegendSymbolForSeries(
+ const VDataSeries& rSeries
+ , const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& xTarget
+ , const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xShapeFactory );
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > createLegendSymbolForPoint(
+ const VDataSeries& rSeries
+ , sal_Int32 nPointIndex
+ , const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& xTarget
+ , const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xShapeFactory );
+
+ virtual std::vector<
+ ::com::sun::star::chart2::ViewLegendEntry > SAL_CALL createLegendEntriesForSeries(
+ const VDataSeries& rSeries,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::beans::XPropertySet >& xTextProperties,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShapes >& xTarget,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::lang::XMultiServiceFactory >& xShapeFactory,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XComponentContext >& xContext
+ );
+
+ virtual std::vector<
+ ::com::sun::star::chart2::ViewLegendEntry > SAL_CALL createLegendEntriesForChartType(
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::beans::XPropertySet >& xTextProperties,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShapes >& xTarget,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::lang::XMultiServiceFactory >& xShapeFactory,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XComponentContext >& xContext
+ );
+
+ //-------------------------------------------------------------------------
+ //-------------------------------------------------------------------------
+
+ static VSeriesPlotter* createSeriesPlotter( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::chart2::XChartType >& xChartTypeModel
+ , sal_Int32 nDimensionCount
+ , bool bExcludingPositioning = false /*for pie and donut charts labels and exploded segments are excluded from the given size*/);
+
+ sal_Int32 getPointCount() const;
+
+ void setNumberFormatsSupplier( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::util::XNumberFormatsSupplier > & xNumFmtSupplier );
+ void setAxesNumberFormats( const AxesNumberFormats& rAxesNumberFormats ) { m_aAxesNumberFormats = rAxesNumberFormats; };
+
+ void setColorScheme( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::chart2::XColorScheme >& xColorScheme );
+
+ void setExplicitCategoriesProvider( ExplicitCategoriesProvider* pExplicitCategoriesProvider );
+
+ //get series names for the z axis labels
+ ::com::sun::star::uno::Sequence< rtl::OUString > getSeriesNames() const;
+
+ void setPageReferenceSize( const ::com::sun::star::awt::Size & rPageRefSize );
+ //better performance for big data
+ void setCoordinateSystemResolution( const ::com::sun::star::uno::Sequence< sal_Int32 >& rCoordinateSystemResolution );
+ bool PointsWereSkipped() const;
+
+ //return the depth for a logic 1
+ double getTransformedDepth() const;
+
+ void releaseShapes();
+
+ virtual void rearrangeLabelToAvoidOverlapIfRequested( const ::com::sun::star::awt::Size& rPageSize );
+
+ bool WantToPlotInFrontOfAxisLine();
+ virtual bool shouldSnapRectToUsedArea();
+
+ //-------------------------------------------------------------------------
+ //-------------------------------------------------------------------------
+ //-------------------------------------------------------------------------
+private: //methods
+ //no default constructor
+ VSeriesPlotter();
+
+protected: //methods
+
+ VSeriesPlotter( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::chart2::XChartType >& xChartTypeModel
+ , sal_Int32 nDimensionCount
+ , bool bCategoryXAxis=true );
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >
+ getSeriesGroupShape( VDataSeries* pDataSeries
+ , const::com::sun::star:: uno::Reference<
+ ::com::sun::star::drawing::XShapes >& xTarget );
+
+ //the following group shapes will be created as children of SeriesGroupShape on demand
+ //they can be used to assure that some parts of a series shape are always in front of others (e.g. symbols in front of lines)
+ //parameter xTarget will be used as parent for the series group shape
+ ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >
+ getSeriesGroupShapeFrontChild( VDataSeries* pDataSeries
+ , const::com::sun::star:: uno::Reference<
+ ::com::sun::star::drawing::XShapes >& xTarget );
+ ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >
+ getSeriesGroupShapeBackChild( VDataSeries* pDataSeries
+ , const::com::sun::star:: uno::Reference<
+ ::com::sun::star::drawing::XShapes >& xTarget );
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >
+ getLabelsGroupShape( VDataSeries& rDataSeries
+ , const::com::sun::star:: uno::Reference<
+ ::com::sun::star::drawing::XShapes >& xTarget );
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >
+ getErrorBarsGroupShape( VDataSeries& rDataSeries
+ , const::com::sun::star:: uno::Reference<
+ ::com::sun::star::drawing::XShapes >& xTarget );
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >
+ createDataLabel( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShapes >& xTarget
+ , VDataSeries& rDataSeries
+ , sal_Int32 nPointIndex
+ , double fValue
+ , double fSumValue
+ , const ::com::sun::star::awt::Point& rScreenPosition2D
+ , LabelAlignment eAlignment=LABEL_ALIGN_CENTER
+ , sal_Int32 nOffset=0 );
+
+ ::rtl::OUString getLabelTextForValue( VDataSeries& rDataSeries
+ , sal_Int32 nPointIndex
+ , double fValue
+ , bool bAsPercentage );
+
+ /** creates two T-shaped error bars in both directions (up/down or
+ left/right depending on the bVertical parameter)
+
+ @param rPos
+ logic coordinates
+
+ @param xErrorBarProperties
+ the XPropertySet returned by the DataPoint-property "ErrorBarX" or
+ "ErrorBarY".
+
+ @param nIndex
+ the index of the data point in rData for which the calculation is
+ done.
+
+ @param bVertical
+ for y-error bars this is true, for x-error-bars it is false.
+ */
+ virtual void createErrorBar(
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShapes >& xTarget
+ , const ::com::sun::star::drawing::Position3D & rPos
+ , const ::com::sun::star::uno::Reference<
+ ::com::sun::star::beans::XPropertySet > & xErrorBarProperties
+ , const VDataSeries& rVDataSeries
+ , sal_Int32 nIndex
+ , bool bVertical
+ );
+
+ virtual void createErrorBar_Y( const ::com::sun::star::drawing::Position3D& rUnscaledLogicPosition
+ , VDataSeries& rVDataSeries, sal_Int32 nPointIndex
+ , const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShapes >& xTarget );
+
+ virtual void createRegressionCurvesShapes( VDataSeries& rVDataSeries
+ , const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShapes >& xTarget
+ , const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShapes >& xEquationTarget
+ , bool bMaySkipPointsInRegressionCalculation );
+
+ virtual void createRegressionCurveEquationShapes( const ::rtl::OUString & rEquationCID
+ , const ::com::sun::star::uno::Reference<
+ ::com::sun::star::beans::XPropertySet > & xEquationProperties
+ , const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShapes >& xEquationTarget
+ , const ::com::sun::star::uno::Reference<
+ ::com::sun::star::chart2::XRegressionCurveCalculator > & xRegressionCurveCalculator
+ , ::com::sun::star::awt::Point aDefaultPos );
+
+ virtual void setMappedProperties(
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShape >& xTarget
+ , const ::com::sun::star::uno::Reference<
+ ::com::sun::star::beans::XPropertySet >& xSource
+ , const tPropertyNameMap& rMap
+ , tPropertyNameValueMap* pOverwriteMap=0 );
+
+ virtual PlottingPositionHelper& getPlottingPositionHelper( sal_Int32 nAxisIndex ) const;//nAxisIndex indicates wether the position belongs to the main axis ( nAxisIndex==0 ) or secondary axis ( nAxisIndex==1 )
+
+ VDataSeries* getFirstSeries() const;
+
+protected: //member
+ PlottingPositionHelper* m_pMainPosHelper;
+
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::chart2::XChartType > m_xChartTypeModel;
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::beans::XPropertySet > m_xChartTypeModelProps;
+
+ ::std::vector< ::std::vector< VDataSeriesGroup > > m_aZSlots;
+
+ bool m_bCategoryXAxis;//true->xvalues are indices (this would not be necessary if series for category chart wouldn't have x-values)
+
+ ::std::auto_ptr< NumberFormatterWrapper > m_apNumberFormatterWrapper;
+ AxesNumberFormats m_aAxesNumberFormats;//direct numberformats on axes, if empty ask the data series instead
+
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::chart2::XColorScheme > m_xColorScheme;
+
+ ExplicitCategoriesProvider* m_pExplicitCategoriesProvider;
+
+ //better performance for big data
+ ::com::sun::star::uno::Sequence< sal_Int32 > m_aCoordinateSystemResolution;
+ bool m_bPointsWereSkipped;
+
+private: //member
+ typedef std::map< sal_Int32 , ::com::sun::star::chart2::ExplicitScaleData > tSecondaryValueScales;
+ tSecondaryValueScales m_aSecondaryValueScales;
+
+ typedef std::map< sal_Int32 , PlottingPositionHelper* > tSecondaryPosHelperMap;
+ mutable tSecondaryPosHelperMap m_aSecondaryPosHelperMap;
+ ::com::sun::star::awt::Size m_aPageReferenceSize;
+};
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
+#endif
diff --git a/chart2/source/view/inc/ViewDefines.hxx b/chart2/source/view/inc/ViewDefines.hxx
new file mode 100644
index 000000000000..623e46e64fb7
--- /dev/null
+++ b/chart2/source/view/inc/ViewDefines.hxx
@@ -0,0 +1,47 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _CHART_COMMONDEFINES_HXX
+#define _CHART_COMMONDEFINES_HXX
+
+namespace chart
+{
+
+//=========================================================================
+//
+//=========================================================================
+#define CHART_3DOBJECT_SEGMENTCOUNT ((sal_Int32)32)
+#define FIXED_SIZE_FOR_3D_CHART_VOLUME (10000.0)
+//There needs to be a little distance betweengrid lines and walls in 3D, otherwise the lines are partly hidden by the walls
+#define GRID_TO_WALL_DISTANCE (1.0)
+
+const double ZDIRECTION = 1.0;
+const sal_Int32 AXIS2D_TICKLENGTH = 150;//value like in old chart
+const sal_Int32 AXIS2D_TICKLABELSPACING = 100;//value like in old chart
+
+
+}//end namespace chart
+#endif
diff --git a/chart2/source/view/main/ChartItemPool.cxx b/chart2/source/view/main/ChartItemPool.cxx
new file mode 100644
index 000000000000..d8f997d36da9
--- /dev/null
+++ b/chart2/source/view/main/ChartItemPool.cxx
@@ -0,0 +1,258 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_chart2.hxx"
+
+#include "ChartItemPool.hxx"
+#include "macros.hxx"
+
+#include "chartview/ChartSfxItemIds.hxx"
+#include <svx/chrtitem.hxx>
+#include <svl/intitem.hxx>
+#include <editeng/brshitem.hxx>
+#include <editeng/sizeitem.hxx>
+#include <svl/stritem.hxx>
+#include <svl/rectitem.hxx>
+#include <svl/ilstitem.hxx>
+#define _SVSTDARR_ULONGS
+#include <svl/svstdarr.hxx>
+#include <editeng/editids.hrc>
+#include <svx/svxids.hrc>
+
+namespace chart
+{
+
+ChartItemPool::ChartItemPool():
+ SfxItemPool( String( RTL_CONSTASCII_USTRINGPARAM( "ChartItemPool" )), SCHATTR_START, SCHATTR_END, NULL, NULL )
+{
+// OSL_TRACE( "SCH: CTOR: ChartItemPool" );
+ /**************************************************************************
+ * PoolDefaults
+ **************************************************************************/
+ ppPoolDefaults = new SfxPoolItem*[SCHATTR_END - SCHATTR_START + 1];
+
+ ppPoolDefaults[SCHATTR_DATADESCR_SHOW_NUMBER - SCHATTR_START] = new SfxBoolItem(SCHATTR_DATADESCR_SHOW_NUMBER);
+ ppPoolDefaults[SCHATTR_DATADESCR_SHOW_PERCENTAGE- SCHATTR_START] = new SfxBoolItem(SCHATTR_DATADESCR_SHOW_PERCENTAGE);
+ ppPoolDefaults[SCHATTR_DATADESCR_SHOW_CATEGORY - SCHATTR_START] = new SfxBoolItem(SCHATTR_DATADESCR_SHOW_CATEGORY);
+ ppPoolDefaults[SCHATTR_DATADESCR_SHOW_SYMBOL - SCHATTR_START] = new SfxBoolItem(SCHATTR_DATADESCR_SHOW_SYMBOL);
+ ppPoolDefaults[SCHATTR_DATADESCR_SEPARATOR - SCHATTR_START] = new SfxStringItem(SCHATTR_DATADESCR_SEPARATOR,C2U(" "));
+ ppPoolDefaults[SCHATTR_DATADESCR_PLACEMENT - SCHATTR_START] = new SfxInt32Item(SCHATTR_DATADESCR_PLACEMENT,0);
+ SvULongs aTmp;
+ ppPoolDefaults[SCHATTR_DATADESCR_AVAILABLE_PLACEMENTS - SCHATTR_START] = new SfxIntegerListItem(SCHATTR_DATADESCR_AVAILABLE_PLACEMENTS,aTmp);
+ ppPoolDefaults[SCHATTR_DATADESCR_NO_PERCENTVALUE - SCHATTR_START] = new SfxBoolItem(SCHATTR_DATADESCR_NO_PERCENTVALUE);
+
+ ppPoolDefaults[SCHATTR_LEGEND_POS - SCHATTR_START] = new SvxChartLegendPosItem( CHLEGEND_RIGHT, SCHATTR_LEGEND_POS );
+// ppPoolDefaults[SCHATTR_TEXT_ORIENT - SCHATTR_START] = new SvxChartTextOrientItem;
+ ppPoolDefaults[SCHATTR_TEXT_STACKED - SCHATTR_START] = new SfxBoolItem(SCHATTR_TEXT_STACKED,FALSE);
+ ppPoolDefaults[SCHATTR_TEXT_ORDER - SCHATTR_START] = new SvxChartTextOrderItem(CHTXTORDER_SIDEBYSIDE, SCHATTR_TEXT_ORDER);
+
+ ppPoolDefaults[SCHATTR_Y_AXIS_AUTO_MIN - SCHATTR_START] = new SfxBoolItem(SCHATTR_Y_AXIS_AUTO_MIN);
+ ppPoolDefaults[SCHATTR_Y_AXIS_MIN - SCHATTR_START] = new SvxDoubleItem(0.0, SCHATTR_Y_AXIS_MIN);
+ ppPoolDefaults[SCHATTR_Y_AXIS_AUTO_MAX - SCHATTR_START] = new SfxBoolItem(SCHATTR_Y_AXIS_AUTO_MAX);
+ ppPoolDefaults[SCHATTR_Y_AXIS_MAX - SCHATTR_START] = new SvxDoubleItem(0.0, SCHATTR_Y_AXIS_MAX);
+ ppPoolDefaults[SCHATTR_Y_AXIS_AUTO_STEP_MAIN - SCHATTR_START] = new SfxBoolItem(SCHATTR_Y_AXIS_AUTO_STEP_MAIN);
+ ppPoolDefaults[SCHATTR_Y_AXIS_STEP_MAIN - SCHATTR_START] = new SvxDoubleItem(0.0, SCHATTR_Y_AXIS_STEP_MAIN);
+ ppPoolDefaults[SCHATTR_Y_AXIS_AUTO_STEP_HELP - SCHATTR_START] = new SfxBoolItem(SCHATTR_Y_AXIS_AUTO_STEP_HELP);
+ ppPoolDefaults[SCHATTR_Y_AXIS_STEP_HELP - SCHATTR_START] = new SvxDoubleItem(0.0, SCHATTR_Y_AXIS_STEP_HELP);
+ ppPoolDefaults[SCHATTR_Y_AXIS_LOGARITHM - SCHATTR_START] = new SfxBoolItem(SCHATTR_Y_AXIS_LOGARITHM);
+ ppPoolDefaults[SCHATTR_Y_AXIS_AUTO_ORIGIN - SCHATTR_START] = new SfxBoolItem(SCHATTR_Y_AXIS_AUTO_ORIGIN);
+ ppPoolDefaults[SCHATTR_Y_AXIS_ORIGIN - SCHATTR_START] = new SvxDoubleItem(0.0, SCHATTR_Y_AXIS_ORIGIN);
+
+ ppPoolDefaults[SCHATTR_X_AXIS_AUTO_MIN - SCHATTR_START] = new SfxBoolItem(SCHATTR_X_AXIS_AUTO_MIN);
+ ppPoolDefaults[SCHATTR_X_AXIS_MIN - SCHATTR_START] = new SvxDoubleItem(0.0, SCHATTR_X_AXIS_MIN);
+ ppPoolDefaults[SCHATTR_X_AXIS_AUTO_MAX - SCHATTR_START] = new SfxBoolItem(SCHATTR_X_AXIS_AUTO_MAX);
+ ppPoolDefaults[SCHATTR_X_AXIS_MAX - SCHATTR_START] = new SvxDoubleItem(0.0, SCHATTR_X_AXIS_MAX);
+ ppPoolDefaults[SCHATTR_X_AXIS_AUTO_STEP_MAIN - SCHATTR_START] = new SfxBoolItem(SCHATTR_X_AXIS_AUTO_STEP_MAIN);
+ ppPoolDefaults[SCHATTR_X_AXIS_STEP_MAIN - SCHATTR_START] = new SvxDoubleItem(0.0, SCHATTR_X_AXIS_STEP_MAIN);
+ ppPoolDefaults[SCHATTR_X_AXIS_AUTO_STEP_HELP - SCHATTR_START] = new SfxBoolItem(SCHATTR_X_AXIS_AUTO_STEP_HELP);
+ ppPoolDefaults[SCHATTR_X_AXIS_STEP_HELP - SCHATTR_START] = new SvxDoubleItem(0.0, SCHATTR_X_AXIS_STEP_HELP);
+ ppPoolDefaults[SCHATTR_X_AXIS_LOGARITHM - SCHATTR_START] = new SfxBoolItem(SCHATTR_X_AXIS_LOGARITHM);
+ ppPoolDefaults[SCHATTR_X_AXIS_AUTO_ORIGIN - SCHATTR_START] = new SfxBoolItem(SCHATTR_X_AXIS_AUTO_ORIGIN);
+ ppPoolDefaults[SCHATTR_X_AXIS_ORIGIN - SCHATTR_START] = new SvxDoubleItem(0.0, SCHATTR_X_AXIS_ORIGIN);
+
+ ppPoolDefaults[SCHATTR_Z_AXIS_AUTO_MIN - SCHATTR_START] = new SfxBoolItem(SCHATTR_Z_AXIS_AUTO_MIN);
+ ppPoolDefaults[SCHATTR_Z_AXIS_MIN - SCHATTR_START] = new SvxDoubleItem(0.0, SCHATTR_Z_AXIS_MIN);
+ ppPoolDefaults[SCHATTR_Z_AXIS_AUTO_MAX - SCHATTR_START] = new SfxBoolItem(SCHATTR_Z_AXIS_AUTO_MAX);
+ ppPoolDefaults[SCHATTR_Z_AXIS_MAX - SCHATTR_START] = new SvxDoubleItem(0.0, SCHATTR_Z_AXIS_MAX);
+ ppPoolDefaults[SCHATTR_Z_AXIS_AUTO_STEP_MAIN - SCHATTR_START] = new SfxBoolItem(SCHATTR_Z_AXIS_AUTO_STEP_MAIN);
+ ppPoolDefaults[SCHATTR_Z_AXIS_STEP_MAIN - SCHATTR_START] = new SvxDoubleItem(0.0, SCHATTR_Z_AXIS_STEP_MAIN);
+ ppPoolDefaults[SCHATTR_Z_AXIS_AUTO_STEP_HELP - SCHATTR_START] = new SfxBoolItem(SCHATTR_Z_AXIS_AUTO_STEP_HELP);
+ ppPoolDefaults[SCHATTR_Z_AXIS_STEP_HELP - SCHATTR_START] = new SvxDoubleItem(0.0, SCHATTR_Z_AXIS_STEP_HELP);
+ ppPoolDefaults[SCHATTR_Z_AXIS_LOGARITHM - SCHATTR_START] = new SfxBoolItem(SCHATTR_Z_AXIS_LOGARITHM);
+ ppPoolDefaults[SCHATTR_Z_AXIS_AUTO_ORIGIN - SCHATTR_START] = new SfxBoolItem(SCHATTR_Z_AXIS_AUTO_ORIGIN);
+ ppPoolDefaults[SCHATTR_Z_AXIS_ORIGIN - SCHATTR_START] = new SvxDoubleItem(0.0, SCHATTR_Z_AXIS_ORIGIN);
+
+ ppPoolDefaults[SCHATTR_AXISTYPE - SCHATTR_START] = new SfxInt32Item(SCHATTR_AXISTYPE, CHART_AXIS_X);
+ ppPoolDefaults[SCHATTR_PERCENT_NUMBERFORMAT_VALUE - SCHATTR_START] = new SfxInt32Item(SCHATTR_PERCENT_NUMBERFORMAT_VALUE, 0);
+ ppPoolDefaults[SCHATTR_PERCENT_NUMBERFORMAT_SOURCE - SCHATTR_START] = new SfxBoolItem(SCHATTR_PERCENT_NUMBERFORMAT_SOURCE);
+
+ ppPoolDefaults[SCHATTR_STAT_AVERAGE - SCHATTR_START] = new SfxBoolItem (SCHATTR_STAT_AVERAGE);
+ ppPoolDefaults[SCHATTR_STAT_KIND_ERROR - SCHATTR_START] = new SvxChartKindErrorItem (CHERROR_NONE, SCHATTR_STAT_KIND_ERROR);
+ ppPoolDefaults[SCHATTR_STAT_PERCENT - SCHATTR_START] = new SvxDoubleItem (0.0, SCHATTR_STAT_PERCENT);
+ ppPoolDefaults[SCHATTR_STAT_BIGERROR - SCHATTR_START] = new SvxDoubleItem (0.0, SCHATTR_STAT_BIGERROR);
+ ppPoolDefaults[SCHATTR_STAT_CONSTPLUS - SCHATTR_START] = new SvxDoubleItem (0.0, SCHATTR_STAT_CONSTPLUS);
+ ppPoolDefaults[SCHATTR_STAT_CONSTMINUS - SCHATTR_START] = new SvxDoubleItem (0.0, SCHATTR_STAT_CONSTMINUS);
+ ppPoolDefaults[SCHATTR_STAT_INDICATE - SCHATTR_START] = new SvxChartIndicateItem (CHINDICATE_NONE, SCHATTR_STAT_INDICATE);
+ ppPoolDefaults[SCHATTR_STAT_RANGE_POS - SCHATTR_START] = new SfxStringItem (SCHATTR_STAT_RANGE_POS, String());
+ ppPoolDefaults[SCHATTR_STAT_RANGE_NEG - SCHATTR_START] = new SfxStringItem (SCHATTR_STAT_RANGE_NEG, String());
+
+ ppPoolDefaults[SCHATTR_TEXT_DEGREES - SCHATTR_START] = new SfxInt32Item(SCHATTR_TEXT_DEGREES, 0);
+ ppPoolDefaults[SCHATTR_TEXT_OVERLAP - SCHATTR_START] = new SfxBoolItem(SCHATTR_TEXT_OVERLAP,FALSE);
+
+ ppPoolDefaults[SCHATTR_STYLE_DEEP - SCHATTR_START] = new SfxBoolItem (SCHATTR_STYLE_DEEP, 0);
+ ppPoolDefaults[SCHATTR_STYLE_3D - SCHATTR_START] = new SfxBoolItem (SCHATTR_STYLE_3D, 0);
+ ppPoolDefaults[SCHATTR_STYLE_VERTICAL - SCHATTR_START] = new SfxBoolItem (SCHATTR_STYLE_VERTICAL, 0);
+ ppPoolDefaults[SCHATTR_STYLE_BASETYPE - SCHATTR_START] = new SfxInt32Item(SCHATTR_STYLE_BASETYPE, 0);
+ ppPoolDefaults[SCHATTR_STYLE_LINES - SCHATTR_START] = new SfxBoolItem (SCHATTR_STYLE_LINES, 0);
+ ppPoolDefaults[SCHATTR_STYLE_PERCENT - SCHATTR_START] = new SfxBoolItem (SCHATTR_STYLE_PERCENT, 0);
+ ppPoolDefaults[SCHATTR_STYLE_STACKED - SCHATTR_START] = new SfxBoolItem (SCHATTR_STYLE_STACKED, 0);
+ ppPoolDefaults[SCHATTR_STYLE_SPLINES - SCHATTR_START] = new SfxInt32Item (SCHATTR_STYLE_SPLINES, 0); //Bug: war Bool! ->Fileformat testen (betrifft nur 5er)
+ ppPoolDefaults[SCHATTR_STYLE_SYMBOL - SCHATTR_START] = new SfxInt32Item (SCHATTR_STYLE_SYMBOL, 0);
+ ppPoolDefaults[SCHATTR_STYLE_SHAPE - SCHATTR_START] = new SfxInt32Item (SCHATTR_STYLE_SHAPE, 0);
+
+ ppPoolDefaults[SCHATTR_AXIS - SCHATTR_START] = new SfxInt32Item(SCHATTR_AXIS,2); //2 = Y-Achse!!!
+
+ ppPoolDefaults[SCHATTR_AXIS_AUTO_MIN - SCHATTR_START] = new SfxBoolItem(SCHATTR_AXIS_AUTO_MIN);
+ ppPoolDefaults[SCHATTR_AXIS_MIN - SCHATTR_START] = new SvxDoubleItem(0.0, SCHATTR_AXIS_MIN);
+ ppPoolDefaults[SCHATTR_AXIS_AUTO_MAX - SCHATTR_START] = new SfxBoolItem(SCHATTR_AXIS_AUTO_MAX);
+ ppPoolDefaults[SCHATTR_AXIS_MAX - SCHATTR_START] = new SvxDoubleItem(0.0, SCHATTR_AXIS_MAX);
+ ppPoolDefaults[SCHATTR_AXIS_AUTO_STEP_MAIN - SCHATTR_START] = new SfxBoolItem(SCHATTR_AXIS_AUTO_STEP_MAIN);
+ ppPoolDefaults[SCHATTR_AXIS_STEP_MAIN - SCHATTR_START] = new SvxDoubleItem(0.0, SCHATTR_AXIS_STEP_MAIN);
+ ppPoolDefaults[SCHATTR_AXIS_AUTO_STEP_HELP - SCHATTR_START] = new SfxBoolItem(SCHATTR_AXIS_AUTO_STEP_HELP);
+// ppPoolDefaults[SCHATTR_AXIS_STEP_HELP - SCHATTR_START] = new SvxDoubleItem(0.0, SCHATTR_AXIS_STEP_HELP);
+ // type changed from double to sal_Int32
+ ppPoolDefaults[SCHATTR_AXIS_STEP_HELP - SCHATTR_START] = new SfxInt32Item(SCHATTR_AXIS_STEP_HELP,0);
+ ppPoolDefaults[SCHATTR_AXIS_LOGARITHM - SCHATTR_START] = new SfxBoolItem(SCHATTR_AXIS_LOGARITHM);
+ ppPoolDefaults[SCHATTR_AXIS_AUTO_ORIGIN - SCHATTR_START] = new SfxBoolItem(SCHATTR_AXIS_AUTO_ORIGIN);
+ ppPoolDefaults[SCHATTR_AXIS_ORIGIN - SCHATTR_START] = new SvxDoubleItem(0.0, SCHATTR_AXIS_ORIGIN);
+
+ ppPoolDefaults[SCHATTR_AXIS_TICKS - SCHATTR_START] = new SfxInt32Item(SCHATTR_AXIS_TICKS,CHAXIS_MARK_OUTER);
+ ppPoolDefaults[SCHATTR_AXIS_NUMFMT - SCHATTR_START] = new SfxUInt32Item(SCHATTR_AXIS_NUMFMT,0);
+ ppPoolDefaults[SCHATTR_AXIS_NUMFMTPERCENT - SCHATTR_START] = new SfxUInt32Item(SCHATTR_AXIS_NUMFMTPERCENT,11);
+ ppPoolDefaults[SCHATTR_AXIS_SHOWAXIS - SCHATTR_START] = new SfxBoolItem(SCHATTR_AXIS_SHOWAXIS,0);
+ ppPoolDefaults[SCHATTR_AXIS_SHOWDESCR - SCHATTR_START] = new SfxBoolItem(SCHATTR_AXIS_SHOWDESCR,0);
+ ppPoolDefaults[SCHATTR_AXIS_SHOWMAINGRID - SCHATTR_START] = new SfxBoolItem(SCHATTR_AXIS_SHOWMAINGRID,0);
+ ppPoolDefaults[SCHATTR_AXIS_SHOWHELPGRID - SCHATTR_START] = new SfxBoolItem(SCHATTR_AXIS_SHOWHELPGRID,0);
+ ppPoolDefaults[SCHATTR_AXIS_TOPDOWN - SCHATTR_START] = new SfxBoolItem(SCHATTR_AXIS_TOPDOWN,0);
+ ppPoolDefaults[SCHATTR_AXIS_HELPTICKS - SCHATTR_START] = new SfxInt32Item(SCHATTR_AXIS_HELPTICKS,0);
+ ppPoolDefaults[SCHATTR_AXIS_REVERSE - SCHATTR_START] = new SfxBoolItem(SCHATTR_AXIS_REVERSE,0);
+
+ ppPoolDefaults[SCHATTR_AXIS_POSITION - SCHATTR_START] = new SfxInt32Item(SCHATTR_AXIS_POSITION,0);
+ ppPoolDefaults[SCHATTR_AXIS_POSITION_VALUE - SCHATTR_START] = new SvxDoubleItem(0.0, SCHATTR_AXIS_POSITION_VALUE);
+ ppPoolDefaults[SCHATTR_AXIS_CROSSING_MAIN_AXIS_NUMBERFORMAT - SCHATTR_START] = new SfxUInt32Item(SCHATTR_AXIS_CROSSING_MAIN_AXIS_NUMBERFORMAT,0);
+ ppPoolDefaults[SCHATTR_AXIS_LABEL_POSITION - SCHATTR_START] = new SfxInt32Item(SCHATTR_AXIS_LABEL_POSITION,0);
+ ppPoolDefaults[SCHATTR_AXIS_MARK_POSITION - SCHATTR_START] = new SfxInt32Item(SCHATTR_AXIS_MARK_POSITION,0);
+
+ ppPoolDefaults[SCHATTR_SYMBOL_BRUSH - SCHATTR_START] = new SvxBrushItem(SCHATTR_SYMBOL_BRUSH);
+ ppPoolDefaults[SCHATTR_STOCK_VOLUME - SCHATTR_START] = new SfxBoolItem(SCHATTR_STOCK_VOLUME,0);
+ ppPoolDefaults[SCHATTR_STOCK_UPDOWN - SCHATTR_START] = new SfxBoolItem(SCHATTR_STOCK_UPDOWN,0);
+ ppPoolDefaults[SCHATTR_SYMBOL_SIZE - SCHATTR_START] = new SvxSizeItem(SCHATTR_SYMBOL_SIZE,Size(0,0));
+
+ // new for New Chart
+ ppPoolDefaults[SCHATTR_BAR_OVERLAP - SCHATTR_START] = new SfxInt32Item(SCHATTR_BAR_OVERLAP,0);
+ ppPoolDefaults[SCHATTR_BAR_GAPWIDTH - SCHATTR_START] = new SfxInt32Item(SCHATTR_BAR_GAPWIDTH,0);
+ ppPoolDefaults[SCHATTR_BAR_CONNECT - SCHATTR_START] = new SfxBoolItem(SCHATTR_BAR_CONNECT, FALSE);
+ ppPoolDefaults[SCHATTR_NUM_OF_LINES_FOR_BAR - SCHATTR_START] = new SfxInt32Item( SCHATTR_NUM_OF_LINES_FOR_BAR, 0 );
+ ppPoolDefaults[SCHATTR_SPLINE_ORDER - SCHATTR_START] = new SfxInt32Item( SCHATTR_SPLINE_ORDER, 3 );
+ ppPoolDefaults[SCHATTR_SPLINE_RESOLUTION - SCHATTR_START] = new SfxInt32Item( SCHATTR_SPLINE_RESOLUTION, 20 );
+ ppPoolDefaults[SCHATTR_DIAGRAM_STYLE - SCHATTR_START] = new SvxChartStyleItem( CHSTYLE_2D_COLUMN, SCHATTR_DIAGRAM_STYLE );
+ ppPoolDefaults[SCHATTR_TEXTBREAK - SCHATTR_START] = new SfxBoolItem( SCHATTR_TEXTBREAK, FALSE );
+ ppPoolDefaults[SCHATTR_GROUP_BARS_PER_AXIS - SCHATTR_START] = new SfxBoolItem(SCHATTR_GROUP_BARS_PER_AXIS, FALSE);
+ ppPoolDefaults[SCHATTR_INCLUDE_HIDDEN_CELLS - SCHATTR_START] = new SfxBoolItem(SCHATTR_INCLUDE_HIDDEN_CELLS, TRUE);
+ ppPoolDefaults[SCHATTR_STARTING_ANGLE - SCHATTR_START] = new SfxInt32Item( SCHATTR_STARTING_ANGLE, 90 );
+ ppPoolDefaults[SCHATTR_CLOCKWISE - SCHATTR_START] = new SfxBoolItem( SCHATTR_CLOCKWISE, FALSE );
+
+ ppPoolDefaults[SCHATTR_MISSING_VALUE_TREATMENT - SCHATTR_START] = new SfxInt32Item(SCHATTR_MISSING_VALUE_TREATMENT, 0);
+ ppPoolDefaults[SCHATTR_AVAILABLE_MISSING_VALUE_TREATMENTS - SCHATTR_START] = new SfxIntegerListItem(SCHATTR_AVAILABLE_MISSING_VALUE_TREATMENTS,aTmp);
+
+ ppPoolDefaults[SCHATTR_AXIS_FOR_ALL_SERIES - SCHATTR_START] = new SfxInt32Item(SCHATTR_AXIS_FOR_ALL_SERIES, 0);
+ ppPoolDefaults[SCHATTR_REGRESSION_TYPE - SCHATTR_START] = new SvxChartRegressItem (CHREGRESS_NONE, SCHATTR_REGRESSION_TYPE);
+ ppPoolDefaults[SCHATTR_REGRESSION_SHOW_EQUATION - SCHATTR_START] = new SfxBoolItem(SCHATTR_REGRESSION_SHOW_EQUATION, 0);
+ ppPoolDefaults[SCHATTR_REGRESSION_SHOW_COEFF - SCHATTR_START] = new SfxBoolItem(SCHATTR_REGRESSION_SHOW_COEFF, 0);
+
+ /**************************************************************************
+ * ItemInfos
+ **************************************************************************/
+ pItemInfos = new SfxItemInfo[SCHATTR_END - SCHATTR_START + 1];
+
+ USHORT i;
+ for( i = SCHATTR_START; i <= SCHATTR_END; i++ )
+ {
+ pItemInfos[i - SCHATTR_START]._nSID = 0;
+ pItemInfos[i - SCHATTR_START]._nFlags = SFX_ITEM_POOLABLE;
+ }
+
+ // slot ids differing from which ids
+ pItemInfos[SCHATTR_SYMBOL_BRUSH - SCHATTR_START]._nSID = SID_ATTR_BRUSH;
+ pItemInfos[SCHATTR_STYLE_SYMBOL - SCHATTR_START]._nSID = SID_ATTR_SYMBOLTYPE;
+ pItemInfos[SCHATTR_SYMBOL_SIZE - SCHATTR_START]._nSID = SID_ATTR_SYMBOLSIZE;
+
+ SetDefaults(ppPoolDefaults);
+ SetItemInfos(pItemInfos);
+}
+
+ChartItemPool::ChartItemPool(const ChartItemPool& rPool):
+ SfxItemPool(rPool)
+{
+// OSL_TRACE( "SCH: CTOR: ChartItemPool" );
+}
+
+ChartItemPool::~ChartItemPool()
+{
+// OSL_TRACE( "SCH: DTOR: ChartItemPool" );
+ Delete();
+
+ delete[] pItemInfos;
+
+ const USHORT nMax = SCHATTR_END - SCHATTR_START + 1;
+ for( USHORT i=0; i<nMax; ++i )
+ {
+ SetRefCount(*ppPoolDefaults[i], 0);
+ delete ppPoolDefaults[i];
+ }
+
+ delete[] ppPoolDefaults;
+}
+
+SfxItemPool* ChartItemPool::Clone() const
+{
+ return new ChartItemPool(*this);
+}
+
+SfxMapUnit ChartItemPool::GetMetric(USHORT /* nWhich */) const
+{
+ return SFX_MAPUNIT_100TH_MM;
+}
+
+// static
+SfxItemPool* ChartItemPool::CreateChartItemPool()
+{
+ return new ChartItemPool();
+}
+
+} // namespace chart
diff --git a/chart2/source/view/main/ChartItemPool.hxx b/chart2/source/view/main/ChartItemPool.hxx
new file mode 100644
index 000000000000..b8ee9910ce2d
--- /dev/null
+++ b/chart2/source/view/main/ChartItemPool.hxx
@@ -0,0 +1,58 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _CHART2_ITEMPOOL_HXX
+#define _CHART2_ITEMPOOL_HXX
+
+#include <svl/poolitem.hxx>
+#include <svl/itempool.hxx>
+
+namespace chart
+{
+class ChartItemPool : public SfxItemPool
+{
+private:
+ SfxPoolItem** ppPoolDefaults;
+ SfxItemInfo* pItemInfos;
+
+public:
+ ChartItemPool();
+ ChartItemPool(const ChartItemPool& rPool);
+protected:
+ virtual ~ChartItemPool();
+public:
+
+ virtual SfxItemPool* Clone() const;
+ SfxMapUnit GetMetric( USHORT nWhich ) const;
+
+ /// creates a pure chart item pool
+ static SfxItemPool* CreateChartItemPool();
+};
+
+} // namespace chart
+
+#endif
+// _CHART2_ITEMPOOL_HXX
diff --git a/chart2/source/view/main/ChartView.cxx b/chart2/source/view/main/ChartView.cxx
new file mode 100644
index 000000000000..2347824664c5
--- /dev/null
+++ b/chart2/source/view/main/ChartView.cxx
@@ -0,0 +1,3187 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_chart2.hxx"
+
+#include "ChartView.hxx"
+#include "chartview/DrawModelWrapper.hxx"
+#include "ViewDefines.hxx"
+#include "VDiagram.hxx"
+#include "VTitle.hxx"
+#include "ShapeFactory.hxx"
+#include "VCoordinateSystem.hxx"
+#include "VSeriesPlotter.hxx"
+#include "CommonConverters.hxx"
+#include "macros.hxx"
+#include "TitleHelper.hxx"
+#include "LegendHelper.hxx"
+#include "VLegend.hxx"
+#include "PropertyMapper.hxx"
+#include "ChartModelHelper.hxx"
+#include "ChartTypeHelper.hxx"
+#include "ScaleAutomatism.hxx"
+#include "MinimumAndMaximumSupplier.hxx"
+#include "ObjectIdentifier.hxx"
+#include "DiagramHelper.hxx"
+#include "RelativePositionHelper.hxx"
+#include "servicenames.hxx"
+#include "AxisHelper.hxx"
+#include "AxisIndexDefines.hxx"
+#include "ControllerLockGuard.hxx"
+#include "BaseGFXHelper.hxx"
+#include "DataSeriesHelper.hxx"
+
+#include <comphelper/scopeguard.hxx>
+#include <boost/bind.hpp>
+#include <unotools/streamwrap.hxx>
+// header for class LocaleDataWrapper
+#include <unotools/localedatawrapper.hxx>
+// header for class SdrPage
+#include <svx/svdpage.hxx>
+// header for class SvxDrawPage
+#include <svx/unopage.hxx>
+// header for class SvxShape
+#include <svx/unoshape.hxx>
+// header for class Application
+#include <vcl/svapp.hxx>
+#include <vos/mutex.hxx>
+#include <svx/unofill.hxx>
+
+#include <time.h>
+
+#include <com/sun/star/chart/ChartAxisPosition.hpp>
+#include <com/sun/star/chart/DataLabelPlacement.hpp>
+#include <com/sun/star/chart/MissingValueTreatment.hpp>
+#include <com/sun/star/chart2/ExplicitSubIncrement.hpp>
+#include <com/sun/star/chart2/StackingDirection.hpp>
+#include <com/sun/star/chart2/XChartDocument.hpp>
+#include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
+#include <com/sun/star/chart2/XChartTypeContainer.hpp>
+#include <com/sun/star/chart2/XDataSeriesContainer.hpp>
+#include <com/sun/star/chart2/XTitled.hpp>
+#include <com/sun/star/chart2/RelativePosition.hpp>
+#include <com/sun/star/chart2/RelativeSize.hpp>
+#include <com/sun/star/drawing/FillStyle.hpp>
+#include <com/sun/star/drawing/LineStyle.hpp>
+#include <com/sun/star/drawing/XShapeGroup.hpp>
+#include <com/sun/star/document/XExporter.hpp>
+#include <com/sun/star/document/XFilter.hpp>
+#include <com/sun/star/io/XSeekable.hpp>
+#include <com/sun/star/util/XModifiable.hpp>
+#include <com/sun/star/util/XRefreshable.hpp>
+#include <com/sun/star/util/NumberFormat.hpp>
+
+#include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
+#include <com/sun/star/text/XTextDocument.hpp>
+#include <com/sun/star/text/WritingMode2.hpp>
+#include <com/sun/star/text/XTextEmbeddedObjectsSupplier.hpp>
+#include <com/sun/star/view/XSelectionSupplier.hpp>
+#include <svl/languageoptions.hxx>
+#include <sot/clsids.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;
+using ::com::sun::star::uno::Any;
+using rtl::OUString;
+
+//static
+const uno::Sequence<sal_Int8>& ExplicitValueProvider::getUnoTunnelId()
+{
+ static uno::Sequence<sal_Int8> * pSeq = 0;
+ if( !pSeq )
+ {
+ osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
+ if( !pSeq )
+ {
+ static uno::Sequence< sal_Int8 > aSeq( 16 );
+ rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True );
+ pSeq = &aSeq;
+ }
+ }
+ return *pSeq;
+}
+
+//static
+ExplicitValueProvider* ExplicitValueProvider::getExplicitValueProvider(
+ const Reference< uno::XInterface >& xChartView )
+{
+ ExplicitValueProvider* pExplicitValueProvider=0;
+
+ Reference< lang::XUnoTunnel > xTunnel( xChartView, uno::UNO_QUERY );
+ if( xTunnel.is() )
+ {
+ pExplicitValueProvider = reinterpret_cast<ExplicitValueProvider*>(xTunnel->getSomething(
+ ExplicitValueProvider::getUnoTunnelId() ));
+ }
+ return pExplicitValueProvider;
+}
+
+ChartView::ChartView(
+ uno::Reference<uno::XComponentContext> const & xContext)
+ : m_aMutex()
+ , m_xCC(xContext)
+ , m_xChartModel()
+ , m_xShapeFactory()
+ , m_xDrawPage()
+ , m_pDrawModelWrapper()
+ , m_aListenerContainer( m_aMutex )
+ , m_bViewDirty(true)
+ , m_bInViewUpdate(false)
+ , m_bViewUpdatePending(false)
+ , m_bRefreshAddIn(true)
+ , m_aPageResolution(1000,1000)
+ , m_bPointsWereSkipped(false)
+ , m_nScaleXNumerator(1)
+ , m_nScaleXDenominator(1)
+ , m_nScaleYNumerator(1)
+ , m_nScaleYDenominator(1)
+ , m_bSdrViewIsInEditMode(sal_False)
+ , m_aResultingDiagramRectangleExcludingAxes(0,0,0,0)
+{
+}
+
+void ChartView::impl_setChartModel( const uno::Reference< frame::XModel >& xChartModel )
+{
+ if( m_xChartModel != xChartModel )
+ {
+ m_xChartModel = xChartModel;
+ m_bViewDirty = true;
+ }
+}
+
+void SAL_CALL ChartView::initialize( const uno::Sequence< uno::Any >& aArguments )
+ throw ( uno::Exception, uno::RuntimeException)
+{
+ DBG_ASSERT(aArguments.getLength() >= 1,"need 1 argument to initialize the view: xModel");
+ if( !(aArguments.getLength() >= 1) )
+ return;
+
+ uno::Reference< frame::XModel > xNewChartModel;
+ if( !(aArguments[0] >>= xNewChartModel) )
+ {
+ DBG_ERROR( "need a Reference to frame::XModel as first parameter for view initialization" );
+ }
+ impl_setChartModel( xNewChartModel );
+
+ if( !m_pDrawModelWrapper.get() )
+ {
+ // /--
+ ::vos::OGuard aSolarGuard( Application::GetSolarMutex());
+ m_pDrawModelWrapper = ::boost::shared_ptr< DrawModelWrapper >( new DrawModelWrapper( m_xCC ) );
+ m_xShapeFactory = m_pDrawModelWrapper->getShapeFactory();
+ m_xDrawPage = m_pDrawModelWrapper->getMainDrawPage();
+ StartListening( m_pDrawModelWrapper->getSdrModel(), FALSE /*bPreventDups*/ );
+ // \--
+ }
+}
+
+ChartView::~ChartView()
+{
+ if( m_pDrawModelWrapper.get() )
+ {
+ EndListening( m_pDrawModelWrapper->getSdrModel(), FALSE /*bAllDups*/ );
+ ::vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ m_pDrawModelWrapper.reset();
+ }
+ m_xDrawPage = NULL;
+ impl_deleteCoordinateSystems();
+}
+
+void ChartView::impl_deleteCoordinateSystems()
+{
+ //delete all coordinate systems
+ ::std::vector< VCoordinateSystem* > aVectorToDeleteObjects;
+ ::std::swap( aVectorToDeleteObjects, m_aVCooSysList );//#i109770#
+ ::std::vector< VCoordinateSystem* >::const_iterator aIter = aVectorToDeleteObjects.begin();
+ const ::std::vector< VCoordinateSystem* >::const_iterator aEnd = aVectorToDeleteObjects.end();
+ for( ; aIter != aEnd; aIter++ )
+ {
+ delete *aIter;
+ }
+ aVectorToDeleteObjects.clear();
+}
+
+
+//-----------------------------------------------------------------
+// datatransfer::XTransferable
+namespace
+{
+const rtl::OUString lcl_aGDIMetaFileMIMEType(
+ RTL_CONSTASCII_USTRINGPARAM("application/x-openoffice-gdimetafile;windows_formatname=\"GDIMetaFile\""));
+const rtl::OUString lcl_aGDIMetaFileMIMETypeHighContrast(
+ RTL_CONSTASCII_USTRINGPARAM("application/x-openoffice-highcontrast-gdimetafile;windows_formatname=\"GDIMetaFile\""));
+} // anonymous namespace
+
+void ChartView::getMetaFile( const uno::Reference< io::XOutputStream >& xOutStream
+ , bool bUseHighContrast )
+{
+ if( !m_xDrawPage.is() )
+ return;
+
+ uno::Reference< lang::XMultiServiceFactory > xFactory( m_xCC->getServiceManager(), uno::UNO_QUERY );
+ if( !xFactory.is() )
+ return;
+
+ // creating the graphic exporter
+ uno::Reference< document::XExporter > xExporter( xFactory->createInstance(
+ C2U("com.sun.star.drawing.GraphicExportFilter")), uno::UNO_QUERY);
+ uno::Reference< document::XFilter > xFilter( xExporter, uno::UNO_QUERY );
+
+ if( !xExporter.is() || !xFilter.is() )
+ return;
+
+ uno::Sequence< beans::PropertyValue > aProps(3);
+ aProps[0].Name = C2U("FilterName");
+ aProps[0].Value <<= C2U("SVM");
+
+ aProps[1].Name = C2U("OutputStream");
+ aProps[1].Value <<= xOutStream;
+
+ uno::Sequence< beans::PropertyValue > aFilterData(4);
+ aFilterData[0].Name = C2U("ExportOnlyBackground");
+ aFilterData[0].Value <<= sal_False;
+ aFilterData[1].Name = C2U("HighContrast");
+ aFilterData[1].Value <<= bUseHighContrast;
+
+ aFilterData[2].Name = C2U("Version");
+ const sal_Int32 nVersion = SOFFICE_FILEFORMAT_50;
+ aFilterData[2].Value <<= nVersion;
+
+ aFilterData[3].Name = C2U("CurrentPage");
+ aFilterData[3].Value <<= uno::Reference< uno::XInterface >( m_xDrawPage, uno::UNO_QUERY );
+
+ //#i75867# poor quality of ole's alternative view with 3D scenes and zoomfactors besides 100%
+ {
+ aFilterData.realloc( aFilterData.getLength()+4 );
+ aFilterData[4].Name = C2U("ScaleXNumerator");
+ aFilterData[4].Value = uno::makeAny( m_nScaleXNumerator );
+ aFilterData[5].Name = C2U("ScaleXDenominator");
+ aFilterData[5].Value = uno::makeAny( m_nScaleXDenominator );
+ aFilterData[6].Name = C2U("ScaleYNumerator");
+ aFilterData[6].Value = uno::makeAny( m_nScaleYNumerator );
+ aFilterData[7].Name = C2U("ScaleYDenominator");
+ aFilterData[7].Value = uno::makeAny( m_nScaleYDenominator );
+ }
+
+ aProps[2].Name = C2U("FilterData");
+ aProps[2].Value <<= aFilterData;
+
+ xExporter->setSourceDocument( uno::Reference< lang::XComponent >( m_xDrawPage, uno::UNO_QUERY) );
+ if( xFilter->filter( aProps ) )
+ {
+ xOutStream->flush();
+ xOutStream->closeOutput();
+ uno::Reference< io::XSeekable > xSeekable( xOutStream, uno::UNO_QUERY );
+ if( xSeekable.is() )
+ xSeekable->seek(0);
+ }
+}
+
+uno::Any SAL_CALL ChartView::getTransferData( const datatransfer::DataFlavor& aFlavor )
+ throw (datatransfer::UnsupportedFlavorException, io::IOException, uno::RuntimeException)
+{
+ bool bHighContrastMetaFile( aFlavor.MimeType.equals(lcl_aGDIMetaFileMIMETypeHighContrast));
+ uno::Any aRet;
+ if( ! (bHighContrastMetaFile || aFlavor.MimeType.equals(lcl_aGDIMetaFileMIMEType)) )
+ return aRet;
+
+ update();
+
+ SvMemoryStream aStream( 1024, 1024 );
+ utl::OStreamWrapper* pStreamWrapper = new utl::OStreamWrapper( aStream );
+
+ uno::Reference< io::XOutputStream > xOutStream( pStreamWrapper );
+ uno::Reference< io::XInputStream > xInStream( pStreamWrapper );
+ uno::Reference< io::XSeekable > xSeekable( pStreamWrapper );
+
+ if( xOutStream.is() )
+ {
+ this->getMetaFile( xOutStream, bHighContrastMetaFile );
+
+ if( xInStream.is() && xSeekable.is() )
+ {
+ xSeekable->seek(0);
+ sal_Int32 nBytesToRead = xInStream->available();
+ uno::Sequence< sal_Int8 > aSeq( nBytesToRead );
+ xInStream->readBytes( aSeq, nBytesToRead);
+ aRet <<= aSeq;
+ xInStream->closeInput();
+ }
+ }
+
+ return aRet;
+}
+uno::Sequence< datatransfer::DataFlavor > SAL_CALL ChartView::getTransferDataFlavors()
+ throw (uno::RuntimeException)
+{
+ uno::Sequence< datatransfer::DataFlavor > aRet(2);
+
+ aRet[0] = datatransfer::DataFlavor( lcl_aGDIMetaFileMIMEType,
+ C2U( "GDIMetaFile" ),
+ ::getCppuType( (const uno::Sequence< sal_Int8 >*) NULL ) );
+ aRet[1] = datatransfer::DataFlavor( lcl_aGDIMetaFileMIMETypeHighContrast,
+ C2U( "GDIMetaFile" ),
+ ::getCppuType( (const uno::Sequence< sal_Int8 >*) NULL ) );
+
+ return aRet;
+}
+::sal_Bool SAL_CALL ChartView::isDataFlavorSupported( const datatransfer::DataFlavor& aFlavor )
+ throw (uno::RuntimeException)
+{
+ return ( aFlavor.MimeType.equals(lcl_aGDIMetaFileMIMEType) ||
+ aFlavor.MimeType.equals(lcl_aGDIMetaFileMIMETypeHighContrast) );
+}
+
+//-----------------------------------------------------------------
+// ____ XUnoTunnel ___
+::sal_Int64 SAL_CALL ChartView::getSomething( const uno::Sequence< ::sal_Int8 >& aIdentifier )
+ throw( uno::RuntimeException)
+{
+ if( aIdentifier.getLength() == 16 && 0 == rtl_compareMemory( ExplicitValueProvider::getUnoTunnelId().getConstArray(),
+ aIdentifier.getConstArray(), 16 ) )
+ {
+ ExplicitValueProvider* pProvider = this;
+ return reinterpret_cast<sal_Int64>(pProvider);
+ }
+ return 0;
+}
+
+//-----------------------------------------------------------------
+// lang::XServiceInfo
+
+APPHELPER_XSERVICEINFO_IMPL(ChartView,CHART_VIEW_SERVICE_IMPLEMENTATION_NAME)
+
+ uno::Sequence< rtl::OUString > ChartView
+::getSupportedServiceNames_Static()
+{
+ uno::Sequence< rtl::OUString > aSNS( 1 );
+ aSNS.getArray()[ 0 ] = CHART_VIEW_SERVICE_NAME;
+ return aSNS;
+}
+
+//-----------------------------------------------------------------
+//-----------------------------------------------------------------
+
+::basegfx::B3DHomMatrix createTransformationSceneToScreen(
+ const ::basegfx::B2IRectangle& rDiagramRectangleWithoutAxes )
+{
+ ::basegfx::B3DHomMatrix aM;
+ aM.scale(double(rDiagramRectangleWithoutAxes.getWidth())/FIXED_SIZE_FOR_3D_CHART_VOLUME
+ , -double(rDiagramRectangleWithoutAxes.getHeight())/FIXED_SIZE_FOR_3D_CHART_VOLUME, 1.0 );
+ aM.translate(double(rDiagramRectangleWithoutAxes.getMinX())
+ , double(rDiagramRectangleWithoutAxes.getMinY()+rDiagramRectangleWithoutAxes.getHeight()-1), 0);
+ return aM;
+}
+
+VCoordinateSystem* findInCooSysList( const std::vector< VCoordinateSystem* >& rVCooSysList
+ , const uno::Reference< XCoordinateSystem >& xCooSys )
+{
+ for( size_t nC=0; nC < rVCooSysList.size(); nC++)
+ {
+ VCoordinateSystem* pVCooSys = rVCooSysList[nC];
+ if(pVCooSys->getModel()==xCooSys)
+ return pVCooSys;
+ }
+ return NULL;
+}
+
+VCoordinateSystem* addCooSysToList( std::vector< VCoordinateSystem* >& rVCooSysList
+ , const uno::Reference< XCoordinateSystem >& xCooSys
+ , const uno::Reference< frame::XModel >& xChartModel )
+{
+ VCoordinateSystem* pVCooSys = findInCooSysList( rVCooSysList, xCooSys );
+ if( !pVCooSys )
+ {
+ pVCooSys = VCoordinateSystem::createCoordinateSystem(xCooSys );
+ if(pVCooSys)
+ {
+ rtl::OUString aCooSysParticle( ObjectIdentifier::createParticleForCoordinateSystem( xCooSys, xChartModel ) );
+ pVCooSys->setParticle(aCooSysParticle);
+
+ pVCooSys->setExplicitCategoriesProvider( new ExplicitCategoriesProvider(xCooSys,xChartModel) );
+
+ rVCooSysList.push_back( pVCooSys );
+ }
+ }
+ return pVCooSys;
+}
+
+VCoordinateSystem* lcl_getCooSysForPlotter( const std::vector< VCoordinateSystem* >& rVCooSysList, MinimumAndMaximumSupplier* pMinimumAndMaximumSupplier )
+{
+ if(!pMinimumAndMaximumSupplier)
+ return 0;
+ for( size_t nC=0; nC < rVCooSysList.size(); nC++)
+ {
+ VCoordinateSystem* pVCooSys = rVCooSysList[nC];
+ if(pVCooSys->hasMinimumAndMaximumSupplier( pMinimumAndMaximumSupplier ))
+ return pVCooSys;
+ }
+ return 0;
+}
+
+typedef std::pair< sal_Int32, sal_Int32 > tFullAxisIndex; //first index is the dimension, second index is the axis index that indicates wether this is a main or secondary axis
+typedef std::pair< VCoordinateSystem* , tFullAxisIndex > tFullCoordinateSystem;
+typedef std::map< VCoordinateSystem*, tFullAxisIndex > tCoordinateSystemMap;
+
+struct AxisUsage
+{
+ AxisUsage();
+ ~AxisUsage();
+
+ void addCoordinateSystem( VCoordinateSystem* pCooSys, sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex );
+ ::std::vector< VCoordinateSystem* > getCoordinateSystems( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex );
+ sal_Int32 getMaxAxisIndexForDimension( sal_Int32 nDimensionIndex );
+ //tFullAxisIndex getDimensionAndIndexForCooSys( VCoordinateSystem* pCooSys );
+
+ ScaleAutomatism aScaleAutomatism;
+
+private:
+ tCoordinateSystemMap aCoordinateSystems;
+ std::map< sal_Int32, sal_Int32 > aMaxIndexPerDimension;
+};
+
+AxisUsage::AxisUsage()
+ : aScaleAutomatism(AxisHelper::createDefaultScale())
+{
+}
+
+AxisUsage::~AxisUsage()
+{
+ aCoordinateSystems.clear();
+}
+
+/*
+tFullScaleIndex AxisUsage::getDimensionAndIndexForCooSys( VCoordinateSystem* pCooSys )
+{
+ tFullScaleIndex aRet(0,0);
+
+ tCoordinateSystemMap::const_iterator aFound( aCoordinateSystems.find(pCooSys) );
+ if(aFound!=aCoordinateSystems.end())
+ aRet = aFound->second;
+
+ return aRet;
+}
+*/
+
+void AxisUsage::addCoordinateSystem( VCoordinateSystem* pCooSys, sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex )
+{
+ if(!pCooSys)
+ return;
+
+ tFullAxisIndex aFullAxisIndex( nDimensionIndex, nAxisIndex );
+ tCoordinateSystemMap::const_iterator aFound( aCoordinateSystems.find(pCooSys) );
+
+ //use one scale only once for each coordinate system
+ //main axis are preferred over secondary axis
+ //value scales are preferred
+ if(aFound!=aCoordinateSystems.end())
+ {
+ sal_Int32 nFoundAxisIndex = aFound->second.second;
+ if( nFoundAxisIndex < nAxisIndex )
+ return;
+ sal_Int32 nFoundDimension = aFound->second.first;
+ if( nFoundDimension ==1 )
+ return;
+ if( nFoundDimension < nDimensionIndex )
+ return;
+ }
+ aCoordinateSystems[pCooSys] = aFullAxisIndex;
+
+ //set maximum scale index
+ std::map< sal_Int32, sal_Int32 >::const_iterator aIter = aMaxIndexPerDimension.find(nDimensionIndex);
+ if( aIter != aMaxIndexPerDimension.end() )
+ {
+ sal_Int32 nCurrentMaxIndex = aIter->second;
+ if( nCurrentMaxIndex < nAxisIndex )
+ aMaxIndexPerDimension[nDimensionIndex]=nAxisIndex;
+ }
+ else
+ aMaxIndexPerDimension[nDimensionIndex]=nAxisIndex;
+}
+::std::vector< VCoordinateSystem* > AxisUsage::getCoordinateSystems( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex )
+{
+ ::std::vector< VCoordinateSystem* > aRet;
+
+ tCoordinateSystemMap::const_iterator aIter;
+ for( aIter = aCoordinateSystems.begin(); aIter!=aCoordinateSystems.end();++aIter )
+ {
+ if( aIter->second.first != nDimensionIndex )
+ continue;
+ if( aIter->second.second != nAxisIndex )
+ continue;
+ aRet.push_back( aIter->first );
+ }
+
+ return aRet;
+}
+sal_Int32 AxisUsage::getMaxAxisIndexForDimension( sal_Int32 nDimensionIndex )
+{
+ sal_Int32 nRet = -1;
+ std::map< sal_Int32, sal_Int32 >::const_iterator aIter = aMaxIndexPerDimension.find(nDimensionIndex);
+ if( aIter != aMaxIndexPerDimension.end() )
+ nRet = aIter->second;
+ return nRet;
+}
+
+//-----------------------------------------------------
+
+class SeriesPlotterContainer
+{
+public:
+ SeriesPlotterContainer( std::vector< VCoordinateSystem* >& rVCooSysList );
+ ~SeriesPlotterContainer();
+
+ void initializeCooSysAndSeriesPlotter( const uno::Reference< frame::XModel >& xChartModel );
+ void initAxisUsageList();
+ void doAutoScaling( const uno::Reference< frame::XModel >& xChartModel );
+ void updateScalesAndIncrementsOnAxes();
+ void setScalesFromCooSysToPlotter();
+ void setNumberFormatsFromAxes();
+ drawing::Direction3D getPreferredAspectRatio();
+
+ std::vector< VSeriesPlotter* >& getSeriesPlotterList() { return m_aSeriesPlotterList; }
+ std::vector< VCoordinateSystem* >& getCooSysList() { return m_rVCooSysList; }
+ std::vector< LegendEntryProvider* > getLegendEntryProviderList();
+
+ void AdaptScaleOfYAxisWithoutAttachedSeries( const uno::Reference< frame::XModel >& xChartModel );
+
+private:
+ std::vector< VSeriesPlotter* > m_aSeriesPlotterList;
+ std::vector< VCoordinateSystem* >& m_rVCooSysList;
+ ::std::map< uno::Reference< XAxis >, AxisUsage > m_aAxisUsageList;
+ sal_Int32 m_nMaxAxisIndex;
+ bool m_bChartTypeUsesShiftedXAxisTicksPerDefault;
+};
+
+SeriesPlotterContainer::SeriesPlotterContainer( std::vector< VCoordinateSystem* >& rVCooSysList )
+ : m_rVCooSysList( rVCooSysList )
+ , m_nMaxAxisIndex(0)
+ , m_bChartTypeUsesShiftedXAxisTicksPerDefault(false)
+{
+}
+
+SeriesPlotterContainer::~SeriesPlotterContainer()
+{
+ // - remove plotter from coordinatesystems
+ for( size_t nC=0; nC < m_rVCooSysList.size(); nC++)
+ m_rVCooSysList[nC]->clearMinimumAndMaximumSupplierList();
+ // - delete all plotter
+ ::std::vector< VSeriesPlotter* >::const_iterator aPlotterIter = m_aSeriesPlotterList.begin();
+ const ::std::vector< VSeriesPlotter* >::const_iterator aPlotterEnd = m_aSeriesPlotterList.end();
+ for( aPlotterIter = m_aSeriesPlotterList.begin(); aPlotterIter != aPlotterEnd; aPlotterIter++ )
+ delete *aPlotterIter;
+ m_aSeriesPlotterList.clear();
+}
+
+std::vector< LegendEntryProvider* > SeriesPlotterContainer::getLegendEntryProviderList()
+{
+ std::vector< LegendEntryProvider* > aRet( m_aSeriesPlotterList.size() );
+ ::std::vector< VSeriesPlotter* >::const_iterator aPlotterIter = m_aSeriesPlotterList.begin();
+ const ::std::vector< VSeriesPlotter* >::const_iterator aPlotterEnd = m_aSeriesPlotterList.end();
+ sal_Int32 nN = 0;
+ for( aPlotterIter = m_aSeriesPlotterList.begin(); aPlotterIter != aPlotterEnd; ++aPlotterIter, nN++ )
+ aRet[nN] = *aPlotterIter;
+ return aRet;
+}
+
+void SeriesPlotterContainer::initializeCooSysAndSeriesPlotter(
+ const uno::Reference< frame::XModel >& xChartModel )
+{
+ //------------ get model series from model
+ sal_Int32 nDiagramIndex = 0;//todo if more than one diagam is supported
+ uno::Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartModel ) );
+ if( !xDiagram.is())
+ return;
+
+ uno::Reference< util::XNumberFormatsSupplier > xNumberFormatsSupplier( xChartModel, uno::UNO_QUERY );
+
+ sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram );
+ if(!nDimensionCount)
+ {
+ //@todo handle mixed dimension
+ nDimensionCount = 2;
+ }
+
+ sal_Bool bSortByXValues = sal_False;
+ sal_Bool bConnectBars = sal_False;
+ sal_Bool bGroupBarsPerAxis = sal_True;
+ sal_Bool bIncludeHiddenCells = sal_True;
+ sal_Int32 nStartingAngle = 90;
+ try
+ {
+ uno::Reference< beans::XPropertySet > xDiaProp( xDiagram, uno::UNO_QUERY_THROW );
+ xDiaProp->getPropertyValue( C2U( "SortByXValues" ) ) >>= bSortByXValues;
+ xDiaProp->getPropertyValue( C2U( "ConnectBars" ) ) >>= bConnectBars;
+ xDiaProp->getPropertyValue( C2U( "GroupBarsPerAxis" ) ) >>= bGroupBarsPerAxis;
+ xDiaProp->getPropertyValue( C2U( "IncludeHiddenCells" ) ) >>= bIncludeHiddenCells;
+ xDiaProp->getPropertyValue( C2U( "StartingAngle" ) ) >>= nStartingAngle;
+ }
+ catch( const uno::Exception & ex )
+ {
+ ASSERT_EXCEPTION( ex );
+ }
+
+ //---------------------------------------------------------------------
+ //prepare for autoscaling and shape creation
+ // - create plotter for charttypes (for each first scale group at each plotter, as they are independent)
+ // - add series to plotter (thus each charttype can provide minimum and maximum values for autoscaling)
+ // - add plotter to coordinate systems
+
+ //iterate through all coordinate systems
+ uno::Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY );
+ OSL_ASSERT( xCooSysContainer.is());
+ if( !xCooSysContainer.is())
+ return;
+ uno::Reference< XColorScheme > xColorScheme( xDiagram->getDefaultColorScheme());
+ uno::Sequence< uno::Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() );
+ sal_Int32 nGlobalSeriesIndex = 0;//for automatic symbols
+ for( sal_Int32 nCS = 0; nCS < aCooSysList.getLength(); ++nCS )
+ {
+ uno::Reference< XCoordinateSystem > xCooSys( aCooSysList[nCS] );
+ VCoordinateSystem* pVCooSys = addCooSysToList(m_rVCooSysList,xCooSys,xChartModel);
+
+ //iterate through all chart types in the current coordinate system
+ uno::Reference< XChartTypeContainer > xChartTypeContainer( xCooSys, uno::UNO_QUERY );
+ OSL_ASSERT( xChartTypeContainer.is());
+ if( !xChartTypeContainer.is() )
+ continue;
+ uno::Sequence< uno::Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() );
+ for( sal_Int32 nT = 0; nT < aChartTypeList.getLength(); ++nT )
+ {
+ uno::Reference< XChartType > xChartType( aChartTypeList[nT] );
+
+ if(nT==0)
+ m_bChartTypeUsesShiftedXAxisTicksPerDefault = ChartTypeHelper::shiftTicksAtXAxisPerDefault( xChartType );
+
+ bool bExcludingPositioning = DiagramPositioningMode_EXCLUDING == DiagramHelper::getDiagramPositioningMode( xDiagram );
+ VSeriesPlotter* pPlotter = VSeriesPlotter::createSeriesPlotter( xChartType, nDimensionCount, bExcludingPositioning );
+ if( !pPlotter )
+ continue;
+ m_aSeriesPlotterList.push_back( pPlotter );
+ pPlotter->setNumberFormatsSupplier( xNumberFormatsSupplier );
+ pPlotter->setColorScheme( xColorScheme );
+ pPlotter->setExplicitCategoriesProvider( pVCooSys->getExplicitCategoriesProvider() );
+ sal_Int32 nMissingValueTreatment = DiagramHelper::getCorrectedMissingValueTreatment( xDiagram, xChartType );
+
+ if(pVCooSys)
+ pVCooSys->addMinimumAndMaximumSupplier(pPlotter);
+
+ //------------ add series to plotter and thus prepare him for providing minimum and maximum values
+ uno::Reference< XDataSeriesContainer > xDataSeriesContainer( xChartType, uno::UNO_QUERY );
+ OSL_ASSERT( xDataSeriesContainer.is());
+ if( !xDataSeriesContainer.is() )
+ continue;
+ sal_Int32 zSlot=-1;
+ sal_Int32 xSlot=-1;
+ sal_Int32 ySlot=-1;
+ uno::Sequence< uno::Reference< XDataSeries > > aSeriesList( xDataSeriesContainer->getDataSeries() );
+ for( sal_Int32 nS = 0; nS < aSeriesList.getLength(); ++nS )
+ {
+ uno::Reference< XDataSeries > xDataSeries( aSeriesList[nS], uno::UNO_QUERY );
+ if(!xDataSeries.is())
+ continue;
+ if( !bIncludeHiddenCells && !DataSeriesHelper::hasUnhiddenData(xDataSeries) )
+ continue;
+
+ VDataSeries* pSeries = new VDataSeries( xDataSeries );
+
+ pSeries->setGlobalSeriesIndex(nGlobalSeriesIndex);
+ nGlobalSeriesIndex++;
+
+ if( bSortByXValues )
+ pSeries->doSortByXValues();
+
+ pSeries->setConnectBars( bConnectBars );
+ pSeries->setGroupBarsPerAxis( bGroupBarsPerAxis );
+ pSeries->setStartingAngle( nStartingAngle );
+
+ pSeries->setMissingValueTreatment( nMissingValueTreatment );
+
+ rtl::OUString aSeriesParticle( ObjectIdentifier::createParticleForSeries( nDiagramIndex, nCS, nT, nS ) );
+ pSeries->setParticle(aSeriesParticle);
+
+ OUString aRole( ChartTypeHelper::getRoleOfSequenceForDataLabelNumberFormatDetection( xChartType ) );
+ pSeries->setRoleOfSequenceForDataLabelNumberFormatDetection(aRole);
+
+ //ignore secondary axis for charttypes that do not suppoert them
+ if( pSeries->getAttachedAxisIndex() != MAIN_AXIS_INDEX &&
+ !ChartTypeHelper::isSupportingSecondaryAxis( xChartType, nDimensionCount, 1 ) )
+ {
+ pSeries->setAttachedAxisIndex(MAIN_AXIS_INDEX);
+ }
+
+ StackingDirection eDirection = pSeries->getStackingDirection();
+ switch(eDirection)
+ {
+ case StackingDirection_NO_STACKING:
+ xSlot++; ySlot=-1;
+ if(zSlot<0)
+ zSlot=0;
+ break;
+ case StackingDirection_Y_STACKING:
+ ySlot++;
+ if(xSlot<0)
+ xSlot=0;
+ if(zSlot<0)
+ zSlot=0;
+ break;
+ case StackingDirection_Z_STACKING:
+ zSlot++; xSlot=-1; ySlot=-1;
+ break;
+ default:
+ // UNO enums have one additional auto-generated case
+ break;
+ }
+ pPlotter->addSeries( pSeries, zSlot, xSlot, ySlot );
+ }
+ }
+ }
+
+ //transport seriesnames to the coordinatesystems if needed
+ if( m_aSeriesPlotterList.size() )
+ {
+ uno::Sequence< rtl::OUString > aSeriesNames;
+ bool bSeriesNamesInitialized = false;
+ for( size_t nC=0; nC < m_rVCooSysList.size(); nC++)
+ {
+ VCoordinateSystem* pVCooSys = m_rVCooSysList[nC];
+ if(!pVCooSys)
+ continue;
+ if( pVCooSys->needSeriesNamesForAxis() )
+ {
+ if(!bSeriesNamesInitialized)
+ {
+ VSeriesPlotter* pSeriesPlotter = m_aSeriesPlotterList[0];
+ if( pSeriesPlotter )
+ aSeriesNames = pSeriesPlotter->getSeriesNames();
+ bSeriesNamesInitialized = true;
+ }
+ pVCooSys->setSeriesNamesForAxis( aSeriesNames );
+ }
+ }
+ }
+}
+
+void SeriesPlotterContainer::initAxisUsageList()
+{
+ m_aAxisUsageList.clear();
+ size_t nC;
+ for( nC=0; nC < m_rVCooSysList.size(); nC++)
+ {
+ VCoordinateSystem* pVCooSys = m_rVCooSysList[nC];
+ for(sal_Int32 nDimensionIndex=0; nDimensionIndex<3; nDimensionIndex++)
+ {
+ uno::Reference< XCoordinateSystem > xCooSys = pVCooSys->getModel();
+ if( nDimensionIndex >= xCooSys->getDimension() )
+ continue;
+ const sal_Int32 nMaximumAxisIndex = xCooSys->getMaximumAxisIndexByDimension(nDimensionIndex);
+ for(sal_Int32 nAxisIndex=0; nAxisIndex<=nMaximumAxisIndex; ++nAxisIndex)
+ {
+ uno::Reference< XAxis > xAxis( xCooSys->getAxisByDimension( nDimensionIndex, nAxisIndex ) );
+ OSL_ASSERT( xAxis.is());
+ if( xAxis.is())
+ {
+ if(m_aAxisUsageList.find(xAxis)==m_aAxisUsageList.end())
+ m_aAxisUsageList[xAxis].aScaleAutomatism = ScaleAutomatism(xAxis->getScaleData());
+ AxisUsage& rAxisUsage = m_aAxisUsageList[xAxis];
+ rAxisUsage.addCoordinateSystem(pVCooSys,nDimensionIndex,nAxisIndex);
+ }
+ }
+ }
+ }
+
+ ::std::map< uno::Reference< XAxis >, AxisUsage >::iterator aAxisIter = m_aAxisUsageList.begin();
+ const ::std::map< uno::Reference< XAxis >, AxisUsage >::const_iterator aAxisEndIter = m_aAxisUsageList.end();
+
+ //init m_nMaxAxisIndex
+ m_nMaxAxisIndex = 0;
+ for(sal_Int32 nDimensionIndex=0; nDimensionIndex<3; nDimensionIndex++)
+ {
+ for( aAxisIter = m_aAxisUsageList.begin(); aAxisIter != aAxisEndIter; aAxisIter++ )
+ {
+ sal_Int32 nLocalMax = aAxisIter->second.getMaxAxisIndexForDimension( nDimensionIndex );
+ if( m_nMaxAxisIndex < nLocalMax )
+ m_nMaxAxisIndex = nLocalMax;
+ }
+ }
+}
+
+void SeriesPlotterContainer::setScalesFromCooSysToPlotter()
+{
+ //set scales to plotter to enable them to provide the preferred scene AspectRatio
+ ::std::vector< VSeriesPlotter* >::const_iterator aPlotterIter = m_aSeriesPlotterList.begin();
+ const ::std::vector< VSeriesPlotter* >::const_iterator aPlotterEnd = m_aSeriesPlotterList.end();
+ for( aPlotterIter = m_aSeriesPlotterList.begin(); aPlotterIter != aPlotterEnd; aPlotterIter++ )
+ {
+ VSeriesPlotter* pSeriesPlotter = *aPlotterIter;
+ VCoordinateSystem* pVCooSys = lcl_getCooSysForPlotter( m_rVCooSysList, pSeriesPlotter );
+ if(pVCooSys)
+ {
+ pSeriesPlotter->setScales( pVCooSys->getExplicitScales(0,0), pVCooSys->getPropertySwapXAndYAxis() );
+ sal_Int32 nMaxAxisIndex = pVCooSys->getMaximumAxisIndexByDimension(1);//only additional value axis are relevant for series plotter
+ for( sal_Int32 nI=1; nI<=nMaxAxisIndex; nI++ )
+ pSeriesPlotter->addSecondaryValueScale( pVCooSys->getExplicitScale(1,nI), nI );
+ }
+ }
+}
+
+void SeriesPlotterContainer::setNumberFormatsFromAxes()
+{
+ //set numberfarmats to plotter to enable them to display the data labels in the numberfromat of teh axis
+
+ ::std::vector< VSeriesPlotter* >::const_iterator aPlotterIter = m_aSeriesPlotterList.begin();
+ const ::std::vector< VSeriesPlotter* >::const_iterator aPlotterEnd = m_aSeriesPlotterList.end();
+ for( aPlotterIter = m_aSeriesPlotterList.begin(); aPlotterIter != aPlotterEnd; aPlotterIter++ )
+ {
+ VSeriesPlotter* pSeriesPlotter = *aPlotterIter;
+ VCoordinateSystem* pVCooSys = lcl_getCooSysForPlotter( m_rVCooSysList, pSeriesPlotter );
+ if(pVCooSys)
+ {
+ AxesNumberFormats aAxesNumberFormats;
+ uno::Reference< XCoordinateSystem > xCooSys = pVCooSys->getModel();
+ sal_Int32 nDimensionCount = xCooSys->getDimension();
+ for(sal_Int32 nDimensionIndex=0; nDimensionIndex<nDimensionCount; ++nDimensionIndex)
+ {
+ const sal_Int32 nMaximumAxisIndex = xCooSys->getMaximumAxisIndexByDimension(nDimensionIndex);
+ for(sal_Int32 nAxisIndex=0; nAxisIndex<=nMaximumAxisIndex; ++nAxisIndex)
+ {
+ try
+ {
+ Reference< beans::XPropertySet > xAxisProp( xCooSys->getAxisByDimension( nDimensionIndex, nAxisIndex ), uno::UNO_QUERY );
+ if( xAxisProp.is())
+ {
+ sal_Int32 nNumberFormatKey(0);
+ if( xAxisProp->getPropertyValue( C2U( "NumberFormat" ) ) >>= nNumberFormatKey )
+ {
+ aAxesNumberFormats.setFormat( nNumberFormatKey, nDimensionIndex, nAxisIndex );
+ }
+ }
+ }
+ catch( lang::IndexOutOfBoundsException& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+ }
+ }
+ pSeriesPlotter->setAxesNumberFormats( aAxesNumberFormats );
+ }
+ }
+}
+
+void SeriesPlotterContainer::updateScalesAndIncrementsOnAxes()
+{
+ for( size_t nC=0; nC < m_rVCooSysList.size(); nC++)
+ m_rVCooSysList[nC]->updateScalesAndIncrementsOnAxes();
+}
+
+void SeriesPlotterContainer::doAutoScaling( const uno::Reference< frame::XModel >& xChartModel )
+{
+ //precondition: need a initialized m_aSeriesPlotterList
+ //precondition: need a initialized m_aAxisUsageList
+
+ ::std::map< uno::Reference< XAxis >, AxisUsage >::iterator aAxisIter = m_aAxisUsageList.begin();
+ const ::std::map< uno::Reference< XAxis >, AxisUsage >::const_iterator aAxisEndIter = m_aAxisUsageList.end();
+
+ //iterate over the main scales first than secondary axis
+ size_t nC;
+ sal_Int32 nAxisIndex=0;
+ for( nAxisIndex=0; nAxisIndex<=m_nMaxAxisIndex; nAxisIndex++ )
+ {
+
+ // - first do autoscale for all x and z scales (because they are treated independent)
+ for( aAxisIter = m_aAxisUsageList.begin(); aAxisIter != aAxisEndIter; aAxisIter++ )
+ {
+ AxisUsage& rAxisUsage = (*aAxisIter).second;
+ ::std::vector< VCoordinateSystem* > aVCooSysList_X = rAxisUsage.getCoordinateSystems(0,nAxisIndex);
+ ::std::vector< VCoordinateSystem* > aVCooSysList_Z = rAxisUsage.getCoordinateSystems(2,nAxisIndex);
+
+ for( nC=0; nC < aVCooSysList_X.size(); nC++)
+ aVCooSysList_X[nC]->prepareScaleAutomatismForDimensionAndIndex(rAxisUsage.aScaleAutomatism,0,nAxisIndex);
+ for( nC=0; nC < aVCooSysList_Z.size(); nC++)
+ aVCooSysList_Z[nC]->prepareScaleAutomatismForDimensionAndIndex(rAxisUsage.aScaleAutomatism,2,nAxisIndex);
+
+ ExplicitScaleData aExplicitScale;
+ ExplicitIncrementData aExplicitIncrement;
+ rAxisUsage.aScaleAutomatism.calculateExplicitScaleAndIncrement( aExplicitScale, aExplicitIncrement );
+
+ for( nC=0; nC < aVCooSysList_X.size(); nC++)
+ {
+ ExplicitCategoriesProvider* pExplicitCategoriesProvider = aVCooSysList_X[nC]->getExplicitCategoriesProvider();
+
+ if( m_bChartTypeUsesShiftedXAxisTicksPerDefault || (aExplicitScale.AxisType==AxisType::CATEGORY && pExplicitCategoriesProvider && pExplicitCategoriesProvider->hasComplexCategories() ) )
+ aExplicitIncrement.ShiftedPosition = true;
+ aVCooSysList_X[nC]->setExplicitScaleAndIncrement( 0, nAxisIndex, aExplicitScale, aExplicitIncrement );
+ }
+ for( nC=0; nC < aVCooSysList_Z.size(); nC++)
+ aVCooSysList_Z[nC]->setExplicitScaleAndIncrement( 2, nAxisIndex, aExplicitScale, aExplicitIncrement );
+ }
+
+ // - second do autoscale for the dependent y scales (the coordinate systems are prepared with x and z scales already )
+ for( aAxisIter = m_aAxisUsageList.begin(); aAxisIter != aAxisEndIter; aAxisIter++ )
+ {
+ AxisUsage& rAxisUsage = (*aAxisIter).second;
+ ::std::vector< VCoordinateSystem* > aVCooSysList_X = rAxisUsage.getCoordinateSystems(0,nAxisIndex);
+ ::std::vector< VCoordinateSystem* > aVCooSysList_Y = rAxisUsage.getCoordinateSystems(1,nAxisIndex);
+ ::std::vector< VCoordinateSystem* > aVCooSysList_Z = rAxisUsage.getCoordinateSystems(2,nAxisIndex);
+
+ if(!aVCooSysList_Y.size())
+ continue;
+
+ for( nC=0; nC < aVCooSysList_Y.size(); nC++)
+ aVCooSysList_Y[nC]->prepareScaleAutomatismForDimensionAndIndex(rAxisUsage.aScaleAutomatism,1,nAxisIndex);
+
+ ExplicitScaleData aExplicitScale;
+ ExplicitIncrementData aExplicitIncrement;
+ rAxisUsage.aScaleAutomatism.calculateExplicitScaleAndIncrement( aExplicitScale, aExplicitIncrement );
+
+ for( nC=0; nC < aVCooSysList_X.size(); nC++)
+ aVCooSysList_X[nC]->setExplicitScaleAndIncrement( 0, nAxisIndex, aExplicitScale, aExplicitIncrement );
+ for( nC=0; nC < aVCooSysList_Y.size(); nC++)
+ aVCooSysList_Y[nC]->setExplicitScaleAndIncrement( 1, nAxisIndex, aExplicitScale, aExplicitIncrement );
+ for( nC=0; nC < aVCooSysList_Z.size(); nC++)
+ aVCooSysList_Z[nC]->setExplicitScaleAndIncrement( 2, nAxisIndex, aExplicitScale, aExplicitIncrement );
+ }
+ }
+ AdaptScaleOfYAxisWithoutAttachedSeries( xChartModel );
+}
+
+void SeriesPlotterContainer::AdaptScaleOfYAxisWithoutAttachedSeries( const uno::Reference< frame::XModel >& xChartModel )
+{
+ //issue #i80518#
+
+ ::std::map< uno::Reference< XAxis >, AxisUsage >::iterator aAxisIter = m_aAxisUsageList.begin();
+ const ::std::map< uno::Reference< XAxis >, AxisUsage >::const_iterator aAxisEndIter = m_aAxisUsageList.end();
+
+ for( sal_Int32 nAxisIndex=0; nAxisIndex<=m_nMaxAxisIndex; nAxisIndex++ )
+ {
+ for( aAxisIter = m_aAxisUsageList.begin(); aAxisIter != aAxisEndIter; aAxisIter++ )
+ {
+ AxisUsage& rAxisUsage = (*aAxisIter).second;
+ ::std::vector< VCoordinateSystem* > aVCooSysList_Y = rAxisUsage.getCoordinateSystems( 1, nAxisIndex );
+ if( !aVCooSysList_Y.size() )
+ continue;
+
+ uno::Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartModel ) );
+ if( xDiagram.is() )
+ {
+ bool bSeriesAttachedToThisAxis = false;
+ sal_Int32 nAttachedAxisIndex = -1;
+ {
+ ::std::vector< Reference< XDataSeries > > aSeriesVector( DiagramHelper::getDataSeriesFromDiagram( xDiagram ) );
+ ::std::vector< Reference< XDataSeries > >::const_iterator aIter = aSeriesVector.begin();
+ for( ; aIter != aSeriesVector.end(); aIter++ )
+ {
+ sal_Int32 nCurrentIndex = DataSeriesHelper::getAttachedAxisIndex( *aIter );
+ if( nAxisIndex == nCurrentIndex )
+ {
+ bSeriesAttachedToThisAxis = true;
+ break;
+ }
+ else if( nAttachedAxisIndex<0 || nAttachedAxisIndex>nCurrentIndex )
+ nAttachedAxisIndex=nCurrentIndex;
+ }
+ }
+
+ if( !bSeriesAttachedToThisAxis && nAttachedAxisIndex >= 0 )
+ {
+ for( size_t nC = 0; nC < aVCooSysList_Y.size(); ++nC )
+ {
+ aVCooSysList_Y[nC]->prepareScaleAutomatismForDimensionAndIndex( rAxisUsage.aScaleAutomatism, 1, nAttachedAxisIndex );
+
+ ExplicitScaleData aExplicitScaleSource = aVCooSysList_Y[nC]->getExplicitScale( 1,nAttachedAxisIndex );
+ ExplicitIncrementData aExplicitIncrementSource = aVCooSysList_Y[nC]->getExplicitIncrement( 1,nAttachedAxisIndex );
+
+ ExplicitScaleData aExplicitScaleDest = aVCooSysList_Y[nC]->getExplicitScale( 1,nAxisIndex );;
+ ExplicitIncrementData aExplicitIncrementDest = aVCooSysList_Y[nC]->getExplicitIncrement( 1,nAxisIndex );;
+
+ aExplicitScaleDest.Orientation = aExplicitScaleSource.Orientation;
+ aExplicitScaleDest.Scaling = aExplicitScaleSource.Scaling;
+ aExplicitScaleDest.Breaks = aExplicitScaleSource.Breaks;
+ aExplicitScaleDest.AxisType = aExplicitScaleSource.AxisType;
+
+ aExplicitIncrementDest.BaseValue = aExplicitIncrementSource.BaseValue;
+
+ ScaleData aScale( rAxisUsage.aScaleAutomatism.getScale() );
+ if( !aScale.Minimum.hasValue() )
+ {
+ bool bNewMinOK = true;
+ double fMax=0.0;
+ if( aScale.Maximum >>= fMax )
+ bNewMinOK = (aExplicitScaleSource.Minimum <= fMax);
+ if( bNewMinOK )
+ aExplicitScaleDest.Minimum = aExplicitScaleSource.Minimum;
+ }
+ else
+ aExplicitIncrementDest.BaseValue = aExplicitScaleDest.Minimum;
+
+ if( !aScale.Maximum.hasValue() )
+ {
+ bool bNewMaxOK = true;
+ double fMin=0.0;
+ if( aScale.Minimum >>= fMin )
+ bNewMaxOK = (fMin <= aExplicitScaleSource.Maximum);
+ if( bNewMaxOK )
+ aExplicitScaleDest.Maximum = aExplicitScaleSource.Maximum;
+ }
+ if( !aScale.Origin.hasValue() )
+ aExplicitScaleDest.Origin = aExplicitScaleSource.Origin;
+
+ if( !aScale.IncrementData.Distance.hasValue() )
+ aExplicitIncrementDest.Distance = aExplicitIncrementSource.Distance;
+
+ bool bAutoMinorInterval = true;
+ if( aScale.IncrementData.SubIncrements.getLength() )
+ bAutoMinorInterval = !( aScale.IncrementData.SubIncrements[0].IntervalCount.hasValue() );
+ if( bAutoMinorInterval )
+ {
+ if( aExplicitIncrementDest.SubIncrements.getLength() && aExplicitIncrementSource.SubIncrements.getLength() )
+ aExplicitIncrementDest.SubIncrements[0].IntervalCount =
+ aExplicitIncrementSource.SubIncrements[0].IntervalCount;
+ }
+
+ aVCooSysList_Y[nC]->setExplicitScaleAndIncrement( 1, nAxisIndex, aExplicitScaleDest, aExplicitIncrementDest );
+ }
+ }
+ }
+ }
+ }
+
+ if( AxisHelper::isAxisPositioningEnabled() )
+ {
+ //correct origin for y main axis (the origin is where the other main axis crosses)
+ sal_Int32 nAxisIndex=0;
+ sal_Int32 nDimensionIndex=1;
+ for( aAxisIter = m_aAxisUsageList.begin(); aAxisIter != aAxisEndIter; aAxisIter++ )
+ {
+ AxisUsage& rAxisUsage = (*aAxisIter).second;
+ ::std::vector< VCoordinateSystem* > aVCooSysList = rAxisUsage.getCoordinateSystems(nDimensionIndex,nAxisIndex);
+ size_t nC;
+ for( nC=0; nC < aVCooSysList.size(); nC++)
+ {
+ ExplicitScaleData aExplicitScale( aVCooSysList[nC]->getExplicitScale( nDimensionIndex, nAxisIndex ) );
+ ExplicitIncrementData aExplicitIncrement( aVCooSysList[nC]->getExplicitIncrement( nDimensionIndex, nAxisIndex ) );
+
+ Reference< chart2::XCoordinateSystem > xCooSys( aVCooSysList[nC]->getModel() );
+ Reference< XAxis > xAxis( xCooSys->getAxisByDimension( nDimensionIndex, nAxisIndex ) );
+ Reference< beans::XPropertySet > xCrossingMainAxis( AxisHelper::getCrossingMainAxis( xAxis, xCooSys ), uno::UNO_QUERY );
+
+ ::com::sun::star::chart::ChartAxisPosition eCrossingMainAxisPos( ::com::sun::star::chart::ChartAxisPosition_ZERO );
+ if( xCrossingMainAxis.is() )
+ {
+ xCrossingMainAxis->getPropertyValue(C2U( "CrossoverPosition" )) >>= eCrossingMainAxisPos;
+ if( ::com::sun::star::chart::ChartAxisPosition_VALUE == eCrossingMainAxisPos )
+ {
+ double fValue = 0.0;
+ xCrossingMainAxis->getPropertyValue(C2U( "CrossoverValue" )) >>= fValue;
+ aExplicitScale.Origin = fValue;
+ }
+ else if( ::com::sun::star::chart::ChartAxisPosition_ZERO == eCrossingMainAxisPos )
+ aExplicitScale.Origin = 0.0;
+ else if( ::com::sun::star::chart::ChartAxisPosition_START == eCrossingMainAxisPos )
+ aExplicitScale.Origin = aExplicitScale.Minimum;
+ else if( ::com::sun::star::chart::ChartAxisPosition_END == eCrossingMainAxisPos )
+ aExplicitScale.Origin = aExplicitScale.Maximum;
+ }
+
+ aVCooSysList[nC]->setExplicitScaleAndIncrement( nDimensionIndex, nAxisIndex, aExplicitScale, aExplicitIncrement );
+ }
+ }
+ }
+}
+
+drawing::Direction3D SeriesPlotterContainer::getPreferredAspectRatio()
+{
+ drawing::Direction3D aPreferredAspectRatio(1.0,1.0,1.0);
+
+ sal_Int32 nPlotterCount=0;
+ //get a list of all preferred aspect ratios and combine them
+ //first with special demands wins (less or equal zero <-> arbitrary)
+ double fx, fy, fz;
+ fx = fy = fz = -1.0;
+ ::std::vector< VSeriesPlotter* >::const_iterator aPlotterIter = m_aSeriesPlotterList.begin();
+ const ::std::vector< VSeriesPlotter* >::const_iterator aPlotterEnd = m_aSeriesPlotterList.end();
+ for( aPlotterIter = m_aSeriesPlotterList.begin(), nPlotterCount=0
+ ; aPlotterIter != aPlotterEnd; aPlotterIter++, nPlotterCount++ )
+ {
+ drawing::Direction3D aSingleRatio( (*aPlotterIter)->getPreferredDiagramAspectRatio() );
+ if( fx<0 && aSingleRatio.DirectionX>0 )
+ fx = aSingleRatio.DirectionX;
+
+ if( fy<0 && aSingleRatio.DirectionY>0 )
+ {
+ if( fx>0 && aSingleRatio.DirectionX>0 )
+ fy = fx*aSingleRatio.DirectionY/aSingleRatio.DirectionX;
+ else if( fz>0 && aSingleRatio.DirectionZ>0 )
+ fy = fz*aSingleRatio.DirectionY/aSingleRatio.DirectionZ;
+ else
+ fy = aSingleRatio.DirectionY;
+ }
+
+ if( fz<0 && aSingleRatio.DirectionZ>0 )
+ {
+ if( fx>0 && aSingleRatio.DirectionX>0 )
+ fz = fx*aSingleRatio.DirectionZ/aSingleRatio.DirectionX;
+ else if( fy>0 && aSingleRatio.DirectionY>0 )
+ fz = fy*aSingleRatio.DirectionZ/aSingleRatio.DirectionY;
+ else
+ fz = aSingleRatio.DirectionZ;
+ }
+
+ if( fx>0 && fy>0 && fz>0 )
+ break;
+ }
+ aPreferredAspectRatio = drawing::Direction3D(fx, fy, fz);
+ return aPreferredAspectRatio;
+}
+
+//-----------------------------------------------------
+
+namespace
+{
+
+bool lcl_IsPieOrDonut( const uno::Reference< XDiagram >& xDiagram )
+{
+ //special treatment for pie charts
+ //the size is checked after complete creation to get the datalabels into the given space
+
+ //todo: this is just a workaround at the moment for pie and donut labels
+ return DiagramHelper::isPieOrDonutChart( xDiagram );
+}
+
+void lcl_setDefaultWritingMode( ::boost::shared_ptr< DrawModelWrapper > pDrawModelWrapper, const Reference< frame::XModel >& xChartModel )
+{
+ //get writing mode from parent document:
+ if( SvtLanguageOptions().IsCTLFontEnabled() )
+ {
+ try
+ {
+ uno::Reference< container::XChild > xChild( xChartModel, uno::UNO_QUERY );
+ sal_Int16 nWritingMode=-1;
+ if ( xChild.is() )
+ {
+ uno::Reference< beans::XPropertySet > xParentProps( xChild->getParent(), uno::UNO_QUERY );
+ uno::Reference< style::XStyleFamiliesSupplier > xStyleFamiliesSupplier( xParentProps, uno::UNO_QUERY );
+ if( xStyleFamiliesSupplier.is() )
+ {
+ uno::Reference< container::XNameAccess > xStylesFamilies( xStyleFamiliesSupplier->getStyleFamilies() );
+ if( xStylesFamilies.is() )
+ {
+ if( !xStylesFamilies->hasByName( C2U("PageStyles") ) )
+ {
+ //draw/impress is parent document
+ uno::Reference< lang::XMultiServiceFactory > xFatcory( xParentProps, uno::UNO_QUERY );
+ if( xFatcory.is() )
+ {
+ uno::Reference< beans::XPropertySet > xDrawDefaults( xFatcory->createInstance( C2U( "com.sun.star.drawing.Defaults" ) ), uno::UNO_QUERY );
+ if( xDrawDefaults.is() )
+ xDrawDefaults->getPropertyValue( C2U("WritingMode") ) >>= nWritingMode;
+ }
+ }
+ else
+ {
+ uno::Reference< container::XNameAccess > xPageStyles( xStylesFamilies->getByName( C2U("PageStyles") ), uno::UNO_QUERY );
+ if( xPageStyles.is() )
+ {
+ rtl::OUString aPageStyle;
+
+ uno::Reference< text::XTextDocument > xTextDocument( xParentProps, uno::UNO_QUERY );
+ if( xTextDocument.is() )
+ {
+ //writer is parent document
+ //retrieve the current page style from the text cursor property PageStyleName
+
+ uno::Reference< text::XTextEmbeddedObjectsSupplier > xTextEmbeddedObjectsSupplier( xTextDocument, uno::UNO_QUERY );
+ if( xTextEmbeddedObjectsSupplier.is() )
+ {
+ uno::Reference< container::XNameAccess > xEmbeddedObjects( xTextEmbeddedObjectsSupplier->getEmbeddedObjects() );
+ if( xEmbeddedObjects.is() )
+ {
+ uno::Sequence< rtl::OUString > aNames( xEmbeddedObjects->getElementNames() );
+
+ sal_Int32 nCount = aNames.getLength();
+ for( sal_Int32 nN=0; nN<nCount; nN++ )
+ {
+ uno::Reference< beans::XPropertySet > xEmbeddedProps( xEmbeddedObjects->getByName( aNames[nN] ), uno::UNO_QUERY );
+ if( xEmbeddedProps.is() )
+ {
+ static rtl::OUString aChartCLSID = rtl::OUString( SvGlobalName( SO3_SCH_CLASSID ).GetHexName());
+ rtl::OUString aCLSID;
+ xEmbeddedProps->getPropertyValue( C2U("CLSID") ) >>= aCLSID;
+ if( aCLSID.equals(aChartCLSID) )
+ {
+ uno::Reference< frame::XModel > xModel;
+ xEmbeddedProps->getPropertyValue( C2U("Model") ) >>= xModel;
+ if( xModel == xChartModel )
+ {
+ uno::Reference< text::XTextContent > xEmbeddedObject( xEmbeddedProps, uno::UNO_QUERY );
+ if( xEmbeddedObject.is() )
+ {
+ uno::Reference< text::XTextRange > xAnchor( xEmbeddedObject->getAnchor() );
+ if( xAnchor.is() )
+ {
+ uno::Reference< beans::XPropertySet > xAnchorProps( xAnchor, uno::UNO_QUERY );
+ if( xAnchorProps.is() )
+ {
+ xAnchorProps->getPropertyValue( C2U("WritingMode") ) >>= nWritingMode;
+ }
+ uno::Reference< text::XText > xText( xAnchor->getText() );
+ if( xText.is() )
+ {
+ uno::Reference< beans::XPropertySet > xTextCursorProps( xText->createTextCursor(), uno::UNO_QUERY );
+ if( xTextCursorProps.is() )
+ xTextCursorProps->getPropertyValue( C2U("PageStyleName") ) >>= aPageStyle;
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ if( !aPageStyle.getLength() )
+ {
+ uno::Reference< text::XText > xText( xTextDocument->getText() );
+ if( xText.is() )
+ {
+ uno::Reference< beans::XPropertySet > xTextCursorProps( xText->createTextCursor(), uno::UNO_QUERY );
+ if( xTextCursorProps.is() )
+ xTextCursorProps->getPropertyValue( C2U("PageStyleName") ) >>= aPageStyle;
+ }
+ }
+ }
+ else
+ {
+ //Calc is parent document
+ xParentProps->getPropertyValue( C2U("PageStyle") ) >>= aPageStyle;
+ if(!aPageStyle.getLength())
+ aPageStyle = C2U("Default");
+ }
+ if( nWritingMode == -1 || nWritingMode == text::WritingMode2::PAGE )
+ {
+ uno::Reference< beans::XPropertySet > xPageStyle( xPageStyles->getByName( aPageStyle ), uno::UNO_QUERY );
+ if( xPageStyle.is() )
+ xPageStyle->getPropertyValue( C2U("WritingMode") ) >>= nWritingMode;
+ }
+ }
+ }
+ }
+ }
+ }
+ if( nWritingMode != -1 && nWritingMode != text::WritingMode2::PAGE )
+ {
+ if( pDrawModelWrapper.get() )
+ pDrawModelWrapper->GetItemPool().SetPoolDefaultItem(SfxInt32Item(EE_PARA_WRITINGDIR, nWritingMode) );
+ }
+ }
+ catch( uno::Exception& ex )
+ {
+ ASSERT_EXCEPTION( ex );
+ }
+ }
+}
+
+sal_Int16 lcl_getDefaultWritingModeFromPool( ::boost::shared_ptr< DrawModelWrapper > pDrawModelWrapper )
+{
+ sal_Int16 nWritingMode = text::WritingMode2::LR_TB;
+ if( pDrawModelWrapper.get() )
+ {
+ const SfxPoolItem* pItem = &(pDrawModelWrapper->GetItemPool().GetDefaultItem( EE_PARA_WRITINGDIR ));
+ if( pItem )
+ nWritingMode = static_cast< sal_Int16 >((static_cast< const SfxInt32Item * >( pItem ))->GetValue());
+ }
+ return nWritingMode;
+}
+
+} //end anonymous namespace
+
+//------------ create complete diagram shape (inclusive axis and series)
+
+awt::Rectangle ChartView::impl_createDiagramAndContent( SeriesPlotterContainer& rSeriesPlotterContainer
+ , const uno::Reference< drawing::XShapes>& xDiagramPlusAxes_Shapes
+ , const awt::Point& rAvailablePos
+ , const awt::Size& rAvailableSize
+ , const awt::Size& rPageSize
+ , bool bUseFixedInnerSize
+ , const uno::Reference< drawing::XShape>& xDiagram_MarkHandles /*needs to be resized to fit the result*/
+ )
+{
+ //return the used rectangle
+ awt::Rectangle aUsedOuterRect( rAvailablePos.X, rAvailablePos.Y, 0, 0 );
+
+// sal_Int32 nDiagramIndex = 0;//todo if more than one diagam is supported
+ uno::Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( m_xChartModel ) );
+ if( !xDiagram.is())
+ return aUsedOuterRect;
+
+ sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram );
+ if(!nDimensionCount)
+ {
+ //@todo handle mixed dimension
+ nDimensionCount = 2;
+ }
+
+ ::basegfx::B2IRectangle aAvailableOuterRect( BaseGFXHelper::makeRectangle(rAvailablePos,rAvailableSize) );
+
+ const std::vector< VCoordinateSystem* >& rVCooSysList( rSeriesPlotterContainer.getCooSysList() );
+ const std::vector< VSeriesPlotter* >& rSeriesPlotterList( rSeriesPlotterContainer.getSeriesPlotterList() );
+
+ //create VAxis, so they can give necessary information for automatic scaling
+ uno::Reference< util::XNumberFormatsSupplier > xNumberFormatsSupplier( m_xChartModel, uno::UNO_QUERY );
+ size_t nC = 0;
+ for( nC=0; nC < rVCooSysList.size(); nC++)
+ {
+ VCoordinateSystem* pVCooSys = rVCooSysList[nC];
+ if(3==nDimensionCount)
+ {
+ uno::Reference<beans::XPropertySet> xSceneProperties( xDiagram, uno::UNO_QUERY );
+ CuboidPlanePosition eLeftWallPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardLeftWall( xSceneProperties ) );
+ CuboidPlanePosition eBackWallPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBackWall( xSceneProperties ) );
+ CuboidPlanePosition eBottomPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBottom( xSceneProperties ) );
+ pVCooSys->set3DWallPositions( eLeftWallPos, eBackWallPos, eBottomPos );
+ }
+ pVCooSys->createVAxisList( xNumberFormatsSupplier
+ , rPageSize //font reference size
+ , BaseGFXHelper::B2IRectangleToAWTRectangle( aAvailableOuterRect ) //maximum space for labels
+ );
+ }
+
+
+ // - prepare list of all axis and how they are used
+ rSeriesPlotterContainer.initAxisUsageList();
+ rSeriesPlotterContainer.doAutoScaling( m_xChartModel );
+ rSeriesPlotterContainer.setScalesFromCooSysToPlotter();
+ rSeriesPlotterContainer.setNumberFormatsFromAxes();
+
+ //---------------------------------------------------------------------
+ //create shapes
+
+ //------------ create diagram shapes
+ //aspect ratio
+ drawing::Direction3D aPreferredAspectRatio(
+ rSeriesPlotterContainer.getPreferredAspectRatio() );
+
+ uno::Reference< drawing::XShapes > xSeriesTargetInFrontOfAxis(0);
+ uno::Reference< drawing::XShapes > xSeriesTargetBehindAxis(0);
+ VDiagram aVDiagram(xDiagram, aPreferredAspectRatio, nDimensionCount);
+ {//create diagram
+ aVDiagram.init(xDiagramPlusAxes_Shapes,xDiagramPlusAxes_Shapes,m_xShapeFactory);
+ aVDiagram.createShapes(rAvailablePos,rAvailableSize);
+ xSeriesTargetInFrontOfAxis = aVDiagram.getCoordinateRegion();
+ if( !bUseFixedInnerSize )
+ aVDiagram.reduceToMimimumSize();
+ }
+
+ uno::Reference< drawing::XShapes > xTextTargetShapes( ShapeFactory(m_xShapeFactory).createGroup2D(xDiagramPlusAxes_Shapes) );
+
+ // - create axis and grids for all coordinate systems
+
+ //init all coordinate systems
+ for( nC=0; nC < rVCooSysList.size(); nC++)
+ {
+ VCoordinateSystem* pVCooSys = rVCooSysList[nC];
+ pVCooSys->initPlottingTargets(xSeriesTargetInFrontOfAxis,xTextTargetShapes,m_xShapeFactory,xSeriesTargetBehindAxis);
+
+ pVCooSys->setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix(
+ createTransformationSceneToScreen( aVDiagram.getCurrentRectangle() ) ));
+
+ pVCooSys->initVAxisInList();
+ }
+
+ //calculate resulting size respecting axis label layout and fontscaling
+
+ uno::Reference< drawing::XShape > xBoundingShape( xDiagramPlusAxes_Shapes, uno::UNO_QUERY );
+ ::basegfx::B2IRectangle aConsumedOuterRect;
+
+ //use first coosys only so far; todo: calculate for more than one coosys if we have more in future
+ //todo: this is just a workaround at the moment for pie and donut labels
+ bool bIsPieOrDonut = lcl_IsPieOrDonut(xDiagram);
+ if( !bIsPieOrDonut && rVCooSysList.size() > 0 )
+ {
+ VCoordinateSystem* pVCooSys = rVCooSysList[0];
+ pVCooSys->createMaximumAxesLabels();
+
+ aConsumedOuterRect = ::basegfx::B2IRectangle( ShapeFactory::getRectangleOfShape(xBoundingShape) );
+ ::basegfx::B2IRectangle aNewInnerRect( aVDiagram.getCurrentRectangle() );
+ if( !bUseFixedInnerSize )
+ aNewInnerRect = aVDiagram.adjustInnerSize( aConsumedOuterRect );
+
+ pVCooSys->setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix(
+ createTransformationSceneToScreen( aNewInnerRect ) ));
+
+ //redo autoscaling to get size and text dependent automatic main increment count
+ rSeriesPlotterContainer.doAutoScaling( m_xChartModel );
+ rSeriesPlotterContainer.updateScalesAndIncrementsOnAxes();
+ rSeriesPlotterContainer.setScalesFromCooSysToPlotter();
+
+ pVCooSys->createAxesLabels();
+
+ bool bLessSpaceConsumedThanExpected = false;
+ {
+ ::basegfx::B2IRectangle aOldRect( aConsumedOuterRect );
+ aConsumedOuterRect = ShapeFactory::getRectangleOfShape(xBoundingShape);
+ if( aConsumedOuterRect.getMinX() > aAvailableOuterRect.getMinX()
+ || aConsumedOuterRect.getMaxX() < aAvailableOuterRect.getMaxX()
+ || aConsumedOuterRect.getMinY() > aAvailableOuterRect.getMinY()
+ || aConsumedOuterRect.getMinY() < aAvailableOuterRect.getMaxY() )
+ bLessSpaceConsumedThanExpected = true;
+ }
+
+ if( bLessSpaceConsumedThanExpected && !bUseFixedInnerSize )
+ {
+ aVDiagram.adjustInnerSize( aConsumedOuterRect );
+ pVCooSys->setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix(
+ createTransformationSceneToScreen( aVDiagram.getCurrentRectangle() ) ));
+ }
+ pVCooSys->updatePositions();//todo: logically this belongs to the condition above, but it seems also to be neccessary to give the axes group shapes the right bounding rects for hit test - probably caused by bug i106183 -> check again if fixed
+ }
+
+ //create axes and grids for the final size
+ for( nC=0; nC < rVCooSysList.size(); nC++)
+ {
+ VCoordinateSystem* pVCooSys = rVCooSysList[nC];
+
+ pVCooSys->setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix(
+ createTransformationSceneToScreen( aVDiagram.getCurrentRectangle() ) ));
+
+ pVCooSys->createAxesShapes();
+ pVCooSys->createGridShapes();
+ }
+
+ // - create data series for all charttypes
+ m_bPointsWereSkipped = false;
+ ::std::vector< VSeriesPlotter* >::const_iterator aPlotterIter = rSeriesPlotterList.begin();
+ const ::std::vector< VSeriesPlotter* >::const_iterator aPlotterEnd = rSeriesPlotterList.end();
+ for( aPlotterIter = rSeriesPlotterList.begin(); aPlotterIter != aPlotterEnd; aPlotterIter++ )
+ {
+ //------------ set transformation to plotter / create series
+ VSeriesPlotter* pSeriesPlotter = *aPlotterIter;
+ rtl::OUString aCID; //III
+ uno::Reference< drawing::XShapes > xSeriesTarget(0);
+ if( pSeriesPlotter->WantToPlotInFrontOfAxisLine() )
+ xSeriesTarget = xSeriesTargetInFrontOfAxis;
+ else
+ {
+ xSeriesTarget = xSeriesTargetBehindAxis;
+ DBG_ASSERT( !bIsPieOrDonut, "not implemented yet! - during a complete recreation this shape is destroyed so no series can be created anymore" );
+ }
+ pSeriesPlotter->initPlotter( xSeriesTarget,xTextTargetShapes,m_xShapeFactory,aCID );
+ pSeriesPlotter->setPageReferenceSize( rPageSize );
+ VCoordinateSystem* pVCooSys = lcl_getCooSysForPlotter( rVCooSysList, pSeriesPlotter );
+ if(2==nDimensionCount)
+ pSeriesPlotter->setTransformationSceneToScreen( pVCooSys->getTransformationSceneToScreen() );
+ //better performance for big data
+ awt::Size aCoordinateRegionResolution(1000,1000);
+ {
+ //calculate resolution for coordinate system
+ Sequence<sal_Int32> aCoordinateSystemResolution = pVCooSys->getCoordinateSystemResolution( rPageSize, m_aPageResolution );
+ pSeriesPlotter->setCoordinateSystemResolution( aCoordinateSystemResolution );
+ }
+ //
+ pSeriesPlotter->createShapes();
+ m_bPointsWereSkipped = m_bPointsWereSkipped || pSeriesPlotter->PointsWereSkipped();
+ }
+
+ //recreate all with corrected sizes if requested
+ if( bIsPieOrDonut )
+ {
+ m_bPointsWereSkipped = false;
+
+ aConsumedOuterRect = ::basegfx::B2IRectangle( ShapeFactory::getRectangleOfShape(xBoundingShape) );
+ ::basegfx::B2IRectangle aNewInnerRect( aVDiagram.getCurrentRectangle() );
+ if( !bUseFixedInnerSize )
+ aNewInnerRect = aVDiagram.adjustInnerSize( aConsumedOuterRect );
+
+ for( aPlotterIter = rSeriesPlotterList.begin(); aPlotterIter != aPlotterEnd; aPlotterIter++ )
+ {
+ VSeriesPlotter* pSeriesPlotter = *aPlotterIter;
+ pSeriesPlotter->releaseShapes();
+ }
+
+ //clear and recreate
+ ShapeFactory::removeSubShapes( xSeriesTargetInFrontOfAxis ); //xSeriesTargetBehindAxis is a sub shape of xSeriesTargetInFrontOfAxis and will be removed here
+ xSeriesTargetBehindAxis.clear();
+ ShapeFactory::removeSubShapes( xTextTargetShapes );
+
+ //set new transformation
+ for( nC=0; nC < rVCooSysList.size(); nC++)
+ {
+ VCoordinateSystem* pVCooSys = rVCooSysList[nC];
+ pVCooSys->setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix(
+ createTransformationSceneToScreen( aNewInnerRect ) ));
+ }
+
+ // - create data series for all charttypes
+ for( aPlotterIter = rSeriesPlotterList.begin(); aPlotterIter != aPlotterEnd; aPlotterIter++ )
+ {
+ //------------ set transformation to plotter / create series
+ VSeriesPlotter* pSeriesPlotter = *aPlotterIter;
+ VCoordinateSystem* pVCooSys = lcl_getCooSysForPlotter( rVCooSysList, pSeriesPlotter );
+ if(2==nDimensionCount)
+ pSeriesPlotter->setTransformationSceneToScreen( pVCooSys->getTransformationSceneToScreen() );
+ pSeriesPlotter->createShapes();
+ m_bPointsWereSkipped = m_bPointsWereSkipped || pSeriesPlotter->PointsWereSkipped();
+ }
+
+ /*
+ uno::Reference< drawing::XShape > xDiagramPlusAxes_KeepRatio( xDiagramPlusAxes_Shapes, uno::UNO_QUERY );
+
+ awt::Size aNewSize( rAvailableSize );
+ awt::Point aNewPos( rAvailablePos );
+ if( bKeepAspectRatio )
+ {
+ awt::Size aCurrentSize( xDiagramPlusAxes_KeepRatio->getSize());
+
+ aNewSize = ShapeFactory::calculateNewSizeRespectingAspectRatio(
+ rAvailableSize, aCurrentSize );
+ aNewPos = ShapeFactory::calculateTopLeftPositionToCenterObject(
+ rAvailablePos, rAvailableSize, aNewSize );
+ }
+
+ xDiagramPlusAxes_KeepRatio->setPosition( aNewPos );
+ xDiagramPlusAxes_KeepRatio->setSize( aNewSize );
+ */
+ for( aPlotterIter = rSeriesPlotterList.begin(); aPlotterIter != aPlotterEnd; aPlotterIter++ )
+ {
+ VSeriesPlotter* pSeriesPlotter = *aPlotterIter;
+ pSeriesPlotter->rearrangeLabelToAvoidOverlapIfRequested( rPageSize );
+ }
+ }
+
+ if( bUseFixedInnerSize )
+ {
+ //if( !bIsPieOrDonut )
+ // aConsumedOuterRect = ::basegfx::B2IRectangle( ShapeFactory::getRectangleOfShape(xBoundingShape) );
+ aUsedOuterRect = awt::Rectangle( aConsumedOuterRect.getMinX(), aConsumedOuterRect.getMinY(), aConsumedOuterRect.getWidth(), aConsumedOuterRect.getHeight() );
+ }
+ else
+ aUsedOuterRect = awt::Rectangle( rAvailablePos.X, rAvailablePos.Y, rAvailableSize.Width, rAvailableSize.Height );
+
+ bool bSnapRectToUsedArea = false;
+ for( aPlotterIter = rSeriesPlotterList.begin(); aPlotterIter != aPlotterEnd; aPlotterIter++ )
+ {
+ VSeriesPlotter* pSeriesPlotter = *aPlotterIter;
+ bSnapRectToUsedArea = pSeriesPlotter->shouldSnapRectToUsedArea();
+ if(bSnapRectToUsedArea)
+ break;
+ }
+ if(bSnapRectToUsedArea)
+ {
+ if( bUseFixedInnerSize )
+ m_aResultingDiagramRectangleExcludingAxes = getRectangleOfObject( C2U("PlotAreaExcludingAxes") );
+ else
+ {
+ ::basegfx::B2IRectangle aConsumedInnerRect = aVDiagram.getCurrentRectangle();
+ m_aResultingDiagramRectangleExcludingAxes = awt::Rectangle( aConsumedInnerRect.getMinX(), aConsumedInnerRect.getMinY(), aConsumedInnerRect.getWidth(), aConsumedInnerRect.getHeight() );
+ }
+ }
+ else
+ {
+ if( bUseFixedInnerSize )
+ m_aResultingDiagramRectangleExcludingAxes = awt::Rectangle( rAvailablePos.X, rAvailablePos.Y, rAvailableSize.Width, rAvailableSize.Height );
+ else
+ {
+ ::basegfx::B2IRectangle aConsumedInnerRect = aVDiagram.getCurrentRectangle();
+ m_aResultingDiagramRectangleExcludingAxes = awt::Rectangle( aConsumedInnerRect.getMinX(), aConsumedInnerRect.getMinY(), aConsumedInnerRect.getWidth(), aConsumedInnerRect.getHeight() );
+ }
+ }
+
+ if( xDiagram_MarkHandles.is() )
+ {
+ awt::Point aPos(rAvailablePos);
+ awt::Size aSize(rAvailableSize);
+ bool bPosSizeExcludeAxesProperty = true;
+ uno::Reference< beans::XPropertySet > xDiaProps( xDiagram, uno::UNO_QUERY_THROW );
+ if( xDiaProps.is() )
+ xDiaProps->getPropertyValue(C2U("PosSizeExcludeAxes")) >>= bPosSizeExcludeAxesProperty;
+ if( bUseFixedInnerSize || bPosSizeExcludeAxesProperty )
+ {
+ aPos = awt::Point( m_aResultingDiagramRectangleExcludingAxes.X, m_aResultingDiagramRectangleExcludingAxes.Y );
+ aSize = awt::Size( m_aResultingDiagramRectangleExcludingAxes.Width, m_aResultingDiagramRectangleExcludingAxes.Height );
+ }
+ xDiagram_MarkHandles->setPosition( aPos );
+ xDiagram_MarkHandles->setSize( aSize );
+ }
+
+ return aUsedOuterRect;
+}
+
+//-------------------------------------------------------------
+//-------------------------------------------------------------
+//-------------------------------------------------------------
+
+sal_Bool ChartView::getExplicitValuesForAxis(
+ uno::Reference< XAxis > xAxis
+ , ExplicitScaleData& rExplicitScale
+ , ExplicitIncrementData& rExplicitIncrement )
+{
+ impl_updateView();
+
+ if(!xAxis.is())
+ return sal_False;
+
+ uno::Reference< XCoordinateSystem > xCooSys( AxisHelper::getCoordinateSystemOfAxis(xAxis,ChartModelHelper::findDiagram( m_xChartModel ) ) );
+ const VCoordinateSystem* pVCooSys = findInCooSysList(m_aVCooSysList,xCooSys);
+ if(!pVCooSys)
+ return sal_False;
+
+ sal_Int32 nDimensionIndex=-1;
+ sal_Int32 nAxisIndex=-1;
+ if( AxisHelper::getIndicesForAxis( xAxis, xCooSys, nDimensionIndex, nAxisIndex ) )
+ {
+ rExplicitScale = pVCooSys->getExplicitScale(nDimensionIndex,nAxisIndex);
+ rExplicitIncrement = pVCooSys->getExplicitIncrement(nDimensionIndex,nAxisIndex);
+ return sal_True;
+ }
+ return sal_False;
+}
+
+SdrPage* ChartView::getSdrPage()
+{
+ SdrPage* pPage=0;
+ Reference< lang::XUnoTunnel> xUnoTunnel(m_xDrawPage,uno::UNO_QUERY);
+ if(xUnoTunnel.is())
+ {
+ SvxDrawPage* pSvxDrawPage = reinterpret_cast<SvxDrawPage*>(xUnoTunnel->getSomething(
+ SvxDrawPage::getUnoTunnelId() ));
+ if(pSvxDrawPage)
+ {
+ pPage = pSvxDrawPage->GetSdrPage();
+ }
+ }
+ return pPage;
+}
+
+uno::Reference< drawing::XShape > ChartView::getShapeForCID( const rtl::OUString& rObjectCID )
+{
+ ::vos::OGuard aSolarGuard( Application::GetSolarMutex());
+ SdrObject* pObj = DrawModelWrapper::getNamedSdrObject( rObjectCID, this->getSdrPage() );
+ if( pObj )
+ return uno::Reference< drawing::XShape >( pObj->getUnoShape(), uno::UNO_QUERY);
+ return 0;
+}
+
+awt::Rectangle ChartView::getDiagramRectangleExcludingAxes()
+{
+ impl_updateView();
+ return m_aResultingDiagramRectangleExcludingAxes;
+}
+
+awt::Rectangle ChartView::getRectangleOfObject( const rtl::OUString& rObjectCID, bool bSnapRect )
+{
+ impl_updateView();
+
+ awt::Rectangle aRet;
+ uno::Reference< drawing::XShape > xShape( getShapeForCID(rObjectCID) );
+ if(xShape.is())
+ {
+ //special handling for axis for old api:
+ //same special handling for diagram
+ ObjectType eObjectType( ObjectIdentifier::getObjectType( rObjectCID ) );
+ if( eObjectType == OBJECTTYPE_AXIS || eObjectType == OBJECTTYPE_DIAGRAM )
+ {
+ ::vos::OGuard aSolarGuard( Application::GetSolarMutex());
+ SvxShape* pRoot = SvxShape::getImplementation( xShape );
+ if( pRoot )
+ {
+ SdrObject* pRootSdrObject = pRoot->GetSdrObject();
+ if( pRootSdrObject )
+ {
+ SdrObjList* pRootList = pRootSdrObject->GetSubList();
+ if( pRootList )
+ {
+ OUString aShapeName = C2U("MarkHandles");
+ if( eObjectType == OBJECTTYPE_DIAGRAM )
+ aShapeName = C2U("PlotAreaIncludingAxes");
+ SdrObject* pShape = DrawModelWrapper::getNamedSdrObject( aShapeName, pRootList );
+ if( pShape )
+ xShape = uno::Reference< drawing::XShape >( pShape->getUnoShape(), uno::UNO_QUERY);
+ }
+ }
+ }
+ }
+
+ awt::Size aSize( xShape->getSize() );
+ awt::Point aPoint( xShape->getPosition() );
+ aRet = awt::Rectangle( aPoint.X, aPoint.Y, aSize.Width, aSize.Height );
+ if( bSnapRect )
+ {
+ //for rotated objects the shape size and position differs from the visible rectangle
+ SvxShape* pShape = SvxShape::getImplementation( xShape );
+ if( pShape )
+ {
+ SdrObject* pSdrObject = pShape->GetSdrObject();
+ if( pSdrObject )
+ {
+ Rectangle aSnapRect( pSdrObject->GetSnapRect() );
+ aRet = awt::Rectangle(aSnapRect.Left(),aSnapRect.Top(),aSnapRect.GetWidth(),aSnapRect.GetHeight());
+ }
+ }
+ }
+ }
+ return aRet;
+}
+
+::boost::shared_ptr< DrawModelWrapper > ChartView::getDrawModelWrapper()
+{
+ return m_pDrawModelWrapper;
+}
+
+namespace
+{
+sal_Int32 lcl_getDiagramTitleSpace()
+{
+ return 200; //=0,2 cm spacing
+}
+bool lcl_getPropertySwapXAndYAxis( const uno::Reference< XDiagram >& xDiagram )
+{
+ bool bSwapXAndY = false;
+
+ uno::Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY );
+ if( xCooSysContainer.is() )
+ {
+ uno::Sequence< uno::Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() );
+ if( aCooSysList.getLength() )
+ {
+ uno::Reference<beans::XPropertySet> xProp(aCooSysList[0], uno::UNO_QUERY );
+ if( xProp.is()) try
+ {
+ xProp->getPropertyValue( C2U( "SwapXAndYAxis" ) ) >>= bSwapXAndY;
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+ }
+ }
+ return bSwapXAndY;
+}
+
+}
+
+sal_Int32 lcl_getExplicitNumberFormatKeyForAxis(
+ const Reference< chart2::XAxis >& xAxis
+ , const Reference< chart2::XCoordinateSystem > & xCorrespondingCoordinateSystem
+ , const Reference< util::XNumberFormatsSupplier >& xNumberFormatsSupplier
+ , bool bSearchForParallelAxisIfNothingIsFound )
+{
+ sal_Int32 nNumberFormatKey(0);
+ Reference< beans::XPropertySet > xProp( xAxis, uno::UNO_QUERY );
+ if( xProp.is() && !( xProp->getPropertyValue( C2U( "NumberFormat" ) ) >>= nNumberFormatKey ) )
+ {
+ bool bPercentFormatSet = false;
+ //check wether we have a percent scale -> use percent format
+ if( xNumberFormatsSupplier.is() )
+ {
+ ScaleData aData = xAxis->getScaleData();
+ if( aData.AxisType==AxisType::PERCENT )
+ {
+ sal_Int32 nPercentFormat = ExplicitValueProvider::getPercentNumberFormat( xNumberFormatsSupplier );
+ if( nPercentFormat != -1 )
+ {
+ nNumberFormatKey = nPercentFormat;
+ bPercentFormatSet = true;
+ }
+ }
+ }
+
+ if( !bPercentFormatSet )
+ {
+ typedef ::std::map< sal_Int32, sal_Int32 > tNumberformatFrequency;
+ tNumberformatFrequency aKeyMap;
+
+ bool bNumberFormatKeyFoundViaAttachedData = false;
+ sal_Int32 nAxisIndex = 0;
+ sal_Int32 nDimensionIndex = 1;
+
+ try
+ {
+ Reference< XChartTypeContainer > xCTCnt( xCorrespondingCoordinateSystem, uno::UNO_QUERY_THROW );
+ if( xCTCnt.is() )
+ {
+ AxisHelper::getIndicesForAxis( xAxis, xCorrespondingCoordinateSystem, nDimensionIndex, nAxisIndex );
+ ::rtl::OUString aRoleToMatch;
+ if( nDimensionIndex == 0 )
+ aRoleToMatch = C2U("values-x");
+ Sequence< Reference< XChartType > > aChartTypes( xCTCnt->getChartTypes());
+ for( sal_Int32 nCTIdx=0; nCTIdx<aChartTypes.getLength(); ++nCTIdx )
+ {
+ if( nDimensionIndex != 0 )
+ aRoleToMatch = ChartTypeHelper::getRoleOfSequenceForYAxisNumberFormatDetection( aChartTypes[nCTIdx] );
+ Reference< XDataSeriesContainer > xDSCnt( aChartTypes[nCTIdx], uno::UNO_QUERY_THROW );
+ Sequence< Reference< XDataSeries > > aDataSeriesSeq( xDSCnt->getDataSeries());
+ for( sal_Int32 nSeriesIdx=0; nSeriesIdx<aDataSeriesSeq.getLength(); ++nSeriesIdx )
+ {
+ Reference< chart2::XDataSeries > xDataSeries(aDataSeriesSeq[nSeriesIdx]);
+ Reference< data::XDataSource > xSource( xDataSeries, uno::UNO_QUERY_THROW );
+
+ if( nDimensionIndex == 1 )
+ {
+ //only take those series into accoutn that are attached to this axis
+ sal_Int32 nAttachedAxisIndex = DataSeriesHelper::getAttachedAxisIndex(xDataSeries);
+ if( nAttachedAxisIndex != nAxisIndex )
+ continue;
+ }
+
+ Sequence< Reference< data::XLabeledDataSequence > > aLabeledSeq( xSource->getDataSequences());
+ for( sal_Int32 nLSeqIdx=0; nLSeqIdx<aLabeledSeq.getLength(); ++nLSeqIdx )
+ {
+ if(!aLabeledSeq[nLSeqIdx].is())
+ continue;
+ Reference< data::XDataSequence > xSeq( aLabeledSeq[nLSeqIdx]->getValues());
+ if(!xSeq.is())
+ continue;
+ Reference< beans::XPropertySet > xSeqProp( xSeq, uno::UNO_QUERY );
+ ::rtl::OUString aRole;
+ bool bTakeIntoAccount =
+ ( xSeqProp.is() && (aRoleToMatch.getLength() > 0) &&
+ (xSeqProp->getPropertyValue(C2U("Role")) >>= aRole ) &&
+ aRole.equals( aRoleToMatch ));
+
+ if( bTakeIntoAccount )
+ {
+ sal_Int32 nKey = xSeq->getNumberFormatKeyByIndex( -1 );
+ // initialize the value
+ if( aKeyMap.find( nKey ) == aKeyMap.end())
+ aKeyMap[ nKey ] = 0;
+ // increase frequency
+ aKeyMap[ nKey ] = (aKeyMap[ nKey ] + 1);
+ }
+ }
+ }
+ }
+ }
+ }
+ catch( const uno::Exception & ex )
+ {
+ ASSERT_EXCEPTION( ex );
+ }
+
+ if( ! aKeyMap.empty())
+ {
+ sal_Int32 nMaxFreq = 0;
+ // find most frequent key
+ for( tNumberformatFrequency::const_iterator aIt = aKeyMap.begin();
+ aIt != aKeyMap.end(); ++aIt )
+ {
+ OSL_TRACE( "NumberFormatKey %d appears %d times", (*aIt).first, (*aIt).second );
+ // all values must at least be 1
+ if( (*aIt).second > nMaxFreq )
+ {
+ nNumberFormatKey = (*aIt).first;
+ bNumberFormatKeyFoundViaAttachedData = true;
+ nMaxFreq = (*aIt).second;
+ }
+ }
+ }
+
+ if( bSearchForParallelAxisIfNothingIsFound )
+ {
+ //no format is set to this axis and no data is set to this axis
+ //--> try to obtain the format from the parallel y-axis
+ if( !bNumberFormatKeyFoundViaAttachedData && nDimensionIndex == 1 )
+ {
+ sal_Int32 nParallelAxisIndex = (nAxisIndex==1) ?0 :1;
+ Reference< XAxis > xParallelAxis( AxisHelper::getAxis( 1, nParallelAxisIndex, xCorrespondingCoordinateSystem ) );
+ nNumberFormatKey = lcl_getExplicitNumberFormatKeyForAxis( xParallelAxis, xCorrespondingCoordinateSystem, xNumberFormatsSupplier, false );
+ }
+ }
+ }
+ }
+ return nNumberFormatKey;
+}
+
+//static
+sal_Int32 ExplicitValueProvider::getExplicitNumberFormatKeyForAxis(
+ const Reference< chart2::XAxis >& xAxis
+ , const Reference< chart2::XCoordinateSystem > & xCorrespondingCoordinateSystem
+ , const Reference< util::XNumberFormatsSupplier >& xNumberFormatsSupplier )
+{
+ return lcl_getExplicitNumberFormatKeyForAxis( xAxis, xCorrespondingCoordinateSystem, xNumberFormatsSupplier
+ , true /*bSearchForParallelAxisIfNothingIsFound*/ );
+}
+
+//static
+sal_Int32 ExplicitValueProvider::getPercentNumberFormat( const Reference< util::XNumberFormatsSupplier >& xNumberFormatsSupplier )
+{
+ sal_Int32 nRet=-1;
+ Reference< util::XNumberFormats > xNumberFormats( xNumberFormatsSupplier->getNumberFormats() );
+ if( xNumberFormats.is() )
+ {
+ sal_Bool bCreate = sal_True;
+ const LocaleDataWrapper& rLocaleDataWrapper = Application::GetSettings().GetLocaleDataWrapper();
+ Sequence<sal_Int32> aKeySeq = xNumberFormats->queryKeys( util::NumberFormat::PERCENT,
+ rLocaleDataWrapper.getLocale(), bCreate );
+ if( aKeySeq.getLength() )
+ {
+ nRet = aKeySeq[0];
+ }
+ }
+ return nRet;
+}
+
+
+sal_Int32 ExplicitValueProvider::getExplicitNumberFormatKeyForDataLabel(
+ const uno::Reference< beans::XPropertySet >& xSeriesOrPointProp,
+ const uno::Reference< XDataSeries >& xSeries,
+ sal_Int32 nPointIndex /*-1 for whole series*/,
+ const uno::Reference< XDiagram >& xDiagram
+ )
+{
+ sal_Int32 nFormat=0;
+ if( !xSeriesOrPointProp.is() )
+ return nFormat;
+
+ rtl::OUString aPropName( C2U( "NumberFormat" ) );
+ if( !(xSeriesOrPointProp->getPropertyValue(aPropName) >>= nFormat) )
+ {
+ uno::Reference< chart2::XChartType > xChartType( DataSeriesHelper::getChartTypeOfSeries( xSeries, xDiagram ) );
+
+ bool bFormatFound = false;
+ if( ChartTypeHelper::shouldLabelNumberFormatKeyBeDetectedFromYAxis( xChartType ) )
+ {
+ uno::Reference< beans::XPropertySet > xAttachedAxisProps( DiagramHelper::getAttachedAxis( xSeries, xDiagram ), uno::UNO_QUERY );
+ if( xAttachedAxisProps.is() && ( xAttachedAxisProps->getPropertyValue( aPropName ) >>= nFormat ) )
+ bFormatFound = true;
+ }
+ if( !bFormatFound )
+ {
+ Reference< chart2::data::XDataSource > xSeriesSource( xSeries, uno::UNO_QUERY );
+ OUString aRole( ChartTypeHelper::getRoleOfSequenceForDataLabelNumberFormatDetection( xChartType ) );
+
+ Reference< data::XLabeledDataSequence > xLabeledSequence(
+ DataSeriesHelper::getDataSequenceByRole( xSeriesSource, aRole, false ));
+ if( xLabeledSequence.is() )
+ {
+ Reference< data::XDataSequence > xValues( xLabeledSequence->getValues() );
+ if( xValues.is() )
+ nFormat = xValues->getNumberFormatKeyByIndex( nPointIndex );
+ }
+ }
+ }
+ if(nFormat<0)
+ nFormat=0;
+ return nFormat;
+}
+
+sal_Int32 ExplicitValueProvider::getExplicitPercentageNumberFormatKeyForDataLabel(
+ const uno::Reference< beans::XPropertySet >& xSeriesOrPointProp,
+ const uno::Reference< util::XNumberFormatsSupplier >& xNumberFormatsSupplier )
+{
+ sal_Int32 nFormat=0;
+ if( !xSeriesOrPointProp.is() )
+ return nFormat;
+ if( !(xSeriesOrPointProp->getPropertyValue(C2U( "PercentageNumberFormat" )) >>= nFormat) )
+ {
+ nFormat = ExplicitValueProvider::getPercentNumberFormat( xNumberFormatsSupplier );
+ }
+ if(nFormat<0)
+ nFormat=0;
+ return nFormat;
+}
+
+//static
+awt::Rectangle ExplicitValueProvider::addAxisTitleSizes(
+ const Reference< frame::XModel >& xChartModel
+ , const Reference< uno::XInterface >& xChartView
+ , const awt::Rectangle& rExcludingPositionAndSize )
+{
+ awt::Rectangle aRet(rExcludingPositionAndSize);
+
+ //add axis title sizes to the diagram size
+ uno::Reference< chart2::XTitle > xTitle_Height( TitleHelper::getTitle( TitleHelper::TITLE_AT_STANDARD_X_AXIS_POSITION, xChartModel ) );
+ uno::Reference< chart2::XTitle > xTitle_Width( TitleHelper::getTitle( TitleHelper::TITLE_AT_STANDARD_Y_AXIS_POSITION, xChartModel ) );
+ uno::Reference< chart2::XTitle > xSecondTitle_Height( TitleHelper::getTitle( TitleHelper::SECONDARY_X_AXIS_TITLE, xChartModel ) );
+ uno::Reference< chart2::XTitle > xSecondTitle_Width( TitleHelper::getTitle( TitleHelper::SECONDARY_Y_AXIS_TITLE, xChartModel ) );
+ if( xTitle_Height.is() || xTitle_Width.is() || xSecondTitle_Height.is() || xSecondTitle_Width.is() )
+ {
+ ExplicitValueProvider* pExplicitValueProvider = ExplicitValueProvider::getExplicitValueProvider(xChartView);
+ if( pExplicitValueProvider )
+ {
+ //detect wether x axis points into x direction or not
+ if( lcl_getPropertySwapXAndYAxis( ChartModelHelper::findDiagram( xChartModel ) ) )
+ {
+ std::swap( xTitle_Height, xTitle_Width );
+ std::swap( xSecondTitle_Height, xSecondTitle_Width );
+ }
+
+ sal_Int32 nTitleSpaceWidth = 0;
+ sal_Int32 nTitleSpaceHeight = 0;
+ sal_Int32 nSecondTitleSpaceWidth = 0;
+ sal_Int32 nSecondTitleSpaceHeight = 0;
+
+ if( xTitle_Height.is() )
+ {
+ rtl::OUString aCID_X( ObjectIdentifier::createClassifiedIdentifierForObject( xTitle_Height, xChartModel ) );
+ nTitleSpaceHeight = pExplicitValueProvider->getRectangleOfObject( aCID_X, true ).Height;
+ if( nTitleSpaceHeight )
+ nTitleSpaceHeight+=lcl_getDiagramTitleSpace();
+ }
+ if( xTitle_Width.is() )
+ {
+ rtl::OUString aCID_Y( ObjectIdentifier::createClassifiedIdentifierForObject( xTitle_Width, xChartModel ) );
+ nTitleSpaceWidth = pExplicitValueProvider->getRectangleOfObject( aCID_Y, true ).Width;
+ if(nTitleSpaceWidth)
+ nTitleSpaceWidth+=lcl_getDiagramTitleSpace();
+ }
+ if( xSecondTitle_Height.is() )
+ {
+ rtl::OUString aCID_X( ObjectIdentifier::createClassifiedIdentifierForObject( xSecondTitle_Height, xChartModel ) );
+ nSecondTitleSpaceHeight = pExplicitValueProvider->getRectangleOfObject( aCID_X, true ).Height;
+ if( nSecondTitleSpaceHeight )
+ nSecondTitleSpaceHeight+=lcl_getDiagramTitleSpace();
+ }
+ if( xSecondTitle_Width.is() )
+ {
+ rtl::OUString aCID_Y( ObjectIdentifier::createClassifiedIdentifierForObject( xSecondTitle_Width, xChartModel ) );
+ nSecondTitleSpaceWidth += pExplicitValueProvider->getRectangleOfObject( aCID_Y, true ).Width;
+ if( nSecondTitleSpaceWidth )
+ nSecondTitleSpaceWidth+=lcl_getDiagramTitleSpace();
+ }
+
+ aRet.X -= nTitleSpaceWidth;
+ aRet.Y -= nSecondTitleSpaceHeight;
+ aRet.Width += nTitleSpaceWidth + nSecondTitleSpaceWidth;
+ aRet.Height += nTitleSpaceHeight + nSecondTitleSpaceHeight;
+ }
+ }
+ return aRet;
+}
+
+//static
+awt::Rectangle ExplicitValueProvider::substractAxisTitleSizes(
+ const Reference< frame::XModel >& xChartModel
+ , const Reference< uno::XInterface >& xChartView
+ , const awt::Rectangle& rPositionAndSizeIncludingTitles )
+{
+ awt::Rectangle aRet(rPositionAndSizeIncludingTitles);
+
+ //add axis title sizes to the diagram size
+ uno::Reference< chart2::XTitle > xTitle_Height( TitleHelper::getTitle( TitleHelper::TITLE_AT_STANDARD_X_AXIS_POSITION, xChartModel ) );
+ uno::Reference< chart2::XTitle > xTitle_Width( TitleHelper::getTitle( TitleHelper::TITLE_AT_STANDARD_Y_AXIS_POSITION, xChartModel ) );
+ uno::Reference< chart2::XTitle > xSecondTitle_Height( TitleHelper::getTitle( TitleHelper::SECONDARY_X_AXIS_TITLE, xChartModel ) );
+ uno::Reference< chart2::XTitle > xSecondTitle_Width( TitleHelper::getTitle( TitleHelper::SECONDARY_Y_AXIS_TITLE, xChartModel ) );
+ if( xTitle_Height.is() || xTitle_Width.is() || xSecondTitle_Height.is() || xSecondTitle_Width.is() )
+ {
+ ExplicitValueProvider* pExplicitValueProvider = ExplicitValueProvider::getExplicitValueProvider(xChartView);
+ if( pExplicitValueProvider )
+ {
+ //detect wether x axis points into x direction or not
+ if( lcl_getPropertySwapXAndYAxis( ChartModelHelper::findDiagram( xChartModel ) ) )
+ {
+ std::swap( xTitle_Height, xTitle_Width );
+ std::swap( xSecondTitle_Height, xSecondTitle_Width );
+ }
+
+ sal_Int32 nTitleSpaceWidth = 0;
+ sal_Int32 nTitleSpaceHeight = 0;
+ sal_Int32 nSecondTitleSpaceWidth = 0;
+ sal_Int32 nSecondTitleSpaceHeight = 0;
+
+ if( xTitle_Height.is() )
+ {
+ rtl::OUString aCID_X( ObjectIdentifier::createClassifiedIdentifierForObject( xTitle_Height, xChartModel ) );
+ nTitleSpaceHeight = pExplicitValueProvider->getRectangleOfObject( aCID_X, true ).Height;
+ if( nTitleSpaceHeight )
+ nTitleSpaceHeight+=lcl_getDiagramTitleSpace();
+ }
+ if( xTitle_Width.is() )
+ {
+ rtl::OUString aCID_Y( ObjectIdentifier::createClassifiedIdentifierForObject( xTitle_Width, xChartModel ) );
+ nTitleSpaceWidth = pExplicitValueProvider->getRectangleOfObject( aCID_Y, true ).Width;
+ if(nTitleSpaceWidth)
+ nTitleSpaceWidth+=lcl_getDiagramTitleSpace();
+ }
+ if( xSecondTitle_Height.is() )
+ {
+ rtl::OUString aCID_X( ObjectIdentifier::createClassifiedIdentifierForObject( xSecondTitle_Height, xChartModel ) );
+ nSecondTitleSpaceHeight = pExplicitValueProvider->getRectangleOfObject( aCID_X, true ).Height;
+ if( nSecondTitleSpaceHeight )
+ nSecondTitleSpaceHeight+=lcl_getDiagramTitleSpace();
+ }
+ if( xSecondTitle_Width.is() )
+ {
+ rtl::OUString aCID_Y( ObjectIdentifier::createClassifiedIdentifierForObject( xSecondTitle_Width, xChartModel ) );
+ nSecondTitleSpaceWidth += pExplicitValueProvider->getRectangleOfObject( aCID_Y, true ).Width;
+ if( nSecondTitleSpaceWidth )
+ nSecondTitleSpaceWidth+=lcl_getDiagramTitleSpace();
+ }
+
+ aRet.X += nTitleSpaceWidth;
+ aRet.Y += nSecondTitleSpaceHeight;
+ aRet.Width -= (nTitleSpaceWidth + nSecondTitleSpaceWidth);
+ aRet.Height -= (nTitleSpaceHeight + nSecondTitleSpaceHeight);
+ }
+ }
+ return aRet;
+}
+
+double lcl_getPageLayoutDistancePercentage()
+{
+ return 0.02;
+}
+
+bool getAvailablePosAndSizeForDiagram(
+ awt::Point& rOutPos, awt::Size& rOutAvailableDiagramSize
+ , const awt::Rectangle& rSpaceLeft
+ , const awt::Size & rPageSize
+ , const uno::Reference< XDiagram > & xDiagram
+ , bool& bUseFixedInnerSize )
+{
+ bUseFixedInnerSize = false;
+
+ //@todo: we need a size dependent on the axis labels
+ awt::Rectangle aRemainingSpace(rSpaceLeft);
+ {
+ sal_Int32 nYDistance = static_cast<sal_Int32>(rPageSize.Height*lcl_getPageLayoutDistancePercentage());
+ sal_Int32 nXDistance = static_cast<sal_Int32>(rPageSize.Width*lcl_getPageLayoutDistancePercentage());
+ aRemainingSpace.X+=nXDistance;
+ aRemainingSpace.Width-=2*nXDistance;
+ aRemainingSpace.Y+=nYDistance;
+ aRemainingSpace.Height-=2*nYDistance;
+ }
+ if(aRemainingSpace.Width <= 0 || aRemainingSpace.Height <= 0 )
+ return false;
+
+ uno::Reference< beans::XPropertySet > xProp(xDiagram, uno::UNO_QUERY);
+
+ bool bPosSizeExcludeAxes = false;
+ if( xProp.is() )
+ xProp->getPropertyValue( C2U( "PosSizeExcludeAxes" ) ) >>= bPosSizeExcludeAxes;
+
+ //size:
+ ::com::sun::star::chart2::RelativeSize aRelativeSize;
+ if( xProp.is() && (xProp->getPropertyValue( C2U( "RelativeSize" ) )>>=aRelativeSize) )
+ {
+ rOutAvailableDiagramSize.Height = static_cast<sal_Int32>(aRelativeSize.Secondary*rPageSize.Height);
+ rOutAvailableDiagramSize.Width = static_cast<sal_Int32>(aRelativeSize.Primary*rPageSize.Width);
+ bUseFixedInnerSize = bPosSizeExcludeAxes;
+ }
+ else
+ rOutAvailableDiagramSize = awt::Size(aRemainingSpace.Width,aRemainingSpace.Height);
+
+ //position:
+ chart2::RelativePosition aRelativePosition;
+ if( xProp.is() && (xProp->getPropertyValue( C2U( "RelativePosition" ) )>>=aRelativePosition) )
+ {
+ //@todo decide wether x is primary or secondary
+
+ //the coordinates re relative to the page
+ double fX = aRelativePosition.Primary*rPageSize.Width;
+ double fY = aRelativePosition.Secondary*rPageSize.Height;
+
+ rOutPos = RelativePositionHelper::getUpperLeftCornerOfAnchoredObject(
+ awt::Point(static_cast<sal_Int32>(fX),static_cast<sal_Int32>(fY))
+ , rOutAvailableDiagramSize, aRelativePosition.Anchor );
+ bUseFixedInnerSize = bPosSizeExcludeAxes;
+ }
+ else
+ rOutPos = awt::Point(aRemainingSpace.X,aRemainingSpace.Y);
+
+ //ensure that the diagram does not lap out right side or out of bottom
+ {
+ if( rOutPos.Y + rOutAvailableDiagramSize.Height > rPageSize.Height )
+ rOutAvailableDiagramSize.Height = rPageSize.Height - rOutPos.Y;
+ if( rOutPos.X + rOutAvailableDiagramSize.Width > rPageSize.Width )
+ rOutAvailableDiagramSize.Width = rPageSize.Width - rOutPos.X;
+ }
+
+ return true;
+}
+
+enum TitleAlignment { ALIGN_LEFT, ALIGN_TOP, ALIGN_RIGHT, ALIGN_BOTTOM, ALIGN_Z };
+
+void changePositionOfAxisTitle( VTitle* pVTitle, TitleAlignment eAlignment
+ , awt::Rectangle& rDiagramPlusAxesRect, const awt::Size & rPageSize )
+{
+ if(!pVTitle)
+ return;
+
+ awt::Point aNewPosition(0,0);
+ awt::Size aTitleSize = pVTitle->getFinalSize();
+ sal_Int32 nYDistance = static_cast<sal_Int32>(rPageSize.Height*lcl_getPageLayoutDistancePercentage());
+ sal_Int32 nXDistance = static_cast<sal_Int32>(rPageSize.Width*lcl_getPageLayoutDistancePercentage());
+ switch( eAlignment )
+ {
+ case ALIGN_TOP:
+ aNewPosition = awt::Point( rDiagramPlusAxesRect.X + rDiagramPlusAxesRect.Width/2
+ , rDiagramPlusAxesRect.Y - aTitleSize.Height/2 - nYDistance );
+ break;
+ case ALIGN_BOTTOM:
+ aNewPosition = awt::Point( rDiagramPlusAxesRect.X + rDiagramPlusAxesRect.Width/2
+ , rDiagramPlusAxesRect.Y + rDiagramPlusAxesRect.Height + aTitleSize.Height/2 + nYDistance );
+ break;
+ case ALIGN_LEFT:
+ aNewPosition = awt::Point( rDiagramPlusAxesRect.X - aTitleSize.Width/2 - nXDistance
+ , rDiagramPlusAxesRect.Y + rDiagramPlusAxesRect.Height/2 );
+ break;
+ case ALIGN_RIGHT:
+ aNewPosition = awt::Point( rDiagramPlusAxesRect.X + rDiagramPlusAxesRect.Width + aTitleSize.Width/2 + nXDistance
+ , rDiagramPlusAxesRect.Y + rDiagramPlusAxesRect.Height/2 );
+ break;
+ case ALIGN_Z:
+ aNewPosition = awt::Point( rDiagramPlusAxesRect.X + rDiagramPlusAxesRect.Width + aTitleSize.Width/2 + nXDistance
+ , rDiagramPlusAxesRect.Y + rDiagramPlusAxesRect.Height - aTitleSize.Height/2 );
+ break;
+ default:
+ break;
+ }
+
+ sal_Int32 nMaxY = rPageSize.Height - aTitleSize.Height/2;
+ sal_Int32 nMaxX = rPageSize.Width - aTitleSize.Width/2;
+ sal_Int32 nMinX = aTitleSize.Width/2;
+ sal_Int32 nMinY = aTitleSize.Height/2;
+ if( aNewPosition.Y > nMaxY )
+ aNewPosition.Y = nMaxY;
+ if( aNewPosition.X > nMaxX )
+ aNewPosition.X = nMaxX;
+ if( aNewPosition.Y < nMinY )
+ aNewPosition.Y = nMinY;
+ if( aNewPosition.X < nMinX )
+ aNewPosition.X = nMinX;
+
+ pVTitle->changePosition( aNewPosition );
+}
+
+std::auto_ptr<VTitle> lcl_createTitle( TitleHelper::eTitleType eType
+ , const uno::Reference< drawing::XShapes>& xPageShapes
+ , const uno::Reference< lang::XMultiServiceFactory>& xShapeFactory
+ , const uno::Reference< frame::XModel >& xChartModel
+ , awt::Rectangle& rRemainingSpace
+ , const awt::Size & rPageSize
+ , TitleAlignment eAlignment
+ , bool& rbAutoPosition )
+{
+ std::auto_ptr<VTitle> apVTitle;
+
+ // #i109336# Improve auto positioning in chart
+ double fPercentage = lcl_getPageLayoutDistancePercentage();
+ sal_Int32 nXDistance = static_cast< sal_Int32 >( rPageSize.Width * fPercentage );
+ sal_Int32 nYDistance = static_cast< sal_Int32 >( rPageSize.Height * fPercentage );
+ if ( eType == TitleHelper::MAIN_TITLE )
+ {
+ sal_Int32 nYOffset = 135; // 1/100 mm
+ nYDistance += nYOffset;
+ }
+ else if ( eType == TitleHelper::TITLE_AT_STANDARD_X_AXIS_POSITION )
+ {
+ sal_Int32 nYOffset = 420; // 1/100 mm
+ nYDistance = nYOffset;
+ }
+ else if ( eType == TitleHelper::TITLE_AT_STANDARD_Y_AXIS_POSITION )
+ {
+ sal_Int32 nXOffset = 450; // 1/100 mm
+ nXDistance = nXOffset;
+ }
+
+ uno::Reference< XTitle > xTitle( TitleHelper::getTitle( eType, xChartModel ) );
+ if(xTitle.is())
+ {
+ rtl::OUString aCompleteString( TitleHelper::getCompleteString( xTitle ) );
+ if ( aCompleteString.getLength() == 0 )
+ return apVTitle;//don't create empty titles as the resulting diagram position is wrong then
+
+ //create title
+ apVTitle = std::auto_ptr<VTitle>(new VTitle(xTitle));
+ rtl::OUString aCID( ObjectIdentifier::createClassifiedIdentifierForObject( xTitle, xChartModel ) );
+ apVTitle->init(xPageShapes,xShapeFactory,aCID);
+ apVTitle->createShapes( awt::Point(0,0), rPageSize );
+ awt::Size aTitleUnrotatedSize = apVTitle->getUnrotatedSize();
+ awt::Size aTitleSize = apVTitle->getFinalSize();
+
+ //position
+ rbAutoPosition=true;
+ awt::Point aNewPosition(0,0);
+ chart2::RelativePosition aRelativePosition;
+ uno::Reference< beans::XPropertySet > xProp(xTitle, uno::UNO_QUERY);
+ if( xProp.is() && (xProp->getPropertyValue( C2U( "RelativePosition" ) )>>=aRelativePosition) )
+ {
+ rbAutoPosition = false;
+
+ //@todo decide wether x is primary or secondary
+ double fX = aRelativePosition.Primary*rPageSize.Width;
+ double fY = aRelativePosition.Secondary*rPageSize.Height;
+
+ double fAnglePi = apVTitle->getRotationAnglePi();
+ aNewPosition = RelativePositionHelper::getCenterOfAnchoredObject(
+ awt::Point(static_cast<sal_Int32>(fX),static_cast<sal_Int32>(fY))
+ , aTitleUnrotatedSize, aRelativePosition.Anchor, fAnglePi );
+ }
+ else //auto position
+ {
+ switch( eAlignment )
+ {
+ case ALIGN_TOP:
+ aNewPosition = awt::Point( rRemainingSpace.X + rRemainingSpace.Width/2
+ , rRemainingSpace.Y + aTitleSize.Height/2 + nYDistance );
+ break;
+ case ALIGN_BOTTOM:
+ aNewPosition = awt::Point( rRemainingSpace.X + rRemainingSpace.Width/2
+ , rRemainingSpace.Y + rRemainingSpace.Height - aTitleSize.Height/2 - nYDistance );
+ break;
+ case ALIGN_LEFT:
+ aNewPosition = awt::Point( rRemainingSpace.X + aTitleSize.Width/2 + nXDistance
+ , rRemainingSpace.Y + rRemainingSpace.Height/2 );
+ break;
+ case ALIGN_RIGHT:
+ aNewPosition = awt::Point( rRemainingSpace.X + rRemainingSpace.Width - aTitleSize.Width/2 - nXDistance
+ , rRemainingSpace.Y + rRemainingSpace.Height/2 );
+ break;
+ default:
+ break;
+
+ }
+ }
+ apVTitle->changePosition( aNewPosition );
+
+ //remaining space
+ switch( eAlignment )
+ {
+ case ALIGN_TOP:
+ rRemainingSpace.Y += ( aTitleSize.Height + nYDistance );
+ rRemainingSpace.Height -= ( aTitleSize.Height + nYDistance );
+ break;
+ case ALIGN_BOTTOM:
+ rRemainingSpace.Height -= ( aTitleSize.Height + nYDistance );
+ break;
+ case ALIGN_LEFT:
+ rRemainingSpace.X += ( aTitleSize.Width + nXDistance );
+ rRemainingSpace.Width -= ( aTitleSize.Width + nXDistance );
+ break;
+ case ALIGN_RIGHT:
+ rRemainingSpace.Width -= ( aTitleSize.Width + nXDistance );
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ // #i109336# Improve auto positioning in chart
+ switch ( eAlignment )
+ {
+ case ALIGN_TOP:
+ {
+ rRemainingSpace.Y += nYDistance;
+ rRemainingSpace.Height -= nYDistance;
+ }
+ break;
+ case ALIGN_BOTTOM:
+ {
+ rRemainingSpace.Height -= nYDistance;
+ }
+ break;
+ case ALIGN_LEFT:
+ {
+ rRemainingSpace.X += nXDistance;
+ rRemainingSpace.Width -= nXDistance;
+ }
+ break;
+ case ALIGN_RIGHT:
+ {
+ rRemainingSpace.Width -= nXDistance;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ return apVTitle;
+}
+
+bool lcl_createLegend( const uno::Reference< XLegend > & xLegend
+ , const uno::Reference< drawing::XShapes>& xPageShapes
+ , const uno::Reference< lang::XMultiServiceFactory>& xShapeFactory
+ , const uno::Reference< uno::XComponentContext > & xContext
+ , awt::Rectangle & rRemainingSpace
+ , const awt::Size & rPageSize
+ , const uno::Reference< frame::XModel > & xModel
+ , const std::vector< LegendEntryProvider* >& rLegendEntryProviderList
+ , sal_Int16 nDefaultWritingMode )
+{
+ if( VLegend::isVisible( xLegend ))
+ {
+ VLegend aVLegend( xLegend, xContext, rLegendEntryProviderList );
+ aVLegend.init( xPageShapes, xShapeFactory, xModel );
+ aVLegend.setDefaultWritingMode( nDefaultWritingMode );
+ aVLegend.createShapes( awt::Size( rRemainingSpace.Width, rRemainingSpace.Height ),
+ rPageSize );
+ aVLegend.changePosition( rRemainingSpace, rPageSize );
+ return true;
+ }
+ return false;
+}
+
+void formatPage(
+ const uno::Reference< frame::XModel > & xModel
+ , const awt::Size rPageSize
+ , const uno::Reference< drawing::XShapes >& xTarget
+ , const uno::Reference< lang::XMultiServiceFactory>& xShapeFactory
+ )
+{
+ try
+ {
+ uno::Reference< XChartDocument > xChartDoc( xModel, uno::UNO_QUERY );
+ OSL_ASSERT( xChartDoc.is());
+ if( ! xChartDoc.is())
+ return;
+ uno::Reference< beans::XPropertySet > xModelPage( xChartDoc->getPageBackground());
+ if( ! xModelPage.is())
+ return;
+
+
+ if( !xShapeFactory.is() )
+ return;
+
+ uno::Reference< beans::XPropertySet > xPageProp;
+ // create a shape for the background
+ {
+ uno::Reference< drawing::XShape > xShape(
+ xShapeFactory->createInstance(
+ C2U( "com.sun.star.drawing.RectangleShape" )), uno::UNO_QUERY );
+ if( xTarget.is() &&
+ xShape.is())
+ {
+ xTarget->add( xShape );
+ xShape->setSize( rPageSize );
+ xPageProp.set( xShape, uno::UNO_QUERY );
+ if( xPageProp.is())
+ {
+ xPageProp->setPropertyValue( C2U("LineStyle"), uno::makeAny( drawing::LineStyle_NONE ));
+ }
+ }
+ }
+
+ //format page
+ if( xPageProp.is())
+ {
+ tPropertyNameValueMap aNameValueMap;
+ PropertyMapper::getValueMap( aNameValueMap, PropertyMapper::getPropertyNameMapForFillAndLineProperties(), xModelPage );
+
+ rtl::OUString aCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_PAGE, rtl::OUString() ) );
+ aNameValueMap.insert( tPropertyNameValueMap::value_type( C2U("Name"), uno::makeAny( aCID ) ) ); //CID rtl::OUString
+
+ tNameSequence aNames;
+ tAnySequence aValues;
+ PropertyMapper::getMultiPropertyListsFromValueMap( aNames, aValues, aNameValueMap );
+ PropertyMapper::setMultiProperties( aNames, aValues, xPageProp );
+ }
+ }
+ catch( uno::Exception & ex )
+ {
+ ASSERT_EXCEPTION( ex );
+ }
+}
+
+void lcl_removeEmptyGroupShapes( const Reference< drawing::XShapes>& xParent )
+{
+ if(!xParent.is())
+ return;
+ Reference< drawing::XShapeGroup > xParentGroup( xParent, uno::UNO_QUERY );
+ if( !xParentGroup.is() )
+ {
+ Reference< drawing::XDrawPage > xPage( xParent, uno::UNO_QUERY );
+ if( !xPage.is() )
+ return;
+ }
+
+ //iterate from back!
+ for( sal_Int32 nN = xParent->getCount(); nN--; )
+ {
+ uno::Any aAny = xParent->getByIndex( nN );
+ Reference< drawing::XShapes> xShapes(0);
+ if( aAny >>= xShapes )
+ lcl_removeEmptyGroupShapes( xShapes );
+ if( xShapes.is() && xShapes->getCount()==0 )
+ {
+ //remove empty group shape
+ Reference< drawing::XShapeGroup > xGroup( xShapes, uno::UNO_QUERY );
+ Reference< drawing::XShape > xShape( xShapes, uno::UNO_QUERY );
+ if( xGroup.is() )
+ xParent->remove( xShape );
+ }
+ }
+}
+
+bool ChartView::impl_AddInDrawsAllByItself()
+{
+ bool bRet = false;
+ /*
+ uno::Reference< beans::XPropertySet > xProp( m_xChartModel, uno::UNO_QUERY );
+ if( xProp.is()) try
+ {
+ uno::Reference< util::XRefreshable > xAddIn;
+ xProp->getPropertyValue( C2U( "AddIn" ) ) >>= xAddIn;
+ if( xAddIn.is() )
+ {
+ rtl::OUString aBaseDiagram;
+ xProp->getPropertyValue( C2U( "BaseDiagram" ) ) >>= aBaseDiagram;
+ if(aBaseDiagram.getLength())
+ bRet = true;
+ }
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+ */
+ return bRet;
+}
+
+void ChartView::impl_refreshAddIn()
+{
+ if( !m_bRefreshAddIn )
+ return;
+
+ uno::Reference< beans::XPropertySet > xProp( m_xChartModel, uno::UNO_QUERY );
+ if( xProp.is()) try
+ {
+ uno::Reference< util::XRefreshable > xAddIn;
+ xProp->getPropertyValue( C2U( "AddIn" ) ) >>= xAddIn;
+ if( xAddIn.is() )
+ {
+ sal_Bool bRefreshAddInAllowed = sal_True;
+ xProp->getPropertyValue( C2U( "RefreshAddInAllowed" ) ) >>= bRefreshAddInAllowed;
+ if( bRefreshAddInAllowed )
+ xAddIn->refresh();
+ }
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+}
+
+void ChartView::createShapes()
+{
+#if OSL_DEBUG_LEVEL > 0
+ clock_t nStart = clock();
+ OSL_TRACE( "\nPPPPPPPPP>>>>>>>>>>>> chart view :: createShapes()" );
+#endif
+
+ //make sure add-in is refreshed after creating the shapes
+ const ::comphelper::ScopeGuard aGuard( boost::bind( &ChartView::impl_refreshAddIn, this ) );
+ if( impl_AddInDrawsAllByItself() )
+ return;
+
+ m_aResultingDiagramRectangleExcludingAxes = awt::Rectangle(0,0,0,0);
+ impl_deleteCoordinateSystems();
+ if( m_pDrawModelWrapper )
+ {
+ // /--
+ ::vos::OGuard aSolarGuard( Application::GetSolarMutex());
+ // #i12587# support for shapes in chart
+ m_pDrawModelWrapper->getSdrModel().EnableUndo( FALSE );
+ m_pDrawModelWrapper->clearMainDrawPage();
+ // \--
+ }
+
+ lcl_setDefaultWritingMode( m_pDrawModelWrapper, m_xChartModel );
+
+ awt::Size aPageSize = ChartModelHelper::getPageSize( m_xChartModel );
+
+ uno::Reference<drawing::XShapes> xPageShapes( ShapeFactory(m_xShapeFactory)
+ .getOrCreateChartRootShape( m_xDrawPage ) );
+
+ SdrPage* pPage = ChartView::getSdrPage();
+ if(pPage) //it is neccessary to use the implementation here as the uno page does not provide a propertyset
+ pPage->SetSize(Size(aPageSize.Width,aPageSize.Height));
+ else
+ {
+ DBG_ERROR("could not set page size correctly");
+ }
+
+ {
+ ::vos::OGuard aSolarGuard( Application::GetSolarMutex());
+
+ //------------ apply fill properties to page
+ // todo: it would be nicer to just pass the page m_xDrawPage and format it,
+ // but the draw page does not support XPropertySet
+ formatPage( m_xChartModel, aPageSize, xPageShapes, m_xShapeFactory );
+
+ //sal_Int32 nYDistance = static_cast<sal_Int32>(aPageSize.Height*lcl_getPageLayoutDistancePercentage());
+ awt::Rectangle aRemainingSpace( 0, 0, aPageSize.Width, aPageSize.Height );
+
+ //create the group shape for diagram and axes first to have title and legends on top of it
+ uno::Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( m_xChartModel ) );
+ rtl::OUString aDiagramCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM, rtl::OUString::valueOf( sal_Int32(0) ) ) );//todo: other index if more than one diagram is possible
+ uno::Reference< drawing::XShapes > xDiagramPlusAxesPlusMarkHandlesGroup_Shapes( ShapeFactory(m_xShapeFactory).createGroup2D(xPageShapes,aDiagramCID) );
+
+ uno::Reference< drawing::XShape > xDiagram_MarkHandles( ShapeFactory(m_xShapeFactory).createInvisibleRectangle(
+ xDiagramPlusAxesPlusMarkHandlesGroup_Shapes, awt::Size(0,0) ) );
+ ShapeFactory::setShapeName( xDiagram_MarkHandles, C2U("MarkHandles") );
+
+ uno::Reference< drawing::XShape > xDiagram_OuterRect( ShapeFactory(m_xShapeFactory).createInvisibleRectangle(
+ xDiagramPlusAxesPlusMarkHandlesGroup_Shapes, awt::Size(0,0) ) );
+ ShapeFactory::setShapeName( xDiagram_OuterRect, C2U("PlotAreaIncludingAxes") );
+
+ uno::Reference< drawing::XShapes > xDiagramPlusAxes_Shapes( ShapeFactory(m_xShapeFactory).createGroup2D(xDiagramPlusAxesPlusMarkHandlesGroup_Shapes ) );
+
+ //------------ create some titles
+ std::auto_ptr<VTitle> apVTitle(0);
+ bool bAutoPositionDummy = true;
+
+ //------------ create main title shape
+ lcl_createTitle( TitleHelper::MAIN_TITLE, xPageShapes, m_xShapeFactory, m_xChartModel
+ , aRemainingSpace, aPageSize, ALIGN_TOP, bAutoPositionDummy );
+ if(aRemainingSpace.Width<=0||aRemainingSpace.Height<=0)
+ return;
+
+ //------------ create sub title shape
+ lcl_createTitle( TitleHelper::SUB_TITLE, xPageShapes, m_xShapeFactory, m_xChartModel
+ , aRemainingSpace, aPageSize, ALIGN_TOP, bAutoPositionDummy );
+ if(aRemainingSpace.Width<=0||aRemainingSpace.Height<=0)
+ return;
+
+
+ //------------ prepare series to give input to the legend (create categories and symbols etc.)
+ SeriesPlotterContainer aSeriesPlotterContainer( m_aVCooSysList );
+ aSeriesPlotterContainer.initializeCooSysAndSeriesPlotter( m_xChartModel );
+
+ //------------ create legend
+ lcl_createLegend( LegendHelper::getLegend( m_xChartModel ), xPageShapes, m_xShapeFactory, m_xCC
+ , aRemainingSpace, aPageSize, m_xChartModel, aSeriesPlotterContainer.getLegendEntryProviderList()
+ , lcl_getDefaultWritingModeFromPool( m_pDrawModelWrapper ) );
+ if(aRemainingSpace.Width<=0||aRemainingSpace.Height<=0)
+ return;
+
+ Reference< chart2::XChartType > xChartType( DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) );
+ sal_Int32 nDimension = DiagramHelper::getDimension( xDiagram );
+
+ //------------ create x axis title
+ bool bAutoPosition_XTitle = true;
+ std::auto_ptr<VTitle> apVTitle_X;
+ if( ChartTypeHelper::isSupportingMainAxis( xChartType, nDimension, 0 ) )
+ apVTitle_X = lcl_createTitle( TitleHelper::TITLE_AT_STANDARD_X_AXIS_POSITION, xPageShapes, m_xShapeFactory, m_xChartModel
+ , aRemainingSpace, aPageSize, ALIGN_BOTTOM, bAutoPosition_XTitle );
+ if(aRemainingSpace.Width<=0||aRemainingSpace.Height<=0)
+ return;
+
+ //------------ create y axis title
+ bool bAutoPosition_YTitle = true;
+ std::auto_ptr<VTitle> apVTitle_Y;
+ if( ChartTypeHelper::isSupportingMainAxis( xChartType, nDimension, 1 ) )
+ apVTitle_Y = lcl_createTitle( TitleHelper::TITLE_AT_STANDARD_Y_AXIS_POSITION, xPageShapes, m_xShapeFactory, m_xChartModel
+ , aRemainingSpace, aPageSize, ALIGN_LEFT, bAutoPosition_YTitle );
+ if(aRemainingSpace.Width<=0||aRemainingSpace.Height<=0)
+ return;
+
+ //------------ create z axis title
+ bool bAutoPosition_ZTitle = true;
+ std::auto_ptr<VTitle> apVTitle_Z;
+ if( ChartTypeHelper::isSupportingMainAxis( xChartType, nDimension, 2 ) )
+ apVTitle_Z = lcl_createTitle( TitleHelper::Z_AXIS_TITLE, xPageShapes, m_xShapeFactory, m_xChartModel
+ , aRemainingSpace, aPageSize, ALIGN_RIGHT, bAutoPosition_ZTitle );
+ if(aRemainingSpace.Width<=0||aRemainingSpace.Height<=0)
+ return;
+
+ bool bDummy = false;
+ bool bIsVertical = DiagramHelper::getVertical( xDiagram, bDummy, bDummy );
+
+ //------------ create secondary x axis title
+ bool bAutoPosition_SecondXTitle = true;
+ std::auto_ptr<VTitle> apVTitle_SecondX;
+ if( ChartTypeHelper::isSupportingSecondaryAxis( xChartType, nDimension, 0 ) )
+ apVTitle_SecondX = lcl_createTitle( TitleHelper::SECONDARY_X_AXIS_TITLE, xPageShapes, m_xShapeFactory, m_xChartModel
+ , aRemainingSpace, aPageSize, bIsVertical? ALIGN_RIGHT : ALIGN_TOP, bAutoPosition_SecondXTitle );
+ if(aRemainingSpace.Width<=0||aRemainingSpace.Height<=0)
+ return;
+
+ //------------ create secondary y axis title
+ bool bAutoPosition_SecondYTitle = true;
+ std::auto_ptr<VTitle> apVTitle_SecondY;
+ if( ChartTypeHelper::isSupportingSecondaryAxis( xChartType, nDimension, 1 ) )
+ apVTitle_SecondY = lcl_createTitle( TitleHelper::SECONDARY_Y_AXIS_TITLE, xPageShapes, m_xShapeFactory, m_xChartModel
+ , aRemainingSpace, aPageSize, bIsVertical? ALIGN_TOP : ALIGN_RIGHT, bAutoPosition_SecondYTitle );
+ if(aRemainingSpace.Width<=0||aRemainingSpace.Height<=0)
+ return;
+
+ //------------ create complete diagram shape (inclusive axis and series)
+ awt::Point aAvailablePosDia;
+ awt::Size aAvailableSizeForDiagram;
+ bool bUseFixedInnerSize = false;
+ if( getAvailablePosAndSizeForDiagram( aAvailablePosDia, aAvailableSizeForDiagram, aRemainingSpace, aPageSize
+ , ChartModelHelper::findDiagram( m_xChartModel ), bUseFixedInnerSize ) )
+ {
+ awt::Rectangle aUsedOuterRect = impl_createDiagramAndContent( aSeriesPlotterContainer
+ , xDiagramPlusAxes_Shapes
+ , aAvailablePosDia ,aAvailableSizeForDiagram, aPageSize, bUseFixedInnerSize, xDiagram_MarkHandles );
+
+ if( xDiagram_OuterRect.is() )
+ {
+ xDiagram_OuterRect->setPosition( awt::Point( aUsedOuterRect.X, aUsedOuterRect.Y ) );
+ xDiagram_OuterRect->setSize( awt::Size( aUsedOuterRect.Width, aUsedOuterRect.Height ) );
+ }
+
+ //correct axis title position
+ awt::Rectangle aDiagramPlusAxesRect( aUsedOuterRect );
+ if(bAutoPosition_XTitle)
+ changePositionOfAxisTitle( apVTitle_X.get(), ALIGN_BOTTOM, aDiagramPlusAxesRect, aPageSize );
+ if(bAutoPosition_YTitle)
+ changePositionOfAxisTitle( apVTitle_Y.get(), ALIGN_LEFT, aDiagramPlusAxesRect, aPageSize );
+ if(bAutoPosition_ZTitle)
+ changePositionOfAxisTitle( apVTitle_Z.get(), ALIGN_Z, aDiagramPlusAxesRect, aPageSize );
+ if(bAutoPosition_SecondXTitle)
+ changePositionOfAxisTitle( apVTitle_SecondX.get(), bIsVertical? ALIGN_RIGHT : ALIGN_TOP, aDiagramPlusAxesRect, aPageSize );
+ if(bAutoPosition_SecondYTitle)
+ changePositionOfAxisTitle( apVTitle_SecondY.get(), bIsVertical? ALIGN_TOP : ALIGN_RIGHT, aDiagramPlusAxesRect, aPageSize );
+ }
+
+ //cleanup: remove all empty group shapes to avoid grey border lines:
+ lcl_removeEmptyGroupShapes( xPageShapes );
+ }
+
+ // #i12587# support for shapes in chart
+ if ( m_pDrawModelWrapper )
+ {
+ ::vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ m_pDrawModelWrapper->getSdrModel().EnableUndo( TRUE );
+ }
+
+#if OSL_DEBUG_LEVEL > 0
+ clock_t nEnd = clock();
+ double fDuration =(double(nEnd-nStart)*1000.0)/double(CLOCKS_PER_SEC);
+
+ OSL_TRACE( "\nPPPPPPPPP<<<<<<<<<<<< chart view :: createShapes():: needed %f msec", fDuration );
+#endif
+}
+
+//-----------------------------------------------------------------
+// util::XEventListener (base of XCloseListener)
+//-----------------------------------------------------------------
+void SAL_CALL ChartView::disposing( const lang::EventObject& /* rSource */ )
+ throw(uno::RuntimeException)
+{
+ impl_setChartModel( 0 );
+}
+
+void ChartView::impl_updateView()
+{
+ if( !m_xChartModel.is() || !m_pDrawModelWrapper )
+ return;
+
+ // #i12587# support for shapes in chart
+ if ( m_bSdrViewIsInEditMode )
+ {
+ return;
+ }
+
+ if( m_bViewDirty && !m_bInViewUpdate )
+ {
+ m_bInViewUpdate = true;
+ //bool bOldRefreshAddIn = m_bRefreshAddIn;
+ //m_bRefreshAddIn = false;
+ try
+ {
+ impl_notifyModeChangeListener(C2U("invalid"));
+
+ //prepare draw model
+ {
+ // /--
+ ::vos::OGuard aSolarGuard( Application::GetSolarMutex());
+ m_pDrawModelWrapper->lockControllers();
+ // \--
+ }
+
+ //create chart view
+ {
+ m_bViewDirty = false;
+ m_bViewUpdatePending = false;
+ createShapes();
+
+ if( m_bViewDirty )
+ {
+ //avoid recursions due to add-in
+ m_bRefreshAddIn = false;
+ m_bViewDirty = false;
+ m_bViewUpdatePending = false;
+ //delete old chart view
+ createShapes();
+ m_bRefreshAddIn = true;
+ }
+ }
+
+ m_bViewDirty = m_bViewUpdatePending;
+ m_bViewUpdatePending = false;
+ m_bInViewUpdate = false;
+ }
+ catch( uno::Exception& ex)
+ {
+ m_bViewDirty = m_bViewUpdatePending;
+ m_bViewUpdatePending = false;
+ m_bInViewUpdate = false;
+ ASSERT_EXCEPTION( ex );
+ }
+
+ {
+ // /--
+ ::vos::OGuard aSolarGuard( Application::GetSolarMutex());
+ m_pDrawModelWrapper->unlockControllers();
+ // \--
+ }
+
+ impl_notifyModeChangeListener(C2U("valid"));
+
+ //m_bRefreshAddIn = bOldRefreshAddIn;
+ }
+}
+
+// ____ XModifyListener ____
+void SAL_CALL ChartView::modified( const lang::EventObject& /* aEvent */ )
+ throw (uno::RuntimeException)
+{
+ m_bViewDirty = sal_True;
+ if( m_bInViewUpdate )
+ m_bViewUpdatePending = true;
+
+ impl_notifyModeChangeListener(C2U("dirty"));
+}
+
+//SfxListener
+void ChartView::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
+{
+ //#i77362 change notification for changes on additional shapes are missing
+ if( m_bInViewUpdate )
+ return;
+
+ // #i12587# support for shapes in chart
+ if ( m_bSdrViewIsInEditMode && m_xChartModel.is() )
+ {
+ uno::Reference< view::XSelectionSupplier > xSelectionSupplier( m_xChartModel->getCurrentController(), uno::UNO_QUERY );
+ if ( xSelectionSupplier.is() )
+ {
+ ::rtl::OUString aSelObjCID;
+ uno::Any aSelObj( xSelectionSupplier->getSelection() );
+ aSelObj >>= aSelObjCID;
+ if ( aSelObjCID.getLength() > 0 )
+ {
+ return;
+ }
+ }
+ }
+
+ const SdrHint* pSdrHint = dynamic_cast< const SdrHint* >(&rHint);
+ if( !pSdrHint )
+ return;
+
+ bool bShapeChanged = false;
+ switch( pSdrHint->GetKind() )
+ {
+ case HINT_OBJCHG:
+ bShapeChanged = true;
+ break;
+ case HINT_OBJINSERTED:
+ bShapeChanged = true;
+ break;
+ case HINT_OBJREMOVED:
+ bShapeChanged = true;
+ break;
+ case HINT_MODELCLEARED:
+ bShapeChanged = true;
+ break;
+ case HINT_ENDEDIT:
+ bShapeChanged = true;
+ break;
+ default:
+ break;
+ }
+
+ if(bShapeChanged)
+ {
+ //#i76053# do not send view modified notifications for changes on the hidden page which contains e.g. the symbols for the dialogs
+ if( ChartView::getSdrPage() != pSdrHint->GetPage() )
+ bShapeChanged=false;
+ }
+
+ if(!bShapeChanged)
+ return;
+
+ Reference< util::XModifiable > xModifiable( m_xChartModel, uno::UNO_QUERY );
+ if( xModifiable.is() )
+ xModifiable->setModified( sal_True );
+}
+
+void ChartView::impl_notifyModeChangeListener( const rtl::OUString& rNewMode )
+{
+ try
+ {
+ ::cppu::OInterfaceContainerHelper* pIC = m_aListenerContainer
+ .getContainer( ::getCppuType((const uno::Reference< util::XModeChangeListener >*)0) );
+ if( pIC )
+ {
+ util::ModeChangeEvent aEvent( static_cast< uno::XWeak* >( this ), rNewMode );
+ ::cppu::OInterfaceIteratorHelper aIt( *pIC );
+ while( aIt.hasMoreElements() )
+ {
+ uno::Reference< util::XModeChangeListener > xListener( aIt.next(), uno::UNO_QUERY );
+ if( xListener.is() )
+ xListener->modeChanged( aEvent );
+ }
+ }
+ }
+ catch( uno::Exception& ex)
+ {
+ ASSERT_EXCEPTION( ex );
+ }
+}
+
+// ____ XModeChangeBroadcaster ____
+
+void SAL_CALL ChartView::addModeChangeListener( const uno::Reference< util::XModeChangeListener >& xListener )
+ throw (uno::RuntimeException)
+{
+ m_aListenerContainer.addInterface(
+ ::getCppuType((const uno::Reference< util::XModeChangeListener >*)0), xListener );
+}
+void SAL_CALL ChartView::removeModeChangeListener( const uno::Reference< util::XModeChangeListener >& xListener )
+ throw (uno::RuntimeException)
+{
+ m_aListenerContainer.removeInterface(
+ ::getCppuType((const uno::Reference< util::XModeChangeListener >*)0), xListener );
+}
+void SAL_CALL ChartView::addModeChangeApproveListener( const uno::Reference< util::XModeChangeApproveListener >& /* _rxListener */ )
+ throw (lang::NoSupportException, uno::RuntimeException)
+{
+
+}
+void SAL_CALL ChartView::removeModeChangeApproveListener( const uno::Reference< util::XModeChangeApproveListener >& /* _rxListener */ )
+ throw (lang::NoSupportException, uno::RuntimeException)
+{
+
+}
+
+// ____ XUpdatable ____
+void SAL_CALL ChartView::update() throw (uno::RuntimeException)
+{
+ impl_updateView();
+
+ //#i100778# migrate all imported or old documents to a plot area sizing exclusive axes (in case the save settings allow for this):
+ //Although in general it is a bad idea to change the model from within the view this is exceptionally the best place to do this special conversion.
+ //When a view update is requested (what happens for creating the metafile or displaying
+ //the chart in edit mode or printing) it is most likely that all necessary informations are available - like the underlying spreadsheet data for example.
+ //Those data is important for the correct axis lable sizes which are needed during conversion.
+ if( DiagramHelper::switchDiagramPositioningToExcludingPositioning( m_xChartModel, true, false ) )
+ impl_updateView();
+}
+
+// ____ XPropertySet ____
+Reference< beans::XPropertySetInfo > SAL_CALL ChartView::getPropertySetInfo()
+ throw (uno::RuntimeException)
+{
+ OSL_ENSURE(false,"not implemented");
+ return 0;
+}
+
+void SAL_CALL ChartView::setPropertyValue( const ::rtl::OUString& rPropertyName
+ , const Any& rValue )
+ throw (beans::UnknownPropertyException, beans::PropertyVetoException, lang::IllegalArgumentException
+ , lang::WrappedTargetException, uno::RuntimeException)
+{
+ if( rPropertyName.equals(C2U("Resolution")) )
+ {
+ awt::Size aNewResolution;
+ if( ! (rValue >>= aNewResolution) )
+ throw lang::IllegalArgumentException( C2U("Property 'Resolution' requires value of type awt::Size"), 0, 0 );
+
+ if( m_aPageResolution.Width!=aNewResolution.Width || m_aPageResolution.Height!=aNewResolution.Height )
+ {
+ //set modified only when the new resolution is higher and points were skipped before
+ bool bSetModified = m_bPointsWereSkipped && (m_aPageResolution.Width<aNewResolution.Width || m_aPageResolution.Height<aNewResolution.Height);
+
+ m_aPageResolution = aNewResolution;
+
+ if( bSetModified )
+ this->modified( lang::EventObject( static_cast< uno::XWeak* >( this ) ) );
+ }
+ }
+ else if( rPropertyName.equals(C2U("ZoomFactors")) )
+ {
+ //#i75867# poor quality of ole's alternative view with 3D scenes and zoomfactors besides 100%
+ uno::Sequence< beans::PropertyValue > aZoomFactors;
+ if( ! (rValue >>= aZoomFactors) )
+ throw lang::IllegalArgumentException( C2U("Property 'ZoomFactors' requires value of type Sequence< PropertyValue >"), 0, 0 );
+
+ sal_Int32 nFilterArgs = aZoomFactors.getLength();
+ beans::PropertyValue* pDataValues = aZoomFactors.getArray();
+ while( nFilterArgs-- )
+ {
+ if( pDataValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ScaleXNumerator" ) ) )
+ pDataValues->Value >>= m_nScaleXNumerator;
+ else if( pDataValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ScaleXDenominator" ) ) )
+ pDataValues->Value >>= m_nScaleXDenominator;
+ else if( pDataValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ScaleYNumerator" ) ) )
+ pDataValues->Value >>= m_nScaleYNumerator;
+ else if( pDataValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ScaleYDenominator" ) ) )
+ pDataValues->Value >>= m_nScaleYDenominator;
+
+ pDataValues++;
+ }
+ }
+ else if( rPropertyName.equals(C2U("SdrViewIsInEditMode")) )
+ {
+ //#i77362 change notification for changes on additional shapes are missing
+ if( ! (rValue >>= m_bSdrViewIsInEditMode) )
+ throw lang::IllegalArgumentException( C2U("Property 'SdrViewIsInEditMode' requires value of type sal_Bool"), 0, 0 );
+ }
+ else
+ throw beans::UnknownPropertyException( C2U("unknown property was tried to set to chart wizard"), 0 );
+}
+
+Any SAL_CALL ChartView::getPropertyValue( const ::rtl::OUString& rPropertyName )
+ throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException)
+{
+ Any aRet;
+ if( rPropertyName.equals(C2U("Resolution")) )
+ {
+ aRet = uno::makeAny( m_aPageResolution );
+ }
+ else
+ throw beans::UnknownPropertyException( C2U("unknown property was tried to get from chart wizard"), 0 );
+ return aRet;
+}
+
+void SAL_CALL ChartView::addPropertyChangeListener(
+ const ::rtl::OUString& /* aPropertyName */, const Reference< beans::XPropertyChangeListener >& /* xListener */ )
+ throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException)
+{
+ OSL_ENSURE(false,"not implemented");
+}
+void SAL_CALL ChartView::removePropertyChangeListener(
+ const ::rtl::OUString& /* aPropertyName */, const Reference< beans::XPropertyChangeListener >& /* aListener */ )
+ throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException)
+{
+ OSL_ENSURE(false,"not implemented");
+}
+
+void SAL_CALL ChartView::addVetoableChangeListener( const ::rtl::OUString& /* PropertyName */, const Reference< beans::XVetoableChangeListener >& /* aListener */ )
+ throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException)
+{
+ OSL_ENSURE(false,"not implemented");
+}
+
+void SAL_CALL ChartView::removeVetoableChangeListener( const ::rtl::OUString& /* PropertyName */, const Reference< beans::XVetoableChangeListener >& /* aListener */ )
+ throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException)
+{
+ OSL_ENSURE(false,"not implemented");
+}
+
+// ____ XMultiServiceFactory ____
+
+Reference< uno::XInterface > ChartView::createInstance( const ::rtl::OUString& aServiceSpecifier )
+ throw (uno::Exception, uno::RuntimeException)
+{
+ SdrModel* pModel = ( m_pDrawModelWrapper ? &m_pDrawModelWrapper->getSdrModel() : NULL );
+ if ( pModel )
+ {
+ if ( aServiceSpecifier.reverseCompareToAsciiL( RTL_CONSTASCII_STRINGPARAM( "com.sun.star.drawing.DashTable" ) ) == 0 )
+ {
+ if ( !m_xDashTable.is() )
+ {
+ m_xDashTable = SvxUnoDashTable_createInstance( pModel );
+ }
+ return m_xDashTable;
+ }
+ else if ( aServiceSpecifier.reverseCompareToAsciiL( RTL_CONSTASCII_STRINGPARAM( "com.sun.star.drawing.GradientTable" ) ) == 0 )
+ {
+ if ( !m_xGradientTable.is() )
+ {
+ m_xGradientTable = SvxUnoGradientTable_createInstance( pModel );
+ }
+ return m_xGradientTable;
+ }
+ else if ( aServiceSpecifier.reverseCompareToAsciiL( RTL_CONSTASCII_STRINGPARAM( "com.sun.star.drawing.HatchTable" ) ) == 0 )
+ {
+ if ( !m_xHatchTable.is() )
+ {
+ m_xHatchTable = SvxUnoHatchTable_createInstance( pModel );
+ }
+ return m_xHatchTable;
+ }
+ else if ( aServiceSpecifier.reverseCompareToAsciiL( RTL_CONSTASCII_STRINGPARAM( "com.sun.star.drawing.BitmapTable" ) ) == 0 )
+ {
+ if ( !m_xBitmapTable.is() )
+ {
+ m_xBitmapTable = SvxUnoBitmapTable_createInstance( pModel );
+ }
+ return m_xBitmapTable;
+ }
+ else if ( aServiceSpecifier.reverseCompareToAsciiL( RTL_CONSTASCII_STRINGPARAM( "com.sun.star.drawing.TransparencyGradientTable" ) ) == 0 )
+ {
+ if ( !m_xTransGradientTable.is() )
+ {
+ m_xTransGradientTable = SvxUnoTransGradientTable_createInstance( pModel );
+ }
+ return m_xTransGradientTable;
+ }
+ else if ( aServiceSpecifier.reverseCompareToAsciiL( RTL_CONSTASCII_STRINGPARAM( "com.sun.star.drawing.MarkerTable" ) ) == 0 )
+ {
+ if ( !m_xMarkerTable.is() )
+ {
+ m_xMarkerTable = SvxUnoMarkerTable_createInstance( pModel );
+ }
+ return m_xMarkerTable;
+ }
+ }
+
+ return 0;
+}
+
+Reference< uno::XInterface > ChartView::createInstanceWithArguments( const ::rtl::OUString& ServiceSpecifier, const uno::Sequence< uno::Any >& Arguments )
+ throw (uno::Exception, uno::RuntimeException)
+{
+ OSL_ENSURE( Arguments.getLength(), "ChartView::createInstanceWithArguments: arguments are ignored" );
+ (void) Arguments; // avoid warning
+ return createInstance( ServiceSpecifier );
+}
+
+uno::Sequence< ::rtl::OUString > ChartView::getAvailableServiceNames() throw (uno::RuntimeException)
+{
+ uno::Sequence< ::rtl::OUString > aServiceNames( 6 );
+
+ aServiceNames[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.DashTable" ) );
+ aServiceNames[1] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.GradientTable" ) );
+ aServiceNames[2] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.HatchTable" ) );
+ aServiceNames[3] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.BitmapTable" ) );
+ aServiceNames[4] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.TransparencyGradientTable" ) );
+ aServiceNames[5] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.MarkerTable" ) );
+
+ return aServiceNames;
+}
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
diff --git a/chart2/source/view/main/ChartView.hxx b/chart2/source/view/main/ChartView.hxx
new file mode 100644
index 000000000000..476adae03674
--- /dev/null
+++ b/chart2/source/view/main/ChartView.hxx
@@ -0,0 +1,261 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _CHARTVIEWIMPL_HXX
+#define _CHARTVIEWIMPL_HXX
+
+#include "chartview/ExplicitValueProvider.hxx"
+#include "ServiceMacros.hxx"
+#include <cppuhelper/implbase9.hxx>
+#include <cppuhelper/interfacecontainer.hxx>
+
+// header for class SfxListener
+#include <svl/lstner.hxx>
+#include <com/sun/star/datatransfer/XTransferable.hpp>
+#include <com/sun/star/drawing/XDrawPage.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/io/XOutputStream.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/util/XModifyListener.hpp>
+#include <com/sun/star/util/XModeChangeBroadcaster.hpp>
+#include <com/sun/star/util/XUpdatable.hpp>
+
+#include <vector>
+#include <boost/shared_ptr.hpp>
+
+class SdrPage;
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+
+class VCoordinateSystem;
+class DrawModelWrapper;
+class SeriesPlotterContainer;
+
+//-----------------------------------------------------------------------------
+/** The ChartView is responsible to manage the generation of Drawing Objects
+for visualization on a given OutputDevice. The ChartModel is responsible to notify changes to the view.
+The view than changes to state dirty. The view can be updated with call 'update'.
+
+The View is not responsible to handle single user events (that is instead done by the ChartWindow).
+*/
+
+class ChartView : public ::cppu::WeakImplHelper9<
+ ::com::sun::star::lang::XInitialization
+ , ::com::sun::star::lang::XServiceInfo
+ , ::com::sun::star::datatransfer::XTransferable
+ ,::com::sun::star::lang::XUnoTunnel
+ //::com::sun::star::lang::XComponent ???
+ //::com::sun::star::uno::XWeak // implemented by WeakImplHelper(optional interface)
+ //::com::sun::star::uno::XInterface // implemented by WeakImplHelper(optional interface)
+ //::com::sun::star::lang::XTypeProvider // implemented by WeakImplHelper
+ ,::com::sun::star::util::XModifyListener
+ ,::com::sun::star::util::XModeChangeBroadcaster
+ ,::com::sun::star::util::XUpdatable
+ ,::com::sun::star::beans::XPropertySet
+ ,::com::sun::star::lang::XMultiServiceFactory
+ >
+ , public ExplicitValueProvider
+ , private SfxListener
+{
+public:
+ ChartView(::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XComponentContext > const & xContext);
+ virtual ~ChartView();
+
+ // ___lang::XServiceInfo___
+ APPHELPER_XSERVICEINFO_DECL()
+ APPHELPER_SERVICE_FACTORY_HELPER(ChartView)
+
+ // ___lang::XInitialization___
+ virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments )
+ throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);
+
+ // ___ExplicitValueProvider___
+ virtual sal_Bool getExplicitValuesForAxis(
+ ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XAxis > xAxis
+ , ::com::sun::star::chart2::ExplicitScaleData& rExplicitScale
+ , ::com::sun::star::chart2::ExplicitIncrementData& rExplicitIncrement );
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >
+ getShapeForCID( const rtl::OUString& rObjectCID );
+
+ virtual ::com::sun::star::awt::Rectangle getRectangleOfObject( const rtl::OUString& rObjectCID, bool bSnapRect=false );
+
+ virtual ::com::sun::star::awt::Rectangle getDiagramRectangleExcludingAxes();
+
+ ::boost::shared_ptr< DrawModelWrapper > getDrawModelWrapper();
+
+ // ___XTransferable___
+ virtual ::com::sun::star::uno::Any SAL_CALL getTransferData( const ::com::sun::star::datatransfer::DataFlavor& aFlavor )
+ throw (::com::sun::star::datatransfer::UnsupportedFlavorException
+ , ::com::sun::star::io::IOException
+ , ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Sequence< ::com::sun::star::datatransfer::DataFlavor > SAL_CALL getTransferDataFlavors( )
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual ::sal_Bool SAL_CALL isDataFlavorSupported( const ::com::sun::star::datatransfer::DataFlavor& aFlavor )
+ throw (::com::sun::star::uno::RuntimeException);
+
+ //-------------------------------------------------------------------------------------
+ // ::com::sun::star::util::XEventListener (base of XCloseListener and XModifyListener)
+ //-------------------------------------------------------------------------------------
+ virtual void SAL_CALL
+ disposing( const ::com::sun::star::lang::EventObject& Source )
+ throw (::com::sun::star::uno::RuntimeException);
+
+ //-----------------------------------------------------------------
+ // ::com::sun::star::util::XModifyListener
+ //-----------------------------------------------------------------
+ virtual void SAL_CALL modified(
+ const ::com::sun::star::lang::EventObject& aEvent )
+ throw (::com::sun::star::uno::RuntimeException);
+
+ //SfxListener
+ virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint );
+
+ //-----------------------------------------------------------------
+ // ::com::sun::star::util::XModeChangeBroadcaster
+ //-----------------------------------------------------------------
+
+ virtual void SAL_CALL addModeChangeListener( const ::com::sun::star::uno::Reference< ::com::sun::star::util::XModeChangeListener >& _rxListener ) throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL removeModeChangeListener( const ::com::sun::star::uno::Reference< ::com::sun::star::util::XModeChangeListener >& _rxListener ) throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL addModeChangeApproveListener( const ::com::sun::star::uno::Reference< ::com::sun::star::util::XModeChangeApproveListener >& _rxListener ) throw (::com::sun::star::lang::NoSupportException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL removeModeChangeApproveListener( const ::com::sun::star::uno::Reference< ::com::sun::star::util::XModeChangeApproveListener >& _rxListener ) throw (::com::sun::star::lang::NoSupportException, ::com::sun::star::uno::RuntimeException);
+
+ //-----------------------------------------------------------------
+ // ::com::sun::star::util::XUpdatable
+ //-----------------------------------------------------------------
+ virtual void SAL_CALL update() throw (::com::sun::star::uno::RuntimeException);
+
+ //-----------------------------------------------------------------
+ // ::com::sun::star::beans::XPropertySet
+ //-----------------------------------------------------------------
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL setPropertyValue( const ::rtl::OUString& aPropertyName, const ::com::sun::star::uno::Any& aValue ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Any SAL_CALL getPropertyValue( const ::rtl::OUString& PropertyName ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL addPropertyChangeListener( const ::rtl::OUString& aPropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& xListener ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL removePropertyChangeListener( const ::rtl::OUString& aPropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& aListener ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL addVetoableChangeListener( const ::rtl::OUString& PropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XVetoableChangeListener >& aListener ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL removeVetoableChangeListener( const ::rtl::OUString& PropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XVetoableChangeListener >& aListener ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
+
+ //-----------------------------------------------------------------
+ // ::com::sun::star::lang::XMultiServiceFactory
+ //-----------------------------------------------------------------
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL createInstance( const ::rtl::OUString& aServiceSpecifier )
+ throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL createInstanceWithArguments(
+ const ::rtl::OUString& ServiceSpecifier, const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& Arguments )
+ throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getAvailableServiceNames() throw (::com::sun::star::uno::RuntimeException);
+
+ // for ExplicitValueProvider
+ // ____ XUnoTunnel ___
+ virtual ::sal_Int64 SAL_CALL getSomething( const ::com::sun::star::uno::Sequence< ::sal_Int8 >& aIdentifier )
+ throw (::com::sun::star::uno::RuntimeException);
+
+private: //methods
+ ChartView();
+
+ void createShapes();
+ void getMetaFile( const ::com::sun::star::uno::Reference< ::com::sun::star::io::XOutputStream >& xOutStream
+ , bool bUseHighContrast );
+ SdrPage* getSdrPage();
+
+ void impl_setChartModel( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel >& xChartModel );
+ void impl_deleteCoordinateSystems();
+ void impl_notifyModeChangeListener( const rtl::OUString& rNewMode );
+
+ void impl_refreshAddIn();
+ bool impl_AddInDrawsAllByItself();
+
+ void impl_updateView();
+
+ ::com::sun::star::awt::Rectangle impl_createDiagramAndContent( SeriesPlotterContainer& rSeriesPlotterContainer
+ , const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes>& xDiagramPlusAxes_Shapes
+ , const ::com::sun::star::awt::Point& rAvailablePos
+ , const ::com::sun::star::awt::Size& rAvailableSize
+ , const ::com::sun::star::awt::Size& rPageSize
+ , bool bUseFixedInnerSize
+ , const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape>& xDiagram_MarkHandles );
+
+
+private: //member
+ ::osl::Mutex m_aMutex;
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext>
+ m_xCC;
+ ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel >
+ m_xChartModel;
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>
+ m_xShapeFactory;
+ ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XDrawPage>
+ m_xDrawPage;
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > m_xDashTable;
+ ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > m_xGradientTable;
+ ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > m_xHatchTable;
+ ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > m_xBitmapTable;
+ ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > m_xTransGradientTable;
+ ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > m_xMarkerTable;
+
+ ::boost::shared_ptr< DrawModelWrapper > m_pDrawModelWrapper;
+
+ std::vector< VCoordinateSystem* > m_aVCooSysList;
+
+ ::cppu::OMultiTypeInterfaceContainerHelper
+ m_aListenerContainer;
+
+ bool volatile m_bViewDirty; //states wether the view needs to be rebuild
+ bool volatile m_bInViewUpdate;
+ bool volatile m_bViewUpdatePending;
+ bool volatile m_bRefreshAddIn;
+
+ //better performance for big data
+ ::com::sun::star::awt::Size m_aPageResolution;
+ bool m_bPointsWereSkipped;
+
+ //#i75867# poor quality of ole's alternative view with 3D scenes and zoomfactors besides 100%
+ sal_Int32 m_nScaleXNumerator;
+ sal_Int32 m_nScaleXDenominator;
+ sal_Int32 m_nScaleYNumerator;
+ sal_Int32 m_nScaleYDenominator;
+
+ sal_Bool m_bSdrViewIsInEditMode;
+
+ ::com::sun::star::awt::Rectangle m_aResultingDiagramRectangleExcludingAxes;
+};
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
+
+#endif
diff --git a/chart2/source/view/main/Clipping.cxx b/chart2/source/view/main/Clipping.cxx
new file mode 100644
index 000000000000..e61096e5a0ba
--- /dev/null
+++ b/chart2/source/view/main/Clipping.cxx
@@ -0,0 +1,304 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_chart2.hxx"
+
+#include "Clipping.hxx"
+#include "CommonConverters.hxx"
+#include "BaseGFXHelper.hxx"
+
+#include <com/sun/star/drawing/Position3D.hpp>
+#include <com/sun/star/drawing/DoubleSequence.hpp>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+using namespace ::com::sun::star;
+using ::basegfx::B2DRectangle;
+using ::basegfx::B2DTuple;
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+namespace{
+/** @descr This is a supporting function for lcl_clip2d. It computes a new parametric
+ value for an entering (dTE) or leaving (dTL) intersection point with one
+ of the edges bounding the clipping area.
+ For explanation of the parameters please refer to :
+
+ Liang-Biarsky parametric line-clipping algorithm as described in:
+ Computer Graphics: principles and practice, 2nd ed.,
+ James D. Foley et al.,
+ Section 3.12.4 on page 117.
+*/
+bool lcl_CLIPt(double fDenom,double fNum, double & fTE, double & fTL)
+{
+ double fT;
+
+ if (fDenom > 0) // Intersection enters: PE
+ {
+ fT = fNum / fDenom; // Parametric value at the intersection.
+ if (fT > fTL) // fTE and fTL crossover
+ return false; // therefore reject the line.
+ else if (fT > fTE) // A new fTE has been found.
+ fTE = fT;
+ }
+ else if (fDenom < 0) // Intersection leaves: PL
+ {
+ fT = fNum / fDenom; // Parametric Value at the intersection.
+ if (fT < fTE) // fTE and fTL crossover
+ return false; // therefore reject the line.
+ else if (fT < fTL) // A new fTL has been found.
+ fTL = fT;
+ }
+ else if (fNum > 0)
+ return false; // Line lies on the outside of the edge.
+
+ return true;
+}
+
+/** @descr The line given by it's two endpoints rP0 and rP1 is clipped at the rectangle
+ rRectangle. If there is at least a part of it visible then TRUE is returned and
+ the endpoints of that part are stored in rP0 and rP1. The points rP0 and rP1
+ may have the same coordinates.
+ @param rP0 Start point of the line to clip. Modified to contain a start point inside
+ the clipping area if possible.
+ @param rP1 End point of the line to clip. Modified to contain an end point inside
+ the clipping area if possible.
+ @param rRectangle Clipping area.
+ @return If the line lies completely or partly inside the clipping area then TRUE
+ is returned. If the line lies completely outside then FALSE is returned and rP0 and
+ rP1 are left unmodified.
+*/
+bool lcl_clip2d(B2DTuple& rPoint0, B2DTuple& rPoint1, const B2DRectangle& rRectangle)
+{
+ //Direction vector of the line.
+ B2DTuple aDirection = rPoint1 - rPoint0;
+
+ if( aDirection.getX()==0 && aDirection.getY()==0 && rRectangle.isInside(rPoint0) )
+ {
+ // Degenerate case of a zero length line.
+ return true;
+ }
+ else
+ {
+ // Values of the line parameter where the line enters resp. leaves the rectangle.
+ double fTE = 0,
+ fTL = 1;
+
+ // Test wether at least a part lies in the four half-planes with respect to
+ // the rectangles four edges.
+ if( lcl_CLIPt(aDirection.getX(), rRectangle.getMinX() - rPoint0.getX(), fTE, fTL) )
+ if( lcl_CLIPt(-aDirection.getX(), rPoint0.getX() - rRectangle.getMaxX(), fTE, fTL) )
+ if( lcl_CLIPt(aDirection.getY(), rRectangle.getMinY() - rPoint0.getY(), fTE, fTL) )
+ if( lcl_CLIPt(-aDirection.getY(), rPoint0.getY() - rRectangle.getMaxY(), fTE, fTL) )
+ {
+ // At least a part is visible.
+ if (fTL < 1)
+ {
+ // Compute the new end point.
+ rPoint1.setX( rPoint0.getX() + fTL * aDirection.getX() );
+ rPoint1.setY( rPoint0.getY() + fTL * aDirection.getY() );
+ }
+ if (fTE > 0)
+ {
+ // Compute the new starting point.
+ rPoint0.setX( rPoint0.getX() + fTE * aDirection.getX() );
+ rPoint0.setY( rPoint0.getY() + fTE * aDirection.getY() );
+ }
+ return true;
+ }
+
+ // Line is not visible.
+ return false;
+ }
+}
+
+bool lcl_clip2d_(drawing::Position3D& rPoint0, drawing::Position3D& rPoint1, const B2DRectangle& rRectangle)
+{
+ B2DTuple aP0(rPoint0.PositionX,rPoint0.PositionY);
+ B2DTuple aP1(rPoint1.PositionX,rPoint1.PositionY);
+ bool bRet = lcl_clip2d( aP0, aP1, rRectangle );
+
+ rPoint0.PositionX = aP0.getX();
+ rPoint0.PositionY = aP0.getY();
+ rPoint1.PositionX = aP1.getX();
+ rPoint1.PositionY = aP1.getY();
+
+ return bRet;
+}
+
+void lcl_addPointToPoly( drawing::PolyPolygonShape3D& rPoly
+ , const drawing::Position3D& rPos
+ , sal_Int32 nPolygonIndex
+ , std::vector< sal_Int32 >& rResultPointCount
+ , sal_Int32 nReservePointCount )
+{
+ if(nPolygonIndex<0)
+ {
+ OSL_ENSURE( false, "The polygon index needs to be > 0");
+ nPolygonIndex=0;
+ }
+
+ //make sure that we have enough polygons
+ if(nPolygonIndex >= rPoly.SequenceX.getLength() )
+ {
+ rPoly.SequenceX.realloc(nPolygonIndex+1);
+ rPoly.SequenceY.realloc(nPolygonIndex+1);
+ rPoly.SequenceZ.realloc(nPolygonIndex+1);
+ rResultPointCount.resize(nPolygonIndex+1,0);
+ }
+
+ drawing::DoubleSequence* pOuterSequenceX = &rPoly.SequenceX.getArray()[nPolygonIndex];
+ drawing::DoubleSequence* pOuterSequenceY = &rPoly.SequenceY.getArray()[nPolygonIndex];
+ drawing::DoubleSequence* pOuterSequenceZ = &rPoly.SequenceZ.getArray()[nPolygonIndex];
+
+ sal_Int32 nNewResultPointCount = rResultPointCount[nPolygonIndex]+1;
+ sal_Int32 nSeqLength = pOuterSequenceX->getLength();
+
+ if( nSeqLength <= nNewResultPointCount )
+ {
+ sal_Int32 nReallocLength = nReservePointCount;
+ if( nNewResultPointCount > nReallocLength )
+ {
+ nReallocLength = nNewResultPointCount;
+ DBG_ERROR("this should not be the case to avoid performance problems");
+ }
+ pOuterSequenceX->realloc(nReallocLength);
+ pOuterSequenceY->realloc(nReallocLength);
+ pOuterSequenceZ->realloc(nReallocLength);
+ }
+
+ double* pInnerSequenceX = pOuterSequenceX->getArray();
+ double* pInnerSequenceY = pOuterSequenceY->getArray();
+ double* pInnerSequenceZ = pOuterSequenceZ->getArray();
+
+ pInnerSequenceX[nNewResultPointCount-1] = rPos.PositionX;
+ pInnerSequenceY[nNewResultPointCount-1] = rPos.PositionY;
+ pInnerSequenceZ[nNewResultPointCount-1] = rPos.PositionZ;
+ rResultPointCount[nPolygonIndex]=nNewResultPointCount;
+}
+
+}//end anonymous namespace
+
+void Clipping::clipPolygonAtRectangle( const drawing::PolyPolygonShape3D& rPolygon
+ , const B2DRectangle& rRectangle
+ , drawing::PolyPolygonShape3D& aResult
+ , bool bSplitPiecesToDifferentPolygons )
+{
+ aResult.SequenceX.realloc(0);
+ aResult.SequenceY.realloc(0);
+ aResult.SequenceZ.realloc(0);
+
+ if(!rPolygon.SequenceX.getLength())
+ return;
+
+ //need clipping?:
+ {
+ ::basegfx::B3DRange a3DRange( BaseGFXHelper::getBoundVolume( rPolygon ) );
+ ::basegfx::B2DRange a2DRange( a3DRange.getMinX(), a3DRange.getMinY(), a3DRange.getMaxX(), a3DRange.getMaxY() );
+ if( rRectangle.isInside( a2DRange ) )
+ {
+ aResult = rPolygon;
+ return;
+ }
+ else
+ {
+ a2DRange.intersect( rRectangle );
+ if( a2DRange.isEmpty() )
+ return;
+ }
+ }
+
+ //
+ std::vector< sal_Int32 > aResultPointCount;//per polygon index
+
+ //apply clipping:
+ drawing::Position3D aFrom;
+ drawing::Position3D aTo;
+
+ sal_Int32 nNewPolyIndex = 0;
+ sal_Int32 nOldPolyCount = rPolygon.SequenceX.getLength();
+ for(sal_Int32 nOldPolyIndex=0; nOldPolyIndex<nOldPolyCount; nOldPolyIndex++, nNewPolyIndex++ )
+ {
+ sal_Int32 nOldPointCount = rPolygon.SequenceX[nOldPolyIndex].getLength();
+
+ // set last point to a position outside the rectangle, such that the first
+ // time lcl_clip2d returns true, the comparison to last will always yield false
+ drawing::Position3D aLast(rRectangle.getMinX()-1.0,rRectangle.getMinY()-1.0, 0.0 );
+
+ for(sal_Int32 nOldPoint=1; nOldPoint<nOldPointCount; nOldPoint++)
+ {
+ aFrom = getPointFromPoly(rPolygon,nOldPoint-1,nOldPolyIndex);
+ aTo = getPointFromPoly(rPolygon,nOldPoint,nOldPolyIndex);
+ if( lcl_clip2d_(aFrom, aTo, rRectangle) )
+ {
+ // compose an Polygon of as many consecutive points as possible
+ if(aFrom == aLast)
+ {
+ if( !(aTo==aFrom) )
+ {
+ lcl_addPointToPoly( aResult, aTo, nNewPolyIndex, aResultPointCount, nOldPointCount );
+ }
+ }
+ else
+ {
+ if( bSplitPiecesToDifferentPolygons && nOldPoint!=1 )
+ {
+ if( nNewPolyIndex < aResult.SequenceX.getLength()
+ && aResultPointCount[nNewPolyIndex]>0 )
+ nNewPolyIndex++;
+ }
+ lcl_addPointToPoly( aResult, aFrom, nNewPolyIndex, aResultPointCount, nOldPointCount );
+ if( !(aTo==aFrom) )
+ lcl_addPointToPoly( aResult, aTo, nNewPolyIndex, aResultPointCount, nOldPointCount );
+ }
+ aLast = aTo;
+ }
+ }
+ }
+ //free unused space
+ for( sal_Int32 nPolygonIndex = aResultPointCount.size(); nPolygonIndex--; )
+ {
+ drawing::DoubleSequence* pOuterSequenceX = &aResult.SequenceX.getArray()[nPolygonIndex];
+ drawing::DoubleSequence* pOuterSequenceY = &aResult.SequenceY.getArray()[nPolygonIndex];
+ drawing::DoubleSequence* pOuterSequenceZ = &aResult.SequenceZ.getArray()[nPolygonIndex];
+
+ sal_Int32 nUsedPointCount = aResultPointCount[nPolygonIndex];
+ pOuterSequenceX->realloc(nUsedPointCount);
+ pOuterSequenceY->realloc(nUsedPointCount);
+ pOuterSequenceZ->realloc(nUsedPointCount);
+ }
+}
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
diff --git a/chart2/source/view/main/DataPointSymbolSupplier.cxx b/chart2/source/view/main/DataPointSymbolSupplier.cxx
new file mode 100644
index 000000000000..d59a011cd429
--- /dev/null
+++ b/chart2/source/view/main/DataPointSymbolSupplier.cxx
@@ -0,0 +1,66 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_chart2.hxx"
+
+#include "chartview/DataPointSymbolSupplier.hxx"
+#include "ShapeFactory.hxx"
+#include "macros.hxx"
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+using namespace ::com::sun::star;
+//using namespace ::com::sun::star::chart2;
+
+uno::Reference< drawing::XShapes > DataPointSymbolSupplier::create2DSymbolList(
+ uno::Reference< lang::XMultiServiceFactory > xShapeFactory
+ , const uno::Reference< drawing::XShapes >& xTarget
+ , const drawing::Direction3D& rSize )
+{
+ uno::Reference< drawing::XShape > xGroup(
+ xShapeFactory->createInstance( C2U(
+ "com.sun.star.drawing.GroupShape" ) ), uno::UNO_QUERY );
+ if(xTarget.is())
+ xTarget->add(xGroup);
+ uno::Reference< drawing::XShapes > xGroupShapes =
+ uno::Reference<drawing::XShapes>( xGroup, uno::UNO_QUERY );
+
+ ShapeFactory aShapeFactory(xShapeFactory);
+ drawing::Position3D aPos(0,0,0);
+ for(sal_Int32 nS=0;nS<ShapeFactory::getSymbolCount();nS++)
+ {
+ aShapeFactory.createSymbol2D( xGroupShapes, aPos, rSize, nS );
+ }
+ return xGroupShapes;
+}
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
diff --git a/chart2/source/view/main/DrawModelWrapper.cxx b/chart2/source/view/main/DrawModelWrapper.cxx
new file mode 100644
index 000000000000..577f450172b5
--- /dev/null
+++ b/chart2/source/view/main/DrawModelWrapper.cxx
@@ -0,0 +1,411 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_chart2.hxx"
+
+#include "chartview/DrawModelWrapper.hxx"
+#include "macros.hxx"
+#include "ShapeFactory.hxx"
+#include "ChartItemPool.hxx"
+#include "ObjectIdentifier.hxx"
+#include <svx/unomodel.hxx>
+#include <svl/itempool.hxx>
+// header for class SfxBoolItem
+#include <svl/eitem.hxx>
+// header for define EE_PARA_HYPHENATE
+#include <editeng/eeitem.hxx>
+// header for class Svx3DPercentDiagonalItem
+#include <svx/svx3ditems.hxx>
+// header for class SvtPathOptions
+#include <unotools/pathoptions.hxx>
+// header E3dObjFactory
+#include <svx/objfac3d.hxx>
+// header for class SdrObjList
+#include <svx/svdpage.hxx>
+// header for SvxUnoXDashTable_createInstance
+#include <svx/XPropertyTable.hxx>
+// header for class XDashList
+#include <svx/xtable.hxx>
+// header for class SdrOutliner
+#include <svx/svdoutl.hxx>
+// header for class LinguMgr
+#include <editeng/unolingu.hxx>
+// header for class Application
+#include <vcl/svapp.hxx>
+// header for class VirtualDevice
+#include <vcl/virdev.hxx>
+
+#include <com/sun/star/container/XChild.hpp>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
+
+#include <sfx2/objsh.hxx>
+#include <com/sun/star/linguistic2/XHyphenator.hpp>
+#include <com/sun/star/linguistic2/XSpellChecker1.hpp>
+
+using namespace ::com::sun::star;
+
+//.............................................................................
+namespace
+{
+// this code is copied from sfx2/source/doc/objembed.cxx
+SfxObjectShell * lcl_GetParentObjectShell( const uno::Reference< frame::XModel > & xModel )
+{
+ SfxObjectShell* pResult = NULL;
+
+ try
+ {
+ uno::Reference< container::XChild > xChildModel( xModel, uno::UNO_QUERY );
+ if ( xChildModel.is() )
+ {
+ uno::Reference< lang::XUnoTunnel > xParentTunnel( xChildModel->getParent(), uno::UNO_QUERY );
+ if ( xParentTunnel.is() )
+ {
+ SvGlobalName aSfxIdent( SFX_GLOBAL_CLASSID );
+ pResult = reinterpret_cast< SfxObjectShell * >(
+ xParentTunnel->getSomething( uno::Sequence< sal_Int8 >( aSfxIdent.GetByteSequence() ) ) );
+ }
+ }
+ }
+ catch( uno::Exception& )
+ {
+ // TODO: error handling
+ }
+
+ return pResult;
+}
+
+// this code is copied from sfx2/source/doc/objembed.cxx. It is a workaround to
+// get the reference device (e.g. printer) fromthe parent document
+OutputDevice * lcl_GetParentRefDevice( const uno::Reference< frame::XModel > & xModel )
+{
+ SfxObjectShell * pParent = lcl_GetParentObjectShell( xModel );
+ if ( pParent )
+ return pParent->GetDocumentRefDev();
+ return NULL;
+}
+
+} // anonymous namespace
+
+//.. ...........................................................................
+namespace chart
+{
+//.............................................................................
+
+DrawModelWrapper::DrawModelWrapper(
+ uno::Reference<uno::XComponentContext> const & xContext )
+ : SdrModel( SvtPathOptions().GetPalettePath() )
+ , m_xMCF(0)
+ , m_pChartItemPool(0)
+ , m_xMainDrawPage(0)
+ , m_xHiddenDrawPage(0)
+ , m_apRefDevice(0)
+{
+ m_pChartItemPool = ChartItemPool::CreateChartItemPool();
+
+ m_xMCF = xContext->getServiceManager();
+
+ SetScaleUnit(MAP_100TH_MM);
+ SetScaleFraction(Fraction(1, 1));
+ SetDefaultFontHeight(423); // 12pt
+
+ SfxItemPool* pMasterPool = &GetItemPool();
+ pMasterPool->SetDefaultMetric(SFX_MAPUNIT_100TH_MM);
+ pMasterPool->SetPoolDefaultItem(SfxBoolItem(EE_PARA_HYPHENATE, TRUE) );
+ pMasterPool->SetPoolDefaultItem(Svx3DPercentDiagonalItem (5));
+
+ SfxItemPool* pPool = pMasterPool;
+ // append chart pool to end of pool chain
+ for (;;)
+ {
+ SfxItemPool* pSecondary = pPool->GetSecondaryPool();
+ if (!pSecondary)
+ break;
+
+ pPool = pSecondary;
+ }
+ pPool->SetSecondaryPool(m_pChartItemPool);
+ pMasterPool->FreezeIdRanges();
+
+ //this factory needs to be created before first use of 3D scenes once upon an office runtime
+ //@todo in future this should be done by drawing engine itself on demand
+ static bool b3dFactoryInitialized = false;
+ if(!b3dFactoryInitialized)
+ {
+ E3dObjFactory aObjFactory;
+ b3dFactoryInitialized = true;
+ }
+
+ //Hyphenyation and spellchecking
+ SdrOutliner& rOutliner = GetDrawOutliner();
+ try
+ {
+ uno::Reference< linguistic2::XHyphenator > xHyphenator( LinguMgr::GetHyphenator() );
+ if( xHyphenator.is() )
+ rOutliner.SetHyphenator( xHyphenator );
+
+ uno::Reference< linguistic2::XSpellChecker1 > xSpellChecker( LinguMgr::GetSpellChecker() );
+ if ( xSpellChecker.is() )
+ rOutliner.SetSpeller( xSpellChecker );
+ }
+ catch(...)
+ {
+ DBG_ERROR("Can't get Hyphenator or SpellChecker for chart");
+ }
+
+ //ref device for font rendering
+ OutputDevice* pDefaultDevice = rOutliner.GetRefDevice();
+ if( !pDefaultDevice )
+ pDefaultDevice = Application::GetDefaultDevice();
+ m_apRefDevice = std::auto_ptr< OutputDevice >( new VirtualDevice( *pDefaultDevice ) );
+ MapMode aMapMode = m_apRefDevice->GetMapMode();
+ aMapMode.SetMapUnit(MAP_100TH_MM);
+ m_apRefDevice->SetMapMode(aMapMode);
+ SetRefDevice(m_apRefDevice.get());
+ rOutliner.SetRefDevice(m_apRefDevice.get());
+}
+
+DrawModelWrapper::~DrawModelWrapper()
+{
+ //remove m_pChartItemPool from pool chain
+ if(m_pChartItemPool)
+ {
+ SfxItemPool* pPool = &GetItemPool();
+ for (;;)
+ {
+ SfxItemPool* pSecondary = pPool->GetSecondaryPool();
+ if(pSecondary == m_pChartItemPool)
+ {
+ pPool->SetSecondaryPool (NULL);
+ break;
+ }
+ pPool = pSecondary;
+ }
+ SfxItemPool::Free(m_pChartItemPool);
+ }
+}
+
+uno::Reference< uno::XInterface > DrawModelWrapper
+::createUnoModel()
+{
+ uno::Reference< lang::XComponent > xComponent = new SvxUnoDrawingModel( this ); //tell Andreas Schluens if SvxUnoDrawingModel is not needed anymore -> remove export from svx to avoid link problems in writer
+ return uno::Reference< uno::XInterface >::query( xComponent );
+}
+
+uno::Reference< frame::XModel > DrawModelWrapper::getUnoModel()
+{
+ uno::Reference< uno::XInterface > xI = this->SdrModel::getUnoModel();
+ return uno::Reference<frame::XModel>::query( xI );
+}
+
+SdrModel& DrawModelWrapper::getSdrModel()
+{
+ return *this;
+}
+
+uno::Reference< lang::XMultiServiceFactory > DrawModelWrapper::getShapeFactory()
+{
+ uno::Reference< lang::XMultiServiceFactory > xShapeFactory( this->getUnoModel(), uno::UNO_QUERY );
+ return xShapeFactory;
+}
+
+uno::Reference< drawing::XDrawPage > DrawModelWrapper::getMainDrawPage()
+{
+ //create draw page:
+ if( !m_xMainDrawPage.is() )
+ {
+ uno::Reference< drawing::XDrawPagesSupplier > xDrawPagesSuplier( this->getUnoModel(), uno::UNO_QUERY );
+ if( xDrawPagesSuplier.is() )
+ {
+ uno::Reference< drawing::XDrawPages > xDrawPages( xDrawPagesSuplier->getDrawPages () );
+ if( xDrawPages->getCount()>1 )
+ {
+ uno::Any aPage = xDrawPages->getByIndex( 0 ) ;
+ aPage >>= m_xMainDrawPage;
+ }
+ if(!m_xMainDrawPage.is())
+ {
+ m_xMainDrawPage = xDrawPages->insertNewByIndex( 0 );
+ }
+ }
+ }
+ //ensure that additional shapes are in front of the chart objects so create the chart root before
+ ShapeFactory(this->getShapeFactory()).getOrCreateChartRootShape( m_xMainDrawPage );
+ return m_xMainDrawPage;
+}
+uno::Reference< drawing::XDrawPage > DrawModelWrapper::getHiddenDrawPage()
+{
+ if( !m_xHiddenDrawPage.is() )
+ {
+ uno::Reference< drawing::XDrawPagesSupplier > xDrawPagesSuplier( this->getUnoModel(), uno::UNO_QUERY );
+ if( xDrawPagesSuplier.is() )
+ {
+ uno::Reference< drawing::XDrawPages > xDrawPages( xDrawPagesSuplier->getDrawPages () );
+ if( xDrawPages->getCount()>1 )
+ {
+ uno::Any aPage = xDrawPages->getByIndex( 1 ) ;
+ aPage >>= m_xHiddenDrawPage;
+ }
+
+ if(!m_xHiddenDrawPage.is())
+ {
+ if( xDrawPages->getCount()==0 )
+ m_xMainDrawPage = xDrawPages->insertNewByIndex( 0 );
+ m_xHiddenDrawPage = xDrawPages->insertNewByIndex( 1 );
+ }
+ }
+ }
+ return m_xHiddenDrawPage;
+}
+void DrawModelWrapper::clearMainDrawPage()
+{
+ //uno::Reference<drawing::XShapes> xChartRoot( m_xMainDrawPage, uno::UNO_QUERY );
+ uno::Reference<drawing::XShapes> xChartRoot( ShapeFactory::getChartRootShape( m_xMainDrawPage ) );
+ if( xChartRoot.is() )
+ {
+ sal_Int32 nSubCount = xChartRoot->getCount();
+ uno::Reference< drawing::XShape > xShape;
+ for( sal_Int32 nS = nSubCount; nS--; )
+ {
+ if( xChartRoot->getByIndex( nS ) >>= xShape )
+ xChartRoot->remove( xShape );
+ }
+ }
+}
+
+uno::Reference< drawing::XShapes > DrawModelWrapper::getChartRootShape(
+ const uno::Reference< drawing::XDrawPage>& xDrawPage )
+{
+ return ShapeFactory::getChartRootShape( xDrawPage );
+}
+
+void DrawModelWrapper::lockControllers()
+{
+ uno::Reference< frame::XModel > xDrawModel( this->getUnoModel() );
+ if( xDrawModel.is())
+ xDrawModel->lockControllers();
+}
+void DrawModelWrapper::unlockControllers()
+{
+ uno::Reference< frame::XModel > xDrawModel( this->getUnoModel() );
+ if( xDrawModel.is())
+ xDrawModel->unlockControllers();
+}
+
+void DrawModelWrapper::attachParentReferenceDevice( const uno::Reference< frame::XModel > & xChartModel )
+{
+ OutputDevice * pParentRefDev( lcl_GetParentRefDevice( xChartModel ));
+ if( pParentRefDev )
+ {
+ SetRefDevice( pParentRefDev );
+ }
+}
+
+OutputDevice* DrawModelWrapper::getReferenceDevice() const
+{
+ return SdrModel::GetRefDevice();
+}
+
+SfxItemPool& DrawModelWrapper::GetItemPool()
+{
+ return this->SdrModel::GetItemPool();
+}
+const SfxItemPool& DrawModelWrapper::GetItemPool() const
+{
+ return this->SdrModel::GetItemPool();
+}
+XColorTable* DrawModelWrapper::GetColorTable() const
+{
+ return this->SdrModel::GetColorTable();
+}
+XDashList* DrawModelWrapper::GetDashList() const
+{
+ return this->SdrModel::GetDashList();
+}
+XLineEndList* DrawModelWrapper::GetLineEndList() const
+{
+ return this->SdrModel::GetLineEndList();
+}
+XGradientList* DrawModelWrapper::GetGradientList() const
+{
+ return this->SdrModel::GetGradientList();
+}
+XHatchList* DrawModelWrapper::GetHatchList() const
+{
+ return this->SdrModel::GetHatchList();
+}
+XBitmapList* DrawModelWrapper::GetBitmapList() const
+{
+ return this->SdrModel::GetBitmapList();
+}
+
+SdrObject* DrawModelWrapper::getNamedSdrObject( const rtl::OUString& rName )
+{
+ if(rName.getLength()==0)
+ return 0;
+ return getNamedSdrObject( rName, GetPage(0) );
+}
+
+//static
+SdrObject* DrawModelWrapper::getNamedSdrObject( const String& rObjectCID, SdrObjList* pSearchList )
+{
+ if(!pSearchList || rObjectCID.Len()==0)
+ return 0;
+ ULONG nCount = pSearchList->GetObjCount();
+ for( ULONG nN=0; nN<nCount; nN++ )
+ {
+ SdrObject* pObj = pSearchList->GetObj(nN);
+ if(!pObj)
+ continue;
+ if( ObjectIdentifier::areIdenticalObjects( rObjectCID, pObj->GetName() ) )
+ return pObj;
+ pObj = DrawModelWrapper::getNamedSdrObject( rObjectCID, pObj->GetSubList() );
+ if(pObj)
+ return pObj;
+ }
+ return 0;
+}
+
+//static
+bool DrawModelWrapper::removeShape( const uno::Reference< drawing::XShape >& xShape )
+{
+ uno::Reference< container::XChild > xChild( xShape, uno::UNO_QUERY );
+ if( xChild.is() )
+ {
+ uno::Reference<drawing::XShapes> xShapes( xChild->getParent(), uno::UNO_QUERY );
+ if( xShapes.is() )
+ {
+ xShapes->remove(xShape);
+ return true;
+ }
+ }
+ return false;
+}
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
diff --git a/chart2/source/view/main/LabelPositionHelper.cxx b/chart2/source/view/main/LabelPositionHelper.cxx
new file mode 100644
index 000000000000..24ec5a285468
--- /dev/null
+++ b/chart2/source/view/main/LabelPositionHelper.cxx
@@ -0,0 +1,488 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_chart2.hxx"
+
+#include "LabelPositionHelper.hxx"
+#include "PlottingPositionHelper.hxx"
+#include "CommonConverters.hxx"
+#include "PropertyMapper.hxx"
+#include "ShapeFactory.hxx"
+#include "macros.hxx"
+#include "RelativeSizeHelper.hxx"
+#include <com/sun/star/drawing/TextVerticalAdjust.hpp>
+#include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+LabelPositionHelper::LabelPositionHelper(
+ PlottingPositionHelper* pPosHelper
+ , sal_Int32 nDimensionCount
+ , const uno::Reference< drawing::XShapes >& xLogicTarget
+ , ShapeFactory* pShapeFactory )
+ : m_pPosHelper(pPosHelper)
+ , m_nDimensionCount(nDimensionCount)
+ , m_xLogicTarget(xLogicTarget)
+ , m_pShapeFactory(pShapeFactory)
+{
+}
+
+LabelPositionHelper::~LabelPositionHelper()
+{
+}
+
+awt::Point LabelPositionHelper::transformSceneToScreenPosition( const drawing::Position3D& rScenePosition3D ) const
+{
+ return PlottingPositionHelper::transformSceneToScreenPosition(
+ rScenePosition3D, m_xLogicTarget, m_pShapeFactory, m_nDimensionCount );
+}
+
+//static
+void LabelPositionHelper::changeTextAdjustment( tAnySequence& rPropValues, const tNameSequence& rPropNames, LabelAlignment eAlignment)
+{
+ //HorizontalAdjustment
+ {
+ drawing::TextHorizontalAdjust eHorizontalAdjust = drawing::TextHorizontalAdjust_CENTER;
+ if( LABEL_ALIGN_RIGHT==eAlignment || LABEL_ALIGN_RIGHT_TOP==eAlignment || LABEL_ALIGN_RIGHT_BOTTOM==eAlignment )
+ eHorizontalAdjust = drawing::TextHorizontalAdjust_LEFT;
+ else if( LABEL_ALIGN_LEFT==eAlignment || LABEL_ALIGN_LEFT_TOP==eAlignment || LABEL_ALIGN_LEFT_BOTTOM==eAlignment )
+ eHorizontalAdjust = drawing::TextHorizontalAdjust_RIGHT;
+ uno::Any* pHorizontalAdjustAny = PropertyMapper::getValuePointer(rPropValues,rPropNames,C2U("TextHorizontalAdjust"));
+ if(pHorizontalAdjustAny)
+ *pHorizontalAdjustAny = uno::makeAny(eHorizontalAdjust);
+ }
+
+ //VerticalAdjustment
+ {
+ drawing::TextVerticalAdjust eVerticalAdjust = drawing::TextVerticalAdjust_CENTER;
+ if( LABEL_ALIGN_TOP==eAlignment || LABEL_ALIGN_RIGHT_TOP==eAlignment || LABEL_ALIGN_LEFT_TOP==eAlignment )
+ eVerticalAdjust = drawing::TextVerticalAdjust_BOTTOM;
+ else if( LABEL_ALIGN_BOTTOM==eAlignment || LABEL_ALIGN_RIGHT_BOTTOM==eAlignment || LABEL_ALIGN_LEFT_BOTTOM==eAlignment )
+ eVerticalAdjust = drawing::TextVerticalAdjust_TOP;
+ uno::Any* pVerticalAdjustAny = PropertyMapper::getValuePointer(rPropValues,rPropNames,C2U("TextVerticalAdjust"));
+ if(pVerticalAdjustAny)
+ *pVerticalAdjustAny = uno::makeAny(eVerticalAdjust);
+ }
+}
+
+void lcl_doDynamicFontResize( uno::Any* pAOldAndNewFontHeightAny
+ , const awt::Size& rOldReferenceSize
+ , const awt::Size& rNewReferenceSize )
+{
+ double fOldFontHeight = 0, fNewFontHeight;
+ if( pAOldAndNewFontHeightAny && ( *pAOldAndNewFontHeightAny >>= fOldFontHeight ) )
+ {
+ fNewFontHeight = RelativeSizeHelper::calculate( fOldFontHeight, rOldReferenceSize, rNewReferenceSize );
+ *pAOldAndNewFontHeightAny = uno::makeAny(fNewFontHeight);
+ }
+}
+
+//static
+void LabelPositionHelper::doDynamicFontResize( tAnySequence& rPropValues
+ , const tNameSequence& rPropNames
+ , const uno::Reference< beans::XPropertySet >& xAxisModelProps
+ , const awt::Size& rNewReferenceSize
+ )
+{
+ //-------------------------
+ //handle dynamic font resize:
+ awt::Size aOldReferenceSize;
+ if( xAxisModelProps->getPropertyValue( C2U("ReferencePageSize")) >>= aOldReferenceSize )
+ {
+ uno::Any* pAOldAndNewFontHeightAny = PropertyMapper::getValuePointer( rPropValues, rPropNames, C2U("CharHeight") );
+ lcl_doDynamicFontResize( pAOldAndNewFontHeightAny, aOldReferenceSize, rNewReferenceSize );
+ pAOldAndNewFontHeightAny = PropertyMapper::getValuePointer( rPropValues, rPropNames, C2U("CharHeightAsian") );
+ lcl_doDynamicFontResize( pAOldAndNewFontHeightAny, aOldReferenceSize, rNewReferenceSize );
+ pAOldAndNewFontHeightAny = PropertyMapper::getValuePointer( rPropValues, rPropNames, C2U("CharHeightComplex") );
+ lcl_doDynamicFontResize( pAOldAndNewFontHeightAny, aOldReferenceSize, rNewReferenceSize );
+ }
+}
+
+namespace
+{
+
+void lcl_correctRotation_Left( double& rfXCorrection, double& rfYCorrection
+ , double fAnglePositiveDegree, const awt::Size& aSize, bool bRotateAroundCenter )
+{
+ //correct label positions for labels on a left side of something with a right centered alignment
+ double fAnglePi = fAnglePositiveDegree*F_PI/180.0;
+ if( fAnglePositiveDegree==0.0 )
+ {
+ }
+ else if( fAnglePositiveDegree<= 90.0 )
+ {
+ rfXCorrection = -aSize.Height*rtl::math::sin( fAnglePi )/2.0;
+ if( bRotateAroundCenter )
+ rfYCorrection = -aSize.Width*rtl::math::sin( fAnglePi )/2.0;
+ }
+ else if( fAnglePositiveDegree<= 180.0 )
+ {
+ double beta = fAnglePi-F_PI/2.0;
+ rfXCorrection = -aSize.Width *rtl::math::sin( beta )
+ -aSize.Height *rtl::math::cos( beta )/2.0;
+ if( bRotateAroundCenter )
+ rfYCorrection = -aSize.Width *rtl::math::cos( beta )/2.0;
+ else
+ rfYCorrection = -aSize.Width *rtl::math::cos( beta );
+ }
+ else if( fAnglePositiveDegree<= 270.0 )
+ {
+ double beta = fAnglePi - F_PI;
+ rfXCorrection = -aSize.Width *rtl::math::cos( beta )
+ -aSize.Height*rtl::math::sin( beta )/2.0;
+ if( bRotateAroundCenter )
+ rfYCorrection = aSize.Width *rtl::math::sin( beta )/2.0;
+ else
+ rfYCorrection = aSize.Width *rtl::math::sin( beta );
+ }
+ else
+ {
+ double beta = 2*F_PI - fAnglePi;
+ rfXCorrection = -aSize.Height*rtl::math::sin( beta )/2.0;
+ if( bRotateAroundCenter )
+ rfYCorrection = aSize.Width*rtl::math::sin( beta )/2.0;
+ }
+}
+
+void lcl_correctRotation_Right( double& rfXCorrection, double& rfYCorrection
+ , double fAnglePositiveDegree, const awt::Size& aSize, bool bRotateAroundCenter )
+{
+ //correct label positions for labels on a right side of something with a left centered alignment
+ double fAnglePi = fAnglePositiveDegree*F_PI/180.0;
+ if( fAnglePositiveDegree== 0.0 )
+ {
+ }
+ else if( fAnglePositiveDegree<= 90.0 )
+ {
+ rfXCorrection = aSize.Height*rtl::math::sin( fAnglePi )/2.0;
+ if( bRotateAroundCenter )
+ rfYCorrection = aSize.Width*rtl::math::sin( fAnglePi )/2.0;
+ }
+ else if( fAnglePositiveDegree<= 180.0 )
+ {
+ double beta = F_PI - fAnglePi;
+ rfXCorrection = aSize.Width *rtl::math::cos( beta )
+ + aSize.Height*rtl::math::sin( beta )/2.0;
+ if( bRotateAroundCenter )
+ rfYCorrection = aSize.Width *rtl::math::sin( beta )/2.0;
+ else
+ rfYCorrection = aSize.Width *rtl::math::sin( beta );
+ }
+ else if( fAnglePositiveDegree<= 270.0 )
+ {
+ double beta = 3*F_PI/2.0 - fAnglePi;
+ rfXCorrection = aSize.Width *rtl::math::sin( beta )
+ +aSize.Height*rtl::math::cos( beta )/2.0;
+ if( bRotateAroundCenter )
+ rfYCorrection = -aSize.Width *rtl::math::cos( beta )/2.0;
+ else
+ rfYCorrection = -aSize.Width *rtl::math::cos( beta );
+ }
+ else
+ {
+ rfXCorrection = aSize.Height*rtl::math::sin( 2*F_PI - fAnglePi )/2.0;
+ if( bRotateAroundCenter )
+ rfYCorrection = -aSize.Width*rtl::math::sin( 2*F_PI - fAnglePi )/2.0;
+ }
+}
+
+void lcl_correctRotation_Top( double& rfXCorrection, double& rfYCorrection
+ , double fAnglePositiveDegree, const awt::Size& aSize, bool bRotateAroundCenter )
+{
+ //correct label positions for labels on top of something with a bottom centered alignment
+ double fAnglePi = fAnglePositiveDegree*F_PI/180.0;
+ if( fAnglePositiveDegree== 0.0 )
+ {
+ }
+ else if( fAnglePositiveDegree<= 90.0 )
+ {
+ rfXCorrection = aSize.Height*rtl::math::sin( fAnglePi )/2.0;
+ if( !bRotateAroundCenter )
+ rfXCorrection += aSize.Width*rtl::math::cos( fAnglePi )/2.0;
+ rfYCorrection = -aSize.Width*rtl::math::sin( fAnglePi )/2.0;
+ }
+ else if( fAnglePositiveDegree<= 180.0 )
+ {
+ double beta = fAnglePi - F_PI/2.0;
+ rfXCorrection = aSize.Height*rtl::math::cos( beta )/2.0;
+ if( !bRotateAroundCenter )
+ rfXCorrection -= aSize.Width*rtl::math::sin( beta )/2.0;
+ rfYCorrection = -aSize.Width*rtl::math::cos( beta )/2.0
+ - aSize.Height*rtl::math::sin( beta );
+ }
+ else if( fAnglePositiveDegree<= 270.0 )
+ {
+ double beta = fAnglePi - F_PI;
+ rfXCorrection = -aSize.Height *rtl::math::sin( beta )/2.0;
+ if( !bRotateAroundCenter )
+ rfXCorrection += aSize.Width *rtl::math::cos( beta )/2.0;
+ rfYCorrection = -aSize.Width *rtl::math::sin( beta )/2.0
+ -aSize.Height *rtl::math::cos( beta );
+ }
+ else
+ {
+ rfXCorrection = aSize.Height*rtl::math::sin( fAnglePi )/2.0;
+ if( !bRotateAroundCenter )
+ rfXCorrection -= aSize.Width*rtl::math::cos( fAnglePi )/2.0;
+ rfYCorrection = aSize.Width*rtl::math::sin( fAnglePi )/2.0;
+ }
+}
+
+void lcl_correctRotation_Bottom( double& rfXCorrection, double& rfYCorrection
+ , double fAnglePositiveDegree, const awt::Size& aSize, bool bRotateAroundCenter )
+{
+ //correct label positions for labels below something with a top centered alignment
+ double fAnglePi = fAnglePositiveDegree*F_PI/180.0;
+ if( fAnglePositiveDegree==0.0 )
+ {
+ }
+ else if( fAnglePositiveDegree<= 90.0 )
+ {
+ rfXCorrection = -aSize.Height*rtl::math::sin( fAnglePi )/2.0;
+ if( !bRotateAroundCenter )
+ rfXCorrection -= aSize.Width *rtl::math::cos( fAnglePi )/2.0;
+ rfYCorrection = aSize.Width*rtl::math::sin( fAnglePi )/2.0;
+ }
+ else if( fAnglePositiveDegree<= 180.0 )
+ {
+ double beta = fAnglePi-F_PI/2.0;
+ rfXCorrection = -aSize.Height*rtl::math::cos( beta )/2.0;
+ if( !bRotateAroundCenter )
+ rfXCorrection += aSize.Width *rtl::math::sin( beta )/2.0;
+ rfYCorrection = aSize.Width *rtl::math::cos( beta )/2.0
+ +aSize.Height*rtl::math::sin( beta );
+ }
+ else if( fAnglePositiveDegree<= 270.0 )
+ {
+ double beta = 3*F_PI/2.0 - fAnglePi;
+ rfXCorrection = aSize.Height*rtl::math::cos( beta )/2.0;
+ if( !bRotateAroundCenter )
+ rfXCorrection -= aSize.Width *rtl::math::sin( beta )/2.0;
+ rfYCorrection = aSize.Height*rtl::math::sin( beta )
+ +aSize.Width*rtl::math::cos( beta )/2.0;
+ }
+ else
+ {
+ double beta = 2*F_PI - fAnglePi;
+ rfXCorrection = aSize.Height*rtl::math::sin( beta )/2.0;
+ if( !bRotateAroundCenter )
+ rfXCorrection += aSize.Width*rtl::math::cos( beta )/2.0;
+ rfYCorrection = aSize.Width*rtl::math::sin( beta )/2.0;
+ }
+}
+
+void lcl_correctRotation_Left_Top( double& rfXCorrection, double& rfYCorrection
+ , double fAnglePositiveDegree, const awt::Size& aSize )
+{
+ //correct position for labels at the left top corner of something with a bottom right alignment
+ double fAnglePi = fAnglePositiveDegree*F_PI/180.0;
+ if( fAnglePositiveDegree==0.0 )
+ {
+ }
+ else if( fAnglePositiveDegree<= 90.0 )
+ {
+ rfYCorrection = -aSize.Width*rtl::math::sin( fAnglePi );
+ }
+ else if( fAnglePositiveDegree<= 180.0 )
+ {
+ double beta = fAnglePi-F_PI/2.0;
+ rfXCorrection = -aSize.Width*rtl::math::sin( beta );
+ rfYCorrection = -aSize.Height*rtl::math::sin( beta )
+ -aSize.Width*rtl::math::cos( beta );
+ }
+ else if( fAnglePositiveDegree<= 270.0 )
+ {
+ double beta = 3*F_PI/2.0 - fAnglePi;
+ rfXCorrection = -aSize.Height*rtl::math::cos( beta )
+ -aSize.Width*rtl::math::sin( beta );
+ rfYCorrection = -aSize.Height*rtl::math::sin( beta );
+ }
+ else
+ {
+ rfXCorrection = aSize.Height*rtl::math::sin( fAnglePi );
+ }
+}
+
+void lcl_correctRotation_Left_Bottom( double& rfXCorrection, double& rfYCorrection
+ , double fAnglePositiveDegree, const awt::Size& aSize )
+{
+ //correct position for labels at the left bottom corner of something with a top right alignment
+ double fAnglePi = fAnglePositiveDegree*F_PI/180.0;
+ if( fAnglePositiveDegree==0.0 )
+ {
+ }
+ else if( fAnglePositiveDegree<= 90.0 )
+ {
+ rfXCorrection = -aSize.Height*rtl::math::sin( fAnglePi );
+ }
+ else if( fAnglePositiveDegree<= 180.0 )
+ {
+ double beta = fAnglePi-F_PI/2.0;
+ rfXCorrection = -aSize.Width*rtl::math::sin( beta )
+ -aSize.Height*rtl::math::cos( beta );;
+ rfYCorrection = aSize.Height*rtl::math::sin( beta );
+ }
+ else if( fAnglePositiveDegree<= 270.0 )
+ {
+ double beta = 3*F_PI/2.0 - fAnglePi;
+ rfXCorrection = -aSize.Width*rtl::math::sin( beta );
+ rfYCorrection = aSize.Width*rtl::math::cos( beta )
+ +aSize.Height*rtl::math::sin( beta );
+ }
+ else
+ {
+ rfYCorrection = -aSize.Width*rtl::math::sin( fAnglePi );
+ }
+}
+
+void lcl_correctRotation_Right_Top( double& rfXCorrection, double& rfYCorrection
+ , double fAnglePositiveDegree, const awt::Size& aSize )
+{
+ //correct position for labels at the right top corner of something with a bottom left alignment
+ double fAnglePi = fAnglePositiveDegree*F_PI/180.0;
+ if( fAnglePositiveDegree==0.0 )
+ {
+ }
+ else if( fAnglePositiveDegree<= 90.0 )
+ {
+ rfXCorrection = aSize.Height*rtl::math::sin( fAnglePi );
+ }
+ else if( fAnglePositiveDegree<= 180.0 )
+ {
+ double beta = fAnglePi-F_PI/2.0;
+ rfXCorrection = aSize.Width*rtl::math::sin( beta )
+ +aSize.Height*rtl::math::cos( beta );
+ rfYCorrection = -aSize.Height*rtl::math::sin( beta );
+ }
+ else if( fAnglePositiveDegree<= 270.0 )
+ {
+ double beta = 3*F_PI/2.0 - fAnglePi;
+ rfXCorrection = aSize.Width*rtl::math::sin( beta );
+ rfYCorrection = -aSize.Width*rtl::math::cos( beta )
+ -aSize.Height*rtl::math::sin( beta );
+ }
+ else
+ {
+ rfYCorrection = aSize.Width*rtl::math::sin( fAnglePi );
+ }
+}
+
+void lcl_correctRotation_Right_Bottom( double& rfXCorrection, double& rfYCorrection
+ , double fAnglePositiveDegree, const awt::Size& aSize )
+{
+ //correct position for labels at the right bottom corner of something with a top left alignment
+ double fAnglePi = fAnglePositiveDegree*F_PI/180.0;
+ if( fAnglePositiveDegree==0.0 )
+ {
+ }
+ else if( fAnglePositiveDegree<= 90.0 )
+ {
+ rfYCorrection = aSize.Width*rtl::math::sin( fAnglePi );
+ }
+ else if( fAnglePositiveDegree<= 180.0 )
+ {
+ double beta = fAnglePi-F_PI/2.0;
+ rfXCorrection = aSize.Width*rtl::math::sin( beta );
+ rfYCorrection = aSize.Height*rtl::math::sin( beta )
+ +aSize.Width*rtl::math::cos( beta );
+ }
+ else if( fAnglePositiveDegree<= 270.0 )
+ {
+ double beta = 3*F_PI/2.0 - fAnglePi;
+ rfXCorrection = aSize.Height*rtl::math::cos( beta )
+ +aSize.Width*rtl::math::sin( beta );
+ rfYCorrection = aSize.Height*rtl::math::sin( beta );
+ }
+ else
+ {
+ rfXCorrection = -aSize.Height*rtl::math::sin( fAnglePi );
+ }
+}
+
+}//end anonymous namespace
+
+//static
+void LabelPositionHelper::correctPositionForRotation( const uno::Reference< drawing::XShape >& xShape2DText
+ , LabelAlignment eLabelAlignment, const double fRotationAngle, bool bRotateAroundCenter )
+{
+ if( !xShape2DText.is() )
+ return;
+
+ awt::Point aOldPos = xShape2DText->getPosition();
+ awt::Size aSize = xShape2DText->getSize();
+
+ double fYCorrection = 0.0;
+ double fXCorrection = 0.0;
+
+ double fAnglePositiveDegree = fRotationAngle;
+ while(fAnglePositiveDegree<0.0)
+ fAnglePositiveDegree+=360.0;
+
+ switch(eLabelAlignment)
+ {
+ case LABEL_ALIGN_LEFT:
+ lcl_correctRotation_Left( fXCorrection, fYCorrection, fAnglePositiveDegree, aSize, bRotateAroundCenter );
+ break;
+ case LABEL_ALIGN_RIGHT:
+ lcl_correctRotation_Right( fXCorrection, fYCorrection, fAnglePositiveDegree, aSize, bRotateAroundCenter );
+ break;
+ case LABEL_ALIGN_TOP:
+ lcl_correctRotation_Top( fXCorrection, fYCorrection, fAnglePositiveDegree, aSize, bRotateAroundCenter );
+ break;
+ case LABEL_ALIGN_BOTTOM:
+ lcl_correctRotation_Bottom( fXCorrection, fYCorrection, fAnglePositiveDegree, aSize, bRotateAroundCenter );
+ break;
+ case LABEL_ALIGN_LEFT_TOP:
+ lcl_correctRotation_Left_Top( fXCorrection, fYCorrection, fAnglePositiveDegree, aSize );
+ break;
+ case LABEL_ALIGN_LEFT_BOTTOM:
+ lcl_correctRotation_Left_Bottom( fXCorrection, fYCorrection, fAnglePositiveDegree, aSize );
+ break;
+ case LABEL_ALIGN_RIGHT_TOP:
+ lcl_correctRotation_Right_Top( fXCorrection, fYCorrection, fAnglePositiveDegree, aSize );
+ break;
+ case LABEL_ALIGN_RIGHT_BOTTOM:
+ lcl_correctRotation_Right_Bottom( fXCorrection, fYCorrection, fAnglePositiveDegree, aSize );
+ break;
+ default: //LABEL_ALIGN_CENTER
+ break;
+ }
+
+ xShape2DText->setPosition( awt::Point(
+ static_cast<sal_Int32>(aOldPos.X + fXCorrection )
+ , static_cast<sal_Int32>(aOldPos.Y + fYCorrection ) ) );
+}
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
diff --git a/chart2/source/view/main/Linear3DTransformation.cxx b/chart2/source/view/main/Linear3DTransformation.cxx
new file mode 100644
index 000000000000..9292ee6eb757
--- /dev/null
+++ b/chart2/source/view/main/Linear3DTransformation.cxx
@@ -0,0 +1,107 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_chart2.hxx"
+#include "Linear3DTransformation.hxx"
+#include <algorithm>
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::RuntimeException;
+
+namespace chart
+{
+
+ Linear3DTransformation::Linear3DTransformation( const drawing::HomogenMatrix& rHomMatrix, bool bSwapXAndY )
+ : m_Matrix(rHomMatrix)
+ , m_bSwapXAndY(bSwapXAndY)
+{}
+
+Linear3DTransformation::~Linear3DTransformation()
+{}
+
+// ____ XTransformation ____
+Sequence< double > SAL_CALL Linear3DTransformation::transform(
+ const Sequence< double >& rSourceValues )
+ throw (RuntimeException,
+ lang::IllegalArgumentException)
+{
+ double fX = rSourceValues[0];
+ double fY = rSourceValues[1];
+ double fZ = rSourceValues[2];
+ if(m_bSwapXAndY)
+ std::swap(fX,fY);
+ Sequence< double > aNewVec(3);
+ double fZwi;
+
+ fZwi = m_Matrix.Line1.Column1 * fX
+ + m_Matrix.Line1.Column2 * fY
+ + m_Matrix.Line1.Column3 * fZ
+ + m_Matrix.Line1.Column4;
+ aNewVec[0] = fZwi;
+
+ fZwi = m_Matrix.Line2.Column1 * fX
+ + m_Matrix.Line2.Column2 * fY
+ + m_Matrix.Line2.Column3 * fZ
+ + m_Matrix.Line2.Column4;
+ aNewVec[1] = fZwi;
+
+ fZwi = m_Matrix.Line3.Column1 * fX
+ + m_Matrix.Line3.Column2 * fY
+ + m_Matrix.Line3.Column3 * fZ
+ + m_Matrix.Line3.Column4;
+ aNewVec[2] = fZwi;
+
+ fZwi = m_Matrix.Line4.Column1 * fX
+ + m_Matrix.Line4.Column2 * fY
+ + m_Matrix.Line4.Column3 * fZ
+ + m_Matrix.Line4.Column4;
+ if(fZwi != 1.0 && fZwi != 0.0)
+ {
+ aNewVec[0] /= fZwi;
+ aNewVec[1] /= fZwi;
+ aNewVec[2] /= fZwi;
+ }
+ return aNewVec;
+}
+
+sal_Int32 SAL_CALL Linear3DTransformation::getSourceDimension()
+ throw (RuntimeException)
+{
+ return 3;
+}
+
+sal_Int32 SAL_CALL Linear3DTransformation::getTargetDimension()
+ throw (RuntimeException)
+{
+ return 3;
+}
+
+
+} // namespace chart
diff --git a/chart2/source/view/main/NumberFormatterWrapper.cxx b/chart2/source/view/main/NumberFormatterWrapper.cxx
new file mode 100644
index 000000000000..4e4cd342506c
--- /dev/null
+++ b/chart2/source/view/main/NumberFormatterWrapper.cxx
@@ -0,0 +1,169 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_chart2.hxx"
+#include "chartview/NumberFormatterWrapper.hxx"
+#include "macros.hxx"
+#include <comphelper/processfactory.hxx>
+// header for class SvNumberFormatsSupplierObj
+#include <svl/numuno.hxx>
+// header for class SvNumberformat
+#include <svl/zformat.hxx>
+#include <tools/color.hxx>
+#include <i18npool/mslangid.hxx>
+#include <tools/debug.hxx>
+#include <com/sun/star/util/DateTime.hpp>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+using namespace ::com::sun::star;
+
+FixedNumberFormatter::FixedNumberFormatter(
+ const uno::Reference< util::XNumberFormatsSupplier >& xSupplier
+ , sal_Int32 nNumberFormatKey )
+ : m_aNumberFormatterWrapper(xSupplier)
+ , m_nNumberFormatKey( nNumberFormatKey )
+{
+}
+
+FixedNumberFormatter::~FixedNumberFormatter()
+{
+}
+
+/*
+sal_Int32 FixedNumberFormatter::getTextAndColor( double fUnscaledValueForText, rtl::OUString& rLabel ) const
+{
+ sal_Int32 nLabelColor = Color(COL_BLUE).GetColor(); //@todo get this from somewheres
+ rLabel = getFormattedString( fUnscaledValueForText, nLabelColor );
+ return nLabelColor;
+}
+*/
+
+rtl::OUString FixedNumberFormatter::getFormattedString( double fValue, sal_Int32& rLabelColor, bool& rbColorChanged ) const
+{
+ return m_aNumberFormatterWrapper.getFormattedString(
+ m_nNumberFormatKey, fValue, rLabelColor, rbColorChanged );
+}
+
+//-----------------------------------------------------------------------
+//-----------------------------------------------------------------------
+//-----------------------------------------------------------------------
+
+NumberFormatterWrapper::NumberFormatterWrapper( const uno::Reference< util::XNumberFormatsSupplier >& xSupplier )
+ : m_xNumberFormatsSupplier(xSupplier)
+ , m_pNumberFormatter(NULL)
+
+{
+ uno::Reference<beans::XPropertySet> xProp(m_xNumberFormatsSupplier,uno::UNO_QUERY);
+ rtl::OUString sNullDate( RTL_CONSTASCII_USTRINGPARAM("NullDate"));
+ if ( xProp.is() && xProp->getPropertySetInfo()->hasPropertyByName(sNullDate) )
+ m_aNullDate = xProp->getPropertyValue(sNullDate);
+ SvNumberFormatsSupplierObj* pSupplierObj = SvNumberFormatsSupplierObj::getImplementation( xSupplier );
+ if( pSupplierObj )
+ m_pNumberFormatter = pSupplierObj->GetNumberFormatter();
+ DBG_ASSERT(m_pNumberFormatter,"need a numberformatter");
+}
+
+NumberFormatterWrapper::~NumberFormatterWrapper()
+{
+}
+
+SvNumberFormatter* NumberFormatterWrapper::getSvNumberFormatter() const
+{
+ return m_pNumberFormatter;
+}
+
+rtl::OUString NumberFormatterWrapper::getFormattedString(
+ sal_Int32 nNumberFormatKey, double fValue, sal_Int32& rLabelColor, bool& rbColorChanged ) const
+{
+ String aText;
+ Color* pTextColor = NULL;
+ if( !m_pNumberFormatter )
+ {
+ DBG_ERROR("Need a NumberFormatter");
+ return aText;
+ }
+ // i99104 handle null date correctly
+ USHORT nYear = 1899,nDay = 30,nMonth = 12;
+ if ( m_aNullDate.hasValue() )
+ {
+ Date* pDate = m_pNumberFormatter->GetNullDate();
+ if ( pDate )
+ {
+ nYear = pDate->GetYear();
+ nMonth = pDate->GetMonth();
+ nDay = pDate->GetDay();
+ } // if ( pDate )
+ util::DateTime aNewNullDate;
+ m_aNullDate >>= aNewNullDate;
+ m_pNumberFormatter->ChangeNullDate(aNewNullDate.Day,aNewNullDate.Month,aNewNullDate.Year);
+ }
+ m_pNumberFormatter->GetOutputString(
+ fValue, nNumberFormatKey, aText, &pTextColor);
+ if ( m_aNullDate.hasValue() )
+ {
+ m_pNumberFormatter->ChangeNullDate(nDay,nMonth,nYear);
+ }
+ rtl::OUString aRet( aText );
+
+ if(pTextColor)
+ {
+ rbColorChanged = true;
+ rLabelColor = pTextColor->GetColor();
+ }
+ else
+ rbColorChanged = false;
+
+ return aRet;
+}
+
+// to get the language type use MsLangId::convertLocaleToLanguage( rNumberFormat.aLocale )
+
+/*
+ uno::Reference< i18n::XNumberFormatCode > xNumberFormatCode(
+ m_xCC->getServiceManager()->createInstanceWithContext( C2U(
+ "com.sun.star.i18n.NumberFormatMapper" ), m_xCC ), uno::UNO_QUERY );
+
+ i18n::NumberFormatCode aNumberFormatCode = xNumberFormatCode->getDefault (
+ i18n::KNumberFormatType::MEDIUM,
+ i18n::KNumberFormatUsage::SCIENTIFIC_NUMBER,
+ aLocale );
+
+ uno::Sequence< i18n::NumberFormatCode > aListOfNumberFormatCode = xNumberFormatCode->getAllFormatCode(
+ i18n::KNumberFormatUsage::SCIENTIFIC_NUMBER,
+ aLocale );
+
+ i18n::NumberFormatCode aNumberFormatCode0 = aListOfNumberFormatCode[0];
+ i18n::NumberFormatCode aNumberFormatCode1 = aListOfNumberFormatCode[1];
+*/
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
diff --git a/chart2/source/view/main/PlotterBase.cxx b/chart2/source/view/main/PlotterBase.cxx
new file mode 100644
index 000000000000..08f43dc7064d
--- /dev/null
+++ b/chart2/source/view/main/PlotterBase.cxx
@@ -0,0 +1,135 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_chart2.hxx"
+#include "PlotterBase.hxx"
+#include "PlottingPositionHelper.hxx"
+#include "ShapeFactory.hxx"
+#include <rtl/math.hxx>
+#include <com/sun/star/chart2/DataPointLabel.hpp>
+#include <tools/debug.hxx>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+PlotterBase::PlotterBase( sal_Int32 nDimensionCount )
+ : m_xLogicTarget(NULL)
+ , m_xFinalTarget(NULL)
+ , m_xShapeFactory(NULL)
+ , m_pShapeFactory(NULL)
+ , m_aCID()
+ , m_nDimension(nDimensionCount)
+ , m_pPosHelper(NULL)
+{
+}
+
+ void SAL_CALL PlotterBase
+::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)
+{
+ DBG_ASSERT(xLogicTarget.is()&&xFinalTarget.is()&&xShapeFactory.is(),"no proper initialization parameters");
+ //is only allowed to be called once
+ m_xLogicTarget = xLogicTarget;
+ m_xFinalTarget = xFinalTarget;
+ m_xShapeFactory = xShapeFactory;
+ m_pShapeFactory = new ShapeFactory(xShapeFactory);
+ m_aCID = rCID;
+}
+
+PlotterBase::~PlotterBase()
+{
+ delete m_pShapeFactory;
+}
+
+void SAL_CALL PlotterBase::setScales( const uno::Sequence< ExplicitScaleData >& rScales
+ , sal_Bool bSwapXAndYAxis )
+ throw (uno::RuntimeException)
+{
+ DBG_ASSERT(m_nDimension<=rScales.getLength(),"Dimension of Plotter does not fit two dimension of given scale sequence");
+ m_pPosHelper->setScales( rScales, bSwapXAndYAxis );
+}
+
+
+void PlotterBase::setTransformationSceneToScreen( const drawing::HomogenMatrix& rMatrix)
+{
+ DBG_ASSERT(m_nDimension==2,"Set this transformation only in case of 2D");
+ if(m_nDimension!=2)
+ return;
+ m_pPosHelper->setTransformationSceneToScreen( rMatrix );
+}
+
+uno::Reference< drawing::XShapes > PlotterBase::createGroupShape(
+ const uno::Reference< drawing::XShapes >& xTarget
+ , ::rtl::OUString rName )
+{
+ if(!m_xShapeFactory.is())
+ return NULL;
+
+ if(m_nDimension==2)
+ {
+ //create and add to target
+ return m_pShapeFactory->createGroup2D( xTarget, rName );
+ }
+ else
+ {
+ //create and added to target
+ return m_pShapeFactory->createGroup3D( xTarget, rName );
+ }
+}
+
+bool PlotterBase::isValidPosition( const drawing::Position3D& rPos )
+{
+ if( ::rtl::math::isNan(rPos.PositionX) )
+ return false;
+ if( ::rtl::math::isNan(rPos.PositionY) )
+ return false;
+ if( ::rtl::math::isNan(rPos.PositionZ) )
+ return false;
+ if( ::rtl::math::isInf(rPos.PositionX) )
+ return false;
+ if( ::rtl::math::isInf(rPos.PositionY) )
+ return false;
+ if( ::rtl::math::isInf(rPos.PositionZ) )
+ return false;
+ return true;
+}
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
diff --git a/chart2/source/view/main/PlottingPositionHelper.cxx b/chart2/source/view/main/PlottingPositionHelper.cxx
new file mode 100644
index 000000000000..deb390b70a79
--- /dev/null
+++ b/chart2/source/view/main/PlottingPositionHelper.cxx
@@ -0,0 +1,667 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_chart2.hxx"
+#include "PlottingPositionHelper.hxx"
+#include "CommonConverters.hxx"
+#include "ViewDefines.hxx"
+#include "Linear3DTransformation.hxx"
+#include "VPolarTransformation.hxx"
+
+#include "ShapeFactory.hxx"
+#include "PropertyMapper.hxx"
+#include <com/sun/star/drawing/DoubleSequence.hpp>
+#include <com/sun/star/drawing/Position3D.hpp>
+#include <com/sun/star/chart2/AxisType.hpp>
+
+#include <rtl/math.hxx>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+PlottingPositionHelper::PlottingPositionHelper()
+ : m_aScales()
+ , m_aMatrixScreenToScene()
+ , m_xTransformationLogicToScene(NULL)
+ , m_bSwapXAndY( false )
+ , m_nXResolution( 1000 )
+ , m_nYResolution( 1000 )
+ , m_nZResolution( 1000 )
+ , m_bMaySkipPointsInRegressionCalculation( true )
+{
+}
+PlottingPositionHelper::PlottingPositionHelper( const PlottingPositionHelper& rSource )
+ : m_aScales( rSource.m_aScales )
+ , m_aMatrixScreenToScene( rSource.m_aMatrixScreenToScene )
+ , m_xTransformationLogicToScene( NULL ) //should be recalculated
+ , m_bSwapXAndY( rSource.m_bSwapXAndY )
+ , m_nXResolution( rSource.m_nXResolution )
+ , m_nYResolution( rSource.m_nYResolution )
+ , m_nZResolution( rSource.m_nZResolution )
+ , m_bMaySkipPointsInRegressionCalculation( rSource.m_bMaySkipPointsInRegressionCalculation )
+{
+}
+
+PlottingPositionHelper::~PlottingPositionHelper()
+{
+
+}
+
+PlottingPositionHelper* PlottingPositionHelper::clone() const
+{
+ PlottingPositionHelper* pRet = new PlottingPositionHelper(*this);
+ return pRet;
+}
+
+PlottingPositionHelper* PlottingPositionHelper::createSecondaryPosHelper( const ExplicitScaleData& rSecondaryScale )
+{
+ PlottingPositionHelper* pRet = this->clone();
+ pRet->m_aScales[1]=rSecondaryScale;
+ return pRet;
+}
+
+void PlottingPositionHelper::setTransformationSceneToScreen( const drawing::HomogenMatrix& rMatrix)
+{
+ m_aMatrixScreenToScene = HomogenMatrixToB3DHomMatrix(rMatrix);
+ m_xTransformationLogicToScene = NULL;
+}
+
+void PlottingPositionHelper::setScales( const uno::Sequence< ExplicitScaleData >& rScales, sal_Bool bSwapXAndYAxis )
+{
+ m_aScales = rScales;
+ m_bSwapXAndY = bSwapXAndYAxis;
+ m_xTransformationLogicToScene = NULL;
+}
+const uno::Sequence< ExplicitScaleData >& PlottingPositionHelper::getScales() const
+{
+ return m_aScales;
+}
+
+uno::Reference< XTransformation > PlottingPositionHelper::getTransformationScaledLogicToScene() const
+{
+ //this is a standard transformation for a cartesian coordinate system
+
+ //transformation from 2) to 4) //@todo 2) and 4) need a ink to a document
+
+ //we need to apply this transformation to each geometric object because of a bug/problem
+ //of the old drawing layer (the UNO_NAME_3D_EXTRUDE_DEPTH is an integer value instead of an double )
+ if(!m_xTransformationLogicToScene.is())
+ {
+ ::basegfx::B3DHomMatrix aMatrix;
+ double MinX = getLogicMinX();
+ double MinY = getLogicMinY();
+ double MinZ = getLogicMinZ();
+ double MaxX = getLogicMaxX();
+ double MaxY = getLogicMaxY();
+ double MaxZ = getLogicMaxZ();
+
+ AxisOrientation nXAxisOrientation = m_aScales[0].Orientation;
+ AxisOrientation nYAxisOrientation = m_aScales[1].Orientation;
+ AxisOrientation nZAxisOrientation = m_aScales[2].Orientation;
+
+ //apply scaling
+ doLogicScaling( &MinX, &MinY, &MinZ );
+ doLogicScaling( &MaxX, &MaxY, &MaxZ);
+
+ if(m_bSwapXAndY)
+ {
+ std::swap(MinX,MinY);
+ std::swap(MaxX,MaxY);
+ std::swap(nXAxisOrientation,nYAxisOrientation);
+ }
+
+ double fWidthX = MaxX - MinX;
+ double fWidthY = MaxY - MinY;
+ double fWidthZ = MaxZ - MinZ;
+
+ double fScaleDirectionX = AxisOrientation_MATHEMATICAL==nXAxisOrientation ? 1.0 : -1.0;
+ double fScaleDirectionY = AxisOrientation_MATHEMATICAL==nYAxisOrientation ? 1.0 : -1.0;
+ double fScaleDirectionZ = AxisOrientation_MATHEMATICAL==nZAxisOrientation ? -1.0 : 1.0;
+
+ double fScaleX = fScaleDirectionX*FIXED_SIZE_FOR_3D_CHART_VOLUME/fWidthX;
+ double fScaleY = fScaleDirectionY*FIXED_SIZE_FOR_3D_CHART_VOLUME/fWidthY;
+ double fScaleZ = fScaleDirectionZ*FIXED_SIZE_FOR_3D_CHART_VOLUME/fWidthZ;
+
+ aMatrix.scale(fScaleX, fScaleY, fScaleZ);
+
+ if( AxisOrientation_MATHEMATICAL==nXAxisOrientation )
+ aMatrix.translate(-MinX*fScaleX, 0.0, 0.0);
+ else
+ aMatrix.translate(-MaxX*fScaleX, 0.0, 0.0);
+ if( AxisOrientation_MATHEMATICAL==nYAxisOrientation )
+ aMatrix.translate(0.0, -MinY*fScaleY, 0.0);
+ else
+ aMatrix.translate(0.0, -MaxY*fScaleY, 0.0);
+ if( AxisOrientation_MATHEMATICAL==nZAxisOrientation )
+ aMatrix.translate(0.0, 0.0, -MaxZ*fScaleZ);//z direction in draw is reverse mathematical direction
+ else
+ aMatrix.translate(0.0, 0.0, -MinZ*fScaleZ);
+
+ aMatrix = m_aMatrixScreenToScene*aMatrix;
+
+ m_xTransformationLogicToScene = new Linear3DTransformation(B3DHomMatrixToHomogenMatrix( aMatrix ),m_bSwapXAndY);
+ }
+ return m_xTransformationLogicToScene;
+}
+
+drawing::Position3D PlottingPositionHelper::transformLogicToScene(
+ double fX, double fY, double fZ, bool bClip ) const
+{
+ if(bClip)
+ this->clipLogicValues( &fX,&fY,&fZ );
+ this->doLogicScaling( &fX,&fY,&fZ );
+
+ return this->transformScaledLogicToScene( fX, fY, fZ, false );
+}
+
+drawing::Position3D PlottingPositionHelper::transformScaledLogicToScene(
+ double fX, double fY, double fZ, bool bClip ) const
+{
+ if( bClip )
+ this->clipScaledLogicValues( &fX,&fY,&fZ );
+
+ drawing::Position3D aPos( fX, fY, fZ);
+
+ uno::Reference< XTransformation > xTransformation =
+ this->getTransformationScaledLogicToScene();
+ uno::Sequence< double > aSeq =
+ xTransformation->transform( Position3DToSequence(aPos) );
+ return SequenceToPosition3D(aSeq);
+}
+
+//static
+awt::Point PlottingPositionHelper::transformSceneToScreenPosition( const drawing::Position3D& rScenePosition3D
+ , const uno::Reference< drawing::XShapes >& xSceneTarget
+ , ShapeFactory* pShapeFactory
+ , sal_Int32 nDimensionCount )
+{
+ //@todo would like to have a cheaper method to do this transformation
+ awt::Point aScreenPoint( static_cast<sal_Int32>(rScenePosition3D.PositionX), static_cast<sal_Int32>(rScenePosition3D.PositionY) );
+
+ //transformation from scene to screen (only neccessary for 3D):
+ if(3==nDimensionCount)
+ {
+ //create 3D anchor shape
+ tPropertyNameMap aDummyPropertyNameMap;
+ uno::Reference< drawing::XShape > xShape3DAnchor = pShapeFactory->createCube( xSceneTarget
+ , rScenePosition3D,drawing::Direction3D(1,1,1)
+ , 0, 0, aDummyPropertyNameMap);
+ //get 2D position from xShape3DAnchor
+ aScreenPoint = xShape3DAnchor->getPosition();
+ xSceneTarget->remove(xShape3DAnchor);
+ }
+ return aScreenPoint;
+}
+
+void PlottingPositionHelper::transformScaledLogicToScene( drawing::PolyPolygonShape3D& rPolygon ) const
+{
+ drawing::Position3D aScenePosition;
+ for( sal_Int32 nS = rPolygon.SequenceX.getLength(); nS--;)
+ {
+ drawing::DoubleSequence& xValues = rPolygon.SequenceX[nS];
+ drawing::DoubleSequence& yValues = rPolygon.SequenceY[nS];
+ drawing::DoubleSequence& zValues = rPolygon.SequenceZ[nS];
+ for( sal_Int32 nP = xValues.getLength(); nP--; )
+ {
+ double& fX = xValues[nP];
+ double& fY = yValues[nP];
+ double& fZ = zValues[nP];
+ aScenePosition = this->transformScaledLogicToScene( fX,fY,fZ,true );
+ fX = aScenePosition.PositionX;
+ fY = aScenePosition.PositionY;
+ fZ = aScenePosition.PositionZ;
+ }
+ }
+}
+
+
+void PlottingPositionHelper::clipScaledLogicValues( double* pX, double* pY, double* pZ ) const
+{
+ //get logic clip values:
+ double MinX = getLogicMinX();
+ double MinY = getLogicMinY();
+ double MinZ = getLogicMinZ();
+ double MaxX = getLogicMaxX();
+ double MaxY = getLogicMaxY();
+ double MaxZ = getLogicMaxZ();
+
+ //apply scaling
+ doLogicScaling( &MinX, &MinY, &MinZ );
+ doLogicScaling( &MaxX, &MaxY, &MaxZ);
+
+ if(pX)
+ {
+ if( *pX < MinX )
+ *pX = MinX;
+ else if( *pX > MaxX )
+ *pX = MaxX;
+ }
+ if(pY)
+ {
+ if( *pY < MinY )
+ *pY = MinY;
+ else if( *pY > MaxY )
+ *pY = MaxY;
+ }
+ if(pZ)
+ {
+ if( *pZ < MinZ )
+ *pZ = MinZ;
+ else if( *pZ > MaxZ )
+ *pZ = MaxZ;
+ }
+}
+
+basegfx::B2DRectangle PlottingPositionHelper::getScaledLogicClipDoubleRect() const
+{
+ //get logic clip values:
+ double MinX = getLogicMinX();
+ double MinY = getLogicMinY();
+ double MinZ = getLogicMinZ();
+ double MaxX = getLogicMaxX();
+ double MaxY = getLogicMaxY();
+ double MaxZ = getLogicMaxZ();
+
+ //apply scaling
+ doLogicScaling( &MinX, &MinY, &MinZ );
+ doLogicScaling( &MaxX, &MaxY, &MaxZ);
+
+ basegfx::B2DRectangle aRet( MinX, MaxY, MaxX, MinY );
+ return aRet;
+}
+
+drawing::Direction3D PlottingPositionHelper::getScaledLogicWidth() const
+{
+ drawing::Direction3D aRet;
+
+ double MinX = getLogicMinX();
+ double MinY = getLogicMinY();
+ double MinZ = getLogicMinZ();
+ double MaxX = getLogicMaxX();
+ double MaxY = getLogicMaxY();
+ double MaxZ = getLogicMaxZ();
+
+ doLogicScaling( &MinX, &MinY, &MinZ );
+ doLogicScaling( &MaxX, &MaxY, &MaxZ);
+
+ aRet.DirectionX = MaxX - MinX;
+ aRet.DirectionY = MaxY - MinY;
+ aRet.DirectionZ = MaxZ - MinZ;
+ return aRet;
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+PolarPlottingPositionHelper::PolarPlottingPositionHelper( NormalAxis eNormalAxis )
+ : m_fRadiusOffset(0.0)
+ , m_fAngleDegreeOffset(90.0)
+ , m_aUnitCartesianToScene()
+ , m_eNormalAxis(eNormalAxis)
+{
+ m_bMaySkipPointsInRegressionCalculation = false;
+}
+
+PolarPlottingPositionHelper::PolarPlottingPositionHelper( const PolarPlottingPositionHelper& rSource )
+ : PlottingPositionHelper(rSource)
+ , m_fRadiusOffset( rSource.m_fRadiusOffset )
+ , m_fAngleDegreeOffset( rSource.m_fAngleDegreeOffset )
+ , m_aUnitCartesianToScene( rSource.m_aUnitCartesianToScene )
+ , m_eNormalAxis( rSource.m_eNormalAxis )
+{
+}
+
+PolarPlottingPositionHelper::~PolarPlottingPositionHelper()
+{
+}
+
+PlottingPositionHelper* PolarPlottingPositionHelper::clone() const
+{
+ PolarPlottingPositionHelper* pRet = new PolarPlottingPositionHelper(*this);
+ return pRet;
+}
+
+void PolarPlottingPositionHelper::setTransformationSceneToScreen( const drawing::HomogenMatrix& rMatrix)
+{
+ PlottingPositionHelper::setTransformationSceneToScreen( rMatrix);
+ m_aUnitCartesianToScene =impl_calculateMatrixUnitCartesianToScene( m_aMatrixScreenToScene );
+}
+void PolarPlottingPositionHelper::setScales( const uno::Sequence< ExplicitScaleData >& rScales, sal_Bool bSwapXAndYAxis )
+{
+ PlottingPositionHelper::setScales( rScales, bSwapXAndYAxis );
+ m_aUnitCartesianToScene =impl_calculateMatrixUnitCartesianToScene( m_aMatrixScreenToScene );
+}
+
+::basegfx::B3DHomMatrix PolarPlottingPositionHelper::impl_calculateMatrixUnitCartesianToScene( const ::basegfx::B3DHomMatrix& rMatrixScreenToScene ) const
+{
+ ::basegfx::B3DHomMatrix aRet;
+
+ if( !m_aScales.getLength() )
+ return aRet;
+
+ double fTranslate =1.0;
+ double fScale =FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0;
+
+ double fTranslateLogicZ =fTranslate;
+ double fScaleLogicZ =fScale;
+ {
+ double fScaleDirectionZ = AxisOrientation_MATHEMATICAL==m_aScales[2].Orientation ? 1.0 : -1.0;
+ double MinZ = getLogicMinZ();
+ double MaxZ = getLogicMaxZ();
+ doLogicScaling( 0, 0, &MinZ );
+ doLogicScaling( 0, 0, &MaxZ );
+ double fWidthZ = MaxZ - MinZ;
+
+ if( AxisOrientation_MATHEMATICAL==m_aScales[2].Orientation )
+ fTranslateLogicZ=MinZ;
+ else
+ fTranslateLogicZ=MaxZ;
+ fScaleLogicZ = fScaleDirectionZ*FIXED_SIZE_FOR_3D_CHART_VOLUME/fWidthZ;
+ }
+
+ double fTranslateX = fTranslate;
+ double fTranslateY = fTranslate;
+ double fTranslateZ = fTranslate;
+
+ double fScaleX = fScale;
+ double fScaleY = fScale;
+ double fScaleZ = fScale;
+
+ switch(m_eNormalAxis)
+ {
+ case NormalAxis_X:
+ {
+ fTranslateX = fTranslateLogicZ;
+ fScaleX = fScaleLogicZ;
+ }
+ break;
+ case NormalAxis_Y:
+ {
+ fTranslateY = fTranslateLogicZ;
+ fScaleY = fScaleLogicZ;
+ }
+ break;
+ default: //NormalAxis_Z:
+ {
+ fTranslateZ = fTranslateLogicZ;
+ fScaleZ = fScaleLogicZ;
+ }
+ break;
+ }
+
+ aRet.translate(fTranslateX, fTranslateY, fTranslateZ);//x first
+ aRet.scale(fScaleX, fScaleY, fScaleZ);//x first
+
+ aRet = rMatrixScreenToScene * aRet;
+ return aRet;
+}
+
+::basegfx::B3DHomMatrix PolarPlottingPositionHelper::getUnitCartesianToScene() const
+{
+ return m_aUnitCartesianToScene;
+}
+
+uno::Reference< XTransformation > PolarPlottingPositionHelper::getTransformationScaledLogicToScene() const
+{
+ if( !m_xTransformationLogicToScene.is() )
+ m_xTransformationLogicToScene = new VPolarTransformation(*this);
+ return m_xTransformationLogicToScene;
+}
+
+double PolarPlottingPositionHelper::getWidthAngleDegree( double& fStartLogicValueOnAngleAxis, double& fEndLogicValueOnAngleAxis ) const
+{
+ const ExplicitScaleData& rAngleScale = m_bSwapXAndY ? m_aScales[1] : m_aScales[0];
+ if( AxisOrientation_MATHEMATICAL != rAngleScale.Orientation )
+ {
+ double fHelp = fEndLogicValueOnAngleAxis;
+ fEndLogicValueOnAngleAxis = fStartLogicValueOnAngleAxis;
+ fStartLogicValueOnAngleAxis = fHelp;
+ }
+
+ double fStartAngleDegree = this->transformToAngleDegree( fStartLogicValueOnAngleAxis );
+ double fEndAngleDegree = this->transformToAngleDegree( fEndLogicValueOnAngleAxis );
+ double fWidthAngleDegree = fEndAngleDegree - fStartAngleDegree;
+
+ if( ::rtl::math::approxEqual( fStartAngleDegree, fEndAngleDegree )
+ && !::rtl::math::approxEqual( fStartLogicValueOnAngleAxis, fEndLogicValueOnAngleAxis ) )
+ fWidthAngleDegree = 360.0;
+
+ while(fWidthAngleDegree<0.0)
+ fWidthAngleDegree+=360.0;
+ while(fWidthAngleDegree>360.0)
+ fWidthAngleDegree-=360.0;
+
+ return fWidthAngleDegree;
+}
+
+double PolarPlottingPositionHelper::transformToAngleDegree( double fLogicValueOnAngleAxis, bool bDoScaling ) const
+{
+ double fRet=0.0;
+
+ double fAxisAngleScaleDirection = 1.0;
+ {
+ const ExplicitScaleData& rScale = m_bSwapXAndY ? m_aScales[1] : m_aScales[0];
+ if(AxisOrientation_MATHEMATICAL != rScale.Orientation)
+ fAxisAngleScaleDirection *= -1.0;
+ }
+
+ double MinAngleValue = 0.0;
+ double MaxAngleValue = 0.0;
+ {
+ double MinX = getLogicMinX();
+ double MinY = getLogicMinY();
+ double MaxX = getLogicMaxX();
+ double MaxY = getLogicMaxY();
+ double MinZ = getLogicMinZ();
+ double MaxZ = getLogicMaxZ();
+
+ doLogicScaling( &MinX, &MinY, &MinZ );
+ doLogicScaling( &MaxX, &MaxY, &MaxZ);
+
+ MinAngleValue = m_bSwapXAndY ? MinY : MinX;
+ MaxAngleValue = m_bSwapXAndY ? MaxY : MaxX;
+ }
+
+ double fScaledLogicAngleValue = 0.0;
+ if(bDoScaling)
+ {
+ double fX = m_bSwapXAndY ? getLogicMaxX() : fLogicValueOnAngleAxis;
+ double fY = m_bSwapXAndY ? fLogicValueOnAngleAxis : getLogicMaxY();
+ double fZ = getLogicMaxZ();
+ clipLogicValues( &fX, &fY, &fZ );
+ doLogicScaling( &fX, &fY, &fZ );
+ fScaledLogicAngleValue = m_bSwapXAndY ? fY : fX;
+ }
+ else
+ fScaledLogicAngleValue = fLogicValueOnAngleAxis;
+
+ fRet = m_fAngleDegreeOffset
+ + fAxisAngleScaleDirection*(fScaledLogicAngleValue-MinAngleValue)*360.0
+ /fabs(MaxAngleValue-MinAngleValue);
+ while(fRet>360.0)
+ fRet-=360.0;
+ while(fRet<0)
+ fRet+=360.0;
+ return fRet;
+}
+
+double PolarPlottingPositionHelper::transformToRadius( double fLogicValueOnRadiusAxis, bool bDoScaling ) const
+{
+ double fNormalRadius = 0.0;
+ {
+ double fScaledLogicRadiusValue = 0.0;
+ double fX = m_bSwapXAndY ? fLogicValueOnRadiusAxis: getLogicMaxX();
+ double fY = m_bSwapXAndY ? getLogicMaxY() : fLogicValueOnRadiusAxis;
+ if(bDoScaling)
+ doLogicScaling( &fX, &fY, 0 );
+
+ fScaledLogicRadiusValue = m_bSwapXAndY ? fX : fY;
+
+ bool bMinIsInnerRadius = true;
+ const ExplicitScaleData& rScale = m_bSwapXAndY ? m_aScales[0] : m_aScales[1];
+ if(AxisOrientation_MATHEMATICAL != rScale.Orientation)
+ bMinIsInnerRadius = false;
+
+ double fInnerScaledLogicRadius=0.0;
+ double fOuterScaledLogicRadius=0.0;
+ {
+ double MinX = getLogicMinX();
+ double MinY = getLogicMinY();
+ doLogicScaling( &MinX, &MinY, 0 );
+ double MaxX = getLogicMaxX();
+ double MaxY = getLogicMaxY();
+ doLogicScaling( &MaxX, &MaxY, 0 );
+
+ double fMin = m_bSwapXAndY ? MinX : MinY;
+ double fMax = m_bSwapXAndY ? MaxX : MaxY;
+
+ fInnerScaledLogicRadius = bMinIsInnerRadius ? fMin : fMax;
+ fOuterScaledLogicRadius = bMinIsInnerRadius ? fMax : fMin;
+ }
+
+ if( bMinIsInnerRadius )
+ fInnerScaledLogicRadius -= fabs(m_fRadiusOffset);
+ else
+ fInnerScaledLogicRadius += fabs(m_fRadiusOffset);
+ fNormalRadius = (fScaledLogicRadiusValue-fInnerScaledLogicRadius)/(fOuterScaledLogicRadius-fInnerScaledLogicRadius);
+ }
+ return fNormalRadius;
+}
+
+drawing::Position3D PolarPlottingPositionHelper::transformLogicToScene( double fX, double fY, double fZ, bool bClip ) const
+{
+ if(bClip)
+ this->clipLogicValues( &fX,&fY,&fZ );
+ double fLogicValueOnAngleAxis = m_bSwapXAndY ? fY : fX;
+ double fLogicValueOnRadiusAxis = m_bSwapXAndY ? fX : fY;
+ return this->transformAngleRadiusToScene( fLogicValueOnAngleAxis, fLogicValueOnRadiusAxis, fZ, true );
+}
+
+drawing::Position3D PolarPlottingPositionHelper::transformScaledLogicToScene( double fX, double fY, double fZ, bool bClip ) const
+{
+ if(bClip)
+ this->clipScaledLogicValues( &fX,&fY,&fZ );
+ double fLogicValueOnAngleAxis = m_bSwapXAndY ? fY : fX;
+ double fLogicValueOnRadiusAxis = m_bSwapXAndY ? fX : fY;
+ return this->transformAngleRadiusToScene( fLogicValueOnAngleAxis, fLogicValueOnRadiusAxis, fZ, false );
+}
+drawing::Position3D PolarPlottingPositionHelper::transformUnitCircleToScene( double fUnitAngleDegree, double fUnitRadius
+ , double fLogicZ, bool /* bDoScaling */ ) const
+{
+ double fAnglePi = fUnitAngleDegree*F_PI/180.0;
+
+ double fX=fUnitRadius*rtl::math::cos(fAnglePi);
+ double fY=fUnitRadius*rtl::math::sin(fAnglePi);
+ double fZ=fLogicZ;
+
+ switch(m_eNormalAxis)
+ {
+ case NormalAxis_X:
+ std::swap(fX,fZ);
+ break;
+ case NormalAxis_Y:
+ std::swap(fY,fZ);
+ fZ*=-1;
+ break;
+ default: //NormalAxis_Z
+ break;
+ }
+
+ //!! applying matrix to vector does ignore translation, so it is important to use a B3DPoint here instead of B3DVector
+ ::basegfx::B3DPoint aPoint(fX,fY,fZ);
+ ::basegfx::B3DPoint aRet = m_aUnitCartesianToScene * aPoint;
+ return B3DPointToPosition3D(aRet);
+}
+
+drawing::Position3D PolarPlottingPositionHelper::transformAngleRadiusToScene( double fLogicValueOnAngleAxis, double fLogicValueOnRadiusAxis, double fLogicZ, bool bDoScaling ) const
+{
+ double fUnitAngleDegree = this->transformToAngleDegree(fLogicValueOnAngleAxis,bDoScaling);
+ double fUnitRadius = this->transformToRadius(fLogicValueOnRadiusAxis,bDoScaling);
+
+ return transformUnitCircleToScene( fUnitAngleDegree, fUnitRadius, fLogicZ, bDoScaling );
+}
+
+#ifdef NOTYET
+double PolarPlottingPositionHelper::getInnerLogicRadius() const
+{
+ const ExplicitScaleData& rScale = m_bSwapXAndY ? m_aScales[0] : m_aScales[1];
+ if( AxisOrientation_MATHEMATICAL==rScale.Orientation )
+ return rScale.Minimum;
+ else
+ return rScale.Maximum;
+}
+#endif
+
+double PolarPlottingPositionHelper::getOuterLogicRadius() const
+{
+ const ExplicitScaleData& rScale = m_bSwapXAndY ? m_aScales[0] : m_aScales[1];
+ if( AxisOrientation_MATHEMATICAL==rScale.Orientation )
+ return rScale.Maximum;
+ else
+ return rScale.Minimum;
+}
+
+bool PlottingPositionHelper::isPercentY() const
+{
+ return m_aScales[1].AxisType==AxisType::PERCENT;
+}
+
+double PlottingPositionHelper::getBaseValueY() const
+{
+ return m_aScales[1].Origin;
+}
+
+/*
+// ____ XTransformation ____
+uno::Sequence< double > SAL_CALL PolarPlottingPositionHelper::transform(
+ const uno::Sequence< double >& rSourceValues )
+ throw (uno::RuntimeException, lang::IllegalArgumentException)
+{
+ uno::Sequence< double > aSourceValues(3);
+ return aSourceValues;
+}
+
+sal_Int32 SAL_CALL PolarPlottingPositionHelper::getSourceDimension() throw (uno::RuntimeException)
+{
+ return 3;
+}
+
+sal_Int32 SAL_CALL PolarPlottingPositionHelper::getTargetDimension() throw (uno::RuntimeException)
+{
+ return 3;
+}
+*/
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
diff --git a/chart2/source/view/main/PolarLabelPositionHelper.cxx b/chart2/source/view/main/PolarLabelPositionHelper.cxx
new file mode 100644
index 000000000000..8e5402b48d63
--- /dev/null
+++ b/chart2/source/view/main/PolarLabelPositionHelper.cxx
@@ -0,0 +1,188 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_chart2.hxx"
+
+#include "PolarLabelPositionHelper.hxx"
+#include "PlottingPositionHelper.hxx"
+#include "CommonConverters.hxx"
+#include <basegfx/vector/b2dvector.hxx>
+#include <basegfx/vector/b2ivector.hxx>
+
+#include <com/sun/star/chart/DataLabelPlacement.hpp>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+PolarLabelPositionHelper::PolarLabelPositionHelper(
+ PolarPlottingPositionHelper* pPosHelper
+ , sal_Int32 nDimensionCount
+ , const uno::Reference< drawing::XShapes >& xLogicTarget
+ , ShapeFactory* pShapeFactory )
+ : LabelPositionHelper( pPosHelper, nDimensionCount, xLogicTarget, pShapeFactory )
+ , m_pPosHelper(pPosHelper)
+{
+}
+
+PolarLabelPositionHelper::~PolarLabelPositionHelper()
+{
+}
+
+awt::Point PolarLabelPositionHelper::getLabelScreenPositionAndAlignmentForLogicValues(
+ LabelAlignment& rAlignment
+ , double fLogicValueOnAngleAxis
+ , double fLogicValueOnRadiusAxis
+ , double fLogicZ
+ , sal_Int32 nScreenValueOffsetInRadiusDirection ) const
+{
+ double fUnitCircleAngleDegree = m_pPosHelper->transformToAngleDegree( fLogicValueOnAngleAxis );
+ double fUnitCircleRadius = m_pPosHelper->transformToRadius( fLogicValueOnRadiusAxis );
+
+ return getLabelScreenPositionAndAlignmentForUnitCircleValues(
+ rAlignment, ::com::sun::star::chart::DataLabelPlacement::OUTSIDE
+ , fUnitCircleAngleDegree, 0.0
+ , fUnitCircleRadius, fUnitCircleRadius, fLogicZ, nScreenValueOffsetInRadiusDirection );
+}
+
+awt::Point PolarLabelPositionHelper::getLabelScreenPositionAndAlignmentForUnitCircleValues(
+ LabelAlignment& rAlignment, sal_Int32 nLabelPlacement
+ , double fUnitCircleStartAngleDegree, double fUnitCircleWidthAngleDegree
+ , double fUnitCircleInnerRadius, double fUnitCircleOuterRadius
+ , double fLogicZ
+ , sal_Int32 nScreenValueOffsetInRadiusDirection ) const
+{
+ bool bCenter = (nLabelPlacement != ::com::sun::star::chart::DataLabelPlacement::OUTSIDE)
+ && (nLabelPlacement != ::com::sun::star::chart::DataLabelPlacement::INSIDE);
+
+ double fAngleDegree = fUnitCircleStartAngleDegree + fUnitCircleWidthAngleDegree/2.0;
+ double fRadius = 0.0;
+ if( !bCenter ) //e.g. for pure pie chart(one ring only) or for angle axis of polyar coordinate system
+ fRadius = fUnitCircleOuterRadius;
+ else
+ fRadius = fUnitCircleInnerRadius + (fUnitCircleOuterRadius-fUnitCircleInnerRadius)/2.0 ;
+
+ awt::Point aRet( this->transformSceneToScreenPosition(
+ m_pPosHelper->transformUnitCircleToScene( fAngleDegree, fRadius, fLogicZ+0.5 ) ) );
+
+ if(3==m_nDimensionCount && nLabelPlacement == ::com::sun::star::chart::DataLabelPlacement::OUTSIDE)
+ {
+ //check wether the upper or the downer edge is more distant from the center
+ //take the farest point to put the label to
+
+ awt::Point aP0( this->transformSceneToScreenPosition(
+ m_pPosHelper->transformUnitCircleToScene( 0, 0, fLogicZ ) ) );
+ awt::Point aP1(aRet);
+ awt::Point aP2( this->transformSceneToScreenPosition(
+ m_pPosHelper->transformUnitCircleToScene( fAngleDegree, fRadius, fLogicZ-0.5 ) ) );
+
+ ::basegfx::B2DVector aV0( aP0.X, aP0.Y );
+ ::basegfx::B2DVector aV1( aP1.X, aP1.Y );
+ ::basegfx::B2DVector aV2( aP2.X, aP2.Y );
+
+ double fL1 = ::basegfx::B2DVector(aV1-aV0).getLength();
+ double fL2 = ::basegfx::B2DVector(aV2-aV0).getLength();
+
+ if(fL2>fL1)
+ aRet = aP2;
+
+ //calculate new angle for alignment
+ double fDX = aRet.X-aP0.X;
+ double fDY = aRet.Y-aP0.Y;
+ fDY*=-1.0;//drawing layer has inverse y values
+ if( fDX != 0.0 )
+ {
+ fAngleDegree = atan(fDY/fDX)*180.0/F_PI;
+ if(fDX<0.0)
+ fAngleDegree+=180.0;
+ }
+ else
+ {
+ if(fDY>0.0)
+ fAngleDegree = 90.0;
+ else
+ fAngleDegree = 270.0;
+ }
+ }
+ //------------------------------
+ //set LabelAlignment
+ if( !bCenter )
+ {
+ while(fAngleDegree>360.0)
+ fAngleDegree-=360.0;
+ while(fAngleDegree<0.0)
+ fAngleDegree+=360.0;
+
+ bool bOutside = nLabelPlacement == ::com::sun::star::chart::DataLabelPlacement::OUTSIDE;
+
+ if(fAngleDegree==0.0)
+ rAlignment = LABEL_ALIGN_CENTER;
+ else if(fAngleDegree<=22.5)
+ rAlignment = bOutside ? LABEL_ALIGN_RIGHT : LABEL_ALIGN_LEFT;
+ else if(fAngleDegree<67.5)
+ rAlignment = bOutside ? LABEL_ALIGN_RIGHT_TOP : LABEL_ALIGN_LEFT_BOTTOM;
+ else if(fAngleDegree<112.5)
+ rAlignment = bOutside ? LABEL_ALIGN_TOP : LABEL_ALIGN_BOTTOM;
+ else if(fAngleDegree<=157.5)
+ rAlignment = bOutside ? LABEL_ALIGN_LEFT_TOP : LABEL_ALIGN_RIGHT_BOTTOM;
+ else if(fAngleDegree<=202.5)
+ rAlignment = bOutside ? LABEL_ALIGN_LEFT : LABEL_ALIGN_RIGHT;
+ else if(fAngleDegree<247.5)
+ rAlignment = bOutside ? LABEL_ALIGN_LEFT_BOTTOM : LABEL_ALIGN_RIGHT_TOP;
+ else if(fAngleDegree<292.5)
+ rAlignment = bOutside ? LABEL_ALIGN_BOTTOM : LABEL_ALIGN_TOP;
+ else if(fAngleDegree<337.5)
+ rAlignment = bOutside ? LABEL_ALIGN_RIGHT_BOTTOM : LABEL_ALIGN_LEFT_TOP;
+ else
+ rAlignment = bOutside ? LABEL_ALIGN_RIGHT : LABEL_ALIGN_LEFT;
+ }
+ else
+ {
+ rAlignment = LABEL_ALIGN_CENTER;
+ }
+
+ //add a scaling independent Offset if requested
+ if( nScreenValueOffsetInRadiusDirection != 0)
+ {
+ awt::Point aOrigin( this->transformSceneToScreenPosition(
+ m_pPosHelper->transformUnitCircleToScene( 0.0, 0.0, fLogicZ+0.5 ) ) );
+ basegfx::B2IVector aDirection( aRet.X- aOrigin.X, aRet.Y- aOrigin.Y );
+ aDirection.setLength(nScreenValueOffsetInRadiusDirection);
+ aRet.X += aDirection.getX();
+ aRet.Y += aDirection.getY();
+ }
+
+ return aRet;
+}
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
diff --git a/chart2/source/view/main/PropertyMapper.cxx b/chart2/source/view/main/PropertyMapper.cxx
new file mode 100644
index 000000000000..1979582763fa
--- /dev/null
+++ b/chart2/source/view/main/PropertyMapper.cxx
@@ -0,0 +1,539 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_chart2.hxx"
+#include "PropertyMapper.hxx"
+#include "ContainerHelper.hxx"
+#include "macros.hxx"
+
+#include <com/sun/star/beans/XMultiPropertySet.hpp>
+#include <com/sun/star/drawing/LineStyle.hpp>
+#include <com/sun/star/drawing/TextVerticalAdjust.hpp>
+#include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
+#include <com/sun/star/drawing/LineJoint.hpp>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+using namespace ::com::sun::star;
+
+namespace
+{
+
+void lcl_overwriteOrAppendValues(
+ tPropertyNameValueMap &rMap, const tPropertyNameValueMap& rOverwriteMap )
+{
+ tPropertyNameValueMap::const_iterator aIt( rOverwriteMap.begin() );
+ tPropertyNameValueMap::const_iterator aEnd( rOverwriteMap.end() );
+
+ for( ; aIt != aEnd; ++aIt )
+ rMap[ aIt->first ] = aIt->second;
+}
+
+} // anonymous namespace
+
+//static
+void PropertyMapper::setMappedProperties(
+ const uno::Reference< beans::XPropertySet >& xTarget
+ , const uno::Reference< beans::XPropertySet >& xSource
+ , const tPropertyNameMap& rMap
+ , tPropertyNameValueMap* pOverwriteMap )
+{
+ if( !xTarget.is() || !xSource.is() )
+ return;
+
+ tNameSequence aNames;
+ tAnySequence aValues;
+ getMultiPropertyLists(aNames, aValues, xSource, rMap );
+ if(pOverwriteMap && (aNames.getLength() == aValues.getLength()))
+ {
+ tPropertyNameValueMap aNewMap;
+ for( sal_Int32 nI=0; nI<aNames.getLength(); ++nI )
+ aNewMap[ aNames[nI] ] = aValues[nI];
+ lcl_overwriteOrAppendValues( aNewMap, *pOverwriteMap );
+ aNames = ContainerHelper::MapKeysToSequence( aNewMap );
+ aValues = ContainerHelper::MapValuesToSequence( aNewMap );
+ }
+
+ PropertyMapper::setMultiProperties( aNames, aValues, xTarget );
+}
+
+void PropertyMapper::getValueMap(
+ tPropertyNameValueMap& rValueMap
+ , const tPropertyNameMap& rNameMap
+ , const uno::Reference< beans::XPropertySet >& xSourceProp
+ )
+{
+ tPropertyNameMap::const_iterator aIt( rNameMap.begin() );
+ tPropertyNameMap::const_iterator aEnd( rNameMap.end() );
+
+ for( ; aIt != aEnd; ++aIt )
+ {
+ rtl::OUString aTarget = aIt->first;
+ rtl::OUString aSource = aIt->second;
+ try
+ {
+ uno::Any aAny( xSourceProp->getPropertyValue(aSource) );
+ if( aAny.hasValue() )
+ rValueMap.insert( tPropertyNameValueMap::value_type( aTarget, aAny ) );
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+ }
+}
+
+void PropertyMapper::getMultiPropertyLists(
+ tNameSequence& rNames
+ , tAnySequence& rValues
+ , const uno::Reference< beans::XPropertySet >& xSourceProp
+ , const tPropertyNameMap& rNameMap
+ )
+{
+ tPropertyNameValueMap aValueMap;
+ getValueMap( aValueMap, rNameMap, xSourceProp );
+ getMultiPropertyListsFromValueMap( rNames, rValues, aValueMap );
+}
+
+void PropertyMapper::getMultiPropertyListsFromValueMap(
+ tNameSequence& rNames
+ , tAnySequence& rValues
+ , const tPropertyNameValueMap& rValueMap
+ )
+{
+ sal_Int32 nPropertyCount = rValueMap.size();
+ rNames.realloc(nPropertyCount);
+ rValues.realloc(nPropertyCount);
+
+ //fill sequences
+ tPropertyNameValueMap::const_iterator aValueIt( rValueMap.begin() );
+ tPropertyNameValueMap::const_iterator aValueEnd( rValueMap.end() );
+ sal_Int32 nN=0;
+ for( ; aValueIt != aValueEnd; ++aValueIt )
+ {
+ const uno::Any& rAny = aValueIt->second;
+ if( rAny.hasValue() )
+ {
+ //do not set empty anys because of performance (otherwise SdrAttrObj::ItemChange will take much longer)
+ rNames[nN] = aValueIt->first;
+ rValues[nN] = rAny;
+ ++nN;
+ }
+ }
+ //reduce to real property count
+ rNames.realloc(nN);
+ rValues.realloc(nN);
+}
+
+uno::Any* PropertyMapper::getValuePointer( tAnySequence& rPropValues
+ , const tNameSequence& rPropNames
+ , const rtl::OUString& rPropName )
+{
+ sal_Int32 nCount = rPropNames.getLength();
+ for( sal_Int32 nN = 0; nN < nCount; nN++ )
+ {
+ if(rPropNames[nN].equals(rPropName))
+ return &rPropValues[nN];
+ }
+ return NULL;
+}
+
+uno::Any* PropertyMapper::getValuePointerForLimitedSpace( tAnySequence& rPropValues
+ , const tNameSequence& rPropNames
+ , bool bLimitedHeight)
+{
+ return PropertyMapper::getValuePointer( rPropValues, rPropNames
+ , bLimitedHeight ? C2U("TextMaximumFrameHeight") : C2U("TextMaximumFrameWidth") );
+}
+
+/*
+//set some properties from service style::CharacterProperties:
+//-------- tabpage: Zeichen -----------
+//Schriftart z.B. Albany UNO_NAME_EDIT_CHAR_FONTNAME == UNO_NAME_EDIT_CHAR_FONTSTYLENAME //UNO_NAME_CHAR_FONT
+//Schriftschnitt z.B. kursiv UNO_NAME_EDIT_CHAR_POSTURE UNO_NAME_CHAR_POSTURE awt::FontSlant NONE OBLIQUE ITALIC DONTKNOW REVERSE_OBLIQUE REVERSE_ITALIC
+//Schriftgrad (Punktgrösse z.B. 12) UNO_NAME_EDIT_CHAR_HEIGHT == UNO_NAME_CHAR_HEIGHT
+ //? UNO_NAME_EDIT_CHAR_WEIGHT == UNO_NAME_CHAR_WEIGHT
+//Sprache UNO_NAME_EDIT_CHAR_LOCALE lang::Locale
+
+//-------- tabpage: Schrifteffekt -----------
+//Unterstreichung UNO_NAME_CHAR_UNDERLINE sal_Int16 awt::FontUnderline_NONE _SINGLE _DOUBLE _DOTTED _DONTKNOW _DASH ...
+//Unterstreichung-farbe ??? 'CharUnderlineColor' + CharUnderlineHasColor
+//Durchstreichung z.B. doppelt "CharStrikeout" sal_Int16 awt::FontStrikeout_NONE _SINGLE _DOUBLE ...
+//wortweise-Durchstreichung ja/nein "CharWordMode" bool
+//Schriftfarbe UNO_NAME_EDIT_CHAR_COLOR sal_Int32 UNO_NAME_CHAR_COLOR
+//ReliefArt ohne/erhaben/tief "CharRelief" sal_Int16 text::FontRelief_NONE FontRelief_EMBOSSED FontRelief_ENGRAVED
+//Kontur "CharContoured" bool
+//Schatten UNO_NAME_CHAR_SHADOWED bool
+*/
+
+//static
+const tMakePropertyNameMap& PropertyMapper::getPropertyNameMapForCharacterProperties()
+{
+ //shape property -- chart model object property
+ static tMakePropertyNameMap m_aShapePropertyMapForCharacterProperties =
+ tMakePropertyNameMap
+// ( C2U( "CharBackColor" ), C2U("TextBackgroundColor") )
+// ( C2U( "CharCaseMap" ), C2U("CaseMapping") )
+ ( C2U( "CharColor" ), C2U("CharColor") )
+ ( C2U( "CharContoured" ), C2U("CharContoured") )
+/////// ( C2U( "CharCrossedOut" ), C2U("CharCrossedOut") ) //setting this explicitly somehow conflicts with CharStrikeout
+ ( C2U( "CharEmphasis" ), C2U("CharEmphasis") )//the service style::CharacterProperties describes a property called 'CharEmphasize' wich is nowhere implemented
+// ( C2U( "CharEscapement" ), C2U("CharEscapement") ) //#i98344# @future: add these to properties again, if the user interface offers the possibility to change them; then make sure that older wrong files are corrected on import
+// ( C2U( "CharEscapementHeight" ), C2U("CharEscapementHeight") ) //#i98344# @future: add these to properties again, if the user interface offers the possibility to change them; then make sure that older wrong files are corrected on import
+// ( C2U( "CharFlash" ), C2U("Flashing") )
+
+ ( C2U( "CharFontFamily" ), C2U("CharFontFamily") )
+ ( C2U( "CharFontFamilyAsian" ), C2U("CharFontFamilyAsian") )
+ ( C2U( "CharFontFamilyComplex" ), C2U("CharFontFamilyComplex") )
+ ( C2U( "CharFontCharSet" ), C2U("CharFontCharSet") )
+ ( C2U( "CharFontCharSetAsian" ), C2U("CharFontCharSetAsian") )
+ ( C2U( "CharFontCharSetComplex" ), C2U("CharFontCharSetComplex") )
+ ( C2U( "CharFontName" ), C2U("CharFontName") )
+ ( C2U( "CharFontNameAsian" ), C2U("CharFontNameAsian") )
+ ( C2U( "CharFontNameComplex" ), C2U("CharFontNameComplex") )
+ ( C2U( "CharFontPitch" ), C2U("CharFontPitch") )
+ ( C2U( "CharFontPitchAsian" ), C2U("CharFontPitchAsian") )
+ ( C2U( "CharFontPitchComplex" ), C2U("CharFontPitchComplex") )
+ ( C2U( "CharFontStyleName" ), C2U("CharFontStyleName") )
+ ( C2U( "CharFontStyleNameAsian" ), C2U("CharFontStyleNameAsian") )
+ ( C2U( "CharFontStyleNameComplex" ),C2U("CharFontStyleNameComplex") )
+
+ ( C2U( "CharHeight" ), C2U("CharHeight") )
+ ( C2U( "CharHeightAsian" ), C2U("CharHeightAsian") )
+ ( C2U( "CharHeightComplex" ), C2U("CharHeightComplex") )
+ ( C2U( "CharKerning" ), C2U("CharKerning") )
+ ( C2U( "CharLocale" ), C2U("CharLocale") )
+ ( C2U( "CharLocaleAsian" ), C2U("CharLocaleAsian") )
+ ( C2U( "CharLocaleComplex" ), C2U("CharLocaleComplex") )
+// ( C2U( "CharNoHyphenation" ), C2U("InhibitHyphenation") )
+ ( C2U( "CharPosture" ), C2U("CharPosture") )
+ ( C2U( "CharPostureAsian" ), C2U("CharPostureAsian") )
+ ( C2U( "CharPostureComplex" ), C2U("CharPostureComplex") )
+ ( C2U( "CharRelief" ), C2U("CharRelief") )
+// ( C2U( "CharRotation" ), C2U("Rotation") ) --> additional feature ...
+// ( C2U( "CharScaleWidth" ), C2U("CharScaleWidth") )
+ ( C2U( "CharShadowed" ), C2U("CharShadowed") )
+ ( C2U( "CharStrikeout" ), C2U("CharStrikeout") )
+ ( C2U( "CharUnderline" ), C2U("CharUnderline") )
+ ( C2U( "CharUnderlineColor" ), C2U("CharUnderlineColor") )
+ ( C2U( "CharUnderlineHasColor" ), C2U("CharUnderlineHasColor") )
+ ( C2U( "CharWeight" ), C2U("CharWeight") )
+ ( C2U( "CharWeightAsian" ), C2U("CharWeightAsian") )
+ ( C2U( "CharWeightComplex" ), C2U("CharWeightComplex") )
+ ( C2U( "CharWordMode" ), C2U("CharWordMode") )
+
+ ( C2U( "WritingMode" ), C2U("WritingMode") )
+
+// ( C2U( "RubyText" ), C2U("RubyText") )
+// ( C2U( "RubyAdjust" ), C2U("RubyAdjust") )
+// ( C2U( "RubyCharStyleName" ), C2U("RubyStyleName") )
+// ( C2U( "RubyIsAbove" ), C2U("RubyIsAbove") )
+ ( C2U( "ParaIsCharacterDistance" ), C2U("ParaIsCharacterDistance") )
+ ;
+ return m_aShapePropertyMapForCharacterProperties;
+}
+
+//static
+const tMakePropertyNameMap& PropertyMapper::getPropertyNameMapForParagraphProperties()
+{
+ //shape property -- chart model object property
+ static tMakePropertyNameMap m_aShapePropertyMapForParagraphProperties =
+ tMakePropertyNameMap
+ ( C2U( "ParaAdjust" ), C2U("ParaAdjust") )
+ ( C2U( "ParaBottomMargin" ), C2U("ParaBottomMargin") )
+ ( C2U( "ParaIsHyphenation" ), C2U("ParaIsHyphenation") )
+ ( C2U( "ParaLastLineAdjust" ), C2U("ParaLastLineAdjust") )
+ ( C2U( "ParaLeftMargin" ), C2U("ParaLeftMargin") )
+ ( C2U( "ParaRightMargin" ), C2U("ParaRightMargin") )
+ ( C2U( "ParaTopMargin" ), C2U("ParaTopMargin") )
+ ;
+ return m_aShapePropertyMapForParagraphProperties;
+}
+
+//static
+const tMakePropertyNameMap& PropertyMapper::getPropertyNameMapForFillProperties()
+{
+ //shape property -- chart model object property
+ static tMakePropertyNameMap m_aShapePropertyMapForFillProperties =
+ tMakePropertyNameMap
+ ( C2U( "FillBackground" ), C2U( "FillBackground" ) )
+ ( C2U( "FillBitmapName" ), C2U( "FillBitmapName" ) )
+ ( C2U( "FillColor" ), C2U( "FillColor" ) )
+ ( C2U( "FillGradientName" ), C2U( "FillGradientName" ) )
+ ( C2U( "FillGradientStepCount" ), C2U( "FillGradientStepCount" ) )
+ ( C2U( "FillHatchName" ), C2U( "FillHatchName" ) )
+ ( C2U( "FillStyle" ), C2U( "FillStyle" ) )
+ ( C2U( "FillTransparence" ), C2U( "FillTransparence" ) )
+ ( C2U( "FillTransparenceGradientName" ), C2U("FillTransparenceGradientName") )
+ //bitmap properties
+ ( C2U( "FillBitmapMode" ), C2U( "FillBitmapMode" ) )
+ ( C2U( "FillBitmapSizeX" ), C2U( "FillBitmapSizeX" ) )
+ ( C2U( "FillBitmapSizeY" ), C2U( "FillBitmapSizeY" ) )
+ ( C2U( "FillBitmapLogicalSize" ), C2U( "FillBitmapLogicalSize" ) )
+ ( C2U( "FillBitmapOffsetX" ), C2U( "FillBitmapOffsetX" ) )
+ ( C2U( "FillBitmapOffsetY" ), C2U( "FillBitmapOffsetY" ) )
+ ( C2U( "FillBitmapRectanglePoint" ),C2U( "FillBitmapRectanglePoint" ) )
+ ( C2U( "FillBitmapPositionOffsetX" ),C2U( "FillBitmapPositionOffsetX" ) )
+ ( C2U( "FillBitmapPositionOffsetY" ),C2U( "FillBitmapPositionOffsetY" ) )
+ ;
+ return m_aShapePropertyMapForFillProperties;
+}
+
+//static
+const tMakePropertyNameMap& PropertyMapper::getPropertyNameMapForLineProperties()
+{
+ //shape property -- chart model object property
+ static tMakePropertyNameMap m_aShapePropertyMapForLineProperties =
+ tMakePropertyNameMap
+ ( C2U( "LineColor" ), C2U( "LineColor" ) )
+ ( C2U( "LineDashName" ), C2U( "LineDashName" ) )
+ ( C2U( "LineJoint" ), C2U( "LineJoint" ) )
+ ( C2U( "LineStyle" ), C2U( "LineStyle" ) )
+ ( C2U( "LineTransparence" ), C2U( "LineTransparence" ) )
+ ( C2U( "LineWidth" ), C2U( "LineWidth" ) )
+ ;
+ return m_aShapePropertyMapForLineProperties;
+}
+
+//static
+const tMakePropertyNameMap& PropertyMapper::getPropertyNameMapForFillAndLineProperties()
+{
+ static tMakePropertyNameMap m_aShapePropertyMapForFillAndLineProperties =
+ tMakePropertyNameMap
+ ( PropertyMapper::getPropertyNameMapForFillProperties() )
+ ( PropertyMapper::getPropertyNameMapForLineProperties() )
+ ;
+
+ return m_aShapePropertyMapForFillAndLineProperties;
+}
+
+//static
+const tMakePropertyNameMap& PropertyMapper::getPropertyNameMapForTextShapeProperties()
+{
+ static tMakePropertyNameMap m_aShapePropertyMapForTextShapeProperties =
+ tMakePropertyNameMap
+ ( PropertyMapper::getPropertyNameMapForCharacterProperties() )
+ ( PropertyMapper::getPropertyNameMapForFillProperties() )
+ ( PropertyMapper::getPropertyNameMapForLineProperties() )
+// ( PropertyMapper::getPropertyNameMapForParagraphProperties() )
+ // some text properties
+// ( C2U( "TextHorizontalAdjust" ), C2U( "TextHorizontalAdjust" ) )
+// ( C2U( "TextVerticalAdjust" ), C2U( "TextVerticalAdjust" ) )
+// ( C2U( "TextAutoGrowHeight" ), C2U( "TextAutoGrowHeight" ) )
+// ( C2U( "TextAutoGrowWidth" ), C2U( "TextAutoGrowWidth" ) )
+// ( C2U( "TextLeftDistance" ), C2U( "TextLeftDistance" ) )
+// ( C2U( "TextRightDistance" ), C2U( "TextRightDistance" ) )
+// ( C2U( "TextUpperDistance" ), C2U( "TextUpperDistance" ) )
+// ( C2U( "TextLowerDistance" ), C2U( "TextLowerDistance" ) )
+ ;
+
+ return m_aShapePropertyMapForTextShapeProperties;
+}
+
+//static
+const tMakePropertyNameMap& PropertyMapper::getPropertyNameMapForLineSeriesProperties()
+{
+ //shape property -- chart model object property
+ static tMakePropertyNameMap m_aShapePropertyMapForLineSeriesProperties =
+ tMakePropertyNameMap
+ ( C2U( "LineColor" ), C2U("Color") )
+ ( C2U( "LineDashName" ), C2U("LineDashName") )
+// ( C2U( "LineJoint" ), C2U("LineJoint") )
+ ( C2U( "LineStyle" ), C2U("LineStyle") )
+ ( C2U( "LineTransparence" ), C2U("Transparency") )
+ ( C2U( "LineWidth" ), C2U("LineWidth") )
+
+ ;
+ return m_aShapePropertyMapForLineSeriesProperties;
+}
+
+//static
+const tMakePropertyNameMap& PropertyMapper::getPropertyNameMapForFilledSeriesProperties()
+{
+ //shape property -- chart model object property
+ static tMakePropertyNameMap m_aShapePropertyMapForFilledSeriesProperties =
+ tMakePropertyNameMap
+ ( C2U( "FillBackground"), C2U("FillBackground") )
+ ( C2U( "FillBitmapName" ), C2U("FillBitmapName") )
+ ( C2U( "FillColor" ), C2U("Color") )
+ ( C2U( "FillGradientName" ), C2U("GradientName") )
+ ( C2U( "FillGradientStepCount" ), C2U( "GradientStepCount" ) )
+ ( C2U( "FillHatchName" ), C2U("HatchName") )
+ ( C2U( "FillStyle" ), C2U("FillStyle") )
+ ( C2U( "FillTransparence" ), C2U("Transparency") )
+ ( C2U( "FillTransparenceGradientName" ), C2U("TransparencyGradientName") )
+ //bitmap properties
+ ( C2U( "FillBitmapMode" ), C2U( "FillBitmapMode" ) )
+ ( C2U( "FillBitmapSizeX" ), C2U( "FillBitmapSizeX" ) )
+ ( C2U( "FillBitmapSizeY" ), C2U( "FillBitmapSizeY" ) )
+ ( C2U( "FillBitmapLogicalSize" ), C2U( "FillBitmapLogicalSize" ) )
+ ( C2U( "FillBitmapOffsetX" ), C2U( "FillBitmapOffsetX" ) )
+ ( C2U( "FillBitmapOffsetY" ), C2U( "FillBitmapOffsetY" ) )
+ ( C2U( "FillBitmapRectanglePoint" ),C2U( "FillBitmapRectanglePoint" ) )
+ ( C2U( "FillBitmapPositionOffsetX" ),C2U( "FillBitmapPositionOffsetX" ) )
+ ( C2U( "FillBitmapPositionOffsetY" ),C2U( "FillBitmapPositionOffsetY" ) )
+ //line properties
+ ( C2U( "LineColor" ), C2U("BorderColor") )
+ ( C2U( "LineDashName" ), C2U("BorderDashName") )
+// ( C2U( "LineJoint" ), C2U("LineJoint") )
+ ( C2U( "LineStyle" ), C2U("BorderStyle") )
+ ( C2U( "LineTransparence" ), C2U("BorderTransparency") )
+ ( C2U( "LineWidth" ), C2U("BorderWidth") )
+ ;
+ return m_aShapePropertyMapForFilledSeriesProperties;
+}
+
+// static
+void PropertyMapper::setMultiProperties(
+ const tNameSequence& rNames
+ , const tAnySequence& rValues
+ , const ::com::sun::star::uno::Reference<
+ ::com::sun::star::beans::XPropertySet >& xTarget )
+{
+ bool bSuccess = false;
+ try
+ {
+ uno::Reference< beans::XMultiPropertySet > xShapeMultiProp( xTarget, uno::UNO_QUERY );
+ if( xShapeMultiProp.is() )
+ {
+ xShapeMultiProp->setPropertyValues( rNames, rValues );
+ bSuccess = true;
+ }
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e ); //if this occurs more often think of removing the XMultiPropertySet completly for better performance
+ }
+
+ if(!bSuccess)
+ try
+ {
+ sal_Int32 nCount = std::max( rNames.getLength(), rValues.getLength() );
+ rtl::OUString aPropName;
+ uno::Any aValue;
+ for( sal_Int32 nN = 0; nN < nCount; nN++ )
+ {
+ aPropName = rNames[nN];
+ aValue = rValues[nN];
+
+ try
+ {
+ xTarget->setPropertyValue( aPropName, aValue );
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+ }
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+}
+
+void PropertyMapper::getTextLabelMultiPropertyLists(
+ const uno::Reference< beans::XPropertySet >& xSourceProp
+ , tNameSequence& rPropNames, tAnySequence& rPropValues
+ , bool bName
+ , sal_Int32 nLimitedSpace
+ , bool bLimitedHeight )
+{
+ //fill character properties into the ValueMap
+ tPropertyNameValueMap aValueMap;
+ PropertyMapper::getValueMap( aValueMap
+ , PropertyMapper::getPropertyNameMapForCharacterProperties()
+ , xSourceProp );
+
+ //some more shape properties apart from character properties, position-matrix and label string
+ aValueMap.insert( tPropertyNameValueMap::value_type( C2U("LineStyle"), uno::makeAny(drawing::LineStyle_NONE) ) ); // drawing::LineStyle
+ aValueMap.insert( tPropertyNameValueMap::value_type( C2U("TextHorizontalAdjust"), uno::makeAny(drawing::TextHorizontalAdjust_CENTER) ) ); // drawing::TextHorizontalAdjust - needs to be overwritten
+ aValueMap.insert( tPropertyNameValueMap::value_type( C2U("TextVerticalAdjust"), uno::makeAny(drawing::TextVerticalAdjust_CENTER) ) ); //drawing::TextVerticalAdjust - needs to be overwritten
+ //aValueMap.insert( tPropertyNameValueMap::value_type( C2U("TextWritingMode"), uno::makeAny(eWritingMode) ) ); //text::WritingMode
+ aValueMap.insert( tPropertyNameValueMap::value_type( C2U("TextAutoGrowHeight"), uno::makeAny(sal_True) ) ); // sal_Bool
+ aValueMap.insert( tPropertyNameValueMap::value_type( C2U("TextAutoGrowWidth"), uno::makeAny(sal_True) ) ); // sal_Bool
+ if( bName )
+ aValueMap.insert( tPropertyNameValueMap::value_type( C2U("Name"), uno::makeAny( rtl::OUString() ) ) ); //CID rtl::OUString - needs to be overwritten for each point
+
+ if( nLimitedSpace > 0 )
+ {
+ if(bLimitedHeight)
+ aValueMap.insert( tPropertyNameValueMap::value_type( C2U("TextMaximumFrameHeight"), uno::makeAny(nLimitedSpace) ) ); //sal_Int32
+ else
+ aValueMap.insert( tPropertyNameValueMap::value_type( C2U("TextMaximumFrameWidth"), uno::makeAny(nLimitedSpace) ) ); //sal_Int32
+ aValueMap.insert( tPropertyNameValueMap::value_type( C2U("ParaIsHyphenation"), uno::makeAny(sal_True) ) );
+ }
+
+ /*
+ //@todo ?: add paragraph properties:
+ //(uno::makeAny(eParaAdjust)) //ParaAdjust - style::ParagraphAdjust
+ //(uno::makeAny( (sal_Bool)rAxisLabelProperties.bLineBreakAllowed )) //ParaIsHyphenation - sal_Bool
+ style::ParagraphAdjust eParaAdjust( style::ParagraphAdjust_LEFT );
+ if( eHorizontalAdjust == drawing::TextHorizontalAdjust_RIGHT )
+ eParaAdjust = style::ParagraphAdjust_RIGHT;
+ */
+
+ PropertyMapper::getMultiPropertyListsFromValueMap( rPropNames, rPropValues, aValueMap );
+}
+
+void PropertyMapper::getPreparedTextShapePropertyLists(
+ const uno::Reference< beans::XPropertySet >& xSourceProp
+ , tNameSequence& rPropNames, tAnySequence& rPropValues )
+{
+ //fill character, line and fill properties into the ValueMap
+ tPropertyNameValueMap aValueMap;
+ PropertyMapper::getValueMap( aValueMap
+ , PropertyMapper::getPropertyNameMapForTextShapeProperties()
+ , xSourceProp );
+
+ // auto-grow makes sure the shape has the correct size after setting text
+ aValueMap.insert( tPropertyNameValueMap::value_type( C2U("TextHorizontalAdjust"), uno::makeAny( drawing::TextHorizontalAdjust_CENTER )));
+ aValueMap.insert( tPropertyNameValueMap::value_type( C2U("TextVerticalAdjust"), uno::makeAny( drawing::TextVerticalAdjust_CENTER )));
+ aValueMap.insert( tPropertyNameValueMap::value_type( C2U("TextAutoGrowHeight"), uno::makeAny( true )));
+ aValueMap.insert( tPropertyNameValueMap::value_type( C2U("TextAutoGrowWidth"), uno::makeAny( true )));
+
+ // set some distance to the border, in case it is shown
+ const sal_Int32 nWidthDist = 250;
+ const sal_Int32 nHeightDist = 125;
+ aValueMap.insert( tPropertyNameValueMap::value_type( C2U("TextLeftDistance"), uno::makeAny( nWidthDist )));
+ aValueMap.insert( tPropertyNameValueMap::value_type( C2U("TextRightDistance"), uno::makeAny( nWidthDist )));
+ aValueMap.insert( tPropertyNameValueMap::value_type( C2U("TextUpperDistance"), uno::makeAny( nHeightDist )));
+ aValueMap.insert( tPropertyNameValueMap::value_type( C2U("TextLowerDistance"), uno::makeAny( nHeightDist )));
+
+ // use a line-joint showing the border of thick lines like two rectangles
+ // filled in between.
+ aValueMap[C2U("LineJoint")] <<= drawing::LineJoint_ROUND;
+
+ PropertyMapper::getMultiPropertyListsFromValueMap( rPropNames, rPropValues, aValueMap );
+}
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
diff --git a/chart2/source/view/main/ShapeFactory.cxx b/chart2/source/view/main/ShapeFactory.cxx
new file mode 100644
index 000000000000..721cabd15d83
--- /dev/null
+++ b/chart2/source/view/main/ShapeFactory.cxx
@@ -0,0 +1,2111 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_chart2.hxx"
+#include "ShapeFactory.hxx"
+#include "ViewDefines.hxx"
+#include "Stripe.hxx"
+#include "CommonConverters.hxx"
+#include "macros.hxx"
+#include "PropertyMapper.hxx"
+#include <comphelper/InlineContainer.hxx>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/drawing/CircleKind.hpp>
+#include <com/sun/star/drawing/DoubleSequence.hpp>
+#include <com/sun/star/drawing/FlagSequence.hpp>
+#include <com/sun/star/drawing/FillStyle.hpp>
+#include <com/sun/star/drawing/LineStyle.hpp>
+#include <com/sun/star/drawing/NormalsKind.hpp>
+#include <com/sun/star/drawing/PointSequence.hpp>
+#include <com/sun/star/drawing/PolygonKind.hpp>
+#include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
+#include <com/sun/star/drawing/ProjectionMode.hpp>
+#include <com/sun/star/drawing/ShadeMode.hpp>
+#include <com/sun/star/drawing/TextFitToSizeType.hpp>
+#include <com/sun/star/drawing/TextureProjectionMode.hpp>
+#include <com/sun/star/text/XText.hpp>
+#include <com/sun/star/uno/Any.hxx>
+
+
+#include <editeng/unoprnms.hxx>
+#include <tools/color.hxx>
+#include <tools/debug.hxx>
+#include <rtl/math.hxx>
+#include <svx/svdocirc.hxx>
+#include <svx/svdopath.hxx>
+
+#ifndef _BGFX_VECTOR_B2DPOINT_HXX
+#include <basegfx/point/b2dpoint.hxx>
+#endif
+#include <basegfx/matrix/b3dhommatrix.hxx>
+
+#include <algorithm>
+
+using namespace ::com::sun::star;
+using ::com::sun::star::uno::Reference;
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// set a name/CID at a shape (is used for selection handling)
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+//static
+void ShapeFactory::setShapeName( const uno::Reference< drawing::XShape >& xShape
+ , const rtl::OUString& rName )
+{
+ if(!xShape.is())
+ return;
+ uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
+ DBG_ASSERT(xProp.is(), "shape offers no XPropertySet");
+ if( xProp.is())
+ {
+ try
+ {
+ xProp->setPropertyValue( C2U( UNO_NAME_MISC_OBJ_NAME )
+ , uno::makeAny( rName ) );
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+
+//static
+rtl::OUString ShapeFactory::getShapeName( const uno::Reference< drawing::XShape >& xShape )
+{
+ rtl::OUString aRet;
+
+ uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
+ DBG_ASSERT(xProp.is(), "shape offers no XPropertySet");
+ if( xProp.is())
+ {
+ try
+ {
+ xProp->getPropertyValue( C2U( UNO_NAME_MISC_OBJ_NAME ) ) >>= aRet;
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+ }
+
+ return aRet;
+}
+
+//-----------------------------------------------------------------------------
+
+uno::Reference< drawing::XShapes > ShapeFactory::getChartRootShape(
+ const uno::Reference< drawing::XDrawPage>& xDrawPage )
+{
+ uno::Reference< drawing::XShapes > xRet;
+ uno::Reference< drawing::XShapes > xShapes( xDrawPage, uno::UNO_QUERY );
+ if( xShapes.is() )
+ {
+ sal_Int32 nCount = xShapes->getCount();
+ uno::Reference< drawing::XShape > xShape;
+ for( sal_Int32 nN = nCount; nN--; )
+ {
+ if( xShapes->getByIndex( nN ) >>= xShape )
+ {
+ if( ShapeFactory::getShapeName( xShape ).equals(C2U("com.sun.star.chart2.shapes")) )
+ {
+ xRet = uno::Reference< drawing::XShapes >( xShape, uno::UNO_QUERY );
+ break;
+ }
+ }
+ }
+ }
+ return xRet;
+}
+
+//-----------------------------------------------------------------------------
+
+uno::Reference< drawing::XShapes > ShapeFactory::getOrCreateChartRootShape(
+ const uno::Reference< drawing::XDrawPage>& xDrawPage )
+{
+ uno::Reference< drawing::XShapes > xRet( ShapeFactory::getChartRootShape( xDrawPage ) );
+ if( !xRet.is() )
+ {
+ //create the root shape
+ xRet = this->createGroup2D(
+ uno::Reference<drawing::XShapes>( xDrawPage, uno::UNO_QUERY )
+ , C2U("com.sun.star.chart2.shapes") );
+ }
+ return xRet;
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// diverse PolyPolygon create methods
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+uno::Any createPolyPolygon_Cube(
+ const drawing::Direction3D& rSize, double fRoundedEdge, bool bRounded = true )
+{
+ DBG_ASSERT(fRoundedEdge>=0, "fRoundedEdge needs to be >= 0");
+
+ // always use extra points, so set percent diagonal to 0.4 which is 0% in the UI (old Chart comment)
+ if( fRoundedEdge == 0.0 && bRounded)
+ fRoundedEdge = 0.4 / 200.0;
+ else if(!bRounded)
+ fRoundedEdge = 0.0;
+
+ //fWidthH stands for Half Width
+ const double fWidthH = rSize.DirectionX >=0.0? rSize.DirectionX/2.0 : -rSize.DirectionX/2.0;
+ const double fHeight = rSize.DirectionY;
+// const double fDepth = rSize.DirectionZ >=0.0? rSize.DirectionZ : -rSize.DirectionZ ;
+
+ const double fHeightSign = fHeight >= 0.0 ? 1.0 : -1.0;
+
+ const double fOffset = (fWidthH * fRoundedEdge) * 1.05; // increase by 5% for safety
+ const bool bRoundEdges = fRoundedEdge && fOffset < fWidthH && 2.0 * fOffset < fHeightSign*fHeight;
+ const sal_Int32 nPointCount = bRoundEdges ? 13 : 5;
+
+ //--------------------------------------
+ drawing::PolyPolygonShape3D aPP;
+
+ aPP.SequenceX.realloc(1);
+ aPP.SequenceY.realloc(1);
+ aPP.SequenceZ.realloc(1);
+
+ drawing::DoubleSequence* pOuterSequenceX = aPP.SequenceX.getArray();
+ drawing::DoubleSequence* pOuterSequenceY = aPP.SequenceY.getArray();
+ drawing::DoubleSequence* pOuterSequenceZ = aPP.SequenceZ.getArray();
+
+ pOuterSequenceX->realloc(nPointCount);
+ pOuterSequenceY->realloc(nPointCount);
+ pOuterSequenceZ->realloc(nPointCount);
+
+ double* pInnerSequenceX = pOuterSequenceX->getArray();
+ double* pInnerSequenceY = pOuterSequenceY->getArray();
+ double* pInnerSequenceZ = pOuterSequenceZ->getArray();
+
+ for(sal_Int32 nN = nPointCount; nN--;)
+ *pInnerSequenceZ++ = 0.0;
+ //*pInnerSequenceZ++ = -fDepth/2.0;
+
+ if(nPointCount == 5)
+ {
+ *pInnerSequenceY++ = 0.0;
+ *pInnerSequenceY++ = 0.0;
+ *pInnerSequenceY++ = fHeight;
+ *pInnerSequenceY++ = fHeight;
+ *pInnerSequenceY++ = 0.0;
+
+ *pInnerSequenceX++ = -fWidthH;
+ *pInnerSequenceX++ = fWidthH;
+ *pInnerSequenceX++ = fWidthH;
+ *pInnerSequenceX++ = -fWidthH;
+ *pInnerSequenceX++ = -fWidthH;
+ }
+ else
+ {
+ *pInnerSequenceY++ = 0.0;
+ *pInnerSequenceY++ = 0.0;
+ *pInnerSequenceY++ = 0.0;
+ *pInnerSequenceY++ = fHeightSign*fOffset;
+ *pInnerSequenceY++ = fHeight - fHeightSign*fOffset;
+ *pInnerSequenceY++ = fHeight;
+ *pInnerSequenceY++ = fHeight;
+ *pInnerSequenceY++ = fHeight;
+ *pInnerSequenceY++ = fHeight;
+ *pInnerSequenceY++ = fHeight - fHeightSign*fOffset;
+ *pInnerSequenceY++ = fHeightSign*fOffset;
+ *pInnerSequenceY++ = 0.0;
+ *pInnerSequenceY++ = 0.0;
+
+ *pInnerSequenceX++ = -fWidthH + fOffset;
+ *pInnerSequenceX++ = fWidthH - fOffset;
+ *pInnerSequenceX++ = fWidthH;
+ *pInnerSequenceX++ = fWidthH;
+ *pInnerSequenceX++ = fWidthH;
+ *pInnerSequenceX++ = fWidthH;
+ *pInnerSequenceX++ = fWidthH - fOffset;
+ *pInnerSequenceX++ = -fWidthH + fOffset;
+ *pInnerSequenceX++ = -fWidthH;
+ *pInnerSequenceX++ = -fWidthH;
+ *pInnerSequenceX++ = -fWidthH;
+ *pInnerSequenceX++ = -fWidthH;
+ *pInnerSequenceX++ = -fWidthH + fOffset;
+ }
+ return uno::Any( &aPP, ::getCppuType((const drawing::PolyPolygonShape3D*)0) );
+}
+
+uno::Any createPolyPolygon_Cylinder(
+ double fHeight
+ , double fRadius
+ , sal_Int32& nVerticalSegmentCount )
+{
+ //fHeight may be negative
+ DBG_ASSERT(fRadius>0, "The radius of a cylinder needs to be > 0");
+
+ //--------------------------------------
+ drawing::PolyPolygonShape3D aPP;
+
+ nVerticalSegmentCount=1;
+
+ aPP.SequenceX.realloc(3);
+ aPP.SequenceY.realloc(3);
+ aPP.SequenceZ.realloc(3);
+
+ drawing::DoubleSequence* pOuterSequenceX = aPP.SequenceX.getArray();
+ drawing::DoubleSequence* pOuterSequenceY = aPP.SequenceY.getArray();
+ drawing::DoubleSequence* pOuterSequenceZ = aPP.SequenceZ.getArray();
+
+ pOuterSequenceX->realloc(2);
+ pOuterSequenceY->realloc(2);
+ pOuterSequenceZ->realloc(2);
+
+ double* pInnerSequenceX = pOuterSequenceX->getArray();
+ double* pInnerSequenceY = pOuterSequenceY->getArray();
+ double* pInnerSequenceZ = pOuterSequenceZ->getArray();
+
+ double fY1 = 0.0;
+ double fY2 = fHeight;
+
+ if( fHeight<0.0 )
+ ::std::swap(fY1,fY2);
+
+ //----------------------------
+ for(sal_Int32 nN = 2; nN--;)
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceX++ = 0.0;
+ *pInnerSequenceY++ = fY1;
+
+ *pInnerSequenceX++ = fRadius;
+ *pInnerSequenceY++ = fY1;
+ //----------------------------
+
+ pOuterSequenceX++;pOuterSequenceY++;pOuterSequenceZ++;
+ pOuterSequenceX->realloc(2);
+ pOuterSequenceY->realloc(2);
+ pOuterSequenceZ->realloc(2);
+
+ pInnerSequenceX = pOuterSequenceX->getArray();
+ pInnerSequenceY = pOuterSequenceY->getArray();
+ pInnerSequenceZ = pOuterSequenceZ->getArray();
+
+ //----------------------------
+ for(sal_Int32 nN = 2; nN--;)
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceX++ = fRadius;
+ *pInnerSequenceY++ = fY1;
+
+ *pInnerSequenceX++ = fRadius;
+ *pInnerSequenceY++ = fY2;
+ //----------------------------
+
+ pOuterSequenceX++;pOuterSequenceY++;pOuterSequenceZ++;
+ pOuterSequenceX->realloc(2);
+ pOuterSequenceY->realloc(2);
+ pOuterSequenceZ->realloc(2);
+
+ pInnerSequenceX = pOuterSequenceX->getArray();
+ pInnerSequenceY = pOuterSequenceY->getArray();
+ pInnerSequenceZ = pOuterSequenceZ->getArray();
+
+ //----------------------------
+ for(sal_Int32 nN = 2; nN--;)
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceX++ = fRadius;
+ *pInnerSequenceY++ = fY2;
+
+ *pInnerSequenceX++ = 0.0;
+ *pInnerSequenceY++ = fY2;
+ //----------------------------
+
+ return uno::Any( &aPP, ::getCppuType((const drawing::PolyPolygonShape3D*)0) );
+}
+
+uno::Any createPolyPolygon_Cone( double fHeight, double fRadius, double fTopHeight
+ , sal_Int32& nVerticalSegmentCount )
+{
+ DBG_ASSERT(fRadius>0, "The radius of a cone needs to be > 0");
+
+ //for stacked charts we need cones without top -> fTopHeight != 0 resp. bTopless == true
+ //fTopHeight indicates the high of the cutted top only (not the full height)
+ bool bTopless = !::rtl::math::approxEqual( fHeight, fHeight + fTopHeight );
+
+ double r1= 0.0, r2 = fRadius;
+ if(bTopless)
+ // #i63212# fHeight may be negative, fTopHeight is always positive -> use fabs(fHeight)
+ r1 = fRadius * (fTopHeight)/(fabs(fHeight)+fTopHeight);
+
+ nVerticalSegmentCount=1;
+ drawing::PolyPolygonShape3D aPP;
+
+ aPP.SequenceX.realloc(2);
+ aPP.SequenceY.realloc(2);
+ aPP.SequenceZ.realloc(2);
+
+ drawing::DoubleSequence* pOuterSequenceX = aPP.SequenceX.getArray();
+ drawing::DoubleSequence* pOuterSequenceY = aPP.SequenceY.getArray();
+ drawing::DoubleSequence* pOuterSequenceZ = aPP.SequenceZ.getArray();
+
+ pOuterSequenceX->realloc(2);
+ pOuterSequenceY->realloc(2);
+ pOuterSequenceZ->realloc(2);
+
+ double* pInnerSequenceX = pOuterSequenceX->getArray();
+ double* pInnerSequenceY = pOuterSequenceY->getArray();
+ double* pInnerSequenceZ = pOuterSequenceZ->getArray();
+
+ double fX1 = 0.0;
+ double fX2 = r2;
+ double fX3 = r1;
+
+ double fY1 = 0.0;
+ double fY2 = 0.0;
+ double fY3 = fHeight;
+
+ if( fHeight<0.0 )
+ {
+ ::std::swap(fX1,fX3);
+ ::std::swap(fY1,fY3);
+ }
+
+ //----------------------------
+ for(sal_Int32 nN = 2; nN--;)
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceY++ = fY1;
+ *pInnerSequenceX++ = fX1;
+
+ *pInnerSequenceY++ = fY2;
+ *pInnerSequenceX++ = fX2;
+ //----------------------------
+
+ pOuterSequenceX++;pOuterSequenceY++;pOuterSequenceZ++;
+ pOuterSequenceX->realloc(2);
+ pOuterSequenceY->realloc(2);
+ pOuterSequenceZ->realloc(2);
+
+ pInnerSequenceX = pOuterSequenceX->getArray();
+ pInnerSequenceY = pOuterSequenceY->getArray();
+ pInnerSequenceZ = pOuterSequenceZ->getArray();
+
+ //----------------------------
+ for(sal_Int32 nN = 2; nN--;)
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceY++ = fY2;
+ *pInnerSequenceX++ = fX2;
+
+ *pInnerSequenceY++ = fY3;
+ *pInnerSequenceX++ = fX3;
+ //----------------------------
+
+ return uno::Any( &aPP, ::getCppuType((const drawing::PolyPolygonShape3D*)0) );
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// methods for 3D shape creation
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+uno::Reference<drawing::XShape>
+ ShapeFactory::createCube(
+ const uno::Reference<drawing::XShapes>& xTarget
+ , const drawing::Position3D& rPosition, const drawing::Direction3D& rSize
+ , sal_Int32 nRotateZAngleHundredthDegree
+ , const uno::Reference< beans::XPropertySet >& xSourceProp
+ , const tPropertyNameMap& rPropertyNameMap
+ , bool bRounded )
+{
+ if( !xTarget.is() )
+ return 0;
+ if( bRounded )
+ {
+ try
+ {
+ if( xSourceProp.is() )
+ {
+ drawing::LineStyle aLineStyle;
+ xSourceProp->getPropertyValue( C2U( "BorderStyle" ) ) >>= aLineStyle;
+ if( aLineStyle == drawing::LineStyle_SOLID )
+ bRounded = false;
+ }
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+ }
+ uno::Reference<drawing::XShape> xShape = impl_createCube( xTarget, rPosition, rSize, nRotateZAngleHundredthDegree, bRounded );
+ uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
+ if( xSourceProp.is())
+ PropertyMapper::setMappedProperties( xProp, xSourceProp, rPropertyNameMap );
+ return xShape;
+}
+
+uno::Reference<drawing::XShape>
+ ShapeFactory::impl_createCube(
+ const uno::Reference<drawing::XShapes>& xTarget
+ , const drawing::Position3D& rPosition, const drawing::Direction3D& rSize
+ , sal_Int32 nRotateZAngleHundredthDegree
+ , bool bRounded )
+{
+ if( !xTarget.is() )
+ return 0;
+
+ //create shape
+ uno::Reference< drawing::XShape > xShape(
+ m_xShapeFactory->createInstance( C2U(
+ "com.sun.star.drawing.Shape3DExtrudeObject") ), uno::UNO_QUERY );
+ xTarget->add(xShape);
+
+ //set properties
+ uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
+ DBG_ASSERT(xProp.is(), "created shape offers no XPropertySet");
+ if( xProp.is())
+ {
+ try
+ {
+ //depth
+ double fDepth = rSize.DirectionZ;
+ if(fDepth<0)
+ fDepth*=-1.0;
+ xProp->setPropertyValue( C2U( UNO_NAME_3D_EXTRUDE_DEPTH )
+ , uno::makeAny((sal_Int32)fDepth) );
+
+ //PercentDiagonal
+ sal_Int16 nPercentDiagonal = bRounded ? 3 : 0;
+ xProp->setPropertyValue( C2U( UNO_NAME_3D_PERCENT_DIAGONAL )
+ , uno::makeAny( nPercentDiagonal ) );
+
+ //Polygon
+ xProp->setPropertyValue( C2U( UNO_NAME_3D_POLYPOLYGON3D )
+ , createPolyPolygon_Cube( rSize, double(nPercentDiagonal)/200.0,bRounded) );
+
+ //Matrix for position
+ {
+ ::basegfx::B3DHomMatrix aM;
+ if(nRotateZAngleHundredthDegree!=0)
+ aM.rotate(0.0,0.0,-nRotateZAngleHundredthDegree/18000.00*F_PI);
+ aM.translate(rPosition.PositionX
+ , rPosition.PositionY
+ , rPosition.PositionZ - (fDepth/2.0));
+ drawing::HomogenMatrix aHM = B3DHomMatrixToHomogenMatrix(aM);
+ xProp->setPropertyValue( C2U( UNO_NAME_3D_TRANSFORM_MATRIX )
+ , uno::makeAny(aHM) );
+ }
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+ }
+ return xShape;
+}
+
+uno::Reference<drawing::XShape>
+ ShapeFactory::createCylinder(
+ const uno::Reference<drawing::XShapes>& xTarget
+ , const drawing::Position3D& rPosition, const drawing::Direction3D& rSize
+ , sal_Int32 nRotateZAngleHundredthDegree )
+{
+ return impl_createConeOrCylinder(
+ xTarget, rPosition, rSize, 0.0, nRotateZAngleHundredthDegree, true );
+}
+
+uno::Reference<drawing::XShape>
+ ShapeFactory::createPyramid(
+ const uno::Reference<drawing::XShapes>& xTarget
+ , const drawing::Position3D& rPosition, const drawing::Direction3D& rSize
+ , double fTopHeight, bool bRotateZ
+ , const uno::Reference< beans::XPropertySet >& xSourceProp
+ , const tPropertyNameMap& rPropertyNameMap )
+{
+ if( !xTarget.is() )
+ return 0;
+
+ Reference< drawing::XShapes > xGroup( ShapeFactory::createGroup3D( xTarget, rtl::OUString() ) );
+
+ sal_Bool bDoubleSided = false;
+ short nRotatedTexture = 0;
+
+ const double fWidth = rSize.DirectionX;
+ const double fDepth = rSize.DirectionZ;
+ const double fHeight = rSize.DirectionY;
+
+ drawing::Position3D aBottomP1( rPosition.PositionX, rPosition.PositionY, rPosition.PositionZ - fDepth/2.0 );
+ if(bRotateZ)
+ aBottomP1.PositionY -= fWidth/2.0;
+ else
+ aBottomP1.PositionX -= fWidth/2.0;
+ drawing::Position3D aBottomP2( aBottomP1 );
+ if(bRotateZ)
+ aBottomP2.PositionY += fWidth;
+ else
+ aBottomP2.PositionX += fWidth;
+ drawing::Position3D aBottomP3( aBottomP2 );
+ drawing::Position3D aBottomP4( aBottomP1 );
+ aBottomP3.PositionZ += fDepth;
+ aBottomP4.PositionZ += fDepth;
+
+ const double fTopFactor = (fTopHeight)/(fabs(fHeight)+fTopHeight);
+ drawing::Position3D aTopP1( rPosition.PositionX, rPosition.PositionY, rPosition.PositionZ - fDepth*fTopFactor/2.0 );
+ if(bRotateZ)
+ {
+ aTopP1.PositionY -= fWidth*fTopFactor/2.0;
+ aTopP1.PositionX += fHeight;
+ }
+ else
+ {
+ aTopP1.PositionX -= fWidth*fTopFactor/2.0;
+ aTopP1.PositionY += fHeight;
+ }
+ drawing::Position3D aTopP2( aTopP1 );
+ if(bRotateZ)
+ aTopP2.PositionY += fWidth*fTopFactor;
+ else
+ aTopP2.PositionX += fWidth*fTopFactor;
+ drawing::Position3D aTopP3( aTopP2 );
+ drawing::Position3D aTopP4( aTopP1 );
+ aTopP3.PositionZ += fDepth*fTopFactor;
+ aTopP4.PositionZ += fDepth*fTopFactor;
+
+ Stripe aStripeBottom( aBottomP1, aBottomP4, aBottomP3, aBottomP2 );
+
+ drawing::Position3D aNormalsBottomP1( aBottomP1 );
+ drawing::Position3D aNormalsBottomP2( aBottomP2 );
+ drawing::Position3D aNormalsBottomP3( aBottomP3 );
+ drawing::Position3D aNormalsBottomP4( aBottomP4 );
+ drawing::Position3D aNormalsTopP1( aBottomP1 );
+ drawing::Position3D aNormalsTopP2( aBottomP2 );
+ drawing::Position3D aNormalsTopP3( aBottomP3 );
+ drawing::Position3D aNormalsTopP4( aBottomP4 );
+ if( bRotateZ )
+ {
+ aNormalsTopP1.PositionX += fHeight;
+ aNormalsTopP2.PositionX += fHeight;
+ aNormalsTopP3.PositionX += fHeight;
+ aNormalsTopP4.PositionX += fHeight;
+ }
+ else
+ {
+ aNormalsTopP1.PositionY += fHeight;
+ aNormalsTopP2.PositionY += fHeight;
+ aNormalsTopP3.PositionY += fHeight;
+ aNormalsTopP4.PositionY += fHeight;
+ }
+
+ bool bInvertPolygon = false;
+ bool bInvertNormals = false;
+
+ if(bRotateZ)
+ {
+ //bars
+ if(fHeight>=0.0)
+ {
+ nRotatedTexture = 2;
+ bInvertNormals = true;
+ aStripeBottom = Stripe( aBottomP1, aBottomP4, aBottomP3, aBottomP2 );
+ }
+ else
+ {
+ bInvertPolygon = true;
+ nRotatedTexture = 1;
+ aStripeBottom = Stripe( aBottomP2, aBottomP3, aBottomP4, aBottomP1 );
+ }
+ }
+ else
+ {
+ //columns
+ if(fHeight>=0.0)
+ {
+ bInvertPolygon = true;
+ nRotatedTexture = 2;
+ aStripeBottom = Stripe( aBottomP2, aBottomP3, aBottomP4, aBottomP1 );
+ }
+ else
+ {
+ nRotatedTexture = 3;
+ bInvertNormals = true;
+ aStripeBottom = Stripe( aBottomP4, aBottomP3, aBottomP2, aBottomP1 );
+ }
+ }
+ aStripeBottom.InvertNormal(true);
+
+ Stripe aStripe1( aTopP2, aTopP1, aBottomP1, aBottomP2 );
+ Stripe aStripe2( aTopP3, aTopP2, aBottomP2, aBottomP3 );
+ Stripe aStripe3( aTopP4, aTopP3, aBottomP3, aBottomP4 );
+ Stripe aStripe4( aTopP1, aTopP4, aBottomP4, aBottomP1 );
+
+ if( bInvertPolygon )
+ {
+ aStripe1 = Stripe( aBottomP1, aTopP1, aTopP2, aBottomP2 );
+ aStripe2 = Stripe( aBottomP2, aTopP2, aTopP3, aBottomP3 );
+ aStripe3 = Stripe( aBottomP3, aTopP3, aTopP4, aBottomP4 );
+ aStripe4 = Stripe( aBottomP4, aTopP4, aTopP1, aBottomP1 );
+ }
+
+ Stripe aNormalsStripe1( aNormalsTopP1, aNormalsBottomP1, aNormalsBottomP2, aNormalsTopP2 );
+ Stripe aNormalsStripe2( aNormalsTopP2, aNormalsBottomP2, aNormalsBottomP3, aNormalsTopP3 );
+ Stripe aNormalsStripe3( aNormalsTopP3, aNormalsBottomP3, aNormalsBottomP4, aNormalsTopP4 );
+ Stripe aNormalsStripe4( aNormalsTopP4, aNormalsBottomP4, aNormalsBottomP1, aNormalsTopP1 );
+
+ if( bInvertNormals )
+ {
+ aNormalsStripe1 = Stripe( aNormalsTopP2, aNormalsBottomP2, aNormalsBottomP1, aNormalsTopP1 );
+ aNormalsStripe2 = Stripe( aNormalsTopP3, aNormalsBottomP3, aNormalsBottomP2, aNormalsTopP2 );
+ aNormalsStripe3 = Stripe( aNormalsTopP4, aNormalsBottomP4, aNormalsBottomP3, aNormalsTopP3 );
+ aNormalsStripe4 = Stripe( aNormalsTopP1, aNormalsBottomP1, aNormalsBottomP4, aNormalsTopP4 );
+ }
+
+ aStripe1.SetManualNormal( aNormalsStripe1.getNormal() );
+ aStripe2.SetManualNormal( aNormalsStripe2.getNormal() );
+ aStripe3.SetManualNormal( aNormalsStripe3.getNormal() );
+ aStripe4.SetManualNormal( aNormalsStripe4.getNormal() );
+
+ const bool bFlatNormals = false;
+ ShapeFactory::createStripe( xGroup, aStripe1, xSourceProp, rPropertyNameMap, bDoubleSided, nRotatedTexture, bFlatNormals );
+ ShapeFactory::createStripe( xGroup, aStripe2, xSourceProp, rPropertyNameMap, bDoubleSided, nRotatedTexture, bFlatNormals );
+ ShapeFactory::createStripe( xGroup, aStripe3, xSourceProp, rPropertyNameMap, bDoubleSided, nRotatedTexture, bFlatNormals );
+ ShapeFactory::createStripe( xGroup, aStripe4, xSourceProp, rPropertyNameMap, bDoubleSided, nRotatedTexture, bFlatNormals );
+ ShapeFactory::createStripe( xGroup, aStripeBottom, xSourceProp, rPropertyNameMap, bDoubleSided, nRotatedTexture, bFlatNormals );
+
+ return Reference< drawing::XShape >( xGroup, uno::UNO_QUERY );
+}
+
+uno::Reference<drawing::XShape>
+ ShapeFactory::createCone(
+ const uno::Reference<drawing::XShapes>& xTarget
+ , const drawing::Position3D& rPosition, const drawing::Direction3D& rSize
+ , double fTopHeight, sal_Int32 nRotateZAngleHundredthDegree )
+{
+ return impl_createConeOrCylinder( xTarget, rPosition, rSize, fTopHeight, nRotateZAngleHundredthDegree );
+}
+
+uno::Reference<drawing::XShape>
+ ShapeFactory::impl_createConeOrCylinder(
+ const uno::Reference<drawing::XShapes>& xTarget
+ , const drawing::Position3D& rPosition, const drawing::Direction3D& rSize
+ , double fTopHeight, sal_Int32 nRotateZAngleHundredthDegree
+ , bool bCylinder )
+{
+ if( !xTarget.is() )
+ return 0;
+
+ //create shape
+ uno::Reference< drawing::XShape > xShape(
+ m_xShapeFactory->createInstance( C2U(
+ "com.sun.star.drawing.Shape3DLatheObject") ), uno::UNO_QUERY );
+ xTarget->add(xShape);
+
+ double fWidth = rSize.DirectionX/2.0; //The depth will be corrrected within Matrix
+ double fRadius = fWidth; //!!!!!!!! problem in drawing layer: rotation object calculates wrong needed size -> wrong camera (it's a problem with bounding boxes)
+ double fHeight = rSize.DirectionY;
+
+ //set properties
+ uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
+ DBG_ASSERT(xProp.is(), "created shape offers no XPropertySet");
+ if( xProp.is())
+ {
+ try
+ {
+ //PercentDiagonal
+ sal_Int16 nPercentDiagonal = 5;
+ xProp->setPropertyValue( C2U( UNO_NAME_3D_PERCENT_DIAGONAL )
+ , uno::makeAny( nPercentDiagonal ) );
+
+ //Polygon
+ sal_Int32 nVerticalSegmentCount = 0;
+ uno::Any aPPolygon = bCylinder ? createPolyPolygon_Cylinder(
+ fHeight, fRadius, nVerticalSegmentCount)
+ : createPolyPolygon_Cone(
+ fHeight, fRadius, fTopHeight, nVerticalSegmentCount);
+ xProp->setPropertyValue( C2U( UNO_NAME_3D_POLYPOLYGON3D ), aPPolygon );
+
+ //Matrix for position
+ {
+ ::basegfx::B3DHomMatrix aM;
+ if(nRotateZAngleHundredthDegree!=0)
+ aM.rotate(0.0,0.0,-nRotateZAngleHundredthDegree/18000.00*F_PI);
+ //stretch the symmetric objects to given depth
+ aM.scale(1.0,1.0,rSize.DirectionZ/rSize.DirectionX);
+ aM.translate(rPosition.PositionX, rPosition.PositionY, rPosition.PositionZ);
+ drawing::HomogenMatrix aHM = B3DHomMatrixToHomogenMatrix(aM);
+ xProp->setPropertyValue( C2U( UNO_NAME_3D_TRANSFORM_MATRIX )
+ , uno::makeAny(aHM) );
+ }
+
+ //Segments
+ xProp->setPropertyValue( C2U( UNO_NAME_3D_HORZ_SEGS )
+ , uno::makeAny(CHART_3DOBJECT_SEGMENTCOUNT) );
+ xProp->setPropertyValue( C2U( UNO_NAME_3D_VERT_SEGS )
+ , uno::makeAny((sal_Int32)nVerticalSegmentCount) );//depends on point count of the used polygon
+
+ //Reduced lines
+ xProp->setPropertyValue( C2U( UNO_NAME_3D_REDUCED_LINE_GEOMETRY )
+ , uno::makeAny((sal_Bool)sal_True) );
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+ }
+ return xShape;
+}
+
+//------------------------------------------------------------------------------------------------------------
+//------------------------------------------------------------------------------------------------------------
+//------------------------------------------------------------------------------------------------------------
+
+void appendAndCloseBezierCoords( drawing::PolyPolygonBezierCoords& rReturn, const drawing::PolyPolygonBezierCoords& rAdd, sal_Bool bAppendInverse )
+{
+ if(!rAdd.Coordinates.getLength())
+ return;
+ sal_Int32 nAddCount = rAdd.Coordinates[0].getLength();
+ if(!nAddCount)
+ return;
+
+ sal_Int32 nOldCount = rReturn.Coordinates[0].getLength();
+
+ rReturn.Coordinates[0].realloc(nOldCount+nAddCount+1);
+ rReturn.Flags[0].realloc(nOldCount+nAddCount+1);
+
+ for(sal_Int32 nN=0;nN<nAddCount; nN++ )
+ {
+ sal_Int32 nAdd = bAppendInverse ? (nAddCount-1-nN) : nN;
+ rReturn.Coordinates[0][nOldCount+nN] = rAdd.Coordinates[0][nAdd];
+ rReturn.Flags[0][nOldCount+nN] = rAdd.Flags[0][nAdd];
+ }
+
+ //close
+ rReturn.Coordinates[0][nOldCount+nAddCount] = rReturn.Coordinates[0][0];
+ rReturn.Flags[0][nOldCount+nAddCount] = rReturn.Flags[0][0];
+}
+
+//------------------------------------------------------------------------------------------------------------
+
+drawing::PolyPolygonBezierCoords getCircularArcBezierCoords(
+ double fStartAngleRadian, double fWidthAngleRadian, double fUnitRadius
+ , const ::basegfx::B2DHomMatrix& rTransformationFromUnitCircle
+ , const double fAngleSubdivisionRadian )
+{
+ //at least one polygon is created using two normal and two control points
+ //if the angle is larger it is separated into multiple sub angles
+
+ drawing::PolyPolygonBezierCoords aReturn = drawing::PolyPolygonBezierCoords();
+ sal_Int32 nSegmentCount = static_cast< sal_Int32 >( fWidthAngleRadian/fAngleSubdivisionRadian );
+ if( fWidthAngleRadian > fAngleSubdivisionRadian*nSegmentCount )
+ nSegmentCount++;
+
+ double fFirstSegmentAngle = fAngleSubdivisionRadian;
+ double fLastSegmentAngle = fAngleSubdivisionRadian;
+ if(nSegmentCount==1)
+ {
+ fFirstSegmentAngle = fWidthAngleRadian;
+ fLastSegmentAngle = 0.0;
+ }
+ else
+ {
+ double fFirstAngleOnSubDevision = (static_cast<sal_Int32>(fStartAngleRadian/fAngleSubdivisionRadian)+1)*fAngleSubdivisionRadian;
+ if( !::rtl::math::approxEqual( fStartAngleRadian, fFirstAngleOnSubDevision ) )
+ fFirstSegmentAngle = fFirstAngleOnSubDevision-fStartAngleRadian;
+
+ if(nSegmentCount>1)
+ {
+ fLastSegmentAngle = fWidthAngleRadian-fFirstSegmentAngle-fAngleSubdivisionRadian*(nSegmentCount-2);
+ if( fLastSegmentAngle<0 )
+ nSegmentCount--;
+ if( fLastSegmentAngle>fAngleSubdivisionRadian )
+ {
+ fLastSegmentAngle-=fAngleSubdivisionRadian;
+ nSegmentCount++;
+ }
+ }
+ }
+
+ sal_Int32 nPointCount = 1 + 3*nSegmentCount; //first point of next segment equals last point of former segment
+
+ aReturn.Coordinates = drawing::PointSequenceSequence(1);
+ aReturn.Flags = drawing::FlagSequenceSequence(1);
+
+ drawing::PointSequence aPoints(nPointCount);
+ drawing::FlagSequence aFlags(nPointCount);
+
+ //
+
+ //!! applying matrix to vector does ignore translation, so it is important to use a B2DPoint here instead of B2DVector
+ ::basegfx::B2DPoint P0,P1,P2,P3;
+ ::basegfx::B2DPoint POrigin = rTransformationFromUnitCircle * ::basegfx::B2DPoint(0.0, 0.0);
+
+ sal_Int32 nPoint=0;
+ double fCurrentRotateAngle = fStartAngleRadian;
+ for(sal_Int32 nSegment=0; nSegment<nSegmentCount; nSegment++)
+ {
+ double fCurrentSegmentAngle = fAngleSubdivisionRadian;
+ if(nSegment==0)//first segment gets only a smaller peace until the next subdevision
+ fCurrentSegmentAngle = fFirstSegmentAngle;
+ else if(nSegment==(nSegmentCount-1)) //the last segment gets the rest angle that does not fit into equal pieces
+ fCurrentSegmentAngle = fLastSegmentAngle;
+
+ //first create untransformed points for a unit circle arc:
+ const double fCos = cos(fCurrentSegmentAngle/2.0);
+ const double fSin = sin(fCurrentSegmentAngle/2.0);
+ P0.setX(fCos);
+ P3.setX(fCos);
+ P0.setY(-fSin);
+ P3.setY(-P0.getY());
+
+ P1.setX((4.0-fCos)/3.0);
+ P2.setX(P1.getX());
+ P1.setY((1.0-fCos)*(fCos-3.0)/(3.0*fSin));
+ P2.setY(-P1.getY());
+ //transform thus startangle equals NULL
+ ::basegfx::B2DHomMatrix aStart;
+ aStart.rotate(fCurrentSegmentAngle/2.0 + fCurrentRotateAngle );
+ fCurrentRotateAngle+=fCurrentSegmentAngle;
+
+ aStart.scale( fUnitRadius, fUnitRadius );
+
+ //apply given transformation to get final points
+ P0 = rTransformationFromUnitCircle*(aStart*P0);
+ P1 = rTransformationFromUnitCircle*(aStart*P1);
+ P2 = rTransformationFromUnitCircle*(aStart*P2);
+ P3 = rTransformationFromUnitCircle*(aStart*P3);
+
+ aPoints[nPoint].X = static_cast< sal_Int32 >( P0.getX());
+ aPoints[nPoint].Y = static_cast< sal_Int32 >( P0.getY());
+ aFlags [nPoint++] = drawing::PolygonFlags_NORMAL;
+
+ aPoints[nPoint].X = static_cast< sal_Int32 >( P1.getX());
+ aPoints[nPoint].Y = static_cast< sal_Int32 >( P1.getY());
+ aFlags[nPoint++] = drawing::PolygonFlags_CONTROL;
+
+ aPoints[nPoint].X = static_cast< sal_Int32 >( P2.getX());
+ aPoints[nPoint].Y = static_cast< sal_Int32 >( P2.getY());
+ aFlags [nPoint++] = drawing::PolygonFlags_CONTROL;
+
+ if(nSegment==(nSegmentCount-1))
+ {
+ aPoints[nPoint].X = static_cast< sal_Int32 >( P3.getX());
+ aPoints[nPoint].Y = static_cast< sal_Int32 >( P3.getY());
+ aFlags [nPoint++] = drawing::PolygonFlags_NORMAL;
+ }
+ }
+
+ aReturn.Coordinates[0] = aPoints;
+ aReturn.Flags[0] = aFlags;
+
+ return aReturn;
+}
+
+//------------------------------------------------------------------------------------------------------------
+
+drawing::PolyPolygonBezierCoords getRingBezierCoords(
+ double fUnitCircleInnerRadius
+ , double fUnitCircleOuterRadius
+ , double fStartAngleRadian, double fWidthAngleRadian
+ , ::basegfx::B2DHomMatrix aTransformationFromUnitCircle
+ , const double fAngleSubdivisionRadian )
+{
+ drawing::PolyPolygonBezierCoords aReturn = drawing::PolyPolygonBezierCoords();
+
+ aReturn.Coordinates = drawing::PointSequenceSequence(1);
+ aReturn.Flags = drawing::FlagSequenceSequence(1);
+
+ drawing::PolyPolygonBezierCoords aOuterArc = getCircularArcBezierCoords(
+ fStartAngleRadian, fWidthAngleRadian, fUnitCircleOuterRadius, aTransformationFromUnitCircle, fAngleSubdivisionRadian );
+ aReturn.Coordinates[0] = aOuterArc.Coordinates[0];
+ aReturn.Flags[0] = aOuterArc.Flags[0];
+
+ drawing::PolyPolygonBezierCoords aInnerArc = getCircularArcBezierCoords(
+ fStartAngleRadian, fWidthAngleRadian, fUnitCircleInnerRadius, aTransformationFromUnitCircle, fAngleSubdivisionRadian );
+ appendAndCloseBezierCoords( aReturn, aInnerArc, sal_True );
+
+ //fill rMarkHandlePoints
+ /*
+ {
+ rMarkHandlePoints.realloc(1);
+ rMarkHandlePoints[0].realloc(6);
+ sal_Int32 nHandleCount=0;
+ sal_Int32 nOuterArcCount = aOuterArc.Coordinates[0].getLength();
+ if(nOuterArcCount>0)
+ rMarkHandlePoints[0][nHandleCount++]=aOuterArc.Coordinates[0][0];
+ if(nOuterArcCount>1)
+ rMarkHandlePoints[0][nHandleCount++]=aOuterArc.Coordinates[0][nOuterArcCount-1];
+ sal_Int32 nInnerArcCount = aInnerArc.Coordinates[0].getLength();
+ if(nInnerArcCount>0)
+ rMarkHandlePoints[0][nHandleCount++]=aInnerArc.Coordinates[0][0];
+ if(nInnerArcCount>1)
+ rMarkHandlePoints[0][nHandleCount++]=aInnerArc.Coordinates[0][nInnerArcCount-1];
+ rMarkHandlePoints[0].realloc(nHandleCount);
+ }
+ */
+
+ return aReturn;
+}
+
+//------------------------------------------------------------------------------------------------------------
+
+uno::Reference< drawing::XShape >
+ ShapeFactory::createPieSegment2D(
+ const uno::Reference< drawing::XShapes >& xTarget
+ , double fUnitCircleStartAngleDegree, double fUnitCircleWidthAngleDegree
+ , double fUnitCircleInnerRadius, double fUnitCircleOuterRadius
+ , const drawing::Direction3D& rOffset
+ , const drawing::HomogenMatrix& rUnitCircleToScene )
+{
+ if( !xTarget.is() )
+ return 0;
+
+ while(fUnitCircleWidthAngleDegree>360)
+ fUnitCircleWidthAngleDegree -= 360.0;
+ while(fUnitCircleWidthAngleDegree<0)
+ fUnitCircleWidthAngleDegree += 360.0;
+
+ //create shape
+ uno::Reference< drawing::XShape > xShape(
+ m_xShapeFactory->createInstance(
+ C2U("com.sun.star.drawing.ClosedBezierShape") ), uno::UNO_QUERY );
+ xTarget->add(xShape); //need to add the shape before setting of properties
+
+ //set properties
+ uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
+ DBG_ASSERT(xProp.is(), "created shape offers no XPropertySet");
+ if( xProp.is())
+ {
+ try
+ {
+ ::basegfx::B2DHomMatrix aTransformationFromUnitCircle( IgnoreZ( HomogenMatrixToB3DHomMatrix(rUnitCircleToScene) ) );
+ aTransformationFromUnitCircle.translate(rOffset.DirectionX,rOffset.DirectionY);
+
+ const double fAngleSubdivisionRadian = F_PI/10.0;
+
+ drawing::PolyPolygonBezierCoords aCoords = getRingBezierCoords(
+ fUnitCircleInnerRadius, fUnitCircleOuterRadius
+ , fUnitCircleStartAngleDegree*F_PI/180.0, fUnitCircleWidthAngleDegree*F_PI/180.0
+ , aTransformationFromUnitCircle, fAngleSubdivisionRadian );
+
+ xProp->setPropertyValue( C2U( "PolyPolygonBezier" ), uno::makeAny( aCoords ) );
+
+ //add shape for markhandles
+ /*
+ drawing::PointSequenceSequence aMarkHandlePoints(1); to be filled within getRingBezierCoords
+ if( xGroup.is() )
+ {
+ VLineProperties aHandleLineProperties;
+ aHandleLineProperties.LineStyle = uno::makeAny( drawing::LineStyle_NONE );
+ uno::Reference< drawing::XShape > xHandleShape =
+ this->createLine2D( xGroup, aMarkHandlePoints, &aHandleLineProperties );
+ this->setShapeName( xHandleShape, C2U("HandlesOnly") );
+ }
+ */
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+ }
+
+ return xShape;
+}
+
+//------------------------------------------------------------------------------------------------------------
+
+uno::Reference< drawing::XShape >
+ ShapeFactory::createPieSegment(
+ const uno::Reference< drawing::XShapes >& xTarget
+ , double fUnitCircleStartAngleDegree, double fUnitCircleWidthAngleDegree
+ , double fUnitCircleInnerRadius, double fUnitCircleOuterRadius
+ , const drawing::Direction3D& rOffset
+ , const drawing::HomogenMatrix& rUnitCircleToScene
+ , double fDepth )
+{
+ if( !xTarget.is() )
+ return 0;
+
+ while(fUnitCircleWidthAngleDegree>360)
+ fUnitCircleWidthAngleDegree -= 360.0;
+ while(fUnitCircleWidthAngleDegree<0)
+ fUnitCircleWidthAngleDegree += 360.0;
+
+ //create shape
+ uno::Reference< drawing::XShape > xShape(
+ m_xShapeFactory->createInstance( C2U(
+ "com.sun.star.drawing.Shape3DExtrudeObject") ), uno::UNO_QUERY );
+ xTarget->add(xShape); //need to add the shape before setting of properties
+
+ //set properties
+ uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
+ DBG_ASSERT(xProp.is(), "created shape offers no XPropertySet");
+ if( xProp.is())
+ {
+ try
+ {
+ ::basegfx::B2DHomMatrix aTransformationFromUnitCircle( IgnoreZ( HomogenMatrixToB3DHomMatrix(rUnitCircleToScene) ) );
+ aTransformationFromUnitCircle.translate(rOffset.DirectionX,rOffset.DirectionY);
+
+ const double fAngleSubdivisionRadian = F_PI/32.0;
+
+ drawing::PolyPolygonBezierCoords aCoords = getRingBezierCoords(
+ fUnitCircleInnerRadius, fUnitCircleOuterRadius
+ , fUnitCircleStartAngleDegree*F_PI/180.0, fUnitCircleWidthAngleDegree*F_PI/180.0
+ , aTransformationFromUnitCircle, fAngleSubdivisionRadian );
+
+ //depth
+ xProp->setPropertyValue( C2U( UNO_NAME_3D_EXTRUDE_DEPTH )
+ , uno::makeAny((sal_Int32)fDepth) );
+
+ //PercentDiagonal
+ sal_Int16 nPercentDiagonal = 0;
+ xProp->setPropertyValue( C2U( UNO_NAME_3D_PERCENT_DIAGONAL )
+ , uno::makeAny( nPercentDiagonal ) );
+
+ //Polygon
+ drawing::PolyPolygonShape3D aPoly( BezierToPoly(aCoords) );
+ ShapeFactory::closePolygon( aPoly );
+ xProp->setPropertyValue( C2U( UNO_NAME_3D_POLYPOLYGON3D )
+ , uno::makeAny( aPoly ) );
+
+ //DoubleSided
+ xProp->setPropertyValue( C2U( UNO_NAME_3D_DOUBLE_SIDED )
+ , uno::makeAny( (sal_Bool)true) );
+
+ //Reduced lines
+ xProp->setPropertyValue( C2U( UNO_NAME_3D_REDUCED_LINE_GEOMETRY )
+ , uno::makeAny((sal_Bool)sal_True) );
+
+ //TextureProjectionMode
+ xProp->setPropertyValue( C2U( UNO_NAME_3D_TEXTURE_PROJ_Y )
+ , uno::makeAny( drawing::TextureProjectionMode_OBJECTSPECIFIC ) );
+
+ //TextureProjectionMode
+ xProp->setPropertyValue( C2U( UNO_NAME_3D_TEXTURE_PROJ_X )
+ , uno::makeAny( drawing::TextureProjectionMode_PARALLEL ) );
+ xProp->setPropertyValue( C2U( UNO_NAME_3D_TEXTURE_PROJ_Y )
+ , uno::makeAny( drawing::TextureProjectionMode_OBJECTSPECIFIC ) );
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+ }
+ return xShape;
+}
+
+//------------------------------------------------------------------------------------------------------------
+//------------------------------------------------------------------------------------------------------------
+//------------------------------------------------------------------------------------------------------------
+
+uno::Reference< drawing::XShape >
+ ShapeFactory::createStripe( const uno::Reference< drawing::XShapes >& xTarget
+ , const Stripe& rStripe
+ , const uno::Reference< beans::XPropertySet >& xSourceProp
+ , const tPropertyNameMap& rPropertyNameMap
+ , sal_Bool bDoubleSided
+ , short nRotatedTexture
+ , bool bFlatNormals )
+{
+ if( !xTarget.is() )
+ return 0;
+
+ //create shape
+ uno::Reference< drawing::XShape > xShape(
+ m_xShapeFactory->createInstance( C2U(
+ "com.sun.star.drawing.Shape3DPolygonObject" ) ), uno::UNO_QUERY );
+ xTarget->add(xShape);
+
+ //set properties
+ uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
+ DBG_ASSERT(xProp.is(), "created shape offers no XPropertySet");
+ if( xProp.is())
+ {
+ try
+ {
+ //Polygon
+ xProp->setPropertyValue( C2U( UNO_NAME_3D_POLYPOLYGON3D )
+ , rStripe.getPolyPolygonShape3D() );
+
+ //TexturePolygon
+ xProp->setPropertyValue( C2U( UNO_NAME_3D_TEXTUREPOLYGON3D )
+ , rStripe.getTexturePolygon( nRotatedTexture ) );
+
+ //Normals Polygon
+ xProp->setPropertyValue( C2U( UNO_NAME_3D_NORMALSPOLYGON3D )
+ , rStripe.getNormalsPolygon() );
+ //NormalsKind
+ if(bFlatNormals)
+ xProp->setPropertyValue( C2U( UNO_NAME_3D_NORMALS_KIND )
+ , uno::makeAny( drawing::NormalsKind_FLAT ) );
+
+ //LineOnly
+ xProp->setPropertyValue( C2U( UNO_NAME_3D_LINEONLY )
+ , uno::makeAny( (sal_Bool)false) );
+
+ //DoubleSided
+ xProp->setPropertyValue( C2U( UNO_NAME_3D_DOUBLE_SIDED )
+ , uno::makeAny(bDoubleSided) );
+
+ if( xSourceProp.is())
+ PropertyMapper::setMappedProperties( xProp, xSourceProp, rPropertyNameMap );
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+ }
+ return xShape;
+}
+
+uno::Reference< drawing::XShape >
+ ShapeFactory::createArea3D( const uno::Reference< drawing::XShapes >& xTarget
+ , const drawing::PolyPolygonShape3D& rPolyPolygon
+ , double fDepth )
+{
+ if( !xTarget.is() )
+ return 0;
+
+ if( !rPolyPolygon.SequenceX.getLength())
+ return 0;
+
+ //create shape
+ uno::Reference< drawing::XShape > xShape(
+ m_xShapeFactory->createInstance( C2U(
+ "com.sun.star.drawing.Shape3DExtrudeObject") ), uno::UNO_QUERY );
+ xTarget->add(xShape);
+
+ //set properties
+ uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
+ DBG_ASSERT(xProp.is(), "created shape offers no XPropertySet");
+ if( xProp.is())
+ {
+ try
+ {
+ //depth
+ xProp->setPropertyValue( C2U( UNO_NAME_3D_EXTRUDE_DEPTH )
+ , uno::makeAny((sal_Int32)fDepth) );
+
+ //PercentDiagonal
+ sal_Int16 nPercentDiagonal = 0;
+ xProp->setPropertyValue( C2U( UNO_NAME_3D_PERCENT_DIAGONAL )
+ , uno::makeAny( nPercentDiagonal ) );
+
+ //Polygon
+ xProp->setPropertyValue( C2U( UNO_NAME_3D_POLYPOLYGON3D )
+ , uno::makeAny( rPolyPolygon ) );
+
+ //DoubleSided
+ xProp->setPropertyValue( C2U( UNO_NAME_3D_DOUBLE_SIDED )
+ , uno::makeAny( (sal_Bool)true) );
+
+ //the z component of the polygon is now ignored by the drawing layer,
+ //so we nned to translate the object via transformation matrix
+
+ //Matrix for position
+ if( rPolyPolygon.SequenceZ.getLength()&& rPolyPolygon.SequenceZ[0].getLength() )
+ {
+ ::basegfx::B3DHomMatrix aM;
+ aM.translate( 0
+ , 0
+ , rPolyPolygon.SequenceZ[0][0] );
+ drawing::HomogenMatrix aHM = B3DHomMatrixToHomogenMatrix(aM);
+ xProp->setPropertyValue( C2U( UNO_NAME_3D_TRANSFORM_MATRIX )
+ , uno::makeAny(aHM) );
+ }
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+ }
+ return xShape;
+}
+
+uno::Reference< drawing::XShape >
+ ShapeFactory::createArea2D( const uno::Reference< drawing::XShapes >& xTarget
+ , const drawing::PolyPolygonShape3D& rPolyPolygon )
+{
+ if( !xTarget.is() )
+ return 0;
+
+ //create shape
+ uno::Reference< drawing::XShape > xShape(
+ m_xShapeFactory->createInstance( C2U(
+ "com.sun.star.drawing.PolyPolygonShape") ), uno::UNO_QUERY );
+ xTarget->add(xShape);
+
+ //set properties
+ uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
+ DBG_ASSERT(xProp.is(), "created shape offers no XPropertySet");
+ if( xProp.is())
+ {
+ try
+ {
+ //UNO_NAME_POLYGON "Polygon" drawing::PointSequence*
+ drawing::PointSequenceSequence aPoints( PolyToPointSequence(rPolyPolygon) );
+
+ //Polygon
+ xProp->setPropertyValue( C2U( UNO_NAME_POLYPOLYGON )
+ , uno::makeAny( aPoints ) );
+
+ //ZOrder
+ //an area should always be behind other shapes
+ xProp->setPropertyValue( C2U( UNO_NAME_MISC_OBJ_ZORDER )
+ , uno::makeAny( sal_Int32(0) ) );
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+ }
+ return xShape;
+}
+
+enum SymbolType { SYMBOL_SQUARE=0
+ , SYMBOL_DIAMOND
+ , SYMBOL_ARROW_DOWN
+ , SYMBOL_ARROW_UP
+ , SYMBOL_ARROW_RIGHT
+ , SYMBOL_ARROW_LEFT
+ , SYMBOL_BOWTIE
+ , SYMBOL_SANDGLASS
+ , SYMBOL_COUNT
+ };
+
+sal_Int32 ShapeFactory::getSymbolCount()
+{
+ return SYMBOL_COUNT;
+}
+
+drawing::PolyPolygonShape3D createPolyPolygon_Symbol( const drawing::Position3D& rPos
+ , const drawing::Direction3D& rSize
+ , sal_Int32 nStandardSymbol )
+{
+ if(nStandardSymbol<0)
+ nStandardSymbol*=-1;
+ nStandardSymbol = nStandardSymbol%ShapeFactory::getSymbolCount();
+ SymbolType eSymbolType=static_cast<SymbolType>(nStandardSymbol);
+
+ const double& fX = rPos.PositionX;
+ const double& fY = rPos.PositionY;
+
+ const double fWidthH = rSize.DirectionX/2.0; //fWidthH stands for Half Width
+ const double fHeightH = rSize.DirectionY/2.0; //fHeightH stands for Half Height
+
+ sal_Int32 nPointCount = 4; //all arrow symbols only need 4 points
+ switch( eSymbolType )
+ {
+ case SYMBOL_SQUARE:
+ case SYMBOL_DIAMOND:
+ case SYMBOL_BOWTIE:
+ case SYMBOL_SANDGLASS:
+ nPointCount = 5;
+ break;
+ default:
+ break;
+ }
+
+ //--------------------------------------
+ drawing::PolyPolygonShape3D aPP;
+
+ aPP.SequenceX.realloc(1);
+ aPP.SequenceY.realloc(1);
+ aPP.SequenceZ.realloc(1);
+
+ drawing::DoubleSequence* pOuterSequenceX = aPP.SequenceX.getArray();
+ drawing::DoubleSequence* pOuterSequenceY = aPP.SequenceY.getArray();
+ drawing::DoubleSequence* pOuterSequenceZ = aPP.SequenceZ.getArray();
+
+ pOuterSequenceX->realloc(nPointCount);
+ pOuterSequenceY->realloc(nPointCount);
+ pOuterSequenceZ->realloc(nPointCount);
+
+ double* pInnerSequenceX = pOuterSequenceX->getArray();
+ double* pInnerSequenceY = pOuterSequenceY->getArray();
+ double* pInnerSequenceZ = pOuterSequenceZ->getArray();
+
+ for(sal_Int32 nN = nPointCount; nN--;)
+ *pInnerSequenceZ++ = 0.0;
+
+ switch(eSymbolType)
+ {
+ case SYMBOL_ARROW_UP:
+ {
+ *pInnerSequenceX++ = fX-fWidthH;
+ *pInnerSequenceY++ = fY+fHeightH;
+
+ *pInnerSequenceX++ = fX+fWidthH;
+ *pInnerSequenceY++ = fY+fHeightH;
+
+ *pInnerSequenceX++ = fX;
+ *pInnerSequenceY++ = fY-fHeightH;
+
+ *pInnerSequenceX++ = fX-fWidthH;
+ *pInnerSequenceY++ = fY+fHeightH;
+ break;
+ }
+ case SYMBOL_ARROW_DOWN:
+ {
+ *pInnerSequenceX++ = fX-fWidthH;
+ *pInnerSequenceY++ = fY-fHeightH;
+
+ *pInnerSequenceX++ = fX;
+ *pInnerSequenceY++ = fY+fHeightH;
+
+ *pInnerSequenceX++ = fX+fWidthH;
+ *pInnerSequenceY++ = fY-fHeightH;
+
+ *pInnerSequenceX++ = fX-fWidthH;
+ *pInnerSequenceY++ = fY-fHeightH;
+ break;
+ }
+ case SYMBOL_ARROW_RIGHT:
+ {
+ *pInnerSequenceX++ = fX-fWidthH;
+ *pInnerSequenceY++ = fY-fHeightH;
+
+ *pInnerSequenceX++ = fX-fWidthH;
+ *pInnerSequenceY++ = fY+fHeightH;
+
+ *pInnerSequenceX++ = fX+fWidthH;
+ *pInnerSequenceY++ = fY;
+
+ *pInnerSequenceX++ = fX-fWidthH;
+ *pInnerSequenceY++ = fY-fHeightH;
+ break;
+ }
+ case SYMBOL_ARROW_LEFT:
+ {
+ *pInnerSequenceX++ = fX-fWidthH;
+ *pInnerSequenceY++ = fY;
+
+ *pInnerSequenceX++ = fX+fWidthH;
+ *pInnerSequenceY++ = fY+fHeightH;
+
+ *pInnerSequenceX++ = fX+fWidthH;
+ *pInnerSequenceY++ = fY-fHeightH;
+
+ *pInnerSequenceX++ = fX-fWidthH;
+ *pInnerSequenceY++ = fY;
+ break;
+ }
+ case SYMBOL_BOWTIE:
+ {
+ *pInnerSequenceX++ = fX-fWidthH;
+ *pInnerSequenceY++ = fY-fHeightH;
+
+ *pInnerSequenceX++ = fX-fWidthH;
+ *pInnerSequenceY++ = fY+fHeightH;
+
+ *pInnerSequenceX++ = fX+fWidthH;
+ *pInnerSequenceY++ = fY-fHeightH;
+
+ *pInnerSequenceX++ = fX+fWidthH;
+ *pInnerSequenceY++ = fY+fHeightH;
+
+ *pInnerSequenceX++ = fX-fWidthH;
+ *pInnerSequenceY++ = fY-fHeightH;
+ break;
+ }
+ case SYMBOL_SANDGLASS:
+ {
+ *pInnerSequenceX++ = fX-fWidthH;
+ *pInnerSequenceY++ = fY+fHeightH;
+
+ *pInnerSequenceX++ = fX+fWidthH;
+ *pInnerSequenceY++ = fY+fHeightH;
+
+ *pInnerSequenceX++ = fX-fWidthH;
+ *pInnerSequenceY++ = fY-fHeightH;
+
+
+ *pInnerSequenceX++ = fX+fWidthH;
+ *pInnerSequenceY++ = fY-fHeightH;
+
+ *pInnerSequenceX++ = fX-fWidthH;
+ *pInnerSequenceY++ = fY+fHeightH;
+ break;
+ }
+ case SYMBOL_DIAMOND:
+ {
+ *pInnerSequenceX++ = fX-fWidthH;
+ *pInnerSequenceY++ = fY;
+
+ *pInnerSequenceX++ = fX;
+ *pInnerSequenceY++ = fY+fHeightH;
+
+ *pInnerSequenceX++ = fX+fWidthH;
+ *pInnerSequenceY++ = fY;
+
+ *pInnerSequenceX++ = fX;
+ *pInnerSequenceY++ = fY-fHeightH;
+
+ *pInnerSequenceX++ = fX-fWidthH;
+ *pInnerSequenceY++ = fY;
+ break;
+ }
+ default: //case SYMBOL_SQUARE:
+ {
+ *pInnerSequenceX++ = fX-fWidthH;
+ *pInnerSequenceY++ = fY-fHeightH;
+
+ *pInnerSequenceX++ = fX-fWidthH;
+ *pInnerSequenceY++ = fY+fHeightH;
+
+ *pInnerSequenceX++ = fX+fWidthH;
+ *pInnerSequenceY++ = fY+fHeightH;
+
+ *pInnerSequenceX++ = fX+fWidthH;
+ *pInnerSequenceY++ = fY-fHeightH;
+
+ *pInnerSequenceX++ = fX-fWidthH;
+ *pInnerSequenceY++ = fY-fHeightH;
+ break;
+ }
+ }
+ //return uno::Any( &aPP, ::getCppuType((const drawing::PolyPolygonShape3D*)0) );
+ return aPP;
+}
+
+uno::Reference< drawing::XShape >
+ ShapeFactory::createSymbol2D(
+ const uno::Reference< drawing::XShapes >& xTarget
+ , const drawing::Position3D& rPosition
+ , const drawing::Direction3D& rSize
+ , sal_Int32 nStandardSymbol
+ , sal_Int32 nBorderColor
+ , sal_Int32 nFillColor )
+{
+ if( !xTarget.is() )
+ return 0;
+
+ //create shape
+ uno::Reference< drawing::XShape > xShape(
+ m_xShapeFactory->createInstance( C2U(
+ "com.sun.star.drawing.PolyPolygonShape") ), uno::UNO_QUERY );
+ xTarget->add(xShape);
+
+ //set properties
+ uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
+ DBG_ASSERT(xProp.is(), "created shape offers no XPropertySet");
+ if( xProp.is())
+ {
+ try
+ {
+ drawing::PointSequenceSequence aPoints( PolyToPointSequence(
+ createPolyPolygon_Symbol( rPosition, rSize, nStandardSymbol ) ));
+
+ //Polygon
+ xProp->setPropertyValue( C2U( UNO_NAME_POLYPOLYGON )
+ , uno::makeAny( aPoints ) );
+
+ //LineColor
+ xProp->setPropertyValue( C2U( UNO_NAME_LINECOLOR )
+ , uno::makeAny( nBorderColor ) );
+
+ //FillColor
+ xProp->setPropertyValue( C2U( UNO_NAME_FILLCOLOR )
+ , uno::makeAny( nFillColor ) );
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+ }
+ return xShape;
+}
+
+uno::Reference< drawing::XShape >
+ ShapeFactory::createGraphic2D(
+ const uno::Reference< drawing::XShapes >& xTarget
+ , const drawing::Position3D& rPosition
+ , const drawing::Direction3D& rSize
+ , const uno::Reference< graphic::XGraphic >& xGraphic )
+{
+ if( !xTarget.is() || !xGraphic.is() )
+ return 0;
+
+ // @todo: change this to a rectangle shape with a fill bitmap for
+ // performance reasons (ask AW, said CL)
+
+ //create shape
+ uno::Reference< drawing::XShape > xShape(
+ m_xShapeFactory->createInstance( C2U(
+ "com.sun.star.drawing.GraphicObjectShape") ), uno::UNO_QUERY );
+ xTarget->add(xShape);
+
+ try
+ {
+ // assume position is upper left corner. Transform to center.
+ drawing::Position3D aCenterPosition(
+ rPosition.PositionX - (rSize.DirectionX / 2.0),
+ rPosition.PositionY - (rSize.DirectionY / 2.0),
+ rPosition.PositionZ );
+ xShape->setPosition( Position3DToAWTPoint( aCenterPosition ));
+ xShape->setSize( Direction3DToAWTSize( rSize ));
+ }
+ catch( const uno::Exception & e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+ uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
+ DBG_ASSERT(xProp.is(), "created shape offers no XPropertySet");
+ if( xProp.is())
+ {
+ try
+ {
+ xProp->setPropertyValue( C2U("Graphic"), uno::makeAny( xGraphic ));
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+ }
+ return xShape;
+}
+
+uno::Reference< drawing::XShapes >
+ ShapeFactory::createGroup2D( const uno::Reference< drawing::XShapes >& xTarget
+ , ::rtl::OUString aName )
+{
+ if( !xTarget.is() )
+ return 0;
+ try
+ {
+ //create and add to target
+ uno::Reference< drawing::XShape > xShape(
+ m_xShapeFactory->createInstance( C2U(
+ "com.sun.star.drawing.GroupShape" ) ), uno::UNO_QUERY );
+ xTarget->add(xShape);
+
+ //set name
+ if(aName.getLength())
+ setShapeName( xShape , aName );
+
+ {//workaround
+ //need this null size as otherwise empty group shapes where painted with a gray border
+ xShape->setSize(awt::Size(0,0));
+ }
+
+ //return
+ uno::Reference< drawing::XShapes > xShapes =
+ uno::Reference<drawing::XShapes>( xShape, uno::UNO_QUERY );
+ return xShapes;
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+ return 0;
+}
+
+uno::Reference< drawing::XShapes >
+ ShapeFactory::createGroup3D( const uno::Reference< drawing::XShapes >& xTarget
+ , ::rtl::OUString aName )
+{
+ if( !xTarget.is() )
+ return 0;
+ try
+ {
+ //create shape
+ uno::Reference< drawing::XShape > xShape(
+ m_xShapeFactory->createInstance( C2U(
+ "com.sun.star.drawing.Shape3DSceneObject" ) ), uno::UNO_QUERY );
+
+ xTarget->add(xShape);
+
+ //it is necessary to set the transform matrix to initialize the scene properly (bug #106316#)
+ //otherwise all objects which are placed into this Group will not be visible
+ //the following should be unnecessary after a the bug is fixed
+ {
+ //set properties
+ uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
+ DBG_ASSERT(xProp.is(), "created shape offers no XPropertySet");
+ if( xProp.is())
+ {
+ try
+ {
+ ::basegfx::B3DHomMatrix aM;
+ xProp->setPropertyValue( C2U( UNO_NAME_3D_TRANSFORM_MATRIX )
+ , uno::makeAny(B3DHomMatrixToHomogenMatrix(aM)) );
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+ }
+ }
+
+ //set name
+ if(aName.getLength())
+ setShapeName( xShape , aName );
+
+ //return
+ uno::Reference< drawing::XShapes > xShapes =
+ uno::Reference<drawing::XShapes>( xShape, uno::UNO_QUERY );
+ return xShapes;
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+ return 0;
+}
+
+uno::Reference< drawing::XShape >
+ ShapeFactory::createCircle2D( const uno::Reference< drawing::XShapes >& xTarget
+ , const drawing::Position3D& rPosition
+ , const drawing::Direction3D& rSize )
+{
+ if( !xTarget.is() )
+ return 0;
+
+ //create shape
+ uno::Reference< drawing::XShape > xShape(
+ m_xShapeFactory->createInstance( C2U(
+ "com.sun.star.drawing.EllipseShape") ), uno::UNO_QUERY );
+ xTarget->add(xShape);
+
+ try
+ {
+ drawing::Position3D aCenterPosition(
+ rPosition.PositionX - (rSize.DirectionX / 2.0),
+ rPosition.PositionY - (rSize.DirectionY / 2.0),
+ rPosition.PositionZ );
+ xShape->setPosition( Position3DToAWTPoint( aCenterPosition ));
+ xShape->setSize( Direction3DToAWTSize( rSize ));
+ }
+ catch( const uno::Exception & e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+
+ //set properties
+ uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
+ DBG_ASSERT(xProp.is(), "created shape offers no XPropertySet");
+ if( xProp.is())
+ {
+ try
+ {
+ drawing::CircleKind eKind = drawing::CircleKind_FULL;
+ xProp->setPropertyValue( C2U( UNO_NAME_CIRCKIND )
+ , uno::makeAny( eKind ) );
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+ }
+ return xShape;
+}
+
+uno::Reference< drawing::XShape >
+ ShapeFactory::createLine3D( const uno::Reference< drawing::XShapes >& xTarget
+ , const drawing::PolyPolygonShape3D& rPoints
+ , const VLineProperties& rLineProperties )
+{
+ if( !xTarget.is() )
+ return 0;
+
+ if(!rPoints.SequenceX.getLength())
+ return NULL;
+
+ //create shape
+ uno::Reference< drawing::XShape > xShape(
+ m_xShapeFactory->createInstance( C2U(
+ "com.sun.star.drawing.Shape3DPolygonObject") ), uno::UNO_QUERY );
+ xTarget->add(xShape);
+
+ //set properties
+ uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
+ DBG_ASSERT(xProp.is(), "created shape offers no XPropertySet");
+ if( xProp.is())
+ {
+ try
+ {
+ //Polygon
+ xProp->setPropertyValue( C2U( UNO_NAME_3D_POLYPOLYGON3D )
+ , uno::makeAny( rPoints ) );
+
+ //LineOnly
+ xProp->setPropertyValue( C2U( UNO_NAME_3D_LINEONLY )
+ , uno::makeAny( (sal_Bool)true ) );
+
+ //Transparency
+ if(rLineProperties.Transparence.hasValue())
+ xProp->setPropertyValue( C2U( UNO_NAME_LINETRANSPARENCE )
+ , rLineProperties.Transparence );
+
+ //LineStyle
+ if(rLineProperties.LineStyle.hasValue())
+ xProp->setPropertyValue( C2U( UNO_NAME_LINESTYLE )
+ , rLineProperties.LineStyle );
+
+ //LineWidth
+ if(rLineProperties.Width.hasValue())
+ xProp->setPropertyValue( C2U( UNO_NAME_LINEWIDTH )
+ , rLineProperties.Width );
+
+ //LineColor
+ if(rLineProperties.Color.hasValue())
+ xProp->setPropertyValue( C2U( UNO_NAME_LINECOLOR )
+ , rLineProperties.Color );
+ //, uno::makeAny( sal_Int32( Color(COL_RED).GetColor()) ) );
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+ }
+ return xShape;
+}
+
+uno::Reference< drawing::XShape >
+ ShapeFactory::createLine2D( const uno::Reference< drawing::XShapes >& xTarget
+ , const drawing::PointSequenceSequence& rPoints
+ , const VLineProperties* pLineProperties )
+{
+ if( !xTarget.is() )
+ return 0;
+
+ if(!rPoints.getLength())
+ return NULL;
+
+ //create shape
+ uno::Reference< drawing::XShape > xShape(
+ m_xShapeFactory->createInstance( C2U(
+ //"com.sun.star.drawing.LineShape") ), uno::UNO_QUERY );
+ "com.sun.star.drawing.PolyLineShape") ), uno::UNO_QUERY );
+ //"com.sun.star.drawing.PolyLinePathShape") ), uno::UNO_QUERY );
+ //"com.sun.star.drawing.PolyPolygonPathShape") ), uno::UNO_QUERY );
+ //"com.sun.star.drawing.PolyPolygonShape") ), uno::UNO_QUERY );
+ xTarget->add(xShape);
+
+ //set properties
+ uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
+ DBG_ASSERT(xProp.is(), "created shape offers no XPropertySet");
+ if( xProp.is())
+ {
+ try
+ {
+ //Polygon
+ xProp->setPropertyValue( C2U( UNO_NAME_POLYPOLYGON )
+ , uno::makeAny( rPoints ) );
+
+ if(pLineProperties)
+ {
+ //Transparency
+ if(pLineProperties->Transparence.hasValue())
+ xProp->setPropertyValue( C2U( UNO_NAME_LINETRANSPARENCE )
+ , pLineProperties->Transparence );
+
+ //LineStyle
+ if(pLineProperties->LineStyle.hasValue())
+ xProp->setPropertyValue( C2U( UNO_NAME_LINESTYLE )
+ , pLineProperties->LineStyle );
+
+ //LineWidth
+ if(pLineProperties->Width.hasValue())
+ xProp->setPropertyValue( C2U( UNO_NAME_LINEWIDTH )
+ , pLineProperties->Width );
+
+ //LineColor
+ if(pLineProperties->Color.hasValue())
+ xProp->setPropertyValue( C2U( UNO_NAME_LINECOLOR )
+ , pLineProperties->Color );
+
+ //LineDashName
+ if(pLineProperties->DashName.hasValue())
+ xProp->setPropertyValue( C2U( "LineDashName" )
+ , pLineProperties->DashName );
+ }
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+ }
+ return xShape;
+}
+
+uno::Any ShapeFactory::makeTransformation( const awt::Point& rScreenPosition2D, double fRotationAnglePi )
+{
+ ::basegfx::B2DHomMatrix aM;
+ //As autogrow is active the rectangle is automatically expanded to that side
+ //to which the text is not adjusted.
+ // aM.scale( 1, 1 ); Oops? A scale with this parameters is neutral, line commented out
+ aM.rotate( fRotationAnglePi );
+ aM.translate( rScreenPosition2D.X, rScreenPosition2D.Y );
+ uno::Any aATransformation = uno::makeAny( B2DHomMatrixToHomogenMatrix3(aM) );
+ return aATransformation;
+}
+
+void ShapeFactory::makeShapeInvisible( const uno::Reference< drawing::XShape >& xShape )
+{
+ uno::Reference< beans::XPropertySet > xShapeProp( xShape, uno::UNO_QUERY );
+ DBG_ASSERT(xShapeProp.is(), "created shape offers no XPropertySet");
+ if( xShapeProp.is())
+ {
+ try
+ {
+ xShapeProp->setPropertyValue( C2U("LineStyle"), uno::makeAny( drawing::LineStyle_NONE ));
+ xShapeProp->setPropertyValue( C2U("FillStyle"), uno::makeAny( drawing::FillStyle_NONE ));
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+ }
+}
+
+uno::Reference< drawing::XShape > ShapeFactory::createInvisibleRectangle(
+ const uno::Reference< drawing::XShapes >& xTarget
+ , const awt::Size& rSize )
+{
+ try
+ {
+ if(!xTarget.is())
+ return 0;
+
+ uno::Reference< drawing::XShape > xShape( m_xShapeFactory->createInstance(
+ C2U( "com.sun.star.drawing.RectangleShape" )), uno::UNO_QUERY );
+ if( xTarget.is() && xShape.is())
+ {
+ xTarget->add( xShape );
+ ShapeFactory::makeShapeInvisible( xShape );
+ xShape->setSize( rSize );
+ }
+ return xShape;
+ }
+ catch( uno::Exception & ex )
+ {
+ ASSERT_EXCEPTION( ex );
+ }
+ return 0;
+}
+
+uno::Reference< drawing::XShape >
+ ShapeFactory::createText( const uno::Reference< drawing::XShapes >& xTarget
+ , const ::rtl::OUString& rText
+ , const tNameSequence& rPropNames
+ , const tAnySequence& rPropValues
+ , const uno::Any& rATransformation )
+{
+ if( !xTarget.is() )
+ return 0;
+
+ if(!rText.getLength())
+ return 0;
+
+ //create shape and add to page
+ uno::Reference< drawing::XShape > xShape(
+ m_xShapeFactory->createInstance( C2U(
+ "com.sun.star.drawing.TextShape" ) ), uno::UNO_QUERY );
+ xTarget->add(xShape);
+
+ //set text
+ uno::Reference< text::XTextRange > xTextRange( xShape, uno::UNO_QUERY );
+ if( xTextRange.is() )
+ xTextRange->setString( rText );
+
+ uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
+ if( xProp.is() )
+ {
+ //set properties
+ PropertyMapper::setMultiProperties( rPropNames, rPropValues, xProp );
+
+ //set position matrix
+ //the matrix needs to be set at the end behind autogrow and such position influencing properties
+ try
+ {
+ xProp->setPropertyValue( C2U( "Transformation" ), rATransformation );
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+ }
+ return xShape;
+}
+
+//static
+rtl::OUString ShapeFactory::getStackedString( const rtl::OUString& rString, bool bStacked )
+{
+ sal_Int32 nLen = rString.getLength();
+ if(!bStacked || !nLen)
+ return rString;
+
+ rtl::OUStringBuffer aStackStr;
+ rtl::OUStringBuffer aSource(rString);
+
+ //add a newline after each letter
+ //as we do not no letters here add a newline after each char
+ for( sal_Int32 nPosSrc=0; nPosSrc < nLen; nPosSrc++ )
+ {
+ if( nPosSrc )
+ aStackStr.append( sal_Unicode('\r') );
+ aStackStr.append( aSource.charAt( nPosSrc ) );
+ }
+ return aStackStr.makeStringAndClear();
+}
+
+//static
+bool ShapeFactory::hasPolygonAnyLines( drawing::PolyPolygonShape3D& rPoly)
+{
+ // #i67757# check all contained polygons, if at least one polygon contains 2 or more points, return true
+ for( sal_Int32 nIdx = 0, nCount = rPoly.SequenceX.getLength(); nIdx < nCount; ++nIdx )
+ if( rPoly.SequenceX[ nIdx ].getLength() > 1 )
+ return true;
+ return false;
+}
+
+//static
+bool ShapeFactory::isPolygonEmptyOrSinglePoint( drawing::PolyPolygonShape3D& rPoly)
+{
+ // true, if empty polypolygon or one polygon with one point
+ return (rPoly.SequenceX.getLength() == 0) ||
+ ((rPoly.SequenceX.getLength() == 1) && (rPoly.SequenceX[0].getLength() <= 1));
+}
+
+//static
+void ShapeFactory::closePolygon( drawing::PolyPolygonShape3D& rPoly)
+{
+ DBG_ASSERT( rPoly.SequenceX.getLength() <= 1, "ShapeFactory::closePolygon - single polygon expected" );
+ //add a last point == first point
+ if(isPolygonEmptyOrSinglePoint(rPoly))
+ return;
+ drawing::Position3D aFirst(rPoly.SequenceX[0][0],rPoly.SequenceY[0][0],rPoly.SequenceZ[0][0]);
+ AddPointToPoly( rPoly, aFirst );
+}
+
+//static
+awt::Size ShapeFactory::calculateNewSizeRespectingAspectRatio(
+ const awt::Size& rTargetSize
+ , const awt::Size& rSourceSizeWithCorrectAspectRatio )
+{
+ awt::Size aNewSize;
+
+ double fFactorWidth = double(rTargetSize.Width)/double(rSourceSizeWithCorrectAspectRatio.Width);
+ double fFactorHeight = double(rTargetSize.Height)/double(rSourceSizeWithCorrectAspectRatio.Height);
+ double fFactor = std::min(fFactorWidth,fFactorHeight);
+ aNewSize.Width=static_cast<sal_Int32>(fFactor*rSourceSizeWithCorrectAspectRatio.Width);
+ aNewSize.Height=static_cast<sal_Int32>(fFactor*rSourceSizeWithCorrectAspectRatio.Height);
+
+ return aNewSize;
+}
+
+//static
+awt::Point ShapeFactory::calculateTopLeftPositionToCenterObject(
+ const awt::Point& rTargetAreaPosition
+ , const awt::Size& rTargetAreaSize
+ , const awt::Size& rObjectSize )
+{
+ awt::Point aNewPosition(rTargetAreaPosition);
+ aNewPosition.X += static_cast<sal_Int32>(double(rTargetAreaSize.Width-rObjectSize.Width)/2.0);
+ aNewPosition.Y += static_cast<sal_Int32>(double(rTargetAreaSize.Height-rObjectSize.Height)/2.0);
+ return aNewPosition;
+}
+
+//static
+::basegfx::B2IRectangle ShapeFactory::getRectangleOfShape(
+ const uno::Reference< drawing::XShape >& xShape )
+{
+ ::basegfx::B2IRectangle aRet;
+
+ if( xShape.is() )
+ {
+ awt::Point aPos = xShape->getPosition();
+ awt::Size aSize = xShape->getSize();
+ aRet = BaseGFXHelper::makeRectangle(aPos,aSize);
+ }
+ return aRet;
+
+}
+
+//static
+awt::Size ShapeFactory::getSizeAfterRotation(
+ const uno::Reference< drawing::XShape >& xShape, double fRotationAngleDegree )
+{
+ awt::Size aRet(0,0);
+ if(xShape.is())
+ {
+ const awt::Size aSize( xShape->getSize() );
+
+ if( ::rtl::math::approxEqual( fRotationAngleDegree, 0.0 ) )
+ aRet = aSize;
+ else
+ {
+ while(fRotationAngleDegree>=360.0)
+ fRotationAngleDegree-=360.0;
+ while(fRotationAngleDegree<0.0)
+ fRotationAngleDegree+=360.0;
+ if(fRotationAngleDegree>270.0)
+ fRotationAngleDegree=360.0-fRotationAngleDegree;
+ else if(fRotationAngleDegree>180.0)
+ fRotationAngleDegree=fRotationAngleDegree-180.0;
+ else if(fRotationAngleDegree>90.0)
+ fRotationAngleDegree=180.0-fRotationAngleDegree;
+
+ const double fAnglePi = fRotationAngleDegree*F_PI/180.0;
+
+ aRet.Height = static_cast<sal_Int32>(
+ aSize.Width*rtl::math::sin( fAnglePi )
+ + aSize.Height*rtl::math::cos( fAnglePi ));
+ aRet.Width = static_cast<sal_Int32>(
+ aSize.Width*rtl::math::cos( fAnglePi )
+ + aSize.Height*rtl::math::sin( fAnglePi ));
+ }
+ }
+ return aRet;
+}
+
+void ShapeFactory::removeSubShapes( const uno::Reference< drawing::XShapes >& xShapes )
+{
+ if( xShapes.is() )
+ {
+ sal_Int32 nSubCount = xShapes->getCount();
+ uno::Reference< drawing::XShape > xShape;
+ for( sal_Int32 nS = nSubCount; nS--; )
+ {
+ if( xShapes->getByIndex( nS ) >>= xShape )
+ xShapes->remove( xShape );
+ }
+ }
+}
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
diff --git a/chart2/source/view/main/Stripe.cxx b/chart2/source/view/main/Stripe.cxx
new file mode 100644
index 000000000000..2df78e2a8e91
--- /dev/null
+++ b/chart2/source/view/main/Stripe.cxx
@@ -0,0 +1,360 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_chart2.hxx"
+#include "Stripe.hxx"
+#include "CommonConverters.hxx"
+#include <com/sun/star/drawing/PolyPolygonShape3D.hpp>
+#include <com/sun/star/drawing/DoubleSequence.hpp>
+#include <basegfx/polygon/b3dpolygon.hxx>
+#include <basegfx/polygon/b3dpolygontools.hxx>
+
+using namespace ::com::sun::star;
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+
+Stripe::Stripe( const drawing::Position3D& rPoint1
+ , const drawing::Direction3D& rDirectionToPoint2
+ , const drawing::Direction3D& rDirectionToPoint4 )
+ : m_aPoint1(rPoint1)
+ , m_aPoint2(rPoint1+rDirectionToPoint2)
+ , m_aPoint3(m_aPoint2+rDirectionToPoint4)
+ , m_aPoint4(rPoint1+rDirectionToPoint4)
+ , m_bInvertNormal(false)
+ , m_bManualNormalSet(false)
+{
+}
+
+Stripe::Stripe( const drawing::Position3D& rPoint1
+ , const drawing::Position3D& rPoint2
+ , double fDepth )
+ : m_aPoint1(rPoint1)
+ , m_aPoint2(rPoint2)
+ , m_aPoint3(rPoint2)
+ , m_aPoint4(rPoint1)
+ , m_bInvertNormal(false)
+ , m_bManualNormalSet(false)
+{
+ m_aPoint3.PositionZ += fDepth;
+ m_aPoint4.PositionZ += fDepth;
+}
+
+Stripe::Stripe( const drawing::Position3D& rPoint1
+ , const drawing::Position3D& rPoint2
+ , const drawing::Position3D& rPoint3
+ , const drawing::Position3D& rPoint4 )
+ : m_aPoint1(rPoint1)
+ , m_aPoint2(rPoint2)
+ , m_aPoint3(rPoint3)
+ , m_aPoint4(rPoint4)
+ , m_bInvertNormal(false)
+ , m_bManualNormalSet(false)
+{
+}
+
+void Stripe::SetManualNormal( const drawing::Direction3D& rNormal )
+{
+ m_aManualNormal = rNormal;
+ m_bManualNormalSet = true;
+}
+
+void Stripe::InvertNormal( bool bInvertNormal )
+{
+ m_bInvertNormal = bInvertNormal;
+}
+
+uno::Any Stripe::getPolyPolygonShape3D() const
+{
+ drawing::PolyPolygonShape3D aPP;
+
+ aPP.SequenceX.realloc(1);
+ aPP.SequenceY.realloc(1);
+ aPP.SequenceZ.realloc(1);
+
+ drawing::DoubleSequence* pOuterSequenceX = aPP.SequenceX.getArray();
+ drawing::DoubleSequence* pOuterSequenceY = aPP.SequenceY.getArray();
+ drawing::DoubleSequence* pOuterSequenceZ = aPP.SequenceZ.getArray();
+
+ pOuterSequenceX->realloc(4);
+ pOuterSequenceY->realloc(4);
+ pOuterSequenceZ->realloc(4);
+
+ double* pInnerSequenceX = pOuterSequenceX->getArray();
+ double* pInnerSequenceY = pOuterSequenceY->getArray();
+ double* pInnerSequenceZ = pOuterSequenceZ->getArray();
+
+ *pInnerSequenceX++ = m_aPoint1.PositionX;
+ *pInnerSequenceY++ = m_aPoint1.PositionY;
+ *pInnerSequenceZ++ = m_aPoint1.PositionZ;
+
+ *pInnerSequenceX++ = m_aPoint2.PositionX;
+ *pInnerSequenceY++ = m_aPoint2.PositionY;
+ *pInnerSequenceZ++ = m_aPoint2.PositionZ;
+
+ *pInnerSequenceX++ = m_aPoint3.PositionX;
+ *pInnerSequenceY++ = m_aPoint3.PositionY;
+ *pInnerSequenceZ++ = m_aPoint3.PositionZ;
+
+ *pInnerSequenceX++ = m_aPoint4.PositionX;
+ *pInnerSequenceY++ = m_aPoint4.PositionY;
+ *pInnerSequenceZ++ = m_aPoint4.PositionZ;
+
+ return uno::Any( &aPP, ::getCppuType((const drawing::PolyPolygonShape3D*)0) );
+}
+
+drawing::Direction3D Stripe::getNormal() const
+{
+ drawing::Direction3D aRet(1.0,0.0,0.0);
+
+ if( m_bManualNormalSet )
+ aRet = m_aManualNormal;
+ else
+ {
+ ::basegfx::B3DPolygon aPolygon3D;
+ aPolygon3D.append(Position3DToB3DPoint( m_aPoint1 ));
+ aPolygon3D.append(Position3DToB3DPoint( m_aPoint2 ));
+ aPolygon3D.append(Position3DToB3DPoint( m_aPoint3 ));
+ aPolygon3D.append(Position3DToB3DPoint( m_aPoint4 ));
+ ::basegfx::B3DVector aNormal(::basegfx::tools::getNormal(aPolygon3D));
+ aRet = B3DVectorToDirection3D(aNormal);
+ }
+
+ if( m_bInvertNormal )
+ {
+ aRet.DirectionX *= -1.0;
+ aRet.DirectionY *= -1.0;
+ aRet.DirectionZ *= -1.0;
+ }
+ return aRet;
+}
+
+uno::Any Stripe::getNormalsPolygon() const
+{
+ drawing::PolyPolygonShape3D aPP;
+
+ aPP.SequenceX.realloc(1);
+ aPP.SequenceY.realloc(1);
+ aPP.SequenceZ.realloc(1);
+
+ drawing::DoubleSequence* pOuterSequenceX = aPP.SequenceX.getArray();
+ drawing::DoubleSequence* pOuterSequenceY = aPP.SequenceY.getArray();
+ drawing::DoubleSequence* pOuterSequenceZ = aPP.SequenceZ.getArray();
+
+ pOuterSequenceX->realloc(4);
+ pOuterSequenceY->realloc(4);
+ pOuterSequenceZ->realloc(4);
+
+ double* pInnerSequenceX = pOuterSequenceX->getArray();
+ double* pInnerSequenceY = pOuterSequenceY->getArray();
+ double* pInnerSequenceZ = pOuterSequenceZ->getArray();
+
+ drawing::Direction3D aNormal( getNormal() );
+
+ for(sal_Int32 nN=4; --nN; )
+ {
+ *pInnerSequenceX++ = aNormal.DirectionX;
+ *pInnerSequenceY++ = aNormal.DirectionY;
+ *pInnerSequenceZ++ = aNormal.DirectionZ;
+ }
+ return uno::Any( &aPP, ::getCppuType((const drawing::PolyPolygonShape3D*)0) );
+}
+
+uno::Any Stripe::getTexturePolygon( short nRotatedTexture ) const
+{
+ drawing::PolyPolygonShape3D aPP;
+
+ aPP.SequenceX.realloc(1);
+ aPP.SequenceY.realloc(1);
+ aPP.SequenceZ.realloc(1);
+
+ drawing::DoubleSequence* pOuterSequenceX = aPP.SequenceX.getArray();
+ drawing::DoubleSequence* pOuterSequenceY = aPP.SequenceY.getArray();
+ drawing::DoubleSequence* pOuterSequenceZ = aPP.SequenceZ.getArray();
+
+ pOuterSequenceX->realloc(4);
+ pOuterSequenceY->realloc(4);
+ pOuterSequenceZ->realloc(4);
+
+ double* pInnerSequenceX = pOuterSequenceX->getArray();
+ double* pInnerSequenceY = pOuterSequenceY->getArray();
+ double* pInnerSequenceZ = pOuterSequenceZ->getArray();
+
+ if( nRotatedTexture==0 )
+ {
+ *pInnerSequenceX++ = 0.0;
+ *pInnerSequenceY++ = 0.0;
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceX++ = 0.0;
+ *pInnerSequenceY++ = 1.0;
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceX++ = 1.0;
+ *pInnerSequenceY++ = 1.0;
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceX++ = 1.0;
+ *pInnerSequenceY++ = 0.0;
+ *pInnerSequenceZ++ = 0.0;
+ }
+ else if( nRotatedTexture==1 )
+ {
+ *pInnerSequenceX++ = 1.0;
+ *pInnerSequenceY++ = 0.0;
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceX++ = 0.0;
+ *pInnerSequenceY++ = 0.0;
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceX++ = 0.0;
+ *pInnerSequenceY++ = 1.0;
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceX++ = 1.0;
+ *pInnerSequenceY++ = 1.0;
+ *pInnerSequenceZ++ = 0.0;
+ }
+ else if( nRotatedTexture==2 )
+ {
+ *pInnerSequenceX++ = 1.0;
+ *pInnerSequenceY++ = 1.0;
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceX++ = 1.0;
+ *pInnerSequenceY++ = 0.0;
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceX++ = 0.0;
+ *pInnerSequenceY++ = 0.0;
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceX++ = 0.0;
+ *pInnerSequenceY++ = 1.0;
+ *pInnerSequenceZ++ = 0.0;
+ }
+ else if( nRotatedTexture==3 )
+ {
+ *pInnerSequenceX++ = 0.0;
+ *pInnerSequenceY++ = 1.0;
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceX++ = 1.0;
+ *pInnerSequenceY++ = 1.0;
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceX++ = 1.0;
+ *pInnerSequenceY++ = 0.0;
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceX++ = 0.0;
+ *pInnerSequenceY++ = 0.0;
+ *pInnerSequenceZ++ = 0.0;
+ }
+ else if( nRotatedTexture==4 )
+ {
+ *pInnerSequenceX++ = 1.0;
+ *pInnerSequenceY++ = 0.0;
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceX++ = 1.0;
+ *pInnerSequenceY++ = 1.0;
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceX++ = 0.0;
+ *pInnerSequenceY++ = 1.0;
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceX++ = 0.0;
+ *pInnerSequenceY++ = 0.0;
+ *pInnerSequenceZ++ = 0.0;
+ }
+ else if( nRotatedTexture==5 )
+ {
+ *pInnerSequenceX++ = 0.0;
+ *pInnerSequenceY++ = 0.0;
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceX++ = 1.0;
+ *pInnerSequenceY++ = 0.0;
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceX++ = 1.0;
+ *pInnerSequenceY++ = 1.0;
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceX++ = 0.0;
+ *pInnerSequenceY++ = 1.0;
+ *pInnerSequenceZ++ = 0.0;
+ }
+ else if( nRotatedTexture==6 )
+ {
+ *pInnerSequenceX++ = 0.0;
+ *pInnerSequenceY++ = 1.0;
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceX++ = 0.0;
+ *pInnerSequenceY++ = 0.0;
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceX++ = 1.0;
+ *pInnerSequenceY++ = 0.0;
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceX++ = 1.0;
+ *pInnerSequenceY++ = 1.0;
+ *pInnerSequenceZ++ = 0.0;
+ }
+ else if( nRotatedTexture==7 )
+ {
+ *pInnerSequenceX++ = 1.0;
+ *pInnerSequenceY++ = 1.0;
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceX++ = 0.0;
+ *pInnerSequenceY++ = 1.0;
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceX++ = 0.0;
+ *pInnerSequenceY++ = 0.0;
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceX++ = 1.0;
+ *pInnerSequenceY++ = 0.0;
+ *pInnerSequenceZ++ = 0.0;
+ }
+
+ return uno::Any( &aPP, ::getCppuType((const drawing::PolyPolygonShape3D*)0) );
+}
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
diff --git a/chart2/source/view/main/VDataSeries.cxx b/chart2/source/view/main/VDataSeries.cxx
new file mode 100644
index 000000000000..8bb6a11b4baf
--- /dev/null
+++ b/chart2/source/view/main/VDataSeries.cxx
@@ -0,0 +1,986 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_chart2.hxx"
+#include "VDataSeries.hxx"
+#include "ObjectIdentifier.hxx"
+#include "macros.hxx"
+#include "CommonConverters.hxx"
+#include "LabelPositionHelper.hxx"
+#include "ChartTypeHelper.hxx"
+#include "ContainerHelper.hxx"
+#include "DataSeriesHelper.hxx"
+#include "RegressionCurveHelper.hxx"
+
+#include <com/sun/star/chart/MissingValueTreatment.hpp>
+#include <com/sun/star/chart2/Symbol.hpp>
+
+//#include "CommonConverters.hxx"
+#include <rtl/math.hxx>
+#include <tools/debug.hxx>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/XPropertyState.hpp>
+#include <com/sun/star/drawing/LineStyle.hpp>
+#include <com/sun/star/drawing/TextVerticalAdjust.hpp>
+#include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
+#include <com/sun/star/text/WritingMode.hpp>
+#include <com/sun/star/chart2/data/XDataSource.hpp>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+using ::com::sun::star::uno::Reference;
+
+void VDataSequence::init( const uno::Reference< data::XDataSequence >& xModel )
+{
+ Model = xModel;
+ Doubles = DataSequenceToDoubleSequence( xModel );
+}
+
+bool VDataSequence::is() const
+{
+ return Model.is();
+}
+void VDataSequence::clear()
+{
+ Model = NULL;
+ Doubles.realloc(0);
+}
+
+double VDataSequence::getValue( sal_Int32 index ) const
+{
+ if( 0<=index && index<Doubles.getLength() )
+ return Doubles[index];
+ else
+ {
+ double fNan;
+ ::rtl::math::setNan( & fNan );
+ return fNan;
+ }
+}
+
+sal_Int32 VDataSequence::detectNumberFormatKey( sal_Int32 index ) const
+{
+ sal_Int32 nNumberFormatKey = -1;
+
+ // -1 is allowed and means a key for the whole sequence
+ if( -1<=index && index<Doubles.getLength() &&
+ Model.is())
+ {
+ nNumberFormatKey = Model->getNumberFormatKeyByIndex( index );
+ }
+
+ return nNumberFormatKey;
+}
+
+sal_Int32 VDataSequence::getLength() const
+{
+ return Doubles.getLength();
+}
+
+namespace
+{
+struct lcl_LessXOfPoint
+{
+ inline bool operator() ( const std::vector< double >& first,
+ const std::vector< double >& second )
+ {
+ if( first.size() > 0 && second.size() > 0 )
+ {
+ return first[0]<second[0];
+ }
+ return false;
+ }
+};
+
+void lcl_clearIfNoValuesButTextIsContained( VDataSequence& rData, const uno::Reference<data::XDataSequence>& xDataSequence )
+{
+ //#i71686#, #i101968#, #i102428#
+ sal_Int32 nCount = rData.Doubles.getLength();
+ for( sal_Int32 i = 0; i < nCount; ++i )
+ {
+ if( !::rtl::math::isNan( rData.Doubles[i] ) )
+ return;
+ }
+ //no double value is countained
+ //is there any text?
+ uno::Sequence< rtl::OUString > aStrings( DataSequenceToStringSequence( xDataSequence ) );
+ sal_Int32 nTextCount = aStrings.getLength();
+ for( sal_Int32 j = 0; j < nTextCount; ++j )
+ {
+ if( aStrings[j].getLength() )
+ {
+ rData.clear();
+ return;
+ }
+ }
+ //no content at all
+}
+
+void lcl_maybeReplaceNanWithZero( double& rfValue, sal_Int32 nMissingValueTreatment )
+{
+ if( nMissingValueTreatment == ::com::sun::star::chart::MissingValueTreatment::USE_ZERO
+ && (::rtl::math::isNan(rfValue) || ::rtl::math::isInf(rfValue)) )
+ rfValue = 0.0;
+}
+
+}
+
+VDataSeries::VDataSeries( const uno::Reference< XDataSeries >& xDataSeries )
+ : m_nPolygonIndex(0)
+ , m_fLogicMinX(0.0)
+ , m_fLogicMaxX(0.0)
+ , m_fLogicZPos(0.0)
+ , m_xGroupShape(NULL)
+ , m_xLabelsGroupShape(NULL)
+ , m_xErrorBarsGroupShape(NULL)
+ , m_xFrontSubGroupShape(NULL)
+ , m_xBackSubGroupShape(NULL)
+ , m_xDataSeries(xDataSeries)
+ , m_aDataSequences()
+ , m_nPointCount(0)
+
+ , m_aValues_X()
+ , m_aValues_Y()
+ , m_aValues_Z()
+ , m_aValues_Y_Min()
+ , m_aValues_Y_Max()
+ , m_aValues_Y_First()
+ , m_aValues_Y_Last()
+ , m_aValues_Bubble_Size()
+ , m_pValueSequenceForDataLabelNumberFormatDetection(&m_aValues_Y)
+
+ , m_fYMeanValue(1.0)
+
+ , m_aAttributedDataPointIndexList()
+
+ , m_eStackingDirection(StackingDirection_NO_STACKING)
+ , m_nAxisIndex(0)
+ , m_bConnectBars(sal_False)
+ , m_bGroupBarsPerAxis(sal_True)
+ , m_nStartingAngle(90)
+
+ , m_aSeriesParticle()
+ , m_aCID()
+ , m_aPointCID_Stub()
+ , m_aLabelCID_Stub()
+
+ , m_nGlobalSeriesIndex(0)
+
+ , m_apLabel_Series(NULL)
+ , m_apLabelPropNames_Series(NULL)
+ , m_apLabelPropValues_Series(NULL)
+ , m_apSymbolProperties_Series(NULL)
+
+ , m_apLabel_AttributedPoint(NULL)
+ , m_apLabelPropNames_AttributedPoint(NULL)
+ , m_apLabelPropValues_AttributedPoint(NULL)
+ , m_apSymbolProperties_AttributedPoint(NULL)
+ , m_apSymbolProperties_InvisibleSymbolForSelection(NULL)
+ , m_nCurrentAttributedPoint(-1)
+ , m_nMissingValueTreatment(::com::sun::star::chart::MissingValueTreatment::LEAVE_GAP)
+ , m_bAllowPercentValueInDataLabel(false)
+{
+ ::rtl::math::setNan( & m_fYMeanValue );
+
+ uno::Reference<data::XDataSource> xDataSource =
+ uno::Reference<data::XDataSource>( xDataSeries, uno::UNO_QUERY );
+
+ m_aDataSequences = xDataSource->getDataSequences();
+
+ for(sal_Int32 nN = m_aDataSequences.getLength();nN--;)
+ {
+ if(!m_aDataSequences[nN].is())
+ continue;
+ uno::Reference<data::XDataSequence> xDataSequence( m_aDataSequences[nN]->getValues());
+ uno::Reference<beans::XPropertySet> xProp(xDataSequence, uno::UNO_QUERY );
+ if( xProp.is())
+ {
+ try
+ {
+ uno::Any aARole = xProp->getPropertyValue( C2U( "Role" ) );
+ rtl::OUString aRole;
+ aARole >>= aRole;
+
+ if( aRole.equals(C2U("values-x")) )
+ {
+ m_aValues_X.init( xDataSequence );
+ lcl_clearIfNoValuesButTextIsContained( m_aValues_X, xDataSequence );
+ }
+ else if( aRole.equals(C2U("values-y")) )
+ m_aValues_Y.init( xDataSequence );
+ else if( aRole.equals(C2U("values-min")) )
+ m_aValues_Y_Min.init( xDataSequence );
+ else if( aRole.equals(C2U("values-max")) )
+ m_aValues_Y_Max.init( xDataSequence );
+ else if( aRole.equals(C2U("values-first")) )
+ m_aValues_Y_First.init( xDataSequence );
+ else if( aRole.equals(C2U("values-last")) )
+ m_aValues_Y_Last.init( xDataSequence );
+ else if( aRole.equals(C2U("values-size")) )
+ m_aValues_Bubble_Size.init( xDataSequence );
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+ }
+ }
+
+ //determine the point count
+ m_nPointCount = m_aValues_Y.getLength();
+ {
+ if( m_nPointCount < m_aValues_Bubble_Size.getLength() )
+ m_nPointCount = m_aValues_Bubble_Size.getLength();
+ if( m_nPointCount < m_aValues_Y_Min.getLength() )
+ m_nPointCount = m_aValues_Y_Min.getLength();
+ if( m_nPointCount < m_aValues_Y_Max.getLength() )
+ m_nPointCount = m_aValues_Y_Max.getLength();
+ if( m_nPointCount < m_aValues_Y_First.getLength() )
+ m_nPointCount = m_aValues_Y_First.getLength();
+ if( m_nPointCount < m_aValues_Y_Last.getLength() )
+ m_nPointCount = m_aValues_Y_Last.getLength();
+ }
+
+ uno::Reference<beans::XPropertySet> xProp(xDataSeries, uno::UNO_QUERY );
+ if( xProp.is())
+ {
+ try
+ {
+ //get AttributedDataPoints
+ xProp->getPropertyValue( C2U( "AttributedDataPoints" ) ) >>= m_aAttributedDataPointIndexList;
+
+ xProp->getPropertyValue( C2U( "StackingDirection" ) ) >>= m_eStackingDirection;
+
+ xProp->getPropertyValue( C2U( "AttachedAxisIndex" ) ) >>= m_nAxisIndex;
+ if(m_nAxisIndex<0)
+ m_nAxisIndex=0;
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+ }
+}
+
+VDataSeries::~VDataSeries()
+{
+}
+
+void VDataSeries::doSortByXValues()
+{
+ if( m_aValues_X.is() && m_aValues_X.Doubles.getLength() )
+ {
+ //prepare a vector vor sorting
+ std::vector< ::std::vector< double > > aTmp;//outer vector are points, inner vector are the different values of athe point
+ double fNan;
+ ::rtl::math::setNan( & fNan );
+ sal_Int32 nPointIndex = 0;
+ for( nPointIndex=0; nPointIndex < m_nPointCount; nPointIndex++ )
+ {
+ std::vector< double > aSinglePoint;
+ aSinglePoint.push_back( (nPointIndex < m_aValues_X.Doubles.getLength()) ? m_aValues_X.Doubles[nPointIndex] : fNan );
+ aSinglePoint.push_back( (nPointIndex < m_aValues_Y.Doubles.getLength()) ? m_aValues_Y.Doubles[nPointIndex] : fNan );
+ aTmp.push_back( aSinglePoint );
+ }
+
+ //do sort
+ std::sort( aTmp.begin(), aTmp.end(), lcl_LessXOfPoint() );
+
+ //fill the sorted points back to the mambers
+ m_aValues_X.Doubles.realloc( m_nPointCount );
+ m_aValues_Y.Doubles.realloc( m_nPointCount );
+
+ for( nPointIndex=0; nPointIndex < m_nPointCount; nPointIndex++ )
+ {
+ m_aValues_X.Doubles[nPointIndex]=aTmp[nPointIndex][0];
+ m_aValues_Y.Doubles[nPointIndex]=aTmp[nPointIndex][1];
+ }
+ }
+}
+
+uno::Reference< XDataSeries > VDataSeries::getModel() const
+{
+ return m_xDataSeries;
+}
+
+void VDataSeries::releaseShapes()
+{
+ m_xGroupShape.set(0);
+ m_xLabelsGroupShape.set(0);
+ m_xErrorBarsGroupShape.set(0);
+ m_xFrontSubGroupShape.set(0);
+ m_xBackSubGroupShape.set(0);
+
+ m_aPolyPolygonShape3D.SequenceX.realloc(0);
+ m_aPolyPolygonShape3D.SequenceY.realloc(0);
+ m_aPolyPolygonShape3D.SequenceZ.realloc(0);
+ m_nPolygonIndex = 0;
+}
+
+void VDataSeries::setCategoryXAxis()
+{
+ m_aValues_X.clear();
+ m_bAllowPercentValueInDataLabel = true;
+}
+
+void VDataSeries::setGlobalSeriesIndex( sal_Int32 nGlobalSeriesIndex )
+{
+ m_nGlobalSeriesIndex = nGlobalSeriesIndex;
+}
+
+void VDataSeries::setParticle( const rtl::OUString& rSeriesParticle )
+{
+ m_aSeriesParticle = rSeriesParticle;
+
+ //get CID
+ m_aCID = ObjectIdentifier::createClassifiedIdentifierForParticle( m_aSeriesParticle );
+ m_aPointCID_Stub = ObjectIdentifier::createSeriesSubObjectStub( OBJECTTYPE_DATA_POINT, m_aSeriesParticle );
+
+ m_aLabelCID_Stub = ObjectIdentifier::createClassifiedIdentifierWithParent(
+ OBJECTTYPE_DATA_LABEL, ::rtl::OUString(), getLabelsCID() );
+}
+rtl::OUString VDataSeries::getSeriesParticle() const
+{
+ return m_aSeriesParticle;
+}
+rtl::OUString VDataSeries::getCID() const
+{
+ return m_aCID;
+}
+rtl::OUString VDataSeries::getPointCID_Stub() const
+{
+ return m_aPointCID_Stub;
+}
+rtl::OUString VDataSeries::getErrorBarsCID() const
+{
+ rtl::OUString aChildParticle( ObjectIdentifier::getStringForType( OBJECTTYPE_DATA_ERRORS ) );
+ aChildParticle+=(C2U("="));
+
+ return ObjectIdentifier::createClassifiedIdentifierForParticles(
+ m_aSeriesParticle, aChildParticle );
+}
+rtl::OUString VDataSeries::getLabelsCID() const
+{
+ rtl::OUString aChildParticle( ObjectIdentifier::getStringForType( OBJECTTYPE_DATA_LABELS ) );
+ aChildParticle+=(C2U("="));
+
+ return ObjectIdentifier::createClassifiedIdentifierForParticles(
+ m_aSeriesParticle, aChildParticle );
+}
+rtl::OUString VDataSeries::getLabelCID_Stub() const
+{
+ return m_aLabelCID_Stub;
+}
+rtl::OUString VDataSeries::getDataCurveCID( sal_Int32 nCurveIndex, bool bAverageLine ) const
+{
+ rtl::OUString aRet;
+ aRet = ObjectIdentifier::createDataCurveCID( m_aSeriesParticle, nCurveIndex, bAverageLine );
+ return aRet;
+}
+
+rtl::OUString VDataSeries::getDataCurveEquationCID( sal_Int32 nCurveIndex ) const
+{
+ rtl::OUString aRet;
+ aRet = ObjectIdentifier::createDataCurveEquationCID( m_aSeriesParticle, nCurveIndex );
+ return aRet;
+}
+void VDataSeries::setPageReferenceSize( const awt::Size & rPageRefSize )
+{
+ m_aReferenceSize = rPageRefSize;
+}
+
+StackingDirection VDataSeries::getStackingDirection() const
+{
+ return m_eStackingDirection;
+}
+sal_Int32 VDataSeries::getAttachedAxisIndex() const
+{
+ return m_nAxisIndex;
+}
+void VDataSeries::setConnectBars( sal_Bool bConnectBars )
+{
+ m_bConnectBars = bConnectBars;
+}
+sal_Bool VDataSeries::getConnectBars() const
+{
+ return m_bConnectBars;
+}
+void VDataSeries::setGroupBarsPerAxis( sal_Bool bGroupBarsPerAxis )
+{
+ m_bGroupBarsPerAxis = bGroupBarsPerAxis;
+}
+sal_Bool VDataSeries::getGroupBarsPerAxis() const
+{
+ return m_bGroupBarsPerAxis;
+}
+
+void VDataSeries::setStartingAngle( sal_Int32 nStartingAngle )
+{
+ m_nStartingAngle = nStartingAngle;
+}
+sal_Int32 VDataSeries::getStartingAngle() const
+{
+ return m_nStartingAngle;
+}
+
+void VDataSeries::setAttachedAxisIndex( sal_Int32 nAttachedAxisIndex )
+{
+ if( nAttachedAxisIndex < 0 )
+ nAttachedAxisIndex = 0;
+ m_nAxisIndex = nAttachedAxisIndex;
+}
+
+sal_Int32 VDataSeries::getTotalPointCount() const
+{
+ return m_nPointCount;
+}
+
+double VDataSeries::getXValue( sal_Int32 index ) const
+{
+ double fRet = 0.0;
+ if(m_aValues_X.is())
+ {
+ if( 0<=index && index<m_aValues_X.getLength() )
+ fRet = m_aValues_X.Doubles[index];
+ else
+ ::rtl::math::setNan( &fRet );
+ }
+ else
+ {
+ // #i70133# always return correct X position - needed for short data series
+ if( 0<=index /*&& index < m_nPointCount*/ )
+ fRet = index+1;//first category (index 0) matches with real number 1.0
+ else
+ ::rtl::math::setNan( &fRet );
+ }
+ lcl_maybeReplaceNanWithZero( fRet, getMissingValueTreatment() );
+ return fRet;
+}
+
+double VDataSeries::getYValue( sal_Int32 index ) const
+{
+ double fRet = 0.0;
+ if(m_aValues_Y.is())
+ {
+ if( 0<=index && index<m_aValues_Y.getLength() )
+ fRet = m_aValues_Y.Doubles[index];
+ else
+ ::rtl::math::setNan( &fRet );
+ }
+ else
+ {
+ // #i70133# always return correct X position - needed for short data series
+ if( 0<=index /*&& index < m_nPointCount*/ )
+ fRet = index+1;//first category (index 0) matches with real number 1.0
+ else
+ ::rtl::math::setNan( &fRet );
+ }
+ lcl_maybeReplaceNanWithZero( fRet, getMissingValueTreatment() );
+ return fRet;
+}
+
+double VDataSeries::getY_Min( sal_Int32 index ) const
+{
+ return m_aValues_Y_Min.getValue( index );
+}
+double VDataSeries::getY_Max( sal_Int32 index ) const
+{
+ return m_aValues_Y_Max.getValue( index );
+}
+double VDataSeries::getY_First( sal_Int32 index ) const
+{
+ return m_aValues_Y_First.getValue( index );
+}
+double VDataSeries::getY_Last( sal_Int32 index ) const
+{
+ return m_aValues_Y_Last.getValue( index );
+}
+double VDataSeries::getBubble_Size( sal_Int32 index ) const
+{
+ return m_aValues_Bubble_Size.getValue( index );
+}
+
+bool VDataSeries::hasExplicitNumberFormat( sal_Int32 nPointIndex, bool bForPercentage ) const
+{
+ rtl::OUString aPropName( bForPercentage ? C2U( "PercentageNumberFormat" ) : C2U( "NumberFormat" ) );
+ bool bHasNumberFormat = false;
+ uno::Reference< beans::XPropertySet > xPointProp( this->getPropertiesOfPoint( nPointIndex ));
+ sal_Int32 nNumberFormat = -1;
+ if( xPointProp.is() && (xPointProp->getPropertyValue(aPropName) >>= nNumberFormat) )
+ bHasNumberFormat = true;
+ return bHasNumberFormat;
+}
+sal_Int32 VDataSeries::getExplicitNumberFormat( sal_Int32 nPointIndex, bool bForPercentage ) const
+{
+ rtl::OUString aPropName( bForPercentage ? C2U( "PercentageNumberFormat" ) : C2U( "NumberFormat" ) );
+ sal_Int32 nNumberFormat = -1;
+ uno::Reference< beans::XPropertySet > xPointProp( this->getPropertiesOfPoint( nPointIndex ));
+ if( xPointProp.is() )
+ xPointProp->getPropertyValue(aPropName) >>= nNumberFormat;
+ return nNumberFormat;
+}
+void VDataSeries::setRoleOfSequenceForDataLabelNumberFormatDetection( const rtl::OUString& rRole )
+{
+ if( rRole.equals(C2U("values-y")) )
+ m_pValueSequenceForDataLabelNumberFormatDetection = &m_aValues_Y;
+ else if( rRole.equals(C2U("values-size")) )
+ m_pValueSequenceForDataLabelNumberFormatDetection = &m_aValues_Bubble_Size;
+ else if( rRole.equals(C2U("values-min")) )
+ m_pValueSequenceForDataLabelNumberFormatDetection = &m_aValues_Y_Min;
+ else if( rRole.equals(C2U("values-max")) )
+ m_pValueSequenceForDataLabelNumberFormatDetection = &m_aValues_Y_Max;
+ else if( rRole.equals(C2U("values-first")) )
+ m_pValueSequenceForDataLabelNumberFormatDetection = &m_aValues_Y_First;
+ else if( rRole.equals(C2U("values-last")) )
+ m_pValueSequenceForDataLabelNumberFormatDetection = &m_aValues_Y_Last;
+ else if( rRole.equals(C2U("values-x")) )
+ m_pValueSequenceForDataLabelNumberFormatDetection = &m_aValues_X;
+}
+bool VDataSeries::shouldLabelNumberFormatKeyBeDetectedFromYAxis() const
+{
+ if( m_pValueSequenceForDataLabelNumberFormatDetection == &m_aValues_Bubble_Size )
+ return false;
+ else if( m_pValueSequenceForDataLabelNumberFormatDetection == &m_aValues_X )
+ return false;
+ return true;
+}
+sal_Int32 VDataSeries::detectNumberFormatKey( sal_Int32 index ) const
+{
+ sal_Int32 nRet = 0;
+ if( m_pValueSequenceForDataLabelNumberFormatDetection )
+ nRet = m_pValueSequenceForDataLabelNumberFormatDetection->detectNumberFormatKey( index );
+ return nRet;
+}
+
+sal_Int32 VDataSeries::getLabelPlacement( sal_Int32 nPointIndex, const uno::Reference< chart2::XChartType >& xChartType, sal_Int32 nDimensionCount, sal_Bool bSwapXAndY ) const
+{
+ sal_Int32 nLabelPlacement=0;
+ try
+ {
+ uno::Reference< beans::XPropertySet > xPointProps( this->getPropertiesOfPoint( nPointIndex ) );
+ if( xPointProps.is() )
+ xPointProps->getPropertyValue( C2U( "LabelPlacement" ) ) >>= nLabelPlacement;
+
+ //ensure that the set label placement is supported by this charttype
+
+ uno::Sequence < sal_Int32 > aAvailablePlacements( ChartTypeHelper::getSupportedLabelPlacements(
+ xChartType, nDimensionCount, bSwapXAndY, m_xDataSeries ) );
+
+ for( sal_Int32 nN = 0; nN < aAvailablePlacements.getLength(); nN++ )
+ if( aAvailablePlacements[nN] == nLabelPlacement )
+ return nLabelPlacement; //ok
+
+ //otherwise use the first supported one
+ if( aAvailablePlacements.getLength() )
+ {
+ nLabelPlacement = aAvailablePlacements[0];
+ return nLabelPlacement;
+ }
+
+ DBG_ERROR("no label placement supported");
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+ return nLabelPlacement;
+}
+
+double VDataSeries::getMinimumofAllDifferentYValues( sal_Int32 index ) const
+{
+ double fMin=0.0;
+ ::rtl::math::setInf(&fMin, false);
+
+ if( !m_aValues_Y.is() &&
+ (m_aValues_Y_Min.is() || m_aValues_Y_Max.is()
+ || m_aValues_Y_First.is() || m_aValues_Y_Last.is() ) )
+ {
+ double fY_Min = getY_Min( index );
+ double fY_Max = getY_Max( index );
+ double fY_First = getY_First( index );
+ double fY_Last = getY_Last( index );
+
+ if(fMin>fY_First)
+ fMin=fY_First;
+ if(fMin>fY_Last)
+ fMin=fY_Last;
+ if(fMin>fY_Min)
+ fMin=fY_Min;
+ if(fMin>fY_Max)
+ fMin=fY_Max;
+ }
+ else
+ {
+ double fY = getYValue( index );
+ if(fMin>fY)
+ fMin=fY;
+ }
+
+ if( ::rtl::math::isInf(fMin) )
+ ::rtl::math::setNan(&fMin);
+
+ return fMin;
+}
+
+double VDataSeries::getMaximumofAllDifferentYValues( sal_Int32 index ) const
+{
+ double fMax=0.0;
+ ::rtl::math::setInf(&fMax, true);
+
+ if( !m_aValues_Y.is() &&
+ (m_aValues_Y_Min.is() || m_aValues_Y_Max.is()
+ || m_aValues_Y_First.is() || m_aValues_Y_Last.is() ) )
+ {
+ double fY_Min = getY_Min( index );
+ double fY_Max = getY_Max( index );
+ double fY_First = getY_First( index );
+ double fY_Last = getY_Last( index );
+
+ if(fMax<fY_First)
+ fMax=fY_First;
+ if(fMax<fY_Last)
+ fMax=fY_Last;
+ if(fMax<fY_Min)
+ fMax=fY_Min;
+ if(fMax<fY_Max)
+ fMax=fY_Max;
+ }
+ else
+ {
+ double fY = getYValue( index );
+ if(fMax<fY)
+ fMax=fY;
+ }
+
+ if( ::rtl::math::isInf(fMax) )
+ ::rtl::math::setNan(&fMax);
+
+ return fMax;
+}
+
+uno::Sequence< double > VDataSeries::getAllX() const
+{
+ if(!m_aValues_X.is() && !m_aValues_X.getLength() && m_nPointCount)
+ {
+ //init x values from category indexes
+ //first category (index 0) matches with real number 1.0
+ m_aValues_X.Doubles.realloc( m_nPointCount );
+ for(sal_Int32 nN=m_aValues_X.getLength();nN--;)
+ m_aValues_X.Doubles[nN] = nN+1;
+ }
+ return m_aValues_X.Doubles;
+}
+
+uno::Sequence< double > VDataSeries::getAllY() const
+{
+ if(!m_aValues_Y.is() && !m_aValues_Y.getLength() && m_nPointCount)
+ {
+ //init y values from indexes
+ //first y-value (index 0) matches with real number 1.0
+ m_aValues_Y.Doubles.realloc( m_nPointCount );
+ for(sal_Int32 nN=m_aValues_Y.getLength();nN--;)
+ m_aValues_Y.Doubles[nN] = nN+1;
+ }
+ return m_aValues_Y.Doubles;
+}
+
+double VDataSeries::getYMeanValue() const
+{
+ if( ::rtl::math::isNan( m_fYMeanValue ) )
+ {
+ uno::Reference< XRegressionCurveCalculator > xCalculator( RegressionCurveHelper::createRegressionCurveCalculatorByServiceName( C2U("com.sun.star.chart2.MeanValueRegressionCurve") ) );
+ uno::Sequence< double > aXValuesDummy;
+ xCalculator->recalculateRegression( aXValuesDummy, getAllY() );
+ double fXDummy = 1.0;
+ m_fYMeanValue = xCalculator->getCurveValue( fXDummy );
+ }
+ return m_fYMeanValue;
+}
+
+::std::auto_ptr< Symbol > getSymbolPropertiesFromPropertySet(
+ const uno::Reference< beans::XPropertySet >& xProp )
+{
+ ::std::auto_ptr< Symbol > apSymbolProps( new Symbol() );
+ try
+ {
+ if( xProp->getPropertyValue( C2U( "Symbol" ) ) >>= *apSymbolProps )
+ {
+ //use main color to fill symbols
+ xProp->getPropertyValue( C2U( "Color" ) ) >>= apSymbolProps->FillColor;
+ // border of symbols always same as fill color
+ apSymbolProps->BorderColor = apSymbolProps->FillColor;
+ }
+ else
+ apSymbolProps.reset();
+ }
+ catch( uno::Exception &e)
+ {
+ ASSERT_EXCEPTION( e );
+ }
+ return apSymbolProps;
+}
+
+Symbol* VDataSeries::getSymbolProperties( sal_Int32 index ) const
+{
+ Symbol* pRet=NULL;
+ if( isAttributedDataPoint( index ) )
+ {
+ adaptPointCache( index );
+ if(!m_apSymbolProperties_AttributedPoint.get())
+ m_apSymbolProperties_AttributedPoint = getSymbolPropertiesFromPropertySet( this->getPropertiesOfPoint( index ) );
+ pRet = m_apSymbolProperties_AttributedPoint.get();
+ //if a single data point does not have symbols but the dataseries itself has symbols
+ //we create an invisible symbol shape to enable selection of that point
+ if( !pRet || pRet->Style == SymbolStyle_NONE )
+ {
+ if(!m_apSymbolProperties_Series.get())
+ m_apSymbolProperties_Series = getSymbolPropertiesFromPropertySet( this->getPropertiesOfSeries() );
+ if( m_apSymbolProperties_Series.get() && m_apSymbolProperties_Series->Style != SymbolStyle_NONE )
+ {
+ if(!m_apSymbolProperties_InvisibleSymbolForSelection.get())
+ {
+ m_apSymbolProperties_InvisibleSymbolForSelection = ::std::auto_ptr< Symbol >( new Symbol() );
+ m_apSymbolProperties_InvisibleSymbolForSelection->Style = SymbolStyle_STANDARD;
+ m_apSymbolProperties_InvisibleSymbolForSelection->StandardSymbol = 0;//square
+ m_apSymbolProperties_InvisibleSymbolForSelection->Size = m_apSymbolProperties_Series->Size;
+ m_apSymbolProperties_InvisibleSymbolForSelection->BorderColor = 0xff000000;//invisible
+ m_apSymbolProperties_InvisibleSymbolForSelection->FillColor = 0xff000000;//invisible
+ }
+ pRet = m_apSymbolProperties_InvisibleSymbolForSelection.get();
+ }
+ }
+ }
+ else
+ {
+ if(!m_apSymbolProperties_Series.get())
+ m_apSymbolProperties_Series = getSymbolPropertiesFromPropertySet( this->getPropertiesOfSeries() );
+ pRet = m_apSymbolProperties_Series.get();
+ }
+
+ if( pRet && pRet->Style == SymbolStyle_AUTO )
+ {
+ pRet->Style = SymbolStyle_STANDARD;
+
+ sal_Int32 nIndex = m_nGlobalSeriesIndex;
+ if(m_aValues_X.is())
+ nIndex++;
+ pRet->StandardSymbol = nIndex;
+ }
+
+ return pRet;
+}
+
+uno::Reference< beans::XPropertySet > VDataSeries::getYErrorBarProperties( sal_Int32 index ) const
+{
+ uno::Reference< beans::XPropertySet > xErrorBarProp;
+
+ uno::Reference< beans::XPropertySet > xPointProp( this->getPropertiesOfPoint( index ));
+ if( xPointProp.is() )
+ xPointProp->getPropertyValue( C2U( "ErrorBarY" )) >>= xErrorBarProp;
+ return xErrorBarProp;
+}
+
+bool VDataSeries::hasPointOwnColor( sal_Int32 index ) const
+{
+ if( !isAttributedDataPoint(index) )
+ return false;
+
+ try
+ {
+ uno::Reference< beans::XPropertyState > xPointState( this->getPropertiesOfPoint(index), uno::UNO_QUERY_THROW );
+ return (xPointState->getPropertyState( C2U("Color")) != beans::PropertyState_DEFAULT_VALUE );
+ }
+ catch( uno::Exception& e)
+ {
+ ASSERT_EXCEPTION( e );
+ }
+ return false;
+}
+
+bool VDataSeries::isAttributedDataPoint( sal_Int32 index ) const
+{
+ //returns true if the data point assigned by the given index has set it's own properties
+ if( index>=m_nPointCount || m_nPointCount==0)
+ return false;
+ for(sal_Int32 nN=m_aAttributedDataPointIndexList.getLength();nN--;)
+ {
+ if(index==m_aAttributedDataPointIndexList[nN])
+ return true;
+ }
+ return false;
+}
+
+bool VDataSeries::isVaryColorsByPoint() const
+{
+ bool bVaryColorsByPoint = false;
+ Reference< beans::XPropertySet > xSeriesProp( this->getPropertiesOfSeries() );
+ if( xSeriesProp.is() )
+ xSeriesProp->getPropertyValue( C2U("VaryColorsByPoint") ) >>= bVaryColorsByPoint;
+ return bVaryColorsByPoint;
+}
+
+uno::Reference< beans::XPropertySet > VDataSeries::getPropertiesOfPoint( sal_Int32 index ) const
+{
+ if( isAttributedDataPoint( index ) )
+ return m_xDataSeries->getDataPointByIndex(index);
+ return this->getPropertiesOfSeries();
+}
+
+uno::Reference< beans::XPropertySet > VDataSeries::getPropertiesOfSeries() const
+{
+ return uno::Reference<beans::XPropertySet>(m_xDataSeries, uno::UNO_QUERY );
+}
+
+::std::auto_ptr< DataPointLabel > getDataPointLabelFromPropertySet(
+ const uno::Reference< beans::XPropertySet >& xProp )
+{
+ ::std::auto_ptr< DataPointLabel > apLabel( new DataPointLabel() );
+ try
+ {
+ if( !(xProp->getPropertyValue( C2U( "Label" ) ) >>= *apLabel) )
+ apLabel.reset();
+ }
+ catch( uno::Exception &e)
+ {
+ ASSERT_EXCEPTION( e );
+ }
+ return apLabel;
+}
+
+void VDataSeries::adaptPointCache( sal_Int32 nNewPointIndex ) const
+{
+ if( m_nCurrentAttributedPoint != nNewPointIndex )
+ {
+ m_apLabel_AttributedPoint.reset();
+ m_apLabelPropNames_AttributedPoint.reset();
+ m_apLabelPropValues_AttributedPoint.reset();
+ m_apSymbolProperties_AttributedPoint.reset();
+ m_nCurrentAttributedPoint = nNewPointIndex;
+ }
+}
+
+DataPointLabel* VDataSeries::getDataPointLabel( sal_Int32 index ) const
+{
+ DataPointLabel* pRet = NULL;
+ if( isAttributedDataPoint( index ) )
+ {
+ adaptPointCache( index );
+ if( !m_apLabel_AttributedPoint.get() )
+ m_apLabel_AttributedPoint = getDataPointLabelFromPropertySet( this->getPropertiesOfPoint( index ) );
+ pRet = m_apLabel_AttributedPoint.get();
+ }
+ else
+ {
+ if(!m_apLabel_Series.get())
+ m_apLabel_Series = getDataPointLabelFromPropertySet( this->getPropertiesOfPoint( index ) );
+ pRet = m_apLabel_Series.get();
+ }
+ if( !m_bAllowPercentValueInDataLabel )
+ {
+ if( pRet )
+ pRet->ShowNumberInPercent = false;
+ }
+ return pRet;
+}
+
+DataPointLabel* VDataSeries::getDataPointLabelIfLabel( sal_Int32 index ) const
+{
+ DataPointLabel* pLabel = this->getDataPointLabel( index );
+ if( !pLabel || (!pLabel->ShowNumber && !pLabel->ShowNumberInPercent
+ && !pLabel->ShowCategoryName ) )
+ return 0;
+ return pLabel;
+}
+
+bool VDataSeries::getTextLabelMultiPropertyLists( sal_Int32 index
+ , tNameSequence*& pPropNames
+ , tAnySequence*& pPropValues ) const
+{
+ pPropNames = NULL; pPropValues = NULL;
+ uno::Reference< beans::XPropertySet > xTextProp;
+ bool bDoDynamicFontResize = false;
+ if( isAttributedDataPoint( index ) )
+ {
+ adaptPointCache( index );
+ if(!m_apLabelPropValues_AttributedPoint.get())
+ {
+ pPropNames = new tNameSequence();
+ pPropValues = new tAnySequence();
+ xTextProp.set( this->getPropertiesOfPoint( index ));
+ PropertyMapper::getTextLabelMultiPropertyLists( xTextProp, *pPropNames, *pPropValues );
+ m_apLabelPropNames_AttributedPoint = ::std::auto_ptr< tNameSequence >(pPropNames);
+ m_apLabelPropValues_AttributedPoint = ::std::auto_ptr< tAnySequence >(pPropValues);
+ bDoDynamicFontResize = true;
+ }
+ pPropNames = m_apLabelPropNames_AttributedPoint.get();
+ pPropValues = m_apLabelPropValues_AttributedPoint.get();
+ }
+ else
+ {
+ if(!m_apLabelPropValues_Series.get())
+ {
+ pPropNames = new tNameSequence();
+ pPropValues = new tAnySequence();
+ xTextProp.set( this->getPropertiesOfPoint( index ));
+ PropertyMapper::getTextLabelMultiPropertyLists( xTextProp, *pPropNames, *pPropValues );
+ m_apLabelPropNames_Series = ::std::auto_ptr< tNameSequence >(pPropNames);
+ m_apLabelPropValues_Series = ::std::auto_ptr< tAnySequence >(pPropValues);
+ bDoDynamicFontResize = true;
+ }
+ pPropNames = m_apLabelPropNames_Series.get();
+ pPropValues = m_apLabelPropValues_Series.get();
+ }
+
+ if( bDoDynamicFontResize &&
+ pPropNames && pPropValues &&
+ xTextProp.is())
+ {
+ LabelPositionHelper::doDynamicFontResize( *pPropValues, *pPropNames, xTextProp, m_aReferenceSize );
+ }
+ if(pPropNames&&pPropValues)
+ return true;
+ return false;
+}
+
+void VDataSeries::setMissingValueTreatment( sal_Int32 nMissingValueTreatment )
+{
+ m_nMissingValueTreatment = nMissingValueTreatment;
+}
+
+sal_Int32 VDataSeries::getMissingValueTreatment() const
+{
+ return m_nMissingValueTreatment;
+}
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
diff --git a/chart2/source/view/main/VLegend.cxx b/chart2/source/view/main/VLegend.cxx
new file mode 100644
index 000000000000..7101a984ee24
--- /dev/null
+++ b/chart2/source/view/main/VLegend.cxx
@@ -0,0 +1,834 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_chart2.hxx"
+#include "VLegend.hxx"
+#include "macros.hxx"
+#include "PropertyMapper.hxx"
+#include "CommonConverters.hxx"
+#include "ObjectIdentifier.hxx"
+#include "RelativePositionHelper.hxx"
+#include "ShapeFactory.hxx"
+#include "RelativeSizeHelper.hxx"
+#include "LegendEntryProvider.hxx"
+#include <com/sun/star/text/XTextRange.hpp>
+#include <com/sun/star/text/WritingMode2.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/XPropertyState.hpp>
+#include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
+#include <com/sun/star/drawing/LineJoint.hpp>
+#include <com/sun/star/chart2/LegendExpansion.hpp>
+#include <com/sun/star/chart2/LegendPosition.hpp>
+#include <com/sun/star/chart2/RelativePosition.hpp>
+#include <rtl/ustrbuf.hxx>
+#include <svl/languageoptions.hxx>
+
+#include <vector>
+#include <algorithm>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+using ::rtl::OUString;
+using ::rtl::OUStringBuffer;
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+
+namespace
+{
+
+typedef ::std::pair< ::chart::tNameSequence, ::chart::tAnySequence > tPropertyValues;
+
+typedef ::std::vector< ViewLegendEntry > tViewLegendEntryContainer;
+
+double lcl_CalcViewFontSize(
+ const Reference< beans::XPropertySet > & xProp,
+ const awt::Size & rReferenceSize )
+{
+ double fResult = 10.0;
+
+ awt::Size aPropRefSize;
+ float fFontHeight( 0.0 );
+ if( xProp.is() && ( xProp->getPropertyValue( C2U( "CharHeight" )) >>= fFontHeight ))
+ {
+ fResult = fFontHeight;
+ try
+ {
+ if( (xProp->getPropertyValue( C2U( "ReferencePageSize" )) >>= aPropRefSize) &&
+ (aPropRefSize.Height > 0))
+ {
+ // todo: find out if asian text is really used
+// Reference< beans::XPropertySetInfo >xInfo( xProp, uno::UNO_QUERY );
+// float fFontHeight2 = fFontHeight;
+// if( xInfo.is() &&
+// xInfo->hasPropertyByName(C2U("CharHeightAsian")) &&
+// (xProp->getPropertyValue(C2U("CharHeightAsian")) >>= fFontHeight2) &&
+// fFontHeight2 > fFontHeight )
+// {
+// fFontHeight = fFontHeight2;
+// }
+
+// if( xInfo.is() &&
+// xInfo->hasPropertyByName(C2U("CharHeightComplex")) &&
+// (xProp->getPropertyValue(C2U("CharHeightComplex")) >>= fFontHeight2) &&
+// fFontHeight2 > fFontHeight )
+// {
+// fFontHeight = fFontHeight2;
+// }
+
+ fResult = ::chart::RelativeSizeHelper::calculate( fFontHeight, aPropRefSize, rReferenceSize );
+ }
+ }
+ catch( const uno::Exception & ex )
+ {
+ ASSERT_EXCEPTION( ex );
+ }
+ }
+
+ // pt -> 1/100th mm
+ return (fResult * (2540.0 / 72.0));
+}
+
+void lcl_getProperties(
+ const Reference< beans::XPropertySet > & xLegendProp,
+ tPropertyValues & rOutLineFillProperties,
+ tPropertyValues & rOutTextProperties,
+ sal_Int32 nMaxLabelWidth,
+ const awt::Size & rReferenceSize )
+{
+ // Get Line- and FillProperties from model legend
+ if( xLegendProp.is())
+ {
+ // set rOutLineFillProperties
+ ::chart::tPropertyNameValueMap aLineFillValueMap;
+ ::chart::PropertyMapper::getValueMap( aLineFillValueMap, ::chart::PropertyMapper::getPropertyNameMapForFillAndLineProperties(), xLegendProp );
+
+ aLineFillValueMap[ C2U("LineJoint") ] = uno::makeAny( drawing::LineJoint_ROUND );
+
+ ::chart::PropertyMapper::getMultiPropertyListsFromValueMap(
+ rOutLineFillProperties.first, rOutLineFillProperties.second, aLineFillValueMap );
+
+ // set rOutTextProperties
+ ::chart::tPropertyNameValueMap aTextValueMap;
+ ::chart::PropertyMapper::getValueMap( aTextValueMap, ::chart::PropertyMapper::getPropertyNameMapForCharacterProperties(), xLegendProp );
+
+ drawing::TextHorizontalAdjust eHorizAdjust( drawing::TextHorizontalAdjust_LEFT );
+ aTextValueMap[ C2U("TextAutoGrowHeight") ] = uno::makeAny( sal_True );
+ aTextValueMap[ C2U("TextAutoGrowWidth") ] = uno::makeAny( sal_True );
+ aTextValueMap[ C2U("TextHorizontalAdjust") ] = uno::makeAny( eHorizAdjust );
+ aTextValueMap[ C2U("TextMaximumFrameWidth") ] = uno::makeAny( nMaxLabelWidth );
+
+ // recalculate font size
+ awt::Size aPropRefSize;
+ float fFontHeight( 0.0 );
+ if( (xLegendProp->getPropertyValue( C2U( "ReferencePageSize" )) >>= aPropRefSize) &&
+ (aPropRefSize.Height > 0) &&
+ (aTextValueMap[ C2U("CharHeight") ] >>= fFontHeight) )
+ {
+ aTextValueMap[ C2U("CharHeight") ] = uno::makeAny(
+ static_cast< float >(
+ ::chart::RelativeSizeHelper::calculate( fFontHeight, aPropRefSize, rReferenceSize )));
+
+ if( aTextValueMap[ C2U("CharHeightAsian") ] >>= fFontHeight )
+ {
+ aTextValueMap[ C2U("CharHeightAsian") ] = uno::makeAny(
+ static_cast< float >(
+ ::chart::RelativeSizeHelper::calculate( fFontHeight, aPropRefSize, rReferenceSize )));
+ }
+ if( aTextValueMap[ C2U("CharHeightComplex") ] >>= fFontHeight )
+ {
+ aTextValueMap[ C2U("CharHeightComplex") ] = uno::makeAny(
+ static_cast< float >(
+ ::chart::RelativeSizeHelper::calculate( fFontHeight, aPropRefSize, rReferenceSize )));
+ }
+ }
+
+ ::chart::PropertyMapper::getMultiPropertyListsFromValueMap(
+ rOutTextProperties.first, rOutTextProperties.second, aTextValueMap );
+ }
+}
+
+awt::Size lcl_createTextShapes(
+ const tViewLegendEntryContainer & rEntries,
+ const Reference< lang::XMultiServiceFactory > & xShapeFactory,
+ const Reference< drawing::XShapes > & xTarget,
+ ::std::vector< Reference< drawing::XShape > > & rOutTextShapes,
+ const tPropertyValues & rTextProperties )
+{
+ awt::Size aResult;
+
+ for( tViewLegendEntryContainer::const_iterator aIt( rEntries.begin());
+ aIt != rEntries.end(); ++aIt )
+ {
+ try
+ {
+ // create label shape
+ Reference< drawing::XShape > xGroupShapeForSingleEntry(
+ xShapeFactory->createInstance(
+ C2U( "com.sun.star.drawing.GroupShape" )), uno::UNO_QUERY_THROW );
+ Reference< drawing::XShape >xEntry(
+ xShapeFactory->createInstance(
+ C2U( "com.sun.star.drawing.TextShape" )), uno::UNO_QUERY_THROW );
+ xTarget->add( xGroupShapeForSingleEntry );
+
+ Reference< drawing::XShapes > xGroup( xGroupShapeForSingleEntry, uno::UNO_QUERY_THROW );
+ xGroup->add( xEntry );
+
+ // set label text
+ Sequence< Reference< XFormattedString > > aLabelSeq = (*aIt).aLabel;
+ for( sal_Int32 i = 0; i < aLabelSeq.getLength(); ++i )
+ {
+ // todo: support more than one text range
+ if( i == 1 )
+ break;
+
+ Reference< text::XTextRange > xRange( xEntry, uno::UNO_QUERY );
+ OUString aLabelString( aLabelSeq[i]->getString());
+ // workaround for Issue #i67540#
+ if( !aLabelString.getLength())
+ aLabelString = C2U(" ");
+ if( xRange.is())
+ xRange->setString( aLabelString );
+
+ PropertyMapper::setMultiProperties(
+ rTextProperties.first, rTextProperties.second,
+ Reference< beans::XPropertySet >( xRange, uno::UNO_QUERY ));
+
+ // adapt max-extent
+ awt::Size aCurrSize( xEntry->getSize());
+ aResult.Width = ::std::max( aResult.Width, aCurrSize.Width );
+ aResult.Height = ::std::max( aResult.Height, aCurrSize.Height );
+ }
+
+ rOutTextShapes.push_back( xGroupShapeForSingleEntry );
+ }
+ catch( uno::Exception & ex )
+ {
+ ASSERT_EXCEPTION( ex );
+ }
+ }
+
+ return aResult;
+}
+
+
+void lcl_placeLegendEntries(
+ const tViewLegendEntryContainer & rEntries,
+ LegendExpansion eExpansion,
+ bool bSymbolsLeftSide,
+ const Reference< beans::XPropertySet > & xProperties,
+ tPropertyValues & rTextProperties,
+ const Reference< drawing::XShapes > & xTarget,
+ const Reference< lang::XMultiServiceFactory > & xShapeFactory,
+ const Reference< uno::XComponentContext > & /* xContext */,
+ const awt::Size & rAvailableSpace,
+ const awt::Size & rPageSize,
+ awt::Size & rOutLegendSize )
+{
+ double fViewFontSize = lcl_CalcViewFontSize( xProperties, rPageSize );
+
+ // padding as percentage of the font height
+ // #i109336# Improve auto positioning in chart
+ double fXPadding = 0.1;
+ double fYPadding = 0.2;
+ double fXOffset = 0.15;
+ double fYOffset = 0.15;
+
+ const sal_Int32 nXPadding = static_cast< sal_Int32 >( fViewFontSize * fXPadding );
+ const sal_Int32 nYPadding = static_cast< sal_Int32 >( fViewFontSize * fYPadding );
+ const sal_Int32 nXOffset = static_cast< sal_Int32 >( fViewFontSize * fXOffset );
+ const sal_Int32 nYOffset = static_cast< sal_Int32 >( fViewFontSize * fYOffset );
+
+ ::std::vector< Reference< drawing::XShape > > aTextShapes;
+ awt::Size aMaxEntryExtent = lcl_createTextShapes(
+ rEntries, xShapeFactory, xTarget, aTextShapes, rTextProperties );
+ OSL_ASSERT( aTextShapes.size() == rEntries.size());
+
+ // #i109336# Improve auto positioning in chart
+ double fSymbolSizeFraction = 0.8;
+ awt::Size aMaxSymbolExtent( static_cast< sal_Int32 >( fViewFontSize * fSymbolSizeFraction * 3.0 / 2.0 ),
+ static_cast< sal_Int32 >( fViewFontSize * fSymbolSizeFraction ) );
+
+ sal_Int32 nCurrentXPos = nXPadding;
+ sal_Int32 nCurrentYPos = nYPadding;
+ sal_Int32 nMaxEntryWidth = 2 * nXOffset + aMaxSymbolExtent.Width + aMaxEntryExtent.Width;
+ sal_Int32 nMaxEntryHeight = nYOffset + aMaxEntryExtent.Height;
+ sal_Int32 nNumberOfEntries = rEntries.size();
+
+ if( !bSymbolsLeftSide )
+ nCurrentXPos = -nXPadding;
+
+ sal_Int32 nNumberOfColumns = 0, nNumberOfRows = 0;
+
+ // determine layout depending on LegendExpansion
+ if( eExpansion == LegendExpansion_HIGH )
+ {
+ sal_Int32 nMaxNumberOfRows = nMaxEntryHeight
+ ? (rAvailableSpace.Height - 2*nYPadding ) / nMaxEntryHeight
+ : 0;
+
+ nNumberOfColumns = nMaxNumberOfRows
+ ? static_cast< sal_Int32 >(
+ ceil( static_cast< double >( nNumberOfEntries ) /
+ static_cast< double >( nMaxNumberOfRows ) ))
+ : 0;
+ nNumberOfRows = nNumberOfColumns
+ ? static_cast< sal_Int32 >(
+ ceil( static_cast< double >( nNumberOfEntries ) /
+ static_cast< double >( nNumberOfColumns ) ))
+ : 0;
+ }
+ else if( eExpansion == LegendExpansion_WIDE )
+ {
+ sal_Int32 nMaxNumberOfColumns = nMaxEntryWidth
+ ? (rAvailableSpace.Width - 2*nXPadding ) / nMaxEntryWidth
+ : 0;
+
+ nNumberOfRows = nMaxNumberOfColumns
+ ? static_cast< sal_Int32 >(
+ ceil( static_cast< double >( nNumberOfEntries ) /
+ static_cast< double >( nMaxNumberOfColumns ) ))
+ : 0;
+ nNumberOfColumns = nNumberOfRows
+ ? static_cast< sal_Int32 >(
+ ceil( static_cast< double >( nNumberOfEntries ) /
+ static_cast< double >( nNumberOfRows ) ))
+ : 0;
+ }
+ else // LegendExpansion_BALANCED
+ {
+ double fAspect = nMaxEntryHeight
+ ? static_cast< double >( nMaxEntryWidth ) / static_cast< double >( nMaxEntryHeight )
+ : 0.0;
+
+ nNumberOfRows = static_cast< sal_Int32 >(
+ ceil( sqrt( static_cast< double >( nNumberOfEntries ) * fAspect )));
+ nNumberOfColumns = nNumberOfRows
+ ? static_cast< sal_Int32 >(
+ ceil( static_cast< double >( nNumberOfEntries ) /
+ static_cast< double >( nNumberOfRows ) ))
+ : 0;
+ }
+
+ if(nNumberOfRows<=0)
+ return;
+
+ // calculate maximum height for current row
+ std::vector< sal_Int32 > nMaxHeights( nNumberOfRows );
+ sal_Int32 nRow = 0;
+ sal_Int32 nColumn = 0;
+ for( ; nRow < nNumberOfRows; ++nRow )
+ {
+ sal_Int32 nMaxHeight = 0;
+ for( nColumn = 0; nColumn < nNumberOfColumns; ++nColumn )
+ {
+ sal_Int32 nEntry = ( eExpansion == LegendExpansion_WIDE )
+ ? (nColumn + nRow * nNumberOfColumns)
+ // HIGH or BALANCED
+ : (nRow + nColumn * nNumberOfRows);
+ if( nEntry < nNumberOfEntries )
+ nMaxHeight = ::std::max(
+ nMaxHeight, nYOffset + aTextShapes[ nEntry ]->getSize().Height );
+ }
+ nMaxHeights[ nRow ] = nMaxHeight;
+ }
+
+ // place entries ordered in optimal-width columns
+ sal_Int32 nMaxYPos = 0;
+ for( nColumn = 0; nColumn < nNumberOfColumns; ++nColumn )
+ {
+ sal_Int32 nMaxWidth = 0;
+ nCurrentYPos = nYPadding;
+
+ for( nRow = 0; nRow < nNumberOfRows; ++nRow )
+ {
+ sal_Int32 nEntry = ( eExpansion == LegendExpansion_WIDE )
+ ? (nColumn + nRow * nNumberOfColumns)
+ // HIGH or BALANCED
+ : (nRow + nColumn * nNumberOfRows);
+
+ if( nEntry >= nNumberOfEntries )
+ break;
+
+ // symbol
+ Reference< drawing::XShape > xSymbol( rEntries[ nEntry ].aSymbol );
+
+ if( xSymbol.is() )
+ {
+ // Note: aspect ratio should always be 3:2
+
+ // set symbol size to 75% of maximum space
+ awt::Size aSymbolSize(
+ aMaxSymbolExtent.Width * 75 / 100,
+ aMaxSymbolExtent.Height * 75 / 100 );
+ xSymbol->setSize( aSymbolSize );
+ sal_Int32 nSymbolXPos = nCurrentXPos + ((aMaxSymbolExtent.Width - aSymbolSize.Width) / 2);
+ if( !bSymbolsLeftSide )
+ nSymbolXPos = nSymbolXPos - aMaxSymbolExtent.Width;
+
+ // #i109336# Improve auto positioning in chart
+ sal_Int32 nTextHeight = nMaxHeights[ nRow ] - nYOffset;
+ sal_Int32 nFontSize = static_cast< sal_Int32 >( fViewFontSize );
+ sal_Int32 nMaxRowHeight = ( ( ( nTextHeight / nFontSize ) <= 1 ) ? nTextHeight : nFontSize );
+ sal_Int32 nSymbolYPos = nCurrentYPos + ( ( nMaxRowHeight - aSymbolSize.Height ) / 2 );
+ xSymbol->setPosition( awt::Point( nSymbolXPos, nSymbolYPos ) );
+ }
+
+ // position text shape
+ awt::Size aTextSize( aTextShapes[ nEntry ]->getSize());
+ nMaxWidth = ::std::max( nMaxWidth, 2 * nXOffset + aMaxSymbolExtent.Width + aTextSize.Width );
+ sal_Int32 nTextXPos = nCurrentXPos + aMaxSymbolExtent.Width;
+ if( !bSymbolsLeftSide )
+ nTextXPos = nCurrentXPos - aMaxSymbolExtent.Width - aTextSize.Width;
+ aTextShapes[ nEntry ]->setPosition( awt::Point( nTextXPos, nCurrentYPos ));
+
+ nCurrentYPos += nMaxHeights[ nRow ];
+ nMaxYPos = ::std::max( nMaxYPos, nCurrentYPos );
+ }
+ if( bSymbolsLeftSide )
+ nCurrentXPos += nMaxWidth;
+ else
+ nCurrentXPos -= nMaxWidth;
+ }
+
+ if( bSymbolsLeftSide )
+ rOutLegendSize.Width = nCurrentXPos + nXPadding;
+ else
+ {
+ sal_Int32 nLegendWidth = -(nCurrentXPos-nXPadding);
+ rOutLegendSize.Width = nLegendWidth;
+
+ awt::Point aPos(0,0);
+ for( sal_Int32 nEntry=0; nEntry<nNumberOfEntries; nEntry++ )
+ {
+ Reference< drawing::XShape > xSymbol( rEntries[ nEntry ].aSymbol );
+ aPos = xSymbol->getPosition();
+ aPos.X += nLegendWidth;
+ xSymbol->setPosition( aPos );
+ Reference< drawing::XShape > xText( aTextShapes[ nEntry ] );
+ aPos = xText->getPosition();
+ aPos.X += nLegendWidth;
+ xText->setPosition( aPos );
+ }
+ }
+ rOutLegendSize.Height = nMaxYPos + nYPadding;
+}
+
+// #i109336# Improve auto positioning in chart
+sal_Int32 lcl_getLegendLeftRightMargin()
+{
+ return 210; // 1/100 mm
+}
+
+// #i109336# Improve auto positioning in chart
+sal_Int32 lcl_getLegendTopBottomMargin()
+{
+ return 185; // 1/100 mm
+}
+
+chart2::RelativePosition lcl_getDefaultPosition( LegendPosition ePos, const awt::Rectangle& rOutAvailableSpace, const awt::Size & rPageSize )
+{
+ chart2::RelativePosition aResult;
+
+ switch( ePos )
+ {
+ case LegendPosition_LINE_START:
+ {
+ // #i109336# Improve auto positioning in chart
+ const double fDefaultDistance = ( static_cast< double >( lcl_getLegendLeftRightMargin() ) /
+ static_cast< double >( rPageSize.Width ) );
+ aResult = chart2::RelativePosition(
+ fDefaultDistance, 0.5, drawing::Alignment_LEFT );
+ }
+ break;
+ case LegendPosition_LINE_END:
+ {
+ // #i109336# Improve auto positioning in chart
+ const double fDefaultDistance = ( static_cast< double >( lcl_getLegendLeftRightMargin() ) /
+ static_cast< double >( rPageSize.Width ) );
+ aResult = chart2::RelativePosition(
+ 1.0 - fDefaultDistance, 0.5, drawing::Alignment_RIGHT );
+ }
+ break;
+ case LegendPosition_PAGE_START:
+ {
+ // #i109336# Improve auto positioning in chart
+ const double fDefaultDistance = ( static_cast< double >( lcl_getLegendTopBottomMargin() ) /
+ static_cast< double >( rPageSize.Height ) );
+ double fDistance = (static_cast<double>(rOutAvailableSpace.Y)/static_cast<double>(rPageSize.Height)) + fDefaultDistance;
+ aResult = chart2::RelativePosition(
+ 0.5, fDistance, drawing::Alignment_TOP );
+ }
+ break;
+ case LegendPosition_PAGE_END:
+ {
+ // #i109336# Improve auto positioning in chart
+ const double fDefaultDistance = ( static_cast< double >( lcl_getLegendTopBottomMargin() ) /
+ static_cast< double >( rPageSize.Height ) );
+ aResult = chart2::RelativePosition(
+ 0.5, 1.0 - fDefaultDistance, drawing::Alignment_BOTTOM );
+ }
+ break;
+
+ case LegendPosition_CUSTOM:
+ // to avoid warning
+ case LegendPosition_MAKE_FIXED_SIZE:
+ // nothing to be set
+ break;
+ }
+
+ return aResult;
+}
+
+/** @return
+ a point relative to the upper left corner that can be used for
+ XShape::setPosition()
+*/
+awt::Point lcl_calculatePositionAndRemainingSpace(
+ awt::Rectangle & rRemainingSpace,
+ const awt::Size & rPageSize,
+ chart2::RelativePosition aRelPos,
+ LegendPosition ePos,
+ const awt::Size& aLegendSize )
+{
+ // calculate position
+ awt::Point aResult(
+ static_cast< sal_Int32 >( aRelPos.Primary * rPageSize.Width ),
+ static_cast< sal_Int32 >( aRelPos.Secondary * rPageSize.Height ));
+
+ aResult = RelativePositionHelper::getUpperLeftCornerOfAnchoredObject(
+ aResult, aLegendSize, aRelPos.Anchor );
+
+ // adapt rRemainingSpace if LegendPosition is not CUSTOM
+ // #i109336# Improve auto positioning in chart
+ sal_Int32 nXDistance = lcl_getLegendLeftRightMargin();
+ sal_Int32 nYDistance = lcl_getLegendTopBottomMargin();
+ switch( ePos )
+ {
+ case LegendPosition_LINE_START:
+ {
+ sal_Int32 nExtent = aLegendSize.Width;
+ rRemainingSpace.Width -= ( nExtent + nXDistance );
+ rRemainingSpace.X += ( nExtent + nXDistance );
+ }
+ break;
+ case LegendPosition_LINE_END:
+ {
+ rRemainingSpace.Width -= ( aLegendSize.Width + nXDistance );
+ }
+ break;
+ case LegendPosition_PAGE_START:
+ {
+ sal_Int32 nExtent = aLegendSize.Height;
+ rRemainingSpace.Height -= ( nExtent + nYDistance );
+ rRemainingSpace.Y += ( nExtent + nYDistance );
+ }
+ break;
+ case LegendPosition_PAGE_END:
+ {
+ rRemainingSpace.Height -= ( aLegendSize.Height + nYDistance );
+ }
+ break;
+
+ default:
+ // nothing
+ break;
+ }
+
+ // adjust the legend position. Esp. for old files that had slightly smaller legends
+ const sal_Int32 nEdgeDistance( 30 );
+ if( aResult.X + aLegendSize.Width > rPageSize.Width )
+ {
+ sal_Int32 nNewX( (rPageSize.Width - aLegendSize.Width) - nEdgeDistance );
+ if( nNewX > rPageSize.Width / 4 )
+ aResult.X = nNewX;
+ }
+ if( aResult.Y + aLegendSize.Height > rPageSize.Height )
+ {
+ sal_Int32 nNewY( (rPageSize.Height - aLegendSize.Height) - nEdgeDistance );
+ if( nNewY > rPageSize.Height / 4 )
+ aResult.Y = nNewY;
+ }
+
+ return aResult;
+}
+
+template< class T >
+void lcl_appendSeqToVector( const Sequence< T > & rSource, ::std::vector< T > & rDest )
+{
+ const sal_Int32 nCount = rSource.getLength();
+ for( sal_Int32 i = 0; i < nCount; ++i )
+ rDest.push_back( rSource[ i ] );
+}
+
+bool lcl_shouldSymbolsBePlacedOnTheLeftSide( const Reference< beans::XPropertySet >& xLegendProp, sal_Int16 nDefaultWritingMode )
+{
+ bool bSymbolsLeftSide = true;
+ try
+ {
+ if( SvtLanguageOptions().IsCTLFontEnabled() )
+ {
+ if(xLegendProp.is())
+ {
+ sal_Int16 nWritingMode=-1;
+ if( (xLegendProp->getPropertyValue( C2U("WritingMode") ) >>= nWritingMode) )
+ {
+ if( nWritingMode == text::WritingMode2::PAGE )
+ nWritingMode = nDefaultWritingMode;
+ if( nWritingMode == text::WritingMode2::RL_TB )
+ bSymbolsLeftSide=false;
+ }
+ }
+ }
+ }
+ catch( uno::Exception & ex )
+ {
+ ASSERT_EXCEPTION( ex );
+ }
+ return bSymbolsLeftSide;
+}
+
+} // anonymous namespace
+
+VLegend::VLegend(
+ const Reference< XLegend > & xLegend,
+ const Reference< uno::XComponentContext > & xContext,
+ const std::vector< LegendEntryProvider* >& rLegendEntryProviderList ) :
+ m_xLegend( xLegend ),
+ m_xContext( xContext ),
+ m_aLegendEntryProviderList( rLegendEntryProviderList )
+{
+}
+
+// ----------------------------------------
+
+void SAL_CALL VLegend::init(
+ const Reference< drawing::XShapes >& xTargetPage,
+ const Reference< lang::XMultiServiceFactory >& xFactory,
+ const Reference< frame::XModel >& xModel )
+{
+ m_xTarget = xTargetPage;
+ m_xShapeFactory = xFactory;
+ m_xModel = xModel;
+}
+
+// ----------------------------------------
+
+void VLegend::setDefaultWritingMode( sal_Int16 nDefaultWritingMode )
+{
+ m_nDefaultWritingMode = nDefaultWritingMode;
+}
+
+// ----------------------------------------
+
+// static
+bool VLegend::isVisible( const Reference< XLegend > & xLegend )
+{
+ if( ! xLegend.is())
+ return sal_False;
+
+ sal_Bool bShow = sal_False;
+ try
+ {
+ Reference< beans::XPropertySet > xLegendProp( xLegend, uno::UNO_QUERY_THROW );
+ xLegendProp->getPropertyValue( C2U( "Show" )) >>= bShow;
+ }
+ catch( uno::Exception & ex )
+ {
+ ASSERT_EXCEPTION( ex );
+ }
+
+ return bShow;
+}
+
+// ----------------------------------------
+
+void VLegend::createShapes(
+ const awt::Size & rAvailableSpace,
+ const awt::Size & rPageSize )
+{
+ if(! (m_xLegend.is() &&
+ m_xShapeFactory.is() &&
+ m_xTarget.is()))
+ return;
+
+ try
+ {
+ //create shape and add to page
+ m_xShape.set( m_xShapeFactory->createInstance(
+ C2U( "com.sun.star.drawing.GroupShape" )), uno::UNO_QUERY );
+ m_xTarget->add( m_xShape );
+
+ // set name to enable selection
+ {
+ OUString aLegendParticle( ObjectIdentifier::createParticleForLegend( m_xLegend, m_xModel ) );
+ ShapeFactory::setShapeName( m_xShape, ObjectIdentifier::createClassifiedIdentifierForParticle( aLegendParticle ) );
+ }
+
+ // create and insert sub-shapes
+ Reference< drawing::XShapes > xLegendContainer( m_xShape, uno::UNO_QUERY );
+ if( xLegendContainer.is())
+ {
+ Reference< drawing::XShape > xBorder(
+ m_xShapeFactory->createInstance(
+ C2U( "com.sun.star.drawing.RectangleShape" )), uno::UNO_QUERY );
+
+ // for quickly setting properties
+ tPropertyValues aLineFillProperties;
+ tPropertyValues aTextProperties;
+
+ // limit the width of texts to 30% of the total available width
+ // #i109336# Improve auto positioning in chart
+ sal_Int32 nMaxLabelWidth = rAvailableSpace.Width * 3 / 10;
+ Reference< beans::XPropertySet > xLegendProp( m_xLegend, uno::UNO_QUERY );
+ LegendExpansion eExpansion = LegendExpansion_HIGH;
+ if( xLegendProp.is())
+ {
+ // get Expansion property
+ xLegendProp->getPropertyValue( C2U( "Expansion" )) >>= eExpansion;
+ if( eExpansion == LegendExpansion_WIDE )
+ {
+ //#i80377#
+ nMaxLabelWidth = (rAvailableSpace.Width * 5) / 6;//completely correct would be available width minus symbol size minus distances to page ...
+ }
+
+ lcl_getProperties( xLegendProp, aLineFillProperties, aTextProperties, nMaxLabelWidth,
+ rPageSize );
+ }
+
+ if( xBorder.is())
+ {
+ xLegendContainer->add( xBorder );
+
+ // apply legend properties
+ PropertyMapper::setMultiProperties(
+ aLineFillProperties.first, aLineFillProperties.second,
+ Reference< beans::XPropertySet >( xBorder, uno::UNO_QUERY ));
+
+ //because of this name this border will be used for marking the legend
+ ShapeFactory(m_xShapeFactory).setShapeName( xBorder, C2U("MarkHandles") );
+ }
+
+ // create entries
+ tViewLegendEntryContainer aViewEntries;
+ {
+ ::std::vector< LegendEntryProvider* >::const_iterator aIter = m_aLegendEntryProviderList.begin();
+ const ::std::vector< LegendEntryProvider* >::const_iterator aEnd = m_aLegendEntryProviderList.end();
+ for( ; aIter != aEnd; aIter++ )
+ {
+ LegendEntryProvider* pLegendEntryProvider( *aIter );
+ if( pLegendEntryProvider )
+ {
+ lcl_appendSeqToVector< ViewLegendEntry >(
+ pLegendEntryProvider->createLegendEntries( eExpansion, xLegendProp, xLegendContainer, m_xShapeFactory, m_xContext )
+ , aViewEntries );
+ }
+ }
+ }
+
+ bool bSymbolsLeftSide = lcl_shouldSymbolsBePlacedOnTheLeftSide( xLegendProp, m_nDefaultWritingMode );
+
+ // place entries
+ awt::Size aLegendSize;
+ lcl_placeLegendEntries( aViewEntries, eExpansion, bSymbolsLeftSide
+ , xLegendProp, aTextProperties
+ , xLegendContainer, m_xShapeFactory, m_xContext
+ , rAvailableSpace, rPageSize, aLegendSize );
+
+ if( xBorder.is())
+ xBorder->setSize( aLegendSize );
+ }
+ }
+ catch( uno::Exception & ex )
+ {
+ ASSERT_EXCEPTION( ex );
+ }
+}
+
+// ----------------------------------------
+
+void VLegend::changePosition(
+ awt::Rectangle & rOutAvailableSpace,
+ const awt::Size & rPageSize )
+{
+ if(! m_xShape.is())
+ return;
+
+ try
+ {
+ // determine position and alignment depending on default position
+ awt::Size aLegendSize = m_xShape->getSize();
+ Reference< beans::XPropertySet > xLegendProp( m_xLegend, uno::UNO_QUERY_THROW );
+ chart2::RelativePosition aRelativePosition;
+
+ bool bAutoPosition =
+ ! (xLegendProp->getPropertyValue( C2U( "RelativePosition" )) >>= aRelativePosition);
+
+ LegendPosition ePos = LegendPosition_CUSTOM;
+ xLegendProp->getPropertyValue( C2U( "AnchorPosition" )) >>= ePos;
+
+ //calculate position
+ if( bAutoPosition )
+ {
+ // auto position: relative to remaining space
+ aRelativePosition = lcl_getDefaultPosition( ePos, rOutAvailableSpace, rPageSize );
+ awt::Point aPos = lcl_calculatePositionAndRemainingSpace(
+ rOutAvailableSpace, rPageSize, aRelativePosition, ePos, aLegendSize );
+ m_xShape->setPosition( aPos );
+ }
+ else
+ {
+ // manual position: relative to whole page
+ awt::Rectangle aAvailableSpace( 0, 0, rPageSize.Width, rPageSize.Height );
+ awt::Point aPos = lcl_calculatePositionAndRemainingSpace(
+ aAvailableSpace, rPageSize, aRelativePosition, ePos, aLegendSize );
+ m_xShape->setPosition( aPos );
+
+ if( ePos != LegendPosition_CUSTOM )
+ {
+ // calculate remaining space as if having autoposition:
+ aRelativePosition = lcl_getDefaultPosition( ePos, rOutAvailableSpace, rPageSize );
+ lcl_calculatePositionAndRemainingSpace(
+ rOutAvailableSpace, rPageSize, aRelativePosition, ePos, aLegendSize );
+ }
+ }
+ }
+ catch( uno::Exception & ex )
+ {
+ ASSERT_EXCEPTION( ex );
+ }
+}
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
diff --git a/chart2/source/view/main/VLegend.hxx b/chart2/source/view/main/VLegend.hxx
new file mode 100644
index 000000000000..9587b50f71e7
--- /dev/null
+++ b/chart2/source/view/main/VLegend.hxx
@@ -0,0 +1,111 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _VLEGEND_HXX
+#define _VLEGEND_HXX
+
+#include <com/sun/star/chart2/XLegend.hpp>
+#include <com/sun/star/drawing/XShapes.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/awt/Rectangle.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+
+#include <vector>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+
+class LegendEntryProvider;
+
+//-----------------------------------------------------------------------------
+/**
+*/
+
+class VLegend
+{
+public:
+ VLegend( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::chart2::XLegend > & xLegend,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XComponentContext > & xContext,
+ const std::vector< LegendEntryProvider* >& rLegendEntryProviderList );
+
+ void SAL_CALL init( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShapes >& xTargetPage,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::lang::XMultiServiceFactory >& xFactory,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::frame::XModel > & xModel );
+
+ void setDefaultWritingMode( sal_Int16 nDefaultWritingMode );
+
+ void createShapes( const ::com::sun::star::awt::Size & rAvailableSpace,
+ const ::com::sun::star::awt::Size & rPageSize );
+
+ /** Sets the position according to its internal anchor.
+
+ @param rOutAvailableSpace
+ is modified by the method, if the legend is in a standard position,
+ such that the space allocated by the legend is removed from it.
+
+ @param rReferenceSize
+ is used to calculate the offset (default 2%) from the edge.
+ */
+ void changePosition(
+ ::com::sun::star::awt::Rectangle & rOutAvailableSpace,
+ const ::com::sun::star::awt::Size & rReferenceSize );
+
+ static bool isVisible(
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::chart2::XLegend > & xLegend );
+
+private:
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShapes > m_xTarget;
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::lang::XMultiServiceFactory> m_xShapeFactory;
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::chart2::XLegend > m_xLegend;
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShape > m_xShape;
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::frame::XModel > m_xModel;
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XComponentContext > m_xContext;
+
+ std::vector< LegendEntryProvider* > m_aLegendEntryProviderList;
+
+ sal_Int16 m_nDefaultWritingMode;//to be used when writing mode is set to page
+};
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
+#endif
+
diff --git a/chart2/source/view/main/VLegendSymbolFactory.cxx b/chart2/source/view/main/VLegendSymbolFactory.cxx
new file mode 100644
index 000000000000..958a8defe0b6
--- /dev/null
+++ b/chart2/source/view/main/VLegendSymbolFactory.cxx
@@ -0,0 +1,374 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_chart2.hxx"
+#include "VLegendSymbolFactory.hxx"
+#include "macros.hxx"
+#include "PropertyMapper.hxx"
+#include "ShapeFactory.hxx"
+#include "ObjectIdentifier.hxx"
+#include <com/sun/star/drawing/LineStyle.hpp>
+#include <com/sun/star/chart2/Symbol.hpp>
+
+// header for define DBG_ASSERT
+#include <tools/debug.hxx>
+
+// uncomment to disable line dashes at the border of boxes
+// #define DISABLE_DASHES_AT_BORDER
+
+using namespace ::com::sun::star;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+using ::rtl::OUString;
+
+namespace
+{
+void lcl_setPropetiesToShape(
+ const Reference< beans::XPropertySet > & xProp,
+ const Reference< drawing::XShape > & xShape,
+ ::chart::VLegendSymbolFactory::tPropertyType ePropertyType )
+{
+ const ::chart::tPropertyNameMap & aFilledSeriesNameMap( ::chart::PropertyMapper::getPropertyNameMapForFilledSeriesProperties());
+ const ::chart::tPropertyNameMap & aLineSeriesNameMap( ::chart::PropertyMapper::getPropertyNameMapForLineSeriesProperties());
+ const ::chart::tPropertyNameMap & aLineNameMap( ::chart::PropertyMapper::getPropertyNameMapForLineProperties());
+ const ::chart::tPropertyNameMap & aFillNameMap( ::chart::PropertyMapper::getPropertyNameMapForFillProperties());
+ const ::chart::tPropertyNameMap & aFillLineNameMap( ::chart::PropertyMapper::getPropertyNameMapForFillAndLineProperties());
+
+ Reference< beans::XPropertySet > xShapeProp( xShape, uno::UNO_QUERY );
+ if( xProp.is() && xShapeProp.is() )
+ {
+ ::chart::tPropertyNameValueMap aValueMap;
+ switch( ePropertyType )
+ {
+ case ::chart::VLegendSymbolFactory::PROP_TYPE_FILLED_SERIES:
+ ::chart::PropertyMapper::getValueMap( aValueMap, aFilledSeriesNameMap, xProp );
+ break;
+ case ::chart::VLegendSymbolFactory::PROP_TYPE_LINE_SERIES:
+ ::chart::PropertyMapper::getValueMap( aValueMap, aLineSeriesNameMap, xProp );
+ break;
+ case ::chart::VLegendSymbolFactory::PROP_TYPE_LINE:
+ ::chart::PropertyMapper::getValueMap( aValueMap, aLineNameMap, xProp );
+ break;
+ case ::chart::VLegendSymbolFactory::PROP_TYPE_FILL:
+ ::chart::PropertyMapper::getValueMap( aValueMap, aFillNameMap, xProp );
+ break;
+ case ::chart::VLegendSymbolFactory::PROP_TYPE_FILL_AND_LINE:
+ ::chart::PropertyMapper::getValueMap( aValueMap, aFillLineNameMap, xProp );
+ break;
+ }
+
+ ::chart::tNameSequence aPropNames;
+ ::chart::tAnySequence aPropValues;
+ ::chart::PropertyMapper::getMultiPropertyListsFromValueMap( aPropNames, aPropValues, aValueMap );
+
+ uno::Any* pLineWidthAny = ::chart::PropertyMapper::getValuePointer(aPropValues,aPropNames,C2U("LineWidth"));
+ sal_Int32 nLineWidth = 0;
+ if( pLineWidthAny && (*pLineWidthAny>>=nLineWidth) )
+ {
+ const sal_Int32 nMaxLineWidthForLegend = 50;/*1/100 mm*///todo: make this dependent from legend entry height
+ if( nLineWidth>nMaxLineWidthForLegend )
+ *pLineWidthAny = uno::makeAny( nMaxLineWidthForLegend );
+ }
+
+ ::chart::PropertyMapper::setMultiProperties( aPropNames, aPropValues, xShapeProp );
+ }
+}
+
+} // anonymous namespace
+
+namespace chart
+{
+
+// static
+Reference< drawing::XShape > VLegendSymbolFactory::createSymbol(
+ const Reference< drawing::XShapes > xSymbolContainer,
+ chart2::LegendSymbolStyle eStyle,
+ const Reference< lang::XMultiServiceFactory > & xShapeFactory,
+ const Reference< beans::XPropertySet > & xLegendEntryProperties,
+ tPropertyType ePropertyType, const uno::Any& rExplicitSymbol )
+{
+ Reference< drawing::XShape > xResult;
+
+ if( ! (xSymbolContainer.is() &&
+ xShapeFactory.is()))
+ return xResult;
+
+ xResult.set( xShapeFactory->createInstance(
+ C2U( "com.sun.star.drawing.GroupShape" )), uno::UNO_QUERY );
+ xSymbolContainer->add( xResult );
+ Reference< drawing::XShapes > xResultGroup( xResult, uno::UNO_QUERY );
+ if( ! xResultGroup.is())
+ return xResult;
+
+ // aspect ratio of symbols is always 3:2
+ awt::Size aBoundSize( 3000, 2000 );
+ bool bUseBox = false;
+
+ // add an invisible square box to maintain aspect ratio
+ switch( eStyle )
+ {
+ case chart2::LegendSymbolStyle_BOX:
+ case chart2::LegendSymbolStyle_HORIZONTAL_LINE:
+ case chart2::LegendSymbolStyle_VERTICAL_LINE:
+ case chart2::LegendSymbolStyle_DIAGONAL_LINE:
+ case chart2::LegendSymbolStyle_LINE_WITH_BOX:
+ case chart2::LegendSymbolStyle_LINE_WITH_SYMBOL:
+ case chart2::LegendSymbolStyle_CIRCLE:
+ {
+ Reference< drawing::XShape > xBound( ShapeFactory(xShapeFactory).createInvisibleRectangle(
+ xResultGroup, aBoundSize ));
+ break;
+ }
+
+ case chart2::LegendSymbolStyle_BAR:
+ case chart2::LegendSymbolStyle_RECTANGLE:
+ case chart2::LegendSymbolStyle_STRETCHED_RECTANGLE:
+ case chart2::LegendSymbolStyle_USER_DEFINED:
+ default:
+ break;
+ }
+
+ // create symbol
+ switch( eStyle )
+ {
+ case chart2::LegendSymbolStyle_BOX:
+ case chart2::LegendSymbolStyle_BAR:
+ case chart2::LegendSymbolStyle_RECTANGLE:
+ case chart2::LegendSymbolStyle_STRETCHED_RECTANGLE:
+ case chart2::LegendSymbolStyle_CIRCLE:
+ {
+ try
+ {
+ Reference< drawing::XShape > xShape;
+
+ if( eStyle == chart2::LegendSymbolStyle_CIRCLE )
+ xShape.set( xShapeFactory->createInstance(
+ C2U( "com.sun.star.drawing.EllipseShape" )), uno::UNO_QUERY );
+ else
+ xShape.set( xShapeFactory->createInstance(
+ C2U( "com.sun.star.drawing.RectangleShape" )), uno::UNO_QUERY );
+
+ if( xShape.is())
+ {
+ xResultGroup->add( xShape );
+ if( eStyle == chart2::LegendSymbolStyle_BOX ||
+ eStyle == chart2::LegendSymbolStyle_CIRCLE )
+ {
+ xShape->setSize( awt::Size( 2000, 2000 ));
+ xShape->setPosition( awt::Point( 500, 0 ));
+ }
+ else
+ {
+ xShape->setSize( aBoundSize );
+ }
+ }
+
+ lcl_setPropetiesToShape( xLegendEntryProperties, xShape, ePropertyType ); // PROP_TYPE_FILLED_SERIES );
+
+#ifdef DISABLE_DASHES_AT_BORDER
+ // don't allow dashed border style
+ Reference< beans::XPropertySet > xShapeProp( xShape, uno::UNO_QUERY );
+ if( xShapeProp.is())
+ {
+ drawing::LineStyle aLineStyle;
+ if( ( xShapeProp->getPropertyValue( C2U("LineStyle")) >>= aLineStyle ) &&
+ aLineStyle == drawing::LineStyle_DASH )
+ {
+ aLineStyle = drawing::LineStyle_SOLID;
+ xShapeProp->setPropertyValue( C2U("LineStyle"), uno::makeAny( aLineStyle ));
+ }
+ }
+#endif
+ }
+ catch( uno::Exception & ex )
+ {
+ ASSERT_EXCEPTION( ex );
+ }
+ break;
+ }
+
+ case chart2::LegendSymbolStyle_HORIZONTAL_LINE:
+ {
+ try
+ {
+ Reference< drawing::XShape > xLine(
+ xShapeFactory->createInstance(
+ C2U( "com.sun.star.drawing.LineShape" )), uno::UNO_QUERY );
+ if( xLine.is())
+ {
+ xResultGroup->add( xLine );
+ xLine->setSize( awt::Size( 3000, 0 ));
+ xLine->setPosition( awt::Point( 0, 1000 ));
+
+ lcl_setPropetiesToShape( xLegendEntryProperties, xLine, ePropertyType ); // PROP_TYPE_LINE_SERIES );
+ }
+ }
+ catch( uno::Exception & ex )
+ {
+ ASSERT_EXCEPTION( ex );
+ }
+ break;
+ }
+
+ case chart2::LegendSymbolStyle_VERTICAL_LINE:
+ {
+ try
+ {
+ Reference< drawing::XShape > xLine(
+ xShapeFactory->createInstance(
+ C2U( "com.sun.star.drawing.LineShape" )), uno::UNO_QUERY );
+ if( xLine.is())
+ {
+ xResultGroup->add( xLine );
+ xLine->setSize( awt::Size( 0, 2000 ));
+ xLine->setPosition( awt::Point( 1500, 0 ));
+
+ lcl_setPropetiesToShape( xLegendEntryProperties, xLine, ePropertyType ); // PROP_TYPE_LINE_SERIES );
+ }
+ }
+ catch( uno::Exception & ex )
+ {
+ ASSERT_EXCEPTION( ex );
+ }
+ break;
+ }
+
+ case chart2::LegendSymbolStyle_DIAGONAL_LINE:
+ {
+ try
+ {
+ Reference< drawing::XShape > xLine(
+ xShapeFactory->createInstance(
+ C2U( "com.sun.star.drawing.LineShape" )), uno::UNO_QUERY );
+ if( xLine.is())
+ {
+ xResultGroup->add( xLine );
+ xLine->setSize( awt::Size( 2000, 2000 ));
+ xLine->setPosition( awt::Point( 500, 0 ));
+
+ lcl_setPropetiesToShape( xLegendEntryProperties, xLine, ePropertyType ); // PROP_TYPE_LINE_SERIES );
+ }
+ }
+ catch( uno::Exception & ex )
+ {
+ ASSERT_EXCEPTION( ex );
+ }
+ break;
+ }
+
+ case chart2::LegendSymbolStyle_LINE_WITH_BOX:
+ bUseBox = true;
+ // fall-through intended
+ case chart2::LegendSymbolStyle_LINE_WITH_SYMBOL:
+ try
+ {
+ Reference< drawing::XShape > xLine(
+ xShapeFactory->createInstance(
+ C2U( "com.sun.star.drawing.LineShape" )), uno::UNO_QUERY );
+ if( xLine.is())
+ {
+ xResultGroup->add( xLine );
+ xLine->setSize( awt::Size( 3000, 0 ));
+ xLine->setPosition( awt::Point( 0, 1000 ));
+
+ lcl_setPropetiesToShape( xLegendEntryProperties, xLine, ePropertyType );
+ }
+
+ Reference< drawing::XShape > xSymbol;
+ const sal_Int32 nSize = 1500;
+ if( bUseBox )
+ {
+ xSymbol.set( xShapeFactory->createInstance(
+ C2U( "com.sun.star.drawing.RectangleShape" )), uno::UNO_QUERY );
+ xResultGroup->add( xSymbol );
+
+ if( xSymbol.is())
+ {
+ xSymbol->setSize( awt::Size( nSize, nSize ));
+ xSymbol->setPosition( awt::Point( 1500 - nSize/2, 1000 - nSize/2 ));
+
+ lcl_setPropetiesToShape( xLegendEntryProperties, xSymbol, ePropertyType );
+ }
+ }
+ else
+ {
+ chart2::Symbol aSymbol;
+
+ if( rExplicitSymbol >>= aSymbol )
+ {
+ drawing::Direction3D aSymbolSize( nSize, nSize, 0 );
+ drawing::Position3D aPos( 1500, 1000, 0 );
+ ShapeFactory aFactory( xShapeFactory );
+ if( aSymbol.Style == chart2::SymbolStyle_STANDARD )
+ {
+ // take series color as fill color
+ xLegendEntryProperties->getPropertyValue( C2U("Color")) >>= aSymbol.FillColor;
+ // border of symbols always same as fill color
+ aSymbol.BorderColor = aSymbol.FillColor;
+
+ xSymbol.set( aFactory.createSymbol2D(
+ xResultGroup,
+ aPos,
+ aSymbolSize,
+ aSymbol.StandardSymbol,
+ aSymbol.BorderColor,
+ aSymbol.FillColor ));
+ }
+ else if( aSymbol.Style == chart2::SymbolStyle_GRAPHIC )
+ {
+ xSymbol.set( aFactory.createGraphic2D(
+ xResultGroup,
+ aPos,
+ aSymbolSize,
+ aSymbol.Graphic ));
+ }
+ else if( aSymbol.Style == chart2::SymbolStyle_AUTO )
+ {
+ DBG_ERROR("the given parameter is not allowed to contain an automatic symbol style");
+ }
+ }
+ }
+ }
+ catch( uno::Exception & ex )
+ {
+ ASSERT_EXCEPTION( ex );
+ }
+ break;
+
+ case chart2::LegendSymbolStyle_USER_DEFINED:
+ break;
+
+ default:
+ // just to remove warning (there is an auto-generated extra label)
+ break;
+ }
+
+ return xResult;
+}
+
+} // namespace chart
diff --git a/chart2/source/view/main/VLineProperties.cxx b/chart2/source/view/main/VLineProperties.cxx
new file mode 100644
index 000000000000..dc8409a6891d
--- /dev/null
+++ b/chart2/source/view/main/VLineProperties.cxx
@@ -0,0 +1,109 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_chart2.hxx"
+
+#include "VLineProperties.hxx"
+#include "macros.hxx"
+#include <com/sun/star/drawing/LineStyle.hpp>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+using namespace ::com::sun::star;
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// get line properties from a propertyset
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+VLineProperties::VLineProperties()
+{
+ this->Color = uno::makeAny( sal_Int32(0x000000) ); //type sal_Int32 UNO_NAME_LINECOLOR
+ this->LineStyle = uno::makeAny( drawing::LineStyle_SOLID ); //type drawing::LineStyle for property UNO_NAME_LINESTYLE
+ this->Transparence = uno::makeAny( sal_Int16(0) );//type sal_Int16 for property UNO_NAME_LINETRANSPARENCE
+ this->Width = uno::makeAny( sal_Int32(0) );//type sal_Int32 for property UNO_NAME_LINEWIDTH
+}
+
+void VLineProperties::initFromPropertySet( const uno::Reference< beans::XPropertySet >& xProp, bool bUseSeriesPropertyNames )
+{
+ if(xProp.is())
+ {
+ if( bUseSeriesPropertyNames ) try
+ {
+ this->Color = xProp->getPropertyValue( C2U( "BorderColor" ) );
+ this->LineStyle = xProp->getPropertyValue( C2U( "BorderStyle" ) );
+ this->Transparence = xProp->getPropertyValue( C2U( "BorderTransparency" ) );
+ this->Width = xProp->getPropertyValue( C2U( "BorderWidth" ) );
+ this->DashName = xProp->getPropertyValue( C2U( "BorderDashName" ) );
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+ else try
+ {
+ this->Color = xProp->getPropertyValue( C2U( "LineColor" ) );
+ this->LineStyle = xProp->getPropertyValue( C2U( "LineStyle" ) );
+ this->Transparence = xProp->getPropertyValue( C2U( "LineTransparence" ) );
+ this->Width = xProp->getPropertyValue( C2U( "LineWidth" ) );
+ this->DashName = xProp->getPropertyValue( C2U( "LineDashName" ) );
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+ }
+ else
+ this->LineStyle = uno::makeAny( drawing::LineStyle_NONE );
+}
+
+bool VLineProperties::isLineVisible() const
+{
+ bool bRet = false;
+
+ drawing::LineStyle aLineStyle(drawing::LineStyle_SOLID);
+ this->LineStyle >>= aLineStyle;
+ if( aLineStyle != drawing::LineStyle_NONE )
+ {
+ sal_Int16 nLineTransparence=0;
+ this->Transparence >>= nLineTransparence;
+ if(100!=nLineTransparence)
+ {
+ bRet = true;
+ }
+ }
+
+ return bRet;
+}
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
diff --git a/chart2/source/view/main/VPolarTransformation.cxx b/chart2/source/view/main/VPolarTransformation.cxx
new file mode 100644
index 000000000000..fd3037316cc6
--- /dev/null
+++ b/chart2/source/view/main/VPolarTransformation.cxx
@@ -0,0 +1,94 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_chart2.hxx"
+
+#include "VPolarTransformation.hxx"
+#include "ViewDefines.hxx"
+#include "CommonConverters.hxx"
+#include <algorithm>
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::RuntimeException;
+
+namespace chart
+{
+
+
+VPolarTransformation::VPolarTransformation( const PolarPlottingPositionHelper& rPositionHelper )
+ : m_aPositionHelper(rPositionHelper)
+ , m_aUnitCartesianToScene( rPositionHelper.getUnitCartesianToScene() )
+{
+}
+
+VPolarTransformation::~VPolarTransformation()
+{
+}
+
+// ____ XTransformation ____
+Sequence< double > SAL_CALL VPolarTransformation::transform(
+ const Sequence< double >& rSourceValues )
+ throw (RuntimeException,
+ lang::IllegalArgumentException)
+{
+ double fScaledLogicAngle = rSourceValues[0];
+ double fScaledLogicRadius = rSourceValues[1];
+
+ if( m_aPositionHelper.isSwapXAndY() )
+ std::swap(fScaledLogicAngle,fScaledLogicRadius);
+
+ double fAngleDegree = m_aPositionHelper.transformToAngleDegree( fScaledLogicAngle, false );
+ double fAnglePi = fAngleDegree*F_PI/180.0;
+ double fRadius = m_aPositionHelper.transformToRadius( fScaledLogicRadius, false);
+
+ double fX=fRadius*cos(fAnglePi);
+ double fY=fRadius*sin(fAnglePi);
+ double fZ=rSourceValues[2];
+
+ //!! applying matrix to vector does ignore translation, so it is important to use a B3DPoint here instead of B3DVector
+ ::basegfx::B3DPoint aPoint(fX,fY,fZ);
+ ::basegfx::B3DPoint aRet = m_aUnitCartesianToScene * aPoint;
+ return B3DPointToSequence(aRet);
+}
+
+sal_Int32 SAL_CALL VPolarTransformation::getSourceDimension()
+ throw (RuntimeException)
+{
+ return 3;
+}
+
+sal_Int32 SAL_CALL VPolarTransformation::getTargetDimension()
+ throw (RuntimeException)
+{
+ return 3;
+}
+
+
+} // namespace chart
diff --git a/chart2/source/view/main/VTitle.cxx b/chart2/source/view/main/VTitle.cxx
new file mode 100644
index 000000000000..f62142735b7c
--- /dev/null
+++ b/chart2/source/view/main/VTitle.cxx
@@ -0,0 +1,299 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_chart2.hxx"
+#include "VTitle.hxx"
+#include "CommonConverters.hxx"
+#include "macros.hxx"
+#include "PropertyMapper.hxx"
+#include "ShapeFactory.hxx"
+#include "RelativeSizeHelper.hxx"
+#include <com/sun/star/chart2/XFormattedString.hpp>
+#include <rtl/math.hxx>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/drawing/TextVerticalAdjust.hpp>
+#include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
+#include <com/sun/star/text/ControlCharacter.hpp>
+#include <com/sun/star/text/XText.hpp>
+#include <com/sun/star/text/XTextCursor.hpp>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+VTitle::VTitle( const uno::Reference< XTitle > & xTitle )
+ : m_xTarget(NULL)
+ , m_xShapeFactory(NULL)
+ , m_xTitle(xTitle)
+ , m_xShape(NULL)
+ , m_aCID()
+ , m_fRotationAngleDegree(0.0)
+ , m_nXPos(0)
+ , m_nYPos(0)
+{
+}
+
+VTitle::~VTitle()
+{
+}
+
+void SAL_CALL VTitle::init(
+ const uno::Reference< drawing::XShapes >& xTargetPage
+ , const uno::Reference< lang::XMultiServiceFactory >& xFactory
+ , const rtl::OUString& rCID )
+{
+ m_xTarget = xTargetPage;
+ m_xShapeFactory = xFactory;
+ m_aCID = rCID;
+}
+
+double VTitle::getRotationAnglePi() const
+{
+ return m_fRotationAngleDegree*F_PI/180.0;
+}
+
+awt::Size VTitle::getUnrotatedSize() const //size before rotation
+{
+ awt::Size aRet;
+ if(m_xShape.is())
+ aRet = m_xShape->getSize();
+ return aRet;
+}
+
+awt::Size VTitle::getFinalSize() const //size after rotation
+{
+ return ShapeFactory::getSizeAfterRotation(
+ m_xShape, m_fRotationAngleDegree );
+}
+
+void VTitle::changePosition( const awt::Point& rPos )
+{
+ if(!m_xShape.is())
+ return;
+ uno::Reference< beans::XPropertySet > xShapeProp( m_xShape, uno::UNO_QUERY );
+ if(!xShapeProp.is())
+ return;
+ try
+ {
+ m_nXPos = rPos.X;
+ m_nYPos = rPos.Y;
+
+ //set position matrix
+ //the matrix needs to be set at the end behind autogrow and such position influencing properties
+ ::basegfx::B2DHomMatrix aM;
+ aM.rotate( -m_fRotationAngleDegree*F_PI/180.0 );//#i78696#->#i80521#
+ aM.translate( m_nXPos, m_nYPos);
+ xShapeProp->setPropertyValue( C2U( "Transformation" ), uno::makeAny( B2DHomMatrixToHomogenMatrix3(aM) ) );
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+}
+
+void VTitle::createShapes(
+ const awt::Point& rPos
+ , const awt::Size& rReferenceSize )
+{
+ try
+ {
+ if(!m_xTitle.is())
+ return;
+
+ uno::Sequence< uno::Reference< XFormattedString > > aStringList = m_xTitle->getText();
+ if(aStringList.getLength()<=0)
+ return;
+
+ //create shape and add to page
+ uno::Reference< drawing::XShape > xShape(
+ m_xShapeFactory->createInstance( C2U(
+ "com.sun.star.drawing.TextShape" ) ), uno::UNO_QUERY );
+ m_xTarget->add(xShape);
+ m_xShape = xShape;
+
+ //set text and text properties
+ uno::Reference< text::XText > xText( xShape, uno::UNO_QUERY );
+ uno::Reference< text::XTextCursor > xTextCursor( xText->createTextCursor() );
+ uno::Reference< text::XTextRange > xTextRange( xTextCursor, uno::UNO_QUERY );
+ uno::Reference< beans::XPropertySet > xShapeProp( xShape, uno::UNO_QUERY );
+ uno::Reference< beans::XPropertySet > xTitleProperties( m_xTitle, uno::UNO_QUERY );
+ if( !xText.is() || !xTextRange.is() || !xTextCursor.is() || !xShapeProp.is() || !xTitleProperties.is() )
+ return;
+
+ tPropertyNameValueMap aValueMap;
+ //fill line-, fill- and paragraph-properties into the ValueMap
+ {
+ tMakePropertyNameMap aNameMap = PropertyMapper::getPropertyNameMapForParagraphProperties();
+ aNameMap( PropertyMapper::getPropertyNameMapForFillAndLineProperties() );
+
+ PropertyMapper::getValueMap( aValueMap, aNameMap, xTitleProperties );
+ }
+
+ //fill some more shape properties into the ValueMap
+ {
+ drawing::TextHorizontalAdjust eHorizontalAdjust = drawing::TextHorizontalAdjust_CENTER;
+ drawing::TextVerticalAdjust eVerticalAdjust = drawing::TextVerticalAdjust_CENTER;
+ //text::WritingMode eWritingMode = text::WritingMode_LR_TB;//@todo get correct one
+
+ aValueMap.insert( tPropertyNameValueMap::value_type( C2U("TextHorizontalAdjust"), uno::makeAny(eHorizontalAdjust) ) ); // drawing::TextHorizontalAdjust
+ aValueMap.insert( tPropertyNameValueMap::value_type( C2U("TextVerticalAdjust"), uno::makeAny(eVerticalAdjust) ) ); //drawing::TextVerticalAdjust
+ //aValueMap.insert( tPropertyNameValueMap::value_type( C2U("TextWritingMode"), uno::makeAny(eWritingMode) ) ); //text::WritingMode
+ aValueMap.insert( tPropertyNameValueMap::value_type( C2U("TextAutoGrowHeight"), uno::makeAny(sal_True) ) ); // sal_Bool
+ aValueMap.insert( tPropertyNameValueMap::value_type( C2U("TextAutoGrowWidth"), uno::makeAny(sal_True) ) ); // sal_Bool
+
+ ////aValueMap.insert( tPropertyNameValueMap::value_type( C2U("TextMaximumFrameWidth"), uno::makeAny(rSize.Width) ) ); //sal_Int32
+ ////aValueMap.insert( tPropertyNameValueMap::value_type( C2U("TextMaximumFrameHeight"), uno::makeAny(rSize.Height) ) ); //sal_Int32
+
+ //set name/classified ObjectID (CID)
+ if( m_aCID.getLength() )
+ aValueMap.insert( tPropertyNameValueMap::value_type( C2U("Name"), uno::makeAny( m_aCID ) ) ); //CID rtl::OUString
+ }
+
+ //set global title properties
+ {
+ tNameSequence aPropNames;
+ tAnySequence aPropValues;
+ PropertyMapper::getMultiPropertyListsFromValueMap( aPropNames, aPropValues, aValueMap );
+ PropertyMapper::setMultiProperties( aPropNames, aPropValues, xShapeProp );
+ }
+
+ sal_Bool bStackCharacters(sal_False);
+ try
+ {
+ xTitleProperties->getPropertyValue( C2U( "StackCharacters" ) ) >>= bStackCharacters;
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+ if(bStackCharacters)
+ {
+ //if the characters should be stacked we use only the first character properties for code simplicity
+ if( aStringList.getLength()>0 )
+ {
+ rtl::OUString aLabel;
+ for( sal_Int32 nN=0; nN<aStringList.getLength();nN++ )
+ aLabel += aStringList[nN]->getString();
+ aLabel = ShapeFactory::getStackedString( aLabel, bStackCharacters );
+
+ xTextCursor->gotoEnd(false);
+ xText->insertString( xTextRange, aLabel, false );
+ xTextCursor->gotoEnd(true);
+ uno::Reference< beans::XPropertySet > xTargetProps( xShape, uno::UNO_QUERY );
+ uno::Reference< beans::XPropertySet > xSourceProps( aStringList[0], uno::UNO_QUERY );
+
+ PropertyMapper::setMappedProperties( xTargetProps, xSourceProps
+ , PropertyMapper::getPropertyNameMapForCharacterProperties() );
+
+ // adapt font size according to page size
+ awt::Size aOldRefSize;
+ if( xTitleProperties->getPropertyValue( C2U("ReferencePageSize")) >>= aOldRefSize )
+ {
+ RelativeSizeHelper::adaptFontSizes( xTargetProps, aOldRefSize, rReferenceSize );
+ }
+ }
+ }
+ else
+ {
+ uno::Sequence< uno::Reference< text::XTextCursor > > aCursorList( aStringList.getLength() );
+ sal_Int32 nN = 0;
+ for( nN=0; nN<aStringList.getLength();nN++ )
+ {
+ xTextCursor->gotoEnd(false);
+ xText->insertString( xTextRange, aStringList[nN]->getString(), false );
+ xTextCursor->gotoEnd(true);
+ aCursorList[nN] = xText->createTextCursorByRange( uno::Reference< text::XTextRange >(xTextCursor,uno::UNO_QUERY) );
+ }
+ awt::Size aOldRefSize;
+ bool bHasRefPageSize =
+ ( xTitleProperties->getPropertyValue( C2U("ReferencePageSize")) >>= aOldRefSize );
+
+ //for( nN=0; nN<aStringList.getLength();nN++ ) //portion wise fromatting does not work still
+ if( aStringList.getLength()>0 )
+ {
+ //uno::Reference< beans::XPropertySet > xTargetProps( aCursorList[nN], uno::UNO_QUERY );
+ //uno::Reference< beans::XPropertySet > xSourceProps( aStringList[nN], uno::UNO_QUERY );
+ uno::Reference< beans::XPropertySet > xTargetProps( xShape, uno::UNO_QUERY );
+ uno::Reference< beans::XPropertySet > xSourceProps( aStringList[0], uno::UNO_QUERY );
+ PropertyMapper::setMappedProperties( xTargetProps, xSourceProps, PropertyMapper::getPropertyNameMapForCharacterProperties() );
+
+ // adapt font size according to page size
+ if( bHasRefPageSize )
+ {
+ RelativeSizeHelper::adaptFontSizes( xTargetProps, aOldRefSize, rReferenceSize );
+ }
+ }
+ }
+
+ // #i109336# Improve auto positioning in chart
+ float fFontHeight = 0.0;
+ if ( xShapeProp.is() && ( xShapeProp->getPropertyValue( C2U( "CharHeight" ) ) >>= fFontHeight ) )
+ {
+ fFontHeight *= ( 2540. / 72. ); // pt -> 1/100 mm
+ float fXFraction = 0.18;
+ sal_Int32 nXDistance = static_cast< sal_Int32 >( ::rtl::math::round( fFontHeight * fXFraction ) );
+ float fYFraction = 0.30;
+ sal_Int32 nYDistance = static_cast< sal_Int32 >( ::rtl::math::round( fFontHeight * fYFraction ) );
+ xShapeProp->setPropertyValue( C2U( "TextLeftDistance" ), uno::makeAny( nXDistance ) );
+ xShapeProp->setPropertyValue( C2U( "TextRightDistance" ), uno::makeAny( nXDistance ) );
+ xShapeProp->setPropertyValue( C2U( "TextUpperDistance" ), uno::makeAny( nYDistance ) );
+ xShapeProp->setPropertyValue( C2U( "TextLowerDistance" ), uno::makeAny( nYDistance ) );
+ }
+
+ try
+ {
+ double fAngleDegree = 0;
+ xTitleProperties->getPropertyValue( C2U( "TextRotation" ) ) >>= fAngleDegree;
+ m_fRotationAngleDegree += fAngleDegree;
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+ m_nXPos = rPos.X;
+ m_nYPos = rPos.Y;
+
+ //set position matrix
+ //the matrix needs to be set at the end behind autogrow and such position influencing properties
+ ::basegfx::B2DHomMatrix aM;
+ aM.rotate( -m_fRotationAngleDegree*F_PI/180.0 );//#i78696#->#i80521#
+ aM.translate( m_nXPos, m_nYPos );
+ xShapeProp->setPropertyValue( C2U( "Transformation" ), uno::makeAny( B2DHomMatrixToHomogenMatrix3(aM) ) );
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+}
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
diff --git a/chart2/source/view/main/VTitle.hxx b/chart2/source/view/main/VTitle.hxx
new file mode 100644
index 000000000000..8a6e7d6e4f16
--- /dev/null
+++ b/chart2/source/view/main/VTitle.hxx
@@ -0,0 +1,83 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _CHART2_VTITLE_HXX
+#define _CHART2_VTITLE_HXX
+
+#include <com/sun/star/chart2/XTitle.hpp>
+#include <com/sun/star/drawing/XShapes.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+
+//-----------------------------------------------------------------------------
+/**
+*/
+
+class VTitle
+{
+public:
+ VTitle( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::chart2::XTitle > & xTitle );
+ virtual ~VTitle();
+
+ void SAL_CALL init( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShapes >& xTargetPage
+ , const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xFactory
+ , const rtl::OUString& rCID );
+
+ void createShapes( const ::com::sun::star::awt::Point& rPos
+ , const ::com::sun::star::awt::Size& rReferenceSize );
+
+ double getRotationAnglePi() const;
+ ::com::sun::star::awt::Size getUnrotatedSize() const;
+ ::com::sun::star::awt::Size getFinalSize() const;
+ void changePosition( const ::com::sun::star::awt::Point& rPos );
+
+private:
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShapes > m_xTarget;
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::lang::XMultiServiceFactory> m_xShapeFactory;
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::chart2::XTitle > m_xTitle;
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShape > m_xShape;
+ rtl::OUString m_aCID;
+
+ double m_fRotationAngleDegree;
+ sal_Int32 m_nXPos;
+ sal_Int32 m_nYPos;
+};
+
+//.............................................................................
+} //namespace chart
+//.............................................................................
+#endif
+
diff --git a/chart2/source/view/main/_serviceregistration_view.cxx b/chart2/source/view/main/_serviceregistration_view.cxx
new file mode 100644
index 000000000000..26f8b9d7cf7e
--- /dev/null
+++ b/chart2/source/view/main/_serviceregistration_view.cxx
@@ -0,0 +1,71 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_chart2.hxx"
+#include <cppuhelper/implementationentry.hxx>
+
+#include "ChartView.hxx"
+
+static struct ::cppu::ImplementationEntry g_entries_chart2_view[] =
+{
+ {
+ ::chart::ChartView::create
+ , ::chart::ChartView::getImplementationName_Static
+ , ::chart::ChartView::getSupportedServiceNames_Static
+ , ::cppu::createSingleComponentFactory
+ , 0
+ , 0
+ }
+ ,{ 0, 0, 0, 0, 0, 0 }
+};
+
+// component exports
+extern "C"
+{
+//==================================================================================================
+SAL_DLLPUBLIC_EXPORT void SAL_CALL component_getImplementationEnvironment(
+ const sal_Char ** ppEnvTypeName, uno_Environment ** /* ppEnv */ )
+{
+ *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
+}
+//==================================================================================================
+SAL_DLLPUBLIC_EXPORT sal_Bool SAL_CALL component_writeInfo(
+ void * pServiceManager, void * pRegistryKey )
+{
+ return ::cppu::component_writeInfoHelper(
+ pServiceManager, pRegistryKey, g_entries_chart2_view );
+}
+//==================================================================================================
+SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory(
+ const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey )
+{
+ return ::cppu::component_getFactoryHelper(
+ pImplName, pServiceManager, pRegistryKey , g_entries_chart2_view );
+}
+}
+//=========================================================================
diff --git a/chart2/source/view/main/makefile.mk b/chart2/source/view/main/makefile.mk
new file mode 100644
index 000000000000..ec9c99f2a898
--- /dev/null
+++ b/chart2/source/view/main/makefile.mk
@@ -0,0 +1,68 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ= ..$/..$/..
+PRJINC= $(PRJ)$/source
+PRJNAME= chart2
+TARGET= chview
+
+ENABLE_EXCEPTIONS= TRUE
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE: settings.mk
+.INCLUDE: $(PRJ)$/chartview.pmk
+
+# --- export library -------------------------------------------------
+
+#object files to build and link together to lib $(SLB)$/$(TARGET).lib
+SLOFILES = \
+ $(SLO)$/ChartItemPool.obj \
+ $(SLO)$/DrawModelWrapper.obj \
+ $(SLO)$/NumberFormatterWrapper.obj \
+ $(SLO)$/PropertyMapper.obj \
+ $(SLO)$/Stripe.obj \
+ $(SLO)$/VLineProperties.obj \
+ $(SLO)$/ShapeFactory.obj \
+ $(SLO)$/VLegendSymbolFactory.obj \
+ $(SLO)$/DataPointSymbolSupplier.obj \
+ $(SLO)$/Linear3DTransformation.obj \
+ $(SLO)$/VPolarTransformation.obj \
+ $(SLO)$/Clipping.obj \
+ $(SLO)$/PlottingPositionHelper.obj \
+ $(SLO)$/LabelPositionHelper.obj \
+ $(SLO)$/PolarLabelPositionHelper.obj \
+ $(SLO)$/PlotterBase.obj \
+ $(SLO)$/VDataSeries.obj \
+ $(SLO)$/VLegend.obj \
+ $(SLO)$/VTitle.obj \
+ $(SLO)$/ChartView.obj \
+ $(SLO)$/_serviceregistration_view.obj
+
+# --- Targets -----------------------------------------------------------------
+
+.INCLUDE: target.mk
diff --git a/chart2/source/view/makefile.mk b/chart2/source/view/makefile.mk
new file mode 100644
index 000000000000..aa3c149a768f
--- /dev/null
+++ b/chart2/source/view/makefile.mk
@@ -0,0 +1,120 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ= ..$/..
+PRJNAME= chart2
+TARGET= chartview
+
+USE_DEFFILE= TRUE
+ENABLE_EXCEPTIONS= TRUE
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE: $(PRJ)$/util$/makefile.pmk
+.INCLUDE: $(PRJ)$/chartview.pmk
+
+# --- export library -------------------------------------------------
+
+#You can use several library macros of this form to build libraries that
+#do not consist of all object files in a directory or to merge different libraries.
+LIB1TARGET= $(SLB)$/$(TARGET).lib
+
+LIB1FILES= \
+ $(SLB)$/chvaxes.lib \
+ $(SLB)$/chvtypes.lib \
+ $(SLB)$/chvdiagram.lib \
+ $(SLB)$/chview.lib
+
+#--------
+
+#Indicates the filename of the shared library.
+SHL1TARGET= $(TARGET)$(DLLPOSTFIX)
+
+#indicates dependencies:
+.IF "$(COM)" == "MSC"
+SHL1DEPN = \
+ $(LB)$/icharttools.lib
+.ELSE
+SHL1DEPN =
+.ENDIF
+
+#Specifies an import library to create. For Win32 only.
+SHL1IMPLIB= i$(TARGET)
+
+#Specifies libraries from the same module to put into the shared library.
+#was created above
+SHL1LIBS= $(LIB1TARGET)
+
+#Links import libraries.
+
+SHL1STDLIBS= $(CHARTTOOLS) \
+ $(CPPULIB) \
+ $(EDITENGLIB) \
+ $(CPPUHELPERLIB) \
+ $(COMPHELPERLIB) \
+ $(SALLIB) \
+ $(SVLLIB) \
+ $(SVTOOLLIB) \
+ $(SVXCORELIB) \
+ $(TOOLSLIB) \
+ $(UNOTOOLSLIB) \
+ $(BASEGFXLIB) \
+ $(VCLLIB) \
+ $(SFXLIB) \
+ $(BASEGFXLIB)
+
+#--------exports
+
+#specifies the exported symbols for Windows only:
+SHL1DEF= $(MISC)$/$(SHL1TARGET).def
+
+#Specifies the library name to parse for symbols. For Win32 only.
+DEFLIB1NAME= $(TARGET)
+
+#A file of symbols to export.
+#DEF1EXPORTFILE= $(PRJ)$/source$/inc$/exports.dxp
+
+#--------definition file
+
+#name of the definition file:
+DEF1NAME= $(SHL1TARGET)
+
+# indicates definition file dependencies
+DEF1DEPN= $(MISC)$/$(SHL1TARGET).flt
+
+#A comment on the definition file.
+DEF1DES= Viewable Component Chart View
+
+# --- Targets -----------------------------------------------------------------
+
+.INCLUDE: target.mk
+
+# --- Filter -----------------------------------------------------------
+
+$(MISC)$/$(SHL1TARGET).flt: makefile.mk \
+ exports.flt
+ $(TYPE) exports.flt > $@