diff options
author | Szymon Kłos <szymon.klos@collabora.com> | 2018-02-12 20:39:14 +0100 |
---|---|---|
committer | Andras Timar <andras.timar@collabora.com> | 2018-02-12 20:39:14 +0100 |
commit | 55e7f7f8d76db06505a04ff7b8505455aff50c5e (patch) | |
tree | adfbf0e03a9a4dd962bc21163dad9ffc92c65db1 /oox | |
parent | 24d674338b4651222620d5823f1d8fe026566679 (diff) |
tdf#114821 import/export/place complex data labels in charts
Change-Id: Ia44abcebb4febcabb1704aef85e396730ac2cd6f
Diffstat (limited to 'oox')
-rw-r--r-- | oox/inc/drawingml/textfield.hxx | 2 | ||||
-rw-r--r-- | oox/source/drawingml/chart/seriesconverter.cxx | 112 | ||||
-rw-r--r-- | oox/source/export/chartexport.cxx | 107 | ||||
-rw-r--r-- | oox/source/token/properties.txt | 1 |
4 files changed, 208 insertions, 14 deletions
diff --git a/oox/inc/drawingml/textfield.hxx b/oox/inc/drawingml/textfield.hxx index 9f5bf9cf27af..7cc15a04fce4 100644 --- a/oox/inc/drawingml/textfield.hxx +++ b/oox/inc/drawingml/textfield.hxx @@ -38,7 +38,9 @@ public: const TextParagraphProperties& getTextParagraphProperties() const { return maTextParagraphProperties; } void setType( const OUString& sType ) { msType = sType; } + const OUString& getType() const { return msType; } void setUuid( const OUString & sUuid ) { msUuid = sUuid; } + const OUString& getUuid() const { return msUuid; } virtual sal_Int32 insertAt( const ::oox::core::XmlFilterBase& rFilterBase, diff --git a/oox/source/drawingml/chart/seriesconverter.cxx b/oox/source/drawingml/chart/seriesconverter.cxx index d0ed206cd0b1..666620b09845 100644 --- a/oox/source/drawingml/chart/seriesconverter.cxx +++ b/oox/source/drawingml/chart/seriesconverter.cxx @@ -22,11 +22,16 @@ #include <com/sun/star/chart/DataLabelPlacement.hpp> #include <com/sun/star/chart/ErrorBarStyle.hpp> #include <com/sun/star/chart2/DataPointLabel.hpp> +#include <com/sun/star/chart2/XDataPointCustomLabelField.hpp> +#include <com/sun/star/chart2/DataPointCustomLabelField.hpp> +#include <com/sun/star/chart2/DataPointCustomLabelFieldType.hpp> #include <com/sun/star/chart2/XDataSeries.hpp> #include <com/sun/star/chart2/XRegressionCurve.hpp> #include <com/sun/star/chart2/XRegressionCurveContainer.hpp> #include <com/sun/star/chart2/data/XDataSink.hpp> #include <com/sun/star/chart2/data/LabeledDataSequence.hpp> +#include <com/sun/star/chart2/XFormattedString2.hpp> +#include <com/sun/star/chart2/FormattedString.hpp> #include <osl/diagnose.h> #include <basegfx/numeric/ftools.hxx> #include "drawingml/chart/datasourceconverter.hxx" @@ -41,6 +46,10 @@ #include <oox/token/properties.hxx> #include <oox/token/tokens.hxx> #include <oox/drawingml/lineproperties.hxx> +#include <drawingml/textparagraph.hxx> +#include <drawingml/textrun.hxx> +#include <drawingml/textfield.hxx> +#include <drawingml/textbody.hxx> namespace oox { namespace drawingml { @@ -54,13 +63,30 @@ using namespace ::com::sun::star::uno; namespace { -/** nested-up sgn function - employs some gratuity around 0 - values - smaller than 0.33 are clamped to 0 +/** Function to get vertical position of label from chart height factor. + Value can be negative, prefer top placement. */ -int lclSgn( double nVal ) +int lclGetPositionY( double nVal ) { - const int intVal=nVal*3; - return intVal == 0 ? 0 : (intVal < 0 ? -1 : 1); + if( nVal <= 0.1 ) + return -1; + else if( nVal <= 0.6 ) + return 0; + else + return 1; +} + +/** Function to get horizontal position of label from chart width factor. + Value can be negative, prefer center placement. +*/ +int lclGetPositionX( double nVal ) +{ + if( nVal <= -0.2 ) + return -1; + else if( nVal <= 0.2 ) + return 0; + else + return 1; } Reference< XLabeledDataSequence > lclCreateLabeledDataSequence( @@ -193,6 +219,20 @@ void importBorderProperties( PropertySet& rPropSet, Shape& rShape, const Graphic rPropSet.setProperty(PROP_LabelBorderColor, uno::makeAny(nColor)); } +DataPointCustomLabelFieldType lcl_ConvertFieldNameToFieldEnum( const OUString& rField ) +{ + if (rField == "VALUE") + return DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_VALUE; + else if (rField == "SERIESNAME") + return DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_SERIESNAME; + else if (rField == "CATEGORYNAME") + return DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_CATEGORYNAME; + else if (rField == "CELLREF") + return DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_CELLREF; + else + return DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_TEXT; +} + } // namespace DataLabelConverter::DataLabelConverter( const ConverterRoot& rParent, DataLabelModel& rModel ) : @@ -228,17 +268,69 @@ void DataLabelConverter::convertFromModel( const Reference< XDataSeries >& rxDat csscd::LEFT, csscd::CENTER, csscd::RIGHT, csscd::BOTTOM_LEFT, csscd::BOTTOM, csscd::BOTTOM_RIGHT }; - const double nMax=std::max( - fabs(mrModel.mxLayout->mfX), - fabs(mrModel.mxLayout->mfY)); - const int simplifiedX=lclSgn(mrModel.mxLayout->mfX/nMax); - const int simplifiedY=lclSgn(mrModel.mxLayout->mfY/nMax); + const int simplifiedX = lclGetPositionX(mrModel.mxLayout->mfX); + const int simplifiedY = lclGetPositionY(mrModel.mxLayout->mfY); aPropSet.setProperty( PROP_LabelPlacement, aPositionsLookupTable[ simplifiedX+1 + 3*(simplifiedY+1) ] ); } if (mrModel.mxShapeProp) importBorderProperties(aPropSet, *mrModel.mxShapeProp, getFilter().getGraphicHelper()); + + if( mrModel.mxText && mrModel.mxText->mxTextBody && mrModel.mxText->mxTextBody->getParagraphs().size() ) + { + css::uno::Reference< XComponentContext > xContext = getComponentContext(); + uno::Sequence< css::uno::Reference< XDataPointCustomLabelField > > aSequence; + + auto& rParagraphs = mrModel.mxText->mxTextBody->getParagraphs(); + + int nSequenceSize = 0; + for( auto& pParagraph : rParagraphs ) + nSequenceSize += pParagraph->getRuns().size(); + + int nParagraphs = rParagraphs.size(); + if( nParagraphs > 1 ) + nSequenceSize += nParagraphs - 1; + + aSequence.realloc( nSequenceSize ); + + int nPos = 0; + for( auto& pParagraph : rParagraphs ) + { + for( auto& pRun : pParagraph->getRuns() ) + { + css::uno::Reference< XDataPointCustomLabelField > xCustomLabel = DataPointCustomLabelField::create( xContext ); + + // Store properties + oox::PropertySet aPropertySet( xCustomLabel ); + pRun->getTextCharacterProperties().pushToPropSet( aPropertySet, getFilter() ); + + TextField* pField = nullptr; + if( ( pField = dynamic_cast< TextField* >( pRun.get() ) ) ) + { + xCustomLabel->setString( pField->getText() ); + xCustomLabel->setFieldType( lcl_ConvertFieldNameToFieldEnum( pField->getType() ) ); + xCustomLabel->setGuid( pField->getUuid() ); + } + else if( pRun.get() ) + { + xCustomLabel->setString( pRun->getText() ); + xCustomLabel->setFieldType( DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_TEXT ); + } + aSequence[ nPos++ ] = xCustomLabel; + } + + if( nParagraphs > 1 && nPos < nSequenceSize ) + { + css::uno::Reference< XDataPointCustomLabelField > xCustomLabel = DataPointCustomLabelField::create( xContext ); + xCustomLabel->setFieldType( DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_NEWLINE ); + xCustomLabel->setString("\n"); + aSequence[ nPos++ ] = xCustomLabel; + } + } + + aPropSet.setProperty( PROP_CustomLabelFields, makeAny( aSequence ) ); + } } catch( Exception& ) { diff --git a/oox/source/export/chartexport.cxx b/oox/source/export/chartexport.cxx index 18b9a02bcd0d..142761afb89d 100644 --- a/oox/source/export/chartexport.cxx +++ b/oox/source/export/chartexport.cxx @@ -57,6 +57,8 @@ #include <com/sun/star/chart2/XDataSeriesContainer.hpp> #include <com/sun/star/chart2/DataPointGeometry3D.hpp> #include <com/sun/star/chart2/DataPointLabel.hpp> +#include <com/sun/star/chart2/DataPointCustomLabelField.hpp> +#include <com/sun/star/chart2/DataPointCustomLabelFieldType.hpp> #include <com/sun/star/chart2/Symbol.hpp> #include <com/sun/star/chart2/data/XDataSource.hpp> #include <com/sun/star/chart2/data/XDataSink.hpp> @@ -2955,17 +2957,111 @@ const char* toOOXMLPlacement( sal_Int32 nPlacement ) return "outEnd"; } -void writeLabelProperties( - const FSHelperPtr& pFS, const uno::Reference<beans::XPropertySet>& xPropSet, const LabelPlacementParam& rLabelParam ) +OUString getFieldTypeString( const chart2::DataPointCustomLabelFieldType aType ) +{ + switch (aType) + { + case chart2::DataPointCustomLabelFieldType_CATEGORYNAME: + return OUString("CATEGORYNAME"); + + case chart2::DataPointCustomLabelFieldType_SERIESNAME: + return OUString("SERIESNAME"); + + case chart2::DataPointCustomLabelFieldType_VALUE: + return OUString("VALUE"); + + case chart2::DataPointCustomLabelFieldType_CELLREF: + return OUString("CELLREF"); + + default: + break; + } + return OUString(); +} + +void writeRunProperties( ChartExport* pChartExport, Reference<XPropertySet>& xPropertySet ) +{ + bool bDummy = false; + sal_Int32 nDummy; + pChartExport->WriteRunProperties(xPropertySet, false, XML_rPr, true, bDummy, nDummy); +} + +void writeCustomLabel( const FSHelperPtr& pFS, ChartExport* pChartExport, + const Sequence<Reference<chart2::XDataPointCustomLabelField>>& rCustomLabelFields ) +{ + pFS->startElement(FSNS(XML_c, XML_tx), FSEND); + pFS->startElement(FSNS(XML_c, XML_rich), FSEND); + + // TODO: body properties? + pFS->singleElement(FSNS(XML_a, XML_bodyPr), FSEND); + + OUString sFieldType; + bool bNewParagraph; + pFS->startElement(FSNS(XML_a, XML_p), FSEND); + + for (auto& rField : rCustomLabelFields) + { + Reference<XPropertySet> xPropertySet(rField, UNO_QUERY); + chart2::DataPointCustomLabelFieldType aType = rField->getFieldType(); + sFieldType.clear(); + bNewParagraph = false; + + if (aType == chart2::DataPointCustomLabelFieldType_NEWLINE) + bNewParagraph = true; + else if (aType != chart2::DataPointCustomLabelFieldType_TEXT) + sFieldType = getFieldTypeString(aType); + + if (bNewParagraph) + { + pFS->endElement(FSNS(XML_a, XML_p)); + pFS->startElement(FSNS(XML_a, XML_p), FSEND); + continue; + } + + if (sFieldType.isEmpty()) + { + // Normal text run + pFS->startElement(FSNS(XML_a, XML_r), FSEND); + writeRunProperties(pChartExport, xPropertySet); + + pFS->startElement(FSNS(XML_a, XML_t), FSEND); + pFS->writeEscaped(rField->getString()); + pFS->endElement(FSNS(XML_a, XML_t)); + + pFS->endElement(FSNS(XML_a, XML_r)); + } + else + { + // Field + pFS->startElement(FSNS(XML_a, XML_fld), XML_id, USS(rField->getGuid()), XML_type, USS(sFieldType), FSEND); + writeRunProperties(pChartExport, xPropertySet); + + pFS->startElement(FSNS(XML_a, XML_t), FSEND); + pFS->writeEscaped(rField->getString()); + pFS->endElement(FSNS(XML_a, XML_t)); + + pFS->endElement(FSNS(XML_a, XML_fld)); + } + } + + pFS->endElement(FSNS(XML_a, XML_p)); + pFS->endElement(FSNS(XML_c, XML_rich)); + pFS->endElement(FSNS(XML_c, XML_tx)); +} + +void writeLabelProperties( const FSHelperPtr& pFS, ChartExport* pChartExport, + const uno::Reference<beans::XPropertySet>& xPropSet, const LabelPlacementParam& rLabelParam ) { if (!xPropSet.is()) return; chart2::DataPointLabel aLabel; + Sequence<Reference<chart2::XDataPointCustomLabelField>> aCustomLabelFields; sal_Int32 nLabelBorderWidth = 0; sal_Int32 nLabelBorderColor = 0x00FFFFFF; xPropSet->getPropertyValue("Label") >>= aLabel; + xPropSet->getPropertyValue("CustomLabelFields") >>= aCustomLabelFields; xPropSet->getPropertyValue("LabelBorderWidth") >>= nLabelBorderWidth; xPropSet->getPropertyValue("LabelBorderColor") >>= nLabelBorderColor; @@ -2986,6 +3082,9 @@ void writeLabelProperties( pFS->endElement(FSNS(XML_c, XML_spPr)); } + if (aCustomLabelFields.getLength() > 0) + writeCustomLabel(pFS, pChartExport, aCustomLabelFields); + if (rLabelParam.mbExport) { sal_Int32 nLabelPlacement = rLabelParam.meDefault; @@ -3081,12 +3180,12 @@ void ChartExport::exportDataLabels( // Individual label property that overwrites the baseline. pFS->startElement(FSNS(XML_c, XML_dLbl), FSEND); pFS->singleElement(FSNS(XML_c, XML_idx), XML_val, I32S(nIdx), FSEND); - writeLabelProperties(pFS, xLabelPropSet, aParam); + writeLabelProperties(pFS, this, xLabelPropSet, aParam); pFS->endElement(FSNS(XML_c, XML_dLbl)); } // Baseline label properties for all labels. - writeLabelProperties(pFS, xPropSet, aParam); + writeLabelProperties(pFS, this, xPropSet, aParam); pFS->singleElement(FSNS(XML_c, XML_showLeaderLines), XML_val, "0", diff --git a/oox/source/token/properties.txt b/oox/source/token/properties.txt index f4ca60265708..c8715881b80e 100644 --- a/oox/source/token/properties.txt +++ b/oox/source/token/properties.txt @@ -278,6 +278,7 @@ LabelBorderWidth LabelPlacement LabelPosition LabelSeparator +CustomLabelFields LayoutInfo LeftBorder LeftBorderDistance |