diff options
author | Dennis Francis <dennis.francis@collabora.com> | 2021-08-25 20:51:56 +0530 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.com> | 2021-09-01 09:15:03 +0200 |
commit | 9d8324524bdcd1244cd6e9d93b063b981d47c9be (patch) | |
tree | 1bbd6560ef3a292b0685d4b768ea1a07c17259b8 /xmloff | |
parent | b365358075d484e034eb9cd6bceeea9d639835b6 (diff) |
tdf#143942: oox: import/export labels from <c15:datalabelsRange>
When <c15:showDataLabelsRange> boolean flag is present, the imported
label texts are added as the first text field in oox data label model.
The cell-range associated is also preserved. The export part preserves
the how labels were store originally in <c15:datalabelsRange>.
However in order to make the custom labels reflect the contents of the
cells in the associated cell-range, more work needs to be done. For this
the labels present in <c15:datalabelsRange> needs to be made available
as a data-sequence with a new "role" like "point-labels" in
XInternalDataProvider implementation and and make the label renderer
read this data source rather than consulting the custom label fields
property which is static after import.
Change-Id: Ibc7045fa5ea209d463680c96efb49a06662d2500
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/121313
Tested-by: Jenkins
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
Diffstat (limited to 'xmloff')
-rw-r--r-- | xmloff/source/chart/SchXMLExport.cxx | 64 | ||||
-rw-r--r-- | xmloff/source/chart/SchXMLPlotAreaContext.cxx | 16 | ||||
-rw-r--r-- | xmloff/source/chart/SchXMLPlotAreaContext.hxx | 4 | ||||
-rw-r--r-- | xmloff/source/chart/SchXMLSeries2Context.cxx | 21 | ||||
-rw-r--r-- | xmloff/source/chart/transporttypes.hxx | 20 | ||||
-rw-r--r-- | xmloff/source/core/xmltoken.cxx | 2 | ||||
-rw-r--r-- | xmloff/source/token/tokens.txt | 2 |
7 files changed, 106 insertions, 23 deletions
diff --git a/xmloff/source/chart/SchXMLExport.cxx b/xmloff/source/chart/SchXMLExport.cxx index 4d1596b04aa5..65510e036ac2 100644 --- a/xmloff/source/chart/SchXMLExport.cxx +++ b/xmloff/source/chart/SchXMLExport.cxx @@ -114,7 +114,27 @@ using ::std::vector; namespace { - using CustomLabelSeq = Sequence<Reference<chart2::XDataPointCustomLabelField>>; + /** + * Used to store a data point custom-label's fields and also the helper members that + * indicates whether this label's contents are sourced from a cell[range] and + * the address of the cell[range] with guid of the CELLRANGE field. + */ + struct CustomLabelData + { + CustomLabelData(): + mbDataLabelsRange( false ) + { + } + + /// Label fields. + Sequence<Reference<chart2::XDataPointCustomLabelField>> maFields; + /// Are label's contents sourced from a cell[range] ? + bool mbDataLabelsRange; + /// cell[range] from which label's contents are sourced. + OUString maRange; + /// GUID of the CELLRANGE field. + OUString maGuid; + }; struct SchXMLDataPointStruct { @@ -124,7 +144,7 @@ namespace // There is no internal equivalent for <chart:data-label>. It will be generated on the fly // on export. All about data label is hold in the data point. - CustomLabelSeq mCustomLabelText; // <text:p> child element in <chart:data-label> + CustomLabelData mCustomLabel; // <text:p> child element in <chart:data-label> OUString msDataLabelStyleName; // chart:style-name attribute in <chart:data-label> SchXMLDataPointStruct() : mnRepeat( 1 ) {} @@ -283,30 +303,43 @@ public: namespace { -CustomLabelSeq lcl_getCustomLabelField(SvXMLExport const& rExport, +CustomLabelData lcl_getCustomLabelField(SvXMLExport const& rExport, sal_Int32 nDataPointIndex, const uno::Reference< chart2::XDataSeries >& rSeries) { if (!rSeries.is()) - return CustomLabelSeq(); + return CustomLabelData(); // Custom data label text will be written to the <text:p> child element of a // <chart:data-label> element. That exists only since ODF 1.2. const SvtSaveOptions::ODFSaneDefaultVersion nCurrentODFVersion( rExport.getSaneDefaultVersion()); if (nCurrentODFVersion < SvtSaveOptions::ODFSVER_012) - return CustomLabelSeq(); + return CustomLabelData(); if(Reference<beans::XPropertySet> xLabels = rSeries->getDataPointByIndex(nDataPointIndex); xLabels.is()) { if(Any aAny = xLabels->getPropertyValue("CustomLabelFields"); aAny.hasValue()) { + CustomLabelData aData; Sequence<uno::Reference<chart2::XDataPointCustomLabelField>> aCustomLabels; aAny >>= aCustomLabels; - return aCustomLabels; + for (const auto& rField: std::as_const(aCustomLabels)) + { + if (rField->getFieldType() == chart2::DataPointCustomLabelFieldType_CELLRANGE) + { + if (rField->getDataLabelsRange()) + aData.mbDataLabelsRange = true; + aData.maRange = rField->getCellRange(); + aData.maGuid = rField->getGuid(); + } + } + + aData.maFields = aCustomLabels; + return aData; } } - return CustomLabelSeq(); + return CustomLabelData(); } css::chart2::RelativePosition lcl_getCustomLabelPosition( @@ -3463,7 +3496,7 @@ void SchXMLExportHelper_Impl::exportDataPoints( maAutoStyleNameQueue.pop(); } if(bExportNumFmt) - aPoint.mCustomLabelText = lcl_getCustomLabelField(mrExport, nElement, xSeries); + aPoint.mCustomLabel = lcl_getCustomLabelField(mrExport, nElement, xSeries); aPoint.mCustomLabelPos = lcl_getCustomLabelPosition(mrExport, nElement, xSeries); aDataPointVector.push_back( aPoint ); @@ -3542,7 +3575,7 @@ void SchXMLExportHelper_Impl::exportDataPoints( aPoint.maStyleName = maAutoStyleNameQueue.front(); maAutoStyleNameQueue.pop(); } - aPoint.mCustomLabelText = lcl_getCustomLabelField(mrExport, nCurrIndex, xSeries); + aPoint.mCustomLabel = lcl_getCustomLabelField(mrExport, nCurrIndex, xSeries); aPoint.mCustomLabelPos = lcl_getCustomLabelPosition(mrExport, nCurrIndex, xSeries); if (!aDataLabelPropertyStates.empty()) { @@ -3598,7 +3631,7 @@ void SchXMLExportHelper_Impl::exportDataPoints( aPoint = rPoint; if (aPoint.maStyleName == aLastPoint.maStyleName - && aLastPoint.mCustomLabelText.getLength() < 1 + && aLastPoint.mCustomLabel.maFields.getLength() < 1 && aLastPoint.mCustomLabelPos.Primary == 0.0 && aLastPoint.mCustomLabelPos.Secondary == 0.0 && aPoint.msDataLabelStyleName == aLastPoint.msDataLabelStyleName) @@ -3655,15 +3688,22 @@ void SchXMLExportHelper_Impl::exportDataPoints( void SchXMLExportHelper_Impl::exportCustomLabel(const SchXMLDataPointStruct& rPoint) { - if (rPoint.mCustomLabelText.getLength() < 1 && rPoint.msDataLabelStyleName.isEmpty()) + if (rPoint.mCustomLabel.maFields.getLength() < 1 && rPoint.msDataLabelStyleName.isEmpty()) return; // nothing to export if (!rPoint.msDataLabelStyleName.isEmpty()) mrExport.AddAttribute(XML_NAMESPACE_CHART, XML_STYLE_NAME, rPoint.msDataLabelStyleName); + + if (rPoint.mCustomLabel.mbDataLabelsRange) + { + mrExport.AddAttribute(XML_NAMESPACE_LO_EXT, XML_DATA_LABELS_CELL_RANGE, rPoint.mCustomLabel.maRange); + mrExport.AddAttribute(XML_NAMESPACE_LO_EXT, XML_DATA_LABEL_GUID, rPoint.mCustomLabel.maGuid); + } // TODO svg:x and svg:y for <chart:data-label> SvXMLElementExport aLabelElem( mrExport, XML_NAMESPACE_CHART, XML_DATA_LABEL, true, true); SvXMLElementExport aPara( mrExport, XML_NAMESPACE_TEXT, XML_P, true, false ); - for (const Reference<chart2::XDataPointCustomLabelField>& label : rPoint.mCustomLabelText) + + for (const Reference<chart2::XDataPointCustomLabelField>& label : rPoint.mCustomLabel.maFields) { // TODO add style SvXMLElementExport aSpan( mrExport, XML_NAMESPACE_TEXT, XML_SPAN, true, false); diff --git a/xmloff/source/chart/SchXMLPlotAreaContext.cxx b/xmloff/source/chart/SchXMLPlotAreaContext.cxx index 563798b7c599..a66b05d0661b 100644 --- a/xmloff/source/chart/SchXMLPlotAreaContext.cxx +++ b/xmloff/source/chart/SchXMLPlotAreaContext.cxx @@ -617,7 +617,7 @@ css::uno::Reference< css::xml::sax::XFastContextHandler > SchXMLDataLabelParaCon } SchXMLDataLabelContext::SchXMLDataLabelContext(SvXMLImport& rImport, - ::std::vector<OUString>& rLabels, + CustomLabelsInfo& rLabels, DataRowPointStyle& rDataLabelStyle) : SvXMLImportContext(rImport) , mrLabels(rLabels) @@ -630,7 +630,7 @@ css::uno::Reference< css::xml::sax::XFastContextHandler > SchXMLDataLabelContext const css::uno::Reference< css::xml::sax::XFastAttributeList >& ) { if ( nElement == XML_ELEMENT(TEXT, XML_P) ) - return new SchXMLDataLabelParaContext(GetImport(), mrLabels); + return new SchXMLDataLabelParaContext(GetImport(), mrLabels.mLabels); else XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement); return nullptr; @@ -663,6 +663,14 @@ void SchXMLDataLabelContext::startFastElement( case XML_ELEMENT(CHART, XML_STYLE_NAME): mrDataLabelStyle.msStyleName = aIter.toString(); break; + case XML_ELEMENT(LO_EXT, XML_DATA_LABEL_GUID): + mrLabels.msLabelGuid = aIter.toString(); + mrLabels.mbDataLabelsRange = true; + break; + case XML_ELEMENT(LO_EXT, XML_DATA_LABELS_CELL_RANGE): + mrLabels.msLabelsCellRange = aIter.toString(); + mrLabels.mbDataLabelsRange = true; + break; default: XMLOFF_WARN_UNKNOWN("xmloff", aIter); } @@ -737,7 +745,7 @@ void SchXMLDataPointContext::startFastElement (sal_Int32 /*Element*/, if (!mbHasLabelParagraph) { sCustomLabelField = aIter.toString(); - mDataPoint.mCustomLabels.push_back(sCustomLabelField); + mDataPoint.mCustomLabels.mLabels.push_back(sCustomLabelField); } break; case XML_ELEMENT(LO_EXT, XML_HIDE_LEGEND): @@ -778,7 +786,7 @@ void SchXMLDataPointContext::startFastElement (sal_Int32 /*Element*/, void SchXMLDataPointContext::endFastElement(sal_Int32 ) { - if(!mDataPoint.msStyleName.isEmpty() || mDataPoint.mCustomLabels.size() > 0) + if(!mDataPoint.msStyleName.isEmpty() || mDataPoint.mCustomLabels.mLabels.size() > 0) { mrStyleVector.push_back(mDataPoint); } diff --git a/xmloff/source/chart/SchXMLPlotAreaContext.hxx b/xmloff/source/chart/SchXMLPlotAreaContext.hxx index f0c2c2982a46..f80ee6f4840a 100644 --- a/xmloff/source/chart/SchXMLPlotAreaContext.hxx +++ b/xmloff/source/chart/SchXMLPlotAreaContext.hxx @@ -164,11 +164,11 @@ public: class SchXMLDataLabelContext: public SvXMLImportContext { private: - ::std::vector<OUString>& mrLabels; + CustomLabelsInfo& mrLabels; DataRowPointStyle& mrDataLabelStyle; public: SchXMLDataLabelContext(SvXMLImport& rImport, - ::std::vector<OUString>& rLabels, DataRowPointStyle& rDataLabel); + CustomLabelsInfo& rLabels, DataRowPointStyle& rDataLabel); virtual void SAL_CALL startFastElement( sal_Int32 nElement, diff --git a/xmloff/source/chart/SchXMLSeries2Context.cxx b/xmloff/source/chart/SchXMLSeries2Context.cxx index 544616846338..1d91af151317 100644 --- a/xmloff/source/chart/SchXMLSeries2Context.cxx +++ b/xmloff/source/chart/SchXMLSeries2Context.cxx @@ -1214,16 +1214,28 @@ void SchXMLSeries2Context::setStylesToDataPoints( SeriesDefaultsAndStyles& rSeri } // Custom labels might be passed as property - if(auto nLabelCount = seriesStyle.mCustomLabels.size(); nLabelCount > 0) + if(const size_t nLabelCount = seriesStyle.mCustomLabels.mLabels.size(); nLabelCount > 0) { + auto& rCustomLabels = seriesStyle.mCustomLabels; + Sequence< Reference<chart2::XDataPointCustomLabelField>> xLabels(nLabelCount); Reference< uno::XComponentContext > xContext( comphelper::getProcessComponentContext() ); - for( auto j = 0; j< xLabels.getLength(); ++j ) + for( size_t j = 0; j < nLabelCount; ++j ) { Reference< chart2::XDataPointCustomLabelField > xCustomLabel = chart2::DataPointCustomLabelField::create(xContext); xLabels[j] = xCustomLabel; - xCustomLabel->setString(seriesStyle.mCustomLabels[j]); - xCustomLabel->setFieldType(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_TEXT); + xCustomLabel->setString(rCustomLabels.mLabels[j]); + if ( j == 0 && rCustomLabels.mbDataLabelsRange) + { + xCustomLabel->setFieldType(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_CELLRANGE); + xCustomLabel->setGuid(rCustomLabels.msLabelGuid); + xCustomLabel->setCellRange(rCustomLabels.msLabelsCellRange); + xCustomLabel->setDataLabelsRange(true); + } + else + { + xCustomLabel->setFieldType(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_TEXT); + } // Restore character properties on the text span manually, till // SchXMLExportHelper_Impl::exportCustomLabel() does not write the style. @@ -1245,6 +1257,7 @@ void SchXMLSeries2Context::setStylesToDataPoints( SeriesDefaultsAndStyles& rSeri } } } + xPointProp->setPropertyValue("CustomLabelFields", uno::Any(xLabels)); xPointProp->setPropertyValue("DataCaption", uno::Any(chart::ChartDataCaption::CUSTOM)); } diff --git a/xmloff/source/chart/transporttypes.hxx b/xmloff/source/chart/transporttypes.hxx index 7393a7b34848..7053d20c84c0 100644 --- a/xmloff/source/chart/transporttypes.hxx +++ b/xmloff/source/chart/transporttypes.hxx @@ -145,6 +145,24 @@ struct RegressionStyle {} }; +/** + * Used to store text content of a data point custom-label's fields and also + * the helper members that indicates whether this label's contents are sourced + * from a cell[range] and the address of the cell[range] with GUID of + * the CELLRANGE field. + */ +struct CustomLabelsInfo +{ + /// Text content of each field. + ::std::vector<OUString> mLabels; + /// Are label's contents sourced from a cell[range] ? + bool mbDataLabelsRange = false; + /// GUID of the CELLRANGE field. + OUString msLabelGuid; + /// cell[range] from which label's contents are sourced. + OUString msLabelsCellRange; +}; + struct DataRowPointStyle { enum StyleType @@ -170,7 +188,7 @@ struct DataRowPointStyle sal_Int32 m_nPointRepeat; OUString msStyleName; OUString msStyleNameOfParent; // e.g. target of line and fill styles of data-labels - ::std::vector<OUString> mCustomLabels; + CustomLabelsInfo mCustomLabels; double mCustomLabelPos[2] = { 0.0, 0.0 }; // for svg:x and svg:y attribute (in core unit), of element <chart:data-label> std::optional<sal_Int32> mo_nLabelAbsolutePosX; diff --git a/xmloff/source/core/xmltoken.cxx b/xmloff/source/core/xmltoken.cxx index d4b996a4d9dd..e3a45924091e 100644 --- a/xmloff/source/core/xmltoken.cxx +++ b/xmloff/source/core/xmltoken.cxx @@ -581,10 +581,12 @@ namespace xmloff::token { TOKEN( "data-bar-entry", XML_DATA_BAR_ENTRY ), TOKEN( "data-cell-range-address", XML_DATA_CELL_RANGE_ADDRESS ), TOKEN( "data-label", XML_DATA_LABEL ), + TOKEN( "data-label-guid", XML_DATA_LABEL_GUID ), TOKEN( "data-label-number", XML_DATA_LABEL_NUMBER ), TOKEN( "data-label-symbol", XML_DATA_LABEL_SYMBOL ), TOKEN( "data-label-text", XML_DATA_LABEL_TEXT ), TOKEN( "data-label-series", XML_DATA_LABEL_SERIES ), + TOKEN( "data-labels-cell-range", XML_DATA_LABELS_CELL_RANGE ), TOKEN( "data-pilot-source", XML_DATA_PILOT_SOURCE ), TOKEN( "data-pilot-field", XML_DATA_PILOT_FIELD ), TOKEN( "data-pilot-grand-total", XML_DATA_PILOT_GRAND_TOTAL ), diff --git a/xmloff/source/token/tokens.txt b/xmloff/source/token/tokens.txt index 9823df1e82e7..3fde556acfee 100644 --- a/xmloff/source/token/tokens.txt +++ b/xmloff/source/token/tokens.txt @@ -493,10 +493,12 @@ data-bar data-bar-entry data-cell-range-address data-label +data-label-guid data-label-number data-label-symbol data-label-text data-label-series +data-labels-cell-range data-pilot-source data-pilot-field data-pilot-grand-total |