mirror of
https://github.com/storytold/designcraft.git
synced 2026-10-28 12:16:53 -06:00
Convert gradient tool drag to spread space on rotated spreads
Found while testing crates/tools/src/gradient.rs:62 (PointerKind::Drag branch: `let to = *sp + (end - *start);`) Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com> Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Haiku 5.5
parent
45ed6cfce0
commit
3e7aeaa142
@@ -1,6 +1,7 @@
|
||||
//! Gradient Swatch tool (G): drag across the selected objects (or the object under the pointer)
|
||||
//! to set where their gradient fill starts and ends; Shift constrains the angle to 45° steps.
|
||||
|
||||
use designcraft_doc::SpreadRef;
|
||||
use designcraft_geom::{Point, Vec2};
|
||||
use serde_json::json;
|
||||
|
||||
@@ -10,8 +11,8 @@ use crate::{Action, Cursor, Mods, Overlay, PointerEvent, PointerKind, Tool, Tool
|
||||
pub struct GradientTool {
|
||||
/// Gradient Feather tool (Shift+G): the drag sets the fade instead of the fill gradient.
|
||||
pub feather: bool,
|
||||
/// Canvas start point, spread-space start point and the target ids.
|
||||
drag: Option<(Point, Point, Vec<u64>)>,
|
||||
/// Canvas start point, spread-space start point and the target ids, and the spread.
|
||||
drag: Option<(Point, Point, Vec<u64>, SpreadRef)>,
|
||||
end: Option<Point>,
|
||||
}
|
||||
|
||||
@@ -44,27 +45,27 @@ impl Tool for GradientTool {
|
||||
} else {
|
||||
cx.selection.items.iter().map(|i| i.0).collect()
|
||||
};
|
||||
let Some((_, sp)) = cx.layout.spread_at(ev.pos) else { return vec![] };
|
||||
let Some((spread, sp)) = cx.layout.spread_at(ev.pos) else { return vec![] };
|
||||
if ids.is_empty() {
|
||||
return vec![];
|
||||
}
|
||||
self.drag = Some((ev.pos, sp, ids));
|
||||
self.drag = Some((ev.pos, sp, ids, spread));
|
||||
self.end = None;
|
||||
vec![Action::Begin(if self.feather { "Gradient Feather".into() } else { "Gradient".into() })]
|
||||
}
|
||||
PointerKind::Drag => {
|
||||
let Some((start, sp, ids)) = &self.drag else { return vec![] };
|
||||
let Some((start, sp, ids, spread)) = &self.drag else { return vec![] };
|
||||
let end = constrain(*start, ev.pos, ev.mods);
|
||||
self.end = Some(end);
|
||||
if (end - *start).hypot() < cx.tol(2.0) {
|
||||
return vec![];
|
||||
}
|
||||
let to = *sp + (end - *start);
|
||||
let to = *sp + cx.layout.delta_to_spread(*spread, end - *start);
|
||||
let cmd = if self.feather { "object.gradientFeather" } else { "object.gradient" };
|
||||
vec![Action::Preview(cmd.into(), json!({"ids": ids, "from": [sp.x, sp.y], "to": [to.x, to.y]}))]
|
||||
}
|
||||
PointerKind::Up => {
|
||||
let moved = self.end.zip(self.drag.as_ref()).is_some_and(|(e, (s, _, _))| (e - *s).hypot() >= cx.tol(2.0));
|
||||
let moved = self.end.zip(self.drag.as_ref()).is_some_and(|(e, (s, ..))| (e - *s).hypot() >= cx.tol(2.0));
|
||||
let was = self.drag.take().is_some();
|
||||
self.end = None;
|
||||
match (was, moved) {
|
||||
@@ -79,7 +80,7 @@ impl Tool for GradientTool {
|
||||
|
||||
fn overlays(&self, _cx: &ToolContext) -> Vec<Overlay> {
|
||||
match (&self.drag, self.end) {
|
||||
(Some((a, _, _)), Some(b)) => vec![Overlay::Line { a: *a, b, color: [0, 0, 0], dashed: false }],
|
||||
(Some((a, ..)), Some(b)) => vec![Overlay::Line { a: *a, b, color: [0, 0, 0], dashed: false }],
|
||||
_ => vec![],
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,6 +193,32 @@ fn gradient_tool_drag_sets_the_vector() {
|
||||
assert_eq!(t.pointer(&cx, &PointerEvent::new(PointerKind::Up, 220.0 + off.x, 153.0 + off.y)), vec![Action::Commit]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gradient_tool_drag_follows_a_rotated_spread() {
|
||||
let mut d = Document::new(&NewDocument::default());
|
||||
let lid = d.default_layer();
|
||||
d.add_text_frame(SpreadRef::Doc(0), Rect::new(100.0, 100.0, 300.0, 200.0), lid, "", ParaFormat::default()).unwrap();
|
||||
Arc::make_mut(&mut d.spreads[0]).pages[0].view_rotation = 1;
|
||||
let (s, c, l) = (Selection::default(), Cache::new(), CanvasLayout::new(&d, false));
|
||||
let cx = ctx(&d, &s, &c, &l);
|
||||
let start = l.to_canvas(SpreadRef::Doc(0), Point::new(150.0, 150.0));
|
||||
let mut t = create("gradientSwatch");
|
||||
t.pointer(&cx, &PointerEvent::new(PointerKind::Down, start.x, start.y));
|
||||
for shift in [false, true] {
|
||||
let ev = PointerEvent::new(PointerKind::Drag, start.x + 100.0, start.y).with_mods(Mods { shift, ..Default::default() });
|
||||
match &t.pointer(&cx, &ev)[0] {
|
||||
Action::Preview(_, p) => {
|
||||
let to: Vec<f64> = p["to"].as_array().unwrap().iter().map(|v| v.as_f64().unwrap()).collect();
|
||||
let want = l.delta_to_spread(SpreadRef::Doc(0), Vec2::new(100.0, 0.0));
|
||||
assert!((to[0] - (150.0 + want.x)).abs() < 1e-6 && (to[1] - (150.0 + want.y)).abs() < 1e-6, "{to:?} want {want:?}");
|
||||
assert!((to[0] - 150.0).abs() > 1e-6 || (to[1] - 150.0).abs() > 1e-6);
|
||||
assert!((to[0] - 150.0).abs() < 1e-6, "{to:?}");
|
||||
}
|
||||
other => panic!("{other:?}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn anchor_tools_emit_path_commands() {
|
||||
let mut d = Document::new(&NewDocument::default());
|
||||
|
||||
Reference in New Issue
Block a user