#include "component/controller/UndoRedoController.h" #include "utility/logging/logging.h" #include "utility/messaging/type/MessageActivateTokens.h" #include "utility/messaging/type/MessageFlushUpdates.h" #include "utility/utility.h" #include "component/view/UndoRedoView.h" #include "data/access/StorageAccess.h" UndoRedoController::UndoRedoController(StorageAccess* storageAccess) { m_iterator = m_list.end(); } UndoRedoController::~UndoRedoController() { } UndoRedoView* UndoRedoController::getView() { return Controller::getView(); } UndoRedoController::Command::Command(std::shared_ptr message, Order order, bool replayLastOnly) : message(message) , order(order) , replayLastOnly(replayLastOnly) { } void UndoRedoController::handleMessage(MessageActivateEdge* message) { if (sameMessageTypeAsLast(message) && static_cast(lastMessage())->getFullName() == message->getFullName()) { return; } Command command( std::make_shared(*message), (message->isAggregation() ? Command::ORDER_ACTIVATE : Command::ORDER_ADAPT) ); processCommand(command); } void UndoRedoController::handleMessage(MessageActivateFile* message) { if (sameMessageTypeAsLast(message) && static_cast(lastMessage())->filePath == message->filePath) { return; } Command command(std::make_shared(*message), Command::ORDER_ACTIVATE); processCommand(command); } void UndoRedoController::handleMessage(MessageActivateLocalSymbols* message) { if (sameMessageTypeAsLast(message)) { static_cast(lastMessage())->symbolIds = message->symbolIds; return; } Command command(std::make_shared(*message), Command::ORDER_VIEW, true); processCommand(command); } void UndoRedoController::handleMessage(MessageActivateNodes* message) { if (sameMessageTypeAsLast(message) && message->nodes.size() && static_cast(lastMessage())->nodes.size() == message->nodes.size() && static_cast(lastMessage())->nodes[0].nameHierarchy.getQualifiedNameWithSignature() == message->nodes[0].nameHierarchy.getQualifiedNameWithSignature()) { return; } Command command(std::make_shared(*message), Command::ORDER_ACTIVATE); processCommand(command); } void UndoRedoController::handleMessage(MessageActivateTokenIds* message) { if (sameMessageTypeAsLast(message) && message->tokenIds.size() && static_cast(lastMessage())->tokenIds == message->tokenIds) { return; } Command command(std::make_shared(*message), Command::ORDER_ACTIVATE); processCommand(command); } void UndoRedoController::handleMessage(MessageChangeFileView* message) { Command command(std::make_shared(*message), Command::ORDER_VIEW); processCommand(command); } void UndoRedoController::handleMessage(MessageDeactivateEdge* message) { if (m_iterator == m_list.begin()) { return; } std::list::iterator it = m_iterator; do { std::advance(it, -1); } while (it != m_list.begin() && it->order != Command::ORDER_ACTIVATE); MessageBase* m = it->message.get(); bool keepContent = m->keepContent(); m->setIsReplayed(false); m->setKeepContent(true); m->dispatch(); m->setKeepContent(keepContent); } void UndoRedoController::handleMessage(MessageGraphNodeBundleSplit* message) { Command command(std::make_shared(*message), Command::ORDER_ADAPT); processCommand(command); } void UndoRedoController::handleMessage(MessageGraphNodeExpand* message) { Command command(std::make_shared(*message), Command::ORDER_VIEW); processCommand(command); } void UndoRedoController::handleMessage(MessageGraphNodeMove* message) { Command command(std::make_shared(*message), Command::ORDER_VIEW); processCommand(command); } void UndoRedoController::handleMessage(MessageLoadProject* message) { clear(); } void UndoRedoController::handleMessage(MessageRedo* message) { if (m_iterator == m_list.end()) { return; } std::list::iterator oldIterator = m_iterator; std::advance(m_iterator, 1); while (m_iterator != m_list.end() && m_iterator->order == Command::ORDER_VIEW) { std::advance(m_iterator, 1); } getView()->setUndoButtonEnabled(true); if (m_iterator == m_list.end()) { getView()->setRedoButtonEnabled(false); } replayCommands(oldIterator); MessageFlushUpdates().dispatch(); } void UndoRedoController::handleMessage(MessageRefresh* message) { if (!message->uiOnly) { return; } if (m_iterator == m_list.begin()) { SearchMatch match = SearchMatch::createCommand(SearchMatch::COMMAND_ALL); MessageSearch msg(std::vector(1, match)); msg.dispatch(); } else { replayCommands(); MessageFlushUpdates().dispatch(); } } void UndoRedoController::handleMessage(MessageScrollCode* message) { if (sameMessageTypeAsLast(message)) { static_cast(lastMessage())->value = message->value; return; } Command command(std::make_shared(*message), Command::ORDER_VIEW, true); processCommand(command); } void UndoRedoController::handleMessage(MessageSearch* message) { if (sameMessageTypeAsLast(message) && static_cast(lastMessage())->getMatchesAsString() == message->getMatchesAsString()) { return; } Command command(std::make_shared(*message), Command::ORDER_ACTIVATE); processCommand(command); } void UndoRedoController::handleMessage(MessageSearchFullText* message) { if (sameMessageTypeAsLast(message))// && //static_cast(lastMessage())->getMatchesAsString() == message->getMatchesAsString()) { return; } Command command(std::make_shared(*message), Command::ORDER_ACTIVATE); processCommand(command); } void UndoRedoController::handleMessage(MessageShowScope* message) { Command command(std::make_shared(*message), Command::ORDER_VIEW); processCommand(command); } void UndoRedoController::handleMessage(MessageUndo* message) { if (!m_list.size() || std::prev(m_iterator) == m_list.begin()) { return; } while (std::prev(m_iterator)->order == Command::ORDER_VIEW) { std::advance(m_iterator, -1); } std::advance(m_iterator, -1); if (std::distance(m_list.begin(), m_iterator) <= 1) { getView()->setUndoButtonEnabled(false); } getView()->setRedoButtonEnabled(true); replayCommands(); MessageFlushUpdates().dispatch(); } void UndoRedoController::replayCommands() { std::list::iterator startIterator = m_iterator; do { std::advance(startIterator, -1); } while (startIterator != m_list.begin() && startIterator->order != Command::ORDER_ACTIVATE); replayCommands(startIterator); } void UndoRedoController::replayCommands(std::list::iterator it) { std::vector::iterator> viewCommands; std::shared_ptr m; while (it != m_iterator) { m = it->message; if (it->order != Command::ORDER_VIEW || it->replayLastOnly == false) { m->setIsReplayed(true); m->setIsLast(it == std::prev(m_iterator)); m->dispatch(); if (it->order != Command::ORDER_VIEW) { viewCommands.clear(); } } else { viewCommands.push_back(it); } std::advance(it, 1); } std::set messageTypes; std::vector::iterator> lastViewCommands; for (size_t i = viewCommands.size(); i > 0; i--) { it = viewCommands[i - 1]; if (messageTypes.find(it->message->getType()) == messageTypes.end()) { messageTypes.insert(it->message->getType()); lastViewCommands.push_back(it); } } for (size_t i = lastViewCommands.size(); i > 0; i--) { it = lastViewCommands[i - 1]; m = it->message; m->setIsReplayed(true); m->setIsLast(it == std::prev(m_iterator)); m->dispatch(); } } void UndoRedoController::processCommand(Command command) { if (command.order == Command::ORDER_ACTIVATE && command.message->keepContent()) { command.order = Command::ORDER_ADAPT; } if (!command.message->isReplayed()) { if (command.order == Command::ORDER_ACTIVATE) { m_iterator = m_list.erase(m_iterator, m_list.end()); } else if (command.order == Command::ORDER_ADAPT) { std::list::iterator end = m_iterator; while (end != m_list.end()) { if (end->order == Command::ORDER_ACTIVATE) { break; } std::advance(end, 1); } m_iterator = m_list.erase(m_iterator, end); } m_list.insert(m_iterator, command); if (command.order != Command::ORDER_VIEW) { if (m_list.begin() != std::prev(m_iterator)) { getView()->setUndoButtonEnabled(true); } if (m_list.end() == m_iterator) { getView()->setRedoButtonEnabled(false); } } } } void UndoRedoController::clear() { m_list.clear(); m_iterator = m_list.end(); getView()->setUndoButtonEnabled(false); getView()->setRedoButtonEnabled(false); } bool UndoRedoController::sameMessageTypeAsLast(MessageBase* message) const { if (!m_list.size() || m_list.begin() == m_iterator) { return false; } return std::prev(m_iterator)->message->getType() == message->getType(); } MessageBase* UndoRedoController::lastMessage() const { return std::prev(m_iterator)->message.get(); }