|
|
|
@@ -1,5 +1,7 @@
|
|
|
|
|
#include "component/controller/GraphController.h"
|
|
|
|
|
|
|
|
|
|
#include <unordered_set>
|
|
|
|
|
|
|
|
|
|
#include "component/view/graphElements/GraphEdge.h"
|
|
|
|
|
#include "component/view/graphElements/GraphNode.h"
|
|
|
|
|
#include "component/view/GraphView.h"
|
|
|
|
@@ -18,67 +20,235 @@ GraphController::~GraphController()
|
|
|
|
|
|
|
|
|
|
void GraphController::handleMessage(MessageActivateToken* message)
|
|
|
|
|
{
|
|
|
|
|
GraphView* view = getView();
|
|
|
|
|
if (view != NULL)
|
|
|
|
|
{
|
|
|
|
|
std::string name = m_graphAccess->getNameForNodeWithId(message->tokenId);
|
|
|
|
|
std::vector<std::pair<Id, Id> > rawEdges = m_graphAccess->getConnectedEdges(message->tokenId);
|
|
|
|
|
std::vector<Id> neighbourIds = m_graphAccess->getIdsOfNeighbours(message->tokenId);
|
|
|
|
|
|
|
|
|
|
DummyNode node(name, message->tokenId, Vec2i(0,0));
|
|
|
|
|
|
|
|
|
|
std::vector<DummyNode> nodes;
|
|
|
|
|
nodes.push_back(node);
|
|
|
|
|
|
|
|
|
|
std::vector<DummyEdge> edges;
|
|
|
|
|
|
|
|
|
|
int offset = 20; // temporary
|
|
|
|
|
|
|
|
|
|
for(unsigned int i = 0; i < rawEdges.size(); i++)
|
|
|
|
|
{
|
|
|
|
|
edges.push_back(DummyEdge(rawEdges[i].first, rawEdges[i].second));
|
|
|
|
|
|
|
|
|
|
Id newId = 0;
|
|
|
|
|
|
|
|
|
|
if (rawEdges[i].first != message->tokenId)
|
|
|
|
|
{
|
|
|
|
|
name = m_graphAccess->getNameForNodeWithId(rawEdges[i].first);
|
|
|
|
|
newId = rawEdges[i].first;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
name = m_graphAccess->getNameForNodeWithId(rawEdges[i].second);
|
|
|
|
|
newId = rawEdges[i].second;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nodes.push_back(DummyNode(name, newId, Vec2i(0, offset)));
|
|
|
|
|
offset += 20;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// find edges between neighbour nodes
|
|
|
|
|
for(unsigned int i = 1; i < nodes.size(); i++)
|
|
|
|
|
{
|
|
|
|
|
std::vector<std::pair<Id, Id>> newEdges = m_graphAccess->getConnectedEdges(nodes[i].tokenId);
|
|
|
|
|
for(unsigned int j = 0; j < newEdges.size(); j++)
|
|
|
|
|
{
|
|
|
|
|
if (std::find(neighbourIds.begin(), neighbourIds.end(), newEdges[j].first) != neighbourIds.end() &&
|
|
|
|
|
std::find(neighbourIds.begin(), neighbourIds.end(), newEdges[j].second) != neighbourIds.end())
|
|
|
|
|
{
|
|
|
|
|
DummyEdge newEdge(newEdges[j].first, newEdges[j].second);
|
|
|
|
|
|
|
|
|
|
if (std::find(edges.begin(), edges.end(), newEdge) == edges.end())
|
|
|
|
|
{
|
|
|
|
|
edges.push_back(newEdge);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
view->rebuildGraph(nodes, edges);
|
|
|
|
|
}
|
|
|
|
|
createDummyGraph(message->tokenId, &GraphLayouter::layoutSimpleRing);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GraphView* GraphController::getView()
|
|
|
|
|
{
|
|
|
|
|
return Controller::getView<GraphView>();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GraphController::createDummyGraph(const Id activeId, const LayoutFunction layoutFunction)
|
|
|
|
|
{
|
|
|
|
|
GraphView* view = getView();
|
|
|
|
|
if (view != NULL)
|
|
|
|
|
{
|
|
|
|
|
std::vector<DummyNode> nodes;
|
|
|
|
|
std::vector<DummyEdge> edges;
|
|
|
|
|
|
|
|
|
|
nodes.push_back(createDummyNode(activeId));
|
|
|
|
|
|
|
|
|
|
std::vector<DummyNode> neighbours = createNeighbourNodes(nodes[0]);
|
|
|
|
|
nodes.insert(nodes.end(), neighbours.begin(), neighbours.end());
|
|
|
|
|
|
|
|
|
|
layoutFunction(nodes);
|
|
|
|
|
|
|
|
|
|
edges = createEdges(nodes);
|
|
|
|
|
|
|
|
|
|
view->rebuildGraph(nodes, edges);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DummyNode GraphController::createDummyNode(const Id nodeId)
|
|
|
|
|
{
|
|
|
|
|
DummyNode result("invalid", 0, Vec2i());
|
|
|
|
|
|
|
|
|
|
Id topLevelId = findTopLevelNode(nodeId);
|
|
|
|
|
|
|
|
|
|
result = buildNodeTopDown(topLevelId);
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Id GraphController::findTopLevelNode(const Id nodeId)
|
|
|
|
|
{
|
|
|
|
|
std::vector<std::pair<Id, Id>> memberEdges = m_graphAccess->getMemberEdgesOfNode(nodeId);
|
|
|
|
|
|
|
|
|
|
for(unsigned int i = 0; i < memberEdges.size(); i++)
|
|
|
|
|
{
|
|
|
|
|
if(memberEdges[i].first != nodeId)
|
|
|
|
|
{
|
|
|
|
|
return findTopLevelNode(memberEdges[i].first);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nodeId;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DummyNode GraphController::buildNodeTopDown(const Id nodeId)
|
|
|
|
|
{
|
|
|
|
|
DummyNode result("invalid", 0, Vec2i());
|
|
|
|
|
|
|
|
|
|
result.name = m_graphAccess->getNameForNodeWithId(nodeId);
|
|
|
|
|
result.tokenId = nodeId;
|
|
|
|
|
|
|
|
|
|
std::vector<std::pair<Id, Id>> memberEdges = m_graphAccess->getMemberEdgesOfNode(nodeId);
|
|
|
|
|
|
|
|
|
|
for(unsigned int i = 0; i < memberEdges.size(); i++)
|
|
|
|
|
{
|
|
|
|
|
if(memberEdges[i].second != nodeId)
|
|
|
|
|
{
|
|
|
|
|
result.subNodes.push_back(buildNodeTopDown(memberEdges[i].second));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::vector<DummyNode> GraphController::createNeighbourNodes(const Id nodeId)
|
|
|
|
|
{
|
|
|
|
|
std::vector<DummyNode> result;
|
|
|
|
|
|
|
|
|
|
std::vector<std::pair<Id, Id>> edges;
|
|
|
|
|
std::vector<std::pair<Id, Id>> callEdges = m_graphAccess->getCallEdgesOfNode(nodeId);
|
|
|
|
|
std::vector<std::pair<Id, Id>> usageEdges = m_graphAccess->getUsageEdgesOfNode(nodeId);
|
|
|
|
|
std::vector<std::pair<Id, Id>> typeOfEdges = m_graphAccess->getTypeOfEdgesOfNode(nodeId);
|
|
|
|
|
std::vector<std::pair<Id, Id>> returnTypeEdges = m_graphAccess->getReturnTypeOfEdgesOfNode(nodeId);
|
|
|
|
|
std::vector<std::pair<Id, Id>> parameterEdges = m_graphAccess->getParameterOfEdgesOfNode(nodeId);
|
|
|
|
|
|
|
|
|
|
if(callEdges.size() > 0)
|
|
|
|
|
{
|
|
|
|
|
edges.insert(edges.end(), callEdges.begin(), callEdges.end());
|
|
|
|
|
}
|
|
|
|
|
if(usageEdges.size() > 0)
|
|
|
|
|
{
|
|
|
|
|
edges.insert(edges.end(), usageEdges.begin(), usageEdges.end());
|
|
|
|
|
}
|
|
|
|
|
if(typeOfEdges.size() > 0)
|
|
|
|
|
{
|
|
|
|
|
edges.insert(edges.end(), typeOfEdges.begin(), typeOfEdges.end());
|
|
|
|
|
}
|
|
|
|
|
if(returnTypeEdges.size() > 0)
|
|
|
|
|
{
|
|
|
|
|
edges.insert(edges.end(), returnTypeEdges.begin(), returnTypeEdges.end());
|
|
|
|
|
}
|
|
|
|
|
if(parameterEdges.size() > 0)
|
|
|
|
|
{
|
|
|
|
|
edges.insert(edges.end(), parameterEdges.begin(), parameterEdges.end());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for(unsigned int i = 0; i < edges.size(); i++)
|
|
|
|
|
{
|
|
|
|
|
if(edges[i].first == nodeId)
|
|
|
|
|
{
|
|
|
|
|
result.push_back(createDummyNode(edges[i].second));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
result.push_back(createDummyNode(edges[i].first));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::vector<DummyNode> GraphController::createNeighbourNodes(const DummyNode& node)
|
|
|
|
|
{
|
|
|
|
|
std::vector<DummyNode> result;
|
|
|
|
|
|
|
|
|
|
std::set<DummyNode> tmpNodes; // to make it easier to keep the nodes unique
|
|
|
|
|
|
|
|
|
|
result = createNeighbourNodes(node.tokenId);
|
|
|
|
|
for(unsigned int i = 0; i < result.size(); i++)
|
|
|
|
|
{
|
|
|
|
|
tmpNodes.insert(result[i]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for(unsigned int i = 0; i < node.subNodes.size(); i++)
|
|
|
|
|
{
|
|
|
|
|
std::vector<DummyNode> tmpNeighbours = createNeighbourNodes(node.subNodes[i].tokenId);
|
|
|
|
|
for(unsigned int j = 0; j < tmpNeighbours.size(); j++)
|
|
|
|
|
{
|
|
|
|
|
tmpNodes.insert(tmpNeighbours[j]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
result.clear();
|
|
|
|
|
std::set<DummyNode>::iterator it = tmpNodes.begin();
|
|
|
|
|
for(it; it != tmpNodes.end(); it++)
|
|
|
|
|
{
|
|
|
|
|
result.push_back(*it);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::vector<DummyEdge> GraphController::createEdges(const std::vector<DummyNode>& nodes)
|
|
|
|
|
{
|
|
|
|
|
std::vector<DummyEdge> result;
|
|
|
|
|
|
|
|
|
|
std::unordered_set<Id> nodeIds; // to help discard edges that point to non-existing nodes in the sub-graph
|
|
|
|
|
for(unsigned int i = 0; i < nodes.size(); i++)
|
|
|
|
|
{
|
|
|
|
|
nodeIds.insert(nodes[i].tokenId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::set<DummyEdge> tmpEdges; // to make it easier to keep the edges unique
|
|
|
|
|
for(unsigned int i = 0; i < nodes.size(); i++)
|
|
|
|
|
{
|
|
|
|
|
std::set<DummyEdge> tmp = getNeighbourEdgesOfNode(nodes[i]);
|
|
|
|
|
|
|
|
|
|
std::set<DummyEdge>::iterator it = tmp.begin();
|
|
|
|
|
for(it; it != tmp.end(); it++)
|
|
|
|
|
{
|
|
|
|
|
if(nodeIds.find(it->ownerId) != nodeIds.end() && nodeIds.find(it->targetId) != nodeIds.end())
|
|
|
|
|
{
|
|
|
|
|
tmpEdges.insert(tmp.begin(), tmp.end());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::set<DummyEdge>::iterator it = tmpEdges.begin();
|
|
|
|
|
for(it; it != tmpEdges.end(); it++)
|
|
|
|
|
{
|
|
|
|
|
result.push_back(*it);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::set<DummyEdge> GraphController::getNeighbourEdgesOfNode(const DummyNode& node)
|
|
|
|
|
{
|
|
|
|
|
std::set<DummyEdge> result;
|
|
|
|
|
|
|
|
|
|
std::vector<std::pair<Id, Id>> rawEdges;
|
|
|
|
|
std::vector<std::pair<Id, Id>> callEdges = m_graphAccess->getCallEdgesOfNode(node.tokenId);
|
|
|
|
|
std::vector<std::pair<Id, Id>> usageEdges = m_graphAccess->getUsageEdgesOfNode(node.tokenId);
|
|
|
|
|
std::vector<std::pair<Id, Id>> typeOfEdges = m_graphAccess->getTypeOfEdgesOfNode(node.tokenId);
|
|
|
|
|
std::vector<std::pair<Id, Id>> returnTypeEdges = m_graphAccess->getReturnTypeOfEdgesOfNode(node.tokenId);
|
|
|
|
|
std::vector<std::pair<Id, Id>> parameterEdges = m_graphAccess->getParameterOfEdgesOfNode(node.tokenId);
|
|
|
|
|
|
|
|
|
|
if(callEdges.size() > 0)
|
|
|
|
|
{
|
|
|
|
|
rawEdges.insert(rawEdges.end(), callEdges.begin(), callEdges.end());
|
|
|
|
|
}
|
|
|
|
|
if(usageEdges.size() > 0)
|
|
|
|
|
{
|
|
|
|
|
rawEdges.insert(rawEdges.end(), usageEdges.begin(), usageEdges.end());
|
|
|
|
|
}
|
|
|
|
|
if(typeOfEdges.size() > 0)
|
|
|
|
|
{
|
|
|
|
|
rawEdges.insert(rawEdges.end(), typeOfEdges.begin(), typeOfEdges.end());
|
|
|
|
|
}
|
|
|
|
|
if(returnTypeEdges.size() > 0)
|
|
|
|
|
{
|
|
|
|
|
rawEdges.insert(rawEdges.end(), returnTypeEdges.begin(), returnTypeEdges.end());
|
|
|
|
|
}
|
|
|
|
|
if(parameterEdges.size() > 0)
|
|
|
|
|
{
|
|
|
|
|
rawEdges.insert(rawEdges.end(), parameterEdges.begin(), parameterEdges.end());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for(unsigned int i = 0; i < rawEdges.size(); i++)
|
|
|
|
|
{
|
|
|
|
|
result.insert(DummyEdge(rawEdges[i].first, rawEdges[i].second));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for(unsigned int i = 0; i < node.subNodes.size(); i++)
|
|
|
|
|
{
|
|
|
|
|
std::set<DummyEdge> tmpNeighbours = getNeighbourEdgesOfNode(node.subNodes[i]);
|
|
|
|
|
result.insert(tmpNeighbours.begin(), tmpNeighbours.end());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|