use super::tombstones::Tombstones;
use super::UndoAction;
use crate::document::Document;
use crate::gpu::compositor::Compositor;
use crate::layer::LayerId;
use std::collections::{HashMap, HashSet};
pub struct LayerAddAction {
layer_id: LayerId,
parent: Option<LayerId>,
position: usize,
}
impl LayerAddAction {
pub fn new(layer_id: LayerId, parent: Option<LayerId>, position: usize) -> Self {
LayerAddAction {
layer_id,
parent,
position,
}
}
}
impl UndoAction for LayerAddAction {
fn undo(&mut self, doc: &mut Document) -> HashMap<LayerId, HashSet<(i32, i32)>> {
doc.detach_for_undo(self.layer_id);
HashMap::new()
}
fn redo(&mut self, doc: &mut Document) -> HashMap<LayerId, HashSet<(i32, i32)>> {
doc.reinsert_node(self.layer_id, self.parent, self.position);
HashMap::new()
}
}
pub struct LayerRemoveAction {
layer_id: LayerId,
parent: Option<LayerId>,
position: usize,
tombstones: Tombstones,
applied: bool,
}
impl LayerRemoveAction {
pub fn new(
layer_id: LayerId,
parent: Option<LayerId>,
position: usize,
tombstones: Vec<LayerId>,
) -> Self {
LayerRemoveAction {
layer_id,
parent,
position,
tombstones: Tombstones::new(tombstones, true),
applied: true,
}
}
}
impl UndoAction for LayerRemoveAction {
fn undo(&mut self, doc: &mut Document) -> HashMap<LayerId, HashSet<(i32, i32)>> {
doc.reinsert_node(self.layer_id, self.parent, self.position);
self.applied = false;
HashMap::new()
}
fn redo(&mut self, doc: &mut Document) -> HashMap<LayerId, HashSet<(i32, i32)>> {
doc.detach_for_undo(self.layer_id);
self.applied = true;
HashMap::new()
}
fn on_evict(&mut self, compositor: &mut Compositor) {
self.tombstones
.dispose_if_detached(self.applied, compositor);
}
}
pub struct LayerMoveAction {
layer_id: LayerId,
old_parent: Option<LayerId>,
old_position: usize,
new_parent: Option<LayerId>,
new_position: usize,
}
impl LayerMoveAction {
pub fn new(
layer_id: LayerId,
old_parent: Option<LayerId>,
old_position: usize,
new_parent: Option<LayerId>,
new_position: usize,
) -> Self {
LayerMoveAction {
layer_id,
old_parent,
old_position,
new_parent,
new_position,
}
}
}
impl UndoAction for LayerMoveAction {
fn undo(&mut self, doc: &mut Document) -> HashMap<LayerId, HashSet<(i32, i32)>> {
if doc.detach_for_undo(self.layer_id).is_some() {
doc.reinsert_node(self.layer_id, self.old_parent, self.old_position);
}
HashMap::new()
}
fn redo(&mut self, doc: &mut Document) -> HashMap<LayerId, HashSet<(i32, i32)>> {
if doc.detach_for_undo(self.layer_id).is_some() {
doc.reinsert_node(self.layer_id, self.new_parent, self.new_position);
}
HashMap::new()
}
}
pub struct DuplicateAction {
root_new_id: LayerId,
parent: Option<LayerId>,
position: usize,
tombstones: Tombstones,
applied: bool,
}
impl DuplicateAction {
pub fn new(
root_new_id: LayerId,
parent: Option<LayerId>,
position: usize,
tombstones: Vec<LayerId>,
) -> Self {
DuplicateAction {
root_new_id,
parent,
position,
tombstones: Tombstones::new(tombstones, false),
applied: true,
}
}
}
impl UndoAction for DuplicateAction {
fn undo(&mut self, doc: &mut Document) -> HashMap<LayerId, HashSet<(i32, i32)>> {
doc.detach_for_undo(self.root_new_id);
self.applied = false;
HashMap::new()
}
fn redo(&mut self, doc: &mut Document) -> HashMap<LayerId, HashSet<(i32, i32)>> {
doc.reinsert_node(self.root_new_id, self.parent, self.position);
self.applied = true;
HashMap::new()
}
fn on_evict(&mut self, compositor: &mut Compositor) {
self.tombstones
.dispose_if_detached(self.applied, compositor);
}
}
#[derive(Clone, Copy, Debug)]
pub struct BakeSourceSlot {
pub id: LayerId,
pub parent: Option<LayerId>,
pub position: usize,
}
pub struct BakeLayersAction {
pub sources: Vec<BakeSourceSlot>,
source_tombstones: Tombstones,
pub result_id: LayerId,
pub result_parent: Option<LayerId>,
pub result_position: usize,
result_tombstones: Tombstones,
applied: bool,
}
impl BakeLayersAction {
pub fn new(
sources: Vec<BakeSourceSlot>,
source_tombstones: Vec<LayerId>,
result_id: LayerId,
result_parent: Option<LayerId>,
result_position: usize,
result_tombstones: Vec<LayerId>,
) -> Self {
BakeLayersAction {
sources,
source_tombstones: Tombstones::new(
source_tombstones,
true,
),
result_id,
result_parent,
result_position,
result_tombstones: Tombstones::new(
result_tombstones,
false,
),
applied: true,
}
}
pub fn source_ids_bottom_to_top(&self) -> Vec<LayerId> {
let mut ids: Vec<(usize, LayerId)> =
self.sources.iter().map(|s| (s.position, s.id)).collect();
ids.sort_by_key(|(p, _)| *p);
ids.into_iter().map(|(_, id)| id).collect()
}
}
impl UndoAction for BakeLayersAction {
fn undo(&mut self, doc: &mut Document) -> HashMap<LayerId, HashSet<(i32, i32)>> {
doc.detach_for_undo(self.result_id);
let mut sources_sorted = self.sources.clone();
sources_sorted.sort_by_key(|s| s.position);
for slot in sources_sorted {
doc.reinsert_node(slot.id, slot.parent, slot.position);
}
self.applied = false;
HashMap::new()
}
fn redo(&mut self, doc: &mut Document) -> HashMap<LayerId, HashSet<(i32, i32)>> {
for slot in &self.sources {
doc.detach_for_undo(slot.id);
}
doc.reinsert_node(self.result_id, self.result_parent, self.result_position);
self.applied = true;
HashMap::new()
}
fn on_evict(&mut self, compositor: &mut Compositor) {
self.source_tombstones
.dispose_if_detached(self.applied, compositor);
self.result_tombstones
.dispose_if_detached(self.applied, compositor);
}
}