summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustin Luth <justin.luth@collabora.com>2024-01-25 11:57:40 -0500
committerMiklos Vajna <vmiklos@collabora.com>2024-01-30 10:40:43 +0100
commita77403d11a60ebe6aeb33d9b6ae611412d9ab1cc (patch)
treeeccb24a43aad7df75620a7b49b2d7e2a4b3a2db7
parent2048db4dc8ee6edb231a9109257846975a6f7834 (diff)
tdf#146756 pie chart2 import: use manualLayout Width for pie chart labels
... and use a compatible 1/5 width if not specified. This patch depends on the previous oox patch (commit 301e27cbebf7d6e4c9b82290d7cd555c43f0c999) which actually reads the width into the model. Fixes a 7.2 regression from commit b0068342398786ca50304260434a18880dddf74d author Tünde Tóth on Wed Dec 16 18:26:26 2020 +0100 tdf#138777 pie chart: improve long data label width and is basically a re-write of 7.1's commit 20da1a5dd37c7edac620566c992d5a53b23a5f12 author Tünde Tóth <toth.tunde@nisz.hu> on Fri Oct 09 09:24:18 2020 +0200 tdf#134978 Chart OOXML Import: fix pie chart label custom position This is very risky, but then ANYTHING changing chart2 is risky. There were a lot of changes made in 7.1, and they all invited regressions. However, our chart implementation is not in a good state, and certainly is not very interoperable, so it is worth taking the risk. Anything dealing with manualLayout at this point should have originated as a pptx, so forcing a compatible max width should be fairly safe. It probably isn't actually all that risky after all. largely copied code from commit 4223ff2be69f03e571464b0b09ad0d278918631b Author: Balazs Varga on Wed Jan 15 16:31:35 2020 +0100 tdf#48436 Chart: add CustomLabelPosition UNO API property Fortunately this all goes away after a round-trip since custom label placement is lost on export to OOXML, and that really helps to reduce the risk. make CppunitTest_chart2_import CPPUNIT_TEST_NAME=testTdf146487 Change-Id: I9722fc6c759c15ac3924780e6fc124f02fba07e1 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162590 Tested-by: Jenkins Reviewed-by: Justin Luth <jluth@mail.com> Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
-rw-r--r--chart2/qa/extras/chart2import.cxx22
-rw-r--r--chart2/source/controller/itemsetwrapper/DataPointItemConverter.cxx1
-rw-r--r--chart2/source/controller/itemsetwrapper/TextLabelItemConverter.cxx1
-rw-r--r--chart2/source/model/main/DataPointProperties.cxx6
-rw-r--r--chart2/source/model/main/DataPointProperties.hxx3
-rw-r--r--chart2/source/tools/DataSeriesHelper.cxx3
-rw-r--r--chart2/source/view/charttypes/PieChart.cxx38
-rw-r--r--chart2/source/view/inc/VDataSeries.hxx1
-rw-r--r--chart2/source/view/main/VDataSeries.cxx21
-rw-r--r--offapi/com/sun/star/chart2/DataPointProperties.idl6
-rw-r--r--oox/source/drawingml/chart/seriesconverter.cxx3
-rw-r--r--oox/source/token/properties.txt1
12 files changed, 92 insertions, 14 deletions
diff --git a/chart2/qa/extras/chart2import.cxx b/chart2/qa/extras/chart2import.cxx
index fc8042a38393..b23e048c6949 100644
--- a/chart2/qa/extras/chart2import.cxx
+++ b/chart2/qa/extras/chart2import.cxx
@@ -29,6 +29,7 @@
#include <com/sun/star/chart2/data/XTextualDataSequence.hpp>
#include <com/sun/star/chart/DataLabelPlacement.hpp>
#include <com/sun/star/text/XTextRange.hpp>
+#include <com/sun/star/qa/XDumper.hpp>
#include <iterator>
#include <com/sun/star/util/Color.hpp>
@@ -37,6 +38,8 @@
#include <basegfx/utils/gradienttools.hxx>
#include <docmodel/uno/UnoGradientTools.hxx>
+namespace
+{
class Chart2ImportTest : public ChartTest
{
public:
@@ -46,6 +49,11 @@ protected:
void testTransparentBackground(std::u16string_view filename);
};
+OUString getShapeDump(css::uno::Reference<css::chart::XChartDocument> const& doc)
+{
+ return css::uno::Reference<css::qa::XDumper>(doc, css::uno::UNO_QUERY_THROW)->dump("shapes");
+}
+
// error bar import
// split method up into smaller chunks for more detailed tests
CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testFdo60083)
@@ -187,7 +195,7 @@ CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testSteppedLines)
}
}
-static uno::Sequence < OUString > getChartColumnDescriptions( uno::Reference< chart::XChartDocument > const & xChart1Doc)
+uno::Sequence < OUString > getChartColumnDescriptions( uno::Reference< chart::XChartDocument > const & xChart1Doc)
{
CPPUNIT_ASSERT(xChart1Doc.is());
uno::Reference< chart::XChartDataArray > xChartData ( xChart1Doc->getData(), UNO_QUERY_THROW);
@@ -1988,6 +1996,17 @@ CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testTdf146487)
Reference<chart2::XTitled> xTitled(xChartDoc, uno::UNO_QUERY_THROW);
uno::Reference<chart2::XTitle> xTitle = xTitled->getTitleObject();
CPPUNIT_ASSERT_MESSAGE("chart doc should not have a title", !xTitle.is());
+
+ // tdf#146756 use manualLayout Width that was provided (so Green; $7,654,321 is not wrapped
+ if (!IsDefaultDPI())
+ return;
+ uno::Reference<chart::XChartDocument> xDoc = getChartDocFromDrawImpress(0, 0);
+ OString aXmlDump = OUStringToOString(getShapeDump(xDoc), RTL_TEXTENCODING_UTF8);
+ xmlDocUniquePtr pXmlDoc(xmlParseDoc(reinterpret_cast<const xmlChar*>(aXmlDump.getStr())));
+ OString aPath("//XShape[@text='Green; $7,654,321 ']"_ostr);
+ assertXPath(pXmlDoc, aPath, 1);
+ // Expected - 1 line tall(371), not 4 lines(1481).
+ CPPUNIT_ASSERT_EQUAL(OUString("371"), getXPath(pXmlDoc, aPath, "sizeY"_ostr));
}
CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testFixedSizeBarChartVeryLongLabel)
@@ -2248,6 +2267,7 @@ CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testPieChartPlotAreaMarginWithAutomaticLa
}
}
+} // end of anonymous namespace
CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/itemsetwrapper/DataPointItemConverter.cxx b/chart2/source/controller/itemsetwrapper/DataPointItemConverter.cxx
index 2b194051a1f2..93490438d753 100644
--- a/chart2/source/controller/itemsetwrapper/DataPointItemConverter.cxx
+++ b/chart2/source/controller/itemsetwrapper/DataPointItemConverter.cxx
@@ -460,6 +460,7 @@ bool DataPointItemConverter::ApplySpecialItem(
{
GetPropertySet()->setPropertyValue("LabelPlacement", uno::Any(nNew));
GetPropertySet()->setPropertyValue("CustomLabelPosition", uno::Any());
+ GetPropertySet()->setPropertyValue("CustomLabelSize", uno::Any());
bChanged = true;
}
}
diff --git a/chart2/source/controller/itemsetwrapper/TextLabelItemConverter.cxx b/chart2/source/controller/itemsetwrapper/TextLabelItemConverter.cxx
index 0f4019546592..10c1f9373547 100644
--- a/chart2/source/controller/itemsetwrapper/TextLabelItemConverter.cxx
+++ b/chart2/source/controller/itemsetwrapper/TextLabelItemConverter.cxx
@@ -401,6 +401,7 @@ bool TextLabelItemConverter::ApplySpecialItem( sal_uInt16 nWhichId, const SfxIte
{
GetPropertySet()->setPropertyValue("LabelPlacement", uno::Any(nNew));
GetPropertySet()->setPropertyValue("CustomLabelPosition", uno::Any());
+ GetPropertySet()->setPropertyValue("CustomLabelSize", uno::Any());
bChanged = true;
}
}
diff --git a/chart2/source/model/main/DataPointProperties.cxx b/chart2/source/model/main/DataPointProperties.cxx
index 819336edd9c4..c27407c98fca 100644
--- a/chart2/source/model/main/DataPointProperties.cxx
+++ b/chart2/source/model/main/DataPointProperties.cxx
@@ -30,6 +30,7 @@
#include <com/sun/star/drawing/BitmapMode.hpp>
#include <com/sun/star/drawing/RectanglePoint.hpp>
#include <com/sun/star/chart2/RelativePosition.hpp>
+#include <com/sun/star/chart2/RelativeSize.hpp>
#include <com/sun/star/chart2/XDataPointCustomLabelField.hpp>
#include <com/sun/star/chart2/DataPointGeometry3D.hpp>
#include <com/sun/star/chart2/DataPointLabel.hpp>
@@ -447,6 +448,11 @@ void DataPointProperties::AddPropertiesToVector(
cppu::UnoType<chart2::RelativePosition>::get(),
beans::PropertyAttribute::BOUND
| beans::PropertyAttribute::MAYBEVOID );
+
+ rOutProperties.emplace_back("CustomLabelSize", PROP_DATAPOINT_LABEL_CUSTOM_SIZE,
+ cppu::UnoType<chart2::RelativeSize>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID);
}
void DataPointProperties::AddDefaultsToMap(
diff --git a/chart2/source/model/main/DataPointProperties.hxx b/chart2/source/model/main/DataPointProperties.hxx
index ada7907b888f..1689322148d8 100644
--- a/chart2/source/model/main/DataPointProperties.hxx
+++ b/chart2/source/model/main/DataPointProperties.hxx
@@ -87,7 +87,8 @@ namespace DataPointProperties
PROP_DATAPOINT_LABEL_BORDER_DASH_NAME,
PROP_DATAPOINT_LABEL_BORDER_TRANS,
PROP_DATAPOINT_CUSTOM_LABEL_FIELDS,
- PROP_DATAPOINT_LABEL_CUSTOM_POS
+ PROP_DATAPOINT_LABEL_CUSTOM_POS,
+ PROP_DATAPOINT_LABEL_CUSTOM_SIZE
// additionally some properties from ::chart::LineProperties
};
diff --git a/chart2/source/tools/DataSeriesHelper.cxx b/chart2/source/tools/DataSeriesHelper.cxx
index dba33728b5aa..a6efbda3a1e9 100644
--- a/chart2/source/tools/DataSeriesHelper.cxx
+++ b/chart2/source/tools/DataSeriesHelper.cxx
@@ -467,7 +467,10 @@ void setPropertyAlsoToAllAttributedDataPoints( const rtl::Reference< ::chart::Da
continue;
xPointProp->setPropertyValue( rPropertyName, rPropertyValue );
if( rPropertyName == "LabelPlacement" )
+ {
xPointProp->setPropertyValue("CustomLabelPosition", uno::Any());
+ xPointProp->setPropertyValue("CustomLabelSize", uno::Any());
+ }
}
}
}
diff --git a/chart2/source/view/charttypes/PieChart.cxx b/chart2/source/view/charttypes/PieChart.cxx
index 5e3a6dcaad17..93221b468473 100644
--- a/chart2/source/view/charttypes/PieChart.cxx
+++ b/chart2/source/view/charttypes/PieChart.cxx
@@ -324,14 +324,18 @@ void PieChart::createTextLabelShape(
sal_Int32 nLabelPlacement = rSeries.getLabelPlacement(
nPointIndex, m_xChartTypeModel, m_aPosHelper.isSwapXAndY());
+ // has an X/Y offset (relative to the OUTSIDE label default position) been provided?
+ const bool bHasCustomLabelPlacement = nLabelPlacement == css::chart::DataLabelPlacement::CUSTOM;
+ if (bHasCustomLabelPlacement)
+ nLabelPlacement = css::chart::DataLabelPlacement::OUTSIDE;
+
///when the placement is of `AVOID_OVERLAP` type a later rearrangement of
///the label position is allowed; the `createTextLabelShape` treats the
///`AVOID_OVERLAP` as if it was of `CENTER` type;
double nVal = rSeries.getYValue(nPointIndex);
//AVOID_OVERLAP is in fact "Best fit" in the UI.
- bool bMovementAllowed = nLabelPlacement == css::chart::DataLabelPlacement::AVOID_OVERLAP
- || nLabelPlacement == css::chart::DataLabelPlacement::CUSTOM;
+ bool bMovementAllowed = nLabelPlacement == css::chart::DataLabelPlacement::AVOID_OVERLAP;
if( bMovementAllowed )
nLabelPlacement = css::chart::DataLabelPlacement::CENTER;
@@ -398,14 +402,26 @@ void PieChart::createTextLabelShape(
// set the maximum text width to be used when text wrapping is enabled
double fTextMaximumFrameWidth = 0.8 * fPieRadius;
- if (nLabelPlacement == css::chart::DataLabelPlacement::OUTSIDE
- && m_aAvailableOuterRect.getWidth())
+ if (m_aAvailableOuterRect.getWidth())
{
- if ((fAngleDegree >= 67.5 && fAngleDegree <= 112.5)
- || (fAngleDegree >= 247.5 && fAngleDegree <= 292.5))
- fTextMaximumFrameWidth = m_aAvailableOuterRect.getWidth() / 3.0;
- else
- fTextMaximumFrameWidth = 0.85 * (m_aAvailableOuterRect.getWidth() / 2.0 - fPieRadius);
+ if (bHasCustomLabelPlacement)
+ {
+ // if a custom width has been provided, then use that of course,
+ // otherwise use the interoperability-compliant 1/5 of the chart space as max width
+ const awt::Size aCustomSize = rSeries.getLabelCustomSize(nPointIndex);
+ if (aCustomSize.Width > 0)
+ fTextMaximumFrameWidth = aCustomSize.Width;
+ else
+ fTextMaximumFrameWidth = m_aAvailableOuterRect.getWidth() / 5.0;
+ }
+ else if (nLabelPlacement == css::chart::DataLabelPlacement::OUTSIDE)
+ {
+ if ((fAngleDegree >= 67.5 && fAngleDegree <= 112.5)
+ || (fAngleDegree >= 247.5 && fAngleDegree <= 292.5))
+ fTextMaximumFrameWidth = m_aAvailableOuterRect.getWidth() / 3.0;
+ else
+ fTextMaximumFrameWidth = 0.85 * (m_aAvailableOuterRect.getWidth() / 2.0 - fPieRadius);
+ }
}
sal_Int32 nTextMaximumFrameWidth = ceil(fTextMaximumFrameWidth);
@@ -430,9 +446,7 @@ void PieChart::createTextLabelShape(
* First off the routine try to place the label inside the related pie slice,
* if this is not possible the label is placed outside.
*/
- if (rSeries.getLabelPlacement(nPointIndex, m_xChartTypeModel, m_aPosHelper.isSwapXAndY())
- == css::chart::DataLabelPlacement::CUSTOM
- || !performLabelBestFitInnerPlacement(rParam, aPieLabelInfo))
+ if (!performLabelBestFitInnerPlacement(rParam, aPieLabelInfo))
{
if (m_aAvailableOuterRect.getWidth())
{
diff --git a/chart2/source/view/inc/VDataSeries.hxx b/chart2/source/view/inc/VDataSeries.hxx
index 65f7247bc197..72f5fca80089 100644
--- a/chart2/source/view/inc/VDataSeries.hxx
+++ b/chart2/source/view/inc/VDataSeries.hxx
@@ -112,6 +112,7 @@ public:
css::awt::Point getLabelPosition( css::awt::Point aTextShapePos, sal_Int32 nPointIndex ) const;
bool isLabelCustomPos( sal_Int32 nPointIndex ) const;
+ css::awt::Size getLabelCustomSize(sal_Int32 nPointIndex) const;
css::uno::Reference<css::beans::XPropertySet> getPropertiesOfPoint( sal_Int32 index ) const;
diff --git a/chart2/source/view/main/VDataSeries.cxx b/chart2/source/view/main/VDataSeries.cxx
index 845e6d6ef0db..455c991b9f89 100644
--- a/chart2/source/view/main/VDataSeries.cxx
+++ b/chart2/source/view/main/VDataSeries.cxx
@@ -36,6 +36,7 @@
#include <com/sun/star/chart2/Symbol.hpp>
#include <com/sun/star/chart2/XRegressionCurveCalculator.hpp>
#include <com/sun/star/chart2/RelativePosition.hpp>
+#include <com/sun/star/chart2/RelativeSize.hpp>
#include <osl/diagnose.h>
#include <tools/color.hxx>
@@ -645,6 +646,26 @@ bool VDataSeries::isLabelCustomPos(sal_Int32 nPointIndex) const
return bCustom;
}
+awt::Size VDataSeries::getLabelCustomSize(sal_Int32 nPointIndex) const
+{
+ awt::Size aSize(-1, -1);
+ try
+ {
+ RelativeSize aCustomLabelSize;
+ const uno::Reference<beans::XPropertySet> xPointProps(getPropertiesOfPoint(nPointIndex));
+ if (xPointProps.is() && (xPointProps->getPropertyValue("CustomLabelSize") >>= aCustomLabelSize))
+ {
+ aSize.Width = static_cast<sal_Int32>(aCustomLabelSize.Primary * m_aReferenceSize.Width);
+ aSize.Height = static_cast<sal_Int32>(aCustomLabelSize.Secondary * m_aReferenceSize.Height);
+ }
+ }
+ catch (const uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ return aSize;
+}
+
double VDataSeries::getMinimumofAllDifferentYValues( sal_Int32 index ) const
{
double fMin = std::numeric_limits<double>::infinity();
diff --git a/offapi/com/sun/star/chart2/DataPointProperties.idl b/offapi/com/sun/star/chart2/DataPointProperties.idl
index b2dd1163967a..7fe64e77ad9d 100644
--- a/offapi/com/sun/star/chart2/DataPointProperties.idl
+++ b/offapi/com/sun/star/chart2/DataPointProperties.idl
@@ -317,6 +317,12 @@ service DataPointProperties
@since LibreOffice 7.0
*/
[optional, maybevoid, property] ::com::sun::star::chart2::RelativePosition CustomLabelPosition;
+
+ /** Custom size associated with the CUSTOM label placement.
+
+ @since LibreOffice 24.8
+ */
+ [optional, maybevoid, property] ::com::sun::star::chart2::RelativeSize CustomLabelSize;
};
} ; // chart2
diff --git a/oox/source/drawingml/chart/seriesconverter.cxx b/oox/source/drawingml/chart/seriesconverter.cxx
index db3916b74f63..2d07f26493ef 100644
--- a/oox/source/drawingml/chart/seriesconverter.cxx
+++ b/oox/source/drawingml/chart/seriesconverter.cxx
@@ -21,6 +21,7 @@
#include <com/sun/star/chart/DataLabelPlacement.hpp>
#include <com/sun/star/chart2/RelativePosition.hpp>
+#include <com/sun/star/chart2/RelativeSize.hpp>
#include <com/sun/star/chart/ErrorBarStyle.hpp>
#include <com/sun/star/chart2/DataPointLabel.hpp>
#include <com/sun/star/drawing/Hatch.hpp>
@@ -291,6 +292,8 @@ void DataLabelConverter::convertFromModel( const Reference< XDataSeries >& rxDat
{
RelativePosition aPos(mrModel.mxLayout->mfX, mrModel.mxLayout->mfY, css::drawing::Alignment_TOP_LEFT);
aPropSet.setProperty(PROP_CustomLabelPosition, aPos);
+ const RelativeSize aSize(mrModel.mxLayout->mfW, mrModel.mxLayout->mfH);
+ aPropSet.setProperty(PROP_CustomLabelSize, aSize);
sal_Int32 nPlacement = -1;
if (bIsPie && aPropSet.getProperty(nPlacement, PROP_LabelPlacement)
&& nPlacement == css::chart::DataLabelPlacement::AVOID_OVERLAP)
diff --git a/oox/source/token/properties.txt b/oox/source/token/properties.txt
index b6fa29c090fe..a8764a432b5d 100644
--- a/oox/source/token/properties.txt
+++ b/oox/source/token/properties.txt
@@ -123,6 +123,7 @@ CursorPositionY
CurveName
CurveStyle
CustomLabelPosition
+CustomLabelSize
CustomShapeGeometry
D3DSceneAmbientColor
D3DSceneLightColor2