UndoStack.cpp 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <LibGUI/Command.h>
  7. #include <LibGUI/UndoStack.h>
  8. namespace GUI {
  9. UndoStack::UndoStack()
  10. {
  11. }
  12. UndoStack::~UndoStack()
  13. {
  14. }
  15. void UndoStack::undo()
  16. {
  17. if (!can_undo())
  18. return;
  19. auto pop_container_and_undo = [this]() {
  20. for (;;) {
  21. if (m_stack_index >= m_stack.size())
  22. break;
  23. auto& container = m_stack[m_stack_index++];
  24. if (container.m_undo_vector.size() == 0)
  25. continue;
  26. for (auto& command : container.m_undo_vector)
  27. command.undo();
  28. break;
  29. }
  30. };
  31. // If this is the first undo, finish off our current combo
  32. if (m_stack_index == 0)
  33. finalize_current_combo();
  34. pop_container_and_undo();
  35. }
  36. void UndoStack::redo()
  37. {
  38. if (!can_redo())
  39. return;
  40. m_stack_index -= 1;
  41. auto& vector = m_stack[m_stack_index].m_undo_vector;
  42. for (int i = vector.size() - 1; i >= 0; i--)
  43. vector[i].redo();
  44. }
  45. void UndoStack::push(NonnullOwnPtr<Command>&& command)
  46. {
  47. if (m_stack.is_empty())
  48. finalize_current_combo();
  49. if (m_stack_index > 0) {
  50. for (size_t i = 0; i < m_stack_index; i++)
  51. m_stack.remove(0);
  52. m_stack_index = 0;
  53. finalize_current_combo();
  54. }
  55. auto& current_vector = m_stack.first().m_undo_vector;
  56. current_vector.prepend(move(command));
  57. }
  58. void UndoStack::finalize_current_combo()
  59. {
  60. if (m_stack_index > 0)
  61. return;
  62. if (m_stack.size() != 0 && m_stack.first().m_undo_vector.size() == 0)
  63. return;
  64. auto undo_commands_container = make<UndoCommandsContainer>();
  65. m_stack.prepend(move(undo_commands_container));
  66. }
  67. void UndoStack::clear()
  68. {
  69. m_stack.clear();
  70. m_stack_index = 0;
  71. }
  72. }