Line data Source code
1 : #include "gui/commands/command_history.h"
2 :
3 : namespace Amplitron {
4 :
5 : /** @brief Execute cmd, attempt coalescing, push to undo stack, clear redo. */
6 225 : void CommandHistory::execute(std::unique_ptr<Command> cmd) {
7 225 : if (!cmd->execute()) return; // no-op — skip history recording
8 :
9 : // Try coalescing with the top of the undo stack
10 210 : if (!undo_stack_.empty() && undo_stack_.back()->merge_with(*cmd)) {
11 : // Merged into existing top — no new entry needed
12 0 : } else {
13 210 : undo_stack_.push_back(std::move(cmd));
14 210 : trim();
15 : }
16 :
17 : // New action invalidates the redo branch
18 210 : redo_stack_.clear();
19 75 : }
20 :
21 : /** @brief Push an already-applied command; attempt coalescing, clear redo. */
22 54 : void CommandHistory::push_executed(std::unique_ptr<Command> cmd) {
23 54 : if (!undo_stack_.empty() && undo_stack_.back()->merge_with(*cmd)) {
24 : // Merged into existing top — no new entry needed
25 3 : } else {
26 45 : undo_stack_.push_back(std::move(cmd));
27 45 : trim();
28 : }
29 :
30 : // New action invalidates the redo branch
31 54 : redo_stack_.clear();
32 54 : }
33 :
34 : /** @brief Pop the top undo command, call its undo(), and move it to redo. */
35 99 : bool CommandHistory::undo() {
36 99 : if (undo_stack_.empty()) return false;
37 :
38 96 : auto cmd = std::move(undo_stack_.back());
39 96 : undo_stack_.pop_back();
40 :
41 96 : cmd->undo();
42 96 : redo_stack_.push_back(std::move(cmd));
43 96 : return true;
44 97 : }
45 :
46 : /** @brief Pop the top redo command, call its execute(), and move it to undo. */
47 51 : bool CommandHistory::redo() {
48 51 : if (redo_stack_.empty()) return false;
49 :
50 48 : auto cmd = std::move(redo_stack_.back());
51 48 : redo_stack_.pop_back();
52 :
53 48 : cmd->execute();
54 48 : undo_stack_.push_back(std::move(cmd));
55 48 : return true;
56 49 : }
57 :
58 : /** @brief Discard all undo and redo history. */
59 27 : void CommandHistory::clear() {
60 27 : undo_stack_.clear();
61 27 : redo_stack_.clear();
62 27 : }
63 :
64 : /** @brief Return the description of the top undo command, or nullptr. */
65 9 : const char* CommandHistory::undo_description() const {
66 9 : if (undo_stack_.empty()) return nullptr;
67 6 : return undo_stack_.back()->description();
68 3 : }
69 :
70 : /** @brief Return the description of the top redo command, or nullptr. */
71 9 : const char* CommandHistory::redo_description() const {
72 9 : if (redo_stack_.empty()) return nullptr;
73 6 : return redo_stack_.back()->description();
74 3 : }
75 :
76 : /** @brief Remove oldest undo entries until stack size <= max_depth_. */
77 261 : void CommandHistory::trim() {
78 297 : while (static_cast<int>(undo_stack_.size()) > max_depth_) {
79 36 : undo_stack_.erase(undo_stack_.begin());
80 : }
81 261 : }
82 :
83 : } // namespace Amplitron
|