Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/LibreOffice/chart2/source/view/main/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 31 kB image not shown  

Quelle  SeriesPlotterContainer.cxx   Sprache: C

 
/* -*- 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 <sal/config.h>

#include <cstddef>

#include "SeriesPlotterContainer.hxx"

#include <ChartView.hxx>
#include <Diagram.hxx>
#include <ChartType.hxx>
#include <DataSeries.hxx>
#include <ChartModel.hxx>
#include <ChartTypeHelper.hxx>
#include <ObjectIdentifier.hxx>
#include <DiagramHelper.hxx>
#include <Axis.hxx>
#include <AxisIndexDefines.hxx>
#include <ConfigColorScheme.hxx>
#include <ChartColorScheme.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/PieChartSubType.hpp>
#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>

#include <comphelper/classids.hxx>
#include <servicenames_charttypes.hxx>
#include <comphelper/diagnose_ex.hxx>

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 rtl::Reference<BaseCoordinateSystem>& 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 rtl::Reference<BaseCoordinateSystem>& 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)
{
    rtl::Reference<Diagram> xDiagram = rChartModel.getFirstChartDiagram();
    if (!xDiagram.is())
        return;

    uno::Reference<util::XNumberFormatsSupplier> xNumberFormatsSupplier(&rChartModel);
    if (rChartModel.hasInternalDataProvider() && xDiagram->isSupportingDateAxis())
        m_nDefaultDateNumberFormat = DiagramHelper::getDateNumberFormat(xNumberFormatsSupplier);

    sal_Int32 nDimensionCount = xDiagram->getDimension();
    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;
    PieChartSubType ePieChartSubType = PieChartSubType_NONE;
    double nSplitPos = 2;
    try
    {
        xDiagram->getPropertyValue(CHART_UNONAME_SORT_BY_XVALUES) >>= bSortByXValues;
        xDiagram->getPropertyValue(u"ConnectBars"_ustr) >>= bConnectBars;
        xDiagram->getPropertyValue(u"GroupBarsPerAxis"_ustr) >>= bGroupBarsPerAxis;
        xDiagram->getPropertyValue(u"IncludeHiddenCells"_ustr) >>= bIncludeHiddenCells;
        xDiagram->getPropertyValue(u"StartingAngle"_ustr) >>= nStartingAngle;

        if (nDimensionCount == 3)
        {
            xDiagram->getPropertyValue(u"3DRelativeHeight"_ustr) >>= n3DRelativeHeight;
        }
        xDiagram->getPropertyValue(u"SubPieType"_ustr) >>= ePieChartSubType;

        xDiagram->getPropertyValue(u"SplitPos"_ustr) >>= nSplitPos;
    }
    catch (const uno::Exception&)
    {
        DBG_UNHANDLED_EXCEPTION("chart2");
    }

    if (xDiagram->getDataTable().is())
        m_bTableShiftPosition = true;

    //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<XColorScheme> xColorScheme;
    if (!rChartModel.usesColorPalette())
        xColorScheme = xDiagram->getDefaultColorScheme();
    else
        xColorScheme = new ChartColorScheme(*rChartModel.getCurrentColorPalette());
    auto aCooSysList = xDiagram->getBaseCoordinateSystems();
    sal_Int32 nGlobalSeriesIndex = 0; //for automatic symbols
    for (std::size_t nCS = 0; nCS < aCooSysList.size(); ++nCS)
    {
        const rtl::Reference<BaseCoordinateSystem>& 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)
            {
                rtl::Reference<Axis> xAxisProp = xCooSys->getAxisByDimension2(1, 1);
                xAxisProp->getPropertyValue(u"Show"_ustr) >>= bSecondaryYaxisVisible;
            }
        }
        catch (const lang::IndexOutOfBoundsException&)
        {
            TOOLS_WARN_EXCEPTION("chart2""");
        }
        //iterate through all chart types in the current coordinate system
        std::vector<rtl::Reference<ChartType>> aChartTypeList(xCooSys->getChartTypes2());
        for (std::size_t nT = 0; nT < aChartTypeList.size(); ++nT)
        {
            const rtl::Reference<ChartType>& xChartType(aChartTypeList[nT]);
            if (nDimensionCount == 3
                && xChartType->getChartType().equalsIgnoreAsciiCase(
                       CHART2_SERVICE_NAME_CHARTTYPE_PIE))
            {
                try
                {
                    sal_Int32 n3DRelativeHeightOldValue(100);
                    uno::Any aAny = xChartType->getFastPropertyValue(
                        PROP_PIECHARTTYPE_3DRELATIVEHEIGHT); // "3DRelativeHeight"
                    aAny >>= n3DRelativeHeightOldValue;
                    if (n3DRelativeHeightOldValue != n3DRelativeHeight)
                        xChartType->setFastPropertyValue(
                            PROP_PIECHARTTYPE_3DRELATIVEHEIGHT, // "3DRelativeHeight"
                            uno::Any(n3DRelativeHeight));
                }
                catch (const uno::Exception&)
                {
                }
            }

            if (ePieChartSubType != PieChartSubType_NONE)
            {
                xChartType->setFastPropertyValue(PROP_PIECHARTTYPE_SUBTYPE,
                                                 uno::Any(ePieChartSubType));
                // Reset the diagram-level property so it's not persistent.
                xDiagram->setPropertyValue(u"SubPieType"_ustr, uno::Any(PieChartSubType_NONE));

                xChartType->setFastPropertyValue(PROP_PIECHARTTYPE_SPLIT_POS, uno::Any(nSplitPos));
                //xDiagram->setPropertyValue(u"SplitPos"_ustr, uno::Any(nSplitPos));
            }

            if (nT == 0)
                m_bChartTypeUsesShiftedCategoryPositionPerDefault
                    = ChartTypeHelper::shiftCategoryPosAtXAxisPerDefault(xChartType);

            bool bExcludingPositioning
                = xDiagram->getDiagramPositioningMode() == 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
                = xDiagram->getCorrectedMissingValueTreatment(xChartType);

            if (pVCooSys)
                pVCooSys->addMinimumAndMaximumSupplier(pPlotter);

            sal_Int32 zSlot = -1;
            sal_Int32 xSlot = -1;
            sal_Int32 ySlot = -1;
            const std::vector<rtl::Reference<DataSeries>>& aSeriesList
                = xChartType->getDataSeries2();
            for (std::size_t nS = 0; nS < aSeriesList.size(); ++nS)
            {
                rtl::Reference<DataSeries> const& xDataSeries = aSeriesList[nS];
                if (!bIncludeHiddenCells && !xDataSeries->hasUnhiddenData())
                    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
                    && (!(xChartType.is() ? xChartType->isSupportingSecondaryAxis(nDimensionCount)
                                          : true)
                        || !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);
            }
        }
    }

    auto order
        = [](const std::unique_ptr<VSeriesPlotter>& a, const std::unique_ptr<VSeriesPlotter>&&nbsp;b) {
              return a->getRenderOrder() < b->getRenderOrder();
          };

    std::stable_sort(m_aSeriesPlotterList.begin(), m_aSeriesPlotterList.end(), order);

    //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_bTableShiftPosition || 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)
    {
        rtl::Reference<BaseCoordinateSystem> xCooSys = pVCooSys->getModel();
        sal_Int32 nDimCount = xCooSys->getDimension();
        auto xChartType = AxisHelper::getChartTypeByIndex(xCooSys, 0);
        bool bComplexCategoryAllowed
            = xChartType.is() ? xChartType->isSupportingComplexCategory() : true;

        for (sal_Int32 nDimIndex = 0; nDimIndex < nDimCount; ++nDimIndex)
        {
            bool bDateAxisAllowed
                = xChartType.is() ? xChartType->isSupportingDateAxis(nDimIndex) : true;

            // Each dimension may have primary and secondary axes.
            const sal_Int32 nMaxAxisIndex = xCooSys->getMaximumAxisIndexByDimension(nDimIndex);
            for (sal_Int32 nAxisIndex = 0; nAxisIndex <= nMaxAxisIndex; ++nAxisIndex)
            {
                rtl::Reference<Axis> xAxis = xCooSys->getAxisByDimension2(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)
    {
        rtl::Reference<BaseCoordinateSystem> 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 rtl::Reference<BaseCoordinateSystem>& 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
                    {
                        rtl::Reference<Axis> xAxisProp
                            = xCooSys->getAxisByDimension2(nDimensionIndex, nAxisIndex);
                        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 & [ rAxis, rAxisUsage ] : m_aAxisUsageList)
        {
            (void)rAxis;
            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 & [ rAxis, rAxisUsage ] : m_aAxisUsageList)
        {
            (void)rAxis;
            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&&nbsp;rModel)
{
    //issue #i80518#
    for (sal_Int32 nAxisIndex = 0; nAxisIndex <= m_nMaxAxisIndex; nAxisIndex++)
    {
        for (auto & [ rAxis, rAxisUsage ] : m_aAxisUsageList)
        {
            (void)rAxis;
            std::vector<VCoordinateSystem*> aVCooSysList_Y
                = rAxisUsage.getCoordinateSystems(1, nAxisIndex);
            if (aVCooSysList_Y.empty())
                continue;

            rtl::Reference<Diagram> xDiagram(rModel.getFirstChartDiagram());
            if (!xDiagram.is())
                continue;

            bool bSeriesAttachedToThisAxis = false;
            sal_Int32 nAttachedAxisIndex = -1;
            {
                std::vector<rtl::Reference<DataSeries>> aSeriesVector = xDiagram->getDataSeries();
                for (auto const& series : aSeriesVector)
                {
                    sal_Int32 nCurrentIndex = series->getAttachedAxisIndex();
                    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 & [ rAxis, rAxisUsage ] : m_aAxisUsageList)
    {
        (void)rAxis;
        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));

            rtl::Reference<BaseCoordinateSystem> xCooSys(aVCooSysList[nC]->getModel());
            rtl::Reference<Axis> xAxis = xCooSys->getAxisByDimension2(nDimensionIndex, nAxisIndex);
            rtl::Reference<Axis> xCrossingMainAxis
                = AxisHelper::getCrossingMainAxis(xAxis, xCooSys);

            if (xCrossingMainAxis.is())
            {
                css::chart::ChartAxisPosition eCrossingMainAxisPos(
                    css::chart::ChartAxisPosition_ZERO);
                xCrossingMainAxis->getPropertyValue(u"CrossoverPosition"_ustr)
                    >>= eCrossingMainAxisPos;
                if (eCrossingMainAxisPos == css::chart::ChartAxisPosition_VALUE)
                {
                    double fValue = 0.0;
                    xCrossingMainAxis->getPropertyValue(u"CrossoverValue"_ustr) >>= 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 chart2 namespace

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Messung V0.5
C=77 H=88 G=82

¤ Dauer der Verarbeitung: 0.3 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.