From 23bcef97c7d1ebac7af2ca3941ec1ce7dd164fe0 Mon Sep 17 00:00:00 2001 From: Don Omondi <282319807+mockydevs@users.noreply.github.com> Date: Wed, 4 Nov 2026 21:20:51 -0500 Subject: [PATCH] Isolation mode: a locked or hidden layer keeps the isolated art from clicks and marquees (#5309) Locking or hiding the layer (or a group) around the isolated object left its art selectable with the Selection tool: the isolation branch of the hit test only checked for a locked artboard, and the marquee's checked nothing. Both now pass over isolated art that isn't editable. --- crates/doc/src/hit.rs | 8 ++++-- crates/engine/src/tests/compound_shape.rs | 32 +++++++++++++++++++++++ docs/ui-parity.md | 5 ++-- 3 files changed, 41 insertions(+), 4 deletions(-) diff --git a/crates/doc/src/hit.rs b/crates/doc/src/hit.rs index cb972b94f..8b498fd3d 100644 --- a/crates/doc/src/hit.rs +++ b/crates/doc/src/hit.rs @@ -508,8 +508,9 @@ fn hit_test_skipping(doc: &Document, p: Point, opt: HitOptions, skip: &dyn Fn(No && let Some(isolated) = doc.node(scope) && let Some(mut chain) = doc.ancestry(scope) { - // Isolated before its artboard was locked: nothing in it hits. - if locks.holds_id(scope) { + // Isolated before its artboard, or its layer or a group around it, was locked or hidden: + // nothing in it hits (#5309). + if !doc.is_editable_with(&locks, scope) { return None; } if isolated.is_container() { @@ -893,6 +894,9 @@ fn marquee_with(doc: &Document, r: Rect, scope: Option, leaves: bool, wh let mut out = Vec::new(); // `tops` pairs each object with the part of `r` in which the marquee can touch it. let tops: Vec<(&std::sync::Arc, Rect)> = match scope.and_then(|s| doc.node(s)) { + // Isolated art whose layer, or a group around it, was locked or hidden afterwards: the + // marquee touches none of it, as clicks don't (#5309). + Some(s) if !doc.is_editable(s.id) => vec![], Some(s) => match (s.children(), marquee_in(s, r)) { (Some(c), Some(r)) => c.iter().enumerate().filter(|(i, _)| !shaper_hides(s, *i, scope)).map(|(_, c)| (c, r)).collect(), (Some(_), None) => vec![], diff --git a/crates/engine/src/tests/compound_shape.rs b/crates/engine/src/tests/compound_shape.rs index 2de8a35b9..7455fbfa5 100644 --- a/crates/engine/src/tests/compound_shape.rs +++ b/crates/engine/src/tests/compound_shape.rs @@ -664,3 +664,35 @@ fn expanded(s: &mut Session, id: NodeId) -> f64 { let made = run(s, "object.compoundShape.expand", json!({})); node_area(&node(s, NodeId(made["ids"][0].as_u64().unwrap()))) } + +/// Locking (or hiding) the layer of an isolated compound shape locks its members too: a click or +/// a marquee with the Selection tool selects none of them, as outside isolation mode (#5309). +#[test] +fn a_locked_or_hidden_layer_keeps_the_isolated_compound_shape_from_clicks() { + use vectorcraft_tools::{PointerEvent, PointerKind}; + for (prop, value) in [("locked", true), ("visible", false)] { + let (mut s, back, _front) = two_squares(); + let id = NodeId(run(&mut s, "object.compoundShape.make", json!({}))["id"].as_u64().unwrap()); + run(&mut s, "object.isolate", json!({"id": id.0})); + let layer = s.doc().unwrap().doc.parent_of(id).unwrap(); + let v = ViewInfo::default(); + s.select_tool("selection", v).unwrap(); + let click = |s: &mut Session, x: f64, y: f64| { + for k in [PointerKind::Down, PointerKind::Up] { + s.pointer(&PointerEvent::new(k, x, y), v).unwrap(); + } + }; + click(&mut s, 25.0, 50.0); + assert_eq!(selected(&s), vec![back], "isolated, a click selects a member"); + run(&mut s, "select.none", json!({})); + run(&mut s, "layer.setProps", json!({"id": layer.0, prop: value})); + click(&mut s, 25.0, 50.0); + assert!(selected(&s).is_empty(), "{prop}: the layer's art isn't selected by a click"); + for (k, x, y) in + [(PointerKind::Down, -10.0, -10.0), (PointerKind::Drag, 60.0, 60.0), (PointerKind::Drag, 120.0, 120.0), (PointerKind::Up, 120.0, 120.0)] + { + s.pointer(&PointerEvent::new(k, x, y), v).unwrap(); + } + assert!(selected(&s).is_empty(), "{prop}: nor by a marquee"); + } +} diff --git a/docs/ui-parity.md b/docs/ui-parity.md index df62d6dd2..50cda9a08 100644 --- a/docs/ui-parity.md +++ b/docs/ui-parity.md @@ -1,6 +1,6 @@ # UI and interaction parity -> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-11-04 · **Change:** minor (Transform Each: Relative and Absolute scaling and the documented panel order; scores and estimates unchanged) · **Target:** Adobe Illustrator 2026 (30.x; Units › East Asian Type acts, with Q and Ha units; scores unchanged) · **Target:** Adobe Illustrator 2026 (30.x; Units › East Asian Type acts, with Q and Ha units; scores unchanged) +> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-11-04 · **Change:** minor (isolation mode: a locked or hidden layer keeps the isolated art from clicks and marquees; scores and estimates unchanged) · **Target:** Adobe Illustrator 2026 (30.x; Units › East Asian Type acts, with Q and Ha units; scores unchanged) · **Target:** Adobe Illustrator 2026 (30.x; Units › East Asian Type acts, with Q and Ha units; scores unchanged) ## Feature submission evidence @@ -30,6 +30,7 @@ Artboard Options forwards the active Artboard tool's Scale Artwork with Artboard | Date | Change | Summary | |---|---|---| +| 2026-11-04 | minor | Isolation mode: once the layer, or a group, around the isolated object is locked or hidden, a click or a marquee with the Selection tool no longer selects the isolated art (part of #5309); scores and estimates unchanged | | 2026-11-04 | minor | Transform Each's Scale has the documented Relative and Absolute radio buttons: percentages of each object's size, or the width and height it becomes (`object.transformEach` `relative`); the two scales have the link that keeps them in proportion (`__constrain`, as the shape dialogs'), and the panel lists Scale, Move, Rotate, the Options in two columns, the Reference Point and Preview (level with Copy, Cancel and OK) in the documented order; scores and estimates unchanged | | 2026-11-04 | minor | Cmd+Space pressed during an active drawing drag keeps that tool's cursor; clarify that Space can move an in-progress shape or anchor. Scores and estimates unchanged. | | 2026-11-04 | minor | Selection Tools add-on: Select by Artboards selects the objects overlapping, fully inside or fully outside several chosen artboards, from a dialog that lists, searches and multi-selects the artboards and fits one in the window on double-click (#5525, #5548, #5549, a VectorCraft addition); scores and estimates unchanged. | @@ -157,7 +158,7 @@ tools, never checked side by side) isn't captured row by row. | Live Corners widgets (radius readout, Alt-click cycles kind, double-click the Corners dialog) | done | a Direct Selection click on a widget selects its corner (#1239); a press-and-drag on a widget of a path selected whole still rounds every corner (#908), and adding widgets to the selection by Shift-click (#1232) is missing; the bounding box hides while a widget is dragged with the Selection tool (#1229); a round corner next to a curved side curves smoothly instead of sticking out of the shape (#1512); a corner rounds until its cut reaches its neighbours' cuts, so one corner of a square alone reaches the whole side (#2332) | | Corners between curved sides (#1144), Relative rounding | done | #1144 closed; Relative rounding in the Corners dialog (Relative / Absolute, radius as a percentage of each corner's maximum, kept as the shape is resized; `object.setLiveShape` `relativeRadii`, #3091, `tests_livecorners::relative_corner_rounding_keeps_fraction_on_resize`) | | Pie widgets on a live ellipse: drag one to set Pie Start or End Angle, double-click one to make the ellipse whole | done | Selection tool, with the bounding box showing | -| Isolation mode by double-click (groups and single objects), breadcrumbs, Esc to exit | done | Single paths, compound paths, images, meshes and placed files isolate too ([helpx: Isolate objects](https://helpx.adobe.com/africa/illustrator/desktop/manage-objects/select-objects/isolate-objects.html)) | +| Isolation mode by double-click (groups and single objects), breadcrumbs, Esc to exit | done | Single paths, compound paths, images, meshes and placed files isolate too ([helpx: Isolate objects](https://helpx.adobe.com/africa/illustrator/desktop/manage-objects/select-objects/isolate-objects.html)); locking or hiding the layer (or a group) around the isolated object afterwards keeps clicks and marquees off it, as outside isolation mode (#5309) | | "Magnetic" moves of selected anchors with a modifier (#955 request) | missing | not a feature of the reference app as documented; under discussion | | Coinciding anchors of overlapping objects: the selected object's anchor is taken, also under another object | done | #1508 |