diff --git a/src/lib/component/controller/GraphController.cpp b/src/lib/component/controller/GraphController.cpp index 130d40e4..3979353a 100644 --- a/src/lib/component/controller/GraphController.cpp +++ b/src/lib/component/controller/GraphController.cpp @@ -779,7 +779,7 @@ void GraphController::bundleNodesAndEdgesMatching( m_dummyEdges.insert(m_dummyEdges.end(), bundleEdges.begin(), bundleEdges.end()); } -void GraphController::bundleNodesMatching( +std::shared_ptr GraphController::bundleNodesMatching( std::list>& nodes, std::function matcher, const std::string& name ){ std::vector>::iterator> matchedNodes; @@ -793,7 +793,7 @@ void GraphController::bundleNodesMatching( if (!matchedNodes.size()) { - return; + return nullptr; } std::shared_ptr bundleNode = std::make_shared(); @@ -806,25 +806,31 @@ void GraphController::bundleNodesMatching( node->visible = false; bundleNode->bundledNodes.push_back(node); - bundleNode->bundledNodeCount += node->getConnectedSubNodeCount(); - nodes.erase(matchedNodes[i]); } // Use token Id of first node and make first bit 1 bundleNode->tokenId = ~(~size_t(0) >> 1) + bundleNode->bundledNodes[0]->data->getId(); - m_dummyNodes.push_back(bundleNode); + return bundleNode; } -#define BUNDLE_BY_TYPE(__nodes__, __type__, __name__) \ - bundleNodesMatching( \ - __nodes__, \ - [&](const DummyNode* node) \ - { \ - return node->visible && node->isGraphNode() && node->data->isType(__type__); \ - }, \ - __name__ \ - ); \ +void GraphController::bundleByType( + std::list>& nodes, Node::NodeType type, const std::string& name) +{ + std::shared_ptr bundleNode = bundleNodesMatching( + nodes, + [&](const DummyNode* node) + { + return node->visible && node->isGraphNode() && node->data->isType(type); + }, + name + ); + + if (bundleNode) + { + m_dummyNodes.push_back(bundleNode); + } +} void GraphController::bundleNodesByType() { @@ -839,43 +845,77 @@ void GraphController::bundleNodesByType() nodes.push_back(oldNodes[i]); } - BUNDLE_BY_TYPE(nodes, Node::NODE_NAMESPACE, "Namespaces"); - BUNDLE_BY_TYPE(nodes, Node::NODE_PACKAGE, "Packages"); - BUNDLE_BY_TYPE(nodes, Node::NODE_BUILTIN_TYPE, "Builtin Types"); - BUNDLE_BY_TYPE(nodes, Node::NODE_CLASS, "Classes"); - BUNDLE_BY_TYPE(nodes, Node::NODE_INTERFACE, "Interfaces"); - BUNDLE_BY_TYPE(nodes, Node::NODE_STRUCT, "Structs"); + bundleByType(nodes, Node::NODE_NAMESPACE, "Namespaces"); + bundleByType(nodes, Node::NODE_PACKAGE, "Packages"); + bundleByType(nodes, Node::NODE_BUILTIN_TYPE, "Builtin Types"); + bundleByType(nodes, Node::NODE_CLASS, "Classes"); + bundleByType(nodes, Node::NODE_INTERFACE, "Interfaces"); + bundleByType(nodes, Node::NODE_STRUCT, "Structs"); - BUNDLE_BY_TYPE(nodes, Node::NODE_FUNCTION, "Functions"); - BUNDLE_BY_TYPE(nodes, Node::NODE_GLOBAL_VARIABLE, "Global Variables"); + bundleByType(nodes, Node::NODE_FUNCTION, "Functions"); + bundleByType(nodes, Node::NODE_GLOBAL_VARIABLE, "Global Variables"); - BUNDLE_BY_TYPE(nodes, Node::NODE_TYPE, "Types"); - BUNDLE_BY_TYPE(nodes, Node::NODE_TYPEDEF, "Typedefs"); - BUNDLE_BY_TYPE(nodes, Node::NODE_ENUM, "Enums"); + bundleByType(nodes, Node::NODE_TYPE, "Types"); + bundleByType(nodes, Node::NODE_TYPEDEF, "Typedefs"); + bundleByType(nodes, Node::NODE_ENUM, "Enums"); - BUNDLE_BY_TYPE(nodes, Node::NODE_FILE, "Files"); - BUNDLE_BY_TYPE(nodes, Node::NODE_MACRO, "Macros"); + bundleByType(nodes, Node::NODE_FILE, "Files"); + bundleByType(nodes, Node::NODE_MACRO, "Macros"); // // should never be visible - BUNDLE_BY_TYPE(nodes, Node::NODE_METHOD, "Methods"); - BUNDLE_BY_TYPE(nodes, Node::NODE_FIELD, "Fields"); - BUNDLE_BY_TYPE(nodes, Node::NODE_ENUM_CONSTANT, "Enum Constants"); - BUNDLE_BY_TYPE(nodes, Node::NODE_TEMPLATE_PARAMETER_TYPE, "Template Parameter Types"); - BUNDLE_BY_TYPE(nodes, Node::NODE_TYPE_PARAMETER, "Type Parameters"); - BUNDLE_BY_TYPE(nodes, Node::NODE_UNDEFINED, "Undefined Symbols"); + bundleByType(nodes, Node::NODE_METHOD, "Methods"); + bundleByType(nodes, Node::NODE_FIELD, "Fields"); + bundleByType(nodes, Node::NODE_ENUM_CONSTANT, "Enum Constants"); + bundleByType(nodes, Node::NODE_TEMPLATE_PARAMETER_TYPE, "Template Parameter Types"); + bundleByType(nodes, Node::NODE_TYPE_PARAMETER, "Type Parameters"); + bundleByType(nodes, Node::NODE_UNDEFINED, "Undefined Symbols"); - for (std::shared_ptr node : m_dummyNodes) + if (nodes.size()) { - if (node->isBundleNode()) + LOG_ERROR("Nodes left after bundling for overview"); + } + + for (std::shared_ptr bundleNode : m_dummyNodes) + { + if (!bundleNode->isBundleNode()) { - sort(node->bundledNodes.begin(), node->bundledNodes.end(), - [](const std::shared_ptr a, const std::shared_ptr b) -> bool - { - return utility::toLowerCase(a->name) < utility::toLowerCase(b->name); - } - ); + LOG_ERROR("Non-Bundle node in overview"); } + + if (bundleNode->name == "Namespaces") + { + std::list> nodes; + for (std::shared_ptr node : bundleNode->bundledNodes) + { + nodes.push_back(node); + } + bundleNode->bundledNodes.clear(); + + std::shared_ptr anonymousBundle = bundleNodesMatching( + nodes, + [&](const DummyNode* node) + { + return utility::isPrefix("anonymous", node->name); + }, + "Anonymous Namespaces" + ); + + for (std::shared_ptr node : nodes) + { + bundleNode->bundledNodes.push_back(node); + } + + if (anonymousBundle) + { + anonymousBundle->sortBundleNode(); + + bundleNode->bundledNodeCount = bundleNode->getBundledNodeCount() + anonymousBundle->getBundledNodeCount(); + bundleNode->bundledNodes.push_back(anonymousBundle); + } + } + + bundleNode->sortBundleNode(); } } diff --git a/src/lib/component/controller/GraphController.h b/src/lib/component/controller/GraphController.h index 37abab70..76a7dc43 100644 --- a/src/lib/component/controller/GraphController.h +++ b/src/lib/component/controller/GraphController.h @@ -21,11 +21,11 @@ #include "component/controller/helper/DummyEdge.h" #include "component/controller/helper/DummyNode.h" #include "component/view/GraphView.h" +#include "data/graph/Node.h" #include "data/graph/token_component/TokenComponentAccess.h" #include "data/graph/token_component/TokenComponentAggregation.h" class Graph; -class Node; class StorageAccess; class GraphController @@ -81,7 +81,8 @@ private: void bundleNodes(); void bundleNodesAndEdgesMatching(std::function matcher, size_t count, const std::string& name); - void bundleNodesMatching(std::list>& nodes, std::function matcher, const std::string& name); + std::shared_ptr bundleNodesMatching(std::list>& nodes, std::function matcher, const std::string& name); + void bundleByType(std::list>& nodes, Node::NodeType type, const std::string& name); void bundleNodesByType(); void layoutNesting(); diff --git a/src/lib/component/controller/helper/DummyNode.h b/src/lib/component/controller/helper/DummyNode.h index 62b96fa8..7414ca36 100644 --- a/src/lib/component/controller/helper/DummyNode.h +++ b/src/lib/component/controller/helper/DummyNode.h @@ -4,6 +4,7 @@ #include "utility/math/Vector2.h" #include "utility/types.h" #include "utility/utility.h" +#include "utility/utilityString.h" #include "data/graph/token_component/TokenComponentAccess.h" @@ -192,6 +193,21 @@ public: return bundledNodes.size(); } + void sortBundleNode() + { + sort(bundledNodes.begin(), bundledNodes.end(), + [](const std::shared_ptr a, const std::shared_ptr b) -> bool + { + if (a->isBundleNode() != b->isBundleNode()) + { + return a->isBundleNode(); + } + + return utility::toLowerCase(a->name) < utility::toLowerCase(b->name); + } + ); + } + void forEachDummyNodeRecursive(std::function func) { func(this); diff --git a/src/lib_gui/qt/view/graphElements/QtGraphNodeExpandToggle.cpp b/src/lib_gui/qt/view/graphElements/QtGraphNodeExpandToggle.cpp index 872cdb26..b0634e11 100644 --- a/src/lib_gui/qt/view/graphElements/QtGraphNodeExpandToggle.cpp +++ b/src/lib_gui/qt/view/graphElements/QtGraphNodeExpandToggle.cpp @@ -62,6 +62,11 @@ void QtGraphNodeExpandToggle::onClick() void QtGraphNodeExpandToggle::updateStyle() { + if (!m_icon) + { + return; + } + GraphViewStyle::NodeStyle style = GraphViewStyle::getStyleOfExpandToggleNode(); setStyle(style);