1use crate::SheetId;
8use crate::engine::DependencyGraph;
9use crate::engine::graph::editor::change_log::ChangeEvent;
10use crate::engine::graph::editor::vertex_editor::{EditorError, VertexEditor};
11use formualizer_common::LiteralValue;
12
13#[derive(Debug, Clone, PartialEq)]
14pub enum ArrowOp {
15 SetDeltaCell {
16 sheet_id: SheetId,
17 row0: u32,
18 col0: u32,
19 old: Option<LiteralValue>,
20 new: Option<LiteralValue>,
21 },
22 SetComputedCell {
23 sheet_id: SheetId,
24 row0: u32,
25 col0: u32,
26 old: Option<LiteralValue>,
27 new: Option<LiteralValue>,
28 },
29 RestoreComputedRect {
30 sheet_id: SheetId,
31 sr0: u32,
32 sc0: u32,
33 er0: u32,
34 ec0: u32,
35 old: Vec<Vec<LiteralValue>>,
36 new: Vec<Vec<LiteralValue>>,
37 },
38 InsertRows {
39 sheet_id: SheetId,
40 before0: u32,
41 count: u32,
42 },
43 InsertCols {
44 sheet_id: SheetId,
45 before0: u32,
46 count: u32,
47 },
48}
49
50#[derive(Debug, Clone, Default, PartialEq)]
51pub struct ArrowUndoBatch {
52 pub ops: Vec<ArrowOp>,
53}
54
55impl ArrowUndoBatch {
56 #[inline]
57 pub fn is_empty(&self) -> bool {
58 self.ops.is_empty()
59 }
60
61 #[inline]
62 pub fn record_delta_cell(
63 &mut self,
64 sheet_id: SheetId,
65 row0: u32,
66 col0: u32,
67 old: Option<LiteralValue>,
68 new: Option<LiteralValue>,
69 ) {
70 if old == new {
71 return;
72 }
73 self.ops.push(ArrowOp::SetDeltaCell {
74 sheet_id,
75 row0,
76 col0,
77 old,
78 new,
79 });
80 }
81
82 #[inline]
83 pub fn record_computed_cell(
84 &mut self,
85 sheet_id: SheetId,
86 row0: u32,
87 col0: u32,
88 old: Option<LiteralValue>,
89 new: Option<LiteralValue>,
90 ) {
91 if old == new {
92 return;
93 }
94 self.ops.push(ArrowOp::SetComputedCell {
95 sheet_id,
96 row0,
97 col0,
98 old,
99 new,
100 });
101 }
102
103 #[inline]
104 pub fn record_restore_computed_rect(
105 &mut self,
106 sheet_id: SheetId,
107 sr0: u32,
108 sc0: u32,
109 er0: u32,
110 ec0: u32,
111 old: Vec<Vec<LiteralValue>>,
112 new: Vec<Vec<LiteralValue>>,
113 ) {
114 if old == new {
115 return;
116 }
117 self.ops.push(ArrowOp::RestoreComputedRect {
118 sheet_id,
119 sr0,
120 sc0,
121 er0,
122 ec0,
123 old,
124 new,
125 });
126 }
127
128 #[inline]
129 pub fn record_insert_rows(&mut self, sheet_id: SheetId, before0: u32, count: u32) {
130 if count == 0 {
131 return;
132 }
133 self.ops.push(ArrowOp::InsertRows {
134 sheet_id,
135 before0,
136 count,
137 });
138 }
139
140 #[inline]
141 pub fn record_insert_cols(&mut self, sheet_id: SheetId, before0: u32, count: u32) {
142 if count == 0 {
143 return;
144 }
145 self.ops.push(ArrowOp::InsertCols {
146 sheet_id,
147 before0,
148 count,
149 });
150 }
151}
152
153#[derive(Debug, Clone, Default, PartialEq)]
154pub struct GraphUndoBatch {
155 pub events: Vec<ChangeEvent>,
156}
157
158impl GraphUndoBatch {
159 #[inline]
160 pub fn is_empty(&self) -> bool {
161 self.events.is_empty()
162 }
163
164 pub fn undo(&self, graph: &mut DependencyGraph) -> Result<(), EditorError> {
165 let mut editor = VertexEditor::new(graph);
166 let mut compound_stack: Vec<usize> = Vec::new();
167 for ev in self.events.iter().rev() {
168 match ev {
169 ChangeEvent::CompoundEnd { depth } => compound_stack.push(*depth),
170 ChangeEvent::CompoundStart { depth, .. } => {
171 if compound_stack.last() == Some(depth) {
172 compound_stack.pop();
173 }
174 }
175 _ => {
176 editor.apply_inverse(ev.clone())?;
177 }
178 }
179 }
180 Ok(())
181 }
182
183 pub fn redo(&self, graph: &mut DependencyGraph) -> Result<(), EditorError> {
184 for ev in &self.events {
185 apply_forward_change_event(graph, ev)?;
186 }
187 Ok(())
188 }
189}
190
191fn apply_forward_change_event(
192 graph: &mut DependencyGraph,
193 ev: &ChangeEvent,
194) -> Result<(), EditorError> {
195 use crate::engine::graph::editor::vertex_editor::VertexMeta;
196 match ev {
197 ChangeEvent::SetValue { addr, new, .. } => {
198 let mut editor = VertexEditor::new(graph);
199 editor.set_cell_value(*addr, new.clone());
200 }
201 ChangeEvent::SetFormula { addr, new, .. } => {
202 let mut editor = VertexEditor::new(graph);
203 editor.set_cell_formula(*addr, new.clone());
204 }
205 ChangeEvent::AddVertex {
206 coord,
207 sheet_id,
208 kind,
209 ..
210 } => {
211 let mut editor = VertexEditor::new(graph);
212 let meta = VertexMeta::new(
213 coord.row(),
214 coord.col(),
215 *sheet_id,
216 kind.unwrap_or(crate::engine::vertex::VertexKind::Cell),
217 );
218 editor.add_vertex(meta);
219 }
220 ChangeEvent::RemoveVertex {
221 coord, sheet_id, ..
222 } => {
223 if let (Some(c), Some(sid)) = (coord, sheet_id) {
224 let mut editor = VertexEditor::new(graph);
225 let cell_ref = crate::reference::CellRef::new(
226 *sid,
227 crate::reference::Coord::new(c.row(), c.col(), true, true),
228 );
229 let _ = editor.remove_vertex_at(cell_ref);
230 }
231 }
232 ChangeEvent::VertexMoved { id, new_coord, .. } => {
233 let mut editor = VertexEditor::new(graph);
234 let _ = editor.move_vertex(*id, *new_coord);
235 }
236 ChangeEvent::FormulaAdjusted { id, new_ast, .. } => {
237 let _ = graph.update_vertex_formula(*id, new_ast.clone());
238 graph.mark_vertex_dirty(*id);
239 }
240 ChangeEvent::DefineName {
241 name,
242 scope,
243 definition,
244 } => {
245 let mut editor = VertexEditor::new(graph);
246 let _ = editor.define_name(name, definition.clone(), *scope);
247 }
248 ChangeEvent::UpdateName {
249 name,
250 scope,
251 new_definition,
252 ..
253 } => {
254 let mut editor = VertexEditor::new(graph);
255 let _ = editor.update_name(name, new_definition.clone(), *scope);
256 }
257 ChangeEvent::DeleteName { name, scope, .. } => {
258 let mut editor = VertexEditor::new(graph);
259 let _ = editor.delete_name(name, *scope);
260 }
261 ChangeEvent::NamedRangeAdjusted {
262 name,
263 scope,
264 new_definition,
265 ..
266 } => {
267 let mut editor = VertexEditor::new(graph);
268 let _ = editor.update_name(name, new_definition.clone(), *scope);
269 }
270 ChangeEvent::SpillCommitted { anchor, new, .. } => {
271 let _ = graph.commit_spill_region_atomic_with_fault(
272 *anchor,
273 new.target_cells.clone(),
274 new.values.clone(),
275 None,
276 );
277 }
278 ChangeEvent::SpillCleared { anchor, .. } => {
279 graph.clear_spill_region(*anchor);
280 }
281 ChangeEvent::EdgeAdded { from, to } => {
282 let mut editor = VertexEditor::new(graph);
283 let _ = editor.add_edge(*from, *to);
284 }
285 ChangeEvent::EdgeRemoved { from, to } => {
286 let mut editor = VertexEditor::new(graph);
287 let _ = editor.remove_edge(*from, *to);
288 }
289 ChangeEvent::CompoundStart { .. } | ChangeEvent::CompoundEnd { .. } => {}
290 }
291 Ok(())
292}
293
294#[derive(Debug, Clone, Default, PartialEq)]
295pub struct ActionJournal {
296 pub name: String,
297 pub graph: GraphUndoBatch,
298 pub arrow: ArrowUndoBatch,
299 pub affected_cells: usize,
300}