Files
Sourcetrail/src/lib/component/controller/GraphController.cpp
T
Manuel Dobusch 2c9c83d003 ui: typed edges
Edges in the graph view are now colored according to their type.
2014-07-16 15:38:54 +02:00

249 lines
6.7 KiB
C++

#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"
#include "data/access/GraphAccess.h"
#include "utility/logging/logging.h"
GraphController::GraphController(GraphAccess* graphAccess)
: m_graphAccess(graphAccess)
{
}
GraphController::~GraphController()
{
}
void GraphController::handleMessage(MessageActivateToken* message)
{
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>> 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);
for(unsigned int i = 0; i < callEdges.size(); i++)
{
result.insert(DummyEdge(callEdges[i].first, callEdges[i].second, Edge::EdgeType::EDGE_CALL));
}
for(unsigned int i = 0; i < usageEdges.size(); i++)
{
result.insert(DummyEdge(usageEdges[i].first, usageEdges[i].second, Edge::EdgeType::EDGE_USAGE));
}
for(unsigned int i = 0; i < typeOfEdges.size(); i++)
{
result.insert(DummyEdge(typeOfEdges[i].first, typeOfEdges[i].second, Edge::EdgeType::EDGE_TYPE_OF));
}
for(unsigned int i = 0; i < returnTypeEdges.size(); i++)
{
result.insert(DummyEdge(returnTypeEdges[i].first, returnTypeEdges[i].second, Edge::EdgeType::EDGE_RETURN_TYPE_OF));
}
for(unsigned int i = 0; i < parameterEdges.size(); i++)
{
result.insert(DummyEdge(parameterEdges[i].first, parameterEdges[i].second, Edge::EdgeType::EDGE_PARAMETER_TYPE_OF));
}
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;
}