use super::UndoAction;
use crate::coord::{CanvasPoint, CanvasRect};
use crate::document::Document;
use crate::gpu::compositor::Compositor;
use crate::gpu::region_store::UndoRegionEntry;
use crate::layer::LayerId;
use std::collections::{HashMap, HashSet};
struct SelectionPart {
was_active: bool,
entry: UndoRegionEntry,
}
pub struct CanvasGeometryAction {
old_w: u32,
old_h: u32,
new_w: u32,
new_h: u32,
old_origin: CanvasPoint,
new_origin: CanvasPoint,
bounds: Vec<(LayerId, CanvasRect, CanvasRect)>,
regions: Vec<UndoRegionEntry>,
selection: Option<SelectionPart>,
}
impl CanvasGeometryAction {
#[allow(clippy::too_many_arguments)]
pub fn new(
old_dims: (u32, u32),
new_dims: (u32, u32),
old_origin: CanvasPoint,
new_origin: CanvasPoint,
bounds: Vec<(LayerId, CanvasRect, CanvasRect)>,
regions: Vec<UndoRegionEntry>,
selection: Option<(bool, UndoRegionEntry)>,
) -> Self {
CanvasGeometryAction {
old_w: old_dims.0,
old_h: old_dims.1,
new_w: new_dims.0,
new_h: new_dims.1,
old_origin,
new_origin,
bounds,
regions,
selection: selection.map(|(was_active, entry)| SelectionPart { was_active, entry }),
}
}
}
impl UndoAction for CanvasGeometryAction {
fn undo(&mut self, doc: &mut Document) -> HashMap<LayerId, HashSet<(i32, i32)>> {
doc.width = self.old_w;
doc.height = self.old_h;
doc.canvas_origin = self.old_origin;
for (id, old_extent, _) in &self.bounds {
doc.set_node_pixel_bounds(*id, *old_extent);
}
HashMap::new()
}
fn redo(&mut self, doc: &mut Document) -> HashMap<LayerId, HashSet<(i32, i32)>> {
doc.width = self.new_w;
doc.height = self.new_h;
doc.canvas_origin = self.new_origin;
for (id, _, new_extent) in &self.bounds {
doc.set_node_pixel_bounds(*id, *new_extent);
}
HashMap::new()
}
fn gpu_region_entries_mut(&mut self) -> Vec<&mut UndoRegionEntry> {
self.regions.iter_mut().collect()
}
fn selection_region_entry_mut(&mut self) -> Option<&mut UndoRegionEntry> {
self.selection.as_mut().map(|s| &mut s.entry)
}
fn swap_selection_active(&mut self, current_active: bool) -> Option<bool> {
self.selection.as_mut().map(|s| {
let restore_to = s.was_active;
s.was_active = current_active;
restore_to
})
}
fn byte_cost(&self) -> u64 {
let regions: u64 = self
.regions
.iter()
.map(|e| e.byte_size)
.fold(0, u64::saturating_add);
let sel = self
.selection
.as_ref()
.map(|s| s.entry.byte_size)
.unwrap_or(0);
regions.saturating_add(sel)
}
fn on_evict(&mut self, _compositor: &mut Compositor) {
}
}