oox/source/drawingml/diagram/diagramlayoutatoms.cxx | 53 +++++++++++++++++++- sd/qa/unit/import-tests-smartart.cxx | 6 ++ 2 files changed, 57 insertions(+), 2 deletions(-)
New commits: commit 3a655975e5ea43417885513d0752da3627dd25ed Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Thu Jan 17 11:22:28 2019 +0100 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Thu Jan 17 12:47:30 2019 +0100 oox smartart, org chart: improve width of non-manager nodes The default case is that all managers have assistants/employees, so nodes under a manager can only use the horizontal space under the manager to avoid overlapping. But in case the previous / next sibling of the manager have no child nodes (assistant/employee) then we can use that space to make the child nodes larger. This improves readability of the chart's text a lot and brings the layout closer to what PowerPoint does for the same input. Handle all this in the hierChild algorithm, i.e. the container for a list of assistants or a list of employees, which means "parent" in this context always refers to a manager node. Change-Id: Ib4125ea2a113339ab7bbcd78e43c5d204f442996 Reviewed-on: https://gerrit.libreoffice.org/66504 Reviewed-by: Miklos Vajna <vmik...@collabora.com> Tested-by: Jenkins diff --git a/oox/source/drawingml/diagram/diagramlayoutatoms.cxx b/oox/source/drawingml/diagram/diagramlayoutatoms.cxx index 1e68896b1e9c..fc5b1c059410 100644 --- a/oox/source/drawingml/diagram/diagramlayoutatoms.cxx +++ b/oox/source/drawingml/diagram/diagramlayoutatoms.cxx @@ -117,6 +117,49 @@ bool containsDataNodeType(const oox::drawingml::ShapePtr& pShape, sal_Int32 nTyp return false; } + +/** + * Calculates the offset and scaling for pShape (laid out with the hierChild + * algorithm) based on the siblings of pParent. + */ +void calculateHierChildOffsetScale(const oox::drawingml::ShapePtr& pShape, + const oox::drawingml::LayoutNode* pParent, sal_Int32& rXOffset, + double& rWidthScale) +{ + if (!pParent) + return; + + const std::vector<oox::drawingml::ShapePtr>& rParents = pParent->getNodeShapes(); + for (size_t nParent = 0; nParent < rParents.size(); ++nParent) + { + const oox::drawingml::ShapePtr& pParentShape = rParents[nParent]; + const std::vector<oox::drawingml::ShapePtr>& rChildren = pParentShape->getChildren(); + auto it = std::find_if( + rChildren.begin(), rChildren.end(), + [pShape](const oox::drawingml::ShapePtr& pChild) { return pChild == pShape; }); + if (it == rChildren.end()) + // This is not our parent. + continue; + + if (nParent > 0) + { + if (rParents[nParent - 1]->getChildren().size() == 1) + { + // Previous sibling of our parent has no children: can use that + // space, so shift to the left and scale up. + rWidthScale += 1.0; + rXOffset -= pShape->getSize().Width; + } + } + if (nParent < rParents.size() - 1) + { + if (rParents[nParent + 1]->getChildren().size() == 1) + // Next sibling of our parent has no children: can use that + // space, so scale up. + rWidthScale += 1.0; + } + } +} } namespace oox { namespace drawingml { @@ -568,16 +611,22 @@ void AlgAtom::layoutShape( const ShapePtr& rShape, std::swap(rChildren[1], rChildren[2]); } + sal_Int32 nXOffset = 0; + double fWidthScale = 1.0; + if (mnType == XML_hierChild) + calculateHierChildOffsetScale(rShape, pParent, nXOffset, fWidthScale); + awt::Size aChildSize = rShape->getSize(); if (nDir == XML_fromT) { aChildSize.Height /= nCount; - aChildSize.Height *= fHeightScale; } else aChildSize.Width /= nCount; + aChildSize.Height *= fHeightScale; + aChildSize.Width *= fWidthScale; - awt::Point aChildPos(0, 0); + awt::Point aChildPos(nXOffset, 0); for (auto& pChild : rShape->getChildren()) { pChild->setPosition(aChildPos); diff --git a/sd/qa/unit/import-tests-smartart.cxx b/sd/qa/unit/import-tests-smartart.cxx index 66fdfbc254cd..846a95ee6738 100644 --- a/sd/qa/unit/import-tests-smartart.cxx +++ b/sd/qa/unit/import-tests-smartart.cxx @@ -739,6 +739,7 @@ void SdImportTestSmartArt::testOrgChart() CPPUNIT_ASSERT(xEmployeeShape.is()); awt::Point aEmployeePos = xEmployeeShape->getPosition(); + awt::Size aEmployeeSize = xEmployeeShape->getSize(); CPPUNIT_ASSERT_EQUAL(aManagerPos.X, aEmployeePos.X); @@ -760,6 +761,7 @@ void SdImportTestSmartArt::testOrgChart() CPPUNIT_ASSERT(xEmployee2Shape.is()); awt::Point aEmployee2Pos = xEmployee2Shape->getPosition(); + awt::Size aEmployee2Size = xEmployee2Shape->getSize(); CPPUNIT_ASSERT_GREATER(aEmployeePos.X, aEmployee2Pos.X); // Make sure that assistant is above employees. @@ -791,6 +793,10 @@ void SdImportTestSmartArt::testOrgChart() // xManager2's height was 3 times larger than xManager's height. CPPUNIT_ASSERT_EQUAL(aManagerSize.Height, aManager2Size.Height); + // Make sure the employee nodes use the free space on the right, since + // manager2 has no assistants / employees. + CPPUNIT_ASSERT_GREATER(aManagerSize.Width, aEmployeeSize.Width + aEmployee2Size.Width); + xDocShRef->DoClose(); } _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits