diff --git a/src/lib/component/controller/GraphController.cpp b/src/lib/component/controller/GraphController.cpp index 1a01dd00..42ce46f1 100644 --- a/src/lib/component/controller/GraphController.cpp +++ b/src/lib/component/controller/GraphController.cpp @@ -36,6 +36,7 @@ void GraphController::handleMessage(MessageActivateAll* message) bundleNodesByType(); layoutNesting(); + assignBundleIds(); layoutGraph(); buildGraph(message, false); @@ -82,6 +83,7 @@ void GraphController::handleMessage(MessageActivateTokens* message) layoutNesting(); layoutGraph(true); + assignBundleIds(); buildGraph(message, true); } @@ -133,7 +135,7 @@ void GraphController::handleMessage(MessageGraphNodeBundleSplit* message) setActiveAndVisibility(tokenIds); layoutNesting(); - layoutGraph(tokenIds.size() > 0); + layoutGraph(); buildGraph(message, false); } @@ -785,13 +787,13 @@ void GraphController::bundleNodesAndEdgesMatching( std::shared_ptr node = m_dummyNodes[matchedNodeIndices[i]]; node->visible = false; - bundleNode->bundledNodes.push_back(node); + bundleNode->bundledNodes.insert(node); bundleNode->bundledNodeCount += node->getBundledNodeCount(); m_dummyNodes.erase(m_dummyNodes.begin() + matchedNodeIndices[i]); } - DummyNode* firstNode = bundleNode->bundledNodes[0].get(); + DummyNode* firstNode = bundleNode->bundledNodes.begin()->get(); // Use token Id of first node and make first bit 1 bundleNode->tokenId = ~(~size_t(0) >> 1) + firstNode->data->getId(); @@ -875,12 +877,12 @@ std::shared_ptr GraphController::bundleNodesMatching( std::shared_ptr node = *matchedNodes[i]; node->visible = false; - bundleNode->bundledNodes.push_back(node); + bundleNode->bundledNodes.insert(node); 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(); + bundleNode->tokenId = ~(~size_t(0) >> 1) + (*bundleNode->bundledNodes.begin())->data->getId(); return bundleNode; } @@ -973,19 +975,15 @@ void GraphController::bundleNodesByType() for (std::shared_ptr node : nodes) { - bundleNode->bundledNodes.push_back(node); + bundleNode->bundledNodes.insert(node); } if (anonymousBundle) { - anonymousBundle->sortBundleNode(); - bundleNode->bundledNodeCount = bundleNode->getBundledNodeCount() + anonymousBundle->getBundledNodeCount(); - bundleNode->bundledNodes.push_back(anonymousBundle); + bundleNode->bundledNodes.insert(anonymousBundle); } } - - bundleNode->sortBundleNode(); } } @@ -1233,19 +1231,27 @@ void GraphController::layoutToGrid(DummyNode* node) const } } -void GraphController::layoutGraph(bool sort) +void GraphController::layoutGraph(bool getSortedNodes) { TRACE(); BucketGrid grid(getView()->getViewSize()); grid.createBuckets(m_dummyNodes, m_dummyEdges); - - if (sort) - { - grid.sortBuckets(); - } - grid.layoutBuckets(); + + if (getSortedNodes) + { + m_dummyNodes = grid.getSortedNodes(); + } +} + +void GraphController::assignBundleIds() +{ + Id bundleId = 0; + for (size_t i = m_dummyNodes.size(); i > 0; i--) + { + bundleId = m_dummyNodes[i - 1]->setBundleIdRecursive(bundleId); + } } DummyNode* GraphController::getDummyGraphNodeById(Id tokenId) const @@ -1505,7 +1511,7 @@ void GraphController::handleMessage(MessageColorSchemeTest* message) focusedTokenIds.push_back(bundleNode->tokenId); } - bundleNode->bundledNodes.push_back(std::make_shared()); + bundleNode->bundledNodes.insert(std::make_shared()); bundleNode->bundledNodeCount = 123; m_dummyNodes.push_back(bundleNode); } diff --git a/src/lib/component/controller/GraphController.h b/src/lib/component/controller/GraphController.h index 95dfae29..135ba7fe 100644 --- a/src/lib/component/controller/GraphController.h +++ b/src/lib/component/controller/GraphController.h @@ -93,7 +93,8 @@ private: void addExpandToggleNode(DummyNode* node) const; void layoutToGrid(DummyNode* node) const; - void layoutGraph(bool sort = false); + void layoutGraph(bool getSortedNodes = false); + void assignBundleIds(); DummyNode* getDummyGraphNodeById(Id tokenId) const; diff --git a/src/lib/component/controller/helper/BucketGrid.cpp b/src/lib/component/controller/helper/BucketGrid.cpp index 875592a8..335161f9 100644 --- a/src/lib/component/controller/helper/BucketGrid.cpp +++ b/src/lib/component/controller/helper/BucketGrid.cpp @@ -1,9 +1,6 @@ #include "component/controller/helper/BucketGrid.h" -#include "utility/utilityString.h" - #include "component/controller/helper/DummyEdge.h" -#include "component/controller/helper/DummyNode.h" #include "component/view/GraphViewStyle.h" Bucket::Bucket() @@ -32,9 +29,9 @@ int Bucket::getHeight() const return m_height; } -bool Bucket::hasNode(DummyNode* node) const +bool Bucket::hasNode(std::shared_ptr node) const { - for (DummyNode* n : m_nodes) + for (std::shared_ptr n : m_nodes) { if (node == n) { @@ -45,33 +42,17 @@ bool Bucket::hasNode(DummyNode* node) const return false; } -void Bucket::addNode(DummyNode* node) +void Bucket::addNode(std::shared_ptr node) { - m_nodes.push_back(node); + m_nodes.insert(node); m_width = (node->size.x > m_width ? node->size.x : m_width); m_height += node->size.y + GraphViewStyle::toGridGap(10); } -void Bucket::sort() +const DummyNode::BundledNodesSet& Bucket::getNodes() const { - std::sort(m_nodes.begin(), m_nodes.end(), - [](const DummyNode* a, const DummyNode* b) -> bool - { - if ((a->isGraphNode() && b->isGraphNode()) || (a->isBundleNode() && b->isBundleNode())) - { - return utility::toLowerCase(a->name) < utility::toLowerCase(b->name); - } - else if (a->isGraphNode()) - { - return true; - } - else - { - return false; - } - } - ); + return m_nodes; } void Bucket::preLayout(Vec2i viewSize) @@ -85,7 +66,7 @@ void Bucket::preLayout(Vec2i viewSize) m_height = 0; - for (DummyNode* node : m_nodes) + for (std::shared_ptr node : m_nodes) { node->position.x = x; node->position.y = y; @@ -112,7 +93,7 @@ void Bucket::layout(int x, int y, int width, int height) int cx = GraphViewStyle::toGridOffset(x + (width - m_width) / 2); int cy = GraphViewStyle::toGridOffset(y + (height - m_height) / 2); - for (DummyNode* node : m_nodes) + for (std::shared_ptr node : m_nodes) { node->position.x = node->position.x + cx; node->position.y = node->position.y + cy; @@ -143,7 +124,7 @@ void BucketGrid::createBuckets( { if (node->hasActiveSubNode() || !edges.size()) { - addNode(node.get()); + addNode(node); activeNodeAdded = true; } } @@ -155,7 +136,7 @@ void BucketGrid::createBuckets( if (!activeNodeAdded) { - addNode(nodes[0].get()); + addNode(nodes[0]); } std::vector remainingEdges; @@ -169,8 +150,8 @@ void BucketGrid::createBuckets( { const DummyEdge* edge = remainingEdges[i]; - DummyNode* owner = findTopMostDummyNodeRecursive(nodes, edge->ownerId); - DummyNode* target = findTopMostDummyNodeRecursive(nodes, edge->targetId); + std::shared_ptr owner = findTopMostDummyNodeRecursive(nodes, edge->ownerId, nullptr); + std::shared_ptr target = findTopMostDummyNodeRecursive(nodes, edge->targetId, nullptr); bool removeEdge = false; if (!owner || !target) @@ -213,17 +194,6 @@ void BucketGrid::createBuckets( } } -void BucketGrid::sortBuckets() -{ - for (int j = m_j1; j <= m_j2; j++) - { - for (int i = m_i1; i <= m_i2; i++) - { - m_buckets[j][i].sort(); - } - } -} - void BucketGrid::layoutBuckets() { std::map widths; @@ -275,19 +245,35 @@ void BucketGrid::layoutBuckets() } } -DummyNode* BucketGrid::findTopMostDummyNodeRecursive( - std::vector>& nodes, Id tokenId, DummyNode* top +std::vector> BucketGrid::getSortedNodes() +{ + std::vector> sortedNodes; + + for (int j = m_j1; j <= m_j2; j++) + { + for (int i = m_i1; i <= m_i2; i++) + { + DummyNode::BundledNodesSet nodes = m_buckets[j][i].getNodes(); + sortedNodes.insert(sortedNodes.end(), nodes.begin(), nodes.end()); + } + } + + return sortedNodes; +} + +std::shared_ptr BucketGrid::findTopMostDummyNodeRecursive( + std::vector>& nodes, Id tokenId, std::shared_ptr top ){ for (std::shared_ptr node : nodes) { - DummyNode* t = (top ? top : node.get()); + std::shared_ptr t = (top ? top : node); if (node->visible && node->tokenId == tokenId) { return t; } - DummyNode* result = findTopMostDummyNodeRecursive(node->subNodes, tokenId, t); + std::shared_ptr result = findTopMostDummyNodeRecursive(node->subNodes, tokenId, t); if (result != nullptr) { return result; @@ -297,13 +283,13 @@ DummyNode* BucketGrid::findTopMostDummyNodeRecursive( return nullptr; } -void BucketGrid::addNode(DummyNode* node) +void BucketGrid::addNode(std::shared_ptr node) { Bucket* bucket = getBucket(node->layoutBucket.x, node->layoutBucket.y); bucket->addNode(node); } -bool BucketGrid::addNode(DummyNode* owner, DummyNode* target, bool horizontal) +bool BucketGrid::addNode(std::shared_ptr owner, std::shared_ptr target, bool horizontal) { Bucket* ownerBucket = getBucket(owner); Bucket* targetBucket = getBucket(target); @@ -389,7 +375,7 @@ Bucket* BucketGrid::getBucket(int i, int j) return nullptr; } -Bucket* BucketGrid::getBucket(DummyNode* node) +Bucket* BucketGrid::getBucket(std::shared_ptr node) { for (int j = m_j1; j <= m_j2; j++) { diff --git a/src/lib/component/controller/helper/BucketGrid.h b/src/lib/component/controller/helper/BucketGrid.h index 1be46be6..ebc5020c 100644 --- a/src/lib/component/controller/helper/BucketGrid.h +++ b/src/lib/component/controller/helper/BucketGrid.h @@ -6,10 +6,10 @@ #include "utility/math/Vector2.h" #include "utility/types.h" +#include "component/controller/helper/DummyNode.h" #include "data/graph/Edge.h" struct DummyEdge; -struct DummyNode; class Bucket { @@ -20,10 +20,9 @@ public: int getWidth() const; int getHeight() const; - bool hasNode(DummyNode* node) const; - void addNode(DummyNode* node); - - void sort(); + bool hasNode(std::shared_ptr node) const; + void addNode(std::shared_ptr node); + const DummyNode::BundledNodesSet& getNodes() const; void preLayout(Vec2i viewSize); void layout(int x, int y, int width, int height); @@ -35,7 +34,7 @@ private: int m_width; int m_height; - std::vector m_nodes; + DummyNode::BundledNodesSet m_nodes; }; @@ -46,18 +45,19 @@ public: void createBuckets( std::vector>& nodes, const std::vector>& edges); - void sortBuckets(); void layoutBuckets(); -private: - DummyNode* findTopMostDummyNodeRecursive( - std::vector>& nodes, Id tokenId, DummyNode* top = nullptr); + std::vector> getSortedNodes(); - void addNode(DummyNode* node); - bool addNode(DummyNode* owner, DummyNode* target, bool horizontal); +private: + std::shared_ptr findTopMostDummyNodeRecursive( + std::vector>& nodes, Id tokenId, std::shared_ptr top); + + void addNode(std::shared_ptr node); + bool addNode(std::shared_ptr owner, std::shared_ptr target, bool horizontal); Bucket* getBucket(int i, int j); - Bucket* getBucket(DummyNode* node); + Bucket* getBucket(std::shared_ptr node); Vec2i m_viewSize; std::map> m_buckets; diff --git a/src/lib/component/controller/helper/DummyNode.h b/src/lib/component/controller/helper/DummyNode.h index e7e0d397..a29e9604 100644 --- a/src/lib/component/controller/helper/DummyNode.h +++ b/src/lib/component/controller/helper/DummyNode.h @@ -15,6 +15,25 @@ class Node; struct DummyNode { public: + struct DummyNodeComp + { + bool operator()(const std::shared_ptr a, const std::shared_ptr b) const + { + if (a->bundleId != b->bundleId) + { + return a->bundleId > b->bundleId; + } + else if (a->isBundleNode() != b->isBundleNode()) + { + return a->isBundleNode(); + } + + return utility::toLowerCase(a->name) < utility::toLowerCase(b->name); + } + }; + + typedef std::set, DummyNodeComp> BundledNodesSet; + struct BundleInfo { BundleInfo() @@ -46,6 +65,7 @@ public: , hasQualifier(false) , accessKind(ACCESS_NONE) , invisibleSubNodeCount(0) + , bundleId(0) , layoutBucket(0, 0) , bundledNodeCount(0) { @@ -184,21 +204,6 @@ 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); @@ -209,6 +214,23 @@ public: } } + Id setBundleIdRecursive(Id bundleId) + { + if (isBundleNode()) + { + bundleId++; + } + + this->bundleId = bundleId; + + for (std::shared_ptr node : bundledNodes) + { + bundleId = node->setBundleIdRecursive(bundleId); + } + + return bundleId; + } + Vec2i position; Vec2i size; @@ -239,12 +261,13 @@ public: // Bundling BundleInfo bundleInfo; + Id bundleId; // Layout Vec2i layoutBucket; // BundleNode - std::vector> bundledNodes; + BundledNodesSet bundledNodes; size_t bundledNodeCount; // QualifierNode