From 72750822840d9f84f5b445a1063e6ab547ef811d Mon Sep 17 00:00:00 2001 From: Eberhard Graether Date: Wed, 24 Jun 2015 01:15:31 +0200 Subject: [PATCH] logic: correctly undoing graph interactions by replaying actions since last active token change This change introdoces a classification of commands by order in the undo stack. Undoing the last action will resend the message of the last active token change and all messages changing the ui after that. --- src/app/qt/view/QtGraphView.cpp | 2 +- .../graphElements/QtGraphNodeExpandToggle.cpp | 7 +- .../graphElements/QtGraphNodeExpandToggle.h | 3 +- .../component/controller/CodeController.cpp | 5 + .../controller/FeatureController.cpp | 24 ++-- .../component/controller/GraphController.cpp | 72 +++++++++--- .../component/controller/GraphController.h | 7 ++ .../component/controller/SearchController.cpp | 20 ++++ .../controller/UndoRedoController.cpp | 103 ++++++++++++------ .../component/controller/UndoRedoController.h | 25 +++-- .../component/controller/helper/DummyNode.h | 4 +- src/lib/utility/messaging/Message.h | 6 + src/lib/utility/messaging/MessageBase.h | 16 ++- src/lib/utility/messaging/MessageQueue.cpp | 32 ++++-- src/lib/utility/messaging/MessageQueue.h | 3 +- .../messaging/type/MessageGraphNodeExpand.h | 4 +- src/lib/utility/scheduling/Task.cpp | 5 + src/lib/utility/scheduling/Task.h | 1 + src/lib/utility/scheduling/TaskScheduler.cpp | 13 ++- src/lib/utility/scheduling/TaskScheduler.h | 5 +- 20 files changed, 262 insertions(+), 95 deletions(-) diff --git a/src/app/qt/view/QtGraphView.cpp b/src/app/qt/view/QtGraphView.cpp index 8671df6e..fd469bc5 100644 --- a/src/app/qt/view/QtGraphView.cpp +++ b/src/app/qt/view/QtGraphView.cpp @@ -175,7 +175,7 @@ void QtGraphView::doRebuildGraph( if (m_transition && m_transition->currentTime() < m_transition->totalDuration()) { m_transition->stop(); - switchToNewGraphData(); + finishedTransition(); } QGraphicsView* view = getView(); diff --git a/src/app/qt/view/graphElements/QtGraphNodeExpandToggle.cpp b/src/app/qt/view/graphElements/QtGraphNodeExpandToggle.cpp index 64864e50..8b14aeb8 100644 --- a/src/app/qt/view/graphElements/QtGraphNodeExpandToggle.cpp +++ b/src/app/qt/view/graphElements/QtGraphNodeExpandToggle.cpp @@ -10,7 +10,8 @@ #include "qt/view/graphElements/QtGraphNodeData.h" QtGraphNodeExpandToggle::QtGraphNodeExpandToggle(bool expanded, int invisibleSubNodeCount) - : m_allVisible(invisibleSubNodeCount == 0) + : m_invisibleSubNodeCount(invisibleSubNodeCount) + , m_expanded(expanded) { if (!expanded && !invisibleSubNodeCount) { @@ -52,7 +53,7 @@ void QtGraphNodeExpandToggle::onClick() if (parent && parent->getTokenId()) { - MessageGraphNodeExpand(parent->getTokenId()).dispatch(); + MessageGraphNodeExpand(parent->getTokenId(), !m_expanded).dispatch(); } } @@ -68,6 +69,6 @@ void QtGraphNodeExpandToggle::updateStyle() m_icon->setPos( (m_rect->rect().width() - m_icon->pixmap().width() / QtDeviceScaledPixmap::devicePixelRatio()) / 2, - (m_allVisible ? 9 : 14) + (m_invisibleSubNodeCount == 0 ? 9 : 14) ); } diff --git a/src/app/qt/view/graphElements/QtGraphNodeExpandToggle.h b/src/app/qt/view/graphElements/QtGraphNodeExpandToggle.h index ea54e1fe..398ff7f5 100644 --- a/src/app/qt/view/graphElements/QtGraphNodeExpandToggle.h +++ b/src/app/qt/view/graphElements/QtGraphNodeExpandToggle.h @@ -20,7 +20,8 @@ public: private: QGraphicsPixmapItem* m_icon; - bool m_allVisible; + bool m_invisibleSubNodeCount; + bool m_expanded; }; #endif // QT_EXPAND_TOGGLE_H diff --git a/src/lib/component/controller/CodeController.cpp b/src/lib/component/controller/CodeController.cpp index 53ae1fa4..76771aa9 100644 --- a/src/lib/component/controller/CodeController.cpp +++ b/src/lib/component/controller/CodeController.cpp @@ -25,6 +25,11 @@ const uint CodeController::s_lineRadius = 2; void CodeController::handleMessage(MessageActivateTokens* message) { + if (message->isIgnorable()) + { + return; + } + std::vector activeTokenIds = message->tokenIds; Id declarationId = 0; // 0 means that no token is found. diff --git a/src/lib/component/controller/FeatureController.cpp b/src/lib/component/controller/FeatureController.cpp index d59a8c73..6b4c3a39 100644 --- a/src/lib/component/controller/FeatureController.cpp +++ b/src/lib/component/controller/FeatureController.cpp @@ -29,18 +29,23 @@ void FeatureController::handleMessage(MessageActivateEdge* message) if (message->type == Edge::EDGE_AGGREGATION) { - MessageActivateTokens(m_storageAccess->getTokenIdsForAggregationEdge(edgeId)).dispatch(); + MessageActivateTokens m(m_storageAccess->getTokenIdsForAggregationEdge(edgeId)); + m.undoRedoType = message->undoRedoType; + m.dispatch(); return; } MessageActivateTokens msg(std::vector(1, edgeId)); msg.isEdge = true; - msg.dispatch(); + msg.undoRedoType = message->undoRedoType; + msg.dispatchImmediately(); } void FeatureController::handleMessage(MessageActivateFile* message) { - MessageActivateTokens(std::vector(1, m_storageAccess->getTokenIdForFileNode(message->filePath))).dispatch(); + MessageActivateTokens m(std::vector(1, m_storageAccess->getTokenIdForFileNode(message->filePath))); + m.undoRedoType = message->undoRedoType; + m.dispatchImmediately(); } void FeatureController::handleMessage(MessageActivateNode* message) @@ -54,9 +59,10 @@ void FeatureController::handleMessage(MessageActivateNode* message) if (nodeId) { - MessageActivateTokens msg(nodeId); - msg.isFromSystem = message->isFromSystem; - msg.dispatch(); + MessageActivateTokens m(nodeId); + m.isFromSystem = message->isFromSystem; + m.undoRedoType = message->undoRedoType; + m.dispatchImmediately(); } } @@ -69,11 +75,13 @@ void FeatureController::handleMessage(MessageActivateTokenLocation* message) nodeId, m_storageAccess->getNodeTypeForNodeWithId(nodeId), m_storageAccess->getNameForNodeWithId(nodeId) - ).dispatch(); + ).dispatchImmediately(); } } void FeatureController::handleMessage(MessageSearch* message) { - MessageActivateTokens(m_storageAccess->getTokenIdsForQuery(message->getQuery())).dispatch(); + MessageActivateTokens m(m_storageAccess->getTokenIdsForQuery(message->getQuery())); + m.undoRedoType = message->undoRedoType; + m.dispatchImmediately(); } diff --git a/src/lib/component/controller/GraphController.cpp b/src/lib/component/controller/GraphController.cpp index 1702130d..09416e20 100644 --- a/src/lib/component/controller/GraphController.cpp +++ b/src/lib/component/controller/GraphController.cpp @@ -15,6 +15,8 @@ GraphController::GraphController(StorageAccess* storageAccess) : m_storageAccess(storageAccess) + , m_rebuild(true) + , m_restore(false) { } @@ -24,12 +26,14 @@ GraphController::~GraphController() void GraphController::handleMessage(MessageActivateTokens* message) { + setRebuildState(message); + m_activeTokenIds = message->tokenIds; if (message->isEdge && message->tokenIds.size() == 1) { setActiveAndVisibility(message->tokenIds); - getView()->rebuildGraph(nullptr, m_dummyNodes, m_dummyEdges); + rebuildGraph(); return; } @@ -53,6 +57,8 @@ void GraphController::handleMessage(MessageFocusOut *message) void GraphController::handleMessage(MessageGraphNodeBundleSplit* message) { + setRebuildState(message); + for (size_t i = 0; i < m_dummyNodes.size(); i++) { DummyNode& node = m_dummyNodes[i]; @@ -80,40 +86,44 @@ void GraphController::handleMessage(MessageGraphNodeBundleSplit* message) GraphLayouter::layoutSpectralPrototype(m_dummyNodes, m_dummyEdges); GraphPostprocessor::doPostprocessing(m_dummyNodes); - getView()->rebuildGraph(nullptr, m_dummyNodes, m_dummyEdges); + rebuildGraph(); } void GraphController::handleMessage(MessageGraphNodeExpand* message) { + setRebuildState(message); + DummyNode* node = findDummyNodeRecursive(m_dummyNodes, message->tokenId); if (node) { - if (node->autoExpanded) - { - node->autoExpanded = false; - node->expanded = false; - } - else - { - node->expanded = !node->expanded; - } + node->expanded = message->expand; setActiveAndVisibility(m_activeTokenIds); layoutNesting(); GraphPostprocessor::doPostprocessing(m_dummyNodes); - getView()->rebuildGraph(nullptr, m_dummyNodes, m_dummyEdges); + rebuildGraph(); } } void GraphController::handleMessage(MessageGraphNodeMove* message) { + setRebuildState(message); + DummyNode* node = findDummyNodeRecursive(m_dummyNodes, message->tokenId); if (node) { node->position += message->delta; - getView()->resizeView(); + + if (message->isFresh()) + { + getView()->resizeView(); + } + else + { + rebuildGraph(); + } } } @@ -164,7 +174,8 @@ void GraphController::createDummyGraphForTokenIds(const std::vector& tokenId GraphLayouter::layoutSpectralPrototype(m_dummyNodes, m_dummyEdges); GraphPostprocessor::doPostprocessing(m_dummyNodes); - view->rebuildGraph(graph, m_dummyNodes, m_dummyEdges); + m_graph = graph; + rebuildGraph(); } DummyNode GraphController::createDummyNodeTopDown(Node* node) @@ -186,7 +197,7 @@ DummyNode GraphController::createDummyNodeTopDown(Node* node) } DummyNode* oldNode = findDummyNodeRecursive(m_dummyNodes, node->getId()); - if (oldNode) + if (oldNode && !m_restore) { result.expanded = oldNode->isExpanded(); } @@ -269,7 +280,7 @@ void GraphController::autoExpandActiveNode(const std::vector& activeTokenIds if (node && node->data->isType(Node::NODE_CLASS | Node::NODE_STRUCT)) { - node->autoExpanded = true; + node->expanded = true; } } @@ -762,7 +773,6 @@ void GraphController::addExpandToggleNode(DummyNode& node) const DummyNode expandNode; expandNode.visible = true; expandNode.expanded = node.expanded; - expandNode.autoExpanded = node.autoExpanded; for (size_t i = 0; i < node.subNodes.size(); i++) { @@ -871,3 +881,31 @@ DummyNode* GraphController::findDummyNodeAccessRecursive( } return nullptr; } + +void GraphController::setRebuildState(MessageBase* message) +{ + m_restore = false; + + switch (message->undoRedoType) + { + case MessageBase::UNDOTYPE_UNDO: + m_restore = true; + case MessageBase::UNDOTYPE_NORMAL: + case MessageBase::UNDOTYPE_REDO: + m_rebuild = true; + break; + case MessageBase::UNDOTYPE_IGNORE: + m_restore = true; + m_rebuild = false; + break; + } +} + +void GraphController::rebuildGraph() +{ + if (m_rebuild) + { + getView()->rebuildGraph(m_graph, m_dummyNodes, m_dummyEdges); + m_graph.reset(); + } +} diff --git a/src/lib/component/controller/GraphController.h b/src/lib/component/controller/GraphController.h index c3278625..32572e63 100644 --- a/src/lib/component/controller/GraphController.h +++ b/src/lib/component/controller/GraphController.h @@ -72,12 +72,19 @@ private: DummyNode* findDummyNodeRecursive(std::vector& nodes, Id tokenId) const; DummyNode* findDummyNodeAccessRecursive(std::vector& nodes, Id parentId, TokenComponentAccess::AccessType type) const; + void setRebuildState(MessageBase* message); + void rebuildGraph(); + StorageAccess* m_storageAccess; std::vector m_dummyNodes; std::vector m_dummyEdges; std::vector m_activeTokenIds; + + std::shared_ptr m_graph; + bool m_rebuild; + bool m_restore; }; #endif // GRAPH_CONTROLLER_H diff --git a/src/lib/component/controller/SearchController.cpp b/src/lib/component/controller/SearchController.cpp index 0d63b77b..6a7fe259 100644 --- a/src/lib/component/controller/SearchController.cpp +++ b/src/lib/component/controller/SearchController.cpp @@ -14,6 +14,11 @@ SearchController::~SearchController() void SearchController::handleMessage(MessageActivateEdge* message) { + if (message->isIgnorable()) + { + return; + } + SearchMatch match; match.fullName = message->name; match.nodeType = Node::NODE_CLASS; @@ -25,6 +30,11 @@ void SearchController::handleMessage(MessageActivateEdge* message) void SearchController::handleMessage(MessageActivateFile* message) { + if (message->isIgnorable()) + { + return; + } + SearchMatch match; match.fullName = message->filePath.fileName(); match.nodeType = Node::NODE_FILE; @@ -36,6 +46,11 @@ void SearchController::handleMessage(MessageActivateFile* message) void SearchController::handleMessage(MessageActivateNode* message) { + if (message->isIgnorable()) + { + return; + } + SearchMatch match; match.fullName = message->name; match.nodeType = message->type; @@ -57,6 +72,11 @@ void SearchController::handleMessage(MessageFinishedParsing* message) void SearchController::handleMessage(MessageSearch* message) { + if (message->isIgnorable()) + { + return; + } + getView()->setMatches(message->getMatches()); } diff --git a/src/lib/component/controller/UndoRedoController.cpp b/src/lib/component/controller/UndoRedoController.cpp index fd6bb627..fd4a1215 100644 --- a/src/lib/component/controller/UndoRedoController.cpp +++ b/src/lib/component/controller/UndoRedoController.cpp @@ -5,7 +5,7 @@ #include "component/view/UndoRedoView.h" UndoRedoController::UndoRedoController() - : m_lastCommand(nullptr) + : m_lastCommand(nullptr, 0) { } @@ -18,45 +18,64 @@ UndoRedoView* UndoRedoController::getView() return Controller::getView(); } +UndoRedoController::Command::Command(std::shared_ptr message, size_t order) + : message(message) + , order(order) +{ +} + void UndoRedoController::handleMessage(MessageActivateEdge* message) { - if (m_lastCommand && m_lastCommand->getType() == message->getType() && - static_cast(m_lastCommand.get())->name == message->name) + if (m_lastCommand.message && m_lastCommand.message->getType() == message->getType() && + static_cast(m_lastCommand.message.get())->name == message->name) { return; } - processMessage(std::make_shared(*message)); + Command command(std::make_shared(*message), (message->type == Edge::EDGE_AGGREGATION ? 0 : 1)); + processCommand(command); } void UndoRedoController::handleMessage(MessageActivateFile* message) { - if (m_lastCommand && m_lastCommand->getType() == message->getType() && - static_cast(m_lastCommand.get())->filePath == message->filePath) + if (m_lastCommand.message && m_lastCommand.message->getType() == message->getType() && + static_cast(m_lastCommand.message.get())->filePath == message->filePath) { return; } - processMessage(std::make_shared(*message)); + Command command(std::make_shared(*message), 0); + processCommand(command); } void UndoRedoController::handleMessage(MessageActivateNode* message) { - if (m_lastCommand && m_lastCommand->getType() == message->getType() && - static_cast(m_lastCommand.get())->name == message->name) + if (m_lastCommand.message && m_lastCommand.message->getType() == message->getType() && + static_cast(m_lastCommand.message.get())->name == message->name) { return; } - processMessage(std::make_shared(*message)); + Command command(std::make_shared(*message), 0); + processCommand(command); +} + +void UndoRedoController::handleMessage(MessageGraphNodeBundleSplit* message) +{ + Command command(std::make_shared(*message), 1); + processCommand(command); } void UndoRedoController::handleMessage(MessageGraphNodeExpand* message) { + Command command(std::make_shared(*message), 1); + processCommand(command); } void UndoRedoController::handleMessage(MessageGraphNodeMove* message) { + Command command(std::make_shared(*message), 1); + processCommand(command); } void UndoRedoController::handleMessage(MessageLoadProject* message) @@ -73,69 +92,87 @@ void UndoRedoController::handleMessage(MessageRedo* message) { if (!m_redo.empty()) { - std::shared_ptr m = m_redo.back(); + std::shared_ptr m = m_redo.back().message; m_redo.pop_back(); - m->undoRedoType = MessageBase::UndoType_Redo; + m->undoRedoType = MessageBase::UNDOTYPE_REDO; m->dispatch(); } } void UndoRedoController::handleMessage(MessageSearch* message) { - if (m_lastCommand && m_lastCommand->getType() == message->getType() && - static_cast(m_lastCommand.get())->getQuery() == message->getQuery()) + if (m_lastCommand.message && m_lastCommand.message->getType() == message->getType() && + static_cast(m_lastCommand.message.get())->getQuery() == message->getQuery()) { return; } - processMessage(std::make_shared(*message)); + Command command(std::make_shared(*message), 0); + processCommand(command); } void UndoRedoController::handleMessage(MessageUndo* message) { if (!m_undo.empty()) { - std::shared_ptr m = m_undo.back(); + int i = m_undo.size() - 1; + while (i >= 1 && m_undo[i].order > 0) + { + i--; + } + + std::shared_ptr m; + while (i < int(m_undo.size() - 1)) + { + m = m_undo[i].message; + m->undoRedoType = MessageBase::UNDOTYPE_IGNORE; + m->dispatch(); + i++; + } + + m = m_undo.back().message; m_undo.pop_back(); - m->undoRedoType = MessageBase::UndoType_Undo; + m->undoRedoType = MessageBase::UNDOTYPE_UNDO; m->dispatch(); } } -void UndoRedoController::processMessage(std::shared_ptr message) +void UndoRedoController::processCommand(const Command& command) { - switch (message->undoRedoType) + switch (command.message->undoRedoType) { - case MessageBase::UndoType_Normal: - processNormalMessage(message);; + case MessageBase::UNDOTYPE_NORMAL: + processNormalCommand(command); break; - case MessageBase::UndoType_Redo: - processRedoMessage(message); + case MessageBase::UNDOTYPE_REDO: + processRedoCommand(command); break; - case MessageBase::UndoType_Undo: - processUndoMessage(message); + case MessageBase::UNDOTYPE_UNDO: + processUndoCommand(command); + break; + case MessageBase::UNDOTYPE_IGNORE: break; } } -void UndoRedoController::processNormalMessage(std::shared_ptr message) +void UndoRedoController::processNormalCommand(const Command& command) { - if (m_lastCommand) + if (m_lastCommand.message) { m_undo.push_back(m_lastCommand); getView()->setUndoButtonEnabled(true); } - m_lastCommand = message; + m_lastCommand = command; m_redo.clear(); getView()->setRedoButtonEnabled(false); } -void UndoRedoController::processRedoMessage(std::shared_ptr message) +void UndoRedoController::processRedoCommand(const Command& command) { m_undo.push_back(m_lastCommand); - m_lastCommand = message; + m_lastCommand = command; getView()->setUndoButtonEnabled(true); @@ -145,10 +182,10 @@ void UndoRedoController::processRedoMessage(std::shared_ptr message } } -void UndoRedoController::processUndoMessage(std::shared_ptr message) +void UndoRedoController::processUndoCommand(const Command& command) { m_redo.push_back(m_lastCommand); - m_lastCommand = message; + m_lastCommand = command; getView()->setRedoButtonEnabled(true); @@ -160,7 +197,7 @@ void UndoRedoController::processUndoMessage(std::shared_ptr message void UndoRedoController::clear() { - m_lastCommand = nullptr; + m_lastCommand = Command(nullptr, 0); m_undo.clear(); m_redo.clear(); diff --git a/src/lib/component/controller/UndoRedoController.h b/src/lib/component/controller/UndoRedoController.h index 66f9b645..ad48847e 100644 --- a/src/lib/component/controller/UndoRedoController.h +++ b/src/lib/component/controller/UndoRedoController.h @@ -8,6 +8,7 @@ #include "utility/messaging/type/MessageActivateEdge.h" #include "utility/messaging/type/MessageActivateFile.h" #include "utility/messaging/type/MessageActivateNode.h" +#include "utility/messaging/type/MessageGraphNodeBundleSplit.h" #include "utility/messaging/type/MessageGraphNodeExpand.h" #include "utility/messaging/type/MessageGraphNodeMove.h" #include "utility/messaging/type/MessageLoadProject.h" @@ -25,6 +26,7 @@ class UndoRedoController , public MessageListener , public MessageListener , public MessageListener + , public MessageListener , public MessageListener , public MessageListener , public MessageListener @@ -40,9 +42,18 @@ public: UndoRedoView* getView(); private: + struct Command + { + Command(std::shared_ptr message, size_t order); + + std::shared_ptr message; + size_t order; + }; + virtual void handleMessage(MessageActivateEdge* message); virtual void handleMessage(MessageActivateFile* message); virtual void handleMessage(MessageActivateNode* message); + virtual void handleMessage(MessageGraphNodeBundleSplit* message); virtual void handleMessage(MessageGraphNodeExpand* message); virtual void handleMessage(MessageGraphNodeMove* message); virtual void handleMessage(MessageLoadProject* message); @@ -51,17 +62,17 @@ private: virtual void handleMessage(MessageSearch* message); virtual void handleMessage(MessageUndo* message); - void processMessage(std::shared_ptr message); - void processNormalMessage(std::shared_ptr message); - void processRedoMessage(std::shared_ptr message); - void processUndoMessage(std::shared_ptr message); + void processCommand(const Command& command); + void processNormalCommand(const Command& command); + void processRedoCommand(const Command& command); + void processUndoCommand(const Command& command); void clear(); - std::shared_ptr m_lastCommand; + Command m_lastCommand; - std::deque> m_undo; - std::deque> m_redo; + std::deque m_undo; + std::deque m_redo; }; #endif // UNDO_REDO_CONTROLLER_H diff --git a/src/lib/component/controller/helper/DummyNode.h b/src/lib/component/controller/helper/DummyNode.h index b5a9cd01..fd64b845 100644 --- a/src/lib/component/controller/helper/DummyNode.h +++ b/src/lib/component/controller/helper/DummyNode.h @@ -22,7 +22,6 @@ public: , connected(false) , aggregated(false) , expanded(false) - , autoExpanded(false) , accessType(TokenComponentAccess::ACCESS_NONE) , invisibleSubNodeCount(0) { @@ -50,7 +49,7 @@ public: bool isExpanded() const { - return expanded || autoExpanded; + return expanded; } bool hasVisibleSubNode() const @@ -119,7 +118,6 @@ public: bool connected; bool aggregated; bool expanded; - bool autoExpanded; // AccessNode TokenComponentAccess::AccessType accessType; diff --git a/src/lib/utility/messaging/Message.h b/src/lib/utility/messaging/Message.h index 86cef81a..09147907 100644 --- a/src/lib/utility/messaging/Message.h +++ b/src/lib/utility/messaging/Message.h @@ -26,6 +26,12 @@ public: std::shared_ptr message = std::make_shared(*dynamic_cast(this)); MessageQueue::getInstance()->pushMessage(message); } + + virtual void dispatchImmediately() + { + std::shared_ptr message = std::make_shared(*dynamic_cast(this)); + MessageQueue::getInstance()->processMessage(message, true); + } }; #endif // MESSAGE_H diff --git a/src/lib/utility/messaging/MessageBase.h b/src/lib/utility/messaging/MessageBase.h index bf40c5d7..fba7824d 100644 --- a/src/lib/utility/messaging/MessageBase.h +++ b/src/lib/utility/messaging/MessageBase.h @@ -8,13 +8,14 @@ class MessageBase public: enum UndoType { - UndoType_Normal, - UndoType_Redo, - UndoType_Undo + UNDOTYPE_NORMAL, + UNDOTYPE_REDO, + UNDOTYPE_UNDO, + UNDOTYPE_IGNORE }; MessageBase() - : undoRedoType(UndoType_Normal) + : undoRedoType(UNDOTYPE_NORMAL) , m_sendAsTask(true) { } @@ -38,7 +39,12 @@ public: bool isFresh() const { - return (undoRedoType == UndoType_Normal); + return (undoRedoType == UNDOTYPE_NORMAL); + } + + bool isIgnorable() const + { + return (undoRedoType == UNDOTYPE_IGNORE); } UndoType undoRedoType; diff --git a/src/lib/utility/messaging/MessageQueue.cpp b/src/lib/utility/messaging/MessageQueue.cpp index 8922df5c..913c02d2 100644 --- a/src/lib/utility/messaging/MessageQueue.cpp +++ b/src/lib/utility/messaging/MessageQueue.cpp @@ -59,6 +59,18 @@ void MessageQueue::pushMessage(std::shared_ptr message) m_backMessageBuffer->push(message); } +void MessageQueue::processMessage(std::shared_ptr message, bool asNextTask) +{ + if (m_sendMessagesAsTasks && message->sendAsTask()) + { + sendMessageAsTask(message, asNextTask); + } + else + { + sendMessage(message); + } +} + void MessageQueue::startMessageLoopThreaded() { std::thread(&MessageQueue::startMessageLoop, this).detach(); @@ -189,14 +201,7 @@ void MessageQueue::processMessages() m_frontMessageBuffer->pop(); } - if (m_sendMessagesAsTasks && message->sendAsTask()) - { - sendMessageAsTask(message); - } - else - { - sendMessage(message); - } + processMessage(message, false); } } @@ -224,7 +229,7 @@ void MessageQueue::sendMessage(std::shared_ptr message) } } -void MessageQueue::sendMessageAsTask(std::shared_ptr message) const +void MessageQueue::sendMessageAsTask(std::shared_ptr message, bool asNextTask) const { std::shared_ptr taskGroup = std::make_shared(); @@ -244,5 +249,12 @@ void MessageQueue::sendMessageAsTask(std::shared_ptr message) const } } - Task::dispatch(taskGroup); + if (asNextTask) + { + Task::dispatchNext(taskGroup); + } + else + { + Task::dispatch(taskGroup); + } } diff --git a/src/lib/utility/messaging/MessageQueue.h b/src/lib/utility/messaging/MessageQueue.h index 7232d809..f66e428c 100644 --- a/src/lib/utility/messaging/MessageQueue.h +++ b/src/lib/utility/messaging/MessageQueue.h @@ -17,6 +17,7 @@ public: void unregisterListener(MessageListenerBase* listener); void pushMessage(std::shared_ptr message); + void processMessage(std::shared_ptr message, bool asNextTask); void startMessageLoopThreaded(); void startMessageLoop(); @@ -38,7 +39,7 @@ private: void processMessages(); void sendMessage(std::shared_ptr message); - void sendMessageAsTask(std::shared_ptr message) const; + void sendMessageAsTask(std::shared_ptr message, bool asNextTask) const; std::shared_ptr m_frontMessageBuffer; std::shared_ptr m_backMessageBuffer; diff --git a/src/lib/utility/messaging/type/MessageGraphNodeExpand.h b/src/lib/utility/messaging/type/MessageGraphNodeExpand.h index 52b0c423..104644aa 100644 --- a/src/lib/utility/messaging/type/MessageGraphNodeExpand.h +++ b/src/lib/utility/messaging/type/MessageGraphNodeExpand.h @@ -8,8 +8,9 @@ class MessageGraphNodeExpand : public Message { public: - MessageGraphNodeExpand(Id tokenId) + MessageGraphNodeExpand(Id tokenId, bool expand) : tokenId(tokenId) + , expand(expand) { } @@ -19,6 +20,7 @@ public: } const Id tokenId; + const bool expand; }; #endif // MESSAGE_GRAPH_NODE_EXPAND_H diff --git a/src/lib/utility/scheduling/Task.cpp b/src/lib/utility/scheduling/Task.cpp index 37c6230c..87dfa9ea 100644 --- a/src/lib/utility/scheduling/Task.cpp +++ b/src/lib/utility/scheduling/Task.cpp @@ -8,6 +8,11 @@ void Task::dispatch(std::shared_ptr task) TaskScheduler::getInstance()->pushTask(task); } +void Task::dispatchNext(std::shared_ptr task) +{ + TaskScheduler::getInstance()->pushNextTask(task); +} + Task::Task() : m_state(STATE_NEW) { diff --git a/src/lib/utility/scheduling/Task.h b/src/lib/utility/scheduling/Task.h index 1fca06ae..e86407bc 100644 --- a/src/lib/utility/scheduling/Task.h +++ b/src/lib/utility/scheduling/Task.h @@ -15,6 +15,7 @@ public: }; static void dispatch(std::shared_ptr task); + static void dispatchNext(std::shared_ptr task); Task(); virtual ~Task(); diff --git a/src/lib/utility/scheduling/TaskScheduler.cpp b/src/lib/utility/scheduling/TaskScheduler.cpp index c7d65c74..21872a92 100644 --- a/src/lib/utility/scheduling/TaskScheduler.cpp +++ b/src/lib/utility/scheduling/TaskScheduler.cpp @@ -19,7 +19,13 @@ std::shared_ptr TaskScheduler::getInstance() void TaskScheduler::pushTask(std::shared_ptr task) { std::lock_guard lock(m_tasksMutex); - m_tasks.push(task); + m_tasks.push_back(task); +} + +void TaskScheduler::pushNextTask(std::shared_ptr task) +{ + std::lock_guard lock(m_tasksMutex); + m_tasks.push_front(task); } void TaskScheduler::interruptCurrentTask() @@ -136,14 +142,15 @@ void TaskScheduler::updateTasks() while (m_tasks.size()) { std::shared_ptr task = m_tasks.front(); + m_tasks.pop_front(); m_tasksMutex.unlock(); Task::TaskState state = task->process(interrupt); m_tasksMutex.lock(); - if (state == Task::STATE_FINISHED || state == Task::STATE_CANCELED) + if (state != Task::STATE_FINISHED && state != Task::STATE_CANCELED) { - m_tasks.pop(); + m_tasks.push_front(task); } interrupt = m_interruptTask; diff --git a/src/lib/utility/scheduling/TaskScheduler.h b/src/lib/utility/scheduling/TaskScheduler.h index c42e4009..ce168fa6 100644 --- a/src/lib/utility/scheduling/TaskScheduler.h +++ b/src/lib/utility/scheduling/TaskScheduler.h @@ -3,7 +3,7 @@ #include #include -#include +#include #include "utility/messaging/MessageListener.h" #include "utility/messaging/type/MessageInterruptTasks.h" @@ -16,6 +16,7 @@ public: static std::shared_ptr getInstance(); void pushTask(std::shared_ptr task); + void pushNextTask(std::shared_ptr task); void interruptCurrentTask(); void startSchedulerLoopThreaded(); @@ -39,7 +40,7 @@ private: bool m_loopIsRunning; bool m_threadIsRunning; - std::queue> m_tasks; + std::deque> m_tasks; bool m_interruptTask; mutable std::mutex m_tasksMutex;