diff --git a/src/lib/component/controller/GraphController.cpp b/src/lib/component/controller/GraphController.cpp index fd44e795..2d5ad046 100644 --- a/src/lib/component/controller/GraphController.cpp +++ b/src/lib/component/controller/GraphController.cpp @@ -6,8 +6,6 @@ #include "utility/utility.h" #include "utility/utilityString.h" -#include "component/controller/helper/DummyEdge.h" -#include "component/controller/helper/DummyNode.h" #include "component/controller/helper/GraphLayouter.h" #include "component/controller/helper/GraphPostprocessor.h" #include "component/view/GraphView.h" @@ -489,76 +487,151 @@ void GraphController::setNodeVisibilityRecursiveTopDown(DummyNode& node, bool pa void GraphController::bundleNodes() { - bundleNodesAndEdgesMatching( - [&](const DummyNode& node) + // evaluate top level nodes + for (DummyNode& node : m_dummyNodes) + { + if (!node.isGraphNode() || !node.visible) { - return isTypeNodeWithSingleAggregation(node, TokenComponentAggregation::DIRECTION_BACKWARD); - }, - 3, - "Referenced Types" - ); + continue; + } - // bundleNodesAndEdgesMatching( - // [&](const DummyNode& node) - // { - // return isTypeNodeWithSingleAggregation(node, TokenComponentAggregation::DIRECTION_FORWARD); - // }, - // 3, - // "Referencing Types" - // ); + DummyNode::BundleInfo* bundleInfo = &node.bundleInfo; + bundleInfo->isActive = node.hasActiveSubNode(); - bundleNodesAndEdgesMatching( - [&](const DummyNode& node) + node.data->forEachNodeRecursive( + [&bundleInfo](const Node* n) + { + if (n->isDefined()) + { + bundleInfo->isDefined = true; + } + + n->forEachEdgeOfType( + ~Edge::EDGE_MEMBER, + [&bundleInfo, &n](Edge* e) + { + if (e->isType(Edge::EDGE_INHERITANCE | Edge::EDGE_OVERRIDE)) + { + bundleInfo->layoutVertical = true; + } + + if (e->isType(Edge::EDGE_AGGREGATION)) + { + TokenComponentAggregation::Direction dir = + e->getComponent()->getDirection(); + + if (dir == TokenComponentAggregation::DIRECTION_NONE) + { + bundleInfo->isReferenced = true; + bundleInfo->isReferencing = true; + } + else if ((dir == TokenComponentAggregation::DIRECTION_FORWARD && e->getFrom() == n) || + (dir == TokenComponentAggregation::DIRECTION_BACKWARD && e->getTo() == n)) + { + bundleInfo->isReferencing = true; + } + else if ((dir == TokenComponentAggregation::DIRECTION_FORWARD && e->getTo() == n) || + (dir == TokenComponentAggregation::DIRECTION_BACKWARD && e->getFrom() == n)) + { + bundleInfo->isReferenced = true; + } + } + else + { + if (e->getTo() == n) + { + bundleInfo->isReferenced = true; + } + else if (e->getFrom() == n) + { + bundleInfo->isReferencing = true; + } + } + } + ); + } + ); + + if (bundleInfo->isReferenced && bundleInfo->isReferencing) { - return isTypeNodeWithSingleInheritance(node, true); - }, - 3, - "Base Types" - ); + bundleInfo->isReferenced = false; + bundleInfo->isReferencing = false; + } - bundleNodesAndEdgesMatching( - [&](const DummyNode& node) + if (bundleInfo->isActive) { - return isTypeNodeWithSingleInheritance(node, false); - }, - 3, - "Derived Types" - ); + bundleInfo->layoutVertical = false; + } + } + // bundle bundleNodesAndEdgesMatching( - [&](const DummyNode& node) + [](const DummyNode::BundleInfo& info) { - return isUndefinedNode(node, false); + return !info.isDefined && info.isReferencing && !info.layoutVertical; }, 2, "Undefined Symbols" ); bundleNodesAndEdgesMatching( - [&](const DummyNode& node) + [](const DummyNode::BundleInfo& info) { - return isUndefinedNode(node, true); + return !info.isDefined && info.isReferenced && !info.layoutVertical; }, 2, "Undefined Symbols" ); bundleNodesAndEdgesMatching( - [&](const DummyNode& node) + [](const DummyNode::BundleInfo& info) { - return isTypeUserNode(node); + return info.isDefined && info.isReferencing && !info.layoutVertical; }, - 8, + 10, "Referencing Symbols" ); + + bundleNodesAndEdgesMatching( + [](const DummyNode::BundleInfo& info) + { + return info.isDefined && info.isReferenced && !info.layoutVertical; + }, + 10, + "Referenced Symbols" + ); + + bundleNodesAndEdgesMatching( + [](const DummyNode::BundleInfo& info) + { + return info.isReferencing && info.layoutVertical; + }, + 5, + "Derived Symbols" + ); + + bundleNodesAndEdgesMatching( + [](const DummyNode::BundleInfo& info) + { + return info.isReferenced && info.layoutVertical; + }, + 5, + "Base Symbols" + ); } -void GraphController::bundleNodesAndEdgesMatching(std::function matcher, size_t count, const std::string& name) +void GraphController::bundleNodesAndEdgesMatching(std::function matcher, size_t count, const std::string& name) { std::vector matchedNodeIndices; for (size_t i = 0; i < m_dummyNodes.size(); i++) { - if (matcher(m_dummyNodes[i])) + const DummyNode& node = m_dummyNodes[i]; + if (node.bundleInfo.isActive || !node.visible) + { + continue; + } + + if (matcher(node.bundleInfo)) { matchedNodeIndices.push_back(i); } @@ -585,6 +658,7 @@ void GraphController::bundleNodesAndEdgesMatching(std::functiongetId(); + bundleNode.bundleInfo.layoutVertical = bundleNode.bundledNodes[0].bundleInfo.layoutVertical; m_dummyNodes.push_back(bundleNode); if (m_dummyEdges.size() == 0) @@ -671,183 +745,6 @@ void GraphController::bundleNodesMatching(std::list& nodes, std::fun m_dummyNodes.push_back(bundleNode); } -bool GraphController::isTypeNodeWithSingleAggregation( - const DummyNode& node, TokenComponentAggregation::Direction direction -) const { - const Node::NodeTypeMask typeMask = Node::NODE_STRUCT | Node::NODE_CLASS | Node::NODE_TYPEDEF; - - if (!node.visible || !node.isGraphNode() || node.hasVisibleSubNode() || !node.data->isType(typeMask)) - { - return false; - } - - bool matches = false; - int count = 0; - Id tokenId = node.data->getId(); - - node.data->forEachEdgeOfType( - ~Edge::EDGE_MEMBER, - [direction, tokenId, &matches, &count](Edge* edge) - { - count++; - - if (edge->isType(Edge::EDGE_AGGREGATION)) - { - TokenComponentAggregation::Direction dir = - edge->getComponent()->getDirection(); - - if ((edge->getFrom()->getId() == tokenId && dir == direction) || - (edge->getTo()->getId() == tokenId && dir == TokenComponentAggregation::opposite(direction))) - { - matches = true; - } - } - } - ); - - if (count > 1) - { - matches = false; - } - - return matches; -} - -bool GraphController::isTypeNodeWithSingleInheritance(const DummyNode& node, bool isBase) const -{ - const Node::NodeTypeMask typeMask = Node::NODE_STRUCT | Node::NODE_CLASS; - - if (!node.visible || !node.isGraphNode() || node.hasVisibleSubNode() || !node.data->isType(typeMask)) - { - return false; - } - - bool matches = false; - Id tokenId = node.data->getId(); - - node.data->forEachEdgeOfType( - Edge::EDGE_INHERITANCE, - [isBase, tokenId, &matches](Edge* edge) - { - if ((!isBase && edge->getFrom()->getId() == tokenId) || - (isBase && edge->getTo()->getId() == tokenId)) - { - matches = true; - } - } - ); - - return matches; -} - -bool GraphController::isUndefinedNode(const DummyNode& node, bool isUsed) const -{ - if (!node.visible || node.active || !node.isGraphNode() || node.hasActiveSubNode() || node.data->isDefined()) - { - return false; - } - - bool matches = true; - Id tokenId = node.data->getId(); - - node.data->forEachEdge( - [isUsed, tokenId, &matches](Edge* edge) - { - if (edge->isType(Edge::EDGE_MEMBER)) - { - return; - } - - Id fromId = edge->getFrom()->getId(); - Id toId = edge->getTo()->getId(); - - if (edge->isType(Edge::EDGE_AGGREGATION)) - { - TokenComponentAggregation::Direction dir = edge->getComponent()->getDirection(); - - switch (dir) - { - case TokenComponentAggregation::DIRECTION_BACKWARD: - { - Id id = fromId; - fromId = toId; - toId = id; - } - break; - case TokenComponentAggregation::DIRECTION_NONE: - matches = false; - return; - default: - break; - } - } - - if ((!isUsed && toId == tokenId) || - (isUsed && fromId == tokenId)) - { - matches = false; - } - } - ); - - return matches; -} - -bool GraphController::isTypeUserNode(const DummyNode& node) const -{ - if (!node.visible || node.active || !node.isGraphNode() || node.hasActiveSubNode()) - { - return false; - } - - std::vector nodes; - nodes.push_back(node.data); - - node.data->forEachChildNodeRecursive( - [&nodes](Node* n) - { - nodes.push_back(n); - } - ); - - bool matches = true; - for (const Node* n : nodes) - { - Id tokenId = n->getId(); - - n->forEachEdge( - [tokenId, &matches](Edge* edge) - { - if (edge->isType(Edge::EDGE_MEMBER)) - { - return; - } - - if (edge->isType(Edge::EDGE_AGGREGATION)) - { - TokenComponentAggregation::Direction dir = - edge->getComponent()->getDirection(); - if ((dir == TokenComponentAggregation::DIRECTION_FORWARD && edge->getTo()->getId() == tokenId) || - (dir == TokenComponentAggregation::DIRECTION_BACKWARD && edge->getTo()->getId() != tokenId)) - { - matches = false; - } - - return; - } - - if (!edge->isType(Edge::EDGE_TYPE_USAGE | Edge::EDGE_TYPE_OF | Edge::EDGE_TEMPLATE_ARGUMENT | Edge::EDGE_TYPEDEF_OF) || - edge->getTo()->getId() == tokenId) - { - matches = false; - } - } - ); - } - - return matches; -} - #define BUNDLE_BY_TYPE(__nodes__, __type__, __name__) \ bundleNodesMatching( \ __nodes__, \ diff --git a/src/lib/component/controller/GraphController.h b/src/lib/component/controller/GraphController.h index fd7cefc1..9b7cbcf3 100644 --- a/src/lib/component/controller/GraphController.h +++ b/src/lib/component/controller/GraphController.h @@ -17,12 +17,12 @@ #include "utility/messaging/type/MessageShowErrors.h" #include "component/controller/Controller.h" +#include "component/controller/helper/DummyEdge.h" +#include "component/controller/helper/DummyNode.h" #include "component/view/GraphView.h" #include "data/graph/token_component/TokenComponentAccess.h" #include "data/graph/token_component/TokenComponentAggregation.h" -struct DummyNode; -struct DummyEdge; class Graph; class Node; class StorageAccess; @@ -72,12 +72,8 @@ private: void setNodeVisibilityRecursiveTopDown(DummyNode& node, bool parentExpanded) const; void bundleNodes(); - void bundleNodesAndEdgesMatching(std::function matcher, size_t count, const std::string& name); + void bundleNodesAndEdgesMatching(std::function matcher, size_t count, const std::string& name); void bundleNodesMatching(std::list& nodes, std::function matcher, const std::string& name); - bool isTypeNodeWithSingleAggregation(const DummyNode& node, TokenComponentAggregation::Direction direction) const; - bool isTypeNodeWithSingleInheritance(const DummyNode& node, bool isBase) const; - bool isUndefinedNode(const DummyNode& node, bool isUsed) const; - bool isTypeUserNode(const DummyNode& node) const; void bundleNodesByType(); void layoutNesting(); diff --git a/src/lib/component/controller/helper/BucketGrid.cpp b/src/lib/component/controller/helper/BucketGrid.cpp index a606332e..5d7a4fe9 100644 --- a/src/lib/component/controller/helper/BucketGrid.cpp +++ b/src/lib/component/controller/helper/BucketGrid.cpp @@ -4,8 +4,6 @@ #include "component/controller/helper/DummyNode.h" #include "component/view/GraphViewStyle.h" -const Edge::EdgeTypeMask BucketGrid::s_verticalEdgeMask = Edge::EDGE_INHERITANCE | Edge::EDGE_OVERRIDE; - Bucket::Bucket() : i(0) , j(0) @@ -169,7 +167,7 @@ void BucketGrid::createBuckets(std::vector& nodes, const std::vector< } else { - bool horizontal = edge->data ? !edge->data->isType(s_verticalEdgeMask) : true; + bool horizontal = !owner->bundleInfo.layoutVertical && !target->bundleInfo.layoutVertical; removeEdge = addNode(owner, target, horizontal); } diff --git a/src/lib/component/controller/helper/DummyNode.h b/src/lib/component/controller/helper/DummyNode.h index 41e92e20..11abe166 100644 --- a/src/lib/component/controller/helper/DummyNode.h +++ b/src/lib/component/controller/helper/DummyNode.h @@ -13,6 +13,23 @@ class Node; struct DummyNode { public: + struct BundleInfo + { + BundleInfo() + : isActive(false) + , isDefined(false) + , layoutVertical(false) + , isReferenced(false) + , isReferencing(false) + {} + + bool isActive; + bool isDefined; + bool layoutVertical; + bool isReferenced; + bool isReferencing; + }; + DummyNode() : visible(false) , childVisible(false) @@ -200,6 +217,9 @@ public: // ExpandToggleNode size_t invisibleSubNodeCount; + // Bundling + BundleInfo bundleInfo; + // BundleNode std::vector bundledNodes; size_t bundledNodeCount; diff --git a/src/lib/data/graph/Node.cpp b/src/lib/data/graph/Node.cpp index cb8ccf23..a85f4c47 100644 --- a/src/lib/data/graph/Node.cpp +++ b/src/lib/data/graph/Node.cpp @@ -309,15 +309,16 @@ void Node::forEachChildNode(std::function func) const ); } -void Node::forEachChildNodeRecursive(std::function func) const +void Node::forEachNodeRecursive(std::function func) const { + func(this); + forEachEdgeOfType(Edge::EDGE_MEMBER, [func, this](Edge* e) { if (this != e->getTo()) { - func(e->getTo()); - e->getTo()->forEachChildNode(func); + e->getTo()->forEachNodeRecursive(func); } } ); diff --git a/src/lib/data/graph/Node.h b/src/lib/data/graph/Node.h index 8ca75c48..7631a7f0 100644 --- a/src/lib/data/graph/Node.h +++ b/src/lib/data/graph/Node.h @@ -86,7 +86,7 @@ public: void forEachEdge(std::function func) const; void forEachEdgeOfType(Edge::EdgeTypeMask mask, std::function func) const; void forEachChildNode(std::function func) const; - void forEachChildNodeRecursive(std::function func) const; + void forEachNodeRecursive(std::function func) const; bool hasReferences() const;