use std::collections::VecDeque;
use mathtex_editor_core::Snapshot;
pub const DEFAULT_UNDO_LIMIT: usize = 200;
#[derive(Debug, Clone)]
pub struct UndoStack {
undo: VecDeque<Snapshot>,
redo: Vec<Snapshot>,
limit: usize,
}
impl Default for UndoStack {
fn default() -> Self {
Self::new(DEFAULT_UNDO_LIMIT)
}
}
impl UndoStack {
pub fn new(limit: usize) -> Self {
Self { undo: VecDeque::new(), redo: Vec::new(), limit }
}
pub fn limit(&self) -> usize {
self.limit
}
pub fn set_limit(&mut self, limit: usize) {
self.limit = limit;
self.trim();
}
pub fn record(&mut self, before: Snapshot) {
self.redo.clear();
self.undo.push_back(before);
self.trim();
}
pub fn undo(&mut self, current: Snapshot) -> Option<Snapshot> {
let target = self.undo.pop_back()?;
self.redo.push(current);
Some(target)
}
pub fn redo(&mut self, current: Snapshot) -> Option<Snapshot> {
let target = self.redo.pop()?;
self.undo.push_back(current);
self.trim();
Some(target)
}
pub fn can_undo(&self) -> bool {
!self.undo.is_empty()
}
pub fn can_redo(&self) -> bool {
!self.redo.is_empty()
}
pub fn clear(&mut self) {
self.undo.clear();
self.redo.clear();
}
pub fn snapshots(&self) -> impl Iterator<Item = &Snapshot> {
self.undo.iter().chain(&self.redo)
}
fn trim(&mut self) {
while self.undo.len() > self.limit {
self.undo.pop_front();
}
}
}