diff --git a/src/app/qt/view/QtGraphView.cpp b/src/app/qt/view/QtGraphView.cpp index b9150eee..f7585901 100644 --- a/src/app/qt/view/QtGraphView.cpp +++ b/src/app/qt/view/QtGraphView.cpp @@ -17,10 +17,7 @@ QtGraphView::QtGraphView(ViewLayout* viewLayout) : GraphView(viewLayout) , m_rebuildGraphFunctor( - std::bind( - &QtGraphView::doRebuildGraph, this, - std::placeholders::_1, std::placeholders::_2, - std::placeholders::_3, std::placeholders::_4)) + std::bind(&QtGraphView::doRebuildGraph, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)) , m_clearFunctor(std::bind(&QtGraphView::doClear, this)) { } @@ -57,11 +54,10 @@ void QtGraphView::refreshView() void QtGraphView::rebuildGraph( std::shared_ptr graph, - std::vector activeTokenIds, const std::vector& nodes, const std::vector& edges ){ - m_rebuildGraphFunctor(graph, activeTokenIds, nodes, edges); + m_rebuildGraphFunctor(graph, nodes, edges); } void QtGraphView::clear() @@ -69,22 +65,38 @@ void QtGraphView::clear() m_clearFunctor(); } -QGraphicsView* QtGraphView::getView() +GraphView::Metrics QtGraphView::getViewMetrics() const +{ + GraphView::Metrics metrics; + + QGraphicsView* view = getView(); + if (view == NULL) + { + return metrics; + } + + metrics.width = view->width(); + metrics.height = view->height(); + + metrics.typeNameCharWidth = QFontMetrics(QtGraphNode::getFontForNodeType(Node::NODE_CLASS)).width("QtGraphNode") / 11.0f; + metrics.variableNameCharWidth = QFontMetrics(QtGraphNode::getFontForNodeType(Node::NODE_FIELD)).width("QtGraphNode") / 11.0f; + metrics.functionNameCharWidth = QFontMetrics(QtGraphNode::getFontForNodeType(Node::NODE_METHOD)).width("QtGraphNode") / 11.0f; + + return metrics; +} + +QGraphicsView* QtGraphView::getView() const { QWidget* widget = QtViewWidgetWrapper::getWidgetOfView(this); - QObjectList children = widget->children(); - return widget->findChild(""); } void QtGraphView::doRebuildGraph( std::shared_ptr graph, - std::vector activeTokenIds, const std::vector& nodes, const std::vector& edges ){ - m_activeTokenIds = activeTokenIds; QGraphicsView* view = getView(); if (view == NULL) @@ -100,9 +112,11 @@ void QtGraphView::doRebuildGraph( // create nodes (or find existing nodes for re-use) for (unsigned int i = 0; i < nodes.size(); i++) { - std::shared_ptr newNode = createNodeRecursive(view, NULL, nodes[i]); - newNode->setPosition(nodes[i].position); - newNodes.push_back(newNode); + std::shared_ptr node = createNodeRecursive(view, NULL, nodes[i]); + if (node) + { + newNodes.push_back(node); + } } doClear(); @@ -117,18 +131,23 @@ void QtGraphView::doRebuildGraph( } } - // hide node content by default, must be done after all edges are created to keep subnodes with connections visible - for (const std::shared_ptr& node : m_nodes) + if (graph) { - node->hideContent(); + m_graph = graph; } - for (const std::shared_ptr& edge : m_edges) + // Manually hover the items below the mouse cursor. + view->scene()->setSceneRect(view->scene()->itemsBoundingRect()); + QPointF point = view->mapToScene(view->mapFromGlobal(QCursor::pos())); + QGraphicsItem* item = view->scene()->itemAt(point, QTransform()); + if (item) { - edge->updateLine(); + QtGraphNode* node = dynamic_cast(item->parentItem()); + if (node) + { + node->hoverEnter(); + } } - - m_graph = graph; } void QtGraphView::doClear() @@ -159,6 +178,11 @@ std::shared_ptr QtGraphView::findNodeRecursive(const std::list QtGraphView::createNodeRecursive( QGraphicsView* view, std::shared_ptr parentNode, const DummyNode& node ){ + if (!node.visible) + { + return NULL; + } + std::shared_ptr newNode; if (node.data) { @@ -166,18 +190,17 @@ std::shared_ptr QtGraphView::createNodeRecursive( } else { - newNode = std::make_shared(node.accessType); + newNode = std::make_shared(node.accessType, node.expanded, node.invisibleSubNodeCount); } + newNode->setPosition(node.position); + newNode->setSize(node.size); + newNode->setIsActive(node.active); + newNode->addComponent(std::make_shared(newNode)); view->scene()->addItem(newNode.get()); - if (node.data && isActiveTokenId(node.data->getId())) - { - newNode->setIsActive(true); - } - if (parentNode) { newNode->setParent(parentNode); @@ -190,9 +213,14 @@ std::shared_ptr QtGraphView::createNodeRecursive( for (unsigned int i = 0; i < node.subNodes.size(); i++) { std::shared_ptr subNode = createNodeRecursive(view, newNode, node.subNodes[i]); - newNode->addSubNode(subNode); + if (subNode) + { + newNode->addSubNode(subNode); + } } + newNode->setStyle(); + return newNode; } @@ -204,8 +232,9 @@ std::shared_ptr QtGraphView::createEdge(QGraphicsView* view, const if (owner != NULL && target != NULL) { std::shared_ptr qtEdge = std::make_shared(owner, target, edge.data); - bool added = owner->addOutEdge(qtEdge) | target->addInEdge(qtEdge); + qtEdge->setIsActive(edge.active); + bool added = owner->addOutEdge(qtEdge) | target->addInEdge(qtEdge); if (!added) { return NULL; @@ -213,11 +242,6 @@ std::shared_ptr QtGraphView::createEdge(QGraphicsView* view, const view->scene()->addItem(qtEdge.get()); - if (isActiveTokenId(edge.data->getId())) - { - qtEdge->setIsActive(true); - } - return qtEdge; } else @@ -226,8 +250,3 @@ std::shared_ptr QtGraphView::createEdge(QGraphicsView* view, const return NULL; } } - -bool QtGraphView::isActiveTokenId(Id tokenId) const -{ - return find(m_activeTokenIds.begin(), m_activeTokenIds.end(), tokenId) != m_activeTokenIds.end(); -} diff --git a/src/app/qt/view/QtGraphView.h b/src/app/qt/view/QtGraphView.h index 8ca0c8eb..0c971f04 100644 --- a/src/app/qt/view/QtGraphView.h +++ b/src/app/qt/view/QtGraphView.h @@ -24,22 +24,15 @@ public: virtual void initView(); virtual void refreshView(); - virtual void rebuildGraph( - std::shared_ptr graph, - std::vector activeTokenIds, - const std::vector& nodes, - const std::vector& edges); - + virtual void rebuildGraph(std::shared_ptr graph, const std::vector& nodes, const std::vector& edges); virtual void clear(); -private: - QGraphicsView* getView(); + virtual GraphView::Metrics getViewMetrics() const; - void doRebuildGraph( - std::shared_ptr graph, - std::vector activeTokenIds, - const std::vector& nodes, - const std::vector& edges); +private: + QGraphicsView* getView() const; + + void doRebuildGraph(std::shared_ptr graph, const std::vector& nodes, const std::vector& edges); void doClear(); std::shared_ptr findNodeRecursive(const std::list>& nodes, Id tokenId); @@ -48,16 +41,10 @@ private: QGraphicsView* view, std::shared_ptr parentNode, const DummyNode& node); std::shared_ptr createEdge(QGraphicsView* view, const DummyEdge& edge); - bool isActiveTokenId(Id tokenId) const; - - QtThreadedFunctor< - std::shared_ptr, std::vector, const std::vector&, const std::vector& - > m_rebuildGraphFunctor; - + QtThreadedFunctor, const std::vector&, const std::vector&> m_rebuildGraphFunctor; QtThreadedFunctor m_clearFunctor; std::shared_ptr m_graph; - std::vector m_activeTokenIds; std::list> m_edges; std::list> m_nodes; diff --git a/src/app/qt/view/graphElements/QtGraphNode.cpp b/src/app/qt/view/graphElements/QtGraphNode.cpp index 7c4cabc6..bbe7d17f 100644 --- a/src/app/qt/view/graphElements/QtGraphNode.cpp +++ b/src/app/qt/view/graphElements/QtGraphNode.cpp @@ -1,22 +1,55 @@ #include "qt/view/graphElements/QtGraphNode.h" #include -#include #include #include #include "utility/messaging/type/MessageActivateToken.h" +#include "utility/messaging/type/MessageGraphNodeMove.h" #include "qt/graphics/QtGraphicsRoundedRectItem.h" #include "qt/utility/QtDeviceScaledPixmap.h" #include "qt/view/graphElements/nodeComponents/QtGraphNodeComponent.h" #include "qt/view/graphElements/QtGraphEdge.h" +QFont QtGraphNode::getFontForNodeType(Node::NodeType type) +{ + QFont font("Source Code Pro"); + + switch (type) + { + case Node::NODE_UNDEFINED: + case Node::NODE_NAMESPACE: + font.setPointSize(12); + break; + + case Node::NODE_UNDEFINED_TYPE: + case Node::NODE_STRUCT: + case Node::NODE_CLASS: + case Node::NODE_ENUM: + case Node::NODE_TYPEDEF: + font.setPointSize(14); + break; + + case Node::NODE_UNDEFINED_FUNCTION: + case Node::NODE_FUNCTION: + case Node::NODE_METHOD: + font.setPointSize(11); + break; + + case Node::NODE_UNDEFINED_VARIABLE: + case Node::NODE_GLOBAL_VARIABLE: + case Node::NODE_FIELD: + font.setPointSize(11); + break; + } + + return font; +} + QtGraphNode::QtGraphNode() : GraphNode(nullptr) , m_undefinedRect(nullptr) - , m_padding(0, 0, 0, 0) - , m_spacing(8) , m_isActive(false) , m_isHovering(false) { @@ -29,8 +62,6 @@ QtGraphNode::QtGraphNode() QtGraphNode::QtGraphNode(const Node* data) : GraphNode(data) , m_undefinedRect(nullptr) - , m_padding(0, 0, 0, 0) - , m_spacing(8) , m_isActive(false) , m_isHovering(false) { @@ -42,9 +73,6 @@ QtGraphNode::QtGraphNode(const Node* data) this->setAcceptHoverEvents(true); this->setName(data->getName()); - this->setStyle(); - - this->setSize(m_baseSize); } QtGraphNode::~QtGraphNode() @@ -66,7 +94,7 @@ Vec2i QtGraphNode::getPosition() const return Vec2i(this->scenePos().x(), this->scenePos().y()); } -void QtGraphNode::setPosition(const Vec2i& position) +bool QtGraphNode::setPosition(const Vec2i& position) { Vec2i currentPosition = getPosition(); Vec2i offset = position - currentPosition; @@ -75,17 +103,28 @@ void QtGraphNode::setPosition(const Vec2i& position) { this->moveBy(offset.x, offset.y); notifyEdgesAfterMove(); + return true; + } + + return false; +} + +void QtGraphNode::moveTo(const Vec2i& position) +{ + if (setPosition(position) && m_data) + { + MessageGraphNodeMove(m_data->getId(), position).dispatch(); } } Vec2i QtGraphNode::getSize() const { - return m_currentSize; + return m_size; } -void QtGraphNode::setSize(Vec2i size) +void QtGraphNode::setSize(const Vec2i& size) { - m_currentSize = size; + m_size = size; this->setRect(0, 0, size.x, size.y); m_rect->setRect(0, 0, size.x, size.y); @@ -206,38 +245,143 @@ void QtGraphNode::addSubNode(const std::shared_ptr& node) m_subNodes.push_back(node); } -unsigned int QtGraphNode::getEdgeAndActiveCountRecursive() const +void QtGraphNode::setStyle() { - unsigned int result = 0; + if (!m_data) + { + return; + } + + QColor color = Qt::lightGray; + qreal radius = 0.0f; + QPen p(Qt::transparent); + QFont font(getFontForNodeType(m_data->getType())); + + bool undefined = false; + bool useUndefinedColor = false; + + Vec2i padding; + + switch (m_data->getType()) + { + case Node::NODE_UNDEFINED: + undefined = true; + case Node::NODE_NAMESPACE: + color = Qt::white; + + p.setColor("#cc8d91"); + p.setWidth(1); + + radius = 20.0f; + padding.x = 15; + padding.y = 6; + break; + + case Node::NODE_UNDEFINED_TYPE: + undefined = true; + case Node::NODE_STRUCT: + case Node::NODE_CLASS: + case Node::NODE_ENUM: + case Node::NODE_TYPEDEF: + if (m_isHovering) + { + m_rect->setShadow(QColor(0, 0, 0, 255), 5); + } + else + { + m_rect->setShadow(QColor(0, 0, 0, 128), 5); + } + + color = "#ededed"; + if (m_subNodes.size()) + { + radius = 20.0f; + padding.x = 15; + padding.y = 8; + } + else + { + radius = 10.0f; + padding.x = 8; + padding.y = 4; + } + break; + + case Node::NODE_UNDEFINED_FUNCTION: + undefined = true; + useUndefinedColor = true; + case Node::NODE_FUNCTION: + case Node::NODE_METHOD: + if (m_isActive || m_isHovering) + { + color = "#ffcc00"; + font.setWeight(QFont::Bold); + } + else + { + color = "#ffe47a"; + } + + radius = 8.0f; + padding.x = 5; + padding.y = 3; + break; + + case Node::NODE_UNDEFINED_VARIABLE: + undefined = true; + useUndefinedColor = true; + case Node::NODE_GLOBAL_VARIABLE: + case Node::NODE_FIELD: + if (m_isActive || m_isHovering) + { + color = "#62b29d"; + font.setWeight(QFont::Bold); + } + else + { + color = "#9ab4ad"; + } + + radius = 8.0f; + padding.x = 5; + padding.y = 3; + break; + } if (m_isActive) { - result++; + p.setWidthF(1.5f); + p.setColor("#3c3c3c"); } - for (std::shared_ptr node : m_subNodes) + m_rect->setPen(p); + m_rect->setBrush(QBrush(color)); + m_rect->setRadius(radius); + + if (undefined) { - result += node->getEdgeAndActiveCountRecursive(); - } + QtDeviceScaledPixmap pixmap("data/gui/graph_view/images/pattern.png"); + pixmap.scaleToHeight(10); - result += (getInEdgeCount() + getOutEdgeCount()); - - return result; -} - -void QtGraphNode::hideContent() -{ - for (std::shared_ptr node : m_subNodes) - { - node->hideContent(); - - if (node->getTokenId() && node->getEdgeAndActiveCountRecursive() <= 0) + if (!m_undefinedRect) { - node->hide(); + m_undefinedRect = new QtGraphicsRoundedRectItem(this); + setSize(getSize()); } + + p.setWidth(1); + p.setColor(Qt::transparent); + if (useUndefinedColor && !m_isActive) + { + p.setColor(color); + } + m_undefinedRect->setPen(p); + m_undefinedRect->setBrush(QBrush(pixmap.pixmap())); + m_undefinedRect->setRadius(radius); } - rebuildLayout(); + m_text->setFont(font); + m_text->setPos(padding.x, padding.y); } void QtGraphNode::onClick() @@ -248,6 +392,17 @@ void QtGraphNode::onClick() } } +void QtGraphNode::hoverEnter() +{ + hoverEnterEvent(nullptr); + + QtGraphNode* parent = getParent(); + if (parent) + { + parent->hoverEnter(); + } +} + void QtGraphNode::mousePressEvent(QGraphicsSceneMouseEvent* event) { event->ignore(); @@ -338,190 +493,3 @@ void QtGraphNode::notifyEdgesAfterMove() node->notifyEdgesAfterMove(); } } - -void QtGraphNode::onSizeChanged() -{ - rebuildLayout(); - - std::shared_ptr parentNode = m_parentNode.lock(); - - if (parentNode != NULL) - { - parentNode->onSizeChanged(); - } -} - -void QtGraphNode::rebuildLayout() -{ - setStyle(); - - Vec2i newSize(m_baseSize); - newSize.y = newSize.y - m_padding.w; - - for (const std::shared_ptr& node : m_subNodes) - { - if (node->isVisible()) - { - node->setPosition(this->getPosition() + Vec2i(m_padding.x, m_spacing + newSize.y)); - newSize.y = newSize.y + m_spacing + node->getSize().y; - - int tmpWidth = node->getSize().x + m_padding.x + m_padding.z; - - if (tmpWidth > newSize.x) - { - newSize.x = tmpWidth; - } - } - } - - newSize.y = newSize.y + m_padding.w; - setSize(newSize); -} - -void QtGraphNode::setStyle() -{ - if (!m_data) - { - return; - } - - QColor color = Qt::lightGray; - qreal radius = 0.0f; - QFont font("Source Code Pro"); - QPen p(Qt::transparent); - - bool undefined = false; - bool useUndefinedColor = false; - - switch (m_data->getType()) - { - case Node::NODE_UNDEFINED: - undefined = true; - case Node::NODE_NAMESPACE: - color = Qt::white; - - p.setColor("#cc8d91"); - p.setWidth(1); - - font.setPointSize(12); - - radius = 20.0f; - m_padding.x = m_padding.z = 15; - m_padding.y = 6; - m_padding.w = 15; - break; - - case Node::NODE_UNDEFINED_TYPE: - undefined = true; - case Node::NODE_STRUCT: - case Node::NODE_CLASS: - case Node::NODE_ENUM: - case Node::NODE_TYPEDEF: - if (m_isHovering) - { - m_rect->setShadow(QColor(0, 0, 0, 255), 5); - } - else - { - m_rect->setShadow(QColor(0, 0, 0, 128), 5); - } - - font.setPointSize(14); - - color = "#ededed"; - if (m_subNodes.size()) - { - radius = 20.0f; - m_padding.x = m_padding.z = 15; - m_padding.y = m_padding.w = 10; - } - else - { - radius = 10.0f; - m_padding.x = m_padding.z = 8; - m_padding.y = m_padding.w = 5; - } - break; - - case Node::NODE_UNDEFINED_FUNCTION: - undefined = true; - useUndefinedColor = true; - case Node::NODE_FUNCTION: - case Node::NODE_METHOD: - if (m_isActive || m_isHovering) - { - color = "#ffcc00"; - font.setWeight(QFont::Bold); - } - else - { - color = "#ffe47a"; - } - - font.setPointSize(11); - - radius = 8.0f; - m_padding.x = m_padding.z = 5; - m_padding.y = m_padding.w = 3; - break; - - case Node::NODE_UNDEFINED_VARIABLE: - undefined = true; - useUndefinedColor = true; - case Node::NODE_GLOBAL_VARIABLE: - case Node::NODE_FIELD: - if (m_isActive || m_isHovering) - { - color = "#62b29d"; - font.setWeight(QFont::Bold); - } - else - { - color = "#9ab4ad"; - } - - font.setPointSize(11); - - radius = 8.0f; - m_padding.x = m_padding.z = 5; - m_padding.y = m_padding.w = 3; - break; - } - - if (m_isActive) - { - p.setWidthF(1.5f); - p.setColor("#3c3c3c"); - } - - m_rect->setPen(p); - m_rect->setBrush(QBrush(color)); - m_rect->setRadius(radius); - - if (undefined) - { - QtDeviceScaledPixmap pixmap("data/gui/graph_view/images/pattern.png"); - pixmap.scaleToHeight(10); - - if (!m_undefinedRect) - { - m_undefinedRect = new QtGraphicsRoundedRectItem(this); - } - - p.setWidth(1); - p.setColor(Qt::transparent); - if (useUndefinedColor && !m_isActive) - { - p.setColor(color); - } - m_undefinedRect->setPen(p); - m_undefinedRect->setBrush(QBrush(pixmap.pixmap())); - m_undefinedRect->setRadius(radius); - } - - m_text->setFont(font); - m_text->setPos(m_padding.x, m_padding.y); - - m_baseSize.x = QFontMetrics(m_text->font()).width(m_text->text()) + m_padding.x + m_padding.z; - m_baseSize.y = QFontMetrics(m_text->font()).height() + m_padding.y + m_padding.w; -} diff --git a/src/app/qt/view/graphElements/QtGraphNode.h b/src/app/qt/view/graphElements/QtGraphNode.h index 648ff1fe..864942c5 100644 --- a/src/app/qt/view/graphElements/QtGraphNode.h +++ b/src/app/qt/view/graphElements/QtGraphNode.h @@ -1,6 +1,7 @@ #ifndef QT_GRAPH_NODE_H #define QT_GRAPH_NODE_H +#include #include #include "component/view/graphElements/GraphNode.h" @@ -14,6 +15,8 @@ class QtGraphNode , public QGraphicsRectItem { public: + static QFont getFontForNodeType(Node::NodeType type); + QtGraphNode(); QtGraphNode(const Node* data); virtual ~QtGraphNode(); @@ -22,10 +25,11 @@ public: void setName(const std::string& name); virtual Vec2i getPosition() const; - virtual void setPosition(const Vec2i& position); + virtual bool setPosition(const Vec2i& position); + virtual void moveTo(const Vec2i& position); virtual Vec2i getSize() const; - virtual void setSize(Vec2i size); + virtual void setSize(const Vec2i& size); virtual Vec4i getBoundingRect() const; virtual Vec4i getParentBoundingRect() const; @@ -45,16 +49,12 @@ public: void addComponent(const std::shared_ptr& component); std::list> getSubNodes() const; - void addSubNode(const std::shared_ptr& node); + virtual void addSubNode(const std::shared_ptr& node); - /** - * @brief Returns the count of all connected edges and active nodes (including sub nodes) - */ - unsigned int getEdgeAndActiveCountRecursive() const; - - virtual void hideContent(); + void setStyle(); virtual void onClick(); + void hoverEnter(); protected: virtual void mousePressEvent(QGraphicsSceneMouseEvent* event); @@ -65,9 +65,6 @@ protected: virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent* event); void notifyEdgesAfterMove(); - void onSizeChanged(); - - virtual void rebuildLayout(); std::list> m_outEdges; std::list> m_inEdges; @@ -79,15 +76,9 @@ protected: QtGraphicsRoundedRectItem* m_rect; QtGraphicsRoundedRectItem* m_undefinedRect; - Vec2i m_baseSize; - Vec2i m_currentSize; - - Vec4i m_padding; - int m_spacing; + Vec2i m_size; private: - void setStyle(); - std::list> m_components; bool m_isActive; diff --git a/src/app/qt/view/graphElements/QtGraphNodeAccess.cpp b/src/app/qt/view/graphElements/QtGraphNodeAccess.cpp index 6f6f6f23..67f6dd56 100644 --- a/src/app/qt/view/graphElements/QtGraphNodeAccess.cpp +++ b/src/app/qt/view/graphElements/QtGraphNodeAccess.cpp @@ -4,79 +4,67 @@ #include #include +#include "utility/messaging/type/MessageGraphNodeExpand.h" + #include "qt/graphics/QtGraphicsRoundedRectItem.h" #include "qt/utility/QtDeviceScaledPixmap.h" -QtGraphNodeAccess::QtAccessArrow::QtAccessArrow(QGraphicsItem* parent) +QtGraphNodeAccess::QtAccessToggle::QtAccessToggle(bool expanded, int invisibleSubNodeCount, QGraphicsItem* parent) : QGraphicsRectItem(parent) { + const int iconHeight = 4; m_icon = new QGraphicsPixmapItem(this); - QFont font; - font.setFamily("Myriad Pro"); - font.setWeight(QFont::Normal); - font.setPointSize(9); - - m_number = new QGraphicsSimpleTextItem(this); - m_number->setFont(font); -} - -QtGraphNodeAccess::QtAccessArrow::~QtAccessArrow() -{ -} - -int QtGraphNodeAccess::QtAccessArrow::update(bool visible, int number) -{ - const int iconHeight = 4; - - int spacing = 0; - - if (!visible) + if (!expanded && !invisibleSubNodeCount) { - m_icon->hide(); - m_number->hide(); - return spacing; - } - - m_icon->show(); - - QtDeviceScaledPixmap pixmap("data/gui/graph_view/images/arrow.png"); - pixmap.scaleToHeight(iconHeight); - - if (number) - { - m_number->show(); - spacing = 13; - - QString numberStr = QString::number(number); - m_number->setText(numberStr); - m_number->setPos( - -QFontMetrics(m_number->font()).width(numberStr) / 2, - -iconHeight - QFontMetrics(m_number->font()).height() - ); + this->hide(); + return; } else { - m_number->hide(); - spacing = 5; + QtDeviceScaledPixmap pixmap("data/gui/graph_view/images/arrow.png"); + pixmap.scaleToHeight(iconHeight); - pixmap.mirror(); + if (invisibleSubNodeCount) + { + QFont font; + font.setFamily("Myriad Pro"); + font.setWeight(QFont::Normal); + font.setPointSize(9); + + m_number = new QGraphicsSimpleTextItem(this); + m_number->setFont(font); + + QString numberStr = QString::number(invisibleSubNodeCount); + m_number->setText(numberStr); + m_number->setPos( + -QFontMetrics(m_number->font()).width(numberStr) / 2, + -iconHeight - QFontMetrics(m_number->font()).height() + ); + } + else + { + pixmap.mirror(); + } + + m_icon->setPixmap(pixmap.pixmap()); + m_icon->setPos(-pixmap.width() / 2, -iconHeight); } +} - m_icon->setPixmap(pixmap.pixmap()); - m_icon->setPos(-pixmap.width() / 2, -iconHeight); - - return spacing; +QtGraphNodeAccess::QtAccessToggle::~QtAccessToggle() +{ } -QtGraphNodeAccess::QtGraphNodeAccess(TokenComponentAccess::AccessType accessType) +QtGraphNodeAccess::QtGraphNodeAccess( + TokenComponentAccess::AccessType accessType, bool expanded, int invisibleSubNodeCount +) : QtGraphNode() - , m_contentHidden(false) + , m_access(accessType) , m_accessIconSize(20) { - m_padding = Vec4i(10, 10, 10, 10); - m_spacing = 8; + Vec2i padding(10, 10); QFont font; font.setFamily("Myriad Pro"); @@ -84,7 +72,7 @@ QtGraphNodeAccess::QtGraphNodeAccess(TokenComponentAccess::AccessType accessType font.setPointSize(11); font.setCapitalization(QFont::AllUppercase); m_text->setFont(font); - m_text->setPos(m_padding.x + m_accessIconSize + 3, m_padding.y + m_accessIconSize / 2 - 1); + m_text->setPos(padding.x + m_accessIconSize + 3, padding.y + m_accessIconSize / 2 - 1); m_rect->setPen(QPen(Qt::transparent)); m_rect->setBrush(QBrush(Qt::white)); @@ -92,93 +80,41 @@ QtGraphNodeAccess::QtGraphNodeAccess(TokenComponentAccess::AccessType accessType std::string accessString = TokenComponentAccess::getAccessString(accessType); this->setName(accessString); + m_text->hide(); QtDeviceScaledPixmap pixmap(QString::fromStdString("data/gui/graph_view/images/" + accessString + ".png")); pixmap.scaleToHeight(m_accessIconSize); m_accessIcon = new QGraphicsPixmapItem(pixmap.pixmap(), this); - m_accessIcon->setPos(m_padding.x, m_padding.y); + m_accessIcon->setPos(padding.x, padding.y); - m_arrow = new QtAccessArrow(this); + m_accessToggle = new QtAccessToggle(expanded, invisibleSubNodeCount, this); } QtGraphNodeAccess::~QtGraphNodeAccess() { } -void QtGraphNodeAccess::hideContent() +void QtGraphNodeAccess::setSize(const Vec2i& size) { - m_contentHidden = true; + QtGraphNode::setSize(size); - QtGraphNode::hideContent(); + m_accessToggle->setPos(m_rect->rect().width() / 2, m_rect->rect().height() - 5); } -void QtGraphNodeAccess::showContent() +void QtGraphNodeAccess::addSubNode(const std::shared_ptr& node) { - for (std::shared_ptr node : m_subNodes) - { - node->show(); - } + QtGraphNode::addSubNode(node); - m_contentHidden = false; + m_text->show(); } void QtGraphNodeAccess::onClick() { - if (m_contentHidden) - { - showContent(); - } - else - { - hideContent(); - } + QtGraphNode* parent = getParent(); - onSizeChanged(); -} - -void QtGraphNodeAccess::rebuildLayout() -{ - bool allActive = true; - int visibleSubNodes = 0; - for (const std::shared_ptr& node : m_subNodes) + if (m_accessToggle->isVisible() && parent && parent->getData()) { - if (!node->getEdgeAndActiveCountRecursive()) - { - allActive = false; - } - - if (node->isVisible()) - { - visibleSubNodes++; - } + MessageGraphNodeExpand(parent->getData()->getId(), m_access).dispatch(); } - - int width = m_padding.x + m_accessIconSize; - int height = m_padding.y + m_accessIconSize; - - int arrowSpace = m_arrow->update(!allActive, m_subNodes.size() - visibleSubNodes); - - if (visibleSubNodes) - { - m_text->show(); - width += QFontMetrics(m_text->font()).width(m_text->text()) + 3; - } - else - { - m_text->hide(); - arrowSpace -= 3; - } - - m_padding.w = 10 + arrowSpace; - - width += m_padding.z; - height += m_padding.w; - - m_baseSize.x = width; - m_baseSize.y = height; - - QtGraphNode::rebuildLayout(); - - m_arrow->setPos(m_currentSize.x / 2, m_currentSize.y - 5); } diff --git a/src/app/qt/view/graphElements/QtGraphNodeAccess.h b/src/app/qt/view/graphElements/QtGraphNodeAccess.h index 9937d18a..5acf5dd5 100644 --- a/src/app/qt/view/graphElements/QtGraphNodeAccess.h +++ b/src/app/qt/view/graphElements/QtGraphNodeAccess.h @@ -8,14 +8,12 @@ class QtGraphNodeAccess : public QtGraphNode { public: - class QtAccessArrow + class QtAccessToggle : public QGraphicsRectItem { public: - QtAccessArrow(QGraphicsItem* parent); - virtual ~QtAccessArrow(); - - int update(bool visible, int number); + QtAccessToggle(bool expanded, int invisibleSubNodeCount, QGraphicsItem* parent); + virtual ~QtAccessToggle(); private: QGraphicsPixmapItem* m_icon; @@ -23,23 +21,22 @@ public: }; - QtGraphNodeAccess(TokenComponentAccess::AccessType accessType); + QtGraphNodeAccess(TokenComponentAccess::AccessType accessType, bool expanded, int invisibleSubNodeCount); virtual ~QtGraphNodeAccess(); - virtual void hideContent(); - virtual void showContent(); + virtual void setSize(const Vec2i& size); + + virtual void addSubNode(const std::shared_ptr& node); virtual void onClick(); - virtual void rebuildLayout(); - private: - bool m_contentHidden; + TokenComponentAccess::AccessType m_access; QGraphicsPixmapItem* m_accessIcon; int m_accessIconSize; - QtAccessArrow* m_arrow; + QtAccessToggle* m_accessToggle; }; #endif // QT_GRAPH_NODE_ACCESS_H diff --git a/src/app/qt/view/graphElements/nodeComponents/QtGraphNodeComponentMoveable.cpp b/src/app/qt/view/graphElements/nodeComponents/QtGraphNodeComponentMoveable.cpp index eecae1e3..c68d8183 100644 --- a/src/app/qt/view/graphElements/nodeComponents/QtGraphNodeComponentMoveable.cpp +++ b/src/app/qt/view/graphElements/nodeComponents/QtGraphNodeComponentMoveable.cpp @@ -31,7 +31,7 @@ void QtGraphNodeComponentMoveable::nodeMouseMoveEvent(QGraphicsSceneMouseEvent* std::shared_ptr node = m_graphNode.lock(); if (node != NULL) { - node->setPosition(Vec2i(event->scenePos().x() - m_mouseOffset.x, event->scenePos().y() - m_mouseOffset.y)); + node->moveTo(Vec2i(event->scenePos().x() - m_mouseOffset.x, event->scenePos().y() - m_mouseOffset.y)); event->accept(); } } diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt index cf9b8524..524560b2 100644 --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -193,6 +193,8 @@ add_files( utility/messaging/type/MessageActivateToken.h utility/messaging/type/MessageFind.h utility/messaging/type/MessageFinishedParsing.h + utility/messaging/type/MessageGraphNodeExpand.h + utility/messaging/type/MessageGraphNodeMove.h utility/messaging/type/MessageLoadProject.h utility/messaging/type/MessageLoadSource.h utility/messaging/type/MessageRefresh.h diff --git a/src/lib/component/controller/Controller.h b/src/lib/component/controller/Controller.h index 605562a9..4a4d9080 100644 --- a/src/lib/component/controller/Controller.h +++ b/src/lib/component/controller/Controller.h @@ -13,7 +13,7 @@ public: protected: template - ViewType* getView(); + ViewType* getView() const; private: Component* m_component; @@ -22,7 +22,7 @@ private: template -ViewType* Controller::getView() +ViewType* Controller::getView() const { if (m_component) return m_component->getView(); diff --git a/src/lib/component/controller/GraphController.cpp b/src/lib/component/controller/GraphController.cpp index afd59ebd..5ecde805 100644 --- a/src/lib/component/controller/GraphController.cpp +++ b/src/lib/component/controller/GraphController.cpp @@ -9,6 +9,19 @@ #include "component/view/GraphView.h" #include "data/access/GraphAccess.h" +GraphController::Margins::Margins() + : left(0) + , right(0) + , top(0) + , bottom(0) + , betweenX(0) + , betweenY(0) + , minWidth(0) + , charWidth(0.0f) +{ +} + + GraphController::GraphController(GraphAccess* graphAccess) : m_graphAccess(graphAccess) { @@ -29,7 +42,30 @@ void GraphController::handleMessage(MessageActivateTokens* message) createDummyGraphForTokenIds(message->tokenIds); } -GraphView* GraphController::getView() +void GraphController::handleMessage(MessageGraphNodeExpand* message) +{ + DummyNode* node = findDummyNodeAccessRecursive(m_dummyNodes, message->tokenId, message->access); + if (node) + { + node->expanded = !node->expanded; + + setActiveAndVisibility(m_activeTokenIds); + layoutNesting(); + + getView()->rebuildGraph(nullptr, m_dummyNodes, m_dummyEdges); + } +} + +void GraphController::handleMessage(MessageGraphNodeMove* message) +{ + DummyNode* node = findDummyNodeRecursive(m_dummyNodes, message->tokenId); + if (node) + { + node->position = message->position; + } +} + +GraphView* GraphController::getView() const { return Controller::getView(); } @@ -47,12 +83,14 @@ void GraphController::createDummyGraphForTokenIds(const std::vector& tokenId std::shared_ptr graph = m_graphAccess->getGraphForActiveTokenIds(tokenIds); - std::vector dummyNodes; - std::vector dummyEdges; + + m_dummyEdges.clear(); + std::set addedNodes; + std::vector dummyNodes; graph->forEachNode( - [&dummyNodes, &dummyEdges, &addedNodes, this](Node* node) + [&addedNodes, &dummyNodes, this](Node* node) { Node* parent = node->getLastParentNode(); Id id = parent->getId(); @@ -62,23 +100,29 @@ void GraphController::createDummyGraphForTokenIds(const std::vector& tokenId } addedNodes.insert(id); - dummyNodes.push_back(createDummyNodeTopDown(parent, &dummyEdges)); + dummyNodes.push_back(createDummyNodeTopDown(parent)); } ); - layoutFunction(dummyNodes); + m_dummyNodes = dummyNodes; - view->rebuildGraph(graph, tokenIds, dummyNodes, dummyEdges); + m_activeTokenIds = tokenIds; + setActiveAndVisibility(tokenIds); + + layoutNesting(); + layoutFunction(m_dummyNodes); + + view->rebuildGraph(graph, m_dummyNodes, m_dummyEdges); } -DummyNode GraphController::createDummyNodeTopDown(Node* node, std::vector* dummyEdges) const +DummyNode GraphController::createDummyNodeTopDown(Node* node) { DummyNode result(node); node->forEachChildNode( - [&result, dummyEdges, this](Node* child) + [node, &result, this](Node* child) { - DummyNode* container = nullptr; + DummyNode* parent = nullptr; Edge* edge = child->getMemberEdge(); TokenComponentAccess* access = edge->getComponent(); @@ -90,36 +134,43 @@ DummyNode GraphController::createDummyNodeTopDown(Node* node, std::vectorgetId(), accessType); + if (oldParent) + { + parent->expanded = oldParent->expanded; + } + } } else { - container = &result; + parent = &result; } - container->subNodes.push_back(createDummyNodeTopDown(child, dummyEdges)); + parent->subNodes.push_back(createDummyNodeTopDown(child)); } ); node->forEachEdge( - [&result, node, dummyEdges](Edge* edge) + [&result, node, this](Edge* edge) { if (edge->isType(Edge::EDGE_MEMBER)) { return; } - for (const DummyEdge& dummy : *dummyEdges) + result.connected = true; + + for (const DummyEdge& dummy : m_dummyEdges) { if (dummy.data->getId() == edge->getId()) { @@ -127,9 +178,291 @@ DummyNode GraphController::createDummyNodeTopDown(Node* node, std::vectorpush_back(DummyEdge(edge->getFrom()->getId(), edge->getTo()->getId(), edge)); + m_dummyEdges.push_back(DummyEdge(edge->getFrom()->getId(), edge->getTo()->getId(), edge)); } ); return result; } + +void GraphController::setActiveAndVisibility(const std::vector& activeTokenIds) +{ + for (DummyNode& node : m_dummyNodes) + { + setNodeActiveAndVisibilityRecursiveBottomUp(node, activeTokenIds); + } + + for (DummyEdge& edge : m_dummyEdges) + { + edge.visible = true; + if (find(activeTokenIds.begin(), activeTokenIds.end(), edge.data->getId()) != activeTokenIds.end()) + { + edge.active = true; + } + } +} + +bool GraphController::setNodeActiveAndVisibilityRecursiveBottomUp( + DummyNode& node, const std::vector& activeTokenIds +) const { + node.visible = false; + node.active = false; + + if (node.data) + { + node.active = find(activeTokenIds.begin(), activeTokenIds.end(), node.data->getId()) != activeTokenIds.end(); + } + + bool childVisible = false; + for (DummyNode& subNode : node.subNodes) + { + if (setNodeActiveAndVisibilityRecursiveBottomUp(subNode, activeTokenIds)) + { + childVisible = true; + } + } + + if (node.active || node.connected || childVisible) + { + setNodeVisibilityRecursiveTopDown(node); + } + + return node.visible; +} + +void GraphController::setNodeVisibilityRecursiveTopDown(DummyNode& node) const +{ + node.visible = true; + + for (DummyNode& subNode : node.subNodes) + { + if (subNode.accessType != TokenComponentAccess::ACCESS_NONE || node.expanded || + (node.data && node.data->getType() == Node::NODE_ENUM)) + { + setNodeVisibilityRecursiveTopDown(subNode); + } + } +} + +void GraphController::layoutNesting() +{ + if (!m_viewMetrics.width) + { + m_viewMetrics = getView()->getViewMetrics(); + } + + for (DummyNode& node : m_dummyNodes) + { + layoutNestingRecursive(node); + } +} + +void GraphController::layoutNestingRecursive(DummyNode& node) const +{ + Margins margins = getMarginsForDummyNode(node); + + int y = 0; + int x = 0; + int width = margins.minWidth; + int height = 0; + + if (node.data) + { + width = margins.charWidth * node.data->getName().size(); + } + + bool layoutHorizontal = true; + for (DummyNode& subNode : node.subNodes) + { + if (!subNode.visible) + { + continue; + } + + layoutNestingRecursive(subNode); + + if (subNode.data || subNode.expanded || subNode.invisibleSubNodeCount != subNode.subNodes.size()) + { + layoutHorizontal = false; + } + } + + for (DummyNode& subNode : node.subNodes) + { + if (!subNode.visible) + { + continue; + } + + subNode.position.x = margins.left + x; + subNode.position.y = margins.top + y; + + if (layoutHorizontal) + { + x += subNode.size.x + margins.betweenX; + if (subNode.size.y > height) + { + height = subNode.size.y; + } + } + else + { + y += subNode.size.y + margins.betweenY; + if (subNode.size.x > width) + { + width = subNode.size.x; + } + } + } + + if (x > 0) + { + x -= margins.betweenX; + } + if (y > 0) + { + y -= margins.betweenY; + } + + if (layoutHorizontal && x > width) + { + width = x; + } + + node.size.x = margins.left + width + margins.right; + node.size.y = margins.top + y + height + margins.bottom; +} + +GraphController::Margins GraphController::getMarginsForDummyNode(DummyNode& node) const +{ + Margins margins; + margins.betweenX = margins.betweenY = 8; + + if (node.data) + { + switch (node.data->getType()) + { + case Node::NODE_UNDEFINED: + case Node::NODE_NAMESPACE: + margins.left = margins.right = 15; + margins.top = 28; + margins.bottom = 15; + + margins.charWidth = m_viewMetrics.typeNameCharWidth; + break; + + case Node::NODE_UNDEFINED_TYPE: + case Node::NODE_STRUCT: + case Node::NODE_CLASS: + case Node::NODE_ENUM: + case Node::NODE_TYPEDEF: + if (node.subNodes.size()) + { + margins.left = margins.right = 15; + margins.top = 30; + margins.bottom = 10; + } + else + { + margins.left = margins.right = 8; + margins.top = margins.bottom = 13; + } + + margins.charWidth = m_viewMetrics.typeNameCharWidth; + break; + + case Node::NODE_UNDEFINED_FUNCTION: + case Node::NODE_FUNCTION: + case Node::NODE_METHOD: + margins.left = margins.right = 5; + margins.top = margins.bottom = 10; + + margins.charWidth = m_viewMetrics.functionNameCharWidth; + break; + + case Node::NODE_UNDEFINED_VARIABLE: + case Node::NODE_GLOBAL_VARIABLE: + case Node::NODE_FIELD: + margins.left = margins.right = 5; + margins.top = margins.bottom = 10; + + margins.charWidth = m_viewMetrics.variableNameCharWidth; + break; + } + } + else + { + node.invisibleSubNodeCount = 0; + for (const DummyNode& subNode : node.subNodes) + { + if (!subNode.visible) + { + node.invisibleSubNodeCount++; + } + } + + margins.left = margins.right = 10; + margins.top = 40; + + if (node.invisibleSubNodeCount == node.subNodes.size()) + { + margins.minWidth = 20; + margins.bottom = 10; + } + else + { + margins.minWidth = 82; + + if (node.expanded) + { + margins.bottom = 15; + } + else if (node.invisibleSubNodeCount) + { + margins.bottom = 23; + } + else + { + margins.bottom = 10; + } + } + } + + return margins; +} + +DummyNode* GraphController::findDummyNodeRecursive(std::vector& nodes, Id tokenId) +{ + for (DummyNode& node : nodes) + { + if (node.data && node.data->getId() == tokenId) + { + return &node; + } + + DummyNode* result = findDummyNodeRecursive(node.subNodes, tokenId); + if (result != nullptr) + { + return result; + } + } + + return nullptr; +} + +DummyNode* GraphController::findDummyNodeAccessRecursive( + std::vector& nodes, Id parentId, TokenComponentAccess::AccessType type +){ + DummyNode* node = findDummyNodeRecursive(nodes, parentId); + if (node) + { + for (DummyNode& subNode : node->subNodes) + { + if (subNode.accessType == type) + { + return &subNode; + } + } + } + return nullptr; +} diff --git a/src/lib/component/controller/GraphController.h b/src/lib/component/controller/GraphController.h index fbbf000c..676a74cb 100644 --- a/src/lib/component/controller/GraphController.h +++ b/src/lib/component/controller/GraphController.h @@ -6,14 +6,16 @@ #include "utility/messaging/MessageListener.h" #include "utility/messaging/type/MessageActivateToken.h" #include "utility/messaging/type/MessageActivateTokens.h" +#include "utility/messaging/type/MessageGraphNodeExpand.h" +#include "utility/messaging/type/MessageGraphNodeMove.h" #include "component/controller/Controller.h" #include "component/controller/GraphLayouter.h" +#include "component/view/GraphView.h" struct DummyNode; struct DummyEdge; class Graph; -class GraphView; class GraphAccess; class Node; @@ -21,21 +23,59 @@ class GraphController : public Controller , public MessageListener , public MessageListener + , public MessageListener + , public MessageListener { public: + struct Margins + { + Margins(); + + int left; + int right; + + int top; + int bottom; + + int betweenX; + int betweenY; + + int minWidth; + float charWidth; + }; + GraphController(GraphAccess* graphAccess); ~GraphController(); private: virtual void handleMessage(MessageActivateToken* message); virtual void handleMessage(MessageActivateTokens* message); + virtual void handleMessage(MessageGraphNodeExpand* message); + virtual void handleMessage(MessageGraphNodeMove* message); - GraphView* getView(); + GraphView* getView() const; void createDummyGraphForTokenIds(const std::vector& tokenIds); - DummyNode createDummyNodeTopDown(Node* node, std::vector* dummyEdges) const; + DummyNode createDummyNodeTopDown(Node* node); + + void setActiveAndVisibility(const std::vector& activeTokenIds); + bool setNodeActiveAndVisibilityRecursiveBottomUp(DummyNode& node, const std::vector& activeTokenIds) const; + void setNodeVisibilityRecursiveTopDown(DummyNode& node) const; + + void layoutNesting(); + void layoutNestingRecursive(DummyNode& node) const; + + Margins getMarginsForDummyNode(DummyNode& node) const; + DummyNode* findDummyNodeRecursive(std::vector& nodes, Id tokenId); + DummyNode* findDummyNodeAccessRecursive(std::vector& nodes, Id parentId, TokenComponentAccess::AccessType type); GraphAccess* m_graphAccess; + GraphView::Metrics m_viewMetrics; + + std::vector m_dummyNodes; + std::vector m_dummyEdges; + + std::vector m_activeTokenIds; }; #endif // GRAPH_CONTROLLER_H diff --git a/src/lib/component/view/GraphView.cpp b/src/lib/component/view/GraphView.cpp index a6bab76f..5da420c2 100644 --- a/src/lib/component/view/GraphView.cpp +++ b/src/lib/component/view/GraphView.cpp @@ -1,5 +1,14 @@ #include "component/view/GraphView.h" +GraphView::Metrics::Metrics() + : width(0) + , height(0) + , typeNameCharWidth(0.0f) + , variableNameCharWidth(0.0f) + , functionNameCharWidth(0.0f) +{ +} + GraphView::GraphView(ViewLayout* viewLayout) : View(viewLayout, Vec2i(100, 100)) { diff --git a/src/lib/component/view/GraphView.h b/src/lib/component/view/GraphView.h index 4bd893e2..cf1c5c2a 100644 --- a/src/lib/component/view/GraphView.h +++ b/src/lib/component/view/GraphView.h @@ -15,18 +15,28 @@ class Graph; class GraphView : public View { public: + struct Metrics + { + Metrics(); + + int width; + int height; + + float typeNameCharWidth; + float variableNameCharWidth; + float functionNameCharWidth; + }; + GraphView(ViewLayout* viewLayout); virtual ~GraphView(); virtual std::string getName() const; virtual void rebuildGraph( - std::shared_ptr graph, - std::vector activeTokenIds, - const std::vector& nodes, - const std::vector& edges) = 0; - + std::shared_ptr graph, const std::vector& nodes, const std::vector& edges) = 0; virtual void clear() = 0; + + virtual Metrics getViewMetrics() const = 0; }; #endif // GRAPH_VIEW_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 4af86d34..bafb1da8 100644 --- a/src/lib/component/view/graphElements/GraphEdge.h +++ b/src/lib/component/view/graphElements/GraphEdge.h @@ -33,6 +33,8 @@ struct DummyEdge : ownerId(o) , targetId(t) , data(data) + , visible(false) + , active(false) { } @@ -40,6 +42,9 @@ struct DummyEdge Id targetId; const Edge* data; + + bool visible; + bool active; }; #endif // GRAPH_EDGE_H diff --git a/src/lib/component/view/graphElements/GraphNode.h b/src/lib/component/view/graphElements/GraphNode.h index ea8124f6..3f2ef26c 100644 --- a/src/lib/component/view/graphElements/GraphNode.h +++ b/src/lib/component/view/graphElements/GraphNode.h @@ -26,9 +26,12 @@ public: void setData(const Node* data); virtual Vec2i getPosition() const = 0; - virtual void setPosition(const Vec2i& position) = 0; + virtual bool setPosition(const Vec2i& position) = 0; + virtual void moveTo(const Vec2i& position) = 0; virtual Vec2i getSize() const = 0; + virtual void setSize(const Vec2i& size) = 0; + virtual Vec4i getBoundingRect() const = 0; virtual Vec4i getParentBoundingRect() const = 0; @@ -47,19 +50,39 @@ struct DummyNode DummyNode(const Node* data) : data(data) , accessType(TokenComponentAccess::ACCESS_NONE) + , active(false) + , connected(false) + , expanded(false) + , invisibleSubNodeCount(0) + , visible(false) { } DummyNode(TokenComponentAccess::AccessType accessType) : data(nullptr) , accessType(accessType) + , active(false) + , connected(false) + , expanded(false) + , invisibleSubNodeCount(0) + , visible(false) { } const Node* data; - const TokenComponentAccess::AccessType accessType; + TokenComponentAccess::AccessType accessType; Vec2i position; + Vec2i size; + + bool active; + bool connected; + + bool expanded; + size_t invisibleSubNodeCount; + + bool visible; + std::vector subNodes; }; diff --git a/src/lib/utility/messaging/type/MessageGraphNodeExpand.h b/src/lib/utility/messaging/type/MessageGraphNodeExpand.h new file mode 100644 index 00000000..7ab7b062 --- /dev/null +++ b/src/lib/utility/messaging/type/MessageGraphNodeExpand.h @@ -0,0 +1,26 @@ +#ifndef MESSAGE_GRAPH_NODE_EXPAND_H +#define MESSAGE_GRAPH_NODE_EXPAND_H + +#include "utility/messaging/Message.h" +#include "utility/types.h" +#include "data/graph/token_component/TokenComponentAccess.h" + +class MessageGraphNodeExpand: public Message +{ +public: + MessageGraphNodeExpand(Id tokenId, TokenComponentAccess::AccessType access) + : tokenId(tokenId) + , access(access) + { + } + + static const std::string getStaticType() + { + return "MessageGraphNodeExpand"; + } + + const Id tokenId; + const TokenComponentAccess::AccessType access; +}; + +#endif // MESSAGE_GRAPH_NODE_EXPAND_H diff --git a/src/lib/utility/messaging/type/MessageGraphNodeMove.h b/src/lib/utility/messaging/type/MessageGraphNodeMove.h new file mode 100644 index 00000000..0253c118 --- /dev/null +++ b/src/lib/utility/messaging/type/MessageGraphNodeMove.h @@ -0,0 +1,26 @@ +#ifndef MESSAGE_GRAPH_NODE_MOVE_H +#define MESSAGE_GRAPH_NODE_MOVE_H + +#include "utility/math/Vector2.h" +#include "utility/messaging/Message.h" +#include "utility/types.h" + +class MessageGraphNodeMove: public Message +{ +public: + MessageGraphNodeMove(Id tokenId, Vec2i position) + : tokenId(tokenId) + , position(position) + { + } + + static const std::string getStaticType() + { + return "MessageGraphNodeMove"; + } + + const Id tokenId; + const Vec2i position; +}; + +#endif // MESSAGE_GRAPH_NODE_MOVE_H