summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomaž Vajngerl <tomaz.vajngerl@collabora.co.uk>2022-02-11 19:41:37 +0900
committerMiklos Vajna <vmiklos@collabora.com>2022-02-28 12:48:59 +0100
commit89b77d414c2c45d2b013089ed2a2b5c7cc4f00ec (patch)
tree811c9f99bab2170803c4c0ef058164613c1a9359
parentchart2: crop x-axis label if it's too long on fixed size charts (diff)
downloadcore-89b77d414c2c45d2b013089ed2a2b5c7cc4f00ec.tar.gz
core-89b77d414c2c45d2b013089ed2a2b5c7cc4f00ec.zip
chart2: Break labels text and limit the size to the axis size
Previously a long label wouldn't be broken into multiple lines and be limited to the axis size if the chart sizing was automatic. This would cause the label to distort the whole chart and make the chart area very narrow. With this change the label text is limited to the axis width and gets broken into multiple lines if this is necessary. BarChartVeryLongLabel.odp provides a test document which includes automatic size and fixed size chart are. We make sure the area that the label text occupies is not larger than the chart wall size. Change-Id: If58bfa3e51ab68f720f22df5416ae305401bcd34 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/129814 Tested-by: Jenkins Reviewed-by: Tomaž Vajngerl <quikee@gmail.com> (cherry picked from commit ca22f1ce703c1d03fc1b1ed1f5ac1fc903b09e6f) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/129898 Reviewed-by: Dennis Francis <dennis.francis@collabora.com>
-rw-r--r--chart2/qa/extras/chart2import.cxx86
-rw-r--r--chart2/qa/extras/data/odp/BarChartVeryLongLabel.odpbin0 -> 16390 bytes
-rw-r--r--chart2/qa/extras/data/odp/FixedSizeBarChartVeryLongLabel.odpbin13293 -> 0 bytes
-rw-r--r--chart2/source/view/axes/Tickmarks.cxx5
-rw-r--r--chart2/source/view/axes/Tickmarks.hxx11
-rw-r--r--chart2/source/view/axes/VCartesianAxis.cxx17
-rw-r--r--chart2/source/view/main/ChartView.cxx12
-rw-r--r--sw/qa/extras/layout/layout2.cxx2
8 files changed, 121 insertions, 12 deletions
diff --git a/chart2/qa/extras/chart2import.cxx b/chart2/qa/extras/chart2import.cxx
index 467bac3a7f62..60be3b21529d 100644
--- a/chart2/qa/extras/chart2import.cxx
+++ b/chart2/qa/extras/chart2import.cxx
@@ -133,6 +133,7 @@ public:
void testTdf48041();
void testTdf121205();
void testFixedSizeBarChartVeryLongLabel();
+ void testAutomaticSizeBarChartVeryLongLabel();
void testTdf114179();
void testTdf124243();
@@ -253,6 +254,7 @@ public:
CPPUNIT_TEST(testTdf48041);
CPPUNIT_TEST(testTdf121205);
CPPUNIT_TEST(testFixedSizeBarChartVeryLongLabel);
+ CPPUNIT_TEST(testAutomaticSizeBarChartVeryLongLabel);
CPPUNIT_TEST(testTdf114179);
CPPUNIT_TEST(testTdf124243);
@@ -2915,8 +2917,9 @@ void Chart2ImportTest::testFixedSizeBarChartVeryLongLabel()
// case the best course of action is to just crop the label text. This
// test checks that the rendered text is actually cropped.
- load(u"/chart2/qa/extras/data/odp/", "FixedSizeBarChartVeryLongLabel.odp");
+ load(u"/chart2/qa/extras/data/odp/", "BarChartVeryLongLabel.odp");
+ // Select shape 0 which has fixed size chart
Reference<chart2::XChartDocument> xChartDoc(getChartDocFromDrawImpress(0, 0), uno::UNO_QUERY);
CPPUNIT_ASSERT(xChartDoc.is());
@@ -2965,7 +2968,86 @@ void Chart2ImportTest::testFixedSizeBarChartVeryLongLabel()
// Check text is actually cropped
uno::Reference<text::XTextRange> xLabel(xIndexAccess->getByIndex(0), uno::UNO_QUERY);
- CPPUNIT_ASSERT_EQUAL(OUString("Very very very very..."), xLabel->getString());
+ CPPUNIT_ASSERT_EQUAL(OUString("Very very very very very very..."), xLabel->getString());
+
+ uno::Reference<drawing::XShape> xChartWall = getShapeByName(xShapes, "CID/DiagramWall=");
+ CPPUNIT_ASSERT(xChartWall.is());
+
+ // The text shape width should be smaller than the chart wall
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(5085), xChartWall->getSize().Width);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(7113), xChartWall->getSize().Height);
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(4870), xXAxis->getSize().Width);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(398), xXAxis->getSize().Height);
+}
+
+void Chart2ImportTest::testAutomaticSizeBarChartVeryLongLabel()
+{
+ // Bar chart area size is automatic so we expect the label to be broken
+ // into multiple lines.
+
+ load(u"/chart2/qa/extras/data/odp/", "BarChartVeryLongLabel.odp");
+
+ // Select shape 1, which has an automatic sized chart
+ Reference<chart2::XChartDocument> xChartDoc(getChartDocFromDrawImpress(0, 1), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ Reference<chart2::XAxis> xHAxis = getAxisFromDoc(xChartDoc, 0, 0, 0);
+ CPPUNIT_ASSERT(xHAxis.is());
+
+ chart2::ScaleData aScaleData = xHAxis->getScaleData();
+ CPPUNIT_ASSERT(aScaleData.Categories.is());
+
+ Reference<chart2::data::XLabeledDataSequence> xLabeledDataSequence = aScaleData.Categories;
+ CPPUNIT_ASSERT(xLabeledDataSequence.is());
+
+ Reference<chart2::data::XDataSequence> xDataSequence = xLabeledDataSequence->getValues();
+ CPPUNIT_ASSERT(xDataSequence.is());
+
+ Reference<chart2::data::XTextualDataSequence> xTextualDataSequence(xDataSequence, uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xTextualDataSequence.is());
+
+ std::vector<OUString> aCategories;
+ const Sequence<OUString> aTextData(xTextualDataSequence->getTextualData());
+ ::std::copy(aTextData.begin(), aTextData.end(),
+ ::std::back_inserter(aCategories));
+
+ // Check that we have a very very long label text
+ CPPUNIT_ASSERT_EQUAL(OUString("Very very very very very very very very very very very loooooooooooong label"), aCategories[0]);
+
+ // Check visible text
+ uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xChartDoc, uno::UNO_QUERY);
+ uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage();
+ uno::Reference<drawing::XShapes> xShapes(xDrawPage->getByIndex(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xShapes.is());
+
+ uno::Reference<drawing::XShape> xXAxis = getShapeByName(xShapes, "CID/D=0:CS=0:Axis=0,0",
+ // Axis occurs twice in chart xshape representation so need to get the one related to labels
+ [](const uno::Reference<drawing::XShape>& rXShape) -> bool
+ {
+ uno::Reference<drawing::XShapes> xAxisShapes(rXShape, uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xAxisShapes.is());
+ uno::Reference<drawing::XShape> xChildShape(xAxisShapes->getByIndex(0), uno::UNO_QUERY);
+ uno::Reference< drawing::XShapeDescriptor > xShapeDescriptor(xChildShape, uno::UNO_QUERY_THROW);
+ return (xShapeDescriptor->getShapeType() == "com.sun.star.drawing.TextShape");
+ });
+ CPPUNIT_ASSERT(xXAxis.is());
+
+ uno::Reference<container::XIndexAccess> xIndexAccess(xXAxis, UNO_QUERY_THROW);
+
+ // Check text is unmodified
+ uno::Reference<text::XTextRange> xLabel(xIndexAccess->getByIndex(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("Very very very very very very very very very very very loooooooooooong label"), xLabel->getString());
+
+ uno::Reference<drawing::XShape> xChartWall = getShapeByName(xShapes, "CID/DiagramWall=");
+ CPPUNIT_ASSERT(xChartWall.is());
+
+ // The text shape width should be smaller than the chart wall
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(5761), xChartWall->getSize().Width);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(7200), xChartWall->getSize().Height);
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(5320), xXAxis->getSize().Width);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1192), xXAxis->getSize().Height);
}
CPPUNIT_TEST_SUITE_REGISTRATION(Chart2ImportTest);
diff --git a/chart2/qa/extras/data/odp/BarChartVeryLongLabel.odp b/chart2/qa/extras/data/odp/BarChartVeryLongLabel.odp
new file mode 100644
index 000000000000..c627af79e4d5
--- /dev/null
+++ b/chart2/qa/extras/data/odp/BarChartVeryLongLabel.odp
Binary files differ
diff --git a/chart2/qa/extras/data/odp/FixedSizeBarChartVeryLongLabel.odp b/chart2/qa/extras/data/odp/FixedSizeBarChartVeryLongLabel.odp
deleted file mode 100644
index 18869b638d1e..000000000000
--- a/chart2/qa/extras/data/odp/FixedSizeBarChartVeryLongLabel.odp
+++ /dev/null
Binary files differ
diff --git a/chart2/source/view/axes/Tickmarks.cxx b/chart2/source/view/axes/Tickmarks.cxx
index 73c8e041cf40..7a63e58924d1 100644
--- a/chart2/source/view/axes/Tickmarks.cxx
+++ b/chart2/source/view/axes/Tickmarks.cxx
@@ -203,11 +203,6 @@ sal_Int32 TickFactory2D::getTickScreenDistance( TickIter& rIter )
return pFirstTickInfo->getScreenDistanceBetweenTicks( *pSecondTickInfo );
}
-const B2DVector & TickFactory2D::getXaxisStartPos() const
-{
- return m_aAxisStartScreenPosition2D;
-}
-
B2DVector TickFactory2D::getTickScreenPosition2D( double fScaledLogicTickValue ) const
{
B2DVector aRet(m_aAxisStartScreenPosition2D);
diff --git a/chart2/source/view/axes/Tickmarks.hxx b/chart2/source/view/axes/Tickmarks.hxx
index 77b9a2b85bdc..7947993be3db 100644
--- a/chart2/source/view/axes/Tickmarks.hxx
+++ b/chart2/source/view/axes/Tickmarks.hxx
@@ -134,7 +134,16 @@ public:
bool isHorizontalAxis() const;
bool isVerticalAxis() const;
- const ::basegfx::B2DVector & getXaxisStartPos() const;
+
+ const ::basegfx::B2DVector & getXaxisStartPos() const
+ {
+ return m_aAxisStartScreenPosition2D;
+ }
+
+ const ::basegfx::B2DVector & getXaxisEndPos() const
+ {
+ return m_aAxisEndScreenPosition2D;
+ }
private:
::basegfx::B2DVector getTickScreenPosition2D( double fScaledLogicTickValue ) const;
diff --git a/chart2/source/view/axes/VCartesianAxis.cxx b/chart2/source/view/axes/VCartesianAxis.cxx
index eceaf5d95fd4..8b373c0b3a1d 100644
--- a/chart2/source/view/axes/VCartesianAxis.cxx
+++ b/chart2/source/view/axes/VCartesianAxis.cxx
@@ -735,10 +735,13 @@ bool VCartesianAxis::createTextShapes(
}
}
- if (!isBreakOfLabelsAllowed(rAxisLabelProperties, bIsHorizontalAxis, bIsVerticalAxis) &&
+ bool bIsBreakOfLabelsAllowed = isBreakOfLabelsAllowed( rAxisLabelProperties, bIsHorizontalAxis, bIsVerticalAxis );
+ if (!bIsBreakOfLabelsAllowed &&
!isAutoStaggeringOfLabelsAllowed(rAxisLabelProperties, bIsHorizontalAxis, bIsVerticalAxis) &&
!rAxisLabelProperties.isStaggered())
+ {
return createTextShapesSimple(xTarget, rTickIter, rAxisLabelProperties, pTickFactory);
+ }
FixedNumberFormatter aFixedNumberFormatter(
m_xNumberFormatsSupplier, rAxisLabelProperties.nNumberFormatKey );
@@ -747,9 +750,16 @@ bool VCartesianAxis::createTextShapes(
B2DVector aTextToTickDistance = pTickFactory->getDistanceAxisTickToText(m_aAxisProperties, true);
sal_Int32 nLimitedSpaceForText = -1;
- if( isBreakOfLabelsAllowed( rAxisLabelProperties, bIsHorizontalAxis, bIsVerticalAxis ) )
+ if (bIsBreakOfLabelsAllowed)
{
- nLimitedSpaceForText = nScreenDistanceBetweenTicks;
+ if (!m_aAxisProperties.m_bLimitSpaceForLabels)
+ {
+ basegfx::B2DVector nDeltaVector = pTickFactory->getXaxisEndPos() - pTickFactory->getXaxisStartPos();
+ nLimitedSpaceForText = nDeltaVector.getX();
+ }
+ if (nScreenDistanceBetweenTicks > 0)
+ nLimitedSpaceForText = nScreenDistanceBetweenTicks;
+
if( bIsStaggered )
nLimitedSpaceForText *= 2;
@@ -888,6 +898,7 @@ bool VCartesianAxis::createTextShapes(
// Label has multiple lines and the words are broken
if( nLimitedSpaceForText>0 && !rAxisLabelProperties.bOverlapAllowed
&& rAxisLabelProperties.fRotationAngleDegree == 0.0
+ && nTick > 0
&& lcl_hasWordBreak( pTickInfo->xTextShape ) )
{
// Label has multiple lines and belongs to a complex category
diff --git a/chart2/source/view/main/ChartView.cxx b/chart2/source/view/main/ChartView.cxx
index 5cfee64f0641..d40c09a509d5 100644
--- a/chart2/source/view/main/ChartView.cxx
+++ b/chart2/source/view/main/ChartView.cxx
@@ -1530,7 +1530,9 @@ awt::Rectangle ChartView::impl_createDiagramAndContent( const CreateShapeParam2D
|| aConsumedOuterRect.getMaxX() < aAvailableOuterRect.getMaxX()
|| aConsumedOuterRect.getMinY() > aAvailableOuterRect.getMinY()
|| aConsumedOuterRect.getMinY() < aAvailableOuterRect.getMaxY() )
+ {
bLessSpaceConsumedThanExpected = true;
+ }
}
if (bLessSpaceConsumedThanExpected && !rParam.mbUseFixedInnerSize)
@@ -1538,6 +1540,16 @@ awt::Rectangle ChartView::impl_createDiagramAndContent( const CreateShapeParam2D
aVDiagram.adjustInnerSize( aConsumedOuterRect );
pVCooSys->setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix(
createTransformationSceneToScreen( aVDiagram.getCurrentRectangle() ) ));
+
+ // Need to re-adjust again if the labels have changed height because of
+ // text can break. Ideally this shouldn't be needed, but the chart height
+ // isn't readjusted otherwise.
+ pVCooSys->createAxesLabels();
+ aConsumedOuterRect = ShapeFactory::getRectangleOfShape(xBoundingShape);
+ aVDiagram.adjustInnerSize(aConsumedOuterRect);
+ pVCooSys->setTransformationSceneToScreen(B3DHomMatrixToHomogenMatrix(
+ createTransformationSceneToScreen(aVDiagram.getCurrentRectangle())));
+
}
pVCooSys->updatePositions();//todo: logically this belongs to the condition above, but it seems also to be necessary to give the axes group shapes the right bounding rects for hit test - probably caused by bug i106183 -> check again if fixed
}
diff --git a/sw/qa/extras/layout/layout2.cxx b/sw/qa/extras/layout/layout2.cxx
index 3586afe23d3d..609365f6c6ae 100644
--- a/sw/qa/extras/layout/layout2.cxx
+++ b/sw/qa/extras/layout/layout2.cxx
@@ -758,7 +758,7 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testHorizontal_multilevel)
sal_Int32 nYposition
= getXPath(pXmlDoc, "/metafile/push[1]/push[1]/push[1]/push[3]/push[1]/textarray[7]", "y")
.toInt32();
- CPPUNIT_ASSERT_DOUBLES_EQUAL(7945, nYposition, 20);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(8057, nYposition, 20);
}
CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf138194)