134 lines
4.2 KiB
Rust
134 lines
4.2 KiB
Rust
//! Move shape instances action
|
|
//!
|
|
//! Handles moving one or more shape instances to new positions.
|
|
|
|
use crate::action::Action;
|
|
use crate::document::Document;
|
|
use crate::layer::AnyLayer;
|
|
use std::collections::HashMap;
|
|
use uuid::Uuid;
|
|
use vello::kurbo::Point;
|
|
|
|
/// Action that moves shape instances to new positions
|
|
pub struct MoveShapeInstancesAction {
|
|
/// Layer ID containing the shape instances
|
|
layer_id: Uuid,
|
|
|
|
/// Map of object IDs to their old and new positions
|
|
shape_instance_positions: HashMap<Uuid, (Point, Point)>, // (old_pos, new_pos)
|
|
}
|
|
|
|
impl MoveShapeInstancesAction {
|
|
/// Create a new move shape instances action
|
|
///
|
|
/// # Arguments
|
|
///
|
|
/// * `layer_id` - The layer containing the shape instances
|
|
/// * `shape_instance_positions` - Map of object IDs to (old_position, new_position)
|
|
pub fn new(layer_id: Uuid, shape_instance_positions: HashMap<Uuid, (Point, Point)>) -> Self {
|
|
Self {
|
|
layer_id,
|
|
shape_instance_positions,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Action for MoveShapeInstancesAction {
|
|
fn execute(&mut self, document: &mut Document) -> Result<(), String> {
|
|
let layer = match document.get_layer_mut(&self.layer_id) {
|
|
Some(l) => l,
|
|
None => return Ok(()),
|
|
};
|
|
|
|
if let AnyLayer::Vector(vector_layer) = layer {
|
|
for (shape_instance_id, (_old, new)) in &self.shape_instance_positions {
|
|
vector_layer.modify_object_internal(shape_instance_id, |obj| {
|
|
obj.transform.x = new.x;
|
|
obj.transform.y = new.y;
|
|
});
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
fn rollback(&mut self, document: &mut Document) -> Result<(), String> {
|
|
let layer = match document.get_layer_mut(&self.layer_id) {
|
|
Some(l) => l,
|
|
None => return Ok(()),
|
|
};
|
|
|
|
if let AnyLayer::Vector(vector_layer) = layer {
|
|
for (shape_instance_id, (old, _new)) in &self.shape_instance_positions {
|
|
vector_layer.modify_object_internal(shape_instance_id, |obj| {
|
|
obj.transform.x = old.x;
|
|
obj.transform.y = old.y;
|
|
});
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
fn description(&self) -> String {
|
|
let count = self.shape_instance_positions.len();
|
|
if count == 1 {
|
|
"Move shape instance".to_string()
|
|
} else {
|
|
format!("Move {} shape instances", count)
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
use crate::layer::VectorLayer;
|
|
use crate::object::ShapeInstance;
|
|
use crate::shape::Shape;
|
|
use vello::kurbo::{Circle, Shape as KurboShape};
|
|
|
|
#[test]
|
|
fn test_move_shape_instances_action() {
|
|
// Create a document with a test object
|
|
let mut document = Document::new("Test");
|
|
|
|
let circle = Circle::new((100.0, 100.0), 50.0);
|
|
let path = circle.to_path(0.1);
|
|
let shape = Shape::new(path);
|
|
let object = ShapeInstance::new(shape.id).with_position(50.0, 50.0);
|
|
|
|
let mut vector_layer = VectorLayer::new("Layer 1");
|
|
vector_layer.add_shape(shape);
|
|
let shape_instance_id = vector_layer.add_object(object);
|
|
let layer_id = document.root.add_child(AnyLayer::Vector(vector_layer));
|
|
|
|
// Create move action
|
|
let mut positions = HashMap::new();
|
|
positions.insert(
|
|
shape_instance_id,
|
|
(Point::new(50.0, 50.0), Point::new(150.0, 200.0))
|
|
);
|
|
|
|
let mut action = MoveShapeInstancesAction::new(layer_id, positions);
|
|
|
|
// Execute
|
|
action.execute(&mut document).unwrap();
|
|
|
|
// Verify position changed
|
|
if let Some(AnyLayer::Vector(layer)) = document.get_layer(&layer_id) {
|
|
let obj = layer.get_object(&shape_instance_id).unwrap();
|
|
assert_eq!(obj.transform.x, 150.0);
|
|
assert_eq!(obj.transform.y, 200.0);
|
|
}
|
|
|
|
// Rollback
|
|
action.rollback(&mut document).unwrap();
|
|
|
|
// Verify position restored
|
|
if let Some(AnyLayer::Vector(layer)) = document.get_layer(&layer_id) {
|
|
let obj = layer.get_object(&shape_instance_id).unwrap();
|
|
assert_eq!(obj.transform.x, 50.0);
|
|
assert_eq!(obj.transform.y, 50.0);
|
|
}
|
|
}
|
|
}
|