M3.17: interactive gradient annotator — drag the start handle or the bar to move the gradient, the end handle to change length and angle, just past the end to rotate (Shift snaps to 45°); a bar click adds a stop, stops drag along the bar, off it to delete (never below two), Alt-drag copies, diamonds move midpoints; a click inside selected art applies the gradient from that point; double-clicking a stop opens a popover (Color/Swatches, Opacity, Location); the selected stop lives in the session (gradient.selectStop), shared by the tool, the Gradient and Color panels and agents, and takes Delete/Backspace and ←/→ ahead of their shortcuts (Tool::claims_key, also headless); stop chips draw as Overlay::Swatch with generated add/remove-stop cursors; the stop math moves into the color crate

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
bflatastic
2026-10-04 17:39:36 +07:00
co-authored by Claude Opus 5.5
parent aa1b592935
commit 3786cfaf36
20 changed files with 1263 additions and 216 deletions
+6
View File
@@ -79,6 +79,7 @@ impl Session {
snap_to_point: view.snap_to_point,
corner_widgets: view.corner_widgets,
fill_active: self.fill_active,
gradient_stop: self.gradient_stop,
};
f(self.tool.as_mut(), &cx)
}
@@ -109,6 +110,11 @@ impl Session {
self.tool.busy()
}
/// Does the active tool take `key` ahead of the shortcuts bound to it (see `Tool::claims_key`)?
pub fn tool_claims_key(&mut self, key: ToolKey, view: ViewInfo) -> bool {
self.with_tool_cx(view, |t, cx| t.claims_key(cx, key))
}
pub fn overlays(&mut self, view: ViewInfo) -> Vec<Overlay> {
let mut v = self.with_tool_cx(view, |t, cx| t.overlays(cx));
if let Some(d) = self.active() {