chart2/qa/extras/chart2export.cxx | 41 +++++++++++++++++++++ chart2/qa/extras/data/xlsx/invertIfNeg_bar.xlsx |binary chart2/qa/extras/data/xlsx/invertIfNeg_bubble.xlsx |binary chart2/source/inc/DataSeriesProperties.hxx | 3 + chart2/source/model/main/DataPointProperties.cxx | 7 +++ chart2/source/model/main/DataPointProperties.hxx | 1 chart2/source/model/main/DataSeriesProperties.cxx | 7 +++ chart2/source/view/charttypes/BarChart.cxx | 21 ++++++++++ chart2/source/view/charttypes/BubbleChart.cxx | 27 ++++++++++++- oox/source/drawingml/chart/seriesconverter.cxx | 7 +++ oox/source/token/properties.txt | 1 11 files changed, 112 insertions(+), 3 deletions(-)
New commits: commit 4c45ce3493e9ee842fff42228913cc11b173ca93 Author: Kurt Nordback <kurt.nordb...@protonmail.com> AuthorDate: Wed Aug 14 15:44:24 2024 -0600 Commit: Noel Grandin <noel.gran...@collabora.co.uk> CommitDate: Tue Aug 27 09:21:35 2024 +0200 tdf#90733 - support invertIfNegative for bar and bubble chart Extend the existing initial support for the OOXML invertIfNegative tag to pass the data down into bar and bubble chart rendering. Also add corresponding unit tests. This does not include a UI control to select/deselect the invert-if- negative option, nor support for export of the flag to OOXML, nor any support in ODF. Change-Id: I45b24b816edc379c9b431e86269dd5ff37977b89 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/171879 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk> diff --git a/chart2/qa/extras/chart2export.cxx b/chart2/qa/extras/chart2export.cxx index 4335ee9ff887..9a81cc0d052a 100644 --- a/chart2/qa/extras/chart2export.cxx +++ b/chart2/qa/extras/chart2export.cxx @@ -1321,6 +1321,47 @@ CPPUNIT_TEST_FIXTURE(Chart2ExportTest, testLabelStringODS) CPPUNIT_ASSERT_EQUAL(u"\"LabelName\""_ustr, aLabelString); } + +CPPUNIT_TEST_FIXTURE(Chart2ExportTest, testInvertNegative) +{ + // Bar chart + { + loadFromFile(u"xlsx/invertIfNeg_bar.xlsx"); + // make sure the import was successful + uno::Reference< chart2::XChartDocument > xChartDoc = getChartDocFromSheet( 0, mxComponent ); + CPPUNIT_ASSERT(xChartDoc.is()); + + Reference< chart2::XDataSeries > xDataSeries = getDataSeriesFromDoc( xChartDoc, 0 ); + CPPUNIT_ASSERT( xDataSeries.is() ); + + Reference< beans::XPropertySet > xPropSet( xDataSeries, UNO_QUERY_THROW ); + + bool bInvertNeg; + CPPUNIT_ASSERT( + xPropSet->getPropertyValue(u"InvertNegative"_ustr) >>= bInvertNeg); + CPPUNIT_ASSERT_EQUAL(true, bInvertNeg); + } + + // Bubble chart + { + loadFromFile(u"xlsx/invertIfNeg_bubble.xlsx"); + // make sure the import was successful + uno::Reference< chart2::XChartDocument > xChartDoc = getChartDocFromSheet( 0, mxComponent ); + CPPUNIT_ASSERT(xChartDoc.is()); + + Reference< chart2::XDataSeries > xDataSeries = getDataSeriesFromDoc( xChartDoc, 0 ); + CPPUNIT_ASSERT( xDataSeries.is() ); + + Reference< beans::XPropertySet > xPropSet( xDataSeries, UNO_QUERY_THROW ); + + bool bInvertNeg; + CPPUNIT_ASSERT( + xPropSet->getPropertyValue(u"InvertNegative"_ustr) >>= bInvertNeg); + CPPUNIT_ASSERT_EQUAL(true, bInvertNeg); + } +} + + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/qa/extras/data/xlsx/invertIfNeg_bar.xlsx b/chart2/qa/extras/data/xlsx/invertIfNeg_bar.xlsx new file mode 100644 index 000000000000..97a83b43dc2f Binary files /dev/null and b/chart2/qa/extras/data/xlsx/invertIfNeg_bar.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/invertIfNeg_bubble.xlsx b/chart2/qa/extras/data/xlsx/invertIfNeg_bubble.xlsx new file mode 100644 index 000000000000..27ae097e2eba Binary files /dev/null and b/chart2/qa/extras/data/xlsx/invertIfNeg_bubble.xlsx differ diff --git a/chart2/source/inc/DataSeriesProperties.hxx b/chart2/source/inc/DataSeriesProperties.hxx index 7d36721ef066..d0c19d07bf23 100644 --- a/chart2/source/inc/DataSeriesProperties.hxx +++ b/chart2/source/inc/DataSeriesProperties.hxx @@ -35,7 +35,8 @@ namespace chart::DataSeriesProperties PROP_DATASERIES_ATTACHED_AXIS_INDEX, PROP_DATASERIES_SHOW_LEGEND_ENTRY, PROP_DATASERIES_DELETED_LEGEND_ENTRIES, - PROP_DATASERIES_SHOW_CUSTOM_LEADERLINES + PROP_DATASERIES_SHOW_CUSTOM_LEADERLINES, + PROP_DATASERIES_INVERT_NEGATIVE }; void AddPropertiesToVector( diff --git a/chart2/source/model/main/DataPointProperties.cxx b/chart2/source/model/main/DataPointProperties.cxx index d86128b7593e..53f88600214f 100644 --- a/chart2/source/model/main/DataPointProperties.cxx +++ b/chart2/source/model/main/DataPointProperties.cxx @@ -340,6 +340,12 @@ void DataPointProperties::AddPropertiesToVector( beans::PropertyAttribute::BOUND | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "InvertNegative", + PROP_DATAPOINT_INVERT_NEGATIVE, + cppu::UnoType<bool>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + // statistics rOutProperties.emplace_back( CHART_UNONAME_ERRORBAR_X, PROP_DATAPOINT_ERROR_BAR_X, @@ -513,6 +519,7 @@ void DataPointProperties::AddDefaultsToMap( PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DATAPOINT_PERCENT_DIAGONAL, sal_Int16(0) ); PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DATAPOINT_TEXT_ROTATION, 0.0 ); + PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DATAPOINT_INVERT_NEGATIVE, false ); PropertyHelper::setPropertyValueDefault(rOutMap, PROP_DATAPOINT_LINK_NUMBERFORMAT_TO_SOURCE, true); diff --git a/chart2/source/model/main/DataPointProperties.hxx b/chart2/source/model/main/DataPointProperties.hxx index 1689322148d8..fe1969bc5f15 100644 --- a/chart2/source/model/main/DataPointProperties.hxx +++ b/chart2/source/model/main/DataPointProperties.hxx @@ -69,6 +69,7 @@ namespace DataPointProperties PROP_DATAPOINT_LABEL_PLACEMENT, PROP_DATAPOINT_REFERENCE_DIAGRAM_SIZE, PROP_DATAPOINT_TEXT_ROTATION, + PROP_DATAPOINT_INVERT_NEGATIVE, // statistics PROP_DATAPOINT_ERROR_BAR_X, diff --git a/chart2/source/model/main/DataSeriesProperties.cxx b/chart2/source/model/main/DataSeriesProperties.cxx index e6d40feb5ab6..c558b3820cab 100644 --- a/chart2/source/model/main/DataSeriesProperties.cxx +++ b/chart2/source/model/main/DataSeriesProperties.cxx @@ -75,6 +75,12 @@ void DataSeriesProperties::AddPropertiesToVector( beans::PropertyAttribute::BOUND | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "InvertNegative", + PROP_DATASERIES_INVERT_NEGATIVE, + cppu::UnoType<sal_Bool>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + // add properties of service DataPointProperties DataPointProperties::AddPropertiesToVector( rOutProperties ); } @@ -87,6 +93,7 @@ void DataSeriesProperties::AddDefaultsToMap( PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DATASERIES_ATTACHED_AXIS_INDEX, sal_Int32(0) ); PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DATASERIES_SHOW_LEGEND_ENTRY, true ); PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DATASERIES_SHOW_CUSTOM_LEADERLINES, true ); + PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DATASERIES_INVERT_NEGATIVE, false ); // PROP_DATASERIES_ATTRIBUTED_DATA_POINTS has no default diff --git a/chart2/source/view/charttypes/BarChart.cxx b/chart2/source/view/charttypes/BarChart.cxx index 8babf67271fd..38a497707d22 100644 --- a/chart2/source/view/charttypes/BarChart.cxx +++ b/chart2/source/view/charttypes/BarChart.cxx @@ -708,6 +708,27 @@ void BarChart::doXSlot( if( std::isnan( fLogicBarHeight )) //no value at this category continue; + // Handle "invert negative" + { + bool bInvertNeg(false); + uno::Reference< beans::XPropertySet > xPointProperties = pSeries->getPropertiesOfPoint(nPointIndex); + + // check point properties, and if none then series properties + try { + xPointProperties->getPropertyValue(u"InvertNegative"_ustr) >>= bInvertNeg; + } catch (const uno::Exception&) + { + uno::Reference< beans::XPropertySet > xSeriesProperties = + pSeries->getPropertiesOfSeries(); + try { + xSeriesProperties->getPropertyValue(u"InvertNegative"_ustr) >>= bInvertNeg; + } catch (const uno::Exception&) + {} + } + + if (bInvertNeg) fLogicBarHeight = fabs(fLogicBarHeight); + } + double fLogicValueForLabeDisplay = fLogicBarHeight; fLogicBarHeight-=fBaseValue; diff --git a/chart2/source/view/charttypes/BubbleChart.cxx b/chart2/source/view/charttypes/BubbleChart.cxx index fb7b3fe6f33d..88f39b3a5235 100644 --- a/chart2/source/view/charttypes/BubbleChart.cxx +++ b/chart2/source/view/charttypes/BubbleChart.cxx @@ -217,8 +217,31 @@ void BubbleChart::createShapes() double fLogicY = pSeries->getYValue(nIndex); double fBubbleSize = pSeries->getBubble_Size( nIndex ); - if( fBubbleSize<0.0 ) - continue; + bool bInvertNeg(false); + uno::Reference< beans::XPropertySet > xPointProperties = + pSeries->getPropertiesOfPoint(nIndex); + + // check point properties, and if none then series + // properties + try { + xPointProperties->getPropertyValue(u"InvertNegative"_ustr) >>= bInvertNeg; + } catch (const uno::Exception&) + { + uno::Reference< beans::XPropertySet > xSeriesProperties = + pSeries->getPropertiesOfSeries(); + try { + xSeriesProperties->getPropertyValue(u"InvertNegative"_ustr) >>= bInvertNeg; + } catch (const uno::Exception&) + {} + } + + if( fBubbleSize<0.0 ) { + if (bInvertNeg) { + fBubbleSize = -fBubbleSize; + } else { + continue; + } + } if( fBubbleSize == 0.0 || std::isnan(fBubbleSize) ) continue; diff --git a/oox/source/drawingml/chart/seriesconverter.cxx b/oox/source/drawingml/chart/seriesconverter.cxx index b3c8b51c16b9..efa7f303662e 100644 --- a/oox/source/drawingml/chart/seriesconverter.cxx +++ b/oox/source/drawingml/chart/seriesconverter.cxx @@ -765,6 +765,11 @@ void DataPointConverter::convertFromModel( const Reference< XDataSeries >& rxDat if( mrModel.monExplosion.has_value() && mrModel.monExplosion.value() != rSeries.mnExplosion ) rTypeGroup.convertPieExplosion( aPropSet, mrModel.monExplosion.value() ); + // data point invert negative + if( mrModel.mbInvertNeg != rSeries.mbInvertNeg ) { + aPropSet.setProperty( PROP_InvertNegative, mrModel.mbInvertNeg); + } + // point formatting if( mrModel.mxShapeProp.is() ) { @@ -873,6 +878,8 @@ Reference< XDataSeries > SeriesConverter::createDataSeries( const TypeGroupConve rTypeGroup.convertBarGeometry( aSeriesProp, mrModel.monShape.value_or( rTypeGroup.getModel().mnShape ) ); // pie explosion (restricted to [0%,100%] in Chart2) rTypeGroup.convertPieExplosion( aSeriesProp, mrModel.mnExplosion ); + // invert if negative + aSeriesProp.setProperty(PROP_InvertNegative, mrModel.mbInvertNeg); // series formatting ObjectFormatter& rFormatter = getFormatter(); diff --git a/oox/source/token/properties.txt b/oox/source/token/properties.txt index f68726957df9..6140d192b55d 100644 --- a/oox/source/token/properties.txt +++ b/oox/source/token/properties.txt @@ -290,6 +290,7 @@ InputMessage InputTitle InterceptValue InvalidUrl +InvertNegative IsActive IsAdjustHeightEnabled IsCaseSensitive