diff options
author | Szymon Kłos <szymon.klos@collabora.com> | 2018-01-04 22:15:32 +0100 |
---|---|---|
committer | Szymon Kłos <szymon.klos@collabora.com> | 2018-01-29 23:49:42 +0100 |
commit | 790f9abeb1a1167ad5ab84c5fb855b36669c125b (patch) | |
tree | dea7c957b67be7518d2092614b82f18148817265 /chart2/source/view | |
parent | a1f933ee2b9e23a505d937035821e9571cf4119c (diff) |
tdf#114821 import complex data labels in bar chart
* import static text & fields:
VALUE, SERIESNAME, COLUMNNAME
* text is formatted
* DataPointCustomLabelField with field type
(DataPointCustomLabelFieldType) was introduced.
* text can have many portions & multiple lines
* unit tests for import data labels with formatting
Not implemented: CELLREF field support which needs
importing some additional data from extLst
Shows custom text as a label for data points.
Change-Id: Iba8fd508eb16356b05586b93d7b8da32240d2b91
Reviewed-on: https://gerrit.libreoffice.org/48243
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Szymon Kłos <szymon.klos@collabora.com>
Diffstat (limited to 'chart2/source/view')
-rw-r--r-- | chart2/source/view/charttypes/VSeriesPlotter.cxx | 126 | ||||
-rw-r--r-- | chart2/source/view/inc/AbstractShapeFactory.hxx | 7 | ||||
-rw-r--r-- | chart2/source/view/inc/OpenglShapeFactory.hxx | 7 | ||||
-rw-r--r-- | chart2/source/view/inc/ShapeFactory.hxx | 7 | ||||
-rw-r--r-- | chart2/source/view/inc/VSeriesPlotter.hxx | 2 | ||||
-rw-r--r-- | chart2/source/view/main/OpenglShapeFactory.cxx | 12 | ||||
-rw-r--r-- | chart2/source/view/main/ShapeFactory.cxx | 94 |
7 files changed, 240 insertions, 15 deletions
diff --git a/chart2/source/view/charttypes/VSeriesPlotter.cxx b/chart2/source/view/charttypes/VSeriesPlotter.cxx index af1544b22815..23cad6ada542 100644 --- a/chart2/source/view/charttypes/VSeriesPlotter.cxx +++ b/chart2/source/view/charttypes/VSeriesPlotter.cxx @@ -56,6 +56,7 @@ #include <com/sun/star/chart/ErrorBarStyle.hpp> #include <com/sun/star/chart/TimeUnit.hpp> +#include <com/sun/star/chart2/XDataPointCustomLabelField.hpp> #include <com/sun/star/chart2/XRegressionCurveContainer.hpp> #include <com/sun/star/container/XChild.hpp> #include <com/sun/star/chart2/RelativePosition.hpp> @@ -413,9 +414,21 @@ uno::Reference< drawing::XShape > VSeriesPlotter::createDataLabel( const uno::Re , sal_Int32 nTextWidth ) { uno::Reference< drawing::XShape > xTextShape; + Sequence<uno::Reference<XDataPointCustomLabelField>> aCustomLabels; try { + const uno::Reference< css::beans::XPropertySet >& xPropertySet( + rDataSeries.getPropertiesOfPoint( nPointIndex ) ); + if( xPropertySet.is() ) + { + uno::Any aAny = xPropertySet->getPropertyValue( CHART_UNONAME_CUSTOM_LABEL_FIELDS ); + if( aAny.hasValue() ) + { + aAny >>= aCustomLabels; + } + } + awt::Point aScreenPosition2D(rScreenPosition2D); if(eAlignment==LABEL_ALIGN_LEFT) aScreenPosition2D.X -= nOffset; @@ -495,26 +508,75 @@ uno::Reference< drawing::XShape > VSeriesPlotter::createDataLabel( const uno::Re } sal_Int32 nLineCountForSymbolsize = 0; - Sequence< OUString > aTextList(3); + sal_uInt32 nTextListLength = 3; + sal_uInt32 nCustomLabelsCount = aCustomLabels.getLength(); + bool bUseCustomLabel = false; + Sequence< OUString > aTextList( nTextListLength ); + + bUseCustomLabel = nCustomLabelsCount > 0; + if( bUseCustomLabel ) { - if(pLabel->ShowCategoryName) + nTextListLength = ( nCustomLabelsCount > 3 ) ? nCustomLabelsCount : 3; + aSeparator = ""; + aTextList = Sequence< OUString >( nTextListLength ); + for( sal_uInt32 i = 0; i < nCustomLabelsCount; ++i ) { - if( m_pExplicitCategoriesProvider ) + switch( aCustomLabels[i]->getFieldType() ) { - Sequence< OUString > aCategories( m_pExplicitCategoriesProvider->getSimpleCategories() ); - if( nPointIndex >= 0 && nPointIndex < aCategories.getLength() ) + case DataPointCustomLabelFieldType_VALUE: + { + aTextList[i] = getLabelTextForValue( rDataSeries, nPointIndex, fValue, false ); + break; + } + case DataPointCustomLabelFieldType_CATEGORYNAME: + { + aTextList[i] = getCategoryName( nPointIndex ); + break; + } + case DataPointCustomLabelFieldType_SERIESNAME: { - aTextList[0] = aCategories[nPointIndex]; + OUString aRole; + if ( m_xChartTypeModel ) + aRole = m_xChartTypeModel->getRoleOfSequenceForSeriesLabel(); + uno::Reference< XDataSeries > xSeries( rDataSeries.getModel() ); + aTextList[i] = DataSeriesHelper::getDataSeriesLabel( xSeries, aRole ); + break; } + case DataPointCustomLabelFieldType_CELLREF: + { + // TODO: for now doesn't show placeholder + aTextList[i] = OUString(); + break; + } + case DataPointCustomLabelFieldType_TEXT: + { + aTextList[i] = aCustomLabels[i]->getString(); + break; + } + case DataPointCustomLabelFieldType_NEWLINE: + { + aTextList[i] = "\n"; + break; + } + default: + break; } + aCustomLabels[i]->setString( aTextList[i] ); + } + } + else + { + if( pLabel->ShowCategoryName ) + { + aTextList[0] = getCategoryName( nPointIndex ); } - if(pLabel->ShowNumber) + if( pLabel->ShowNumber ) { aTextList[1] = getLabelTextForValue(rDataSeries, nPointIndex, fValue, false); } - if(pLabel->ShowNumberInPercent) + if( pLabel->ShowNumberInPercent ) { if(fSumValue==0.0) fSumValue=1.0; @@ -524,13 +586,13 @@ uno::Reference< drawing::XShape > VSeriesPlotter::createDataLabel( const uno::Re aTextList[2] = getLabelTextForValue(rDataSeries, nPointIndex, fValue, true); } + } - for( sal_Int32 nN = 0; nN < 3; ++nN) + for( sal_Int32 nN = 0; nN < aTextList.getLength(); ++nN ) + { + if( !aTextList[nN].isEmpty() ) { - if( !aTextList[nN].isEmpty() ) - { - ++nLineCountForSymbolsize; - } + ++nLineCountForSymbolsize; } } @@ -549,7 +611,28 @@ uno::Reference< drawing::XShape > VSeriesPlotter::createDataLabel( const uno::Re // a multi-line label. bool bMultiLineLabel = ( aSeparator == "\n" ); - if( bMultiLineLabel ) + if( bUseCustomLabel ) + { + Sequence< uno::Reference< XFormattedString > > aFormattedLabels( aCustomLabels.getLength() ); + for( int i = 0; i < aFormattedLabels.getLength(); i++ ) + { + uno::Reference< XFormattedString > xString( aCustomLabels[i], uno::UNO_QUERY ); + aFormattedLabels[i] = xString; + } + + // center the text + sal_uInt32 nProperties = pPropNames->getLength(); + pPropNames->realloc( nProperties + 1 ); + pPropValues->realloc( nProperties + 1 ); + (*pPropNames)[ nProperties ] = UNO_NAME_EDIT_PARA_ADJUST; + (*pPropValues)[ nProperties ] <<= style::ParagraphAdjust_CENTER; + + // create text shape + xTextShape = AbstractShapeFactory::getOrCreateShapeFactory( m_xShapeFactory )-> + createText( xTarget_, aFormattedLabels, *pPropNames, *pPropValues, + AbstractShapeFactory::makeTransformation( aScreenPosition2D ) ); + } + else if( bMultiLineLabel ) { // prepare properties for each paragraph // we want to have the value and percent value centered respect @@ -575,7 +658,7 @@ uno::Reference< drawing::XShape > VSeriesPlotter::createDataLabel( const uno::Re { // join text list elements OUStringBuffer aText; - for( sal_Int32 nN = 0; nN < 3; ++nN) + for( sal_uInt32 nN = 0; nN < nTextListLength; ++nN) { if( !aTextList[nN].isEmpty() ) { @@ -2050,6 +2133,19 @@ VDataSeries* VSeriesPlotter::getFirstSeries() const return nullptr; } +OUString VSeriesPlotter::getCategoryName( sal_Int32 nPointIndex ) const +{ + if (m_pExplicitCategoriesProvider) + { + Sequence< OUString > aCategories(m_pExplicitCategoriesProvider->getSimpleCategories()); + if (nPointIndex >= 0 && nPointIndex < aCategories.getLength()) + { + return aCategories[nPointIndex]; + } + } + return OUString(); +} + uno::Sequence< OUString > VSeriesPlotter::getSeriesNames() const { std::vector<OUString> aRetVector; diff --git a/chart2/source/view/inc/AbstractShapeFactory.hxx b/chart2/source/view/inc/AbstractShapeFactory.hxx index 26512214341d..e281e6291ebf 100644 --- a/chart2/source/view/inc/AbstractShapeFactory.hxx +++ b/chart2/source/view/inc/AbstractShapeFactory.hxx @@ -200,6 +200,13 @@ public: , const css::uno::Any& rATransformation ) = 0; virtual css::uno::Reference< css::drawing::XShape > + createText(const css::uno::Reference< css::drawing::XShapes >& xTarget + , css::uno::Sequence< css::uno::Reference< css::chart2::XFormattedString > >& xFormattedString + , const tNameSequence& rPropNames + , const tAnySequence& rPropValues + , const css::uno::Any& rATransformation) = 0; + + virtual css::uno::Reference< css::drawing::XShape > createText( const css::uno::Reference< css::drawing::XShapes >& xTarget2D, const css::awt::Size& rSize, const css::awt::Point& rPosition, diff --git a/chart2/source/view/inc/OpenglShapeFactory.hxx b/chart2/source/view/inc/OpenglShapeFactory.hxx index 01b2223cf59c..7963068ce79e 100644 --- a/chart2/source/view/inc/OpenglShapeFactory.hxx +++ b/chart2/source/view/inc/OpenglShapeFactory.hxx @@ -151,6 +151,13 @@ public: , const css::uno::Any& rATransformation ) override; virtual css::uno::Reference< css::drawing::XShape > + createText( const css::uno::Reference< css::drawing::XShapes >& xTarget + , css::uno::Sequence< css::uno::Reference< css::chart2::XFormattedString > >& xFormattedString + , const tNameSequence& rPropNames + , const tAnySequence& rPropValues + , const css::uno::Any& rATransformation ) override; + + virtual css::uno::Reference< css::drawing::XShape > createText( const css::uno::Reference< css::drawing::XShapes >& xTarget2D, const css::awt::Size& rSize, const css::awt::Point& rPosition, diff --git a/chart2/source/view/inc/ShapeFactory.hxx b/chart2/source/view/inc/ShapeFactory.hxx index 02a75d3a0764..ec1080732142 100644 --- a/chart2/source/view/inc/ShapeFactory.hxx +++ b/chart2/source/view/inc/ShapeFactory.hxx @@ -189,6 +189,13 @@ public: , const css::uno::Any& rATransformation ) override; virtual css::uno::Reference< css::drawing::XShape > + createText(const css::uno::Reference< css::drawing::XShapes >& xTarget + , css::uno::Sequence< css::uno::Reference< css::chart2::XFormattedString > >& xFormattedString + , const tNameSequence& rPropNames + , const tAnySequence& rPropValues + , const css::uno::Any& rATransformation) override; + + virtual css::uno::Reference< css::drawing::XShape > createText( const css::uno::Reference< css::drawing::XShapes >& xTarget2D, const css::awt::Size& rSize, const css::awt::Point& rPosition, diff --git a/chart2/source/view/inc/VSeriesPlotter.hxx b/chart2/source/view/inc/VSeriesPlotter.hxx index 6702f9833420..6613596cbb74 100644 --- a/chart2/source/view/inc/VSeriesPlotter.hxx +++ b/chart2/source/view/inc/VSeriesPlotter.hxx @@ -389,6 +389,8 @@ protected: VDataSeries* getFirstSeries() const; + OUString getCategoryName( sal_Int32 nPointIndex ) const; + protected: PlottingPositionHelper* m_pMainPosHelper; diff --git a/chart2/source/view/main/OpenglShapeFactory.cxx b/chart2/source/view/main/OpenglShapeFactory.cxx index 9cb3318f7fa2..e6c4980b8017 100644 --- a/chart2/source/view/main/OpenglShapeFactory.cxx +++ b/chart2/source/view/main/OpenglShapeFactory.cxx @@ -408,6 +408,18 @@ uno::Reference< drawing::XShape > } uno::Reference< drawing::XShape > + OpenglShapeFactory::createText( const uno::Reference< drawing::XShapes >& xTarget + , uno::Sequence< uno::Reference< chart2::XFormattedString > >& rFormattedString + , const tNameSequence& rPropNames + , const tAnySequence& rPropValues + , const uno::Any& rATransformation ) +{ + dummy::DummyText* pText = new dummy::DummyText( rFormattedString[0]->getString(), rPropNames, rPropValues, + rATransformation, xTarget, 0 ); + return pText; +} + +uno::Reference< drawing::XShape > OpenglShapeFactory::createText( const uno::Reference< drawing::XShapes >& xTarget, const awt::Size& , const awt::Point& rPos, uno::Sequence< uno::Reference< chart2::XFormattedString > >& rFormattedString, diff --git a/chart2/source/view/main/ShapeFactory.cxx b/chart2/source/view/main/ShapeFactory.cxx index ad79415d6a6c..4ba77826d912 100644 --- a/chart2/source/view/main/ShapeFactory.cxx +++ b/chart2/source/view/main/ShapeFactory.cxx @@ -2266,6 +2266,100 @@ uno::Reference< drawing::XShape > } uno::Reference< drawing::XShape > + ShapeFactory::createText( const uno::Reference< drawing::XShapes >& xTarget + , uno::Sequence< uno::Reference< chart2::XFormattedString > >& xFormattedString + , const tNameSequence& rPropNames + , const tAnySequence& rPropValues + , const uno::Any& rATransformation ) +{ + if( !xTarget.is() ) + return nullptr; + + if( !xFormattedString.hasElements() ) + return nullptr; + + sal_Int32 nNumberOfParagraphs = xFormattedString.getLength(); + + bool bNotEmpty = false; + for( sal_Int32 nN = 0; nN < nNumberOfParagraphs; ++nN ) + { + if( !xFormattedString[nN]->getString().isEmpty() ) + { + bNotEmpty = true; + break; + } + } + if( !bNotEmpty ) + return nullptr; + + //create shape and add to page + uno::Reference< drawing::XShape > xShape( + m_xShapeFactory->createInstance( + "com.sun.star.drawing.TextShape" ), uno::UNO_QUERY ); + xTarget->add(xShape); + + //set paragraph properties + bNotEmpty = false; + Reference< text::XText > xText( xShape, uno::UNO_QUERY ); + if( xText.is() ) + { + // the first cursor is used for appending the next paragraph, + // after a new string has been inserted the cursor is moved at the end + // of the inserted string + // the second cursor is used for selecting the paragraph and apply the + // passed text properties + Reference< text::XTextCursor > xInsertCursor = xText->createTextCursor(); + Reference< text::XTextCursor > xSelectionCursor = xText->createTextCursor(); + if( xInsertCursor.is() && xSelectionCursor.is() ) + { + uno::Reference< beans::XPropertySet > xSelectionProp( xSelectionCursor, uno::UNO_QUERY ); + if( xSelectionProp.is() ) + { + for( sal_Int32 nN = 0; nN < nNumberOfParagraphs; ++nN ) + { + if( !xFormattedString[nN]->getString().isEmpty() ) + { + xInsertCursor->gotoEnd( false ); + xSelectionCursor->gotoEnd( false ); + xText->insertString( xInsertCursor, xFormattedString[nN]->getString(), false ); + bNotEmpty = true; + xSelectionCursor->gotoEnd( true ); // select current paragraph + uno::Reference< beans::XPropertySet > xStringProperties( xFormattedString[nN], uno::UNO_QUERY ); + PropertyMapper::setMappedProperties( xSelectionProp, xStringProperties, + PropertyMapper::getPropertyNameMapForTextShapeProperties() ); + } + } + } + } + } + + if( !bNotEmpty ) + return nullptr; + + uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY ); + if( xProp.is() ) + { + //set whole text shape properties + PropertyMapper::setMultiProperties( rPropNames, rPropValues, xProp ); + + if( rATransformation.hasValue() ) + { + //set position matrix + //the matrix needs to be set at the end behind autogrow and such position influencing properties + try + { + xProp->setPropertyValue( "Transformation", rATransformation ); + } + catch( const uno::Exception& e ) + { + SAL_WARN("chart2", "Exception caught. " << e ); + } + } + } + return xShape; +} + +uno::Reference< drawing::XShape > ShapeFactory::createText( const uno::Reference< drawing::XShapes >& xTarget, const awt::Size& rSize, const awt::Point& rPos, |