feat(iced): implement transform drag messages and handlers
This commit is contained in:
@@ -201,6 +201,10 @@ pub struct IcedDocument {
|
||||
pub selection_transform: Option<SelectionTransform>,
|
||||
/// Transform handle being dragged
|
||||
pub transform_drag_handle: TransformHandle,
|
||||
/// Transform drag start position in canvas coordinates
|
||||
pub transform_drag_start: Option<(f32, f32)>,
|
||||
/// Original transform state before drag (for undo)
|
||||
pub transform_original: Option<SelectionTransform>,
|
||||
/// Internal clipboard for copy/paste operations
|
||||
pub internal_clipboard: Option<SelectionTransform>,
|
||||
/// Selection mask (alpha channel) for the current selection
|
||||
@@ -375,6 +379,13 @@ pub enum Message {
|
||||
SelectionDragMove(f32, f32),
|
||||
SelectionDragEnd,
|
||||
|
||||
// ── Selection transform ─────────────────────────────
|
||||
TransformDragStart(f32, f32),
|
||||
TransformDragMove(f32, f32),
|
||||
TransformDragEnd,
|
||||
TransformApply,
|
||||
TransformCancel,
|
||||
|
||||
// ── Vector tools ────────────────────────────────────
|
||||
VectorDrawStart(f32, f32),
|
||||
VectorDrawMove(f32, f32),
|
||||
@@ -527,6 +538,8 @@ impl HcieIcedApp {
|
||||
full_upload: std::cell::RefCell::new(true),
|
||||
selection_transform: None,
|
||||
transform_drag_handle: TransformHandle::None,
|
||||
transform_drag_start: None,
|
||||
transform_original: None,
|
||||
internal_clipboard: None,
|
||||
selection_mask: None,
|
||||
selection_bounds: None,
|
||||
@@ -1809,6 +1822,8 @@ impl HcieIcedApp {
|
||||
full_upload: std::cell::RefCell::new(true),
|
||||
selection_transform: None,
|
||||
transform_drag_handle: TransformHandle::None,
|
||||
transform_drag_start: None,
|
||||
transform_original: None,
|
||||
internal_clipboard: None,
|
||||
selection_mask: None,
|
||||
selection_bounds: None,
|
||||
@@ -1929,6 +1944,100 @@ impl HcieIcedApp {
|
||||
}
|
||||
}
|
||||
|
||||
// ── Selection transform ────────────────────────
|
||||
Message::TransformDragStart(x, y) => {
|
||||
let doc = &mut self.documents[self.active_doc];
|
||||
if let Some(ref tr) = doc.selection_transform {
|
||||
let original = tr.clone();
|
||||
doc.transform_drag_start = Some((x, y));
|
||||
doc.transform_original = Some(original);
|
||||
}
|
||||
}
|
||||
Message::TransformDragMove(x, y) => {
|
||||
let doc = &mut self.documents[self.active_doc];
|
||||
if let (Some(start), Some(ref mut tr)) = (doc.transform_drag_start, &mut doc.selection_transform) {
|
||||
let dx = x - start.0;
|
||||
let dy = y - start.1;
|
||||
|
||||
match doc.transform_drag_handle {
|
||||
TransformHandle::Move => {
|
||||
tr.pos = iced::Vector::new(tr.pos.x + dx, tr.pos.y + dy);
|
||||
doc.transform_drag_start = Some((x, y));
|
||||
}
|
||||
TransformHandle::TopLeft => {
|
||||
tr.pos = iced::Vector::new(tr.pos.x + dx, tr.pos.y + dy);
|
||||
tr.size = iced::Vector::new(tr.size.x - dx, tr.size.y - dy);
|
||||
doc.transform_drag_start = Some((x, y));
|
||||
}
|
||||
TransformHandle::TopRight => {
|
||||
tr.size = iced::Vector::new(tr.size.x + dx, tr.size.y - dy);
|
||||
tr.pos = iced::Vector::new(tr.pos.x, tr.pos.y + dy);
|
||||
doc.transform_drag_start = Some((x, y));
|
||||
}
|
||||
TransformHandle::BottomLeft => {
|
||||
tr.size = iced::Vector::new(tr.size.x - dx, tr.size.y + dy);
|
||||
tr.pos = iced::Vector::new(tr.pos.x + dx, tr.pos.y);
|
||||
doc.transform_drag_start = Some((x, y));
|
||||
}
|
||||
TransformHandle::BottomRight => {
|
||||
tr.size = iced::Vector::new(tr.size.x + dx, tr.size.y + dy);
|
||||
doc.transform_drag_start = Some((x, y));
|
||||
}
|
||||
TransformHandle::Top => {
|
||||
tr.pos = iced::Vector::new(tr.pos.x, tr.pos.y + dy);
|
||||
tr.size = iced::Vector::new(tr.size.x, tr.size.y - dy);
|
||||
doc.transform_drag_start = Some((x, y));
|
||||
}
|
||||
TransformHandle::Bottom => {
|
||||
tr.size = iced::Vector::new(tr.size.x, tr.size.y + dy);
|
||||
doc.transform_drag_start = Some((x, y));
|
||||
}
|
||||
TransformHandle::Left => {
|
||||
tr.pos = iced::Vector::new(tr.pos.x + dx, tr.pos.y);
|
||||
tr.size = iced::Vector::new(tr.size.x - dx, tr.size.y);
|
||||
doc.transform_drag_start = Some((x, y));
|
||||
}
|
||||
TransformHandle::Right => {
|
||||
tr.size = iced::Vector::new(tr.size.x + dx, tr.size.y);
|
||||
doc.transform_drag_start = Some((x, y));
|
||||
}
|
||||
TransformHandle::Rotate => {
|
||||
// Calculate rotation from center
|
||||
let center_x = tr.pos.x + tr.size.x / 2.0;
|
||||
let center_y = tr.pos.y + tr.size.y / 2.0;
|
||||
let angle = (y - center_y).atan2(x - center_x);
|
||||
tr.rotation = angle;
|
||||
}
|
||||
TransformHandle::None => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
Message::TransformDragEnd => {
|
||||
let doc = &mut self.documents[self.active_doc];
|
||||
doc.transform_drag_start = None;
|
||||
doc.transform_original = None;
|
||||
}
|
||||
Message::TransformApply => {
|
||||
let doc = &mut self.documents[self.active_doc];
|
||||
if let Some(_tr) = doc.selection_transform.take() {
|
||||
// TODO: Apply transform to layer pixels
|
||||
// For now, just clear the transform
|
||||
doc.transform_drag_handle = TransformHandle::None;
|
||||
return Task::perform(async {}, |_| Message::CompositeRefresh);
|
||||
}
|
||||
}
|
||||
Message::TransformCancel => {
|
||||
let doc = &mut self.documents[self.active_doc];
|
||||
// Restore original transform if we have it
|
||||
if let Some(original) = doc.transform_original.take() {
|
||||
doc.selection_transform = Some(original);
|
||||
} else {
|
||||
doc.selection_transform = None;
|
||||
}
|
||||
doc.transform_drag_start = None;
|
||||
doc.transform_drag_handle = TransformHandle::None;
|
||||
}
|
||||
|
||||
// ── Vector tools ──────────────────────────────
|
||||
Message::VectorDrawStart(x, y) => {
|
||||
self.documents[self.active_doc].vector_draw = Some(((x, y), (x, y)));
|
||||
@@ -2230,6 +2339,8 @@ impl HcieIcedApp {
|
||||
full_upload: std::cell::RefCell::new(true),
|
||||
selection_transform: None,
|
||||
transform_drag_handle: TransformHandle::None,
|
||||
transform_drag_start: None,
|
||||
transform_original: None,
|
||||
internal_clipboard: None,
|
||||
selection_mask: None,
|
||||
selection_bounds: None,
|
||||
|
||||
Reference in New Issue
Block a user