ui: graph view layouting and member rendering
Added simple layouting functions (implementations for simple grid and circle layout). Also the graph displays class members and connections (edges) to or from them "correctly" now. fortune cookie message = Your exotic ideas will lead you to many exciting new adventures.
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user