From e5cad53e8530fca2c0485611d15a133c6140e903 Mon Sep 17 00:00:00 2001 From: Eberhard Graether Date: Sat, 6 May 2017 22:56:17 +0200 Subject: [PATCH] ui: Click edges in trail to show source location --- src/lib/CMakeLists.txt | 1 + .../component/controller/CodeController.cpp | 19 ++++ src/lib/component/controller/CodeController.h | 3 + .../component/controller/GraphController.cpp | 15 +++- .../component/controller/GraphController.h | 3 + .../controller/UndoRedoController.cpp | 12 +++ .../component/controller/UndoRedoController.h | 3 + src/lib/component/view/GraphView.h | 2 + .../messaging/type/MessageActivateTrailEdge.h | 48 +++++++++++ src/lib_gui/qt/view/QtGraphView.cpp | 86 +++++++++++++------ src/lib_gui/qt/view/QtGraphView.h | 7 +- .../qt/view/graphElements/QtGraphEdge.cpp | 75 ++++++++-------- .../qt/view/graphElements/QtGraphEdge.h | 12 ++- 13 files changed, 215 insertions(+), 71 deletions(-) create mode 100644 src/lib/utility/messaging/type/MessageActivateTrailEdge.h diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt index 78312cf7..c7128572 100644 --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -339,6 +339,7 @@ add_files( utility/messaging/type/MessageActivateTokenIds.h utility/messaging/type/MessageActivateTokens.h utility/messaging/type/MessageActivateTrail.h + utility/messaging/type/MessageActivateTrailEdge.h utility/messaging/type/MessageActivateWindow.h utility/messaging/type/MessageChangeFileView.h utility/messaging/type/MessageClearErrorCount.h diff --git a/src/lib/component/controller/CodeController.cpp b/src/lib/component/controller/CodeController.cpp index 6b741d3f..bbfe7f30 100644 --- a/src/lib/component/controller/CodeController.cpp +++ b/src/lib/component/controller/CodeController.cpp @@ -175,6 +175,25 @@ void CodeController::handleMessage(MessageActivateTokens* message) showContents(message); } +void CodeController::handleMessage(MessageActivateTrailEdge* message) +{ + TRACE("trail edge activate"); + + CodeView* view = getView(); + view->clearCodeSnippets(); + + std::vector activeTokenIds = { message->tokenId }; + m_collection = m_storageAccess->getSourceLocationsForTokenIds(activeTokenIds); + + view->showCodeSnippets( + getSnippetsForActiveSourceLocations(m_collection.get(), 0), + activeTokenIds, + !message->isReplayed() || message->isReplayCleared() + ); + + showContents(message); +} + void CodeController::handleMessage(MessageChangeFileView* message) { TRACE("code change file"); diff --git a/src/lib/component/controller/CodeController.h b/src/lib/component/controller/CodeController.h index c2e09bc2..f49ebb62 100644 --- a/src/lib/component/controller/CodeController.h +++ b/src/lib/component/controller/CodeController.h @@ -9,6 +9,7 @@ #include "utility/messaging/type/MessageActivateAll.h" #include "utility/messaging/type/MessageActivateLocalSymbols.h" #include "utility/messaging/type/MessageActivateTokens.h" +#include "utility/messaging/type/MessageActivateTrailEdge.h" #include "utility/messaging/type/MessageChangeFileView.h" #include "utility/messaging/type/MessageClearErrorCount.h" #include "utility/messaging/type/MessageCodeViewExpandedInitialFiles.h" @@ -37,6 +38,7 @@ class CodeController , public MessageListener , public MessageListener , public MessageListener + , public MessageListener , public MessageListener , public MessageListener , public MessageListener @@ -60,6 +62,7 @@ private: virtual void handleMessage(MessageActivateAll* message); virtual void handleMessage(MessageActivateLocalSymbols* message); virtual void handleMessage(MessageActivateTokens* message); + virtual void handleMessage(MessageActivateTrailEdge* message); virtual void handleMessage(MessageChangeFileView* message); virtual void handleMessage(MessageClearErrorCount* message); virtual void handleMessage(MessageCodeViewExpandedInitialFiles* message); diff --git a/src/lib/component/controller/GraphController.cpp b/src/lib/component/controller/GraphController.cpp index 246a7fc7..69f570b2 100644 --- a/src/lib/component/controller/GraphController.cpp +++ b/src/lib/component/controller/GraphController.cpp @@ -152,11 +152,24 @@ void GraphController::handleMessage(MessageActivateTrail* message) MessageStatus("Displaying graph", false, true).dispatch(); - buildGraph(message, true, true, false); + message->setIsReplayed(false); + buildGraph(message, message->isLast(), true, false); +} + +void GraphController::handleMessage(MessageActivateTrailEdge* message) +{ + TRACE("trail edge activate"); + + getView()->activateEdge(message->tokenId, message->isReplayed()); } void GraphController::handleMessage(MessageFlushUpdates* message) { + if (m_graph->getTrailMode() != Graph::TRAIL_NONE) + { + return; + } + buildGraph(message, true, !message->keepContent(), false); } diff --git a/src/lib/component/controller/GraphController.h b/src/lib/component/controller/GraphController.h index 6596effd..f0486cf4 100644 --- a/src/lib/component/controller/GraphController.h +++ b/src/lib/component/controller/GraphController.h @@ -8,6 +8,7 @@ #include "utility/messaging/type/MessageActivateAll.h" #include "utility/messaging/type/MessageActivateTokens.h" #include "utility/messaging/type/MessageActivateTrail.h" +#include "utility/messaging/type/MessageActivateTrailEdge.h" #include "utility/messaging/type/MessageColorSchemeTest.h" #include "utility/messaging/type/MessageFlushUpdates.h" #include "utility/messaging/type/MessageFocusIn.h" @@ -36,6 +37,7 @@ class GraphController , public MessageListener , public MessageListener , public MessageListener + , public MessageListener , public MessageListener , public MessageListener , public MessageListener @@ -56,6 +58,7 @@ private: virtual void handleMessage(MessageActivateAll* message); virtual void handleMessage(MessageActivateTokens* message); virtual void handleMessage(MessageActivateTrail* message); + virtual void handleMessage(MessageActivateTrailEdge* message); virtual void handleMessage(MessageFlushUpdates* message); virtual void handleMessage(MessageFocusIn* message); virtual void handleMessage(MessageFocusOut* message); diff --git a/src/lib/component/controller/UndoRedoController.cpp b/src/lib/component/controller/UndoRedoController.cpp index d2c85ef3..a2123d6c 100644 --- a/src/lib/component/controller/UndoRedoController.cpp +++ b/src/lib/component/controller/UndoRedoController.cpp @@ -90,6 +90,18 @@ void UndoRedoController::handleMessage(MessageActivateTrail* message) processCommand(command); } +void UndoRedoController::handleMessage(MessageActivateTrailEdge* message) +{ + if (sameMessageTypeAsLast(message) && + static_cast(lastMessage())->tokenId == message->tokenId) + { + return; + } + + Command command(std::make_shared(*message), Command::ORDER_ADAPT, true); + processCommand(command); +} + void UndoRedoController::handleMessage(MessageChangeFileView* message) { Command command(std::make_shared(*message), Command::ORDER_VIEW); diff --git a/src/lib/component/controller/UndoRedoController.h b/src/lib/component/controller/UndoRedoController.h index 9e806725..caa36c91 100644 --- a/src/lib/component/controller/UndoRedoController.h +++ b/src/lib/component/controller/UndoRedoController.h @@ -9,6 +9,7 @@ #include "utility/messaging/type/MessageActivateLocalSymbols.h" #include "utility/messaging/type/MessageActivateTokens.h" #include "utility/messaging/type/MessageActivateTrail.h" +#include "utility/messaging/type/MessageActivateTrailEdge.h" #include "utility/messaging/type/MessageChangeFileView.h" #include "utility/messaging/type/MessageDeactivateEdge.h" #include "utility/messaging/type/MessageFinishedParsing.h" @@ -36,6 +37,7 @@ class UndoRedoController , public MessageListener , public MessageListener , public MessageListener + , public MessageListener , public MessageListener , public MessageListener , public MessageListener @@ -81,6 +83,7 @@ private: virtual void handleMessage(MessageActivateLocalSymbols* message); virtual void handleMessage(MessageActivateTokens* message); virtual void handleMessage(MessageActivateTrail* message); + virtual void handleMessage(MessageActivateTrailEdge* message); virtual void handleMessage(MessageChangeFileView* message); virtual void handleMessage(MessageDeactivateEdge* message); virtual void handleMessage(MessageFinishedParsing* message); diff --git a/src/lib/component/view/GraphView.h b/src/lib/component/view/GraphView.h index 2f630800..d3c2783e 100644 --- a/src/lib/component/view/GraphView.h +++ b/src/lib/component/view/GraphView.h @@ -44,6 +44,8 @@ public: virtual Vec2i getViewSize() const = 0; virtual void scrollToValues(int xValue, int yValue) = 0; + + virtual void activateEdge(Id edgeId, bool centerOrigin) = 0; }; #endif // GRAPH_VIEW_H diff --git a/src/lib/utility/messaging/type/MessageActivateTrailEdge.h b/src/lib/utility/messaging/type/MessageActivateTrailEdge.h new file mode 100644 index 00000000..8cfb79dc --- /dev/null +++ b/src/lib/utility/messaging/type/MessageActivateTrailEdge.h @@ -0,0 +1,48 @@ +#ifndef MESSAGE_ACTIVATE_TRAIL_EDGE_H +#define MESSAGE_ACTIVATE_TRAIL_EDGE_H + +#include "utility/messaging/Message.h" +#include "utility/types.h" + +#include "data/graph/Edge.h" +#include "data/name/NameHierarchy.h" + +class MessageActivateTrailEdge + : public Message +{ +public: + MessageActivateTrailEdge( + Id tokenId, Edge::EdgeType type, const NameHierarchy& sourceNameHierarchy, const NameHierarchy& targetNameHierarchy + ) + : tokenId(tokenId) + , type(type) + , sourceNameHierarchy(sourceNameHierarchy) + , targetNameHierarchy(targetNameHierarchy) + { + } + + static const std::string getStaticType() + { + return "MessageActivateTrailEdge"; + } + + std::string getFullName() const + { + std::string name = Edge::getReadableTypeString(type) + ":"; + name += sourceNameHierarchy.getQualifiedNameWithSignature() + "->"; + name += targetNameHierarchy.getQualifiedNameWithSignature(); + return name; + } + + virtual void print(std::ostream& os) const + { + os << tokenId << " - " << getFullName(); + } + + const Id tokenId; + const Edge::EdgeType type; + const NameHierarchy sourceNameHierarchy; + const NameHierarchy targetNameHierarchy; +}; + +#endif // MESSAGE_ACTIVATE_TRAIL_EDGE_H diff --git a/src/lib_gui/qt/view/QtGraphView.cpp b/src/lib_gui/qt/view/QtGraphView.cpp index b37ebac8..ca489248 100644 --- a/src/lib_gui/qt/view/QtGraphView.cpp +++ b/src/lib_gui/qt/view/QtGraphView.cpp @@ -200,6 +200,31 @@ void QtGraphView::scrollToValues(int xValue, int yValue) m_scrollValues = Vec2i(xValue, yValue); } +void QtGraphView::activateEdge(Id edgeId, bool centerOrigin) +{ + m_onQtThread( + [=]() + { + clickedInEmptySpace(); + + for (std::shared_ptr edge : m_oldEdges) + { + if (edge->getData() && edge->getData()->getId() == edgeId) + { + edge->setIsActive(true); + + if (centerOrigin) + { + centerNode(edge->getOwner().lock().get()); + } + + break; + } + } + } + ); +} + void QtGraphView::updateScrollBars() { QGraphicsView* view = getView(); @@ -240,6 +265,8 @@ void QtGraphView::clickedInEmptySpace() { activeEdges.push_back(edge); } + + edge->setIsFocused(false); } if (m_graph && m_graph->getTrailMode() != Graph::TRAIL_NONE) @@ -503,17 +530,7 @@ void QtGraphView::switchToNewGraphData() { if (m_centerActiveNode) { - Vec2i pos = m_activeNodes.front()->getPosition(); - Vec2i size = m_activeNodes.front()->getSize(); - - QRectF rect(pos.x, pos.y, size.x, size.y); - - if (rect.height() > view->height() - 200) - { - rect.setHeight(view->height() - 200); - } - - view->ensureVisibleAnimated(rect, 100, 100); + centerNode(m_activeNodes.front().get()); } if (m_activeNodes.size() == 1) @@ -603,17 +620,6 @@ void QtGraphView::doRebuildGraph( m_edges.clear(); - for (std::shared_ptr edge : edges) - { - for (size_t i = 0; i < edge->path.size(); i++) - { - edge->path[i].x = edge->path[i].x - offset.x(); - edge->path[i].z = edge->path[i].z - offset.x(); - edge->path[i].y = edge->path[i].y - offset.y(); - edge->path[i].w = edge->path[i].w - offset.y(); - } - } - // create edges Graph::TrailMode trailMode = m_graph ? m_graph->getTrailMode() : Graph::TRAIL_NONE; std::set visibleEdgeIds; @@ -621,7 +627,7 @@ void QtGraphView::doRebuildGraph( { if (!edge->data || !edge->data->isType(Edge::EDGE_AGGREGATION)) { - createEdge(view, edge.get(), &visibleEdgeIds, trailMode); + createEdge(view, edge.get(), &visibleEdgeIds, trailMode, offset); } } for (const std::shared_ptr edge : edges) @@ -784,7 +790,7 @@ std::shared_ptr QtGraphView::createNodeRecursive( } std::shared_ptr QtGraphView::createEdge( - QGraphicsView* view, const DummyEdge* edge, std::set* visibleEdgeIds, Graph::TrailMode trailMode) + QGraphicsView* view, const DummyEdge* edge, std::set* visibleEdgeIds, Graph::TrailMode trailMode, QPointF pathOffset) { if (!edge->visible) { @@ -801,12 +807,21 @@ std::shared_ptr QtGraphView::createEdge( if (trailMode != Graph::TRAIL_NONE) { - for (const Vec4i& rect : edge->path) + std::vector path = edge->path; + for (size_t i = 0; i < path.size(); i++) + { + path[i].x = path[i].x - pathOffset.x(); + path[i].z = path[i].z - pathOffset.x(); + path[i].y = path[i].y - pathOffset.y(); + path[i].w = path[i].w - pathOffset.y(); + } + + for (const Vec4i& rect : path) { m_virtualNodeRects.push_back(QRectF(QPointF(rect.x(), rect.y()), QPointF(rect.z(), rect.w()))); } - qtEdge->setIsTrailEdge(edge->path, trailMode == Graph::TRAIL_HORIZONTAL); + qtEdge->setIsTrailEdge(path, trailMode == Graph::TRAIL_HORIZONTAL); } qtEdge->updateLine(); @@ -854,7 +869,7 @@ std::shared_ptr QtGraphView::createAggregationEdge( return NULL; } - return createEdge(view, edge, visibleEdgeIds, Graph::TRAIL_NONE); + return createEdge(view, edge, visibleEdgeIds, Graph::TRAIL_NONE, QPointF()); } QRectF QtGraphView::itemsBoundingRect(const std::list>& items) const @@ -879,6 +894,23 @@ QRectF QtGraphView::getSceneRect(const std::list>& return sceneRect.adjusted(-75, -75, 75, 75).translated(m_sceneRectOffset); } +void QtGraphView::centerNode(QtGraphNode* node) +{ + QtGraphicsView* view = getView(); + + Vec2i pos = node->getPosition(); + Vec2i size = node->getSize(); + + QRectF rect(pos.x, pos.y, size.x, size.y); + + if (rect.height() > view->height() - 200) + { + rect.setHeight(view->height() - 200); + } + + view->ensureVisibleAnimated(rect, 100, 100); +} + void QtGraphView::compareNodesRecursive( std::list> newSubNodes, std::list> oldSubNodes, diff --git a/src/lib_gui/qt/view/QtGraphView.h b/src/lib_gui/qt/view/QtGraphView.h index a355c8b0..fcb6bd74 100644 --- a/src/lib_gui/qt/view/QtGraphView.h +++ b/src/lib_gui/qt/view/QtGraphView.h @@ -55,6 +55,8 @@ public: virtual void scrollToValues(int xValue, int yValue); + virtual void activateEdge(Id edgeId, bool centerOrigin); + private slots: void updateScrollBars(); void finishedTransition(); @@ -96,13 +98,15 @@ private: std::shared_ptr createNodeRecursive( QGraphicsView* view, std::shared_ptr parentNode, const DummyNode* node, bool multipleActive); std::shared_ptr createEdge( - QGraphicsView* view, const DummyEdge* edge, std::set* visibleEdgeIds, Graph::TrailMode trailMode); + QGraphicsView* view, const DummyEdge* edge, std::set* visibleEdgeIds, Graph::TrailMode trailMode, QPointF pathOffset); std::shared_ptr createAggregationEdge( QGraphicsView* view, const DummyEdge* edge, std::set* visibleEdgeIds); QRectF itemsBoundingRect(const std::list>& items) const; QRectF getSceneRect(const std::list>& items) const; + void centerNode(QtGraphNode* node); + void compareNodesRecursive( std::list> newSubNodes, std::list> oldSubNodes, @@ -123,6 +127,7 @@ private: QtThreadedFunctor m_refreshFunctor; QtThreadedFunctor&> m_focusInFunctor; QtThreadedFunctor&> m_focusOutFunctor; + QtThreadedLambdaFunctor m_onQtThread; std::shared_ptr m_graph; std::shared_ptr m_oldGraph; diff --git a/src/lib_gui/qt/view/graphElements/QtGraphEdge.cpp b/src/lib_gui/qt/view/graphElements/QtGraphEdge.cpp index f23ee60c..1d15a413 100644 --- a/src/lib_gui/qt/view/graphElements/QtGraphEdge.cpp +++ b/src/lib_gui/qt/view/graphElements/QtGraphEdge.cpp @@ -2,7 +2,6 @@ #include #include -#include #include "component/view/GraphViewStyle.h" #include "data/graph/Edge.h" @@ -12,12 +11,15 @@ #include "qt/graphics/QtLineItemStraight.h" #include "qt/view/graphElements/QtGraphNode.h" #include "utility/messaging/type/MessageActivateEdge.h" +#include "utility/messaging/type/MessageActivateTrailEdge.h" #include "utility/messaging/type/MessageFocusIn.h" #include "utility/messaging/type/MessageFocusOut.h" #include "utility/messaging/type/MessageGraphNodeBundleSplit.h" #include "utility/utility.h" #include "utility/utilityString.h" +QtGraphEdge* QtGraphEdge::s_focusedTrailEdge = nullptr; + QtGraphEdge::QtGraphEdge( const std::weak_ptr& owner, const std::weak_ptr& target, @@ -40,8 +42,6 @@ QtGraphEdge::QtGraphEdge( , m_isHorizontalTrail(false) , m_mousePos(0.0f, 0.0f) , m_mouseMoved(false) - , m_willFocusIn(false) - , m_ignoreFocusIn(false) { if (m_direction == TokenComponentAggregation::DIRECTION_BACKWARD) { @@ -50,6 +50,8 @@ QtGraphEdge::QtGraphEdge( m_fromActive = m_owner.lock()->getIsActive(); m_toActive = m_target.lock()->getIsActive(); + + s_focusedTrailEdge = nullptr; } QtGraphEdge::~QtGraphEdge() @@ -230,11 +232,25 @@ void QtGraphEdge::setIsActive(bool isActive) } } +void QtGraphEdge::setIsFocused(bool isFocused) +{ + if (m_isFocused != isFocused) + { + m_isFocused = isFocused; + updateLine(); + } +} + void QtGraphEdge::onClick() { if (isTrailEdge()) { - setIsActive(!getIsActive()); + MessageActivateTrailEdge( + getData()->getId(), + getData()->getType(), + getData()->getFrom()->getNameHierarchy(), + getData()->getTo()->getNameHierarchy() + ).dispatch(); return; } @@ -307,37 +323,18 @@ void QtGraphEdge::mouseReleaseEvent(QGraphicsSceneMouseEvent* event) void QtGraphEdge::hoverEnterEvent(QGraphicsSceneHoverEvent* event) { - if (!m_ignoreFocusIn) - { - QTimer::singleShot(50, this, SLOT(doFocusIn())); - m_ignoreFocusIn = true; - m_willFocusIn = true; - } -} - -void QtGraphEdge::hoverLeaveEvent(QGraphicsSceneHoverEvent* event) -{ - m_willFocusIn = false; - QTimer::singleShot(100, this, SLOT(doFocusOut())); - - if (!getData()) - { - focusOut(); - return; - } - - MessageFocusOut(std::vector(1, getData()->getId())).dispatch(); -} - -void QtGraphEdge::doFocusIn() -{ - if (!m_willFocusIn) - { - return; - } - if (!getData() || isTrailEdge()) { + if (isTrailEdge()) + { + if (s_focusedTrailEdge && s_focusedTrailEdge != this) + { + s_focusedTrailEdge->focusOut(); + } + + s_focusedTrailEdge = this; + } + focusIn(); return; } @@ -345,9 +342,17 @@ void QtGraphEdge::doFocusIn() MessageFocusIn(std::vector(1, getData()->getId())).dispatch(); } -void QtGraphEdge::doFocusOut() +void QtGraphEdge::hoverLeaveEvent(QGraphicsSceneHoverEvent* event) { - m_ignoreFocusIn = false; + s_focusedTrailEdge = nullptr; + + if (!getData() || isTrailEdge()) + { + focusOut(); + return; + } + + MessageFocusOut(std::vector(1, getData()->getId())).dispatch(); } void QtGraphEdge::setDirection(TokenComponentAggregation::Direction direction) diff --git a/src/lib_gui/qt/view/graphElements/QtGraphEdge.h b/src/lib_gui/qt/view/graphElements/QtGraphEdge.h index cf64ef16..5b3e9454 100644 --- a/src/lib_gui/qt/view/graphElements/QtGraphEdge.h +++ b/src/lib_gui/qt/view/graphElements/QtGraphEdge.h @@ -41,6 +41,8 @@ public: void setIsActive(bool isActive); void setFromAndToActive(bool fromActive, bool toActive); + void setIsFocused(bool isFocused); + void onClick(); void focusIn(); @@ -59,11 +61,10 @@ protected: virtual void hoverEnterEvent(QGraphicsSceneHoverEvent* event); virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent* event); -private slots: - void doFocusIn(); - void doFocusOut(); - private: + // used to unfocus recent edge, because hover leave event is not always received for trail edges (bezier) + static QtGraphEdge* s_focusedTrailEdge; + const Edge* m_data; std::weak_ptr m_owner; @@ -87,9 +88,6 @@ private: Vec2i m_mousePos; bool m_mouseMoved; - - bool m_willFocusIn; - bool m_ignoreFocusIn; }; #endif // QT_GRAPH_EDGE_H