diff options
author | Tünde Tóth <toth.tunde@nisz.hu> | 2020-12-16 11:29:48 +0100 |
---|---|---|
committer | László Németh <nemeth@numbertext.org> | 2020-12-28 11:55:40 +0100 |
commit | f22b77f204e433004aeb5fc2885881c03a62aa70 (patch) | |
tree | 862351744f9d245e1b004ceefcb188227a89d478 /chart2 | |
parent | bd51df8e4e267cdad369af402bb243cb3ed222f1 (diff) |
tdf#121281 pie chart: improve data label position
to avoid chart distortion.
Move the data label to inside the chart area when it
goes outside the border.
Change-Id: I78669ed601f28129944ac8f61c6478d386322b76
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/107829
Tested-by: Jenkins
Tested-by: László Németh <nemeth@numbertext.org>
Reviewed-by: László Németh <nemeth@numbertext.org>
Diffstat (limited to 'chart2')
-rw-r--r-- | chart2/qa/extras/chart2import.cxx | 21 | ||||
-rw-r--r-- | chart2/qa/extras/data/xlsx/incorrect_label_position.xlsx | bin | 0 -> 14112 bytes | |||
-rw-r--r-- | chart2/source/view/charttypes/PieChart.cxx | 101 | ||||
-rw-r--r-- | chart2/source/view/inc/VSeriesPlotter.hxx | 2 |
4 files changed, 87 insertions, 37 deletions
diff --git a/chart2/qa/extras/chart2import.cxx b/chart2/qa/extras/chart2import.cxx index 9bb042fb6867..943cbd57ea99 100644 --- a/chart2/qa/extras/chart2import.cxx +++ b/chart2/qa/extras/chart2import.cxx @@ -171,6 +171,7 @@ public: void testTdf137734(); void testTdf137874(); void testTdfCustomShapePos(); + void testTdf121281(); CPPUNIT_TEST_SUITE(Chart2ImportTest); CPPUNIT_TEST(Fdo60083); @@ -291,6 +292,7 @@ public: CPPUNIT_TEST(testTdf137734); CPPUNIT_TEST(testTdf137874); CPPUNIT_TEST(testTdfCustomShapePos); + CPPUNIT_TEST(testTdf121281); CPPUNIT_TEST_SUITE_END(); @@ -2802,6 +2804,25 @@ void Chart2ImportTest::testTdfCustomShapePos() } } +void Chart2ImportTest::testTdf121281() +{ + load("/chart2/qa/extras/data/xlsx/", "incorrect_label_position.xlsx"); + Reference<chart::XChartDocument> xChartDoc(getChartDocFromSheet(0, mxComponent), + UNO_QUERY_THROW); + Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xChartDoc, UNO_QUERY_THROW); + Reference<drawing::XDrawPage> xDrawPage(xDrawPageSupplier->getDrawPage(), UNO_SET_THROW); + Reference<drawing::XShapes> xShapes(xDrawPage->getByIndex(0), UNO_QUERY_THROW); + Reference<drawing::XShape> xDataPointLabel( + getShapeByName(xShapes, + "CID/MultiClick/CID/D=0:CS=0:CT=0:Series=0:DataLabels=:DataLabel=0"), + UNO_SET_THROW); + + CPPUNIT_ASSERT(xDataPointLabel.is()); + awt::Point aLabelPosition = xDataPointLabel->getPosition(); + // This failed, if the data label flowed out of the chart area. + CPPUNIT_ASSERT_GREATEREQUAL(static_cast<sal_Int32>(0), aLabelPosition.Y); +} + CPPUNIT_TEST_SUITE_REGISTRATION(Chart2ImportTest); CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/chart2/qa/extras/data/xlsx/incorrect_label_position.xlsx b/chart2/qa/extras/data/xlsx/incorrect_label_position.xlsx Binary files differnew file mode 100644 index 000000000000..4f133b558116 --- /dev/null +++ b/chart2/qa/extras/data/xlsx/incorrect_label_position.xlsx diff --git a/chart2/source/view/charttypes/PieChart.cxx b/chart2/source/view/charttypes/PieChart.cxx index 3b61cb9c46e3..e77a7964ee71 100644 --- a/chart2/source/view/charttypes/PieChart.cxx +++ b/chart2/source/view/charttypes/PieChart.cxx @@ -468,49 +468,78 @@ void PieChart::createTextLabelShape( } bool bShowLeaderLine = rSeries.getPropertiesOfSeries() - ->getPropertyValue("ShowCustomLeaderLines") - .get<sal_Bool>(); - if (m_bPieLabelsAllowToMove && rSeries.isLabelCustomPos(nPointIndex) && bShowLeaderLine) + ->getPropertyValue("ShowCustomLeaderLines") + .get<sal_Bool>(); + if (m_bPieLabelsAllowToMove) { - sal_Int32 nX1 = aPieLabelInfo.aOuterPosition.getX(); - sal_Int32 nY1 = aPieLabelInfo.aOuterPosition.getY(); - sal_Int32 nX2 = nX1; - sal_Int32 nY2 = nY1; ::basegfx::B2IRectangle aRect(lcl_getRect(aPieLabelInfo.xLabelGroupShape)); - if (nX1 < aRect.getMinX()) - nX2 = aRect.getMinX(); - else if (nX1 > aRect.getMaxX()) - nX2 = aRect.getMaxX(); - - if (nY1 < aRect.getMinY()) - nY2 = aRect.getMinY(); - else if (nY1 > aRect.getMaxY()) - nY2 = aRect.getMaxY(); + sal_Int32 nPageWidth = m_aPageReferenceSize.Width; + sal_Int32 nPageHeight = m_aPageReferenceSize.Height; + + // the data label should be inside the chart area + awt::Point aShapePos = aPieLabelInfo.xLabelGroupShape->getPosition(); + if (aRect.getMinX() < 0) + aPieLabelInfo.xLabelGroupShape->setPosition( + awt::Point(aShapePos.X - aRect.getMinX(), aShapePos.Y)); + if (aRect.getMinY() < 0) + aPieLabelInfo.xLabelGroupShape->setPosition( + awt::Point(aShapePos.X, aShapePos.Y - aRect.getMinY())); + if (aRect.getMaxX() > nPageWidth) + aPieLabelInfo.xLabelGroupShape->setPosition( + awt::Point(aShapePos.X - (aRect.getMaxX() - nPageWidth), aShapePos.Y)); + if (aRect.getMaxY() > nPageHeight) + aPieLabelInfo.xLabelGroupShape->setPosition( + awt::Point(aShapePos.X, aShapePos.Y - (aRect.getMaxY() - nPageHeight))); + + if (rSeries.isLabelCustomPos(nPointIndex) && bShowLeaderLine) + { + sal_Int32 nX1 = aPieLabelInfo.aOuterPosition.getX(); + sal_Int32 nY1 = aPieLabelInfo.aOuterPosition.getY(); + sal_Int32 nX2 = nX1; + sal_Int32 nY2 = nY1; + if (nX1 < aRect.getMinX()) + nX2 = aRect.getMinX(); + else if (nX1 > aRect.getMaxX()) + nX2 = aRect.getMaxX(); - sal_Int32 nSquaredDistanceFromOrigin - = (nX2 - aOrigin.X) * (nX2 - aOrigin.X) + (nY2 - aOrigin.Y) * (nY2 - aOrigin.Y); + if (nY1 < aRect.getMinY()) + nY2 = aRect.getMinY(); + else if (nY1 > aRect.getMaxY()) + nY2 = aRect.getMaxY(); - // tdf#138018 Don't show leader line when custom positioned data label is inside pie chart - if (nSquaredDistanceFromOrigin > fSquaredPieRadius) - { - drawing::PointSequenceSequence aPoints(1); - aPoints[0].realloc(2); - aPoints[0][0].X = nX1; - aPoints[0][0].Y = nY1; - aPoints[0][1].X = nX2; - aPoints[0][1].Y = nY2; + sal_Int32 nSquaredDistanceFromOrigin + = (nX2 - aOrigin.X) * (nX2 - aOrigin.X) + (nY2 - aOrigin.Y) * (nY2 - aOrigin.Y); - uno::Reference<beans::XPropertySet> xProp(aPieLabelInfo.xTextShape, uno::UNO_QUERY); - VLineProperties aVLineProperties; - if (xProp.is()) + // tdf#138018 Don't show leader line when custom positioned data label is inside pie chart + if (nSquaredDistanceFromOrigin > fSquaredPieRadius) { - sal_Int32 nColor = 0; - xProp->getPropertyValue("CharColor") >>= nColor; - //automatic font color does not work for lines -> fallback to black - if (nColor != -1) - aVLineProperties.Color <<= nColor; + //when the line is very short compared to the page size don't create one + ::basegfx::B2DVector aLength(nX1 - nX2, nY1 - nY2); + double fPageDiagonaleLength = sqrt(double(nPageWidth) * double(nPageWidth) + + double(nPageHeight) * double(nPageHeight)); + if ((aLength.getLength() / fPageDiagonaleLength) >= 0.01) + { + drawing::PointSequenceSequence aPoints(1); + aPoints[0].realloc(2); + aPoints[0][0].X = nX1; + aPoints[0][0].Y = nY1; + aPoints[0][1].X = nX2; + aPoints[0][1].Y = nY2; + + uno::Reference<beans::XPropertySet> xProp(aPieLabelInfo.xTextShape, + uno::UNO_QUERY); + VLineProperties aVLineProperties; + if (xProp.is()) + { + sal_Int32 nColor = 0; + xProp->getPropertyValue("CharColor") >>= nColor; + //automatic font color does not work for lines -> fallback to black + if (nColor != -1) + aVLineProperties.Color <<= nColor; + } + m_pShapeFactory->createLine2D(xTextTarget, aPoints, &aVLineProperties); + } } - m_pShapeFactory->createLine2D(xTextTarget, aPoints, &aVLineProperties); } } diff --git a/chart2/source/view/inc/VSeriesPlotter.hxx b/chart2/source/view/inc/VSeriesPlotter.hxx index 7632ff586633..a824ff14c77b 100644 --- a/chart2/source/view/inc/VSeriesPlotter.hxx +++ b/chart2/source/view/inc/VSeriesPlotter.hxx @@ -426,6 +426,7 @@ protected: bool m_bPointsWereSkipped; bool m_bPieLabelsAllowToMove; basegfx::B2IRectangle m_aAvailableOuterRect; + css::awt::Size m_aPageReferenceSize; private: typedef std::map< sal_Int32 , ExplicitScaleData > tSecondaryValueScales; @@ -433,7 +434,6 @@ private: typedef std::map< sal_Int32 , std::unique_ptr<PlottingPositionHelper> > tSecondaryPosHelperMap; mutable tSecondaryPosHelperMap m_aSecondaryPosHelperMap; - css::awt::Size m_aPageReferenceSize; }; } //namespace chart |