chart2/Library_chartcore.mk | 6 chart2/inc/bitmaps.hlst | 2 chart2/inc/strings.hrc | 2 chart2/source/chartcore.component | 5 chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx | 6 chart2/source/controller/dialogs/ChartTypeDialogController.cxx | 51 ++ chart2/source/controller/dialogs/tp_ChartType.cxx | 1 chart2/source/inc/ChartTypeDialogController.hxx | 14 chart2/source/inc/HistogramDataSequence.hxx | 104 +++++ chart2/source/inc/servicenames_charttypes.hxx | 2 chart2/source/model/template/ChartTypeManager.cxx | 8 chart2/source/model/template/ChartTypeTemplate.cxx | 1 chart2/source/model/template/HistogramCalculator.cxx | 99 ++++ chart2/source/model/template/HistogramCalculator.hxx | 36 + chart2/source/model/template/HistogramChartType.cxx | 203 ++++++++++ chart2/source/model/template/HistogramChartType.hxx | 50 ++ chart2/source/model/template/HistogramChartTypeTemplate.cxx | 160 +++++++ chart2/source/model/template/HistogramChartTypeTemplate.hxx | 67 +++ chart2/source/model/template/HistogramDataInterpreter.cxx | 116 +++++ chart2/source/model/template/HistogramDataInterpreter.hxx | 35 + chart2/source/tools/ChartTypeHelper.cxx | 25 + chart2/source/tools/HistogramDataSequence.cxx | 155 +++++++ chart2/source/view/charttypes/HistogramChart.cxx | 181 ++++++++ chart2/source/view/charttypes/HistogramChart.hxx | 50 ++ chart2/source/view/charttypes/VSeriesPlotter.cxx | 4 icon-themes/colibre/chart2/res/histogram_52x60.png |binary icon-themes/colibre/chart2/res/typehistogram_16.png |binary offapi/UnoApi_offapi.mk | 1 offapi/com/sun/star/chart/HistogramDiagram.idl | 35 + oox/inc/drawingml/chart/typegroupconverter.hxx | 6 oox/source/drawingml/chart/typegroupconverter.cxx | 2 solenv/bin/native-code.py | 1 sw/qa/uitest/chart/tdf138556.py | 4 33 files changed, 1426 insertions(+), 6 deletions(-)
New commits: commit 07ae0e5ada7cb595eb4815413a5bdd442c32a6ab Author: varshneydevansh <varshney.devansh...@gmail.com> AuthorDate: Sun Jul 14 21:20:45 2024 +0900 Commit: Tomaž Vajngerl <qui...@gmail.com> CommitDate: Sun Jul 21 08:02:43 2024 +0200 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 <qui...@gmail.com> diff --git a/chart2/Library_chartcore.mk b/chart2/Library_chartcore.mk index b61390ec42ea..6c7e0c06a6df 100644 --- a/chart2/Library_chartcore.mk +++ b/chart2/Library_chartcore.mk @@ -87,6 +87,7 @@ $(eval $(call gb_Library_add_exception_objects,chartcore,\ chart2/source/view/charttypes/BubbleChart \ chart2/source/view/charttypes/CandleStickChart \ chart2/source/view/charttypes/CategoryPositionHelper \ + chart2/source/view/charttypes/HistogramChart \ chart2/source/view/charttypes/NetChart \ chart2/source/view/charttypes/PieChart \ chart2/source/view/charttypes/Splines \ @@ -156,6 +157,10 @@ $(eval $(call gb_Library_add_exception_objects,chartcore,\ chart2/source/model/template/ColumnLineDataInterpreter \ chart2/source/model/template/DataInterpreter \ chart2/source/model/template/FilledNetChartType \ + chart2/source/model/template/HistogramChartType \ + chart2/source/model/template/HistogramChartTypeTemplate \ + chart2/source/model/template/HistogramDataInterpreter \ + chart2/source/model/template/HistogramCalculator \ chart2/source/model/template/LineChartType \ chart2/source/model/template/LineChartTypeTemplate \ chart2/source/model/template/NetChartType \ @@ -191,6 +196,7 @@ $(eval $(call gb_Library_add_exception_objects,chartcore,\ chart2/source/tools/ExponentialRegressionCurveCalculator \ chart2/source/tools/FillProperties \ chart2/source/tools/FormattedStringHelper \ + chart2/source/tools/HistogramDataSequence \ chart2/source/tools/InternalData \ chart2/source/tools/InternalDataProvider \ chart2/source/tools/LabeledDataSequence \ diff --git a/chart2/inc/bitmaps.hlst b/chart2/inc/bitmaps.hlst index 4c184dc09aeb..d5c7b75ff4c1 100644 --- a/chart2/inc/bitmaps.hlst +++ b/chart2/inc/bitmaps.hlst @@ -11,6 +11,7 @@ inline constexpr OUString BMP_TYPE_COLUMN = u"chart2/res/typecolumn_16.png"_ustr; inline constexpr OUString BMP_TYPE_BAR = u"chart2/res/typebar_16.png"_ustr; +inline constexpr OUString BMP_TYPE_HISTOGRAM = u"chart2/res/typehistogram_16.png"_ustr; inline constexpr OUString BMP_TYPE_PIE = u"chart2/res/typepie_16.png"_ustr; inline constexpr OUString BMP_TYPE_LINE = u"chart2/res/typepointline_16.png"_ustr; inline constexpr OUString BMP_TYPE_XY = u"chart2/res/typexy_16.png"_ustr; @@ -51,6 +52,7 @@ inline constexpr OUString BMP_COLUMNS_3D = u"chart2/res/columns3ddeep_52x60.png" inline constexpr OUString BMP_COLUMNS_3D_1 = u"chart2/res/columns3d_52x60.png"_ustr; inline constexpr OUString BMP_COLUMNS_3D_2 = u"chart2/res/columnstack3d_52x60.png"_ustr; inline constexpr OUString BMP_COLUMNS_3D_3 = u"chart2/res/columnpercent3d_52x60.png"_ustr; +inline constexpr OUString BMP_HISTOGRAM = u"chart2/res/histogram_52x60.png"_ustr; inline constexpr OUString BMP_KEGELQ_3D_1 = u"chart2/res/conehori_52x60.png"_ustr; inline constexpr OUString BMP_KEGELQ_3D_2 = u"chart2/res/conehoristack_52x60.png"_ustr; inline constexpr OUString BMP_KEGELQ_3D_3 = u"chart2/res/conehoripercent_52x60.png"_ustr; diff --git a/chart2/inc/strings.hrc b/chart2/inc/strings.hrc index 8a6ec2fd2777..f671a404a6d5 100644 --- a/chart2/inc/strings.hrc +++ b/chart2/inc/strings.hrc @@ -158,6 +158,8 @@ #define STR_TYPE_COLUMN NC_("STR_TYPE_COLUMN", "Column") #define STR_TYPE_BAR NC_("STR_TYPE_BAR", "Bar") +#define STR_TYPE_HISTOGRAM NC_("STR_TYPE_HISTOGRAM", "Histogram") +#define STR_HISTOGRAM NC_("STR_HISTOGRAM", "Histogram Chart") #define STR_TYPE_AREA NC_("STR_TYPE_AREA", "Area") #define STR_TYPE_PIE NC_("STR_TYPE_PIE", "Pie") #define STR_PIE_EXPLODED NC_("STR_PIE_EXPLODED", "Exploded Pie Chart") diff --git a/chart2/source/chartcore.component b/chart2/source/chartcore.component index d15c808919df..9527f52cf432 100644 --- a/chart2/source/chartcore.component +++ b/chart2/source/chartcore.component @@ -136,6 +136,11 @@ constructor="com_sun_star_comp_chart_ColumnChartType_get_implementation"> <service name="com.sun.star.chart2.ChartType"/> <service name="com.sun.star.chart2.ColumnChartType"/> + </implementation> + <implementation name="com.sun.star.comp.chart.HistogramChartType" + constructor="com_sun_star_comp_chart_HistogramChartType_get_implementation"> + <service name="com.sun.star.chart2.ChartType"/> + <service name="com.sun.star.chart2.HistogramChartType"/> </implementation> <implementation name="com.sun.star.comp.chart.DataSeries" constructor="com_sun_star_comp_chart_DataSeries_get_implementation"> diff --git a/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx b/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx index f0e8d0168e1a..12b8b1f07943 100644 --- a/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx +++ b/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx @@ -519,9 +519,12 @@ OUString lcl_getDiagramType( std::u16string_view rTemplateServiceName ) // "PercentStackedLine" "LineSymbol" "StackedLineSymbol" // "PercentStackedLineSymbol" "ThreeDLine" "StackedThreeDLine" // "PercentStackedThreeDLine" "ThreeDLineDeep" - if( aName.find( u"Line" ) != std::u16string_view::npos || aName.find( u"Symbol" ) != std::u16string_view::npos ) + if( aName.find(u"Line") != std::u16string_view::npos || aName.find( u"Symbol" ) != std::u16string_view::npos ) return u"com.sun.star.chart.LineDiagram"_ustr; + if (aName.find(u"Histogram") != std::u16string_view::npos) + return u"com.sun.star.chart.HistogramDiagram"_ustr; + OSL_FAIL( "unknown template" ); } @@ -536,6 +539,7 @@ const tMakeStringStringMap& lcl_getChartTypeNameMap() {"com.sun.star.chart2.LineChartType", "com.sun.star.chart.LineDiagram"}, {"com.sun.star.chart2.AreaChartType", "com.sun.star.chart.AreaDiagram"}, {"com.sun.star.chart2.ColumnChartType", "com.sun.star.chart.BarDiagram"}, + {"com.sun.star.chart2.HistogramChartType", "com.sun.star.chart.HistogramDiagram"}, {"com.sun.star.chart2.PieChartType", "com.sun.star.chart.PieDiagram"}, {"com.sun.star.chart2.DonutChartType", "com.sun.star.chart.DonutDiagram"}, {"com.sun.star.chart2.ScatterChartType", "com.sun.star.chart.XYDiagram"}, diff --git a/chart2/source/controller/dialogs/ChartTypeDialogController.cxx b/chart2/source/controller/dialogs/ChartTypeDialogController.cxx index 12ad91e3aa1b..211d54a0e80c 100644 --- a/chart2/source/controller/dialogs/ChartTypeDialogController.cxx +++ b/chart2/source/controller/dialogs/ChartTypeDialogController.cxx @@ -541,6 +541,57 @@ void BarChartDialogController::fillSubTypeList( ValueSet& rSubTypeList, const Ch rSubTypeList.SetItemText( 4, SchResId( STR_DEEP ) ); } +HistogramChartDialogController::HistogramChartDialogController() +{ + bSupports3D = false; +} + +HistogramChartDialogController::~HistogramChartDialogController() +{ +} + +OUString HistogramChartDialogController::getName() +{ + return SchResId(STR_TYPE_HISTOGRAM); +} + +OUString HistogramChartDialogController::getImage() +{ + return BMP_TYPE_HISTOGRAM; +} + +const tTemplateServiceChartTypeParameterMap& HistogramChartDialogController::getTemplateMap() const +{ + static tTemplateServiceChartTypeParameterMap s_aTemplateMap{ + {"com.sun.star.chart2.template.Histogram" , ChartTypeParameter(1, false, false, GlobalStackMode_NONE)} + }; + return s_aTemplateMap; +} +void HistogramChartDialogController::fillSubTypeList(ValueSet& rSubTypeList, const ChartTypeParameter& /*rParameter*/) +{ + rSubTypeList.Clear(); + rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_HISTOGRAM)); + rSubTypeList.SetItemText(1, SchResId(STR_HISTOGRAM)); +} + +void HistogramChartDialogController::adjustParameterToSubType(ChartTypeParameter& rParameter) +{ + rParameter.b3DLook = false; + + switch (rParameter.nSubTypeIndex) + { + case 2: + // Pareto Histogram + break; + default: + // Standard Histogram + rParameter.eStackMode = GlobalStackMode_NONE; // Ensure no stacking + rParameter.bXAxisWithValues = false; // Standard histogram may not need X-axis values + // Set default bin width or other relevant properties if needed + break; + } +} + PieChartDialogController::PieChartDialogController() { } diff --git a/chart2/source/controller/dialogs/tp_ChartType.cxx b/chart2/source/controller/dialogs/tp_ChartType.cxx index b92caf4902e9..f469505438af 100644 --- a/chart2/source/controller/dialogs/tp_ChartType.cxx +++ b/chart2/source/controller/dialogs/tp_ChartType.cxx @@ -95,6 +95,7 @@ ChartTypeTabPage::ChartTypeTabPage(weld::Container* pPage, weld::DialogControlle m_aChartTypeDialogControllerList.push_back(std::make_unique<ColumnChartDialogController>()); m_aChartTypeDialogControllerList.push_back(std::make_unique<BarChartDialogController>()); + m_aChartTypeDialogControllerList.push_back(std::make_unique<HistogramChartDialogController>()); m_aChartTypeDialogControllerList.push_back(std::make_unique<PieChartDialogController>()); m_aChartTypeDialogControllerList.push_back(std::make_unique<AreaChartDialogController>()); m_aChartTypeDialogControllerList.push_back(std::make_unique<LineChartDialogController>()); diff --git a/chart2/source/inc/ChartTypeDialogController.hxx b/chart2/source/inc/ChartTypeDialogController.hxx index 4c03ff269e1f..72c584a89095 100644 --- a/chart2/source/inc/ChartTypeDialogController.hxx +++ b/chart2/source/inc/ChartTypeDialogController.hxx @@ -179,6 +179,20 @@ public: const ChartTypeParameter& rParameter) override; }; +class HistogramChartDialogController final : public ChartTypeDialogController +{ +public: + HistogramChartDialogController(); + virtual ~HistogramChartDialogController() override; + + virtual OUString getName() override; + virtual OUString getImage() override; + virtual const tTemplateServiceChartTypeParameterMap& getTemplateMap() const override; + virtual void fillSubTypeList(ValueSet& rSubTypeList, + const ChartTypeParameter& rParameter) override; + virtual void adjustParameterToSubType(ChartTypeParameter& rParameter) override; +}; + class PieChartDialogController final : public ChartTypeDialogController { public: diff --git a/chart2/source/inc/HistogramDataSequence.hxx b/chart2/source/inc/HistogramDataSequence.hxx new file mode 100644 index 000000000000..3a8ac0233476 --- /dev/null +++ b/chart2/source/inc/HistogramDataSequence.hxx @@ -0,0 +1,104 @@ +/* -*- 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 + +// helper classes +#include <comphelper/compbase.hxx> +#include <comphelper/uno3.hxx> +#include <comphelper/broadcasthelper.hxx> +#include <comphelper/propertycontainer2.hxx> +#include <comphelper/proparrhlp.hxx> +#include <rtl/ref.hxx> + +#include "ModifyListenerHelper.hxx" + +// interfaces and types +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/chart2/data/XDataSequence.hpp> +#include <com/sun/star/chart2/data/XNumericalDataSequence.hpp> +#include <com/sun/star/chart2/data/XTextualDataSequence.hpp> +#include <com/sun/star/util/XCloneable.hpp> +#include <com/sun/star/util/XModifiable.hpp> + +namespace chart +{ +typedef ::comphelper::WeakComponentImplHelper< + css::chart2::data::XDataSequence, css::chart2::data::XNumericalDataSequence, + css::chart2::data::XTextualDataSequence, css::util::XCloneable, css::util::XModifyBroadcaster, + css::lang::XServiceInfo> + HistogramDataSequence_Base; + +class HistogramDataSequence final + : public HistogramDataSequence_Base, + public ::comphelper::OPropertyContainer2, + public ::comphelper::OPropertyArrayUsageHelper<HistogramDataSequence> +{ +public: + HistogramDataSequence(); + virtual ~HistogramDataSequence() override; + + /// declare XServiceInfo methods + OUString SAL_CALL getImplementationName() override; + sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override; + css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override; + + /// merge XInterface implementations + DECLARE_XINTERFACE() + + /// merge XTypeProvider implementations + DECLARE_XTYPEPROVIDER() + + // XPropertySet + /// @see css::beans::XPropertySet + virtual css::uno::Reference<css::beans::XPropertySetInfo> + SAL_CALL getPropertySetInfo() override; + /// @see ::comphelper::OPropertySetHelper + virtual ::cppu::IPropertyArrayHelper& getInfoHelper() override; + /// @see ::comphelper::OPropertyArrayUsageHelper + virtual ::cppu::IPropertyArrayHelper* createArrayHelper() const override; + + // XDataSequence + css::uno::Sequence<css::uno::Any> SAL_CALL getData() override; + OUString SAL_CALL getSourceRangeRepresentation() override; + css::uno::Sequence<OUString> + SAL_CALL generateLabel(css::chart2::data::LabelOrigin nLabelOrigin) override; + sal_Int32 SAL_CALL getNumberFormatKeyByIndex(sal_Int32 nIndex) override; + + // XNumericalDataSequence + /// @see css::chart::data::XNumericalDataSequence + virtual css::uno::Sequence<double> SAL_CALL getNumericalData() override; + + // XTextualDataSequence + /// @see css::chart::data::XTextualDataSequence + virtual css::uno::Sequence<OUString> SAL_CALL getTextualData() override; + + // XCloneable + virtual css::uno::Reference<css::util::XCloneable> SAL_CALL createClone() override; + + // XModifyBroadcaster + virtual void SAL_CALL + addModifyListener(const css::uno::Reference<css::util::XModifyListener>& aListener) override; + virtual void SAL_CALL + removeModifyListener(const css::uno::Reference<css::util::XModifyListener>& aListener) override; + + void setLabels(css::uno::Sequence<OUString> const& xLabels) { mxLabels = xLabels; } + + void setValues(css::uno::Sequence<double> const& xValues) { mxValues = xValues; } + +private: + rtl::Reference<chart::ModifyEventForwarder> m_xModifyEventForwarder; + OUString m_sRole; + css::uno::Sequence<OUString> mxLabels; + css::uno::Sequence<double> mxValues; +}; + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/inc/servicenames_charttypes.hxx b/chart2/source/inc/servicenames_charttypes.hxx index 5ab2dcbf4929..2ef665a0254f 100644 --- a/chart2/source/inc/servicenames_charttypes.hxx +++ b/chart2/source/inc/servicenames_charttypes.hxx @@ -26,6 +26,8 @@ inline constexpr OUString CHART2_SERVICE_NAME_CHARTTYPE_BAR = u"com.sun.star.chart2.BarChartType"_ustr; inline constexpr OUString CHART2_SERVICE_NAME_CHARTTYPE_COLUMN = u"com.sun.star.chart2.ColumnChartType"_ustr; +inline constexpr OUString CHART2_SERVICE_NAME_CHARTTYPE_HISTOGRAM + = u"com.sun.star.chart2.HistogramChartType"_ustr; inline constexpr OUString CHART2_SERVICE_NAME_CHARTTYPE_LINE = u"com.sun.star.chart2.LineChartType"_ustr; inline constexpr OUString CHART2_SERVICE_NAME_CHARTTYPE_SCATTER 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: */ diff --git a/chart2/source/tools/ChartTypeHelper.cxx b/chart2/source/tools/ChartTypeHelper.cxx index f49a45ad4162..dec8fcec29bf 100644 --- a/chart2/source/tools/ChartTypeHelper.cxx +++ b/chart2/source/tools/ChartTypeHelper.cxx @@ -208,6 +208,8 @@ bool ChartTypeHelper::isSupportingOverlapAndGapWidthProperties( return true; if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_BAR) ) return true; + if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_HISTOGRAM) ) + return true; } return false; } @@ -314,6 +316,18 @@ uno::Sequence < sal_Int32 > ChartTypeHelper::getSupportedLabelPlacements( const *pSeq++ = css::chart::DataLabelPlacement::INSIDE; *pSeq++ = css::chart::DataLabelPlacement::NEAR_ORIGIN; } + else if (aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_HISTOGRAM)) + { + aRet.realloc(6); + sal_Int32* pSeq = aRet.getArray(); + + *pSeq++ = css::chart::DataLabelPlacement::TOP; + *pSeq++ = css::chart::DataLabelPlacement::BOTTOM; + *pSeq++ = css::chart::DataLabelPlacement::CENTER; + *pSeq++ = css::chart::DataLabelPlacement::OUTSIDE; + *pSeq++ = css::chart::DataLabelPlacement::INSIDE; + *pSeq++ = css::chart::DataLabelPlacement::NEAR_ORIGIN; + } else if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_AREA) ) { bool bStacked = false; @@ -458,7 +472,9 @@ bool ChartTypeHelper::isSupportingCategoryPositioning( const rtl::Reference< Cha aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK)) return true; else if (nDimensionCount == 2 && - (aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_COLUMN) || aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_BAR))) + (aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_COLUMN) || + aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_BAR) || + aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_HISTOGRAM))) return true; } return false; @@ -627,6 +643,13 @@ uno::Sequence < sal_Int32 > ChartTypeHelper::getSupportedMissingValueTreatments( *pSeq++ = css::chart::MissingValueTreatment::LEAVE_GAP; *pSeq++ = css::chart::MissingValueTreatment::USE_ZERO; } + else if (aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_HISTOGRAM)) + { + // Assuming histograms typically use zero for missing values + aRet.realloc(1); + sal_Int32* pSeq = aRet.getArray(); + *pSeq++ = css::chart::MissingValueTreatment::USE_ZERO; + } else if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_AREA) ) { aRet.realloc( bStacked ? 1 : 2 ); diff --git a/chart2/source/tools/HistogramDataSequence.cxx b/chart2/source/tools/HistogramDataSequence.cxx new file mode 100644 index 000000000000..d71e45ef74a4 --- /dev/null +++ b/chart2/source/tools/HistogramDataSequence.cxx @@ -0,0 +1,155 @@ +/* -*- 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/. + */ + +#include <HistogramDataSequence.hxx> + +#include <CommonFunctors.hxx> +#include <ModifyListenerHelper.hxx> + +#include <comphelper/sequenceashashmap.hxx> +#include <cppuhelper/supportsservice.hxx> + +#include <cppuhelper/supportsservice.hxx> +#include <algorithm> +#include <strings.hrc> +#include <ResId.hxx> +#include <utility> + +using namespace css; + +namespace +{ +constexpr OUString lcl_aServiceName = u"com.sun.star.comp.chart.HistogramDataSequence"_ustr; + +enum +{ + PROP_PROPOSED_ROLE +}; + +} // anonymous namespace + +namespace chart +{ +HistogramDataSequence::HistogramDataSequence() + : m_xModifyEventForwarder(new ModifyEventForwarder()) +{ + registerProperty(u"Role"_ustr, PROP_PROPOSED_ROLE, + 0, // PropertyAttributes + &m_sRole, cppu::UnoType<decltype(m_sRole)>::get()); +} + +HistogramDataSequence::~HistogramDataSequence() {} + +IMPLEMENT_FORWARD_XINTERFACE2(HistogramDataSequence, HistogramDataSequence_Base, + comphelper::OPropertyContainer2) + +IMPLEMENT_FORWARD_XTYPEPROVIDER2(HistogramDataSequence, HistogramDataSequence_Base, + comphelper::OPropertyContainer2) + +// XPropertySet +uno::Reference<beans::XPropertySetInfo> SAL_CALL HistogramDataSequence::getPropertySetInfo() +{ + return createPropertySetInfo(getInfoHelper()); +} + +// comphelper::OPropertySetHelper +::cppu::IPropertyArrayHelper& HistogramDataSequence::getInfoHelper() { return *getArrayHelper(); } + +// comphelper::OPropertyArrayHelper +::cppu::IPropertyArrayHelper* HistogramDataSequence::createArrayHelper() const +{ + uno::Sequence<beans::Property> aProperties; + // describes all properties which have been registered in the ctor + describeProperties(aProperties); + + return new ::cppu::OPropertyArrayHelper(aProperties); +} + +OUString SAL_CALL HistogramDataSequence::getImplementationName() { return lcl_aServiceName; } + +sal_Bool SAL_CALL HistogramDataSequence::supportsService(const OUString& rServiceName) +{ + return cppu::supportsService(this, rServiceName); +} + +uno::Sequence<OUString> SAL_CALL HistogramDataSequence::getSupportedServiceNames() +{ + return { lcl_aServiceName, u"com.sun.star.chart2.data.DataSequence"_ustr, + u"com.sun.star.chart2.data.NumericalDataSequence"_ustr, + u"com.sun.star.chart2.data.TextualDataSequence"_ustr }; +} + +// XNumericalDataSequence +uno::Sequence<double> SAL_CALL HistogramDataSequence::getNumericalData() +{ + std::unique_lock<std::mutex> aGuard; + + return mxValues; +} + +// XTextualDataSequence +uno::Sequence<OUString> SAL_CALL HistogramDataSequence::getTextualData() +{ + std::unique_lock<std::mutex> aGuard; + return {}; +} + +// XDataSequence +uno::Sequence<uno::Any> SAL_CALL HistogramDataSequence::getData() +{ + std::unique_lock<std::mutex> aGuard; + uno::Sequence<uno::Any> aSequence(mxValues.size()); + auto pSequence = aSequence.getArray(); + + size_t i = 0; + for (double nValue : mxValues) + { + pSequence[i] <<= nValue; + i++; + } + return aSequence; +} + +OUString SAL_CALL HistogramDataSequence::getSourceRangeRepresentation() { return m_sRole; } + +uno::Sequence<OUString> + SAL_CALL HistogramDataSequence::generateLabel(css::chart2::data::LabelOrigin) +{ + return mxLabels; +} + +sal_Int32 SAL_CALL HistogramDataSequence::getNumberFormatKeyByIndex(sal_Int32) +{ + return 0; // TODO - NumberFormat support +} + +// XModifyBroadcaster +void SAL_CALL +HistogramDataSequence::addModifyListener(const uno::Reference<util::XModifyListener>& aListener) +{ + m_xModifyEventForwarder->addModifyListener(aListener); +} + +void SAL_CALL +HistogramDataSequence::removeModifyListener(const uno::Reference<util::XModifyListener>& aListener) +{ + m_xModifyEventForwarder->removeModifyListener(aListener); +} + +// XCloneable + +uno::Reference<util::XCloneable> SAL_CALL HistogramDataSequence::createClone() +{ + rtl::Reference<HistogramDataSequence> pClone(new HistogramDataSequence()); + return pClone; +} + +} // namespace chart2 + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/charttypes/HistogramChart.cxx b/chart2/source/view/charttypes/HistogramChart.cxx new file mode 100644 index 000000000000..e7191732605a --- /dev/null +++ b/chart2/source/view/charttypes/HistogramChart.cxx @@ -0,0 +1,181 @@ +/* -*- 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 "HistogramChart.hxx" + +#include <ChartType.hxx> +#include <../chart2/inc/ChartModel.hxx> +#include <ShapeFactory.hxx> +#include <CommonConverters.hxx> +#include <ObjectIdentifier.hxx> +#include <LabelPositionHelper.hxx> +#include <AxisIndexDefines.hxx> +#include <Clipping.hxx> +#include <DateHelper.hxx> +#include <svx/scene3d.hxx> +#include <comphelper/scopeguard.hxx> + +#include <com/sun/star/chart/DataLabelPlacement.hpp> + +#include <com/sun/star/chart2/DataPointGeometry3D.hpp> +#include <rtl/math.hxx> +#include <comphelper/diagnose_ex.hxx> + +namespace chart +{ +using namespace ::com::sun::star; +using namespace ::rtl::math; +using namespace ::com::sun::star::chart2; + +HistogramChart::HistogramChart(const rtl::Reference<ChartType>& xChartTypeModel, + sal_Int32 nDimensionCount) + : BarChart(xChartTypeModel, nDimensionCount) +{ + // We only support 2 dimensional histogram charts + assert(nDimensionCount == 2 && "HistogramChart only supports 2D charts"); + + // Runtime check for all builds + if (nDimensionCount != 2) + { + // Log a warning or throw an exception if appropriate + SAL_WARN("chart2", "HistogramChart created with invalid dimension count. Forcing 2D."); + } + + PlotterBase::m_pPosHelper = &m_aMainPosHelper; + VSeriesPlotter::m_pMainPosHelper = &m_aMainPosHelper; + + try + { + if (m_xChartTypeModel.is()) + m_xChartTypeModel->getPropertyValue(u"GapWidthSequence"_ustr) >>= m_aGapwidthSequence; + } + catch (const uno::Exception&) + { + TOOLS_WARN_EXCEPTION("chart2", ""); + } +} + +HistogramChart::~HistogramChart() {} + +css::drawing::Direction3D HistogramChart::getPreferredDiagramAspectRatio() const +{ + // Return the preferred aspect ratio for the histogram chart + return css::drawing::Direction3D(-1, -1, -1); +} + +PlottingPositionHelper& HistogramChart::getPlottingPositionHelper(sal_Int32 nAxisIndex) const +{ + PlottingPositionHelper& rPosHelper = VSeriesPlotter::getPlottingPositionHelper(nAxisIndex); + BarPositionHelper* pHistogramPosHelper = dynamic_cast<BarPositionHelper*>(&rPosHelper); + if (pHistogramPosHelper && nAxisIndex >= 0) + { + if (nAxisIndex < m_aGapwidthSequence.getLength()) + pHistogramPosHelper->setOuterDistance(m_aGapwidthSequence[nAxisIndex] / 100.0); + } + return rPosHelper; +} + +awt::Point HistogramChart::getLabelScreenPositionAndAlignment( + LabelAlignment& rAlignment, sal_Int32 nLabelPlacement, double fScaledX, + double fScaledLowerYValue, double fScaledUpperYValue, double fBaseValue, + BarPositionHelper const* pPosHelper) const +{ + double fY = fScaledUpperYValue; + bool bReverse = !pPosHelper->isMathematicalOrientationY(); + bool bNormalOutside = (!bReverse == (fBaseValue < fScaledUpperYValue)); + + switch (nLabelPlacement) + { + case css::chart::DataLabelPlacement::TOP: + fY = bReverse ? fScaledLowerYValue : fScaledUpperYValue; + rAlignment = LABEL_ALIGN_TOP; + break; + case css::chart::DataLabelPlacement::BOTTOM: + fY = bReverse ? fScaledUpperYValue : fScaledLowerYValue; + rAlignment = LABEL_ALIGN_BOTTOM; + break; + case css::chart::DataLabelPlacement::OUTSIDE: + fY = (fBaseValue < fScaledUpperYValue) ? fScaledUpperYValue : fScaledLowerYValue; + rAlignment = bNormalOutside ? LABEL_ALIGN_TOP : LABEL_ALIGN_BOTTOM; + break; + case css::chart::DataLabelPlacement::INSIDE: + fY = (fBaseValue < fScaledUpperYValue) ? fScaledUpperYValue : fScaledLowerYValue; + rAlignment = bNormalOutside ? LABEL_ALIGN_BOTTOM : LABEL_ALIGN_TOP; + break; + case css::chart::DataLabelPlacement::CENTER: + fY -= (fScaledUpperYValue - fScaledLowerYValue) / 2.0; + rAlignment = LABEL_ALIGN_CENTER; + break; + default: + OSL_FAIL("this label alignment is not implemented yet"); + break; + } + + drawing::Position3D aScenePosition3D( + pPosHelper->transformScaledLogicToScene(fScaledX, fY, 0.0, true)); + return LabelPositionHelper(2, m_xLogicTarget).transformSceneToScreenPosition(aScenePosition3D); +} + +void HistogramChart::addSeries(std::unique_ptr<VDataSeries> pSeries, sal_Int32 zSlot, + sal_Int32 xSlot, sal_Int32 ySlot) +{ + if (!pSeries) + return; + + if (m_nDimension == 2) + { + sal_Int32 nAxisIndex = pSeries->getAttachedAxisIndex(); + zSlot = nAxisIndex; + + if (!pSeries->getGroupBarsPerAxis()) + zSlot = 0; + if (zSlot >= static_cast<sal_Int32>(m_aZSlots.size())) + m_aZSlots.resize(zSlot + 1); + } + VSeriesPlotter::addSeries(std::move(pSeries), zSlot, xSlot, ySlot); + adaptGapWidthForHistogram(); +} + +void HistogramChart::adaptGapWidthForHistogram() +{ + VDataSeries* pFirstSeries = getFirstSeries(); + if (!pFirstSeries) + return; + + sal_Int32 nAxisIndex = pFirstSeries->getAttachedAxisIndex(); + sal_Int32 nUseThisIndex = nAxisIndex; + if (nUseThisIndex < 0 || nUseThisIndex >= m_aGapwidthSequence.getLength()) + nUseThisIndex = 0; + + auto aGapwidthSequenceRange = asNonConstRange(m_aGapwidthSequence); + for (sal_Int32 nN = 0; nN < m_aGapwidthSequence.getLength(); nN++) + { + aGapwidthSequenceRange[nN] = 0; // Set gap width to 0 + } +} + +void HistogramChart::createShapes() +{ + if (m_aZSlots.empty()) //No data series Available + return; + + OSL_ENSURE( + m_xLogicTarget.is() && m_xFinalTarget.is(), + "HistogramChart is not properly initialized"); // Ensuring chart is properly initialized + if (!(m_xLogicTarget.is() && m_xFinalTarget.is())) + return; + + adaptGapWidthForHistogram(); + + BarChart::createShapes(); +} + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/chart2/source/view/charttypes/HistogramChart.hxx b/chart2/source/view/charttypes/HistogramChart.hxx new file mode 100644 index 000000000000..8921be6712f1 --- /dev/null +++ b/chart2/source/view/charttypes/HistogramChart.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 "BarChart.hxx" +#include "BarPositionHelper.hxx" +#include <memory> + +namespace chart +{ +class HistogramChart : public BarChart +{ +public: + HistogramChart() = delete; + + HistogramChart(const rtl::Reference<ChartType>& xChartTypeModel, sal_Int32 nDimensionCount); + virtual ~HistogramChart() override; + + virtual void createShapes() override; + virtual void addSeries(std::unique_ptr<VDataSeries> pSeries, sal_Int32 zSlot, sal_Int32 xSlot, + sal_Int32 ySlot) override; + + virtual css::drawing::Direction3D getPreferredDiagramAspectRatio() const override; + +private: + css::awt::Point getLabelScreenPositionAndAlignment(LabelAlignment& rAlignment, + sal_Int32 nLabelPlacement, double fScaledX, + double fScaledLowerYValue, + double fScaledUpperYValue, double fBaseValue, + BarPositionHelper const* pPosHelper) const; + + virtual PlottingPositionHelper& getPlottingPositionHelper(sal_Int32 nAxisIndex) const override; + + void adaptGapWidthForHistogram(); + +private: + BarPositionHelper m_aMainPosHelper; + css::uno::Sequence<sal_Int32> m_aGapwidthSequence; +}; + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/chart2/source/view/charttypes/VSeriesPlotter.cxx b/chart2/source/view/charttypes/VSeriesPlotter.cxx index 84491047696a..0d134173ba66 100644 --- a/chart2/source/view/charttypes/VSeriesPlotter.cxx +++ b/chart2/source/view/charttypes/VSeriesPlotter.cxx @@ -54,6 +54,7 @@ //only for creation: @todo remove if all plotter are uno components and instantiated via servicefactory #include "BarChart.hxx" +#include "HistogramChart.hxx" #include "PieChart.hxx" #include "AreaChart.hxx" #include "CandleStickChart.hxx" @@ -2317,6 +2318,7 @@ const ROrderPair pairList[] = { ROrderPair(CHART2_SERVICE_NAME_CHARTTYPE_AREA, 0), ROrderPair(CHART2_SERVICE_NAME_CHARTTYPE_BAR, 6), // bar & column are same ROrderPair(CHART2_SERVICE_NAME_CHARTTYPE_COLUMN, 6), + ROrderPair(CHART2_SERVICE_NAME_CHARTTYPE_HISTOGRAM, 9), ROrderPair(CHART2_SERVICE_NAME_CHARTTYPE_LINE, 8), ROrderPair(CHART2_SERVICE_NAME_CHARTTYPE_SCATTER, 5), ROrderPair(CHART2_SERVICE_NAME_CHARTTYPE_PIE, 1), @@ -2956,6 +2958,8 @@ VSeriesPlotter* VSeriesPlotter::createSeriesPlotter( pRet = new BarChart(xChartTypeModel,nDimensionCount); else if( aChartType.equalsIgnoreAsciiCase( CHART2_SERVICE_NAME_CHARTTYPE_BAR ) ) pRet = new BarChart(xChartTypeModel,nDimensionCount); + else if( aChartType.equalsIgnoreAsciiCase( CHART2_SERVICE_NAME_CHARTTYPE_HISTOGRAM ) ) + pRet = new HistogramChart(xChartTypeModel, nDimensionCount); else if( aChartType.equalsIgnoreAsciiCase( CHART2_SERVICE_NAME_CHARTTYPE_AREA ) ) pRet = new AreaChart(xChartTypeModel,nDimensionCount,true); else if( aChartType.equalsIgnoreAsciiCase( CHART2_SERVICE_NAME_CHARTTYPE_LINE ) ) diff --git a/icon-themes/colibre/chart2/res/histogram_52x60.png b/icon-themes/colibre/chart2/res/histogram_52x60.png new file mode 100644 index 000000000000..d8c9a4340713 Binary files /dev/null and b/icon-themes/colibre/chart2/res/histogram_52x60.png differ diff --git a/icon-themes/colibre/chart2/res/typehistogram_16.png b/icon-themes/colibre/chart2/res/typehistogram_16.png new file mode 100644 index 000000000000..0bab3c3f7e82 Binary files /dev/null and b/icon-themes/colibre/chart2/res/typehistogram_16.png differ diff --git a/offapi/UnoApi_offapi.mk b/offapi/UnoApi_offapi.mk index 864346d584dc..cf86c82a2ab9 100644 --- a/offapi/UnoApi_offapi.mk +++ b/offapi/UnoApi_offapi.mk @@ -625,6 +625,7 @@ $(eval $(call gb_UnoApi_add_idlfiles_noheader,offapi,com/sun/star/chart,\ Dim3DDiagram \ DonutDiagram \ FilledNetDiagram \ + HistogramDiagram \ LineDiagram \ NetDiagram \ PieDiagram \ diff --git a/offapi/com/sun/star/chart/HistogramDiagram.idl b/offapi/com/sun/star/chart/HistogramDiagram.idl new file mode 100644 index 000000000000..ff31bff379c6 --- /dev/null +++ b/offapi/com/sun/star/chart/HistogramDiagram.idl @@ -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/. + */ + +module com { module sun { module star { module chart { + + +/** This is a service for histogram diagrams. + @since LibreOffice 25.2 +*/ +service HistogramDiagram +{ + service com::sun::star::chart::Diagram; + service com::sun::star::chart::ChartStatistics; + service com::sun::star::chart::ChartAxisXSupplier; + service com::sun::star::chart::ChartTwoAxisYSupplier; + + /** Specifies the width of each bin in the histogram. */ + [property] double BinWidth; + + /** Specifies the range of values covered by the bins. */ + [property] string BinRange; + + /** Specifies the type of frequency representation (count or density). */ + [property] long FrequencyType; +}; + +}; }; }; }; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/inc/drawingml/chart/typegroupconverter.hxx b/oox/inc/drawingml/chart/typegroupconverter.hxx index e017f81e19c7..c77959bfd35b 100644 --- a/oox/inc/drawingml/chart/typegroupconverter.hxx +++ b/oox/inc/drawingml/chart/typegroupconverter.hxx @@ -49,7 +49,8 @@ enum TypeId TYPEID_SCATTER, /// Scatter (XY) chart. TYPEID_BUBBLE, /// Bubble chart. TYPEID_SURFACE, /// Surface chart. - TYPEID_UNKNOWN /// Default for unknown chart types. + TYPEID_HISTO, /// Histogram chart. + TYPEID_UNKNOWN, /// Default for unknown chart types. }; /** Enumerates different categories of similar chart types. */ @@ -60,7 +61,8 @@ enum TypeCategory TYPECATEGORY_RADAR, /// Radar charts (linear or filled). TYPECATEGORY_PIE, /// Pie and donut charts. TYPECATEGORY_SCATTER, /// Scatter and bubble charts. - TYPECATEGORY_SURFACE /// Surface charts. + TYPECATEGORY_SURFACE, /// Surface charts. + TYPECATEGORY_HISTO /// Histogram charts. }; /** Enumerates modes for varying point colors in a series. */ diff --git a/oox/source/drawingml/chart/typegroupconverter.cxx b/oox/source/drawingml/chart/typegroupconverter.cxx index 8c2886671761..6d135be07c53 100644 --- a/oox/source/drawingml/chart/typegroupconverter.cxx +++ b/oox/source/drawingml/chart/typegroupconverter.cxx @@ -67,6 +67,7 @@ const char SERVICE_CHART2_PIE[] = "com.sun.star.chart2.PieChartType"; const char SERVICE_CHART2_SCATTER[] = "com.sun.star.chart2.ScatterChartType"; const char SERVICE_CHART2_BUBBLE[] = "com.sun.star.chart2.BubbleChartType"; const char SERVICE_CHART2_SURFACE[] = "com.sun.star.chart2.ColumnChartType"; // Todo +const char SERVICE_CHART2_HISTO[] = "com.sun.star.chart2.HistogramChartType"; namespace csscd = ::com::sun::star::chart::DataLabelPlacement; @@ -75,6 +76,7 @@ const TypeGroupInfo spTypeInfos[] = // type-id type-category service varied-point-color default label pos polar area2d 1stvis xcateg swap stack picopt { TYPEID_BAR, TYPECATEGORY_BAR, SERVICE_CHART2_COLUMN, VARPOINTMODE_SINGLE, csscd::OUTSIDE, false, true, false, true, false, true, true }, { TYPEID_HORBAR, TYPECATEGORY_BAR, SERVICE_CHART2_COLUMN, VARPOINTMODE_SINGLE, csscd::OUTSIDE, false, true, false, true, true, true, true }, + { TYPEID_HISTO, TYPECATEGORY_HISTO, SERVICE_CHART2_HISTO, VARPOINTMODE_SINGLE, csscd::OUTSIDE, false, true, false, true, true, true, true }, { TYPEID_LINE, TYPECATEGORY_LINE, SERVICE_CHART2_LINE, VARPOINTMODE_SINGLE, csscd::RIGHT, false, false, false, true, false, true, false }, { TYPEID_AREA, TYPECATEGORY_LINE, SERVICE_CHART2_AREA, VARPOINTMODE_NONE, csscd::CENTER, false, true, false, true, false, true, false }, { TYPEID_STOCK, TYPECATEGORY_LINE, SERVICE_CHART2_CANDLE, VARPOINTMODE_NONE, csscd::RIGHT, false, false, false, true, false, true, false }, diff --git a/solenv/bin/native-code.py b/solenv/bin/native-code.py index 743d8bfb5a8e..bd84bd68e305 100755 --- a/solenv/bin/native-code.py +++ b/solenv/bin/native-code.py @@ -52,6 +52,7 @@ core_constructor_list = [ "com_sun_star_comp_chart_CandleStickChartType_get_implementation", "com_sun_star_comp_chart_ChartTypeManager_get_implementation", "com_sun_star_comp_chart_ColumnChartType_get_implementation", + "com_sun_star_comp_chart_HistogramChartType_get_implementation", "com_sun_star_comp_chart_DataSeries_get_implementation", "com_sun_star_comp_chart_DataSource_get_implementation", "com_sun_star_comp_chart_FilledNetChartType_get_implementation", diff --git a/sw/qa/uitest/chart/tdf138556.py b/sw/qa/uitest/chart/tdf138556.py index 3fc7bb19734d..7bddbf7c7227 100644 --- a/sw/qa/uitest/chart/tdf138556.py +++ b/sw/qa/uitest/chart/tdf138556.py @@ -27,7 +27,7 @@ class tdf138556( UITestCase ): #TODO: test other subtypes with self.ui_test.execute_dialog_through_action( xChart, "COMMAND", mkPropertyValues({ "COMMAND" : "DiagramType" })) as xDialog: xChartType = xDialog.getChild( "charttype" ) - xStockType = xChartType.getChild( "8" ) + xStockType = xChartType.getChild( "9" ) xStockType.executeAction( "SELECT", tuple()) #Insert Data Series @@ -41,4 +41,4 @@ class tdf138556( UITestCase ): CoordinateSystems[0].ChartTypes[0].DataSeries[0].DataSequences ) self.assertEqual( nSequences, 3 ) -# vim: set shiftwidth=4 softtabstop=4 expandtab: \ No newline at end of file +# vim: set shiftwidth=4 softtabstop=4 expandtab: