chart2/Library_chartcore.mk                        |    1 
 chart2/source/view/main/ChartView.cxx              |  778 ---------------------
 chart2/source/view/main/SeriesPlotterContainer.cxx |  761 ++++++++++++++++++++
 chart2/source/view/main/SeriesPlotterContainer.hxx |  164 ++++
 4 files changed, 933 insertions(+), 771 deletions(-)

New commits:
commit 39107dccb3c2fad67057ff06bf0efb5fe8467c8a
Author:     Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk>
AuthorDate: Mon Apr 18 20:08:57 2022 +0900
Commit:     Tomaž Vajngerl <qui...@gmail.com>
CommitDate: Tue Apr 19 08:53:35 2022 +0200

    chart2: extract SeriesPlotterContainer into its own file
    
    Change-Id: If190f0d99d5686e90fa56487744a9a663b345fad
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133121
    Tested-by: Tomaž Vajngerl <qui...@gmail.com>
    Reviewed-by: Tomaž Vajngerl <qui...@gmail.com>
    (cherry picked from commit dc8cbdae0a96708872cbfb6bd6e21deec2ce9a0b)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133159
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>

diff --git a/chart2/Library_chartcore.mk b/chart2/Library_chartcore.mk
index dd13d9b7b860..54585db4d30d 100644
--- a/chart2/Library_chartcore.mk
+++ b/chart2/Library_chartcore.mk
@@ -110,6 +110,7 @@ $(eval $(call gb_Library_add_exception_objects,chartcore,\
     chart2/source/view/main/PlottingPositionHelper \
     chart2/source/view/main/PolarLabelPositionHelper \
     chart2/source/view/main/PropertyMapper \
+    chart2/source/view/main/SeriesPlotterContainer \
     chart2/source/view/main/ShapeFactory \
     chart2/source/view/main/Stripe \
     chart2/source/view/main/VDataSeries \
diff --git a/chart2/source/view/main/ChartView.cxx 
b/chart2/source/view/main/ChartView.cxx
index 04eb2193cdd6..f658eadb15ce 100644
--- a/chart2/source/view/main/ChartView.cxx
+++ b/chart2/source/view/main/ChartView.cxx
@@ -19,6 +19,8 @@
 
 #include <config_feature_desktop.h>
 
+#include "SeriesPlotterContainer.hxx"
+
 #include <ChartView.hxx>
 #include <chartview/DrawModelWrapper.hxx>
 #include <NumberFormatterWrapper.hxx>
@@ -107,6 +109,7 @@
 
 #include <memory>
 #include <libxml/xmlwriter.h>
+
 namespace com::sun::star::chart2 { class XChartDocument; }
 
 namespace chart {
@@ -117,774 +120,6 @@ using ::com::sun::star::uno::Reference;
 using ::com::sun::star::uno::Sequence;
 using ::com::sun::star::uno::Any;
 
-namespace {
-
-typedef std::vector<std::unique_ptr<VSeriesPlotter> > SeriesPlottersType;
-
-/** This class is a container of `SeriesPlotter` objects (such as `PieChart`
- *  instances). It is used for initializing coordinate systems, axes and scales
- *  of all series plotters which belongs to the container.
- */
-class SeriesPlotterContainer
-{
-public:
-    explicit SeriesPlotterContainer( std::vector< 
std::unique_ptr<VCoordinateSystem> >& rVCooSysList );
-    ~SeriesPlotterContainer();
-
-    /** It is used to set coordinate systems (`m_rVCooSysList`), this method
-     *  is invoked by `ChartView::createShapes2D` before of
-     *  `ChartView::impl_createDiagramAndContent`.
-     *  Coordinate systems are retrieved through the 
`XCoordinateSystemContainer`
-     *  interface implemented by a diagram object which is provided by the
-     *  `ChartModel` object passed to the method 
(`rChartModel.getFirstDiagram()`).
-     *
-     *  It is used for creating series plotters and appending them
-     *  to `m_aSeriesPlotterList`. The created series plotters are initialized
-     *  through data (number formats supplier, color scheme, data series),
-     *  extracted from the chart model or the diagram objects. An exception is
-     *  the explicit category provider that is retrieved through the
-     *  `VCoordinateSystem` object used by the series plotter.
-     *
-     *  It sets the minimum-maximum supplier for a coordinate system:
-     *  this supplier is the series plotter itself which utilizes the given
-     *  coordinate system. In fact `VSeriesPlotter` has 
`MinimumMaximumSupplier`
-     *  as one of its base classes.
-     *  Hence, for instance, a `PieChart`, which is a series plotter, is
-     *  a `MinimumMaximumSupplier`, too.
-     */
-    void initializeCooSysAndSeriesPlotter( ChartModel& rModel );
-
-    /** This method is invoked by `ChartView::impl_createDiagramAndContent`.
-     *  It iterates on every axis of every coordinate systems, and if the axis
-     *  is not yet present in `m_aAxisUsageList` it creates a new `AxisUsage`
-     *  object and initialize its `aAutoScaling` member to the `ScaleData`
-     *  object of the current axis.
-     */
-    void initAxisUsageList(const Date& rNullDate);
-
-    /**
-     * Perform automatic axis scaling and determine the amount and spacing of
-     * increments.  It assumes that the caller has determined the size of the
-     * largest axis label text object prior to calling this method.
-     *
-     * The new axis scaling data will be stored in the VCoordinateSystem
-     * objects.  The label alignment direction for each axis will also get
-     * determined during this process, and stored in VAxis.
-     *
-     * This method is invoked by `ChartView::impl_createDiagramAndContent`
-     * soon after `initAxisUsageList`.
-     * It initializes explicit scale and increment objects for all coordinate
-     * systems in `m_rVCooSysList`.
-     * This action is achieved by iterating on the `m_aAxisUsageList` 
container,
-     * and performing 3 steps:
-     *   1- call `VCoordinateSystem::prepareAutomaticAxisScaling` for setting
-     *      scaling parameters of the `aAutoScaling` member (a 
`ScaleAutomatism`
-     *      object) for the current `AxisUsage` instance
-     *      (see `VCoordinateSystem::prepareAutomaticAxisScaling`);
-     *   2- calculate the explicit scale and increment objects
-     *      (see ScaleAutomatism::calculateExplicitScaleAndIncrement);
-     *   3- set the explicit scale and increment objects for each coordinate
-     *      system.
-     */
-    void doAutoScaling( ChartModel& rModel );
-
-    /**
-     * After auto-scaling is performed, call this method to set the explicit
-     * scaling and increment data to all relevant VAxis objects.
-     */
-    void updateScalesAndIncrementsOnAxes();
-
-    /**
-     * After auto-scaling is performed, call this method to set the explicit
-     * scaling data to all the plotters.
-     */
-    void setScalesFromCooSysToPlotter();
-
-    void setNumberFormatsFromAxes();
-    drawing::Direction3D getPreferredAspectRatio();
-
-    SeriesPlottersType& getSeriesPlotterList() { return m_aSeriesPlotterList; }
-    std::vector< std::unique_ptr<VCoordinateSystem> >& getCooSysList() { 
return m_rVCooSysList; }
-    std::vector< LegendEntryProvider* > getLegendEntryProviderList();
-
-    void AdaptScaleOfYAxisWithoutAttachedSeries( ChartModel& rModel );
-
-    bool isCategoryPositionShifted(
-        const chart2::ScaleData& rSourceScale, bool bHasComplexCategories );
-
-private:
-    /** A vector of series plotters.
-     */
-    SeriesPlottersType m_aSeriesPlotterList;
-
-    /** A vector of coordinate systems.
-     */
-    std::vector< std::unique_ptr<VCoordinateSystem> >& m_rVCooSysList;
-
-    /** A map whose key is a `XAxis` interface and the related value is
-     *  an object of `AxisUsage` type.
-     */
-    std::map< uno::Reference< XAxis >, AxisUsage > m_aAxisUsageList;
-
-    /**
-     * Max axis index of all dimensions.  Currently this can be either 0 or 1
-     * since we only support primary and secondary axes per dimension.  The
-     * value of 0 means all dimensions have only primary axis, while 1 means
-     * at least one dimension has a secondary axis.
-     */
-    sal_Int32 m_nMaxAxisIndex;
-
-    bool m_bChartTypeUsesShiftedCategoryPositionPerDefault;
-    sal_Int32 m_nDefaultDateNumberFormat;
-};
-
-SeriesPlotterContainer::SeriesPlotterContainer( std::vector< 
std::unique_ptr<VCoordinateSystem> >& rVCooSysList )
-        : m_rVCooSysList( rVCooSysList )
-        , m_nMaxAxisIndex(0)
-        , m_bChartTypeUsesShiftedCategoryPositionPerDefault(false)
-        , m_nDefaultDateNumberFormat(0)
-{
-}
-
-SeriesPlotterContainer::~SeriesPlotterContainer()
-{
-    // - remove plotter from coordinatesystems
-    for(auto & nC : m_rVCooSysList)
-        nC->clearMinimumAndMaximumSupplierList();
-}
-
-std::vector< LegendEntryProvider* > 
SeriesPlotterContainer::getLegendEntryProviderList()
-{
-    std::vector< LegendEntryProvider* > aRet( m_aSeriesPlotterList.size() );
-    sal_Int32 nN = 0;
-    for( const std::unique_ptr<VSeriesPlotter>& aPlotter : 
m_aSeriesPlotterList)
-        aRet[nN++] = aPlotter.get();
-    return aRet;
-}
-
-VCoordinateSystem* findInCooSysList( const std::vector< 
std::unique_ptr<VCoordinateSystem> >& rVCooSysList
-                                    , const uno::Reference< XCoordinateSystem 
>& xCooSys )
-{
-    for(auto & pVCooSys : rVCooSysList)
-    {
-        if(pVCooSys->getModel()==xCooSys)
-            return pVCooSys.get();
-    }
-    return nullptr;
-}
-
-VCoordinateSystem* lcl_getCooSysForPlotter( const std::vector< 
std::unique_ptr<VCoordinateSystem> >& rVCooSysList, MinimumAndMaximumSupplier* 
pMinimumAndMaximumSupplier )
-{
-    if(!pMinimumAndMaximumSupplier)
-        return nullptr;
-    for(auto & pVCooSys : rVCooSysList)
-    {
-        if(pVCooSys->hasMinimumAndMaximumSupplier( pMinimumAndMaximumSupplier 
))
-            return pVCooSys.get();
-    }
-    return nullptr;
-}
-
-VCoordinateSystem* addCooSysToList( std::vector< 
std::unique_ptr<VCoordinateSystem> >& rVCooSysList
-            , const uno::Reference< XCoordinateSystem >& xCooSys
-            , ChartModel& rChartModel )
-{
-    VCoordinateSystem* pExistingVCooSys = findInCooSysList( rVCooSysList, 
xCooSys );
-    if( pExistingVCooSys )
-        return pExistingVCooSys;
-
-    std::unique_ptr<VCoordinateSystem> pVCooSys = 
VCoordinateSystem::createCoordinateSystem(xCooSys );
-    if(!pVCooSys)
-        return nullptr;
-
-    OUString aCooSysParticle( 
ObjectIdentifier::createParticleForCoordinateSystem( xCooSys, rChartModel ) );
-    pVCooSys->setParticle(aCooSysParticle);
-
-    pVCooSys->setExplicitCategoriesProvider( new 
ExplicitCategoriesProvider(xCooSys, rChartModel) );
-    rVCooSysList.push_back( std::move(pVCooSys) );
-    return rVCooSysList.back().get();
-}
-
-void SeriesPlotterContainer::initializeCooSysAndSeriesPlotter(
-              ChartModel& rChartModel )
-{
-    uno::Reference< XDiagram > xDiagram( rChartModel.getFirstDiagram() );
-    if( !xDiagram.is())
-        return;
-
-    uno::Reference< util::XNumberFormatsSupplier > xNumberFormatsSupplier( 
&rChartModel );
-    if( rChartModel.hasInternalDataProvider() && 
DiagramHelper::isSupportingDateAxis( xDiagram ) )
-            m_nDefaultDateNumberFormat=DiagramHelper::getDateNumberFormat( 
xNumberFormatsSupplier );
-
-    sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram );
-    if(!nDimensionCount)
-    {
-        //@todo handle mixed dimension
-        nDimensionCount = 2;
-    }
-
-    bool bSortByXValues = false;
-    bool bConnectBars = false;
-    bool bGroupBarsPerAxis = true;
-    bool bIncludeHiddenCells = true;
-    bool bSecondaryYaxisVisible = true;
-    sal_Int32 nStartingAngle = 90;
-    sal_Int32 n3DRelativeHeight = 100;
-    try
-    {
-        uno::Reference< beans::XPropertySet > xDiaProp( xDiagram, 
uno::UNO_QUERY_THROW );
-        xDiaProp->getPropertyValue(CHART_UNONAME_SORT_BY_XVALUES) >>= 
bSortByXValues;
-        xDiaProp->getPropertyValue( "ConnectBars" ) >>= bConnectBars;
-        xDiaProp->getPropertyValue( "GroupBarsPerAxis" ) >>= bGroupBarsPerAxis;
-        xDiaProp->getPropertyValue( "IncludeHiddenCells" ) >>= 
bIncludeHiddenCells;
-        xDiaProp->getPropertyValue( "StartingAngle" ) >>= nStartingAngle;
-
-        if (nDimensionCount == 3)
-        {
-            xDiaProp->getPropertyValue( "3DRelativeHeight" ) >>= 
n3DRelativeHeight;
-        }
-    }
-    catch( const uno::Exception & )
-    {
-        DBG_UNHANDLED_EXCEPTION("chart2" );
-    }
-
-    //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,rChartModel);
-        // Let's check whether the secondary Y axis is visible
-        try
-        {
-            if (xCooSys->getMaximumAxisIndexByDimension(1) > 0)
-            {
-                Reference< beans::XPropertySet > 
xAxisProp(xCooSys->getAxisByDimension(1, 1), uno::UNO_QUERY);
-                xAxisProp->getPropertyValue("Show") >>= bSecondaryYaxisVisible;
-            }
-        }
-        catch (const lang::IndexOutOfBoundsException&)
-        {
-            TOOLS_WARN_EXCEPTION("chart2", "" );
-        }
-        //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(nDimensionCount == 3 && 
xChartType->getChartType().equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_PIE))
-            {
-                uno::Reference< beans::XPropertySet > xPropertySet( 
xChartType, uno::UNO_QUERY );
-                if (xPropertySet.is())
-                {
-                    try
-                    {
-                        sal_Int32 n3DRelativeHeightOldValue(100);
-                        uno::Any aAny = xPropertySet->getPropertyValue( 
"3DRelativeHeight" );
-                        aAny >>= n3DRelativeHeightOldValue;
-                        if (n3DRelativeHeightOldValue != n3DRelativeHeight)
-                            xPropertySet->setPropertyValue( 
"3DRelativeHeight", uno::Any(n3DRelativeHeight) );
-                    }
-                    catch (const uno::Exception&) { }
-                }
-            }
-
-            if(nT==0)
-                m_bChartTypeUsesShiftedCategoryPositionPerDefault = 
ChartTypeHelper::shiftCategoryPosAtXAxisPerDefault( xChartType );
-
-            bool bExcludingPositioning = 
DiagramHelper::getDiagramPositioningMode( xDiagram ) == 
DiagramPositioningMode_EXCLUDING;
-            VSeriesPlotter* pPlotter = VSeriesPlotter::createSeriesPlotter( 
xChartType, nDimensionCount, bExcludingPositioning );
-            if( !pPlotter )
-                continue;
-
-            m_aSeriesPlotterList.push_back( 
std::unique_ptr<VSeriesPlotter>(pPlotter) );
-            pPlotter->setNumberFormatsSupplier( xNumberFormatsSupplier );
-            pPlotter->setColorScheme( xColorScheme );
-            if(pVCooSys)
-                pPlotter->setExplicitCategoriesProvider( 
pVCooSys->getExplicitCategoriesProvider() );
-            sal_Int32 nMissingValueTreatment = 
DiagramHelper::getCorrectedMissingValueTreatment( xDiagram, xChartType );
-
-            if(pVCooSys)
-                pVCooSys->addMinimumAndMaximumSupplier(pPlotter);
-
-            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 > const & xDataSeries = 
aSeriesList[nS];
-                if(!xDataSeries.is())
-                    continue;
-                if( !bIncludeHiddenCells && 
!DataSeriesHelper::hasUnhiddenData(xDataSeries) )
-                    continue;
-
-                std::unique_ptr<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 );
-
-                OUString aSeriesParticle( 
ObjectIdentifier::createParticleForSeries( 0, nCS, nT, nS ) );
-                pSeries->setParticle(aSeriesParticle);
-
-                OUString aRole( 
ChartTypeHelper::getRoleOfSequenceForDataLabelNumberFormatDetection( xChartType 
) );
-                
pSeries->setRoleOfSequenceForDataLabelNumberFormatDetection(aRole);
-
-                //ignore secondary axis for charttypes that do not support them
-                if( pSeries->getAttachedAxisIndex() != MAIN_AXIS_INDEX &&
-                  ( !ChartTypeHelper::isSupportingSecondaryAxis( xChartType, 
nDimensionCount ) ||
-                    !bSecondaryYaxisVisible ) )
-                {
-                    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( std::move(pSeries), zSlot, xSlot, ySlot );
-            }
-        }
-    }
-
-    //transport seriesnames to the coordinatesystems if needed
-    if( m_aSeriesPlotterList.empty() )
-        return;
-
-    uno::Sequence< OUString > aSeriesNames;
-    bool bSeriesNamesInitialized = false;
-    for(auto & pVCooSys : m_rVCooSysList)
-    {
-        if( pVCooSys->needSeriesNamesForAxis() )
-        {
-            if(!bSeriesNamesInitialized)
-            {
-                aSeriesNames = m_aSeriesPlotterList[0]->getSeriesNames();
-                bSeriesNamesInitialized = true;
-            }
-            pVCooSys->setSeriesNamesForAxis( aSeriesNames );
-        }
-    }
-}
-
-bool SeriesPlotterContainer::isCategoryPositionShifted(
-    const chart2::ScaleData& rSourceScale, bool bHasComplexCategories )
-{
-    if (rSourceScale.AxisType == AxisType::CATEGORY)
-        return bHasComplexCategories || rSourceScale.ShiftedCategoryPosition 
|| m_bChartTypeUsesShiftedCategoryPositionPerDefault;
-
-    if (rSourceScale.AxisType == AxisType::DATE)
-        return rSourceScale.ShiftedCategoryPosition;
-
-    return rSourceScale.AxisType == AxisType::SERIES;
-}
-
-void SeriesPlotterContainer::initAxisUsageList(const Date& rNullDate)
-{
-    m_aAxisUsageList.clear();
-
-    // Loop through coordinate systems in the diagram (though for now
-    // there should only be one coordinate system per diagram).
-    for (auto & pVCooSys : m_rVCooSysList)
-    {
-        uno::Reference<XCoordinateSystem> xCooSys = pVCooSys->getModel();
-        sal_Int32 nDimCount = xCooSys->getDimension();
-        bool bComplexCategoryAllowed = 
ChartTypeHelper::isSupportingComplexCategory(AxisHelper::getChartTypeByIndex(xCooSys,
 0));
-
-        for (sal_Int32 nDimIndex = 0; nDimIndex < nDimCount; ++nDimIndex)
-        {
-            bool bDateAxisAllowed = ChartTypeHelper::isSupportingDateAxis(
-                AxisHelper::getChartTypeByIndex(xCooSys, 0), nDimIndex);
-
-            // Each dimension may have primary and secondary axes.
-            const sal_Int32 nMaxAxisIndex = 
xCooSys->getMaximumAxisIndexByDimension(nDimIndex);
-            for (sal_Int32 nAxisIndex = 0; nAxisIndex <= nMaxAxisIndex; 
++nAxisIndex)
-            {
-                uno::Reference<XAxis> xAxis = 
xCooSys->getAxisByDimension(nDimIndex, nAxisIndex);
-
-                if (!xAxis.is())
-                    continue;
-
-                if (m_aAxisUsageList.find(xAxis) == m_aAxisUsageList.end())
-                {
-                    // Create axis usage object for this axis.
-
-                    chart2::ScaleData aSourceScale = xAxis->getScaleData();
-                    ExplicitCategoriesProvider* pCatProvider = 
pVCooSys->getExplicitCategoriesProvider();
-                    if (nDimIndex == 0)
-                        AxisHelper::checkDateAxis( aSourceScale, pCatProvider, 
bDateAxisAllowed );
-
-                    bool bHasComplexCat = pCatProvider && 
pCatProvider->hasComplexCategories() && bComplexCategoryAllowed;
-                    aSourceScale.ShiftedCategoryPosition = 
isCategoryPositionShifted(aSourceScale, bHasComplexCat);
-
-                    m_aAxisUsageList[xAxis].aAutoScaling = 
ScaleAutomatism(aSourceScale, rNullDate);
-                }
-
-                AxisUsage& rAxisUsage = m_aAxisUsageList[xAxis];
-                rAxisUsage.addCoordinateSystem(pVCooSys.get(), nDimIndex, 
nAxisIndex);
-            }
-        }
-    }
-
-    // Determine the highest axis index of all dimensions.
-    m_nMaxAxisIndex = 0;
-    for (const auto & pVCooSys : m_rVCooSysList)
-    {
-        uno::Reference<XCoordinateSystem> xCooSys = pVCooSys->getModel();
-        sal_Int32 nDimCount = xCooSys->getDimension();
-
-        for (sal_Int32 nDimIndex = 0; nDimIndex < nDimCount; ++nDimIndex)
-        {
-            for (auto & axisUsage : m_aAxisUsageList)
-            {
-                sal_Int32 nLocalMax = 
axisUsage.second.getMaxAxisIndexForDimension(nDimIndex);
-                if (m_nMaxAxisIndex < nLocalMax)
-                    m_nMaxAxisIndex = nLocalMax;
-            }
-        }
-    }
-}
-
-void SeriesPlotterContainer::setScalesFromCooSysToPlotter()
-{
-    //set scales to plotter to enable them to provide the preferred scene 
AspectRatio
-    for( const std::unique_ptr<VSeriesPlotter>& aPlotter : 
m_aSeriesPlotterList )
-    {
-        VSeriesPlotter* pSeriesPlotter = aPlotter.get();
-        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 numberformats to plotter to enable them to display the data labels 
in the numberformat of the axis
-    for( const std::unique_ptr<VSeriesPlotter>& aPlotter : 
m_aSeriesPlotterList )
-    {
-        VSeriesPlotter* pSeriesPlotter = aPlotter.get();
-        VCoordinateSystem* pVCooSys = lcl_getCooSysForPlotter( m_rVCooSysList, 
pSeriesPlotter );
-        if(pVCooSys)
-        {
-            AxesNumberFormats aAxesNumberFormats;
-            const 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(CHART_UNONAME_NUMFMT) >>= nNumberFormatKey )
-                            {
-                                aAxesNumberFormats.setFormat( 
nNumberFormatKey, nDimensionIndex, nAxisIndex );
-                            }
-                            else if( nDimensionIndex==0 )
-                            {
-                                //provide a default date format for date axis 
with own data
-                                aAxesNumberFormats.setFormat( 
m_nDefaultDateNumberFormat, nDimensionIndex, nAxisIndex );
-                            }
-                        }
-                    }
-                    catch( const lang::IndexOutOfBoundsException& )
-                    {
-                        TOOLS_WARN_EXCEPTION("chart2", "" );
-                    }
-                }
-            }
-        }
-    }
-}
-
-void SeriesPlotterContainer::updateScalesAndIncrementsOnAxes()
-{
-    for(auto & nC : m_rVCooSysList)
-        nC->updateScalesAndIncrementsOnAxes();
-}
-
-void SeriesPlotterContainer::doAutoScaling( ChartModel& rChartModel )
-{
-    if (m_aSeriesPlotterList.empty() || m_aAxisUsageList.empty())
-        // We need these two containers populated to do auto-scaling.  Bail 
out.
-        return;
-
-    //iterate over the main scales first than secondary axis
-    for (sal_Int32 nAxisIndex = 0; nAxisIndex <= m_nMaxAxisIndex; ++nAxisIndex)
-    {
-        // - first do autoscale for all x and z scales (because they are 
treated independent)
-        for (auto & axisUsage : m_aAxisUsageList)
-        {
-            AxisUsage& rAxisUsage = axisUsage.second;
-
-            rAxisUsage.prepareAutomaticAxisScaling(rAxisUsage.aAutoScaling, 0, 
nAxisIndex);
-            rAxisUsage.prepareAutomaticAxisScaling(rAxisUsage.aAutoScaling, 2, 
nAxisIndex);
-
-            ExplicitScaleData       aExplicitScale;
-            ExplicitIncrementData   aExplicitIncrement;
-            rAxisUsage.aAutoScaling.calculateExplicitScaleAndIncrement( 
aExplicitScale, aExplicitIncrement );
-
-            rAxisUsage.setExplicitScaleAndIncrement(0, nAxisIndex, 
aExplicitScale, aExplicitIncrement);
-            rAxisUsage.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 (auto & axisUsage : m_aAxisUsageList)
-        {
-            AxisUsage& rAxisUsage = axisUsage.second;
-
-            rAxisUsage.prepareAutomaticAxisScaling(rAxisUsage.aAutoScaling, 1, 
nAxisIndex);
-
-            ExplicitScaleData       aExplicitScale;
-            ExplicitIncrementData   aExplicitIncrement;
-            rAxisUsage.aAutoScaling.calculateExplicitScaleAndIncrement( 
aExplicitScale, aExplicitIncrement );
-
-            rAxisUsage.setExplicitScaleAndIncrement(0, nAxisIndex, 
aExplicitScale, aExplicitIncrement);
-            rAxisUsage.setExplicitScaleAndIncrement(1, nAxisIndex, 
aExplicitScale, aExplicitIncrement);
-            rAxisUsage.setExplicitScaleAndIncrement(2, nAxisIndex, 
aExplicitScale, aExplicitIncrement);
-        }
-    }
-    AdaptScaleOfYAxisWithoutAttachedSeries( rChartModel );
-}
-
-void SeriesPlotterContainer::AdaptScaleOfYAxisWithoutAttachedSeries( 
ChartModel& rModel )
-{
-    //issue #i80518#
-    for( sal_Int32 nAxisIndex=0; nAxisIndex<=m_nMaxAxisIndex; nAxisIndex++ )
-    {
-        for (auto & axisUsage : m_aAxisUsageList)
-        {
-            AxisUsage& rAxisUsage = axisUsage.second;
-            std::vector< VCoordinateSystem* > aVCooSysList_Y = 
rAxisUsage.getCoordinateSystems( 1, nAxisIndex );
-            if( aVCooSysList_Y.empty() )
-                continue;
-
-            uno::Reference< XDiagram > xDiagram( rModel.getFirstDiagram() );
-            if (!xDiagram.is())
-                continue;
-
-            bool bSeriesAttachedToThisAxis = false;
-            sal_Int32 nAttachedAxisIndex = -1;
-            {
-                std::vector< Reference< XDataSeries > > aSeriesVector( 
DiagramHelper::getDataSeriesFromDiagram( xDiagram ) );
-                for (auto const& series : aSeriesVector)
-                {
-                    sal_Int32 nCurrentIndex = 
DataSeriesHelper::getAttachedAxisIndex(series);
-                    if( nAxisIndex == nCurrentIndex )
-                    {
-                        bSeriesAttachedToThisAxis = true;
-                        break;
-                    }
-                    else if( nAttachedAxisIndex<0 || 
nAttachedAxisIndex>nCurrentIndex )
-                        nAttachedAxisIndex=nCurrentIndex;
-                }
-            }
-
-            if (bSeriesAttachedToThisAxis || nAttachedAxisIndex < 0)
-                continue;
-
-            for(VCoordinateSystem* nC : aVCooSysList_Y)
-            {
-                nC->prepareAutomaticAxisScaling( rAxisUsage.aAutoScaling, 1, 
nAttachedAxisIndex );
-
-                ExplicitScaleData aExplicitScaleSource = nC->getExplicitScale( 
1,nAttachedAxisIndex );
-                ExplicitIncrementData aExplicitIncrementSource = 
nC->getExplicitIncrement( 1,nAttachedAxisIndex );
-
-                ExplicitScaleData aExplicitScaleDest = nC->getExplicitScale( 
1,nAxisIndex );
-                ExplicitIncrementData aExplicitIncrementDest = 
nC->getExplicitIncrement( 1,nAxisIndex );
-
-                aExplicitScaleDest.Orientation = 
aExplicitScaleSource.Orientation;
-                aExplicitScaleDest.Scaling = aExplicitScaleSource.Scaling;
-                aExplicitScaleDest.AxisType = aExplicitScaleSource.AxisType;
-
-                aExplicitIncrementDest.BaseValue = 
aExplicitIncrementSource.BaseValue;
-
-                ScaleData aScale( rAxisUsage.aAutoScaling.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.hasElements() )
-                    bAutoMinorInterval = !( 
aScale.IncrementData.SubIncrements[0].IntervalCount.hasValue() );
-                if( bAutoMinorInterval )
-                {
-                    if( !aExplicitIncrementDest.SubIncrements.empty() && 
!aExplicitIncrementSource.SubIncrements.empty() )
-                        aExplicitIncrementDest.SubIncrements[0].IntervalCount =
-                            
aExplicitIncrementSource.SubIncrements[0].IntervalCount;
-                }
-
-                nC->setExplicitScaleAndIncrement( 1, nAxisIndex, 
aExplicitScaleDest, aExplicitIncrementDest );
-            }
-        }
-    }
-
-    if( !AxisHelper::isAxisPositioningEnabled() )
-        return;
-
-    //correct origin for y main axis (the origin is where the other main axis 
crosses)
-    sal_Int32 nAxisIndex=0;
-    sal_Int32 nDimensionIndex=1;
-    for (auto & axisUsage : m_aAxisUsageList)
-    {
-        AxisUsage& rAxisUsage = axisUsage.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 );
-
-            if( xCrossingMainAxis.is() )
-            {
-                css::chart::ChartAxisPosition eCrossingMainAxisPos( 
css::chart::ChartAxisPosition_ZERO );
-                xCrossingMainAxis->getPropertyValue("CrossoverPosition") >>= 
eCrossingMainAxisPos;
-                if( eCrossingMainAxisPos == 
css::chart::ChartAxisPosition_VALUE )
-                {
-                    double fValue = 0.0;
-                    xCrossingMainAxis->getPropertyValue("CrossoverValue") >>= 
fValue;
-                    aExplicitScale.Origin = fValue;
-                }
-                else if( eCrossingMainAxisPos == 
css::chart::ChartAxisPosition_ZERO )
-                    aExplicitScale.Origin = 0.0;
-                else  if( eCrossingMainAxisPos == 
css::chart::ChartAxisPosition_START )
-                    aExplicitScale.Origin = aExplicitScale.Minimum;
-                else  if( eCrossingMainAxisPos == 
css::chart::ChartAxisPosition_END )
-                    aExplicitScale.Origin = aExplicitScale.Maximum;
-            }
-
-            aVCooSysList[nC]->setExplicitScaleAndIncrement( nDimensionIndex, 
nAxisIndex, aExplicitScale, aExplicitIncrement );
-        }
-    }
-}
-
-drawing::Direction3D SeriesPlotterContainer::getPreferredAspectRatio()
-{
-    drawing::Direction3D aPreferredAspectRatio(1.0,1.0,1.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;
-    for( const std::unique_ptr<VSeriesPlotter>& aPlotter : 
m_aSeriesPlotterList )
-    {
-        drawing::Direction3D aSingleRatio( 
aPlotter->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;
-}
-
-}
-
 struct CreateShapeParam2D
 {
     css::awt::Rectangle maRemainingSpace;
@@ -1442,7 +677,7 @@ awt::Rectangle ChartView::impl_createDiagramAndContent( 
const CreateShapeParam2D
         }
         pSeriesPlotter->initPlotter( 
xSeriesTarget,xTextTargetShapes,m_xShapeFactory,OUString() );
         pSeriesPlotter->setPageReferenceSize( rPageSize );
-        VCoordinateSystem* pVCooSys = lcl_getCooSysForPlotter( rVCooSysList, 
pSeriesPlotter );
+        VCoordinateSystem* pVCooSys = 
SeriesPlotterContainer::getCooSysForPlotter( rVCooSysList, pSeriesPlotter );
         if(nDimensionCount==2)
             pSeriesPlotter->setTransformationSceneToScreen( 
pVCooSys->getTransformationSceneToScreen() );
         //better performance for big data
@@ -1493,7 +728,7 @@ awt::Rectangle ChartView::impl_createDiagramAndContent( 
const CreateShapeParam2D
         // - create data series for all charttypes
         for( std::unique_ptr<VSeriesPlotter>& aPlotter : rSeriesPlotterList )
         {
-            VCoordinateSystem* pVCooSys = lcl_getCooSysForPlotter( 
rVCooSysList, aPlotter.get() );
+            VCoordinateSystem* pVCooSys = 
SeriesPlotterContainer::getCooSysForPlotter( rVCooSysList, aPlotter.get() );
             if(nDimensionCount==2)
                 aPlotter->setTransformationSceneToScreen( 
pVCooSys->getTransformationSceneToScreen() );
             // Now we can move data labels in case of pie or donut chart!
@@ -1574,7 +809,8 @@ bool ChartView::getExplicitValuesForAxis(
         return false;
 
     uno::Reference< XCoordinateSystem > xCooSys( 
AxisHelper::getCoordinateSystemOfAxis(xAxis, mrChartModel.getFirstDiagram() ) );
-    const VCoordinateSystem* pVCooSys = 
findInCooSysList(m_aVCooSysList,xCooSys);
+    const VCoordinateSystem* pVCooSys = 
SeriesPlotterContainer::findInCooSysList(m_aVCooSysList, xCooSys);
+
     if(!pVCooSys)
         return false;
 
diff --git a/chart2/source/view/main/SeriesPlotterContainer.cxx 
b/chart2/source/view/main/SeriesPlotterContainer.cxx
new file mode 100644
index 000000000000..b72d2f1bba42
--- /dev/null
+++ b/chart2/source/view/main/SeriesPlotterContainer.cxx
@@ -0,0 +1,761 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "SeriesPlotterContainer.hxx"
+
+#include <ChartView.hxx>
+#include <Diagram.hxx>
+#include <DataSeries.hxx>
+#include <ChartModel.hxx>
+#include <ChartTypeHelper.hxx>
+#include <ObjectIdentifier.hxx>
+#include <DiagramHelper.hxx>
+
+#include <AxisIndexDefines.hxx>
+#include <DataSeriesHelper.hxx>
+#include <ExplicitCategoriesProvider.hxx>
+#include <unonames.hxx>
+
+#include <com/sun/star/chart/ChartAxisPosition.hpp>
+#include <com/sun/star/chart2/AxisType.hpp>
+#include <com/sun/star/chart2/XDataSeriesContainer.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+
+#include <comphelper/classids.hxx>
+#include <servicenames_charttypes.hxx>
+#include <tools/diagnose_ex.h>
+
+namespace chart
+{
+using namespace ::css;
+using namespace ::css::chart2;
+
+using ::css::uno::Reference;
+using ::css::uno::Sequence;
+using ::css::uno::Any;
+
+SeriesPlotterContainer::SeriesPlotterContainer(
+    std::vector<std::unique_ptr<VCoordinateSystem>>& rVCooSysList)
+    : m_rVCooSysList(rVCooSysList)
+    , m_nMaxAxisIndex(0)
+    , m_bChartTypeUsesShiftedCategoryPositionPerDefault(false)
+    , m_nDefaultDateNumberFormat(0)
+{
+}
+
+SeriesPlotterContainer::~SeriesPlotterContainer()
+{
+    // - remove plotter from coordinatesystems
+    for (auto& nC : m_rVCooSysList)
+        nC->clearMinimumAndMaximumSupplierList();
+}
+
+std::vector<LegendEntryProvider*> 
SeriesPlotterContainer::getLegendEntryProviderList()
+{
+    std::vector<LegendEntryProvider*> aRet(m_aSeriesPlotterList.size());
+    sal_Int32 nN = 0;
+    for (const std::unique_ptr<VSeriesPlotter>& aPlotter : 
m_aSeriesPlotterList)
+        aRet[nN++] = aPlotter.get();
+    return aRet;
+}
+
+VCoordinateSystem* SeriesPlotterContainer::findInCooSysList(
+    const std::vector<std::unique_ptr<VCoordinateSystem>>& rVCooSysList,
+    const uno::Reference<XCoordinateSystem>& xCooSys)
+{
+    for (auto& pVCooSys : rVCooSysList)
+    {
+        if (pVCooSys->getModel() == xCooSys)
+            return pVCooSys.get();
+    }
+    return nullptr;
+}
+
+VCoordinateSystem* SeriesPlotterContainer::getCooSysForPlotter(
+    const std::vector<std::unique_ptr<VCoordinateSystem>>& rVCooSysList,
+    MinimumAndMaximumSupplier* pMinimumAndMaximumSupplier)
+{
+    if (!pMinimumAndMaximumSupplier)
+        return nullptr;
+    for (auto& pVCooSys : rVCooSysList)
+    {
+        if (pVCooSys->hasMinimumAndMaximumSupplier(pMinimumAndMaximumSupplier))
+            return pVCooSys.get();
+    }
+    return nullptr;
+}
+
+VCoordinateSystem* SeriesPlotterContainer::addCooSysToList(
+    std::vector<std::unique_ptr<VCoordinateSystem>>& rVCooSysList,
+    const uno::Reference<XCoordinateSystem>& xCooSys, ChartModel& rChartModel)
+{
+    VCoordinateSystem* pExistingVCooSys
+        = SeriesPlotterContainer::findInCooSysList(rVCooSysList, xCooSys);
+    if (pExistingVCooSys)
+        return pExistingVCooSys;
+
+    std::unique_ptr<VCoordinateSystem> pVCooSys
+        = VCoordinateSystem::createCoordinateSystem(xCooSys);
+    if (!pVCooSys)
+        return nullptr;
+
+    OUString aCooSysParticle(
+        ObjectIdentifier::createParticleForCoordinateSystem(xCooSys, 
rChartModel));
+    pVCooSys->setParticle(aCooSysParticle);
+
+    pVCooSys->setExplicitCategoriesProvider(new 
ExplicitCategoriesProvider(xCooSys, rChartModel));
+    rVCooSysList.push_back(std::move(pVCooSys));
+    return rVCooSysList.back().get();
+}
+
+void SeriesPlotterContainer::initializeCooSysAndSeriesPlotter(ChartModel& 
rChartModel)
+{
+    uno::Reference<XDiagram> xDiagram(rChartModel.getFirstDiagram());
+    if (!xDiagram.is())
+        return;
+
+    uno::Reference<util::XNumberFormatsSupplier> 
xNumberFormatsSupplier(&rChartModel);
+    if (rChartModel.hasInternalDataProvider() && 
DiagramHelper::isSupportingDateAxis(xDiagram))
+        m_nDefaultDateNumberFormat = 
DiagramHelper::getDateNumberFormat(xNumberFormatsSupplier);
+
+    sal_Int32 nDimensionCount = DiagramHelper::getDimension(xDiagram);
+    if (!nDimensionCount)
+    {
+        //@todo handle mixed dimension
+        nDimensionCount = 2;
+    }
+
+    bool bSortByXValues = false;
+    bool bConnectBars = false;
+    bool bGroupBarsPerAxis = true;
+    bool bIncludeHiddenCells = true;
+    bool bSecondaryYaxisVisible = true;
+    sal_Int32 nStartingAngle = 90;
+    sal_Int32 n3DRelativeHeight = 100;
+    try
+    {
+        uno::Reference<beans::XPropertySet> xDiaProp(xDiagram, 
uno::UNO_QUERY_THROW);
+        xDiaProp->getPropertyValue(CHART_UNONAME_SORT_BY_XVALUES) >>= 
bSortByXValues;
+        xDiaProp->getPropertyValue("ConnectBars") >>= bConnectBars;
+        xDiaProp->getPropertyValue("GroupBarsPerAxis") >>= bGroupBarsPerAxis;
+        xDiaProp->getPropertyValue("IncludeHiddenCells") >>= 
bIncludeHiddenCells;
+        xDiaProp->getPropertyValue("StartingAngle") >>= nStartingAngle;
+
+        if (nDimensionCount == 3)
+        {
+            xDiaProp->getPropertyValue("3DRelativeHeight") >>= 
n3DRelativeHeight;
+        }
+    }
+    catch (const uno::Exception&)
+    {
+        DBG_UNHANDLED_EXCEPTION("chart2");
+    }
+
+    //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
+            = SeriesPlotterContainer::addCooSysToList(m_rVCooSysList, xCooSys, 
rChartModel);
+        // Let's check whether the secondary Y axis is visible
+        try
+        {
+            if (xCooSys->getMaximumAxisIndexByDimension(1) > 0)
+            {
+                Reference<beans::XPropertySet> 
xAxisProp(xCooSys->getAxisByDimension(1, 1),
+                                                         uno::UNO_QUERY);
+                xAxisProp->getPropertyValue("Show") >>= bSecondaryYaxisVisible;
+            }
+        }
+        catch (const lang::IndexOutOfBoundsException&)
+        {
+            TOOLS_WARN_EXCEPTION("chart2", "");
+        }
+        //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 (nDimensionCount == 3
+                && xChartType->getChartType().equalsIgnoreAsciiCase(
+                       CHART2_SERVICE_NAME_CHARTTYPE_PIE))
+            {
+                uno::Reference<beans::XPropertySet> xPropertySet(xChartType, 
uno::UNO_QUERY);
+                if (xPropertySet.is())
+                {
+                    try
+                    {
+                        sal_Int32 n3DRelativeHeightOldValue(100);
+                        uno::Any aAny = 
xPropertySet->getPropertyValue("3DRelativeHeight");
+                        aAny >>= n3DRelativeHeightOldValue;
+                        if (n3DRelativeHeightOldValue != n3DRelativeHeight)
+                            xPropertySet->setPropertyValue("3DRelativeHeight",
+                                                           
uno::Any(n3DRelativeHeight));
+                    }
+                    catch (const uno::Exception&)
+                    {
+                    }
+                }
+            }
+
+            if (nT == 0)
+                m_bChartTypeUsesShiftedCategoryPositionPerDefault
+                    = 
ChartTypeHelper::shiftCategoryPosAtXAxisPerDefault(xChartType);
+
+            bool bExcludingPositioning = 
DiagramHelper::getDiagramPositioningMode(xDiagram)
+                                         == DiagramPositioningMode_EXCLUDING;
+            VSeriesPlotter* pPlotter = VSeriesPlotter::createSeriesPlotter(
+                xChartType, nDimensionCount, bExcludingPositioning);
+            if (!pPlotter)
+                continue;
+
+            
m_aSeriesPlotterList.push_back(std::unique_ptr<VSeriesPlotter>(pPlotter));
+            pPlotter->setNumberFormatsSupplier(xNumberFormatsSupplier);
+            pPlotter->setColorScheme(xColorScheme);
+            if (pVCooSys)
+                
pPlotter->setExplicitCategoriesProvider(pVCooSys->getExplicitCategoriesProvider());
+            sal_Int32 nMissingValueTreatment
+                = DiagramHelper::getCorrectedMissingValueTreatment(xDiagram, 
xChartType);
+
+            if (pVCooSys)
+                pVCooSys->addMinimumAndMaximumSupplier(pPlotter);
+
+            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> const& xDataSeries = 
aSeriesList[nS];
+                if (!xDataSeries.is())
+                    continue;
+                if (!bIncludeHiddenCells && 
!DataSeriesHelper::hasUnhiddenData(xDataSeries))
+                    continue;
+
+                std::unique_ptr<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);
+
+                OUString 
aSeriesParticle(ObjectIdentifier::createParticleForSeries(0, nCS, nT, nS));
+                pSeries->setParticle(aSeriesParticle);
+
+                OUString 
aRole(ChartTypeHelper::getRoleOfSequenceForDataLabelNumberFormatDetection(
+                    xChartType));
+                
pSeries->setRoleOfSequenceForDataLabelNumberFormatDetection(aRole);
+
+                //ignore secondary axis for charttypes that do not support them
+                if (pSeries->getAttachedAxisIndex() != MAIN_AXIS_INDEX
+                    && 
(!ChartTypeHelper::isSupportingSecondaryAxis(xChartType, nDimensionCount)
+                        || !bSecondaryYaxisVisible))
+                {
+                    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(std::move(pSeries), zSlot, xSlot, ySlot);
+            }
+        }
+    }
+
+    //transport seriesnames to the coordinatesystems if needed
+    if (m_aSeriesPlotterList.empty())
+        return;
+
+    uno::Sequence<OUString> aSeriesNames;
+    bool bSeriesNamesInitialized = false;
+    for (auto& pVCooSys : m_rVCooSysList)
+    {
+        if (pVCooSys->needSeriesNamesForAxis())
+        {
+            if (!bSeriesNamesInitialized)
+            {
+                aSeriesNames = m_aSeriesPlotterList[0]->getSeriesNames();
+                bSeriesNamesInitialized = true;
+            }
+            pVCooSys->setSeriesNamesForAxis(aSeriesNames);
+        }
+    }
+}
+
+bool SeriesPlotterContainer::isCategoryPositionShifted(const 
chart2::ScaleData& rSourceScale,
+                                                       bool 
bHasComplexCategories)
+{
+    if (rSourceScale.AxisType == AxisType::CATEGORY)
+        return bHasComplexCategories || rSourceScale.ShiftedCategoryPosition
+               || m_bChartTypeUsesShiftedCategoryPositionPerDefault;
+
+    if (rSourceScale.AxisType == AxisType::DATE)
+        return rSourceScale.ShiftedCategoryPosition;
+
+    return rSourceScale.AxisType == AxisType::SERIES;
+}
+
+void SeriesPlotterContainer::initAxisUsageList(const Date& rNullDate)
+{
+    m_aAxisUsageList.clear();
+
+    // Loop through coordinate systems in the diagram (though for now
+    // there should only be one coordinate system per diagram).
+    for (auto& pVCooSys : m_rVCooSysList)
+    {
+        uno::Reference<XCoordinateSystem> xCooSys = pVCooSys->getModel();
+        sal_Int32 nDimCount = xCooSys->getDimension();
+        bool bComplexCategoryAllowed = 
ChartTypeHelper::isSupportingComplexCategory(
+            AxisHelper::getChartTypeByIndex(xCooSys, 0));
+
+        for (sal_Int32 nDimIndex = 0; nDimIndex < nDimCount; ++nDimIndex)
+        {
+            bool bDateAxisAllowed = ChartTypeHelper::isSupportingDateAxis(
+                AxisHelper::getChartTypeByIndex(xCooSys, 0), nDimIndex);
+
+            // Each dimension may have primary and secondary axes.
+            const sal_Int32 nMaxAxisIndex = 
xCooSys->getMaximumAxisIndexByDimension(nDimIndex);
+            for (sal_Int32 nAxisIndex = 0; nAxisIndex <= nMaxAxisIndex; 
++nAxisIndex)
+            {
+                uno::Reference<XAxis> xAxis = 
xCooSys->getAxisByDimension(nDimIndex, nAxisIndex);
+
+                if (!xAxis.is())
+                    continue;
+
+                if (m_aAxisUsageList.find(xAxis) == m_aAxisUsageList.end())
+                {
+                    // Create axis usage object for this axis.
+
+                    chart2::ScaleData aSourceScale = xAxis->getScaleData();
+                    ExplicitCategoriesProvider* pCatProvider
+                        = pVCooSys->getExplicitCategoriesProvider();
+                    if (nDimIndex == 0)
+                        AxisHelper::checkDateAxis(aSourceScale, pCatProvider, 
bDateAxisAllowed);
+
+                    bool bHasComplexCat = pCatProvider && 
pCatProvider->hasComplexCategories()
+                                          && bComplexCategoryAllowed;
+                    aSourceScale.ShiftedCategoryPosition
+                        = isCategoryPositionShifted(aSourceScale, 
bHasComplexCat);
+
+                    m_aAxisUsageList[xAxis].aAutoScaling = 
ScaleAutomatism(aSourceScale, rNullDate);
+                }
+
+                AxisUsage& rAxisUsage = m_aAxisUsageList[xAxis];
+                rAxisUsage.addCoordinateSystem(pVCooSys.get(), nDimIndex, 
nAxisIndex);
+            }
+        }
+    }
+
+    // Determine the highest axis index of all dimensions.
+    m_nMaxAxisIndex = 0;
+    for (const auto& pVCooSys : m_rVCooSysList)
+    {
+        uno::Reference<XCoordinateSystem> xCooSys = pVCooSys->getModel();
+        sal_Int32 nDimCount = xCooSys->getDimension();
+
+        for (sal_Int32 nDimIndex = 0; nDimIndex < nDimCount; ++nDimIndex)
+        {
+            for (auto& axisUsage : m_aAxisUsageList)
+            {
+                sal_Int32 nLocalMax = 
axisUsage.second.getMaxAxisIndexForDimension(nDimIndex);
+                if (m_nMaxAxisIndex < nLocalMax)
+                    m_nMaxAxisIndex = nLocalMax;
+            }
+        }
+    }
+}
+
+void SeriesPlotterContainer::setScalesFromCooSysToPlotter()
+{
+    //set scales to plotter to enable them to provide the preferred scene 
AspectRatio
+    for (const std::unique_ptr<VSeriesPlotter>& aPlotter : 
m_aSeriesPlotterList)
+    {
+        VSeriesPlotter* pSeriesPlotter = aPlotter.get();
+        VCoordinateSystem* pVCooSys
+            = SeriesPlotterContainer::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 numberformats to plotter to enable them to display the data labels 
in the numberformat of the axis
+    for (const std::unique_ptr<VSeriesPlotter>& aPlotter : 
m_aSeriesPlotterList)
+    {
+        VSeriesPlotter* pSeriesPlotter = aPlotter.get();
+        VCoordinateSystem* pVCooSys
+            = SeriesPlotterContainer::getCooSysForPlotter(m_rVCooSysList, 
pSeriesPlotter);
+        if (pVCooSys)
+        {
+            AxesNumberFormats aAxesNumberFormats;
+            const 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(CHART_UNONAME_NUMFMT)
+                                >>= nNumberFormatKey)
+                            {
+                                aAxesNumberFormats.setFormat(nNumberFormatKey, 
nDimensionIndex,
+                                                             nAxisIndex);
+                            }
+                            else if (nDimensionIndex == 0)
+                            {
+                                //provide a default date format for date axis 
with own data
+                                
aAxesNumberFormats.setFormat(m_nDefaultDateNumberFormat,
+                                                             nDimensionIndex, 
nAxisIndex);
+                            }
+                        }
+                    }
+                    catch (const lang::IndexOutOfBoundsException&)
+                    {
+                        TOOLS_WARN_EXCEPTION("chart2", "");
+                    }
+                }
+            }
+        }
+    }
+}
+
+void SeriesPlotterContainer::updateScalesAndIncrementsOnAxes()
+{
+    for (auto& nC : m_rVCooSysList)
+        nC->updateScalesAndIncrementsOnAxes();
+}
+
+void SeriesPlotterContainer::doAutoScaling(ChartModel& rChartModel)
+{
+    if (m_aSeriesPlotterList.empty() || m_aAxisUsageList.empty())
+        // We need these two containers populated to do auto-scaling.  Bail 
out.
+        return;
+
+    //iterate over the main scales first than secondary axis
+    for (sal_Int32 nAxisIndex = 0; nAxisIndex <= m_nMaxAxisIndex; ++nAxisIndex)
+    {
+        // - first do autoscale for all x and z scales (because they are 
treated independent)
+        for (auto& axisUsage : m_aAxisUsageList)
+        {
+            AxisUsage& rAxisUsage = axisUsage.second;
+
+            rAxisUsage.prepareAutomaticAxisScaling(rAxisUsage.aAutoScaling, 0, 
nAxisIndex);
+            rAxisUsage.prepareAutomaticAxisScaling(rAxisUsage.aAutoScaling, 2, 
nAxisIndex);
+
+            ExplicitScaleData aExplicitScale;
+            ExplicitIncrementData aExplicitIncrement;
+            
rAxisUsage.aAutoScaling.calculateExplicitScaleAndIncrement(aExplicitScale,
+                                                                       
aExplicitIncrement);
+
+            rAxisUsage.setExplicitScaleAndIncrement(0, nAxisIndex, 
aExplicitScale,
+                                                    aExplicitIncrement);
+            rAxisUsage.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 (auto& axisUsage : m_aAxisUsageList)
+        {
+            AxisUsage& rAxisUsage = axisUsage.second;
+
+            rAxisUsage.prepareAutomaticAxisScaling(rAxisUsage.aAutoScaling, 1, 
nAxisIndex);
+
+            ExplicitScaleData aExplicitScale;
+            ExplicitIncrementData aExplicitIncrement;
+            
rAxisUsage.aAutoScaling.calculateExplicitScaleAndIncrement(aExplicitScale,
+                                                                       
aExplicitIncrement);
+
+            rAxisUsage.setExplicitScaleAndIncrement(0, nAxisIndex, 
aExplicitScale,
+                                                    aExplicitIncrement);
+            rAxisUsage.setExplicitScaleAndIncrement(1, nAxisIndex, 
aExplicitScale,
+                                                    aExplicitIncrement);
+            rAxisUsage.setExplicitScaleAndIncrement(2, nAxisIndex, 
aExplicitScale,
+                                                    aExplicitIncrement);
+        }
+    }
+    AdaptScaleOfYAxisWithoutAttachedSeries(rChartModel);
+}
+
+void 
SeriesPlotterContainer::AdaptScaleOfYAxisWithoutAttachedSeries(ChartModel& 
rModel)
+{
+    //issue #i80518#
+    for (sal_Int32 nAxisIndex = 0; nAxisIndex <= m_nMaxAxisIndex; nAxisIndex++)
+    {
+        for (auto& axisUsage : m_aAxisUsageList)
+        {
+            AxisUsage& rAxisUsage = axisUsage.second;
+            std::vector<VCoordinateSystem*> aVCooSysList_Y
+                = rAxisUsage.getCoordinateSystems(1, nAxisIndex);
+            if (aVCooSysList_Y.empty())
+                continue;
+
+            uno::Reference<XDiagram> xDiagram(rModel.getFirstDiagram());
+            if (!xDiagram.is())
+                continue;
+
+            bool bSeriesAttachedToThisAxis = false;
+            sal_Int32 nAttachedAxisIndex = -1;
+            {
+                std::vector<Reference<XDataSeries>> aSeriesVector(
+                    DiagramHelper::getDataSeriesFromDiagram(xDiagram));
+                for (auto const& series : aSeriesVector)
+                {
+                    sal_Int32 nCurrentIndex = 
DataSeriesHelper::getAttachedAxisIndex(series);
+                    if (nAxisIndex == nCurrentIndex)
+                    {
+                        bSeriesAttachedToThisAxis = true;
+                        break;
+                    }
+                    else if (nAttachedAxisIndex < 0 || nAttachedAxisIndex > 
nCurrentIndex)
+                        nAttachedAxisIndex = nCurrentIndex;
+                }
+            }
+
+            if (bSeriesAttachedToThisAxis || nAttachedAxisIndex < 0)
+                continue;
+
+            for (VCoordinateSystem* nC : aVCooSysList_Y)
+            {
+                nC->prepareAutomaticAxisScaling(rAxisUsage.aAutoScaling, 1, 
nAttachedAxisIndex);
+
+                ExplicitScaleData aExplicitScaleSource
+                    = nC->getExplicitScale(1, nAttachedAxisIndex);
+                ExplicitIncrementData aExplicitIncrementSource
+                    = nC->getExplicitIncrement(1, nAttachedAxisIndex);
+
+                ExplicitScaleData aExplicitScaleDest = nC->getExplicitScale(1, 
nAxisIndex);
+                ExplicitIncrementData aExplicitIncrementDest
+                    = nC->getExplicitIncrement(1, nAxisIndex);
+
+                aExplicitScaleDest.Orientation = 
aExplicitScaleSource.Orientation;
+                aExplicitScaleDest.Scaling = aExplicitScaleSource.Scaling;
+                aExplicitScaleDest.AxisType = aExplicitScaleSource.AxisType;
+
+                aExplicitIncrementDest.BaseValue = 
aExplicitIncrementSource.BaseValue;
+
+                ScaleData aScale(rAxisUsage.aAutoScaling.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.hasElements())
+                    bAutoMinorInterval
+                        = 
!(aScale.IncrementData.SubIncrements[0].IntervalCount.hasValue());
+                if (bAutoMinorInterval)
+                {
+                    if (!aExplicitIncrementDest.SubIncrements.empty()
+                        && !aExplicitIncrementSource.SubIncrements.empty())
+                        aExplicitIncrementDest.SubIncrements[0].IntervalCount
+                            = 
aExplicitIncrementSource.SubIncrements[0].IntervalCount;
+                }
+
+                nC->setExplicitScaleAndIncrement(1, nAxisIndex, 
aExplicitScaleDest,
+                                                 aExplicitIncrementDest);
+            }
+        }
+    }
+
+    if (!AxisHelper::isAxisPositioningEnabled())
+        return;
+
+    //correct origin for y main axis (the origin is where the other main axis 
crosses)
+    sal_Int32 nAxisIndex = 0;
+    sal_Int32 nDimensionIndex = 1;
+    for (auto& axisUsage : m_aAxisUsageList)
+    {
+        AxisUsage& rAxisUsage = axisUsage.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);
+
+            if (xCrossingMainAxis.is())
+            {
+                css::chart::ChartAxisPosition eCrossingMainAxisPos(
+                    css::chart::ChartAxisPosition_ZERO);
+                xCrossingMainAxis->getPropertyValue("CrossoverPosition") >>= 
eCrossingMainAxisPos;
+                if (eCrossingMainAxisPos == 
css::chart::ChartAxisPosition_VALUE)
+                {
+                    double fValue = 0.0;
+                    xCrossingMainAxis->getPropertyValue("CrossoverValue") >>= 
fValue;
+                    aExplicitScale.Origin = fValue;
+                }
+                else if (eCrossingMainAxisPos == 
css::chart::ChartAxisPosition_ZERO)
+                    aExplicitScale.Origin = 0.0;
+                else if (eCrossingMainAxisPos == 
css::chart::ChartAxisPosition_START)
+                    aExplicitScale.Origin = aExplicitScale.Minimum;
+                else if (eCrossingMainAxisPos == 
css::chart::ChartAxisPosition_END)
+                    aExplicitScale.Origin = aExplicitScale.Maximum;
+            }
+
+            aVCooSysList[nC]->setExplicitScaleAndIncrement(nDimensionIndex, 
nAxisIndex,
+                                                           aExplicitScale, 
aExplicitIncrement);
+        }
+    }
+}
+
+drawing::Direction3D SeriesPlotterContainer::getPreferredAspectRatio()
+{
+    drawing::Direction3D aPreferredAspectRatio(1.0, 1.0, 1.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;
+    for (const std::unique_ptr<VSeriesPlotter>& aPlotter : 
m_aSeriesPlotterList)
+    {
+        drawing::Direction3D 
aSingleRatio(aPlotter->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;
+}
+
+} //end chart namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/main/SeriesPlotterContainer.hxx 
b/chart2/source/view/main/SeriesPlotterContainer.hxx
new file mode 100644
index 000000000000..ccecac059027
--- /dev/null
+++ b/chart2/source/view/main/SeriesPlotterContainer.hxx
@@ -0,0 +1,164 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <config_feature_desktop.h>
+#include <VSeriesPlotter.hxx>
+#include <BaseCoordinateSystem.hxx>
+#include "AxisUsage.hxx"
+#include <rtl/ref.hxx>
+#include <com/sun/star/chart2/XAxis.hpp>
+#include <com/sun/star/chart2/XCoordinateSystem.hpp>
+
+namespace chart
+{
+typedef std::vector<std::unique_ptr<VSeriesPlotter>> SeriesPlottersType;
+
+/** This class is a container of `SeriesPlotter` objects (such as `PieChart`
+ *  instances). It is used for initializing coordinate systems, axes and scales
+ *  of all series plotters which belongs to the container.
+ */
+class SeriesPlotterContainer
+{
+public:
+    explicit 
SeriesPlotterContainer(std::vector<std::unique_ptr<VCoordinateSystem>>& 
rVCooSysList);
+    ~SeriesPlotterContainer();
+
+    /** It is used to set coordinate systems (`m_rVCooSysList`), this method
+     *  is invoked by `ChartView::createShapes2D` before of
+     *  `ChartView::impl_createDiagramAndContent`.
+     *  Coordinate systems are retrieved through the 
`XCoordinateSystemContainer`
+     *  interface implemented by a diagram object which is provided by the
+     *  `ChartModel` object passed to the method 
(`rChartModel.getFirstDiagram()`).
+     *
+     *  It is used for creating series plotters and appending them
+     *  to `m_aSeriesPlotterList`. The created series plotters are initialized
+     *  through data (number formats supplier, color scheme, data series),
+     *  extracted from the chart model or the diagram objects. An exception is
+     *  the explicit category provider that is retrieved through the
+     *  `VCoordinateSystem` object used by the series plotter.
+     *
+     *  It sets the minimum-maximum supplier for a coordinate system:
+     *  this supplier is the series plotter itself which utilizes the given
+     *  coordinate system. In fact `VSeriesPlotter` has 
`MinimumMaximumSupplier`
+     *  as one of its base classes.
+     *  Hence, for instance, a `PieChart`, which is a series plotter, is
+     *  a `MinimumMaximumSupplier`, too.
+     */
+    void initializeCooSysAndSeriesPlotter(ChartModel& rModel);
+
+    /** This method is invoked by `ChartView::impl_createDiagramAndContent`.
+     *  It iterates on every axis of every coordinate systems, and if the axis
+     *  is not yet present in `m_aAxisUsageList` it creates a new `AxisUsage`
+     *  object and initialize its `aAutoScaling` member to the `ScaleData`
+     *  object of the current axis.
+     */
+    void initAxisUsageList(const Date& rNullDate);
+
+    /**
+     * Perform automatic axis scaling and determine the amount and spacing of
+     * increments.  It assumes that the caller has determined the size of the
+     * largest axis label text object prior to calling this method.
+     *
+     * The new axis scaling data will be stored in the VCoordinateSystem
+     * objects.  The label alignment direction for each axis will also get
+     * determined during this process, and stored in VAxis.
+     *
+     * This method is invoked by `ChartView::impl_createDiagramAndContent`
+     * soon after `initAxisUsageList`.
+     * It initializes explicit scale and increment objects for all coordinate
+     * systems in `m_rVCooSysList`.
+     * This action is achieved by iterating on the `m_aAxisUsageList` 
container,
+     * and performing 3 steps:
+     *   1- call `VCoordinateSystem::prepareAutomaticAxisScaling` for setting
+     *      scaling parameters of the `aAutoScaling` member (a 
`ScaleAutomatism`
+     *      object) for the current `AxisUsage` instance
+     *      (see `VCoordinateSystem::prepareAutomaticAxisScaling`);
+     *   2- calculate the explicit scale and increment objects
+     *      (see ScaleAutomatism::calculateExplicitScaleAndIncrement);
+     *   3- set the explicit scale and increment objects for each coordinate
+     *      system.
+     */
+    void doAutoScaling(ChartModel& rModel);
+
+    /**
+     * After auto-scaling is performed, call this method to set the explicit
+     * scaling and increment data to all relevant VAxis objects.
+     */
+    void updateScalesAndIncrementsOnAxes();
+
+    /**
+     * After auto-scaling is performed, call this method to set the explicit
+     * scaling data to all the plotters.
+     */
+    void setScalesFromCooSysToPlotter();
+
+    void setNumberFormatsFromAxes();
+    css::drawing::Direction3D getPreferredAspectRatio();
+
+    SeriesPlottersType& getSeriesPlotterList() { return m_aSeriesPlotterList; }
+    std::vector<std::unique_ptr<VCoordinateSystem>>& getCooSysList() { return 
m_rVCooSysList; }
+    std::vector<LegendEntryProvider*> getLegendEntryProviderList();
+
+    void AdaptScaleOfYAxisWithoutAttachedSeries(ChartModel& rModel);
+
+    bool isCategoryPositionShifted(const css::chart2::ScaleData& rSourceScale,
+                                   bool bHasComplexCategories);
+
+    static VCoordinateSystem*
+    addCooSysToList(std::vector<std::unique_ptr<VCoordinateSystem>>& 
rVCooSysList,
+                    const css::uno::Reference<css::chart2::XCoordinateSystem>& 
xCooSys,
+                    ChartModel& rChartModel);
+
+    static VCoordinateSystem*
+    getCooSysForPlotter(const std::vector<std::unique_ptr<VCoordinateSystem>>& 
rVCooSysList,
+                        MinimumAndMaximumSupplier* pMinimumAndMaximumSupplier);
+
+    static VCoordinateSystem*
+    findInCooSysList(const std::vector<std::unique_ptr<VCoordinateSystem>>& 
rVCooSysList,
+                     const 
css::uno::Reference<css::chart2::XCoordinateSystem>& xCooSys);
+
+private:
+    /** A vector of series plotters.
+     */
+    SeriesPlottersType m_aSeriesPlotterList;
+
+    /** A vector of coordinate systems.
+     */
+    std::vector<std::unique_ptr<VCoordinateSystem>>& m_rVCooSysList;
+
+    /** A map whose key is a `XAxis` interface and the related value is
+     *  an object of `AxisUsage` type.
+     */
+    std::map<css::uno::Reference<css::chart2::XAxis>, AxisUsage> 
m_aAxisUsageList;
+
+    /**
+     * Max axis index of all dimensions.  Currently this can be either 0 or 1
+     * since we only support primary and secondary axes per dimension.  The
+     * value of 0 means all dimensions have only primary axis, while 1 means
+     * at least one dimension has a secondary axis.
+     */
+    sal_Int32 m_nMaxAxisIndex;
+
+    bool m_bChartTypeUsesShiftedCategoryPositionPerDefault;
+    sal_Int32 m_nDefaultDateNumberFormat;
+};
+
+} //end chart namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Reply via email to