diff options
author | varshneydevansh <varshney.devansh614@gmail.com> | 2024-07-14 21:20:45 +0900 |
---|---|---|
committer | Tomaž Vajngerl <quikee@gmail.com> | 2024-07-21 08:02:43 +0200 |
commit | 07ae0e5ada7cb595eb4815413a5bdd442c32a6ab (patch) | |
tree | 8a09c4364cd96f5668d4aa739e7786dfdb8df692 /chart2/source/model | |
parent | b92b1ca8c14979550ec962464ec8d782cdd69d82 (diff) |
tdf#82716 Add initial implementation of the Histogram Chart
- Add the Histogram selection to the UI
- Histogram bars showing with No Gap
- Convert X and Y axis to group data into bins and frequency
- Adjusted failing UI test (tdf138556) as a new chart type was added
Change-Id: Id1f161adac943ead5e17c7fbb7e14c9ab7f1655e
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/167068
Tested-by: Jenkins
Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
Diffstat (limited to 'chart2/source/model')
10 files changed, 775 insertions, 0 deletions
diff --git a/chart2/source/model/template/ChartTypeManager.cxx b/chart2/source/model/template/ChartTypeManager.cxx index cd13bc38cdeb..8db74c180c9a 100644 --- a/chart2/source/model/template/ChartTypeManager.cxx +++ b/chart2/source/model/template/ChartTypeManager.cxx @@ -23,6 +23,7 @@ #include "LineChartTypeTemplate.hxx" #include "BarChartTypeTemplate.hxx" #include "ColumnLineChartTypeTemplate.hxx" +#include "HistogramChartTypeTemplate.hxx" #include "AreaChartTypeTemplate.hxx" #include "PieChartTypeTemplate.hxx" #include "ScatterChartTypeTemplate.hxx" @@ -79,6 +80,7 @@ enum TemplateId TEMPLATE_PERCENTSTACKEDTHREEDBARFLAT, TEMPLATE_COLUMNWITHLINE, TEMPLATE_STACKEDCOLUMNWITHLINE, + TEMPLATE_HISTOGRAM, TEMPLATE_AREA, TEMPLATE_STACKEDAREA, TEMPLATE_PERCENTSTACKEDAREA, @@ -155,6 +157,7 @@ const tTemplateMapType & lcl_DefaultChartTypeMap() {"com.sun.star.chart2.template.PercentStackedThreeDBarFlat", TEMPLATE_PERCENTSTACKEDTHREEDBARFLAT}, {"com.sun.star.chart2.template.ColumnWithLine", TEMPLATE_COLUMNWITHLINE}, {"com.sun.star.chart2.template.StackedColumnWithLine", TEMPLATE_STACKEDCOLUMNWITHLINE}, + {"com.sun.star.chart2.template.Histogram", TEMPLATE_HISTOGRAM}, {"com.sun.star.chart2.template.Area", TEMPLATE_AREA}, {"com.sun.star.chart2.template.StackedArea", TEMPLATE_STACKEDAREA}, {"com.sun.star.chart2.template.PercentStackedArea", TEMPLATE_PERCENTSTACKEDAREA}, @@ -365,6 +368,11 @@ rtl::Reference< ::chart::ChartTypeTemplate > ChartTypeManager::createTemplate( } break; + // Histogram + case TEMPLATE_HISTOGRAM: + xTemplate.set( new HistogramChartTypeTemplate( m_xContext, aServiceSpecifier, StackMode::NONE )); + break; + // Area case TEMPLATE_AREA: xTemplate.set( new AreaChartTypeTemplate( m_xContext, aServiceSpecifier, StackMode::NONE )); diff --git a/chart2/source/model/template/ChartTypeTemplate.cxx b/chart2/source/model/template/ChartTypeTemplate.cxx index 8e6e83fc9a7a..063335a3e626 100644 --- a/chart2/source/model/template/ChartTypeTemplate.cxx +++ b/chart2/source/model/template/ChartTypeTemplate.cxx @@ -574,6 +574,7 @@ void ChartTypeTemplate::adaptScales( // Bar types, but not BarOfPie aData.ShiftedCategoryPosition = m_aServiceName.indexOf("Column") != -1 || + m_aServiceName.indexOf("Histogram") != -1 || (m_aServiceName.indexOf("Bar") != -1 && !m_aServiceName.indexOf("BarOfPie")) || m_aServiceName.endsWith("Close"); diff --git a/chart2/source/model/template/HistogramCalculator.cxx b/chart2/source/model/template/HistogramCalculator.cxx new file mode 100644 index 000000000000..d53ad0eb4460 --- /dev/null +++ b/chart2/source/model/template/HistogramCalculator.cxx @@ -0,0 +1,99 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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/. + */ + +#include "HistogramCalculator.hxx" + +#include <algorithm> +#include <cmath> + +namespace chart +{ +HistogramCalculator::HistogramCalculator() = default; + +void HistogramCalculator::computeBinFrequencyHistogram(const std::vector<double>& rDataPoints) +{ + if (rDataPoints.empty()) + return; + + mnBins = 1; + mfBinWidth = 1.0; + maBinRanges.clear(); + maBinFrequencies.clear(); + + // Set min, max to the first value + double fMinValue = rDataPoints[0]; + double fMaxValue = rDataPoints[0]; + + // Compute min and max values, ignoring non-finite values + for (auto const& rValue : rDataPoints) + { + if (std::isfinite(rValue)) + { + fMinValue = std::min(fMinValue, rValue); + fMaxValue = std::max(fMaxValue, rValue); + } + } + + // Round min and max to 6 decimal places + // Not sure this is needed or desired + fMinValue = std::round(fMinValue * 1e6) / 1e6; + fMaxValue = std::round(fMaxValue * 1e6) / 1e6; + + // Handle the case where all values are the same + if (fMinValue == fMaxValue) + { + maBinRanges = { { fMinValue, fMinValue } }; + maBinFrequencies = { sal_Int32(rDataPoints.size()) }; + return; + } + + mnBins = sal_Int32(std::sqrt(rDataPoints.size())); + + // Calculate bin width, ensuring it's not zero and rounding to 6 decimal places + mfBinWidth = std::round((fMaxValue - fMinValue) / mnBins * 1e6) / 1e6; + + if (mfBinWidth <= 0.0) + { + mfBinWidth = 0.000001; //minimum bin width of 0.000001 + mnBins = sal_Int32(std::ceil((fMaxValue - fMinValue) / mfBinWidth)); + } + + //recalculate maxValue to ensure it's included in the last bin + fMaxValue = fMinValue + mfBinWidth * mnBins; + + // Initialize bin ranges and frequencies + maBinRanges.resize(mnBins); + maBinFrequencies.resize(mnBins, 0); + + // Calculate bin ranges + for (sal_Int32 nBin = 0; nBin < mnBins; ++nBin) + { + double fBinStart = fMinValue + nBin * mfBinWidth; + double fBinEnd = (nBin == mnBins - 1) ? fMaxValue : (fBinStart + mfBinWidth); + maBinRanges[nBin] = { std::round(fBinStart * 1e6) / 1e6, std::round(fBinEnd * 1e6) / 1e6 }; + } + + // Calculate frequencies + for (double fValue : rDataPoints) + { + if (std::isfinite(fValue)) + { + // Calculate into which bin the value falls into + sal_Int32 nBinIndex = sal_Int32((fValue - fMinValue) / mfBinWidth); + // Sanitize + nBinIndex = std::clamp(nBinIndex, sal_Int32(0), mnBins - 1); + + maBinFrequencies[nBinIndex]++; + } + } +} + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/chart2/source/model/template/HistogramCalculator.hxx b/chart2/source/model/template/HistogramCalculator.hxx new file mode 100644 index 000000000000..d2c43453af1b --- /dev/null +++ b/chart2/source/model/template/HistogramCalculator.hxx @@ -0,0 +1,36 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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/. + */ + +#pragma once + +#include <sal/types.h> +#include <vector> + +namespace chart +{ +class HistogramCalculator +{ + sal_Int32 mnBins = 1; + double mfBinWidth = 1.0; + + std::vector<std::pair<double, double>> maBinRanges; + std::vector<sal_Int32> maBinFrequencies; + +public: + HistogramCalculator(); + + void computeBinFrequencyHistogram(const std::vector<double>& dataPoints); + + const std::vector<std::pair<double, double>>& getBinRanges() const { return maBinRanges; } + const std::vector<sal_Int32>& getBinFrequencies() const { return maBinFrequencies; } +}; + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/chart2/source/model/template/HistogramChartType.cxx b/chart2/source/model/template/HistogramChartType.cxx new file mode 100644 index 000000000000..410ae80f04a5 --- /dev/null +++ b/chart2/source/model/template/HistogramChartType.cxx @@ -0,0 +1,203 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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/. + */ + +#include "HistogramChartType.hxx" +#include <servicenames_charttypes.hxx> +#include <CartesianCoordinateSystem.hxx> +#include <PropertyHelper.hxx> +#include <Axis.hxx> +#include <AxisHelper.hxx> +#include <AxisIndexDefines.hxx> +#include <com/sun/star/chart2/AxisType.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <cppuhelper/supportsservice.hxx> + +#include <algorithm> +#include <cmath> +#include <iostream> +namespace com::sun::star::uno +{ +class XComponentContext; +} + +using namespace ::com::sun::star; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::beans::Property; + +namespace +{ +enum +{ + PROP_HISTOGRAMCHARTTYPE_BINWIDTH, + PROP_HISTOGRAMCHARTTYPE_BINRANGE, + PROP_HISTOGRAMCHARTTYPE_FREQUENCYTYPE, + PROP_HISTOGRAMCHARTTYPE_GAPWIDTH_SEQUENCE +}; + +void lcl_AddPropertiesToVector(std::vector<Property>& rOutProperties) +{ + rOutProperties.emplace_back( + "BinWidth", PROP_HISTOGRAMCHARTTYPE_BINWIDTH, cppu::UnoType<double>::get(), + beans::PropertyAttribute::BOUND | beans::PropertyAttribute::MAYBEDEFAULT); + + rOutProperties.emplace_back( + "BinRange", PROP_HISTOGRAMCHARTTYPE_BINRANGE, cppu::UnoType<double>::get(), + beans::PropertyAttribute::BOUND | beans::PropertyAttribute::MAYBEDEFAULT); + + rOutProperties.emplace_back( + "FrequencyType", PROP_HISTOGRAMCHARTTYPE_FREQUENCYTYPE, cppu::UnoType<sal_Int32>::get(), + beans::PropertyAttribute::BOUND | beans::PropertyAttribute::MAYBEDEFAULT); + + rOutProperties.emplace_back("GapWidthSequence", PROP_HISTOGRAMCHARTTYPE_GAPWIDTH_SEQUENCE, + cppu::UnoType<sal_Int32>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT); +} + +::cppu::OPropertyArrayHelper& StaticHistogramChartTypeInfoHelper() +{ + static ::cppu::OPropertyArrayHelper aPropHelper = []() { + std::vector<css::beans::Property> aProperties; + lcl_AddPropertiesToVector(aProperties); + + std::sort(aProperties.begin(), aProperties.end(), ::chart::PropertyNameLess()); + + return comphelper::containerToSequence(aProperties); + }(); + return aPropHelper; +}; + +} // anonymous namespace + +namespace chart +{ +HistogramChartType::HistogramChartType() {} + +HistogramChartType::HistogramChartType(const HistogramChartType& rOther) + : ChartType(rOther) +{ +} + +HistogramChartType::~HistogramChartType() {} + +// ____ XCloneable ____ +uno::Reference<util::XCloneable> SAL_CALL HistogramChartType::createClone() +{ + return uno::Reference<util::XCloneable>(new HistogramChartType(*this)); +} + +rtl::Reference<ChartType> HistogramChartType::cloneChartType() const +{ + return new HistogramChartType(*this); +} + +// ____ XChartType ____ +rtl::Reference<::chart::BaseCoordinateSystem> +HistogramChartType::createCoordinateSystem2(sal_Int32 DimensionCount) +{ + rtl::Reference<CartesianCoordinateSystem> xResult + = new CartesianCoordinateSystem(DimensionCount); + + for (sal_Int32 i = 0; i < DimensionCount; i++) + { + rtl::Reference<Axis> xAxis = xResult->getAxisByDimension2(i, MAIN_AXIS_INDEX); + if (xAxis.is()) + { + chart2::ScaleData aScaleData = xAxis->getScaleData(); + aScaleData.Orientation = chart2::AxisOrientation_MATHEMATICAL; + aScaleData.Scaling = AxisHelper::createLinearScaling(); + + if (i == 0) //X-axis + { + aScaleData.AxisType = chart2::AxisType::REALNUMBER; + aScaleData.AutoDateAxis = false; + } + else if (i == 1) //Y-axis + { + aScaleData.AxisType = chart2::AxisType::REALNUMBER; + } + + xAxis->setScaleData(aScaleData); + } + } + + return xResult; +} + +OUString SAL_CALL HistogramChartType::getChartType() +{ + return CHART2_SERVICE_NAME_CHARTTYPE_HISTOGRAM; +} + +uno::Sequence<OUString> HistogramChartType::getSupportedPropertyRoles() +{ + return { u"FillColor"_ustr, u"BorderColor"_ustr }; +} + +::cppu::IPropertyArrayHelper& SAL_CALL HistogramChartType::getInfoHelper() +{ + return StaticHistogramChartTypeInfoHelper(); +} + +// ____ OPropertySet ____ +void HistogramChartType::GetDefaultValue(sal_Int32 nHandle, uno::Any& rAny) const +{ + static const ::chart::tPropertyValueMap aStaticDefaults = []() { + ::chart::tPropertyValueMap aTmp; + Sequence<sal_Int32> aSeq{ 0 }; // No gap for histogram + ::chart::PropertyHelper::setPropertyValueDefault( + aTmp, PROP_HISTOGRAMCHARTTYPE_GAPWIDTH_SEQUENCE, aSeq); + ::chart::PropertyHelper::setPropertyValueDefault(aTmp, PROP_HISTOGRAMCHARTTYPE_BINWIDTH, + 2.0); + ::chart::PropertyHelper::setPropertyValueDefault(aTmp, PROP_HISTOGRAMCHARTTYPE_BINRANGE, + 1.0); + ::chart::PropertyHelper::setPropertyValueDefault( + aTmp, PROP_HISTOGRAMCHARTTYPE_FREQUENCYTYPE, sal_Int32(0)); + return aTmp; + }(); + + tPropertyValueMap::const_iterator aFound(aStaticDefaults.find(nHandle)); + if (aFound == aStaticDefaults.end()) + rAny.clear(); + else + rAny = (*aFound).second; +} +// ____ XPropertySet ____ +uno::Reference<beans::XPropertySetInfo> SAL_CALL HistogramChartType::getPropertySetInfo() +{ + static uno::Reference<beans::XPropertySetInfo> xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(StaticHistogramChartTypeInfoHelper())); + return xPropertySetInfo; +} + +OUString SAL_CALL HistogramChartType::getImplementationName() +{ + return "com.sun.star.comp.chart.HistogramChartType"; +} + +sal_Bool SAL_CALL HistogramChartType::supportsService(const OUString& rServiceName) +{ + return cppu::supportsService(this, rServiceName); +} + +css::uno::Sequence<OUString> SAL_CALL HistogramChartType::getSupportedServiceNames() +{ + return { CHART2_SERVICE_NAME_CHARTTYPE_HISTOGRAM, "com.sun.star.chart2.ChartType" }; +} + +} // namespace chart + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +com_sun_star_comp_chart_HistogramChartType_get_implementation( + css::uno::XComponentContext* /*context*/, css::uno::Sequence<css::uno::Any> const&) +{ + return cppu::acquire(new ::chart::HistogramChartType()); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/chart2/source/model/template/HistogramChartType.hxx b/chart2/source/model/template/HistogramChartType.hxx new file mode 100644 index 000000000000..fa71b4196c90 --- /dev/null +++ b/chart2/source/model/template/HistogramChartType.hxx @@ -0,0 +1,50 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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/. + */ + +#pragma once + +#include <ChartType.hxx> + +namespace chart +{ +class HistogramChartType : public ChartType +{ +public: + explicit HistogramChartType(); + virtual ~HistogramChartType() override; + + virtual OUString SAL_CALL getImplementationName() override; + virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override; + virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override; + + virtual rtl::Reference<ChartType> cloneChartType() const override; + +protected: + explicit HistogramChartType(const HistogramChartType& rOther); + + // ____ XChartType ____ + rtl::Reference<::chart::BaseCoordinateSystem> + createCoordinateSystem2(sal_Int32 DimensionCount) override; + OUString SAL_CALL getChartType() override; + css::uno::Sequence<OUString> SAL_CALL getSupportedPropertyRoles() override; + + // ____ OPropertySet ____ + void GetDefaultValue(sal_Int32 nHandle, css::uno::Any& rAny) const override; + ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override; + + // ____ XPropertySet ____ + css::uno::Reference<css::beans::XPropertySetInfo> SAL_CALL getPropertySetInfo() override; + + // ____ XCloneable ____ + css::uno::Reference<css::util::XCloneable> SAL_CALL createClone() override; +}; + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/chart2/source/model/template/HistogramChartTypeTemplate.cxx b/chart2/source/model/template/HistogramChartTypeTemplate.cxx new file mode 100644 index 000000000000..0bc41d56fc7b --- /dev/null +++ b/chart2/source/model/template/HistogramChartTypeTemplate.cxx @@ -0,0 +1,160 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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/. + */ + +#include "HistogramChartTypeTemplate.hxx" +#include "HistogramChartType.hxx" +#include "HistogramDataInterpreter.hxx" +#include <Diagram.hxx> +#include <DataSeries.hxx> +#include <DataSeriesHelper.hxx> +#include <PropertyHelper.hxx> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/drawing/LineStyle.hpp> +#include <com/sun/star/chart2/DataPointGeometry3D.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <comphelper/diagnose_ex.hxx> + +#include <algorithm> + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::beans::Property; + +namespace +{ +enum +{ + PROP_HISTOGRAM_TEMPLATE_DIMENSION, +}; + +void lcl_AddPropertiesToVector(std::vector<Property>& rOutProperties) +{ + rOutProperties.emplace_back( + "Dimension", PROP_HISTOGRAM_TEMPLATE_DIMENSION, cppu::UnoType<sal_Int32>::get(), + beans::PropertyAttribute::BOUND | beans::PropertyAttribute::MAYBEDEFAULT); +} + +::cppu::OPropertyArrayHelper& StaticHistogramChartTypeTemplateInfoHelper() +{ + static ::cppu::OPropertyArrayHelper aPropHelper = []() { + std::vector<css::beans::Property> aProperties; + lcl_AddPropertiesToVector(aProperties); + + std::sort(aProperties.begin(), aProperties.end(), ::chart::PropertyNameLess()); + + return comphelper::containerToSequence(aProperties); + }(); + return aPropHelper; +}; + +} // anonymous namespace + +namespace chart +{ +HistogramChartTypeTemplate::HistogramChartTypeTemplate( + Reference<uno::XComponentContext> const& xContext, const OUString& rServiceName, + StackMode eStackMode, sal_Int32 nDim /* = 2 */) + : ChartTypeTemplate(xContext, rServiceName) + , m_eStackMode(eStackMode) + , m_nDim(nDim) +{ +} + +sal_Int32 HistogramChartTypeTemplate::getDimension() const { return m_nDim; } + +StackMode HistogramChartTypeTemplate::getStackMode(sal_Int32 /* nChartTypeIndex */) const +{ + return m_eStackMode; +} + +rtl::Reference<ChartType> + HistogramChartTypeTemplate::getChartTypeForIndex(sal_Int32 /*nChartTypeIndex*/) +{ + return new HistogramChartType(); +} + +rtl::Reference<ChartType> HistogramChartTypeTemplate::getChartTypeForNewSeries2( + const std::vector<rtl::Reference<ChartType>>& aFormerlyUsedChartTypes) +{ + rtl::Reference<ChartType> xResult(getChartTypeForIndex(0)); + ChartTypeTemplate::copyPropertiesFromOldToNewCoordinateSystem(aFormerlyUsedChartTypes, xResult); + return xResult; +} + +// ____ OPropertySet ____ +void HistogramChartTypeTemplate::GetDefaultValue(sal_Int32 nHandle, uno::Any& rAny) const +{ + static ::chart::tPropertyValueMap aStaticDefaults = []() { + ::chart::tPropertyValueMap aTmp; + ::chart::PropertyHelper::setPropertyValueDefault<sal_Int32>( + aTmp, PROP_HISTOGRAM_TEMPLATE_DIMENSION, 2); + return aTmp; + }(); + tPropertyValueMap::const_iterator aFound(aStaticDefaults.find(nHandle)); + if (aFound == aStaticDefaults.end()) + rAny.clear(); + else + rAny = (*aFound).second; +} + +::cppu::IPropertyArrayHelper& SAL_CALL HistogramChartTypeTemplate::getInfoHelper() +{ + return StaticHistogramChartTypeTemplateInfoHelper(); +} + +// ____ XPropertySet ____ +Reference<beans::XPropertySetInfo> SAL_CALL HistogramChartTypeTemplate::getPropertySetInfo() +{ + static uno::Reference<beans::XPropertySetInfo> xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo( + StaticHistogramChartTypeTemplateInfoHelper())); + return xPropertySetInfo; +} + +void HistogramChartTypeTemplate::applyStyle2(const rtl::Reference<DataSeries>& xSeries, + ::sal_Int32 nChartTypeIndex, ::sal_Int32 nSeriesIndex, + ::sal_Int32 nSeriesCount) +{ + ChartTypeTemplate::applyStyle2(xSeries, nChartTypeIndex, nSeriesIndex, nSeriesCount); + DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints(xSeries, "BorderStyle", + uno::Any(drawing::LineStyle_NONE)); +} + +void HistogramChartTypeTemplate::resetStyles2(const rtl::Reference<::chart::Diagram>& xDiagram) +{ + ChartTypeTemplate::resetStyles2(xDiagram); + std::vector<rtl::Reference<DataSeries>> aSeriesVec(xDiagram->getDataSeries()); + uno::Any aLineStyleAny(drawing::LineStyle_NONE); + for (auto const& series : aSeriesVec) + { + if (series->getPropertyValue("BorderStyle") == aLineStyleAny) + { + series->setPropertyToDefault("BorderStyle"); + } + } + + xDiagram->setVertical(false); +} + +rtl::Reference<DataInterpreter> HistogramChartTypeTemplate::getDataInterpreter2() +{ + if (!m_xDataInterpreter.is()) + m_xDataInterpreter.set(new HistogramDataInterpreter); + + return m_xDataInterpreter; +} + +IMPLEMENT_FORWARD_XINTERFACE2(HistogramChartTypeTemplate, ChartTypeTemplate, OPropertySet) +IMPLEMENT_FORWARD_XTYPEPROVIDER2(HistogramChartTypeTemplate, ChartTypeTemplate, OPropertySet) + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/chart2/source/model/template/HistogramChartTypeTemplate.hxx b/chart2/source/model/template/HistogramChartTypeTemplate.hxx new file mode 100644 index 000000000000..292cdce32f33 --- /dev/null +++ b/chart2/source/model/template/HistogramChartTypeTemplate.hxx @@ -0,0 +1,67 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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/. + */ +#pragma once + +#include <OPropertySet.hxx> +#include <comphelper/uno3.hxx> + +#include <ChartTypeTemplate.hxx> +#include <StackMode.hxx> + +namespace chart +{ +class HistogramChartTypeTemplate : public ChartTypeTemplate, public ::property::OPropertySet +{ +public: + explicit HistogramChartTypeTemplate( + css::uno::Reference<css::uno::XComponentContext> const& xContext, + const OUString& rServiceName, StackMode eStackMode, sal_Int32 nDim = 2); + + /// merge XInterface implementations + DECLARE_XINTERFACE() + /// merge XTypeProvider implementations + DECLARE_XTYPEPROVIDER() + +protected: + // ____ OPropertySet ____ + virtual void GetDefaultValue(sal_Int32 nHandle, css::uno::Any& rAny) const override; + virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override; + + // ____ XPropertySet ____ + virtual css::uno::Reference<css::beans::XPropertySetInfo> + SAL_CALL getPropertySetInfo() override; + + // ____ ChartTypeTemplate ____ + virtual rtl::Reference<::chart::ChartType> getChartTypeForNewSeries2( + const std::vector<rtl::Reference<::chart::ChartType>>& aFormerlyUsedChartTypes) override; + + virtual sal_Bool SAL_CALL supportsCategories() override { return true; } + + virtual void applyStyle2(const rtl::Reference<::chart::DataSeries>& xSeries, + ::sal_Int32 nChartTypeGroupIndex, ::sal_Int32 nSeriesIndex, + ::sal_Int32 nSeriesCount) override; + + virtual void resetStyles2(const rtl::Reference<::chart::Diagram>& xDiagram) override; + + virtual rtl::Reference<::chart::ChartType> + getChartTypeForIndex(sal_Int32 nChartTypeIndex) override; + + virtual sal_Int32 getDimension() const override; + virtual StackMode getStackMode(sal_Int32 nChartTypeIndex) const override; + + rtl::Reference<chart::DataInterpreter> getDataInterpreter2() override; + +private: + StackMode m_eStackMode; + sal_Int32 m_nDim; +}; + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/chart2/source/model/template/HistogramDataInterpreter.cxx b/chart2/source/model/template/HistogramDataInterpreter.cxx new file mode 100644 index 000000000000..bfadbbd3c83f --- /dev/null +++ b/chart2/source/model/template/HistogramDataInterpreter.cxx @@ -0,0 +1,116 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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/. + */ + +#include <sal/config.h> + +#include "HistogramDataInterpreter.hxx" +#include <HistogramDataSequence.hxx> +#include "HistogramCalculator.hxx" +#include <LabeledDataSequence.hxx> + +#include <DataSeries.hxx> +#include <DataSeriesHelper.hxx> +#include <CommonConverters.hxx> +#include <com/sun/star/util/XCloneable.hpp> +#include <comphelper/diagnose_ex.hxx> +#include <sal/log.hxx> + +using namespace css; + +namespace chart +{ +InterpretedData HistogramDataInterpreter::interpretDataSource( + const uno::Reference<chart2::data::XDataSource>& xSource, + const uno::Sequence<beans::PropertyValue>& /*aArguments*/, + const std::vector<rtl::Reference<DataSeries>>& /*aSeriesToReUse*/) +{ + if (!xSource.is()) + return InterpretedData(); + + InterpretedData aInterpretedData; + + std::vector<uno::Reference<chart2::data::XLabeledDataSequence>> aData + = DataInterpreter::getDataSequences(xSource); + + if (aData.empty() || !aData[0].is()) + return InterpretedData(); + + SetRole(aData[0]->getValues(), u"values-y-original"_ustr); + + // Extract raw data from the spreadsheet + std::vector<double> rawData; + uno::Reference<chart2::data::XDataSequence> xValues = aData[0]->getValues(); + if (!xValues.is()) + return InterpretedData(); + + uno::Sequence<uno::Any> aRawAnyValues = xValues->getData(); + + for (const auto& aAny : aRawAnyValues) + { + double fValue = 0.0; + if (aAny >>= fValue) // Extract double from Any + { + rawData.push_back(fValue); + } + } + + // Perform histogram calculations + HistogramCalculator aHistogramCalculator; + aHistogramCalculator.computeBinFrequencyHistogram(rawData); + + // Get bin ranges and frequencies + const auto& binRanges = aHistogramCalculator.getBinRanges(); + const auto& binFrequencies = aHistogramCalculator.getBinFrequencies(); + + // Create labels and values for HistogramDataSequence + std::vector<OUString> labels; + std::vector<double> values; + for (size_t i = 0; i < binRanges.size(); ++i) + { + labels.push_back(u"[" + OUString::number(binRanges[i].first) + u"-" + + OUString::number(binRanges[i].second) + u")"); + values.push_back(static_cast<double>(binFrequencies[i])); + } + + rtl::Reference<DataSeries> xSeries = new DataSeries; + std::vector<uno::Reference<chart2::data::XLabeledDataSequence>> aNewData; + aNewData.push_back(aData[0]); + + rtl::Reference<HistogramDataSequence> aValuesDataSequence = new HistogramDataSequence(); + aValuesDataSequence->setValues(comphelper::containerToSequence(values)); + aValuesDataSequence->setLabels(comphelper::containerToSequence(labels)); + + uno::Reference<chart2::data::XDataSequence> aDataSequence = aValuesDataSequence; + SetRole(aDataSequence, u"values-y"_ustr); + aNewData.push_back(new LabeledDataSequence(aDataSequence)); + + xSeries->setData(aNewData); + std::vector<rtl::Reference<DataSeries>> aSeriesVec; + aSeriesVec.push_back(xSeries); + + aInterpretedData.Series.push_back(aSeriesVec); + aInterpretedData.Categories = nullptr; + + return aInterpretedData; +} + +InterpretedData +HistogramDataInterpreter::reinterpretDataSeries(const InterpretedData& rInterpretedData) +{ + return rInterpretedData; +} + +bool HistogramDataInterpreter::isDataCompatible(const InterpretedData& /*aInterpretedData*/) +{ + return false; +} + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/chart2/source/model/template/HistogramDataInterpreter.hxx b/chart2/source/model/template/HistogramDataInterpreter.hxx new file mode 100644 index 000000000000..9d90e0f2512a --- /dev/null +++ b/chart2/source/model/template/HistogramDataInterpreter.hxx @@ -0,0 +1,35 @@ +/* -*- 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/. + */ + +#pragma once + +#include <DataInterpreter.hxx> + +namespace chart +{ +class HistogramDataInterpreter : public DataInterpreter +{ +public: + explicit HistogramDataInterpreter() = default; + +protected: + // ____ DataInterpreter ____ + virtual InterpretedData interpretDataSource( + const css::uno::Reference<css::chart2::data::XDataSource>& xSource, + const css::uno::Sequence<css::beans::PropertyValue>& aArguments, + const std::vector<rtl::Reference<::chart::DataSeries>>& aSeriesToReUse) override; + + virtual InterpretedData reinterpretDataSeries(const InterpretedData& aInterpretedData) override; + + virtual bool isDataCompatible(const InterpretedData& aInterpretedData) override; +}; + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |