diff --git a/bin/app/data/src/header.h b/bin/app/data/src/header.h index b14f1759..bd6cb688 100644 --- a/bin/app/data/src/header.h +++ b/bin/app/data/src/header.h @@ -13,10 +13,6 @@ y fooy(); z fooz(); */ -class A {}; -class B : public A {}; -typedef A* C; - const bool *ab(int a, int b); bool const *abc(int a, int b); @@ -27,3 +23,66 @@ int main(); void foo(); int sum(int a, int b); int diff(int a, int b); + +void funk(); + +class A +{ +public: + A() + : m_importantValue(42) + , m_importanterValue('r') + , m_importantestValue(3.14159265359f) + { + } + + ~A() + { + } + + void doImportantStuff() + { + m_importantValue *= 1; + } + + void doModeratelyImportantStuff() + { + m_importanterValue = 'R'; + + sum(21, 21); + } + +private: + int m_importantValue; + char m_importanterValue; + float m_importantestValue; +}; + +class B : public A {}; + +class C +{ +public: + C() + : m_valuable(0) + { + } + + ~C() + { + } + + void solveAllProblems() + { + A aInstance; + aInstance.doImportantStuff(); + aInstance.doModeratelyImportantStuff(); + } + +private: + int m_valuable; +}; + +A globalA; + +typedef A* C; diff --git a/bin/app/data/src/main.cpp b/bin/app/data/src/main.cpp index 0dd91d90..c122ff93 100644 --- a/bin/app/data/src/main.cpp +++ b/bin/app/data/src/main.cpp @@ -7,6 +7,9 @@ int diff(int a, int b); int main() { + A aInstance; + aInstance.doImportantStuff(); + int a = sum(1, 2); int b = diff(a, 3); int c = a * b; @@ -33,3 +36,9 @@ int diff(int a, int b) { return a - b; } + +void funk() +{ + A aInstance; + aInstance.doModeratelyImportantStuff(); +} diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt index 6a49ccad..872ec856 100644 --- a/src/app/CMakeLists.txt +++ b/src/app/CMakeLists.txt @@ -22,8 +22,8 @@ add_files( qt/view/graphElements/QtGraphEdge.h qt/view/graphElements/QtGraphNode.cpp qt/view/graphElements/QtGraphNode.h - qt/view/graphElements/QtGraphNodeMovable.cpp - qt/view/graphElements/QtGraphNodeMovable.h + qt/view/graphElements/QtGraphNodeMouseMovable.cpp + qt/view/graphElements/QtGraphNodeMouseMovable.h qt/view/QtCodeView.cpp qt/view/QtCodeView.h diff --git a/src/app/qt/view/QtGraphView.cpp b/src/app/qt/view/QtGraphView.cpp index 647afb68..0ea56f71 100644 --- a/src/app/qt/view/QtGraphView.cpp +++ b/src/app/qt/view/QtGraphView.cpp @@ -12,7 +12,7 @@ #include "qt/QtWidgetWrapper.h" #include "qt/view/graphElements/QtGraphEdge.h" #include "qt/view/graphElements/QtGraphNode.h" -#include "qt/view/graphElements/QtGraphNodeMovable.h" +#include "qt/view/graphElements/QtGraphNodeMouseMovable.h" QtGraphView::QtGraphView(ViewLayout* viewLayout) : GraphView(viewLayout) @@ -83,6 +83,7 @@ void QtGraphView::doRebuildGraph(const std::vector& nodes, const std: for(unsigned int i = 0; i < nodes.size(); i++) { std::shared_ptr newNode = findOrCreateNode(view, nodes[i]); + newNode->setPosition(nodes[i].position); newNodes.push_back(newNode); weakNodes[nodes[i].tokenId] = newNode; } @@ -90,8 +91,17 @@ void QtGraphView::doRebuildGraph(const std::vector& nodes, const std: doClear(); m_nodes = newNodes; - // create edges for(unsigned int i = 0; i < edges.size(); i++) + { + std::shared_ptr edge = createEdge(view, edges[i]); + if(edge != NULL) + { + m_edges.push_back(edge); + } + } + + // create edges + /*for(unsigned int i = 0; i < edges.size(); i++) { if (weakNodes.find(edges[i].ownerId) != weakNodes.end() && weakNodes.find(edges[i].targetId) != weakNodes.end()) { @@ -106,7 +116,7 @@ void QtGraphView::doRebuildGraph(const std::vector& nodes, const std: } } } - } + }*/ } else { @@ -124,7 +134,7 @@ std::shared_ptr QtGraphView::findOrCreateNode(QGraphicsView* view, co { std::shared_ptr result; - result = findNode(node); + result = findNode(node.tokenId); if(result == NULL) { @@ -134,41 +144,131 @@ std::shared_ptr QtGraphView::findOrCreateNode(QGraphicsView* view, co return result; } -std::shared_ptr QtGraphView::findNode(const DummyNode& node) +std::shared_ptr QtGraphView::findNode(const Id id) { std::list>::iterator it = m_nodes.begin(); for(it; it != m_nodes.end(); it++) { - if((*it)->getTokenId() == node.tokenId) + if((*it)->getTokenId() == id) { return *it; } + else + { + std::shared_ptr result = findSubNode(*it, id); + if(result != NULL) + { + return result; + } + } } - return NULL; + return std::shared_ptr(); +} + +std::shared_ptr QtGraphView::findSubNode(const std::shared_ptr node, const Id id) +{ + std::list> subNodes = node->getSubNodes(); + + std::list>::iterator it = subNodes.begin(); + for(it; it != subNodes.end(); it++) + { + if((*it)->getTokenId() == id) + { + return *it; + } + else + { + std::shared_ptr result = findSubNode(*it, id); + if(result != NULL) + { + return result; + } + } + } + + return std::shared_ptr(); } std::shared_ptr QtGraphView::createNode(QGraphicsView* view, const DummyNode& node) { if(view != NULL) { - std::shared_ptr newNode = std::make_shared(node.position, node.name, node.tokenId); + std::shared_ptr newNode = std::make_shared(Vec2i(0, 0), node.name, node.tokenId); view->scene()->addItem(newNode.get()); m_nodes.push_back(newNode); - // create debug sub node - std::shared_ptr subNode = std::make_shared(Vec2i(10, 30), node.name + " member", 666); - subNode->setParentItem(newNode.get()); - view->scene()->addItem(subNode.get()); - newNode->addSubNode(subNode); + for(unsigned int i = 0; i < node.subNodes.size(); i++) + { + std::shared_ptr subNode = createSubNode(view, node.subNodes[i]); + subNode->setParentItem(newNode.get()); + newNode->addSubNode(subNode); + subNode->setRect(0, 0, 80, 20); + subNode->moveBy(10, (i+1)*30); + } - subNode->setRect(0, 0, 80, 20); + newNode->setRect(0, 0, 100, 40 + (node.subNodes.size() * 30)); return newNode; } else { LOG_WARNING("Received pointer to QGraphicsView was NULL. No node created."); + return std::shared_ptr(); + } +} + +std::shared_ptr QtGraphView::createSubNode(QGraphicsView* view, const DummyNode& node) +{ + if(view != NULL) + { + std::shared_ptr newNode = std::make_shared(Vec2i(0, 0), node.name, node.tokenId); + view->scene()->addItem(newNode.get()); + + for(unsigned int i = 0; i < node.subNodes.size(); i++) + { + std::shared_ptr subNode = createSubNode(view, node.subNodes[i]); + subNode->setParentItem(newNode.get()); + newNode->addSubNode(subNode); + subNode->setRect(0, 0, 80, 20); + subNode->moveBy(10, (i+1)*30); + } + + return newNode; + } + else + { + LOG_WARNING("Received pointer to QGraphicsView was NULL. No node created."); + return std::shared_ptr(); + } +} + +std::shared_ptr QtGraphView::createEdge(QGraphicsView* view, const DummyEdge& edge) +{ + if(view != NULL) + { + std::shared_ptr owner = findNode(edge.ownerId); + std::shared_ptr target = findNode(edge.targetId); + + if(owner != NULL && target != NULL) + { + std::shared_ptr edge = std::make_shared(owner, target); + owner->addOutEdge(edge); + target->addInEdge(edge); + view->scene()->addItem(edge.get()); + + return edge; + } + else + { + LOG_WARNING("Couldn't find owner or target node."); + return std::shared_ptr(); + } + } + else + { + LOG_WARNING("Received pointer to QGraphicsView was NULL. No node created."); + return std::shared_ptr(); } } diff --git a/src/app/qt/view/QtGraphView.h b/src/app/qt/view/QtGraphView.h index 9c94f402..d07d2319 100644 --- a/src/app/qt/view/QtGraphView.h +++ b/src/app/qt/view/QtGraphView.h @@ -3,11 +3,15 @@ #include "qt/utility/QtThreadedFunctor.h" +#include "utility/types.h" + #include "component/view/GraphView.h" struct DummyEdge; struct DummyNode; class QGraphicsView; +class QtGraphEdge; +class QtGraphNode; class QtGraphView : public GraphView { @@ -30,8 +34,12 @@ private: void doClear(); std::shared_ptr findOrCreateNode(QGraphicsView* view, const DummyNode& node); - std::shared_ptr findNode(const DummyNode& node); + std::shared_ptr findNode(const Id id); + std::shared_ptr findSubNode(const std::shared_ptr node, const Id id); std::shared_ptr createNode(QGraphicsView* view, const DummyNode& node); + std::shared_ptr createSubNode(QGraphicsView* view, const DummyNode& node); + + std::shared_ptr createEdge(QGraphicsView* view, const DummyEdge& edge); QtThreadedFunctor&, const std::vector&> m_rebuildGraph; QtThreadedFunctor m_clear; diff --git a/src/app/qt/view/graphElements/QtGraphNode.cpp b/src/app/qt/view/graphElements/QtGraphNode.cpp index 621ed802..3935b0ef 100644 --- a/src/app/qt/view/graphElements/QtGraphNode.cpp +++ b/src/app/qt/view/graphElements/QtGraphNode.cpp @@ -1,5 +1,7 @@ #include "qt/view/graphElements/QtGraphNode.h" +#include + #include "qgraphicsscene.h" #include "qgraphicssceneevent.h" @@ -15,7 +17,9 @@ QtGraphNode::QtGraphNode(const Vec2i& position, const std::string& name, const I m_text = new QGraphicsTextItem(this); m_text->setPos(0, 0); - m_text->setPlainText(QString(name.c_str())); + std::stringstream text; + text << m_tokenId << " -> " << name; + m_text->setPlainText(QString(text.str().c_str())); } QtGraphNode::~QtGraphNode() @@ -31,16 +35,28 @@ QtGraphNode::~QtGraphNode() } } -std::string QtGraphNode::getName() +std::string QtGraphNode::getName() const { return m_text->toPlainText().toStdString(); } -Vec2i QtGraphNode::getPosition() +Vec2i QtGraphNode::getPosition() const { return Vec2i(this->scenePos().x(), this->scenePos().y()); } +void QtGraphNode::setPosition(const Vec2i& position) +{ + Vec2i currentPosition = getPosition(); + Vec2i offset = position - currentPosition; + + if(offset.getLength() > 0.0f) + { + this->moveBy(offset.x, offset.y); + notifyEdgesAfterMove(); + } +} + bool QtGraphNode::addOutEdge(const std::shared_ptr& edge) { std::list >::iterator it = m_outEdges.begin(); @@ -91,6 +107,11 @@ void QtGraphNode::removeOutEdge(GraphEdge* edge) } } +std::list > QtGraphNode::getSubNodes() const +{ + return m_subNodes; +} + void QtGraphNode::addSubNode(const std::shared_ptr& node) { m_subNodes.push_back(node); @@ -101,3 +122,38 @@ void QtGraphNode::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event) MessageActivateToken message(m_tokenId); message.dispatch(); } + +void QtGraphNode::notifyParentMoved() +{ + notifyEdgesAfterMove(); +} + +void QtGraphNode::notifyEdgesAfterMove() +{ + std::list >::iterator it = m_outEdges.begin(); + for(it; it != m_outEdges.end(); it++) + { + (*it)->ownerMoved(); + } + + std::list >::iterator it2 = m_inEdges.begin(); + while(it2 != m_inEdges.end()) + { + std::shared_ptr edge = it2->lock(); + if(edge.get() != NULL) + { + edge->targetMoved(); + ++it2; + } + else + { + m_inEdges.erase(it2++); + } + } + + std::list >::iterator it3 = m_subNodes.begin(); + for(it3; it3 != m_subNodes.end(); it3++) + { + (*it3)->notifyParentMoved(); + } +} diff --git a/src/app/qt/view/graphElements/QtGraphNode.h b/src/app/qt/view/graphElements/QtGraphNode.h index da8e5e03..bbde5eed 100644 --- a/src/app/qt/view/graphElements/QtGraphNode.h +++ b/src/app/qt/view/graphElements/QtGraphNode.h @@ -18,19 +18,25 @@ public: QtGraphNode(const Vec2i& position, const std::string& name, const Id tokenId); virtual ~QtGraphNode(); - virtual std::string getName(); - virtual Vec2i getPosition(); + virtual std::string getName() const; + virtual Vec2i getPosition() const; + virtual void setPosition(const Vec2i& position); virtual bool addOutEdge(const std::shared_ptr& edge); virtual bool addInEdge(const std::weak_ptr& edge); virtual void removeOutEdge(GraphEdge* edge); + virtual std::list > getSubNodes() const; virtual void addSubNode(const std::shared_ptr& node); void mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event); + virtual void notifyParentMoved(); + protected: + void notifyEdgesAfterMove(); + std::list > m_outEdges; std::list > m_inEdges; diff --git a/src/app/qt/view/graphElements/QtGraphNodeMouseMovable.cpp b/src/app/qt/view/graphElements/QtGraphNodeMouseMovable.cpp new file mode 100644 index 00000000..c0f6f319 --- /dev/null +++ b/src/app/qt/view/graphElements/QtGraphNodeMouseMovable.cpp @@ -0,0 +1,29 @@ +#include "qt/view/graphElements/QtGraphNodeMouseMovable.h" + +#include "qgraphicssceneevent.h" + +#include "qt/view/graphElements/QtGraphEdge.h" + +QtGraphNodeMouseMovable::QtGraphNodeMouseMovable(const Vec2i& position, const std::string& name, const Id tokenId) + : QtGraphNode(position, name, tokenId) +{ +} + +QtGraphNodeMouseMovable::~QtGraphNodeMouseMovable() +{ +} + +void QtGraphNodeMouseMovable::mousePressEvent(QGraphicsSceneMouseEvent* event) +{ + m_mouseOffset.x = event->pos().x(); + m_mouseOffset.y = event->pos().y(); +} + +void QtGraphNodeMouseMovable::mouseMoveEvent(QGraphicsSceneMouseEvent* event) +{ + this->setPos(event->scenePos().x() - m_mouseOffset.x, event->scenePos().y() - m_mouseOffset.y); + + Vec2i p(event->scenePos().x(), event->scenePos().y()); + + notifyEdgesAfterMove(); +} \ No newline at end of file diff --git a/src/app/qt/view/graphElements/QtGraphNodeMouseMovable.h b/src/app/qt/view/graphElements/QtGraphNodeMouseMovable.h new file mode 100644 index 00000000..40d9011e --- /dev/null +++ b/src/app/qt/view/graphElements/QtGraphNodeMouseMovable.h @@ -0,0 +1,19 @@ +#ifndef QT_GRAPH_NODE_MOUSE_MOVABLE_H +#define QT_GRAPH_NODE_MOUSE_MOVABLE_H + +#include "qt/view/graphElements/QtGraphNode.h" + +class QtGraphNodeMouseMovable : public QtGraphNode +{ +public: + QtGraphNodeMouseMovable(const Vec2i& position, const std::string& name, const Id tokenId); + virtual ~QtGraphNodeMouseMovable(); + + void mousePressEvent(QGraphicsSceneMouseEvent* event); + void mouseMoveEvent(QGraphicsSceneMouseEvent* event); + +private: + Vec2i m_mouseOffset; +}; + +#endif // QT_GRAPH_NODE_MOUSE_MOVABLE_H \ No newline at end of file diff --git a/src/app/qt/view/graphElements/QtGraphNodeMovable.cpp b/src/app/qt/view/graphElements/QtGraphNodeMovable.cpp deleted file mode 100644 index f01250a7..00000000 --- a/src/app/qt/view/graphElements/QtGraphNodeMovable.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include "qt/view/graphElements/QtGraphNodeMovable.h" - -#include "qgraphicssceneevent.h" - -#include "qt/view/graphElements/QtGraphEdge.h" - -QtGraphNodeMovable::QtGraphNodeMovable(const Vec2i& position, const std::string& name, const Id tokenId) - : QtGraphNode(position, name, tokenId) -{ -} - -QtGraphNodeMovable::~QtGraphNodeMovable() -{ -} - -void QtGraphNodeMovable::mousePressEvent(QGraphicsSceneMouseEvent* event) -{ - m_mouseOffset.x = event->pos().x(); - m_mouseOffset.y = event->pos().y(); -} - -void QtGraphNodeMovable::mouseMoveEvent(QGraphicsSceneMouseEvent* event) -{ - this->setPos(event->scenePos().x() - m_mouseOffset.x, event->scenePos().y() - m_mouseOffset.y); - - Vec2i p(event->scenePos().x(), event->scenePos().y()); - - std::list >::iterator it = m_outEdges.begin(); - for(it; it != m_outEdges.end(); it++) - { - (*it)->ownerMoved(); - } - - std::list >::iterator it2 = m_inEdges.begin(); - while(it2 != m_inEdges.end()) - { - std::shared_ptr edge = it2->lock(); - if(edge.get() != NULL) - { - edge->targetMoved(); - ++it2; - } - else - { - m_inEdges.erase(it2++); - } - } -} \ No newline at end of file diff --git a/src/app/qt/view/graphElements/QtGraphNodeMovable.h b/src/app/qt/view/graphElements/QtGraphNodeMovable.h deleted file mode 100644 index 97ce2f2c..00000000 --- a/src/app/qt/view/graphElements/QtGraphNodeMovable.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef QT_GRAPH_NODE_MOVABLE_H -#define QT_GRAPH_NODE_MOVABLE_H - -#include "qt/view/graphElements/QtGraphNode.h" - -class QtGraphNodeMovable : public QtGraphNode -{ -public: - QtGraphNodeMovable(const Vec2i& position, const std::string& name, const Id tokenId); - virtual ~QtGraphNodeMovable(); - - void mousePressEvent(QGraphicsSceneMouseEvent* event); - void mouseMoveEvent(QGraphicsSceneMouseEvent* event); - -private: - Vec2i m_mouseOffset; -}; - -#endif // QT_GRAPH_NODE_MOVABLE_H \ No newline at end of file diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt index 7c7ced5d..9048d9db 100644 --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -28,6 +28,8 @@ add_files( component/controller/Controller.h component/controller/GraphController.cpp component/controller/GraphController.h + component/controller/GraphLayouter.cpp + component/controller/GraphLayouter.h component/controller/SearchController.cpp component/controller/SearchController.h diff --git a/src/lib/component/controller/GraphController.cpp b/src/lib/component/controller/GraphController.cpp index 829a59dc..fb80678d 100644 --- a/src/lib/component/controller/GraphController.cpp +++ b/src/lib/component/controller/GraphController.cpp @@ -1,5 +1,7 @@ #include "component/controller/GraphController.h" +#include + #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 > rawEdges = m_graphAccess->getConnectedEdges(message->tokenId); - std::vector neighbourIds = m_graphAccess->getIdsOfNeighbours(message->tokenId); - - DummyNode node(name, message->tokenId, Vec2i(0,0)); - - std::vector nodes; - nodes.push_back(node); - - std::vector 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> 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(); } + +void GraphController::createDummyGraph(const Id activeId, const LayoutFunction layoutFunction) +{ + GraphView* view = getView(); + if (view != NULL) + { + std::vector nodes; + std::vector edges; + + nodes.push_back(createDummyNode(activeId)); + + std::vector 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> 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> 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 GraphController::createNeighbourNodes(const Id nodeId) +{ + std::vector result; + + std::vector> edges; + std::vector> callEdges = m_graphAccess->getCallEdgesOfNode(nodeId); + std::vector> usageEdges = m_graphAccess->getUsageEdgesOfNode(nodeId); + std::vector> typeOfEdges = m_graphAccess->getTypeOfEdgesOfNode(nodeId); + std::vector> returnTypeEdges = m_graphAccess->getReturnTypeOfEdgesOfNode(nodeId); + std::vector> 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 GraphController::createNeighbourNodes(const DummyNode& node) +{ + std::vector result; + + std::set 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 tmpNeighbours = createNeighbourNodes(node.subNodes[i].tokenId); + for(unsigned int j = 0; j < tmpNeighbours.size(); j++) + { + tmpNodes.insert(tmpNeighbours[j]); + } + } + + result.clear(); + std::set::iterator it = tmpNodes.begin(); + for(it; it != tmpNodes.end(); it++) + { + result.push_back(*it); + } + + return result; +} + +std::vector GraphController::createEdges(const std::vector& nodes) +{ + std::vector result; + + std::unordered_set 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 tmpEdges; // to make it easier to keep the edges unique + for(unsigned int i = 0; i < nodes.size(); i++) + { + std::set tmp = getNeighbourEdgesOfNode(nodes[i]); + + std::set::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::iterator it = tmpEdges.begin(); + for(it; it != tmpEdges.end(); it++) + { + result.push_back(*it); + } + + return result; +} + +std::set GraphController::getNeighbourEdgesOfNode(const DummyNode& node) +{ + std::set result; + + std::vector> rawEdges; + std::vector> callEdges = m_graphAccess->getCallEdgesOfNode(node.tokenId); + std::vector> usageEdges = m_graphAccess->getUsageEdgesOfNode(node.tokenId); + std::vector> typeOfEdges = m_graphAccess->getTypeOfEdgesOfNode(node.tokenId); + std::vector> returnTypeEdges = m_graphAccess->getReturnTypeOfEdgesOfNode(node.tokenId); + std::vector> 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 tmpNeighbours = getNeighbourEdgesOfNode(node.subNodes[i]); + result.insert(tmpNeighbours.begin(), tmpNeighbours.end()); + } + + return result; +} diff --git a/src/lib/component/controller/GraphController.h b/src/lib/component/controller/GraphController.h index a0a01a01..17e4f999 100644 --- a/src/lib/component/controller/GraphController.h +++ b/src/lib/component/controller/GraphController.h @@ -1,11 +1,17 @@ #ifndef GRAPH_CONTROLLER_H #define GRAPH_CONTROLLER_H +#include +#include + #include "utility/messaging/MessageListener.h" #include "utility/messaging/type/MessageActivateToken.h" #include "component/controller/Controller.h" +#include "component/controller/GraphLayouter.h" +struct DummyNode; +struct DummyEdge; class GraphView; class GraphAccess; @@ -20,6 +26,17 @@ public: private: virtual void handleMessage(MessageActivateToken* message); GraphView* getView(); + void createDummyGraph(const Id activeId, const LayoutFunction layoutFunction); + + DummyNode createDummyNode(const Id nodeId); + Id findTopLevelNode(const Id nodeId); + DummyNode buildNodeTopDown(const Id nodeId); + + std::vector createNeighbourNodes(const Id nodeId); + std::vector createNeighbourNodes(const DummyNode& node); + + std::vector createEdges(const std::vector& nodes); + std::set getNeighbourEdgesOfNode(const DummyNode& node); GraphAccess* m_graphAccess; }; diff --git a/src/lib/component/controller/GraphLayouter.cpp b/src/lib/component/controller/GraphLayouter.cpp new file mode 100644 index 00000000..578f0dc7 --- /dev/null +++ b/src/lib/component/controller/GraphLayouter.cpp @@ -0,0 +1,48 @@ +#include "component/controller/GraphLayouter.h" + +#include "component/view/graphElements/GraphNode.h" + +void GraphLayouter::layoutSimpleRaster(std::vector& nodes) +{ + int x = 0; + int y = 0; + int offset = 150; + + for(unsigned int i = 0; i < nodes.size(); i++) + { + nodes[i].position = Vec2i(x, y); + + if(x > 0) + { + y += offset; + x = 0; + } + else + { + x += offset; + } + } +} + +void GraphLayouter::layoutSimpleRing(std::vector& nodes) +{ + if(nodes.size() >= 1) + { + nodes[0].position = Vec2i(0, 0); + + if(nodes.size() > 1) + { + int offset = 150; + + for(unsigned int i = 1; i < nodes.size(); i++) + { + float rad = ((2.0f*3.14159265359f) / float(nodes.size()-1)) * i-1; + + int x = (int)((float)offset * std::cos(rad)); + int y = (int)((float)offset * std::sin(rad)); + + nodes[i].position = Vec2i(x, y); + } + } + } +} diff --git a/src/lib/component/controller/GraphLayouter.h b/src/lib/component/controller/GraphLayouter.h new file mode 100644 index 00000000..58e5a284 --- /dev/null +++ b/src/lib/component/controller/GraphLayouter.h @@ -0,0 +1,17 @@ +#ifndef GRAPH_LAYOUTER_H +#define GRAPH_LAYOUTER_H + +#include + +class DummyNode; + +typedef void (*LayoutFunction)(std::vector&); + +class GraphLayouter +{ +public: + static void layoutSimpleRaster(std::vector& nodes); + static void layoutSimpleRing(std::vector& nodes); +}; + +#endif // GRAPH_LAYOUTER_H \ No newline at end of file diff --git a/src/lib/component/view/graphElements/GraphEdge.h b/src/lib/component/view/graphElements/GraphEdge.h index 246caf2d..7598bbc4 100644 --- a/src/lib/component/view/graphElements/GraphEdge.h +++ b/src/lib/component/view/graphElements/GraphEdge.h @@ -32,9 +32,6 @@ public: { } - Id ownerId; - Id targetId; - bool operator==(const DummyEdge& other) const { if(ownerId == other.ownerId && targetId == other.targetId) @@ -48,6 +45,27 @@ public: { return !(*this == other); } + + bool operator<(const DummyEdge& other) const + { + if(ownerId < other.ownerId ) + { + return true; + } + else if(ownerId == other.ownerId) + { + return (targetId < other.targetId); + } + return false; + } + + bool operator>(const DummyEdge& other) const + { + return !(*this < other); + } + + Id ownerId; + Id targetId; }; #endif // GRAPH_EDGE_H \ No newline at end of file diff --git a/src/lib/component/view/graphElements/GraphNode.cpp b/src/lib/component/view/graphElements/GraphNode.cpp index bcc33ded..437aef97 100644 --- a/src/lib/component/view/graphElements/GraphNode.cpp +++ b/src/lib/component/view/graphElements/GraphNode.cpp @@ -9,7 +9,7 @@ GraphNode::~GraphNode() { } -Id GraphNode::getTokenId() +Id GraphNode::getTokenId() const { return m_tokenId; } diff --git a/src/lib/component/view/graphElements/GraphNode.h b/src/lib/component/view/graphElements/GraphNode.h index ed70c4a7..9281579b 100644 --- a/src/lib/component/view/graphElements/GraphNode.h +++ b/src/lib/component/view/graphElements/GraphNode.h @@ -1,6 +1,7 @@ #ifndef GRAPH_NODE_H #define GRAPH_NODE_H +#include #include #include "utility/math/Vector2.h" @@ -14,17 +15,21 @@ public: GraphNode(const Id tokenId); virtual ~GraphNode(); - virtual std::string getName() = 0; - Id getTokenId(); - virtual Vec2i getPosition() = 0; + virtual std::string getName() const = 0; + Id getTokenId() const; + virtual Vec2i getPosition() const = 0; + virtual void setPosition(const Vec2i& position) = 0; virtual bool addOutEdge(const std::shared_ptr& edge) = 0; virtual bool addInEdge(const std::weak_ptr& edge) = 0; virtual void removeOutEdge(GraphEdge* edge) = 0; + virtual std::list > getSubNodes() const = 0; virtual void addSubNode(const std::shared_ptr& node) = 0; + virtual void notifyParentMoved() = 0; + protected: Id m_tokenId; }; @@ -36,13 +41,56 @@ public: : name(n) , tokenId(tId) , position(p) + , subNodes() + , actualNode() { } + bool operator==(const DummyNode& other) const + { + if(tokenId == other.tokenId + && name == other.name + && position == position) + { + return true; + } + return false; + } + + bool operator!=(const DummyNode& other) const + { + return !(*this == other); + } + + bool operator<(const DummyNode& other) const + { + if(tokenId < other.tokenId) + { + return true; + } + return false; + } + + bool operator>(const DummyNode& other) const + { + return !(*this < other); + } + + void operator=(DummyNode& other) + { + name = other.name; + tokenId = other.tokenId; + position = other.position; + subNodes = other.subNodes; + actualNode = other.actualNode; + } + std::string name; Id tokenId; Vec2i position; + std::vector subNodes; + std::weak_ptr actualNode; }; diff --git a/src/lib/data/Storage.cpp b/src/lib/data/Storage.cpp index 80cc1bf5..c54c2551 100644 --- a/src/lib/data/Storage.cpp +++ b/src/lib/data/Storage.cpp @@ -289,7 +289,7 @@ std::vector Storage::getIdsOfNeighbours(const Id id) const return result; } -std::vector> Storage::getConnectedEdges(const Id id) const +std::vector> Storage::getNeighbourEdgesOfNode(const Id id) const { std::vector> result; @@ -300,7 +300,7 @@ std::vector> Storage::getConnectedEdges(const Id id) const if (node != NULL) { node->forEachEdge( - [&result, &id](Edge* e) + [&result](Edge* e) { result.push_back(std::pair(e->getFrom()->getId(), e->getTo()->getId())); } @@ -310,6 +310,36 @@ std::vector> Storage::getConnectedEdges(const Id id) const return result; } +std::vector> Storage::getMemberEdgesOfNode(const Id id) const +{ + return getEdgesOfTypeOfNode(id, Edge::EdgeType::EDGE_MEMBER); +} + +std::vector> Storage::getUsageEdgesOfNode(const Id id) const +{ + return getEdgesOfTypeOfNode(id, Edge::EdgeType::EDGE_USAGE); +} + +std::vector> Storage::getCallEdgesOfNode(const Id id) const +{ + return getEdgesOfTypeOfNode(id, Edge::EdgeType::EDGE_CALL); +} + +std::vector> Storage::getTypeOfEdgesOfNode(const Id id) const +{ + return getEdgesOfTypeOfNode(id, Edge::EdgeType::EDGE_TYPE_OF); +} + +std::vector> Storage::getReturnTypeOfEdgesOfNode(const Id id) const +{ + return getEdgesOfTypeOfNode(id, Edge::EdgeType::EDGE_RETURN_TYPE_OF); +} + +std::vector> Storage::getParameterOfEdgesOfNode(const Id id) const +{ + return getEdgesOfTypeOfNode(id, Edge::EdgeType::EDGE_PARAMETER_TYPE_OF); +} + TokenLocationCollection Storage::getTokenLocationsForTokenId(Id id) const { TokenLocationCollection ret; @@ -430,3 +460,27 @@ void Storage::log(std::string type, std::string str, const ParseLocation& locati info << location.endLineNumber << ":" << location.endColumnNumber << ">"; LOG_INFO(info.str()); } + +std::vector> Storage::getEdgesOfTypeOfNode(const Id id, const Edge::EdgeType type) const +{ + std::vector> result; + + Node* node = m_graph.findNode([&](Node* node){ + return node->getId() == id; + }); + + if (node != NULL) + { + node->forEachEdge( + [&result, &type](Edge* e) + { + if(e->getType() == type) + { + result.push_back(std::pair(e->getFrom()->getId(), e->getTo()->getId())); + } + } + ); + } + + return result; +} diff --git a/src/lib/data/Storage.h b/src/lib/data/Storage.h index fefc8f7d..61130ab0 100644 --- a/src/lib/data/Storage.h +++ b/src/lib/data/Storage.h @@ -62,7 +62,13 @@ public: virtual std::string getNameForNodeWithId(Id id) const; virtual std::vector getNamesForNodesWithNamePrefix(const std::string& prefix) const; virtual std::vector getIdsOfNeighbours(const Id id) const; - virtual std::vector> getConnectedEdges(const Id id) const; + virtual std::vector> getNeighbourEdgesOfNode(const Id id) const; + virtual std::vector> getMemberEdgesOfNode(const Id id) const; + virtual std::vector> getUsageEdgesOfNode(const Id id) const; + virtual std::vector> getCallEdgesOfNode(const Id id) const; + virtual std::vector> getTypeOfEdgesOfNode(const Id id) const; + virtual std::vector> getReturnTypeOfEdgesOfNode(const Id id) const; + virtual std::vector> getParameterOfEdgesOfNode(const Id id) const; // LocationAccess implementation virtual TokenLocationCollection getTokenLocationsForTokenId(Id locationId) const; @@ -78,6 +84,8 @@ private: void log(std::string type, std::string str, const ParseLocation& location) const; + std::vector> getEdgesOfTypeOfNode(const Id id, const Edge::EdgeType type) const; + Graph m_graph; TokenLocationCollection m_locationCollection; }; diff --git a/src/lib/data/access/GraphAccess.h b/src/lib/data/access/GraphAccess.h index eafe50e8..c068032b 100644 --- a/src/lib/data/access/GraphAccess.h +++ b/src/lib/data/access/GraphAccess.h @@ -6,6 +6,7 @@ #include "utility/types.h" +class Edge; class Token; class GraphAccess @@ -17,7 +18,13 @@ public: virtual std::string getNameForNodeWithId(Id id) const = 0; virtual std::vector getNamesForNodesWithNamePrefix(const std::string& prefix) const = 0; virtual std::vector getIdsOfNeighbours(const Id id) const = 0; - virtual std::vector> getConnectedEdges(const Id id) const = 0; + virtual std::vector> getNeighbourEdgesOfNode(const Id id) const = 0; + virtual std::vector> getMemberEdgesOfNode(const Id id) const = 0; + virtual std::vector> getUsageEdgesOfNode(const Id id) const = 0; + virtual std::vector> getCallEdgesOfNode(const Id id) const = 0; + virtual std::vector> getTypeOfEdgesOfNode(const Id id) const = 0; + virtual std::vector> getReturnTypeOfEdgesOfNode(const Id id) const = 0; + virtual std::vector> getParameterOfEdgesOfNode(const Id id) const = 0; }; diff --git a/src/lib/data/access/GraphAccessProxy.cpp b/src/lib/data/access/GraphAccessProxy.cpp index a1271744..42925352 100644 --- a/src/lib/data/access/GraphAccessProxy.cpp +++ b/src/lib/data/access/GraphAccessProxy.cpp @@ -67,11 +67,71 @@ std::vector GraphAccessProxy::getIdsOfNeighbours(const Id id) const return std::vector(); } -std::vector> GraphAccessProxy::getConnectedEdges(const Id id) const +std::vector> GraphAccessProxy::getNeighbourEdgesOfNode(const Id id) const { if (hasSubject()) { - return m_subject->getConnectedEdges(id); + return m_subject->getNeighbourEdgesOfNode(id); + } + + return std::vector>(); +} + +std::vector> GraphAccessProxy::getMemberEdgesOfNode(const Id id) const +{ + if (hasSubject()) + { + return m_subject->getMemberEdgesOfNode(id); + } + + return std::vector>(); +} + +std::vector> GraphAccessProxy::getUsageEdgesOfNode(const Id id) const +{ + if (hasSubject()) + { + return m_subject->getUsageEdgesOfNode(id); + } + + return std::vector>(); +} + +std::vector> GraphAccessProxy::getCallEdgesOfNode(const Id id) const +{ + if (hasSubject()) + { + return m_subject->getCallEdgesOfNode(id); + } + + return std::vector>(); +} + +std::vector> GraphAccessProxy::getTypeOfEdgesOfNode(const Id id) const +{ + if (hasSubject()) + { + return m_subject->getTypeOfEdgesOfNode(id); + } + + return std::vector>(); +} + +std::vector> GraphAccessProxy::getReturnTypeOfEdgesOfNode(const Id id) const +{ + if (hasSubject()) + { + return m_subject->getReturnTypeOfEdgesOfNode(id); + } + + return std::vector>(); +} + +std::vector> GraphAccessProxy::getParameterOfEdgesOfNode(const Id id) const +{ + if (hasSubject()) + { + return m_subject->getParameterOfEdgesOfNode(id); } return std::vector>(); diff --git a/src/lib/data/access/GraphAccessProxy.h b/src/lib/data/access/GraphAccessProxy.h index c376161a..4cea39be 100644 --- a/src/lib/data/access/GraphAccessProxy.h +++ b/src/lib/data/access/GraphAccessProxy.h @@ -17,7 +17,13 @@ public: virtual std::string getNameForNodeWithId(Id id) const; virtual std::vector getNamesForNodesWithNamePrefix(const std::string& prefix) const; virtual std::vector getIdsOfNeighbours(const Id id) const; - virtual std::vector> getConnectedEdges(const Id id) const; + virtual std::vector> getNeighbourEdgesOfNode(const Id id) const; + virtual std::vector> getMemberEdgesOfNode(const Id id) const; + virtual std::vector> getUsageEdgesOfNode(const Id id) const; + virtual std::vector> getCallEdgesOfNode(const Id id) const; + virtual std::vector> getTypeOfEdgesOfNode(const Id id) const; + virtual std::vector> getReturnTypeOfEdgesOfNode(const Id id) const; + virtual std::vector> getParameterOfEdgesOfNode(const Id id) const; private: GraphAccess* m_subject;