use crate::canvas::Canvas; #[derive(Clone, druid::Data)] pub struct VersionedCanvas { // We internally guarantee that this vector // is never empty versions: im::Vector, curr_version: usize, } impl VersionedCanvas { pub fn new(canvas: Canvas) -> VersionedCanvas { VersionedCanvas { versions: im::vector![canvas], curr_version: 0, } } // Get current canvas version pub fn get(&self) -> &Canvas { self.versions.get(self.curr_version).unwrap() } fn has_newer_versions(&self) -> bool { self.curr_version + 1 < self.versions.len() } fn has_older_versions(&self) -> bool { self.curr_version > 0 } pub fn version(&self) -> usize { self.curr_version } pub fn undo(&mut self) { if self.has_older_versions() { self.curr_version = self.curr_version - 1; } } pub fn redo(&mut self) { if self.has_newer_versions() { self.curr_version = self.curr_version + 1; } } pub fn update(&mut self, update_fn: impl FnOnce(&mut Canvas)) { // This is a linear history, // so we first check if there are newer versions, if so // this means we are in the past, so a change in the past destroys the future // and creates a new future. if self.has_newer_versions() { self.versions = self.versions.take(self.curr_version + 1); } let mut new_version = self.get().clone(); update_fn(&mut new_version); // Only push new version if there has been an actual change in the vector if !new_version.elements.ptr_eq(&self.get().elements) { self.versions.push_back(new_version); self.curr_version = self.curr_version + 1; } } // Do inplace update, which will be irreversible pub fn irreversible_update(&mut self, update_fn: impl FnOnce(&mut Canvas)) { // This is a linear history, // so we first check if there are newer versions, if so // this means we are in the past, so a change in the past destroys the future // and creates a new future. if self.has_newer_versions() { self.versions = self.versions.take(self.curr_version + 1); } update_fn(self.versions.back_mut().unwrap()); } }