1use alloc::boxed::Box;
22use alloc::string::String;
23use alloc::vec::Vec;
24
25use super::Ui;
26use super::consts::*;
27
28pub trait Edit<S> {
30 fn apply(&mut self, s: &mut S);
32 fn revert(&mut self, s: &mut S);
34 fn label(&self) -> &str;
36 fn merge(&mut self, _next: &mut dyn Edit<S>) -> bool {
38 false
39 }
40 fn value(&self) -> Option<&dyn core::any::Any> {
42 None
43 }
44}
45
46pub struct Snapshot<T: Clone + 'static> {
48 label: String,
49 before: T,
50 after: T,
51 key: u32,
53}
54
55impl<T: Clone + 'static> Snapshot<T> {
56 pub fn new(label: &str, before: T, after: T) -> Self {
57 Snapshot { label: String::from(label), before, after, key: 0 }
58 }
59 pub fn merging(mut self, key: u32) -> Self {
61 self.key = key;
62 self
63 }
64}
65
66impl<T: Clone + 'static> Edit<T> for Snapshot<T> {
67 fn apply(&mut self, s: &mut T) {
68 *s = self.after.clone();
69 }
70 fn revert(&mut self, s: &mut T) {
71 *s = self.before.clone();
72 }
73 fn label(&self) -> &str {
74 &self.label
75 }
76 fn merge(&mut self, next: &mut dyn Edit<T>) -> bool {
77 if self.key == 0 {
78 return false;
79 }
80 match next.value().and_then(|v| v.downcast_ref::<Snapshot<T>>()) {
81 Some(n) if n.key == self.key => {
82 self.after = n.after.clone();
83 true
84 }
85 _ => false,
86 }
87 }
88 fn value(&self) -> Option<&dyn core::any::Any> {
89 Some(self)
90 }
91}
92
93struct Group<S> {
95 label: String,
96 edits: Vec<Box<dyn Edit<S>>>,
97}
98
99impl<S: 'static> Edit<S> for Group<S> {
100 fn apply(&mut self, s: &mut S) {
101 for e in self.edits.iter_mut() {
102 e.apply(s);
103 }
104 }
105 fn revert(&mut self, s: &mut S) {
106 for e in self.edits.iter_mut().rev() {
107 e.revert(s);
108 }
109 }
110 fn label(&self) -> &str {
111 &self.label
112 }
113}
114
115pub struct History<S> {
117 done: Vec<Box<dyn Edit<S>>>,
118 undone: Vec<Box<dyn Edit<S>>>,
119 limit: usize,
120 groups: Vec<(String, Vec<Box<dyn Edit<S>>>)>,
122 saved: Option<usize>,
124}
125
126impl<S: 'static> History<S> {
127 pub fn new(limit: usize) -> Self {
128 History { done: Vec::new(), undone: Vec::new(), limit: limit.max(1), groups: Vec::new(), saved: Some(0) }
129 }
130
131 pub fn apply(&mut self, s: &mut S, mut edit: Box<dyn Edit<S>>) {
133 edit.apply(s);
134 self.record(edit);
135 }
136
137 pub fn record(&mut self, mut edit: Box<dyn Edit<S>>) {
139 if let Some(g) = self.groups.last_mut() {
140 g.1.push(edit);
141 return;
142 }
143 self.undone.clear();
144 if self.saved.is_some_and(|k| k > self.done.len()) {
145 self.saved = None; }
147 let at_save = self.saved == Some(self.done.len());
149 if let Some(last) = self.done.last_mut() {
150 if !at_save && last.merge(edit.as_mut()) {
151 return;
152 }
153 }
154 self.done.push(edit);
155 if self.done.len() > self.limit {
156 self.done.remove(0);
157 self.saved = match self.saved {
158 Some(0) => None,
159 Some(k) => Some(k - 1),
160 None => None,
161 };
162 }
163 }
164
165 pub fn undo(&mut self, s: &mut S) -> bool {
167 let Some(mut e) = self.done.pop() else { return false };
168 e.revert(s);
169 self.undone.push(e);
170 true
171 }
172
173 pub fn redo(&mut self, s: &mut S) -> bool {
175 let Some(mut e) = self.undone.pop() else { return false };
176 e.apply(s);
177 self.done.push(e);
178 true
179 }
180
181 pub fn can_undo(&self) -> bool {
182 !self.done.is_empty()
183 }
184 pub fn can_redo(&self) -> bool {
185 !self.undone.is_empty()
186 }
187 pub fn undo_label(&self) -> Option<&str> {
189 self.done.last().map(|e| e.label())
190 }
191 pub fn redo_label(&self) -> Option<&str> {
193 self.undone.last().map(|e| e.label())
194 }
195 pub fn undo_value(&self) -> Option<&dyn core::any::Any> {
198 self.done.last().and_then(|e| e.value())
199 }
200 pub fn redo_value(&self) -> Option<&dyn core::any::Any> {
202 self.undone.last().and_then(|e| e.value())
203 }
204
205 pub fn group_begin(&mut self, label: &str) {
207 self.groups.push((String::from(label), Vec::new()));
208 }
209
210 pub fn group_end(&mut self) {
212 let Some((label, edits)) = self.groups.pop() else { return };
213 if !edits.is_empty() {
214 self.record(Box::new(Group { label, edits }));
215 }
216 }
217
218 pub fn mark_saved(&mut self) {
220 self.saved = Some(self.done.len());
221 }
222
223 pub fn mark_unsaved(&mut self) {
225 self.saved = None;
226 }
227
228 pub fn dirty(&self) -> bool {
230 self.saved != Some(self.done.len())
231 }
232
233 pub fn clear(&mut self) {
235 let dirty = self.dirty();
236 self.done.clear();
237 self.undone.clear();
238 self.groups.clear();
239 self.saved = if dirty { None } else { Some(0) };
240 }
241
242 pub fn len(&self) -> usize {
244 self.done.len()
245 }
246
247 pub fn is_empty(&self) -> bool {
248 self.done.is_empty()
249 }
250}
251
252impl Ui {
253 pub fn undo_keys(&mut self) -> Option<bool> {
256 if self.focus_is_text() || self.focus_was_text() {
258 return None;
259 }
260 let k = self.key_first();
261 let (vk, m) = (k & 0xFFFF, k >> 16);
262 if m & (MOD_CTRL | MOD_ALT) != MOD_CTRL {
263 return None;
264 }
265 let shift = m & MOD_SHIFT != 0;
266 let r = match vk {
267 0x5A if !shift => Some(true), 0x5A => Some(false), 0x59 if !shift => Some(false), _ => None,
271 };
272 if r.is_some() {
273 self.key(vk);
274 }
275 r
276 }
277}