mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-13 13:09:16 +00:00
Merge pull request #7043 from dotCooCoo/fix/pen-readout-without-rubber-band
Drawing tools: the measurement readout shows with the rubber band off
This commit is contained in:
@@ -573,12 +573,15 @@ impl Tool for SmartPenTool {
|
||||
|
||||
fn overlays(&self, cx: &ToolContext) -> Vec<Overlay> {
|
||||
let mut o = vec![];
|
||||
if cx.pen_rubber_band
|
||||
&& self.press.is_none()
|
||||
// The rubber band preference hides only the preview segment; Measurement Labels decides the readout.
|
||||
if self.press.is_none()
|
||||
&& let (Some((id, _, sp)), Some(h)) = (self.active(cx), self.hover)
|
||||
&& let Some(path) = self.rubber_band(sp, h)
|
||||
{
|
||||
o.push(Overlay::Path { path, color: cx.doc.layer_color(id), width: 1.0, dashed: false });
|
||||
if cx.pen_rubber_band
|
||||
&& let Some(path) = self.rubber_band(sp, h)
|
||||
{
|
||||
o.push(Overlay::Path { path, color: cx.doc.layer_color(id), width: 1.0, dashed: false });
|
||||
}
|
||||
if let Some(last) = sp.anchors.last().map(|a| a.p)
|
||||
&& cx.measurement_labels
|
||||
&& last.distance(h) > 1e-9
|
||||
|
||||
@@ -315,6 +315,35 @@ fn the_rubber_band_shows_the_next_segment_and_ending_the_path() {
|
||||
assert!(t.overlays(&cx).is_empty());
|
||||
}
|
||||
|
||||
/// With Enable Rubber Band for the Pen off, the preview segment is hidden but Measurement Labels
|
||||
/// still shows the readout from the last anchor to the pointer.
|
||||
#[test]
|
||||
fn the_measurement_label_shows_with_the_rubber_band_off() {
|
||||
let (d, _, s) = doc(line());
|
||||
let p = paint();
|
||||
let on = plain(&d, &s, &p);
|
||||
let off = ToolContext { pen_rubber_band: false, ..plain(&d, &s, &p) };
|
||||
let (from, to) = (Point::new(200.0, 100.0), Point::new(300.0, 160.0));
|
||||
let measure =
|
||||
|o: &[Overlay]| o.iter().filter_map(|o| if let Overlay::Measure { text, .. } = o { Some(text.clone()) } else { None }).collect::<Vec<_>>();
|
||||
let band = |o: &[Overlay]| o.iter().any(|o| matches!(o, Overlay::Path { .. }));
|
||||
let mut t = drawing(&off, from);
|
||||
t.pointer(&off, &ev(PointerKind::Move, to.x, to.y, NO));
|
||||
let o = t.overlays(&off);
|
||||
assert_eq!(measure(&o), vec![off.segment_measure_label(from, to)], "{o:?}");
|
||||
assert!(!band(&o), "{o:?}");
|
||||
let o = t.overlays(&on);
|
||||
assert_eq!(measure(&o), vec![on.segment_measure_label(from, to)], "{o:?}");
|
||||
assert!(band(&o), "{o:?}");
|
||||
for rubber in [true, false] {
|
||||
let quiet = ToolContext { pen_rubber_band: rubber, measurement_labels: false, ..plain(&d, &s, &p) };
|
||||
assert!(measure(&t.overlays(&quiet)).is_empty());
|
||||
}
|
||||
// Hovering exactly on the last anchor measures no segment.
|
||||
t.pointer(&off, &ev(PointerKind::Move, from.x, from.y, NO));
|
||||
assert!(measure(&t.overlays(&off)).is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn an_alt_drag_away_from_paths_selects_the_points_inside_a_marquee() {
|
||||
let (d, id, s) = doc(SubPath::polyline(&[Point::new(100.0, 100.0), Point::new(200.0, 100.0), Point::new(300.0, 100.0)], false));
|
||||
|
||||
@@ -718,38 +718,44 @@ impl Tool for CurvatureTool {
|
||||
}
|
||||
fn overlays(&self, cx: &ToolContext) -> Vec<Overlay> {
|
||||
let mut o = self.snap.guides().to_vec();
|
||||
let band = cx.curvature_rubber_band && self.drag.is_none();
|
||||
// The rubber band preference hides only the preview curve; Measurement Labels decides the readout.
|
||||
let idle = self.drag.is_none();
|
||||
let band = cx.curvature_rubber_band;
|
||||
let mut bp = BezPath::new();
|
||||
if self.active(cx).is_none() {
|
||||
// The curve on from the current end of a selected path: its last segment and the next.
|
||||
if band
|
||||
if idle
|
||||
&& let (Some(e), Some(h)) = (current_end(cx), self.hover)
|
||||
&& let Some(sp) = subpath(cx, e.id, e.si)
|
||||
{
|
||||
let n = sp.anchors.len();
|
||||
let near = if e.start {
|
||||
sp.anchors.iter().take(2).rev().map(Anchor::reversed).collect()
|
||||
} else {
|
||||
sp.anchors.iter().skip(n.saturating_sub(2)).copied().collect()
|
||||
};
|
||||
let mut tail = SubPath::new(near, false);
|
||||
curvature_extend(&mut tail, false, h, self.how(&e), false);
|
||||
tail.to_bezpath_into(&mut bp);
|
||||
o.push(Overlay::Path { path: bp, color: FEEDBACK, width: 1.0, dashed: false });
|
||||
if band {
|
||||
let n = sp.anchors.len();
|
||||
let near = if e.start {
|
||||
sp.anchors.iter().take(2).rev().map(Anchor::reversed).collect()
|
||||
} else {
|
||||
sp.anchors.iter().skip(n.saturating_sub(2)).copied().collect()
|
||||
};
|
||||
let mut tail = SubPath::new(near, false);
|
||||
curvature_extend(&mut tail, false, h, self.how(&e), false);
|
||||
tail.to_bezpath_into(&mut bp);
|
||||
o.push(Overlay::Path { path: bp, color: FEEDBACK, width: 1.0, dashed: false });
|
||||
}
|
||||
if cx.measurement_labels && e.p.distance(h) > 1e-9 {
|
||||
o.push(Overlay::Measure { p: h + Vec2::new(cx.tol(12.0), cx.tol(12.0)), text: cx.segment_measure_label(e.p, h) });
|
||||
}
|
||||
}
|
||||
return o;
|
||||
}
|
||||
if band
|
||||
if idle
|
||||
&& !self.closed
|
||||
&& let Some(h) = self.hover
|
||||
{
|
||||
let mut pts = self.pts.clone();
|
||||
pts.push((h, false));
|
||||
curvature_spline(&pts, false).to_bezpath_into(&mut bp);
|
||||
o.push(Overlay::Path { path: bp, color: FEEDBACK, width: 1.0, dashed: false });
|
||||
if band {
|
||||
let mut pts = self.pts.clone();
|
||||
pts.push((h, false));
|
||||
curvature_spline(&pts, false).to_bezpath_into(&mut bp);
|
||||
o.push(Overlay::Path { path: bp, color: FEEDBACK, width: 1.0, dashed: false });
|
||||
}
|
||||
if let Some((from, _)) = self.pts.last()
|
||||
&& cx.measurement_labels
|
||||
&& from.distance(h) > 1e-9
|
||||
|
||||
@@ -539,3 +539,51 @@ fn clicks_go_on_from_a_current_end_and_the_other_end_closes() {
|
||||
let a = press(&mut t, &quiet(&d, &s, &p), -50.0, 150.0, false);
|
||||
assert!(matches!(edit_op(&a[0]), Some(("extend", v)) if v["end"] == "start" && v["from"] == "keep"), "{a:?}");
|
||||
}
|
||||
|
||||
/// With Enable Rubber Band for the Curvature tool off, the preview curve is hidden but
|
||||
/// Measurement Labels still shows the readout, both while drawing a path and going on from the
|
||||
/// current end of a selected one.
|
||||
#[test]
|
||||
fn the_measurement_label_shows_with_the_rubber_band_off() {
|
||||
let p = paint();
|
||||
let measure =
|
||||
|o: &[Overlay]| o.iter().filter_map(|o| if let Overlay::Measure { text, .. } = o { Some(text.clone()) } else { None }).collect::<Vec<_>>();
|
||||
let band = |o: &[Overlay]| o.iter().any(|o| matches!(o, Overlay::Path { .. }));
|
||||
let to = pt(650.0, 60.0);
|
||||
// Going on from the current end of a selected path.
|
||||
let (d, id) = doc_with(wave());
|
||||
let s = selected(id, Some(4));
|
||||
let on = quiet(&d, &s, &p);
|
||||
let off = ToolContext { curvature_rubber_band: false, ..quiet(&d, &s, &p) };
|
||||
let mut t = CurvatureTool::default();
|
||||
t.pointer(&off, &PointerEvent::new(PointerKind::Move, to.x, to.y));
|
||||
let from = pt(450.0, 60.0);
|
||||
let o = t.overlays(&off);
|
||||
assert_eq!(measure(&o), vec![off.segment_measure_label(from, to)], "{o:?}");
|
||||
assert!(!band(&o), "{o:?}");
|
||||
let o = t.overlays(&on);
|
||||
assert_eq!(measure(&o), vec![on.segment_measure_label(from, to)], "{o:?}");
|
||||
assert!(band(&o), "{o:?}");
|
||||
// A path being drawn.
|
||||
let (d, id) = doc_with(SubPath::polyline(&[pt(100.0, 100.0), pt(200.0, 150.0)], false));
|
||||
let s = selected(id, None);
|
||||
let on = quiet(&d, &s, &p);
|
||||
let off = ToolContext { curvature_rubber_band: false, ..quiet(&d, &s, &p) };
|
||||
let mut t = CurvatureTool { id: Some(id), pts: vec![(pt(100.0, 100.0), false), (pt(200.0, 150.0), false)], ..CurvatureTool::default() };
|
||||
assert!(t.active(&off).is_some());
|
||||
t.pointer(&off, &PointerEvent::new(PointerKind::Move, to.x, to.y));
|
||||
let from = pt(200.0, 150.0);
|
||||
let o = t.overlays(&off);
|
||||
assert_eq!(measure(&o), vec![off.segment_measure_label(from, to)], "{o:?}");
|
||||
assert!(!band(&o), "{o:?}");
|
||||
let o = t.overlays(&on);
|
||||
assert_eq!(measure(&o), vec![on.segment_measure_label(from, to)], "{o:?}");
|
||||
assert!(band(&o), "{o:?}");
|
||||
for rubber in [true, false] {
|
||||
let unlabeled = ToolContext { curvature_rubber_band: rubber, measurement_labels: false, ..quiet(&d, &s, &p) };
|
||||
assert!(measure(&t.overlays(&unlabeled)).is_empty());
|
||||
}
|
||||
// Hovering exactly on the last point measures no segment.
|
||||
t.pointer(&off, &PointerEvent::new(PointerKind::Move, from.x, from.y));
|
||||
assert!(measure(&t.overlays(&off)).is_empty());
|
||||
}
|
||||
|
||||
+11
-9
@@ -495,19 +495,21 @@ impl Tool for PenTool {
|
||||
return t.overlays(cx);
|
||||
}
|
||||
let mut o = vec![];
|
||||
if cx.pen_rubber_band
|
||||
&& self.drag.is_none()
|
||||
// The rubber band preference hides only the preview segment; Measurement Labels decides the readout.
|
||||
if self.drag.is_none()
|
||||
&& self.handle.is_none()
|
||||
&& let (Some((id, _, _, last, out)), Some(h)) = (self.active(cx), self.hover)
|
||||
{
|
||||
let mut bp = BezPath::new();
|
||||
bp.move_to(last);
|
||||
if out.distance(last) > 1e-9 {
|
||||
bp.quad_to(out, h);
|
||||
} else {
|
||||
bp.line_to(h);
|
||||
if cx.pen_rubber_band {
|
||||
let mut bp = BezPath::new();
|
||||
bp.move_to(last);
|
||||
if out.distance(last) > 1e-9 {
|
||||
bp.quad_to(out, h);
|
||||
} else {
|
||||
bp.line_to(h);
|
||||
}
|
||||
o.push(Overlay::Path { path: bp, color: cx.doc.layer_color(id), width: 1.0, dashed: false });
|
||||
}
|
||||
o.push(Overlay::Path { path: bp, color: cx.doc.layer_color(id), width: 1.0, dashed: false });
|
||||
if cx.measurement_labels && last.distance(h) > 1e-9 {
|
||||
o.push(Overlay::Measure { p: h + Vec2::new(cx.tol(12.0), cx.tol(12.0)), text: cx.segment_measure_label(last, h) });
|
||||
}
|
||||
|
||||
@@ -773,6 +773,48 @@ fn anchors_snap_to_smart_guides() {
|
||||
assert_eq!(a[1], Action::Preview("path.create".into(), json!({"anchors": [{"x": 100.0, "y": 100.0}]})));
|
||||
}
|
||||
|
||||
/// With Enable Rubber Band off, the preview segment is hidden but Measurement Labels still shows
|
||||
/// the D / Angle / dX / dY readout at the snapped point before the next click.
|
||||
#[test]
|
||||
fn measurement_label_shows_with_the_rubber_band_off() {
|
||||
let (d, id, s) = drawing(vectorcraft_geom::SubPath::polyline(&[Point::new(10.0, 300.0), Point::new(60.0, 300.0)], false));
|
||||
let p = paint();
|
||||
let on = cx(&d, &s, &p);
|
||||
let off = ToolContext { pen_rubber_band: false, ..cx(&d, &s, &p) };
|
||||
let from = Point::new(60.0, 300.0);
|
||||
let to = Point::new(150.0, 318.0);
|
||||
let measure =
|
||||
|o: &[Overlay]| o.iter().filter_map(|o| if let Overlay::Measure { text, .. } = o { Some(text.clone()) } else { None }).collect::<Vec<_>>();
|
||||
let preview = |o: &[Overlay]| {
|
||||
o.iter().any(|o| matches!(o, Overlay::Path { path, .. } if path.elements().first().and_then(|e| e.end_point()) == Some(from)))
|
||||
};
|
||||
let mut t = PenTool { drawing: true, ..PenTool::default() };
|
||||
t.pointer(&off, &PointerEvent::new(PointerKind::Move, 152.0, 318.0));
|
||||
let o = t.overlays(&off);
|
||||
assert_eq!(measure(&o), vec![off.segment_measure_label(from, to)], "{o:?}");
|
||||
assert!(!preview(&o), "{o:?}");
|
||||
// The rubber band on still shows both.
|
||||
let o = t.overlays(&on);
|
||||
assert_eq!(measure(&o), vec![on.segment_measure_label(from, to)], "{o:?}");
|
||||
assert!(preview(&o), "{o:?}");
|
||||
// Measurement Labels off shows no readout either way.
|
||||
for band in [true, false] {
|
||||
let quiet = ToolContext { pen_rubber_band: band, measurement_labels: false, ..cx(&d, &s, &p) };
|
||||
assert!(measure(&t.overlays(&quiet)).is_empty());
|
||||
}
|
||||
// The click places the same anchor as with the rubber band on.
|
||||
let a = click(&mut t, &off, 152.0, 318.0, Mods::default());
|
||||
assert_eq!(a[1], Action::Preview("path.appendAnchor".into(), json!({"id": id.0, "x": 150.0, "y": 318.0, "subpath": 0})));
|
||||
// Hovering exactly on the last anchor measures no segment.
|
||||
let mut t = PenTool { drawing: true, ..PenTool::default() };
|
||||
t.pointer(&off, &PointerEvent::new(PointerKind::Move, 60.0, 300.0));
|
||||
assert!(measure(&t.overlays(&off)).is_empty());
|
||||
// With no path being drawn there is nothing to measure from.
|
||||
let mut t = PenTool::default();
|
||||
t.pointer(&off, &PointerEvent::new(PointerKind::Move, 152.0, 318.0));
|
||||
assert!(measure(&t.overlays(&off)).is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn alt_over_a_shown_handle_or_an_anchor_converts() {
|
||||
// The middle anchor is smooth: handles at (150, 100) and (250, 100) round (200, 100).
|
||||
|
||||
+2
-1
@@ -5439,7 +5439,8 @@ The Selection & Anchor Display and General preferences apply to `pointer_gesture
|
||||
scales it too; off (the default) it stays where it is. `artboard.duplicate`, `artboard.copy` and `artboard.cut` copy or
|
||||
cut locked and hidden art only with it on. A `lockedAndHidden` param on any of these commands takes its place.
|
||||
- `penRubberBand`, `curvatureRubberBand` (on by default): off, the Pen and Curvature tools draw no preview segment to
|
||||
the pointer.
|
||||
the pointer. With either off, the Pen, the Smart Pen (`penRubberBand`) and the Curvature tool (`curvatureRubberBand`)
|
||||
still show the D / Angle / dX / dY readout at the pointer while `measurementLabels` is on.
|
||||
- `showHandlesMultipleAnchors` (on by default): off, Direct Selection (and the Anchor Point tool, and the Pen with Alt)
|
||||
shows and drags direction handles only while a single anchor is selected. On, the handles of the direct-selected
|
||||
anchors, or of every anchor of a path selected as a whole, show and drag. `handleStyle` (`solid`, `hollow`, `large`) draws their ends (desktop app).
|
||||
|
||||
File diff suppressed because one or more lines are too long
+1
-1
@@ -235,7 +235,7 @@ tools, never checked side by side) isn't captured row by row.
|
||||
| "intersect" label and snapping to path intersections | partial | #1658 (part of #1602): a point drawn with the Pen, the shape tools or the other drawing tools and an anchor dragged with Direct Selection snap to where paths and ruler guides cross; a moved selection's own anchors and the Width tool don't |
|
||||
| Construction guides at preference angles while drawing | done | #506 |
|
||||
| Line extension: the dragged end of a straight segment snaps to the segment's own direction at any angle, past its other end or short of it, with the guide along it | done | #2120; Direct Selection and Curvature, one anchor dragged (with several, the move has no single direction); nearer the horizontal or vertical through the other end, the point lines up with it ("align"), so a nearly level segment can still be straightened |
|
||||
| Measurement labels while drawing, moving and resizing | done | sizes and offsets; the segment being drawn is labeled with its distance, angle and offsets by the Line Segment tool, and by the Pen, Curvature and Smart Pen tools with Enable Rubber Band on (#2983) |
|
||||
| Measurement labels while drawing, moving and resizing | done | sizes and offsets; the segment being drawn is labeled with its distance, angle and offsets by the Line Segment tool, and by the Pen, Curvature and Smart Pen tools with Enable Rubber Band on or off (#2983) |
|
||||
| Spacing guides (equal distances) | partial | for moves and bounding-box resizes (#394); not while drawing |
|
||||
| Distance Guides: Alt/Option over another object, or an empty part of an artboard, shows the selection's distances to it (Smart Guides › Invoke Distance Guides) | done | Selection tool hover with Smart Guides on: the gap between facing edges, else the offsets of matching edges, to another object; the left, right, top and bottom distances to the artboard; labelled in the General unit. The selection is measured as a whole. Nothing while moving or nudging, which the public pages don't describe. [Use Distance Guides](https://helpx.adobe.com/illustrator/desktop/measure-and-align/grids-and-guides/use-distance-guides-for-accurate-placement.html), [Smart Guides options](https://helpx.adobe.com/illustrator/desktop/measure-and-align/grids-and-guides/smart-guides-options.html) |
|
||||
| Snapping tolerance preference | done | |
|
||||
|
||||
Reference in New Issue
Block a user