Skip to main content

rustapi/docks/
data_undo.rs

1use theframework::prelude::*;
2use theframework::theui::thewidget::thetextedit::TheTextEditState;
3
4/// Undo atoms for data editor operations
5#[derive(Clone)]
6pub enum DataUndoAtom {
7    /// Text edit: (before_state, after_state)
8    TextEdit(TheTextEditState, TheTextEditState),
9}
10
11impl DataUndoAtom {
12    pub fn undo(&self, edit: &mut dyn TheTextAreaEditTrait) {
13        match self {
14            DataUndoAtom::TextEdit(prev, _) => {
15                TheTextAreaEditTrait::set_state(edit, prev.clone());
16            }
17        }
18    }
19
20    pub fn redo(&self, edit: &mut dyn TheTextAreaEditTrait) {
21        match self {
22            DataUndoAtom::TextEdit(_, next) => {
23                TheTextAreaEditTrait::set_state(edit, next.clone());
24            }
25        }
26    }
27}
28
29/// Undo stack for data editor
30#[derive(Clone)]
31pub struct DataUndo {
32    pub stack: Vec<DataUndoAtom>,
33    pub index: isize,
34}
35
36impl Default for DataUndo {
37    fn default() -> Self {
38        Self::new()
39    }
40}
41
42impl DataUndo {
43    pub fn new() -> Self {
44        Self {
45            stack: vec![],
46            index: -1,
47        }
48    }
49
50    pub fn is_empty(&self) -> bool {
51        self.stack.is_empty()
52    }
53
54    pub fn clear(&mut self) {
55        self.stack = vec![];
56        self.index = -1;
57    }
58
59    pub fn has_undo(&self) -> bool {
60        self.index >= 0
61    }
62
63    pub fn has_redo(&self) -> bool {
64        self.index >= -1 && self.index < self.stack.len() as isize - 1
65    }
66
67    pub fn has_changes(&self) -> bool {
68        // Has changes if the index is not at the beginning (i.e., not fully undone)
69        self.index >= 0
70    }
71
72    pub fn add(&mut self, atom: DataUndoAtom) {
73        // Remove any redo history
74        let to_remove = self.stack.len() as isize - self.index - 1;
75        for _i in 0..to_remove {
76            self.stack.pop();
77        }
78        self.stack.push(atom);
79        self.index += 1;
80    }
81
82    pub fn undo(&mut self, edit: &mut dyn TheTextAreaEditTrait) {
83        if self.index >= 0 {
84            self.stack[self.index as usize].undo(edit);
85            self.index -= 1;
86        }
87    }
88
89    pub fn redo(&mut self, edit: &mut dyn TheTextAreaEditTrait) {
90        if self.index < self.stack.len() as isize - 1 {
91            self.index += 1;
92            self.stack[self.index as usize].redo(edit);
93        }
94    }
95
96    pub fn truncate_to_limit(&mut self, limit: usize) {
97        if self.stack.len() > limit {
98            let excess = self.stack.len() - limit;
99            self.stack.drain(0..excess);
100            self.index -= excess as isize;
101            if self.index < -1 {
102                self.index = -1;
103            }
104        }
105    }
106}