From 1407a3551d6d075d6f4e15b9f7cd4cb60e177d78 Mon Sep 17 00:00:00 2001 From: cneben Date: Thu, 15 Aug 2024 02:04:11 +0200 Subject: [PATCH] #228 Add horizontal tree layout support. Signed-off-by: cneben --- samples/layouts/layouts.qml | 1 + src/qanTreeLayouts.cpp | 33 ++++++++++++++++++++++++++++++--- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/samples/layouts/layouts.qml b/samples/layouts/layouts.qml index 7ac80dfa..39d49f00 100644 --- a/samples/layouts/layouts.qml +++ b/samples/layouts/layouts.qml @@ -77,6 +77,7 @@ ApplicationWindow { graph.insertEdge(n121, n1211); graph.insertEdge(n13, n131); + orgTreeLayout.layoutOrientation = Qan.OrgTreeLayout.Horizontal orgTreeLayout.layout(n1); } Qan.OrgTreeLayout { diff --git a/src/qanTreeLayouts.cpp b/src/qanTreeLayouts.cpp index d1a85a4a..ac57cd19 100644 --- a/src/qanTreeLayouts.cpp +++ b/src/qanTreeLayouts.cpp @@ -172,7 +172,7 @@ void OrgTreeLayout::layout(qan::Node& root, qreal xSpacing, qreal ySpacing) n // Algorithm: // Traverse graph DFS aligning child nodes vertically // At a given level: `shift` next node according to previous node sub-tree BR - auto layout_rec = [xSpacing, ySpacing](auto&& self, auto& childNodes, QRectF br) -> QRectF { + auto layoutVert_rec = [xSpacing, ySpacing](auto&& self, auto& childNodes, QRectF br) -> QRectF { const auto x = br.right() + xSpacing; for (auto child: childNodes) { child->getItem()->setX(x); @@ -184,9 +184,36 @@ void OrgTreeLayout::layout(qan::Node& root, qreal xSpacing, qreal ySpacing) n } return br; }; + + auto layoutHoriz_rec = [xSpacing, ySpacing](auto&& self, auto& childNodes, QRectF br) -> QRectF { + const auto y = br.bottom() + ySpacing; + for (auto child: childNodes) { + child->getItem()->setX(br.right() + xSpacing); + child->getItem()->setY(y); + // Take into account this level maximum width + br = br.united(child->getItem()->boundingRect().translated(child->getItem()->position())); + const auto childBr = self(self, child->get_out_nodes(), br); + br.setRight(childBr.right()); // Note: Do not take full child BR into account to avoid x drifting + } + return br; + }; + // Note: QQuickItem boundingRect() is in item local CS, translate to "scene" CS. - layout_rec(layout_rec, root.get_out_nodes(), - root.getItem()->boundingRect().translated(root.getItem()->position())); + switch (getLayoutOrientation()) { + case LayoutOrientation::Undefined: return; + case LayoutOrientation::Vertical: + layoutVert_rec(layoutVert_rec, root.get_out_nodes(), + root.getItem()->boundingRect().translated(root.getItem()->position())); + break; + case LayoutOrientation::Horizontal: + layoutHoriz_rec(layoutHoriz_rec, root.get_out_nodes(), + root.getItem()->boundingRect().translated(root.getItem()->position())); + break; + case LayoutOrientation::Mixed: + //layoutHoriz_rec(layout_rec, root.get_out_nodes(), + // root.getItem()->boundingRect().translated(root.getItem()->position())); + break; + } } void OrgTreeLayout::layout(qan::Node* root, qreal xSpacing, qreal ySpacing) noexcept