summaryrefslogtreecommitdiff
path: root/chart2/source/model
diff options
context:
space:
mode:
authorvarshneydevansh <varshney.devansh614@gmail.com>2024-07-14 21:20:45 +0900
committerTomaž Vajngerl <quikee@gmail.com>2024-07-21 08:02:43 +0200
commit07ae0e5ada7cb595eb4815413a5bdd442c32a6ab (patch)
tree8a09c4364cd96f5668d4aa739e7786dfdb8df692 /chart2/source/model
parentb92b1ca8c14979550ec962464ec8d782cdd69d82 (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')
-rw-r--r--chart2/source/model/template/ChartTypeManager.cxx8
-rw-r--r--chart2/source/model/template/ChartTypeTemplate.cxx1
-rw-r--r--chart2/source/model/template/HistogramCalculator.cxx99
-rw-r--r--chart2/source/model/template/HistogramCalculator.hxx36
-rw-r--r--chart2/source/model/template/HistogramChartType.cxx203
-rw-r--r--chart2/source/model/template/HistogramChartType.hxx50
-rw-r--r--chart2/source/model/template/HistogramChartTypeTemplate.cxx160
-rw-r--r--chart2/source/model/template/HistogramChartTypeTemplate.hxx67
-rw-r--r--chart2/source/model/template/HistogramDataInterpreter.cxx116
-rw-r--r--chart2/source/model/template/HistogramDataInterpreter.hxx35
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: */