diff options
author | Tomaž Vajngerl <tomaz.vajngerl@collabora.co.uk> | 2017-02-26 22:48:06 +0100 |
---|---|---|
committer | Tomaž Vajngerl <quikee@gmail.com> | 2017-04-04 13:39:29 +0000 |
commit | 9009663deb8f0862f419fd99bf0b761c7f923eff (patch) | |
tree | ea25976de0919f9d2161037d83be0eace4c1070b /chart2 | |
parent | 1931b5b01c6fdaa204d26ec4b9675dad16373cf2 (diff) |
tdf#83257 [API-CHANGE] Pivot chart implementation
This is a squashed commit of the pivot chart implementation.
Some of the changes:
- Add pivot chart specific (pivot table) data provider which
provides the data from a pivot table to the associated chart.
- When inserting a chart and the cursor is in a pivot table,
in that case insert a pivot chart
- Modify the pivot chart when the pivot table changes
- Collect and set the number format for the values
- isDataFromSpreadsheet check for the creation wizard
- In ChartView (and VLegend) check if the data provider is a
pivot chart data provider and get the pivot table field names
to create the buttons on the UI.
- Adds the functionallity to show a filter pop-up (from calc)
when clicking on row / column / page field buttons.
- Remove (X)PopupRequest as we won't need it.
- Add ODF import/export for pivot charts:
+ Added loext:data-pilot-source attribute on chart:chart
which is the internal name of the pivot table with which the
pivot chart is associated with. If the element is present, then
the it means the chart is a pivot chart, else it is a normal
chart
+ Added service to create pivot chart data provider through UNO
+ Add new methods to XPivotChartDataProvider to create value and
label data sequences separately from the data source, which is
needed for pivot chart import
+ When importing defer setting the data provider until a later
time when we know if we are creating a chart od a pivot chart
- Pivot chart ODF round-trip test
- Add table pivot chart supplier API:
This adds the XTablePivotChartSupplier and related interfaces so
we can access, create, delete pivot charts from UNO in a sheet
document. With this we now distinguish between normal charts
and pivot charts. This was mainly needed because we can't extend
the "published" interfaces of TableChartSupplier.
- Added an extensive test, which uses the API to create a new
pivot chart when there was none, and checks that the pivot chart
updates when the pivot table updates.
Change-Id: Ia9ed96fd6b1d342e61c2f7f9fa33a5e03dda21af
Reviewed-on: https://gerrit.libreoffice.org/36023
Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
Tested-by: Tomaž Vajngerl <quikee@gmail.com>
Diffstat (limited to 'chart2')
18 files changed, 737 insertions, 109 deletions
diff --git a/chart2/CppunitTest_chart2_pivot_chart_test.mk b/chart2/CppunitTest_chart2_pivot_chart_test.mk new file mode 100644 index 000000000000..418db1af9cc9 --- /dev/null +++ b/chart2/CppunitTest_chart2_pivot_chart_test.mk @@ -0,0 +1,131 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +#************************************************************************* +# +# 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/. +# +#************************************************************************* + +$(eval $(call gb_CppunitTest_CppunitTest,chart2_pivot_chart_test)) + +$(eval $(call gb_CppunitTest_use_externals,chart2_pivot_chart_test, \ + boost_headers \ + libxml2 \ +)) + +$(eval $(call gb_CppunitTest_add_exception_objects,chart2_pivot_chart_test, \ + chart2/qa/extras/PivotChartTest \ +)) + +$(eval $(call gb_CppunitTest_use_libraries,chart2_pivot_chart_test, \ + basegfx \ + comphelper \ + cppu \ + cppuhelper \ + drawinglayer \ + editeng \ + for \ + forui \ + i18nlangtag \ + msfilter \ + vcl \ + oox \ + sal \ + salhelper \ + sax \ + sb \ + sc \ + sw \ + sd \ + sfx \ + sot \ + svl \ + svt \ + svx \ + svxcore \ + test \ + tl \ + tk \ + ucbhelper \ + unotest \ + utl \ + vbahelper \ + xo \ + sw \ + $(gb_UWINAPI) \ +)) + +$(eval $(call gb_CppunitTest_set_include,chart2_pivot_chart_test,\ + -I$(SRCDIR)/chart2/inc \ + $$(INCLUDE) \ +)) + +$(eval $(call gb_CppunitTest_use_sdk_api,chart2_pivot_chart_test)) +$(eval $(call gb_CppunitTest_use_ure,chart2_pivot_chart_test)) +$(eval $(call gb_CppunitTest_use_vcl,chart2_pivot_chart_test)) + +$(eval $(call gb_CppunitTest_use_components,chart2_pivot_chart_test,\ + basic/util/sb \ + animations/source/animcore/animcore \ + chart2/source/controller/chartcontroller \ + chart2/source/chartcore \ + comphelper/util/comphelp \ + configmgr/source/configmgr \ + dtrans/util/mcnttype \ + dbaccess/util/dba \ + embeddedobj/util/embobj \ + eventattacher/source/evtatt \ + filter/source/config/cache/filterconfig1 \ + filter/source/odfflatxml/odfflatxml \ + filter/source/storagefilterdetect/storagefd \ + filter/source/xmlfilteradaptor/xmlfa \ + filter/source/xmlfilterdetect/xmlfd \ + forms/util/frm \ + framework/util/fwk \ + i18npool/util/i18npool \ + linguistic/source/lng \ + oox/util/oox \ + package/source/xstor/xstor \ + package/util/package2 \ + sax/source/expatwrap/expwrap \ + sc/util/sc \ + sc/util/scd \ + sc/util/scfilt \ + sw/util/sw \ + sw/util/swd \ + sw/util/msword \ + sd/util/sd \ + sd/util/sdfilt \ + sd/util/sdd \ + $(call gb_Helper_optional,SCRIPTING, \ + sc/util/vbaobj) \ + scaddins/source/analysis/analysis \ + scaddins/source/datefunc/date \ + scripting/source/basprov/basprov \ + scripting/util/scriptframe \ + sfx2/util/sfx \ + sot/util/sot \ + svl/source/fsstor/fsstorage \ + svl/util/svl \ + svtools/util/svt \ + svx/util/svx \ + svx/util/svxcore \ + toolkit/util/tk \ + ucb/source/core/ucb1 \ + ucb/source/ucp/file/ucpfile1 \ + ucb/source/ucp/tdoc/ucptdoc1 \ + unotools/util/utl \ + unoxml/source/rdf/unordf \ + unoxml/source/service/unoxml \ + uui/util/uui \ + writerfilter/util/writerfilter \ + xmloff/util/xo \ + xmlscript/util/xmlscript \ +)) + +$(eval $(call gb_CppunitTest_use_configuration,chart2_pivot_chart_test)) + +# vim: set noet sw=4 ts=4: diff --git a/chart2/Module_chart2.mk b/chart2/Module_chart2.mk index f39140d61002..3273055d5373 100644 --- a/chart2/Module_chart2.mk +++ b/chart2/Module_chart2.mk @@ -34,6 +34,7 @@ $(eval $(call gb_Module_add_slowcheck_targets,chart2,\ CppunitTest_chart2_import \ CppunitTest_chart2_trendcalculators \ CppunitTest_chart2_dump \ + CppunitTest_chart2_pivot_chart_test \ )) ifeq ($(ENABLE_CHART_TESTS),TRUE) diff --git a/chart2/inc/ChartModel.hxx b/chart2/inc/ChartModel.hxx index 29b764b6c546..63bd12667612 100644 --- a/chart2/inc/ChartModel.hxx +++ b/chart2/inc/ChartModel.hxx @@ -45,6 +45,7 @@ #include <com/sun/star/chart2/XChartTypeTemplate.hpp> #include <com/sun/star/container/XNameContainer.hpp> #include <com/sun/star/qa/XDumper.hpp> +#include <com/sun/star/awt/XRequestCallback.hpp> // public API #include <com/sun/star/chart2/data/XDataProvider.hpp> @@ -143,7 +144,7 @@ private: css::awt::Size m_aVisualAreaSize; css::uno::Reference< css::frame::XModel > m_xParent; css::uno::Reference< css::chart2::data::XRangeHighlighter > m_xRangeHighlighter; - css::uno::Reference<css::chart2::data::XPopupRequest> m_xPopupRequest; + css::uno::Reference<css::awt::XRequestCallback> m_xPopupRequest; std::vector< GraphicObject > m_aGraphicObjectVector; css::uno::Reference< css::chart2::data::XDataProvider > m_xDataProvider; @@ -383,7 +384,7 @@ public: virtual void SAL_CALL attachNumberFormatsSupplier( const css::uno::Reference< css::util::XNumberFormatsSupplier >& xSupplier ) override; virtual css::uno::Reference< css::chart2::data::XRangeHighlighter > SAL_CALL getRangeHighlighter() override; - virtual css::uno::Reference< css::chart2::data::XPopupRequest > SAL_CALL getPopupRequest() override; + virtual css::uno::Reference<css::awt::XRequestCallback> SAL_CALL getPopupRequest() override; // ____ XTitled ____ virtual css::uno::Reference< css::chart2::XTitle > SAL_CALL getTitleObject() override; @@ -469,6 +470,10 @@ public: void setTimeBasedRange(sal_Int32 nStart, sal_Int32 nEnd); + bool isDataFromSpreadsheet(); + + bool isDataFromPivotTable(); + #if HAVE_FEATURE_OPENGL OpenGLWindow* getOpenGLWindow() { return mpOpenGLWindow;} #endif diff --git a/chart2/qa/extras/PivotChartTest.cxx b/chart2/qa/extras/PivotChartTest.cxx new file mode 100644 index 000000000000..8d1c11d0ce5d --- /dev/null +++ b/chart2/qa/extras/PivotChartTest.cxx @@ -0,0 +1,298 @@ +/* -*- 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 "charttest.hxx" + +#include <com/sun/star/sheet/DataPilotFieldOrientation.hpp> +#include <com/sun/star/sheet/XDataPilotTable.hpp> +#include <com/sun/star/sheet/XDataPilotDescriptor.hpp> +#include <com/sun/star/sheet/XDataPilotTables.hpp> +#include <com/sun/star/sheet/XDataPilotTablesSupplier.hpp> +#include <com/sun/star/sheet/XSpreadsheet.hpp> +#include <com/sun/star/sheet/XSpreadsheetDocument.hpp> +#include <com/sun/star/sheet/XSpreadsheets.hpp> +#include <com/sun/star/table/XTablePivotChart.hpp> +#include <com/sun/star/table/XTablePivotCharts.hpp> +#include <com/sun/star/table/XTablePivotChartsSupplier.hpp> + +#include <rtl/strbuf.hxx> + +#include <algorithm> + +class PivotChartTest : public ChartTest +{ +public: + PivotChartTest() : ChartTest() + {} + + void testRoundtrip(); + void testChangePivotTable(); + + CPPUNIT_TEST_SUITE(PivotChartTest); + CPPUNIT_TEST(testRoundtrip); + CPPUNIT_TEST(testChangePivotTable); + CPPUNIT_TEST_SUITE_END(); +}; + +namespace +{ + +void lclModifyOrientation(uno::Reference<sheet::XDataPilotDescriptor> const & xDescriptor, + OUString const & sFieldName, + sheet::DataPilotFieldOrientation eOrientation) +{ + uno::Reference<container::XIndexAccess> xPilotIndexAccess(xDescriptor->getDataPilotFields(), UNO_QUERY_THROW); + sal_Int32 nCount = xPilotIndexAccess->getCount(); + for (sal_Int32 i = 0; i < nCount; ++i) + { + uno::Reference<container::XNamed> xNamed(xPilotIndexAccess->getByIndex(i), UNO_QUERY_THROW); + OUString aName = xNamed->getName(); + uno::Reference<beans::XPropertySet> xPropSet(xNamed, UNO_QUERY_THROW); + if (aName == sFieldName) + xPropSet->setPropertyValue("Orientation", uno::makeAny(eOrientation)); + } +} + +bool lclCheckSequence(std::vector<double> const & reference, + uno::Sequence<uno::Any> const & values, + double delta) +{ + if (reference.size() != size_t(values.getLength())) + { + printf ("Sequence size differs - reference is %ld but actual is %ld\n", + reference.size(), size_t(values.getLength())); + return false; + } + + for (size_t i = 0; i < reference.size(); ++i) + { + double value = values[i].get<double>(); + + if (std::fabs(reference[i] - value) > delta) + { + printf ("Value %f is not the same as reference %f (delta %f)\n", value, reference[i], delta); + return false; + } + } + return true; +} + +OUString lclGetLabel(Reference<chart2::XChartDocument> const & xChartDoc, sal_Int32 nSeriesIndex) +{ + Reference<chart2::data::XDataSequence> xLabelDataSequence = getLabelDataSequenceFromDoc(xChartDoc, nSeriesIndex); + return xLabelDataSequence->getData()[0].get<OUString>(); +} + +uno::Reference<sheet::XDataPilotTable> lclGetPivotTableByName(sal_Int32 nIndex, OUString const & sPivotTableName, + uno::Reference<lang::XComponent> const & xComponent) +{ + uno::Reference<sheet::XSpreadsheetDocument> xDoc(xComponent, UNO_QUERY_THROW); + uno::Reference<container::XIndexAccess> xSheetIndexAccess(xDoc->getSheets(), UNO_QUERY_THROW); + uno::Any aAny = xSheetIndexAccess->getByIndex(nIndex); + uno::Reference<sheet::XSpreadsheet> xSheet; + CPPUNIT_ASSERT(aAny >>= xSheet); + uno::Reference<sheet::XDataPilotTablesSupplier> xDataPilotTablesSupplier(xSheet, uno::UNO_QUERY_THROW); + uno::Reference<sheet::XDataPilotTables> xDataPilotTables = xDataPilotTablesSupplier->getDataPilotTables(); + return uno::Reference<sheet::XDataPilotTable>(xDataPilotTables->getByName(sPivotTableName), UNO_QUERY_THROW); +} + +} // end anonymous namespace + +void PivotChartTest::testRoundtrip() +{ + uno::Sequence<uno::Any> xSequence; + Reference<chart2::XChartDocument> xChartDoc; + + std::vector<double> aReference1 { 10162.033139, 16614.523063, 27944.146101 }; + OUString aExpectedLabel1("Exp."); + + std::vector<double> aReference2 { 101879.458079, 178636.929704, 314626.484864 }; + OUString aExpectedLabel2("Rev."); + + load("/chart2/qa/extras/data/ods/", "PivotChartRoundTrip.ods"); + + xChartDoc = getPivotChartDocFromSheet(1, mxComponent); + CPPUNIT_ASSERT(xChartDoc.is()); + + CPPUNIT_ASSERT_EQUAL(sal_Int32(2), getNumberOfDataSeries(xChartDoc)); + + // Check the data series + { + xSequence = getDataSequenceFromDocByRole(xChartDoc, "values-y", 0)->getData(); + CPPUNIT_ASSERT(lclCheckSequence(aReference1, xSequence, 1E-4)); + CPPUNIT_ASSERT_EQUAL(aExpectedLabel1, lclGetLabel(xChartDoc, 0)); + } + { + xSequence = getDataSequenceFromDocByRole(xChartDoc, "values-y", 1)->getData(); + CPPUNIT_ASSERT(lclCheckSequence(aReference2, xSequence, 1E-4)); + CPPUNIT_ASSERT_EQUAL(aExpectedLabel2, lclGetLabel(xChartDoc, 1)); + } + + // Modify the pivot table + { + uno::Reference<sheet::XDataPilotTable> xDataPilotTable = lclGetPivotTableByName(1, "DataPilot1", mxComponent); + uno::Reference<sheet::XDataPilotDescriptor> xDataPilotDescriptor(xDataPilotTable, UNO_QUERY_THROW); + + lclModifyOrientation(xDataPilotDescriptor, "Exp.", sheet::DataPilotFieldOrientation_HIDDEN); + } + + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), getNumberOfDataSeries(xChartDoc)); + + // Check again the data series + { + xSequence = getDataSequenceFromDocByRole(xChartDoc, "values-y", 0)->getData(); + CPPUNIT_ASSERT(lclCheckSequence(aReference2, xSequence, 1E-4)); + CPPUNIT_ASSERT_EQUAL(OUString(""), lclGetLabel(xChartDoc, 0)); + } + + reload("calc8"); + + xChartDoc = getPivotChartDocFromSheet(1, mxComponent); + CPPUNIT_ASSERT(xChartDoc.is()); + + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), getNumberOfDataSeries(xChartDoc)); + + // Check again the data series + { + xSequence = getDataSequenceFromDocByRole(xChartDoc, "values-y", 0)->getData(); + CPPUNIT_ASSERT(lclCheckSequence(aReference2, xSequence, 1E-4)); + CPPUNIT_ASSERT_EQUAL(OUString(""), lclGetLabel(xChartDoc, 0)); + } +} + +void PivotChartTest::testChangePivotTable() +{ + uno::Sequence<uno::Any> xSequence; + Reference<chart2::XChartDocument> xChartDoc; + + load("/chart2/qa/extras/data/ods/", "PivotTableExample.ods"); + + // Check that we don't have any pivot chart in the document + uno::Reference<table::XTablePivotCharts> xTablePivotCharts = getTablePivotChartsFromSheet(1, mxComponent); + uno::Reference<container::XIndexAccess> xIndexAccess(xTablePivotCharts, UNO_QUERY_THROW); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xIndexAccess->getCount()); + + // Create a new pivot chart + xTablePivotCharts->addNewByName("Chart", awt::Rectangle{0, 0, 9000, 9000}, "DataPilot1"); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xIndexAccess->getCount()); + + // Get the pivot chart document so we ca access its data + xChartDoc.set(getPivotChartDocFromSheet(xTablePivotCharts, 0)); + + CPPUNIT_ASSERT(xChartDoc.is()); + + // Check first data series + { + std::vector<double> aReference { 10162.033139, 16614.523063, 27944.146101 }; + OUString aExpectedLabel("Exp."); + + xSequence = getDataSequenceFromDocByRole(xChartDoc, "values-y", 0)->getData(); + CPPUNIT_ASSERT(lclCheckSequence(aReference, xSequence, 1E-4)); + + CPPUNIT_ASSERT_EQUAL(aExpectedLabel, lclGetLabel(xChartDoc, 0)); + } + + // Check second data series + { + std::vector<double> aReference { 101879.458079, 178636.929704, 314626.484864 }; + OUString aExpectedLabel("Rev."); + + xSequence = getDataSequenceFromDocByRole(xChartDoc, "values-y", 1)->getData(); + CPPUNIT_ASSERT(lclCheckSequence(aReference, xSequence, 1E-4)); + + CPPUNIT_ASSERT_EQUAL(aExpectedLabel, lclGetLabel(xChartDoc, 1)); + } + + // Modify the pivot table + { + uno::Reference<sheet::XDataPilotTable> xDataPilotTable = lclGetPivotTableByName(1, "DataPilot1", mxComponent); + uno::Reference<sheet::XDataPilotDescriptor> xDataPilotDescriptor(xDataPilotTable, UNO_QUERY_THROW); + + lclModifyOrientation(xDataPilotDescriptor, "Service Month", sheet::DataPilotFieldOrientation_ROW); + lclModifyOrientation(xDataPilotDescriptor, "Group Segment", sheet::DataPilotFieldOrientation_COLUMN); + lclModifyOrientation(xDataPilotDescriptor, "Rev.", sheet::DataPilotFieldOrientation_HIDDEN); + } + + // Check the pivot chart again as we expect it has been updated when we updated the pivot table + + CPPUNIT_ASSERT(xChartDoc.is()); + + // Check the first data series + { + std::vector<double> aReference { 2855.559, 1780.326, 2208.713, 2130.064, 1187.371 }; + OUString aExpectedLabel("Big"); + + xSequence = getDataSequenceFromDocByRole(xChartDoc, "values-y", 0)->getData(); + CPPUNIT_ASSERT(lclCheckSequence(aReference, xSequence, 1E-3)); + + CPPUNIT_ASSERT_EQUAL(aExpectedLabel, lclGetLabel(xChartDoc, 0)); + } + + // Check the second data series + { + std::vector<double> aReference { 4098.908, 2527.286, 4299.716, 2362.225, 3326.389 }; + OUString aExpectedLabel("Medium"); + + xSequence = getDataSequenceFromDocByRole(xChartDoc, "values-y", 1)->getData(); + CPPUNIT_ASSERT(lclCheckSequence(aReference, xSequence, 1E-3)); + + CPPUNIT_ASSERT_EQUAL(aExpectedLabel, lclGetLabel(xChartDoc, 1)); + } + + // Check the third data series + { + std::vector<double> aReference { 4926.303, 5684.060, 4201.398, 7290.795, 5841.591 }; + OUString aExpectedLabel("Small"); + + xSequence = getDataSequenceFromDocByRole(xChartDoc, "values-y", 2)->getData(); + CPPUNIT_ASSERT(lclCheckSequence(aReference, xSequence, 1E-3)); + + CPPUNIT_ASSERT_EQUAL(aExpectedLabel, lclGetLabel(xChartDoc, 2)); + } + + // Modify the pivot table + { + uno::Reference<sheet::XDataPilotTable> xDataPilotTable = lclGetPivotTableByName(1, "DataPilot1", mxComponent); + uno::Reference<sheet::XDataPilotDescriptor> xDataPilotDescriptor(xDataPilotTable, UNO_QUERY_THROW); + + lclModifyOrientation(xDataPilotDescriptor, "Service Month", sheet::DataPilotFieldOrientation_HIDDEN); + } + + // Check the pivot chart again as we expect it has been updated when we updated the pivot table + + CPPUNIT_ASSERT(xChartDoc.is()); + + // Check the first data series + { + std::vector<double> aReference { 10162.033139 }; + xSequence = getDataSequenceFromDocByRole(xChartDoc, "values-y", 0)->getData(); + CPPUNIT_ASSERT(lclCheckSequence(aReference, xSequence, 1E-3)); + CPPUNIT_ASSERT_EQUAL(OUString("Big"), lclGetLabel(xChartDoc, 0)); + } + // Check the second data series + { + std::vector<double> aReference { 16614.523063 }; + xSequence = getDataSequenceFromDocByRole(xChartDoc, "values-y", 1)->getData(); + CPPUNIT_ASSERT(lclCheckSequence(aReference, xSequence, 1E-3)); + CPPUNIT_ASSERT_EQUAL(OUString("Medium"), lclGetLabel(xChartDoc, 1)); + } + // Check the third data series + { + std::vector<double> aReference { 27944.146101 }; + xSequence = getDataSequenceFromDocByRole(xChartDoc, "values-y", 2)->getData(); + CPPUNIT_ASSERT(lclCheckSequence(aReference, xSequence, 1E-3)); + CPPUNIT_ASSERT_EQUAL(OUString("Small"), lclGetLabel(xChartDoc, 2)); + } +} + +CPPUNIT_TEST_SUITE_REGISTRATION(PivotChartTest); + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/qa/extras/charttest.hxx b/chart2/qa/extras/charttest.hxx index 1d2f4afe9150..b75dac6d25b5 100644 --- a/chart2/qa/extras/charttest.hxx +++ b/chart2/qa/extras/charttest.hxx @@ -24,6 +24,9 @@ #include <com/sun/star/table/XTableChartsSupplier.hpp> #include <com/sun/star/table/XTableCharts.hpp> #include <com/sun/star/table/XTableChart.hpp> +#include <com/sun/star/table/XTablePivotChartsSupplier.hpp> +#include <com/sun/star/table/XTablePivotCharts.hpp> +#include <com/sun/star/table/XTablePivotChart.hpp> #include <com/sun/star/document/XEmbeddedObjectSupplier.hpp> #include <com/sun/star/beans/XPropertySet.hpp> #include <com/sun/star/frame/XStorable.hpp> @@ -213,6 +216,64 @@ Reference< chart2::XChartDocument > getChartDocFromSheet( sal_Int32 nSheet, uno: return xChartDoc; } +uno::Reference<table::XTablePivotCharts> getTablePivotChartsFromSheet(sal_Int32 nSheet, uno::Reference<lang::XComponent> const & xComponent) +{ + uno::Reference<sheet::XSpreadsheetDocument> xDoc(xComponent, UNO_QUERY_THROW); + CPPUNIT_ASSERT(xDoc.is()); + + uno::Reference<container::XIndexAccess> xIA(xDoc->getSheets(), UNO_QUERY_THROW); + CPPUNIT_ASSERT(xIA.is()); + + uno::Reference<table::XTablePivotChartsSupplier> xChartSupplier(xIA->getByIndex(nSheet), UNO_QUERY_THROW); + CPPUNIT_ASSERT(xChartSupplier.is()); + + uno::Reference<table::XTablePivotCharts> xTablePivotCharts = xChartSupplier->getPivotCharts(); + CPPUNIT_ASSERT(xTablePivotCharts.is()); + + return xTablePivotCharts; +} + +Reference<lang::XComponent> getPivotChartCompFromSheet(sal_Int32 nSheet, uno::Reference<lang::XComponent> const & xComponent) +{ + uno::Reference<table::XTablePivotCharts> xTablePivotCharts = getTablePivotChartsFromSheet(nSheet, xComponent); + + uno::Reference<container::XIndexAccess> xIACharts(xTablePivotCharts, UNO_QUERY_THROW); + uno::Reference<table::XTablePivotChart> xTablePivotChart(xIACharts->getByIndex(0), UNO_QUERY_THROW); + CPPUNIT_ASSERT(xTablePivotChart.is()); + + uno::Reference<document::XEmbeddedObjectSupplier> xEmbObjectSupplier(xTablePivotChart, UNO_QUERY_THROW); + CPPUNIT_ASSERT(xEmbObjectSupplier.is()); + + uno::Reference<lang::XComponent> xChartComp(xEmbObjectSupplier->getEmbeddedObject(), UNO_QUERY_THROW); + CPPUNIT_ASSERT(xChartComp.is()); + + return xChartComp; +} + +Reference<chart2::XChartDocument> getPivotChartDocFromSheet(sal_Int32 nSheet, uno::Reference<lang::XComponent> const & xComponent) +{ + uno::Reference<chart2::XChartDocument> xChartDoc(getPivotChartCompFromSheet(nSheet, xComponent), UNO_QUERY_THROW); + CPPUNIT_ASSERT(xChartDoc.is()); + return xChartDoc; +} + +Reference<chart2::XChartDocument> getPivotChartDocFromSheet(uno::Reference<table::XTablePivotCharts> const & xTablePivotCharts, sal_Int32 nIndex) +{ + uno::Reference<container::XIndexAccess> xIACharts(xTablePivotCharts, UNO_QUERY_THROW); + uno::Reference<table::XTablePivotChart> xTablePivotChart(xIACharts->getByIndex(nIndex), UNO_QUERY_THROW); + CPPUNIT_ASSERT(xTablePivotChart.is()); + + uno::Reference<document::XEmbeddedObjectSupplier> xEmbObjectSupplier(xTablePivotChart, UNO_QUERY_THROW); + CPPUNIT_ASSERT(xEmbObjectSupplier.is()); + + uno::Reference<lang::XComponent> xChartComp(xEmbObjectSupplier->getEmbeddedObject(), UNO_QUERY_THROW); + CPPUNIT_ASSERT(xChartComp.is()); + + uno::Reference<chart2::XChartDocument> xChartDoc(xChartComp, UNO_QUERY_THROW); + CPPUNIT_ASSERT(xChartDoc.is()); + return xChartDoc; +} + Reference< chart2::XChartType > getChartTypeFromDoc( Reference< chart2::XChartDocument > const & xChartDoc, sal_Int32 nChartType, sal_Int32 nCooSys = 0 ) { @@ -257,8 +318,20 @@ Reference<chart2::XAxis> getAxisFromDoc( return xAxis; } -Reference< chart2::XDataSeries > getDataSeriesFromDoc( uno::Reference< chart2::XChartDocument > const & xChartDoc, - sal_Int32 nDataSeries, sal_Int32 nChartType = 0, sal_Int32 nCooSys = 0 ) +sal_Int32 getNumberOfDataSeries(uno::Reference<chart2::XChartDocument> const & xChartDoc, + sal_Int32 nChartType = 0, sal_Int32 nCooSys = 0) +{ + Reference<chart2::XChartType> xChartType = getChartTypeFromDoc(xChartDoc, nChartType, nCooSys); + Reference<chart2::XDataSeriesContainer> xDataSeriesContainer(xChartType, UNO_QUERY_THROW); + CPPUNIT_ASSERT(xDataSeriesContainer.is()); + + uno::Sequence<uno::Reference<chart2::XDataSeries>> xSeriesSequence(xDataSeriesContainer->getDataSeries()); + return xSeriesSequence.getLength(); +} + +Reference< chart2::XDataSeries > getDataSeriesFromDoc(uno::Reference<chart2::XChartDocument> const & xChartDoc, + sal_Int32 nDataSeries, sal_Int32 nChartType = 0, + sal_Int32 nCooSys = 0) { Reference< chart2::XChartType > xChartType = getChartTypeFromDoc( xChartDoc, nChartType, nCooSys ); Reference< chart2::XDataSeriesContainer > xDataSeriesContainer( xChartType, UNO_QUERY_THROW ); diff --git a/chart2/qa/extras/data/ods/PivotChartRoundTrip.ods b/chart2/qa/extras/data/ods/PivotChartRoundTrip.ods Binary files differnew file mode 100644 index 000000000000..c34521e0bc52 --- /dev/null +++ b/chart2/qa/extras/data/ods/PivotChartRoundTrip.ods diff --git a/chart2/qa/extras/data/ods/PivotTableExample.ods b/chart2/qa/extras/data/ods/PivotTableExample.ods Binary files differnew file mode 100644 index 000000000000..bc8df8170208 --- /dev/null +++ b/chart2/qa/extras/data/ods/PivotTableExample.ods diff --git a/chart2/source/controller/dialogs/DialogModel.hxx b/chart2/source/controller/dialogs/DialogModel.hxx index 55251b1ad775..722ce266bc98 100644 --- a/chart2/source/controller/dialogs/DialogModel.hxx +++ b/chart2/source/controller/dialogs/DialogModel.hxx @@ -146,6 +146,8 @@ public: // relative ordering, to get e.g. x-values and y-values in the right order static sal_Int32 GetRoleIndexForSorting( const OUString & rInternalRoleString ); + ChartModel& getModel() const; + private: css::uno::Reference< css::chart2::XChartDocument > m_xChartDocument; @@ -168,7 +170,6 @@ private: sal_Int32 countSeries() const; - ChartModel& getModel() const; mutable DialogModelTimeBasedInfo maTimeBasedInfo; }; diff --git a/chart2/source/controller/dialogs/dlg_CreationWizard.cxx b/chart2/source/controller/dialogs/dlg_CreationWizard.cxx index 501272f5c486..b4beb73575a4 100644 --- a/chart2/source/controller/dialogs/dlg_CreationWizard.cxx +++ b/chart2/source/controller/dialogs/dlg_CreationWizard.cxx @@ -33,10 +33,10 @@ #define CHART_WIZARD_PAGEWIDTH 250 #define CHART_WIZARD_PAGEHEIGHT 170 +using namespace css; + namespace chart { -using namespace ::com::sun::star; - #define PATH_FULL 1 #define STATE_FIRST 0 #define STATE_CHARTTYPE STATE_FIRST @@ -45,41 +45,42 @@ using namespace ::com::sun::star; #define STATE_OBJECTS 3 #define STATE_LAST STATE_OBJECTS -CreationWizard::CreationWizard( vcl::Window* pParent, const uno::Reference< frame::XModel >& xChartModel - , const uno::Reference< uno::XComponentContext >& xContext ) - : svt::RoadmapWizard( pParent ) +CreationWizard::CreationWizard(vcl::Window* pParent, const uno::Reference<frame::XModel>& xChartModel, + const uno::Reference<uno::XComponentContext>& xContext) + : svt::RoadmapWizard(pParent) , m_xChartModel(xChartModel,uno::UNO_QUERY) - , m_xCC( xContext ) + , m_xComponentContext(xContext) , m_pTemplateProvider(nullptr) , m_nLastState(STATE_LAST) - , m_aTimerTriggeredControllerLock( xChartModel ) - , m_bCanTravel( true ) + , m_aTimerTriggeredControllerLock(xChartModel) + , m_bCanTravel(true) { - m_pDialogModel.reset( new DialogModel( m_xChartModel, m_xCC )); - defaultButton( WizardButtonFlags::FINISH ); + m_pDialogModel.reset(new DialogModel(m_xChartModel, m_xComponentContext)); + defaultButton(WizardButtonFlags::FINISH); this->setTitleBase(SCH_RESSTR(STR_DLG_CHART_WIZARD)); - declarePath( PATH_FULL - , {STATE_CHARTTYPE - , STATE_SIMPLE_RANGE - , STATE_DATA_SERIES - , STATE_OBJECTS} - ); - this->SetRoadmapHelpId( HID_SCH_WIZARD_ROADMAP ); - this->SetRoadmapInteractive( true ); - Size aAdditionalRoadmapSize( LogicToPixel( Size( 85, 0 ), MapUnit::MapAppFont ) ); + WizardPath aPath = { + STATE_CHARTTYPE, + STATE_SIMPLE_RANGE, + STATE_DATA_SERIES, + STATE_OBJECTS + }; + + declarePath(PATH_FULL, aPath); + + this->SetRoadmapHelpId(HID_SCH_WIZARD_ROADMAP); + this->SetRoadmapInteractive(true); + + Size aAdditionalRoadmapSize(LogicToPixel(Size(85, 0), MapUnit::MapAppFont)); Size aSize(LogicToPixel(Size(CHART_WIZARD_PAGEWIDTH, CHART_WIZARD_PAGEHEIGHT), MapUnit::MapAppFont)); aSize.Width() += aAdditionalRoadmapSize.Width(); - this->SetSizePixel( aSize ); - - uno::Reference< chart2::XChartDocument > xChartDoc( m_xChartModel, uno::UNO_QUERY ); - bool bHasOwnData = (xChartDoc.is() && xChartDoc->hasInternalDataProvider()); + this->SetSizePixel(aSize); - if( bHasOwnData ) + if (!m_pDialogModel->getModel().isDataFromSpreadsheet()) { - this->enableState( STATE_SIMPLE_RANGE, false ); - this->enableState( STATE_DATA_SERIES, false ); + enableState(STATE_SIMPLE_RANGE, false); + enableState(STATE_DATA_SERIES, false); } // Call ActivatePage, to create and activate the first page @@ -117,15 +118,17 @@ VclPtr<TabPage> CreationWizard::createPage(WizardState nState) break; case STATE_OBJECTS: { - pRet = VclPtr<TitlesAndObjectsTabPage>::Create(this,m_xChartModel,m_xCC); + pRet = VclPtr<TitlesAndObjectsTabPage>::Create(this,m_xChartModel, m_xComponentContext); m_aTimerTriggeredControllerLock.startTimer(); } break; default: break; } - if(pRet) - pRet->SetText(OUString());//remove title of pages to not get them in the wizard title + + if (pRet) + pRet->SetText(OUString()); //remove title of pages to not get them in the wizard title + return pRet; } diff --git a/chart2/source/controller/drawinglayer/DrawViewWrapper.cxx b/chart2/source/controller/drawinglayer/DrawViewWrapper.cxx index 47932bb49d82..c1005f5e0ef3 100644 --- a/chart2/source/controller/drawinglayer/DrawViewWrapper.cxx +++ b/chart2/source/controller/drawinglayer/DrawViewWrapper.cxx @@ -182,8 +182,13 @@ SdrObject* DrawViewWrapper::getHitObject( const Point& rPnt ) const if( pRet ) { - //ignore some special shapes + // ignore some special shapes OUString aShapeName = pRet->GetName(); + + // return right away if it is a field button + if (aShapeName.startsWith("FieldButton")) + return pRet; + if( aShapeName.match("PlotAreaIncludingAxes") || aShapeName.match("PlotAreaExcludingAxes") ) { pRet->SetMarkProtect( true ); diff --git a/chart2/source/controller/inc/ChartController.hxx b/chart2/source/controller/inc/ChartController.hxx index ae579cf14b3d..d69a7a268fd2 100644 --- a/chart2/source/controller/inc/ChartController.hxx +++ b/chart2/source/controller/inc/ChartController.hxx @@ -487,6 +487,8 @@ private: void executeDispatch_ToggleGridHorizontal(); void executeDispatch_ToggleGridVertical(); + void sendPopupRequest(OUString const & rCID, tools::Rectangle aRectangle); + void impl_ShapeControllerDispatch( const css::util::URL& rURL, const css::uno::Sequence< css::beans::PropertyValue >& rArgs ); diff --git a/chart2/source/controller/inc/dlg_CreationWizard.hxx b/chart2/source/controller/inc/dlg_CreationWizard.hxx index fed019004716..a1fed3c8ae55 100644 --- a/chart2/source/controller/inc/dlg_CreationWizard.hxx +++ b/chart2/source/controller/inc/dlg_CreationWizard.hxx @@ -24,57 +24,56 @@ #include "TabPageNotifiable.hxx" #include <com/sun/star/chart2/XChartDocument.hpp> -#include <svtools/roadmapwizard.hxx> #include <com/sun/star/uno/XComponentContext.hpp> +#include <svtools/roadmapwizard.hxx> + #include <memory> namespace chart { -class RangeChooserTabPage; -class DataSourceTabPage; class DialogModel; class ChartTypeTemplateProvider; class CreationWizard : public svt::RoadmapWizard, public TabPageNotifiable { public: - CreationWizard( vcl::Window* pParent, - const css::uno::Reference< css::frame::XModel >& xChartModel - , const css::uno::Reference< css::uno::XComponentContext >& xContext ); + CreationWizard(vcl::Window* pParent, + const css::uno::Reference<css::frame::XModel>& xChartModel, + const css::uno::Reference<css::uno::XComponentContext>& xContext); CreationWizard() = delete; virtual ~CreationWizard() override; // TabPageNotifiable - virtual void setInvalidPage( TabPage * pTabPage ) override; - virtual void setValidPage( TabPage * pTabPage ) override; + virtual void setInvalidPage(TabPage * pTabPage) override; + virtual void setValidPage(TabPage * pTabPage) override; protected: - virtual bool leaveState( WizardState _nState ) override; - virtual WizardState determineNextState(WizardState nCurrentState) const override; - virtual void enterState(WizardState nState) override; + virtual bool leaveState( WizardState _nState ) override; + virtual WizardState determineNextState(WizardState nCurrentState) const override; + virtual void enterState(WizardState nState) override; - virtual OUString getStateDisplayName( WizardState nState ) const override; + virtual OUString getStateDisplayName(WizardState nState) const override; private: virtual VclPtr<TabPage> createPage(WizardState nState) override; - css::uno::Reference< css::chart2::XChartDocument > m_xChartModel; - css::uno::Reference< css::uno::XComponentContext> m_xCC; - ChartTypeTemplateProvider* m_pTemplateProvider; + css::uno::Reference<css::chart2::XChartDocument> m_xChartModel; + css::uno::Reference<css::uno::XComponentContext> m_xComponentContext; + ChartTypeTemplateProvider* m_pTemplateProvider; std::unique_ptr<DialogModel> m_pDialogModel; WizardState m_nLastState; - TimerTriggeredControllerLock m_aTimerTriggeredControllerLock; + TimerTriggeredControllerLock m_aTimerTriggeredControllerLock; -// RangeChooserTabPage * m_pRangeChooserTabPage; -// DataSourceTabPage * m_pDataSourceTabPage; - bool m_bCanTravel; + bool m_bCanTravel; }; + } //namespace chart + #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/main/ChartController_Window.cxx b/chart2/source/controller/main/ChartController_Window.cxx index 11dd2d832ab4..441e8da6e682 100644 --- a/chart2/source/controller/main/ChartController_Window.cxx +++ b/chart2/source/controller/main/ChartController_Window.cxx @@ -45,18 +45,23 @@ #include "LegendHelper.hxx" #include "servicenames_charttypes.hxx" #include "DrawCommandDispatch.hxx" +#include "PopupRequest.hxx" #include <com/sun/star/chart2/RelativePosition.hpp> #include <com/sun/star/chart2/RelativeSize.hpp> #include <com/sun/star/chart2/XRegressionCurveContainer.hpp> +#include <com/sun/star/chart2/data/XPivotTableDataProvider.hpp> #include <com/sun/star/awt/PopupMenuDirection.hpp> #include <com/sun/star/frame/DispatchHelper.hpp> #include <com/sun/star/frame/FrameSearchFlag.hpp> #include <com/sun/star/frame/XPopupMenuController.hpp> #include <com/sun/star/util/XUpdatable.hpp> +#include <com/sun/star/awt/Rectangle.hpp> + #include <comphelper/propertysequence.hxx> #include <comphelper/propertyvalue.hxx> +#include <comphelper/sequence.hxx> #include <toolkit/awt/vclxmenu.hxx> @@ -556,7 +561,16 @@ void ChartController::execute_MouseButtonDown( const MouseEvent& rMEvt ) if(!pChartWindow || !pDrawViewWrapper ) return; - Point aMPos = pChartWindow->PixelToLogic(rMEvt.GetPosPixel()); + Point aMPos = pChartWindow->PixelToLogic(rMEvt.GetPosPixel()); + + // Check if button was clicked + SdrObject* pObject = pDrawViewWrapper->getHitObject(aMPos); + if (pObject) + { + OUString aCID = pObject->GetName(); + if (aCID.startsWith("FieldButton")) + return; // Don't take any action if button was clicked + } if ( MOUSE_LEFT == rMEvt.GetButtons() ) { @@ -722,7 +736,19 @@ void ChartController::execute_MouseButtonUp( const MouseEvent& rMEvt ) if(!pChartWindow || !pDrawViewWrapper) return; - Point aMPos = pChartWindow->PixelToLogic(rMEvt.GetPosPixel()); + Point aMPos = pChartWindow->PixelToLogic(rMEvt.GetPosPixel()); + + // Check if button was clicked + SdrObject* pObject = pDrawViewWrapper->getHitObject(aMPos); + if (pObject) + { + OUString aCID = pObject->GetName(); + if (aCID.startsWith("FieldButton")) + { + sendPopupRequest(aCID, pObject->GetCurrentBoundRect()); + return; + } + } if(pDrawViewWrapper->IsTextEdit()) { @@ -1958,6 +1984,47 @@ css::uno::Reference<css::uno::XInterface> const & ChartController::getChartView( return m_xChartView; } +void ChartController::sendPopupRequest(OUString const & rCID, tools::Rectangle aRectangle) +{ + ChartModel* pChartModel = dynamic_cast<ChartModel*>(m_aModel->getModel().get()); + if (!pChartModel) + return; + + uno::Reference<chart2::data::XPivotTableDataProvider> xPivotTableDataProvider; + xPivotTableDataProvider.set(pChartModel->getDataProvider(), uno::UNO_QUERY); + if (!xPivotTableDataProvider.is()) + return; + + OUString sPivotTableName = xPivotTableDataProvider->getPivotTableName(); + + PopupRequest* pPopupRequest = dynamic_cast<PopupRequest*>(pChartModel->getPopupRequest().get()); + if (!pPopupRequest) + return; + + // Get dimension index from CID + sal_Int32 nStartPos = rCID.lastIndexOf('.'); + nStartPos++; + sal_Int32 nEndPos = rCID.getLength(); + OUString sDimensionIndex = rCID.copy(nStartPos, nEndPos - nStartPos); + sal_Int32 nDimensionIndex = sDimensionIndex.toInt32(); + + awt::Rectangle xRectangle { + sal_Int32(aRectangle.Left()), + sal_Int32(aRectangle.Top()), + sal_Int32(aRectangle.GetWidth()), + sal_Int32(aRectangle.GetHeight()) + }; + + uno::Sequence<beans::PropertyValue> aCallbackData = comphelper::InitPropertySequence( + { + {"Rectangle", uno::makeAny<awt::Rectangle>(xRectangle)}, + {"DimensionIndex", uno::makeAny<sal_Int32>(nDimensionIndex)}, + {"PivotTableName", uno::makeAny<OUString>(sPivotTableName)}, + }); + + pPopupRequest->getCallback()->notify(uno::makeAny(aCallbackData)); +} + } //namespace chart /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/inc/PopupRequest.hxx b/chart2/source/inc/PopupRequest.hxx index e564003c9e44..fb98d3d9b19d 100644 --- a/chart2/source/inc/PopupRequest.hxx +++ b/chart2/source/inc/PopupRequest.hxx @@ -12,8 +12,8 @@ #include "MutexContainer.hxx" #include <cppuhelper/compbase.hxx> -#include <com/sun/star/chart2/data/XPopupRequest.hpp> #include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/awt/XRequestCallback.hpp> namespace chart { @@ -21,16 +21,21 @@ namespace chart namespace impl { -typedef cppu::WeakComponentImplHelper<css::chart2::data::XPopupRequest> PopupRequest_Base; +typedef cppu::WeakComponentImplHelper<css::awt::XRequestCallback> PopupRequest_Base; } -class PopupRequest : public MutexContainer, public impl::PopupRequest_Base +class OOO_DLLPUBLIC_CHARTTOOLS PopupRequest : public MutexContainer, public impl::PopupRequest_Base { public: explicit PopupRequest(); virtual ~PopupRequest() override; + css::uno::Reference<css::awt::XCallback> getCallback() + { + return m_xCallback; + } + protected: // ____ XRequestCallback ____ virtual void SAL_CALL addCallback(const css::uno::Reference< ::css::awt::XCallback >& xCallback, diff --git a/chart2/source/model/main/ChartModel.cxx b/chart2/source/model/main/ChartModel.cxx index 814bd315928b..579a9c341eb8 100644 --- a/chart2/source/model/main/ChartModel.cxx +++ b/chart2/source/model/main/ChartModel.cxx @@ -38,6 +38,7 @@ #include <vcl/openglwin.hxx> #include <com/sun/star/chart/ChartDataRowSource.hpp> +#include <com/sun/star/chart2/data/XPivotTableDataProvider.hpp> #include <comphelper/processfactory.hxx> #include <cppuhelper/supportsservice.hxx> @@ -63,6 +64,7 @@ #include <com/sun/star/drawing/XShapes.hpp> #include <com/sun/star/document/DocumentProperties.hpp> #include <com/sun/star/chart2/XTimeBased.hpp> +#include <com/sun/star/util/XModifyBroadcaster.hpp> #include <svl/zforlist.hxx> @@ -744,7 +746,7 @@ Reference< chart2::data::XDataSource > ChartModel::impl_createDefaultData() xIni->initialize(aArgs); } //create data - uno::Sequence< beans::PropertyValue > aArgs( 4 ); + uno::Sequence<beans::PropertyValue> aArgs(4); aArgs[0] = beans::PropertyValue( "CellRangeRepresentation", -1, uno::Any( OUString("all") ), beans::PropertyState_DIRECT_VALUE ); @@ -816,6 +818,12 @@ void SAL_CALL ChartModel::attachDataProvider( const uno::Reference< chart2::data } } + uno::Reference<util::XModifyBroadcaster> xModifyBroadcaster(xDataProvider, uno::UNO_QUERY); + if (xModifyBroadcaster.is()) + { + xModifyBroadcaster->addModifyListener(this); + } + m_xDataProvider.set( xDataProvider ); m_xInternalDataProvider.clear(); @@ -911,7 +919,7 @@ Reference< chart2::data::XRangeHighlighter > SAL_CALL ChartModel::getRangeHighli return m_xRangeHighlighter; } -Reference<chart2::data::XPopupRequest> SAL_CALL ChartModel::getPopupRequest() +Reference<awt::XRequestCallback> SAL_CALL ChartModel::getPopupRequest() { if (!m_xPopupRequest.is()) m_xPopupRequest.set(new PopupRequest); @@ -1348,6 +1356,17 @@ void ChartModel::update() #endif } +bool ChartModel::isDataFromSpreadsheet() +{ + return !isDataFromPivotTable() && !hasInternalDataProvider(); +} + +bool ChartModel::isDataFromPivotTable() +{ + uno::Reference<chart2::data::XPivotTableDataProvider> xPivotTableDataProvider(m_xDataProvider, uno::UNO_QUERY); + return xPivotTableDataProvider.is(); +} + } // namespace chart extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * SAL_CALL diff --git a/chart2/source/model/main/ChartModel_Persistence.cxx b/chart2/source/model/main/ChartModel_Persistence.cxx index c19aeaf7c4d6..58585018b2f0 100644 --- a/chart2/source/model/main/ChartModel_Persistence.cxx +++ b/chart2/source/model/main/ChartModel_Persistence.cxx @@ -22,8 +22,10 @@ #include "macros.hxx" #include "ChartViewHelper.hxx" #include "ChartModelHelper.hxx" +#include "DataSourceHelper.hxx" #include "AxisHelper.hxx" #include "ThreeDHelper.hxx" +#include "DiagramHelper.hxx" #include <com/sun/star/chart2/LegendPosition.hpp> #include <com/sun/star/container/XNameAccess.hpp> @@ -44,11 +46,14 @@ #include <com/sun/star/io/XSeekable.hpp> #include <com/sun/star/ucb/CommandFailedException.hpp> +#include <com/sun/star/chart2/data/XPivotTableDataProvider.hpp> + #include <ucbhelper/content.hxx> #include <unotools/ucbstreamhelper.hxx> #include <vcl/cvtgrf.hxx> #include <comphelper/processfactory.hxx> #include <comphelper/storagehelper.hxx> +#include <comphelper/sequence.hxx> #include <vcl/svapp.hxx> #include <vcl/settings.hxx> @@ -704,10 +709,35 @@ void SAL_CALL ChartModel::removeModifyListener( } // util::XModifyListener -void SAL_CALL ChartModel::modified( const lang::EventObject& ) +void SAL_CALL ChartModel::modified( const lang::EventObject& rEvenObject) { - if( m_nInLoad == 0 ) - setModified( true ); + uno::Reference<chart2::data::XPivotTableDataProvider> xPivotTableDataProvider(rEvenObject.Source, uno::UNO_QUERY); + if (xPivotTableDataProvider.is()) + { + lockControllers(); + uno::Reference<chart2::data::XDataProvider> xDataProvider(xPivotTableDataProvider, uno::UNO_QUERY); + try + { + uno::Sequence<beans::PropertyValue> aArguments = + DataSourceHelper::createArguments("PivotChart", uno::Sequence<sal_Int32>(), true, true, true); + + Reference<chart2::data::XDataSource> xDataSource(xDataProvider->createDataSource(aArguments)); + Reference<lang::XMultiServiceFactory> xFactory(getChartTypeManager(), uno::UNO_QUERY); + Reference<chart2::XDiagram> xDiagram(getFirstDiagram()); + + DiagramHelper::tTemplateWithServiceName aTemplateAndService = DiagramHelper::getTemplateForDiagram(xDiagram, xFactory); + css::uno::Reference<css::chart2::XChartTypeTemplate> xChartTypeTemplate(aTemplateAndService.first); + xChartTypeTemplate->changeDiagramData(xDiagram, xDataSource, aArguments); + } + catch (const uno::Exception & ex) + { + ASSERT_EXCEPTION(ex); + } + unlockControllers(); + } + + if (m_nInLoad == 0) + setModified(true); } // lang::XEventListener (base of util::XModifyListener) diff --git a/chart2/source/view/main/ChartView.cxx b/chart2/source/view/main/ChartView.cxx index 2053ab09eaea..6dccabf2d74f 100644 --- a/chart2/source/view/main/ChartView.cxx +++ b/chart2/source/view/main/ChartView.cxx @@ -90,6 +90,8 @@ #include <com/sun/star/chart2/XTitled.hpp> #include <com/sun/star/chart2/RelativePosition.hpp> #include <com/sun/star/chart2/RelativeSize.hpp> +#include <com/sun/star/chart2/data/XPivotTableDataProvider.hpp> +#include <com/sun/star/chart2/data/PivotTableFieldEntry.hpp> #include <com/sun/star/drawing/FillStyle.hpp> #include <com/sun/star/drawing/GraphicExportFilter.hpp> #include <com/sun/star/drawing/LineStyle.hpp> @@ -114,6 +116,7 @@ #include <comphelper/classids.hxx> #include "servicenames_charttypes.hxx" + #include <rtl/strbuf.hxx> #include <rtl/ustring.hxx> @@ -2490,78 +2493,63 @@ void lcl_createButtons(const uno::Reference< drawing::XShapes>& xPageShapes, ChartModel& rModel, awt::Rectangle& rRemainingSpace) { - uno::Reference<beans::XPropertySet> xModelPage(rModel.getPageBackground()); - -// TODO: Get this from the PivotTable - std::vector<OUString> aPageFields { -// "Subdivision", "Subdivision2" - }; - std::vector<OUString> aDataFields { -// "Sum - Revenue", "Sum - Expenses" - }; - std::vector<OUString> aColumnFields { -// "Group Segment", "Group Segment 2" - }; + uno::Reference<chart2::data::XPivotTableDataProvider> xPivotTableDataProvider(rModel.getDataProvider(), uno::UNO_QUERY); + if (!xPivotTableDataProvider.is()) + return; + uno::Reference<beans::XPropertySet> xModelPage(rModel.getPageBackground()); awt::Size aSize(3000, 700); // size of the button long x = 0; - int nCIDIndex = 0; - if (!aPageFields.empty()) + if (xPivotTableDataProvider->getPageFields().hasElements()) { x = 0; - nCIDIndex = 0; - for (OUString const & aPageField : aPageFields) + for (css::chart2::data::PivotTableFieldEntry const & rPageFieldEntry : xPivotTableDataProvider->getPageFields()) { std::unique_ptr<VButton> pButton(new VButton); pButton->init(xPageShapes, xShapeFactory); awt::Point aNewPosition = awt::Point(rRemainingSpace.X + x + 100, rRemainingSpace.Y + 100); - pButton->setLabel(aPageField); - pButton->setCID("PageFieldButton." + OUString::number(nCIDIndex)); + pButton->setLabel(rPageFieldEntry.Name); + pButton->setCID("FieldButton.Page." + OUString::number(rPageFieldEntry.DimensionIndex)); pButton->createShapes(aNewPosition, aSize, xModelPage); x += aSize.Width + 100; - nCIDIndex += 1; } rRemainingSpace.Y += (aSize.Height + 100 + 100); rRemainingSpace.Height -= (aSize.Height + 100 + 100); } - if (!aDataFields.empty()) + if (xPivotTableDataProvider->getDataFields().hasElements()) { x = 200; - nCIDIndex = 0; - for (OUString const & aDataField : aDataFields) + for (css::chart2::data::PivotTableFieldEntry const & rDataFieldEntry : xPivotTableDataProvider->getDataFields()) { std::unique_ptr<VButton> pButton(new VButton); pButton->init(xPageShapes, xShapeFactory); awt::Point aNewPosition = awt::Point(rRemainingSpace.X + x + 100, rRemainingSpace.Y + 100); - pButton->setLabel(aDataField); - pButton->setCID("DataFieldButton." + OUString::number(nCIDIndex)); + pButton->setLabel(rDataFieldEntry.Name); + pButton->setCID("FieldButton.Data." + OUString::number(rDataFieldEntry.DimensionIndex)); pButton->createShapes(aNewPosition, aSize, xModelPage); x += aSize.Width + 100; - nCIDIndex += 1; } rRemainingSpace.Y += (aSize.Height + 100 + 100); rRemainingSpace.Height -= (aSize.Height + 100 + 100); } - if (!aColumnFields.empty()) + if (xPivotTableDataProvider->getRowFields().hasElements()) { x = 200; - nCIDIndex = 0; - for (OUString const & aColumnField : aColumnFields) + for (css::chart2::data::PivotTableFieldEntry const & rRowFieldEntry : xPivotTableDataProvider->getRowFields()) { std::unique_ptr<VButton> pButton(new VButton); pButton->init(xPageShapes, xShapeFactory); awt::Point aNewPosition = awt::Point(rRemainingSpace.X + x + 100, rRemainingSpace.Y + rRemainingSpace.Height - aSize.Height - 100); - pButton->setLabel(aColumnField); - pButton->setCID("ColumnFieldButton." + OUString::number(nCIDIndex)); + pButton->setLabel(rRowFieldEntry.Name); + pButton->setCID("FieldButton.Row." + OUString::number(rRowFieldEntry.DimensionIndex)); pButton->createShapes(aNewPosition, aSize, xModelPage); x += aSize.Width + 100; - nCIDIndex += 1; } rRemainingSpace.Height -= (aSize.Height + 100 + 100); } diff --git a/chart2/source/view/main/VLegend.cxx b/chart2/source/view/main/VLegend.cxx index 698f7fcc9400..e2d9b735cefd 100644 --- a/chart2/source/view/main/VLegend.cxx +++ b/chart2/source/view/main/VLegend.cxx @@ -37,9 +37,12 @@ #include <com/sun/star/chart/ChartLegendExpansion.hpp> #include <com/sun/star/chart2/LegendPosition.hpp> #include <com/sun/star/chart2/RelativePosition.hpp> +#include <com/sun/star/chart2/data/XPivotTableDataProvider.hpp> +#include <com/sun/star/chart2/data/PivotTableFieldEntry.hpp> #include <rtl/ustrbuf.hxx> #include <svl/languageoptions.hxx> + #include <vector> #include <algorithm> @@ -766,33 +769,31 @@ std::vector<std::shared_ptr<VButton>> lcl_createButtons( const uno::Reference< lang::XMultiServiceFactory>& xShapeFactory, ChartModel& rModel, long& nUsedHeight) { -// TODO: get this info from the Pivot Table - std::vector<OUString> aRowFields { -// "Service Months" - }; - std::vector<std::shared_ptr<VButton>> aButtons; - if (aRowFields.empty()) + uno::Reference<chart2::data::XPivotTableDataProvider> xPivotTableDataProvider(rModel.getDataProvider(), uno::UNO_QUERY); + if (!xPivotTableDataProvider.is()) + return aButtons; + + if (!xPivotTableDataProvider->getColumnFields().hasElements()) return aButtons; uno::Reference<beans::XPropertySet> xModelPage(rModel.getPageBackground()); - int nCIDIndex = 0; awt::Size aSize(2000, 700); - - for (OUString const & sRowField : aRowFields) + int y = 100; + for (chart2::data::PivotTableFieldEntry const & sColumnFieldEntry : xPivotTableDataProvider->getColumnFields()) { std::shared_ptr<VButton> pButton(new VButton); aButtons.push_back(pButton); pButton->init(xLegendContainer, xShapeFactory); - awt::Point aNewPosition = awt::Point(100, 100); - pButton->setLabel(sRowField); - pButton->setCID("RowFieldButton." + OUString::number(nCIDIndex)); + awt::Point aNewPosition = awt::Point(100, y); + pButton->setLabel(sColumnFieldEntry.Name); + pButton->setCID("FieldButton.Column." + OUString::number(sColumnFieldEntry.DimensionIndex)); pButton->createShapes(aNewPosition, aSize, xModelPage); - nCIDIndex += 1; + y += aSize.Height + 100;; } - nUsedHeight += aSize.Height + 100; + nUsedHeight += y + 100; return aButtons; } |