summaryrefslogtreecommitdiff
path: root/oox
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.com>2019-01-17 11:22:28 +0100
committerMiklos Vajna <vmiklos@collabora.com>2019-01-17 12:47:30 +0100
commit3a655975e5ea43417885513d0752da3627dd25ed (patch)
tree4ec8633ed4ae012993942288a3125d80c0aa1680 /oox
parentd8886a051abcb5abf52038bf3e5bced9f10f28af (diff)
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 <vmiklos@collabora.com> Tested-by: Jenkins
Diffstat (limited to 'oox')
-rw-r--r--oox/source/drawingml/diagram/diagramlayoutatoms.cxx53
1 files changed, 51 insertions, 2 deletions
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);