use crate::error::IoError;
use formualizer_eval::engine::graph::DependencyGraph;
use formualizer_eval::engine::graph::editor::change_log::ChangeLog;
use formualizer_eval::engine::graph::editor::undo_engine::UndoEngine;
use formualizer_eval::engine::graph::editor::vertex_editor::{EditorError, VertexEditor};
#[derive(Clone, Debug)]
pub struct IoConfig {
pub enable_changelog: bool,
}
impl Default for IoConfig {
fn default() -> Self {
Self {
enable_changelog: true,
}
}
}
pub struct EditorSession {
pub graph: DependencyGraph,
enable_changelog: bool,
log: ChangeLog,
undo: UndoEngine,
}
impl EditorSession {
pub fn new_with_graph(graph: DependencyGraph, cfg: IoConfig) -> Self {
let mut log = ChangeLog::new();
log.set_enabled(cfg.enable_changelog);
Self {
graph,
enable_changelog: cfg.enable_changelog,
log,
undo: UndoEngine::new(),
}
}
pub fn new(cfg: IoConfig) -> Self {
Self::new_with_graph(DependencyGraph::new(), cfg)
}
pub fn begin_action(&mut self, description: impl Into<String>) {
if self.enable_changelog {
self.log.begin_compound(description.into());
}
}
pub fn end_action(&mut self) {
if self.enable_changelog {
self.log.end_compound();
}
}
pub fn with_action<F, R>(
&mut self,
description: impl Into<String>,
f: F,
) -> Result<R, EditorError>
where
F: FnOnce(&mut VertexEditor) -> Result<R, EditorError>,
{
self.begin_action(description);
let res = {
let mut editor = self.make_editor();
f(&mut editor)
};
self.end_action();
res
}
pub fn make_editor(&mut self) -> VertexEditor<'_> {
if self.enable_changelog {
VertexEditor::with_logger(&mut self.graph, &mut self.log)
} else {
VertexEditor::new(&mut self.graph)
}
}
pub fn undo(&mut self) -> Result<(), EditorError> {
if self.enable_changelog {
let _ = self.undo.undo(&mut self.graph, &mut self.log)?;
Ok(())
} else {
Ok(())
}
}
pub fn redo(&mut self) -> Result<(), EditorError> {
if self.enable_changelog {
let _ = self.undo.redo(&mut self.graph, &mut self.log)?;
Ok(())
} else {
Ok(())
}
}
pub fn commit_with_rollback<F>(&mut self, persist: F) -> Result<(), IoError>
where
F: FnOnce(&DependencyGraph) -> Result<(), IoError>,
{
match persist(&self.graph) {
Ok(()) => Ok(()),
Err(e) => {
if self.enable_changelog {
let _ = self.undo();
}
Err(e)
}
}
}
pub fn changelog_enabled(&self) -> bool {
self.enable_changelog
}
}