Kaydet (Commit) 3a655975 authored tarafından Miklos Vajna's avatar Miklos Vajna

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/66504Reviewed-by: 's avatarMiklos Vajna <vmiklos@collabora.com>
Tested-by: Jenkins
üst d8886a05
......@@ -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);
......
......@@ -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();
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment