122 lines
4.0 KiB
Rust
122 lines
4.0 KiB
Rust
//! Group layers action
|
|
//!
|
|
//! Creates a new GroupLayer containing the selected sibling layers.
|
|
|
|
use crate::action::Action;
|
|
use crate::document::Document;
|
|
use crate::layer::{AnyLayer, GroupLayer};
|
|
use uuid::Uuid;
|
|
|
|
/// Action that groups sibling layers into a new GroupLayer.
|
|
///
|
|
/// All layers must share the same parent (root or a specific GroupLayer).
|
|
pub struct GroupLayersAction {
|
|
/// IDs of layers to group
|
|
layer_ids: Vec<Uuid>,
|
|
/// Parent group ID (None = document root)
|
|
parent_group_id: Option<Uuid>,
|
|
/// Pre-generated UUID for the new GroupLayer
|
|
group_id: Uuid,
|
|
/// Rollback: index where the group was inserted
|
|
insert_index: Option<usize>,
|
|
/// Rollback: (original_index, layer) pairs, sorted by index ascending
|
|
removed_layers: Vec<(usize, AnyLayer)>,
|
|
}
|
|
|
|
impl GroupLayersAction {
|
|
pub fn new(layer_ids: Vec<Uuid>, parent_group_id: Option<Uuid>, group_id: Uuid) -> Self {
|
|
Self {
|
|
layer_ids,
|
|
parent_group_id,
|
|
group_id,
|
|
insert_index: None,
|
|
removed_layers: Vec::new(),
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Get a mutable reference to the children vec of the given parent.
|
|
fn get_parent_children<'a>(
|
|
document: &'a mut Document,
|
|
parent_group_id: Option<Uuid>,
|
|
) -> Result<&'a mut Vec<AnyLayer>, String> {
|
|
match parent_group_id {
|
|
None => Ok(&mut document.root.children),
|
|
Some(id) => {
|
|
let layer = document.root.get_child_mut(&id)
|
|
.ok_or_else(|| format!("Parent group {} not found", id))?;
|
|
match layer {
|
|
AnyLayer::Group(g) => Ok(&mut g.children),
|
|
_ => Err(format!("Layer {} is not a group", id)),
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Action for GroupLayersAction {
|
|
fn execute(&mut self, document: &mut Document) -> Result<(), String> {
|
|
let children = get_parent_children(document, self.parent_group_id)?;
|
|
|
|
// Find indices of all selected layers within the parent's children
|
|
let mut indices: Vec<usize> = Vec::new();
|
|
for layer_id in &self.layer_ids {
|
|
if let Some(idx) = children.iter().position(|l| l.id() == *layer_id) {
|
|
indices.push(idx);
|
|
} else {
|
|
return Err(format!("Layer {} not found in parent", layer_id));
|
|
}
|
|
}
|
|
indices.sort();
|
|
|
|
// Record the insert position (topmost selected layer)
|
|
let insert_index = indices[0];
|
|
self.insert_index = Some(insert_index);
|
|
|
|
// Remove layers back-to-front to preserve indices
|
|
self.removed_layers.clear();
|
|
for &idx in indices.iter().rev() {
|
|
let layer = children.remove(idx);
|
|
self.removed_layers.push((idx, layer));
|
|
}
|
|
// Reverse so removed_layers is sorted by index ascending
|
|
self.removed_layers.reverse();
|
|
|
|
// Build the new GroupLayer with children in their original order
|
|
let mut group = GroupLayer::new("Group");
|
|
group.layer.id = self.group_id;
|
|
for (_, layer) in &self.removed_layers {
|
|
group.add_child(layer.clone());
|
|
}
|
|
|
|
// Insert the group at the topmost position
|
|
let children = get_parent_children(document, self.parent_group_id)?;
|
|
children.insert(insert_index, AnyLayer::Group(group));
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn rollback(&mut self, document: &mut Document) -> Result<(), String> {
|
|
let Some(insert_index) = self.insert_index else {
|
|
return Err("Cannot rollback: action was not executed".to_string());
|
|
};
|
|
|
|
// Remove the GroupLayer
|
|
let children = get_parent_children(document, self.parent_group_id)?;
|
|
children.remove(insert_index);
|
|
|
|
// Re-insert original layers at their original indices (ascending order)
|
|
for (idx, layer) in &self.removed_layers {
|
|
let children = get_parent_children(document, self.parent_group_id)?;
|
|
children.insert(*idx, layer.clone());
|
|
}
|
|
|
|
self.insert_index = None;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn description(&self) -> String {
|
|
format!("Group {} layers", self.layer_ids.len())
|
|
}
|
|
}
|