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 183 : void CommandHistory::execute(std::unique_ptr<Command> cmd) {
7 183 : if (!cmd->execute()) return; // no-op — skip history recording
8 :
9 : // Try coalescing with the top of the undo stack
10 168 : if (!undo_stack_.empty() && undo_stack_.back()->merge_with(*cmd)) {
11 : // Merged into existing top — no new entry needed
12 0 : } else {
13 168 : undo_stack_.push_back(std::move(cmd));
14 168 : trim();
15 : }
16 :
17 : // New action invalidates the redo branch
18 168 : redo_stack_.clear();
19 61 : }
20 :
21 : /** @brief Push an already-applied command; attempt coalescing, clear redo. */
22 45 : void CommandHistory::push_executed(std::unique_ptr<Command> cmd) {
23 45 : if (!undo_stack_.empty() && undo_stack_.back()->merge_with(*cmd)) {
24 : // Merged into existing top — no new entry needed
25 2 : } else {
26 39 : undo_stack_.push_back(std::move(cmd));
27 39 : trim();
28 : }
29 :
30 : // New action invalidates the redo branch
31 45 : redo_stack_.clear();
32 45 : }
33 :
34 : /** @brief Pop the top undo command, call its undo(), and move it to redo. */
35 87 : bool CommandHistory::undo() {
36 87 : if (undo_stack_.empty()) return false;
37 :
38 84 : auto cmd = std::move(undo_stack_.back());
39 84 : undo_stack_.pop_back();
40 :
41 84 : cmd->undo();
42 84 : redo_stack_.push_back(std::move(cmd));
43 84 : return true;
44 85 : }
45 :
46 : /** @brief Pop the top redo command, call its execute(), and move it to undo. */
47 48 : bool CommandHistory::redo() {
48 48 : if (redo_stack_.empty()) return false;
49 :
50 45 : auto cmd = std::move(redo_stack_.back());
51 45 : redo_stack_.pop_back();
52 :
53 45 : cmd->execute();
54 45 : undo_stack_.push_back(std::move(cmd));
55 45 : return true;
56 46 : }
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 207 : void CommandHistory::trim() {
78 222 : while (static_cast<int>(undo_stack_.size()) > max_depth_) {
79 15 : undo_stack_.erase(undo_stack_.begin());
80 : }
81 207 : }
82 :
83 : } // namespace Amplitron
|