mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-03 06:30:00 -06:00
Draw Inside: a double-click outside the object returns to Draw Normal
In Draw Inside, a double-click with the Selection, Direct Selection or
Group Selection tool outside the object being drawn into now sets the
drawing mode to Draw Normal (view.drawMode {mode: "normal"}), as
Shift+D does. The object's geometric bounds, grown by the selection
tolerance, count as inside, and a double-click after the object was
deleted also returns to Draw Normal. The tool then takes the
double-click as before: with the Selection tool, a double-click on the
empty canvas still exits isolation mode, and one on another object
still isolates that object. Other tools leave Draw Inside on.
Docs: docs/target-app-parity.md.
This commit is contained in:
@@ -110,6 +110,44 @@ fn draw_behind_and_inside() {
|
||||
assert!(s.draw_inside.is_none());
|
||||
}
|
||||
|
||||
/// In Draw Inside, a double-click with a selection tool outside the object being drawn into sets
|
||||
/// the drawing mode to Draw Normal, and the tool still takes the double-click. Inside the object's
|
||||
/// bounds, grown by the selection tolerance, and with other tools, Draw Inside stays on.
|
||||
#[test]
|
||||
fn double_clicking_outside_the_draw_inside_object_returns_to_draw_normal() {
|
||||
use vectorcraft_tools::{PointerEvent, PointerKind};
|
||||
let mut s = session();
|
||||
let a = s.execute("shape.rectangle", &json!({"x": 100, "y": 100, "width": 100, "height": 100})).unwrap()["id"].as_u64().unwrap();
|
||||
let inside = |s: &mut Session| {
|
||||
s.execute("select.set", &json!({"ids": [a]})).unwrap();
|
||||
s.execute("view.drawMode", &json!({"mode": "inside"})).unwrap();
|
||||
};
|
||||
let double = |s: &mut Session, x: f64, y: f64| {
|
||||
s.pointer(&PointerEvent::new(PointerKind::DoubleClick, x, y), ViewInfo::default()).unwrap();
|
||||
(s.draw_mode, s.draw_inside)
|
||||
};
|
||||
inside(&mut s);
|
||||
s.select_tool("selection", ViewInfo::default()).unwrap();
|
||||
// Inside the rectangle the Selection tool isolates it, as in Draw Normal; 2 pt past its edge
|
||||
// is within the 3 px selection tolerance at 100%.
|
||||
assert_eq!(double(&mut s, 150.0, 150.0), (DrawMode::Inside, Some(NodeId(a))));
|
||||
assert_eq!(s.doc().unwrap().isolation, Some(NodeId(a)));
|
||||
assert_eq!(double(&mut s, 202.0, 150.0), (DrawMode::Inside, Some(NodeId(a))));
|
||||
// A double-click outside, on the empty canvas, sets Draw Normal and still leaves isolation mode.
|
||||
assert_eq!(double(&mut s, 300.0, 250.0), (DrawMode::Normal, None));
|
||||
assert_eq!(s.doc().unwrap().isolation, None);
|
||||
// With the Rectangle tool a double-click leaves Draw Inside on; with Direct Selection it sets Draw Normal.
|
||||
inside(&mut s);
|
||||
s.select_tool("rectangle", ViewInfo::default()).unwrap();
|
||||
assert_eq!(double(&mut s, 300.0, 250.0), (DrawMode::Inside, Some(NodeId(a))));
|
||||
s.select_tool("directSelection", ViewInfo::default()).unwrap();
|
||||
assert_eq!(double(&mut s, 300.0, 250.0), (DrawMode::Normal, None));
|
||||
// Once the object is gone, any double-click with a selection tool sets Draw Normal.
|
||||
inside(&mut s);
|
||||
s.execute("edit.clear", &json!({})).unwrap();
|
||||
assert_eq!(double(&mut s, 150.0, 150.0), (DrawMode::Normal, None));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn export_for_screens_writes_every_combination() {
|
||||
let mut s = Session::new();
|
||||
|
||||
@@ -267,6 +267,7 @@ impl Session {
|
||||
if let Some(r) = self.plane_widget_pointer(ev, view) {
|
||||
return r;
|
||||
}
|
||||
self.leave_draw_inside(ev, view)?;
|
||||
let ev = &self.lend_selection_tool(ev);
|
||||
let acts = self.with_tool_cx(view, |t, cx| t.pointer(cx, ev));
|
||||
let r = self.take_tool_panic().and_then(|()| {
|
||||
@@ -282,6 +283,26 @@ impl Session {
|
||||
r
|
||||
}
|
||||
|
||||
/// In Draw Inside, a double-click with a selection tool outside the geometric bounds of the
|
||||
/// object new art goes inside, grown by the selection tolerance, or after that object is gone,
|
||||
/// sets the drawing mode to Draw Normal (`view.drawMode {mode: "normal"}`, as Shift+D does).
|
||||
/// The tool then takes the double-click as in Draw Normal.
|
||||
fn leave_draw_inside(&mut self, ev: &PointerEvent, view: ViewInfo) -> Result<()> {
|
||||
if ev.kind != PointerKind::DoubleClick
|
||||
|| self.draw_mode != crate::DrawMode::Inside
|
||||
|| !vectorcraft_tools::catalog::is_selection_tool(self.tool.id())
|
||||
{
|
||||
return Ok(());
|
||||
}
|
||||
let Some(d) = self.active() else { return Ok(()) };
|
||||
let tol = self.prefs.selection_tolerance / view.zoom.max(1e-9);
|
||||
let inside = self.draw_inside.and_then(|t| d.doc.bounds_of(&[t], false)).is_some_and(|b| b.inflate(tol, tol).contains(ev.pos));
|
||||
if !inside {
|
||||
self.execute("view.drawMode", &serde_json::json!({ "mode": "normal" }))?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// A guide dragged out of a ruler, whatever the tool: a vertical one out of the left ruler, a
|
||||
/// horizontal one out of the top ruler. `ev` is the pointer in document space (a drag, then the
|
||||
/// release), over the canvas or not (`on_canvas`). The guide shows where the pointer is over
|
||||
|
||||
Reference in New Issue
Block a user