diff --git a/src/lib/component/controller/GraphController.cpp b/src/lib/component/controller/GraphController.cpp index 1964bbc1..ad3ee089 100644 --- a/src/lib/component/controller/GraphController.cpp +++ b/src/lib/component/controller/GraphController.cpp @@ -1493,7 +1493,6 @@ void GraphController::groupNodesByParents(GroupType groupType) m_dummyNodes.push_back(groupNode); } - std::vector bundleInfos; for (std::shared_ptr dummyNode : p.second) { if (dummyNode->hasActiveSubNode()) @@ -1501,10 +1500,6 @@ void GraphController::groupNodesByParents(GroupType groupType) groupNode->bundleInfo = dummyNode->bundleInfo; groupNode->bundleId = dummyNode->bundleId; } - else - { - bundleInfos.push_back(dummyNode->bundleInfo); - } groupNode->subNodes.push_back(dummyNode); m_topLevelAncestorIds[dummyNode->tokenId] = groupNode->tokenId; @@ -1514,9 +1509,9 @@ void GraphController::groupNodesByParents(GroupType groupType) if (!groupNode->bundleId) { groupNode->bundleId = groupNode->subNodes[0]->bundleId; - groupNode->bundleInfo = DummyNode::BundleInfo::averageBundleInfo(bundleInfos); } + groupNode->bundleInfo = DummyNode::BundleInfo::averageBundleInfo(groupNode->getBundleInfos()); groupNode->sortSubNodesByName(); } diff --git a/src/lib/component/controller/helper/BucketLayouter.cpp b/src/lib/component/controller/helper/BucketLayouter.cpp index 4d2ce9d0..adfaefeb 100644 --- a/src/lib/component/controller/helper/BucketLayouter.cpp +++ b/src/lib/component/controller/helper/BucketLayouter.cpp @@ -71,18 +71,29 @@ void Bucket::preLayout(Vec2i viewSize, bool addVerticalSplit, bool forceVertical std::vector> nodesInCol; nodesInCol.push_back({ }); + int heightDiff = 0; for (const std::shared_ptr& node : m_nodes) { - if (y > height) + if (y > height + heightDiff) { - colHeights.push_back(y - GraphViewStyle::s_gridCellPadding); - colWidths.push_back(width); + // keep adding to the same columns if it only contains 1 element, which will end up above the middle split + if (nodesInCol.back().size() == 1 && m_nodes.size() > 1 && addVerticalSplit | forceVerticalSplit) + { + heightDiff = y; + } + else + { + colHeights.push_back(y - GraphViewStyle::s_gridCellPadding); + colWidths.push_back(width); - y = 0; - x += GraphViewStyle::toGridOffset(width + 45); - width = 0; + y = 0; + x += GraphViewStyle::toGridOffset(width + 45); + width = 0; - nodesInCol.push_back({ }); + nodesInCol.push_back({ }); + + heightDiff = 0; + } } node->position.x = x; @@ -92,8 +103,8 @@ void Bucket::preLayout(Vec2i viewSize, bool addVerticalSplit, bool forceVertical y += GraphViewStyle::toGridSize(node->size.y) + GraphViewStyle::s_gridCellPadding; - width = (node->size.x > width ? node->size.x : width); - m_height = (y > m_height ? y : m_height); + width = std::max(width, node->size.x()); + m_height = std::max(m_height, y); } colHeights.push_back(y - GraphViewStyle::s_gridCellPadding); @@ -242,28 +253,16 @@ void BucketLayouter::createBuckets( addNode(nodes[0]); } - std::vector remainingEdges; - for (const std::shared_ptr& edge : edges) + for (std::shared_ptr edge : edges) { - remainingEdges.push_back(edge.get()); - } - - size_t i = 0; - while (remainingEdges.size()) - { - const DummyEdge* edge = remainingEdges[i]; - std::shared_ptr owner = findTopMostDummyNodeRecursive(nodes, edge->ownerId, nullptr); std::shared_ptr target = findTopMostDummyNodeRecursive(nodes, edge->targetId, nullptr); - bool removeEdge = false; - if (!owner || !target || owner == target) + bool horizontal = true; + + if (owner && target && owner != target && owner->getsLayouted() && target->getsLayouted()) { - removeEdge = true; - } - else - { - bool horizontal = !owner->bundleInfo.layoutVertical && !target->bundleInfo.layoutVertical; + horizontal = !owner->bundleInfo.layoutVertical && !target->bundleInfo.layoutVertical; if (!horizontal) { @@ -273,27 +272,18 @@ void BucketLayouter::createBuckets( std::swap(owner, target); } } - else if (edge->getDirection() == TokenComponentAggregation::DIRECTION_BACKWARD) + else if (edge->getDirection() == TokenComponentAggregation::DIRECTION_BACKWARD || + // put nodes with bidirectional edges on the left + (edge->getDirection() == TokenComponentAggregation::DIRECTION_NONE && + !target->bundleInfo.isReferencing && !target->bundleInfo.isReferenced)) { std::swap(owner, target); } - removeEdge = addNode(owner, target, horizontal); + horizontal = addNode(owner, target, horizontal); } - if (removeEdge) - { - remainingEdges.erase(remainingEdges.begin() + i); - } - else - { - i++; - } - - if (i == remainingEdges.size()) - { - i = 0; - } + edge->layoutHorizontal = horizontal; } } @@ -416,7 +406,7 @@ bool BucketLayouter::addNode(std::shared_ptr owner, std::shared_ptrj == targetBucket->j; } if (ownerBucket) @@ -436,7 +426,7 @@ bool BucketLayouter::addNode(std::shared_ptr owner, std::shared_ptraddNode(owner); } - return true; + return horizontal; } Bucket* BucketLayouter::getBucket(int i, int j) diff --git a/src/lib/component/controller/helper/DummyEdge.h b/src/lib/component/controller/helper/DummyEdge.h index 80edd5f9..75a6213f 100644 --- a/src/lib/component/controller/helper/DummyEdge.h +++ b/src/lib/component/controller/helper/DummyEdge.h @@ -19,6 +19,7 @@ struct DummyEdge , visible(false) , hidden(false) , active(false) + , layoutHorizontal(true) , weight(0) , direction(TokenComponentAggregation::DIRECTION_INVALID) { @@ -31,6 +32,7 @@ struct DummyEdge , visible(false) , hidden(false) , active(false) + , layoutHorizontal(true) , weight(0) , direction(TokenComponentAggregation::DIRECTION_INVALID) { @@ -92,6 +94,8 @@ struct DummyEdge std::vector path; + bool layoutHorizontal; + // BundleEdge int weight; TokenComponentAggregation::Direction direction; diff --git a/src/lib/component/controller/helper/DummyNode.h b/src/lib/component/controller/helper/DummyNode.h index 8bfc0072..2a7de877 100644 --- a/src/lib/component/controller/helper/DummyNode.h +++ b/src/lib/component/controller/helper/DummyNode.h @@ -74,11 +74,11 @@ public: } BundleInfo info; - if (activeCount > bundleInfos.size() / 2) info.isActive = true; - if (definedCount > bundleInfos.size() / 2) info.isDefined = true; - if (verticalLayoutCount > bundleInfos.size() / 2) info.layoutVertical = true; - if (referencedCount > bundleInfos.size() / 2) info.isReferenced = true; - if (referencingCount > bundleInfos.size() / 2) info.isReferencing = true; + if (activeCount >= std::ceil(bundleInfos.size() / 2.0f)) info.isActive = true; + if (definedCount >= std::ceil(bundleInfos.size() / 2.0f)) info.isDefined = true; + if (verticalLayoutCount >= std::ceil(bundleInfos.size() / 2.0f)) info.layoutVertical = true; + if (referencedCount >= std::ceil(bundleInfos.size() / 2.0f)) info.isReferenced = true; + if (referencingCount >= std::ceil(bundleInfos.size() / 2.0f)) info.isReferencing = true; return info; } @@ -431,6 +431,16 @@ public: return nullptr; } + std::vector getBundleInfos() const + { + std::vector bundleInfos; + for (const std::shared_ptr& subNode : subNodes) + { + bundleInfos.push_back(subNode->bundleInfo); + } + return bundleInfos; + } + Type type; Vec2i position; diff --git a/src/lib_gui/qt/view/QtGraphView.cpp b/src/lib_gui/qt/view/QtGraphView.cpp index 2e4f2c03..832ff34c 100644 --- a/src/lib_gui/qt/view/QtGraphView.cpp +++ b/src/lib_gui/qt/view/QtGraphView.cpp @@ -1042,7 +1042,8 @@ QtGraphEdge* QtGraphView::createEdge( if (owner != nullptr && target != nullptr) { QtGraphEdge* qtEdge = new QtGraphEdge( - owner, target, edge->data, edge->getWeight(), edge->active && !useBezier, edge->getDirection()); + owner, target, edge->data, edge->getWeight(), edge->active && !useBezier, edge->layoutHorizontal, + edge->getDirection()); if (trailMode != Graph::TRAIL_NONE) { diff --git a/src/lib_gui/qt/view/graphElements/QtGraphEdge.cpp b/src/lib_gui/qt/view/graphElements/QtGraphEdge.cpp index 5db1db31..14860851 100644 --- a/src/lib_gui/qt/view/graphElements/QtGraphEdge.cpp +++ b/src/lib_gui/qt/view/graphElements/QtGraphEdge.cpp @@ -30,6 +30,7 @@ QtGraphEdge::QtGraphEdge( const Edge* data, size_t weight, bool isActive, + bool horizontal, TokenComponentAggregation::Direction direction ) : m_data(data) @@ -38,10 +39,10 @@ QtGraphEdge::QtGraphEdge( , m_child(nullptr) , m_isActive(isActive) , m_isFocused(false) + , m_isHorizontal(horizontal) , m_weight(weight) , m_direction(direction) , m_isTrailEdge(false) - , m_isHorizontalTrail(false) , m_useBezier(false) , m_mousePos(0.0f, 0.0f) , m_mouseMoved(false) @@ -117,6 +118,8 @@ void QtGraphEdge::updateLine() targetParentRect = targetParent->getBoundingRect(); } + QtLineItemBase::Route route = m_isHorizontal ? QtLineItemBase::ROUTE_HORIZONTAL : QtLineItemBase::ROUTE_VERTICAL; + if (m_useBezier) { for (QGraphicsItem* item : childItems()) @@ -128,9 +131,6 @@ void QtGraphEdge::updateLine() style.originOffset.y() = 0; style.targetOffset.y() = 0; - QtLineItemBase::Route route = - m_isHorizontalTrail ? QtLineItemBase::ROUTE_HORIZONTAL : QtLineItemBase::ROUTE_VERTICAL; - for (const Vec4i& rect : m_path) { QtLineItemBezier* bezier = new QtLineItemBezier(this); @@ -219,7 +219,7 @@ void QtGraphEdge::updateLine() if (type == Edge::EDGE_INHERITANCE || (type == Edge::EDGE_TEMPLATE_SPECIALIZATION && owner == ownerNonGroupParent && target == targetNonGroupParent)) { - child->setRoute(QtLineItemBase::ROUTE_VERTICAL); + route = QtLineItemBase::ROUTE_VERTICAL; if (target->hasActiveChild()) { @@ -229,9 +229,11 @@ void QtGraphEdge::updateLine() else if (type != Edge::EDGE_AGGREGATION || owner != ownerNonGroupParent || target != targetNonGroupParent) { - child->setRoute(QtLineItemBase::ROUTE_HORIZONTAL); + route = QtLineItemBase::ROUTE_HORIZONTAL; } + child->setRoute(route); + bool showArrow = true; if (type == Edge::EDGE_AGGREGATION) { @@ -471,11 +473,11 @@ void QtGraphEdge::setIsTrailEdge(std::vector path, bool horizontal) m_path = path; m_isTrailEdge = true; m_useBezier = true; - m_isHorizontalTrail = horizontal; + m_isHorizontal = horizontal; } void QtGraphEdge::setUseBezier(bool useBezier) { m_useBezier = useBezier; - m_isHorizontalTrail = true; + m_isHorizontal = true; } diff --git a/src/lib_gui/qt/view/graphElements/QtGraphEdge.h b/src/lib_gui/qt/view/graphElements/QtGraphEdge.h index 7d7c98fc..18e65c28 100644 --- a/src/lib_gui/qt/view/graphElements/QtGraphEdge.h +++ b/src/lib_gui/qt/view/graphElements/QtGraphEdge.h @@ -27,6 +27,7 @@ public: const Edge* data, size_t weight, bool isActive, + bool horizontal, TokenComponentAggregation::Direction direction); virtual ~QtGraphEdge(); @@ -82,12 +83,12 @@ private: bool m_isActive; bool m_isFocused; + bool m_isHorizontal; size_t m_weight; TokenComponentAggregation::Direction m_direction; bool m_isTrailEdge; - bool m_isHorizontalTrail; std::vector m_path; bool m_useBezier;