From 71a67601a595c6084c05c12caa92f9ca6238fac0 Mon Sep 17 00:00:00 2001 From: dotCooCoo Date: Wed, 28 Oct 2026 02:22:42 -0700 Subject: [PATCH] Layers: Alt-click selects only on the drawn name, and in an isolated layer An Alt-click right of a short layer name, inside the wider rename target, no longer replaces the selection. The isolated layer's own row now selects the art inside it (layer.selectAll), where it cleared the selection before. The doc line says the click selects visible, unlocked art and clears the selection on a hidden or locked layer. --- crates/engine/src/cmd/layer.rs | 4 +++- crates/engine/src/tests/menucmds.rs | 14 ++++++++++++++ crates/ui-egui/src/panels/layers/rows.rs | 4 +++- crates/ui-egui/src/panels/layers/tests.rs | 14 ++++++++++++++ docs/target-app-parity.md | 2 +- 5 files changed, 35 insertions(+), 3 deletions(-) diff --git a/crates/engine/src/cmd/layer.rs b/crates/engine/src/cmd/layer.rs index 088d81e29..bcf742ffe 100644 --- a/crates/engine/src/cmd/layer.rs +++ b/crates/engine/src/cmd/layer.rs @@ -673,7 +673,9 @@ fn select_art(s: &mut Session, p: &Value) -> Result { let add = switch_or(p, "add", false, C)?; let st = s.doc()?; let n = st.doc.node(id).ok_or(EngineError::NoNode(id))?; - let ids: Vec = if !st.doc.is_editable(id) || !in_isolation(&st.doc, st.isolation, id) { + // An isolated layer's own row selects the art inside it. + let isolated_layer = st.isolation == Some(id) && n.is_layer(); + let ids: Vec = if !st.doc.is_editable(id) || !(isolated_layer || in_isolation(&st.doc, st.isolation, id)) { vec![] } else if n.is_layer() { n.layer_art(true) diff --git a/crates/engine/src/tests/menucmds.rs b/crates/engine/src/tests/menucmds.rs index a1672d65c..c02314b96 100644 --- a/crates/engine/src/tests/menucmds.rs +++ b/crates/engine/src/tests/menucmds.rs @@ -1602,6 +1602,20 @@ fn layers_panel_selects_nothing_outside_the_isolated_group() { assert_eq!(selected(&s), vec![b]); } +/// In isolation mode the selection column of the isolated layer's own row selects the art on it. +#[test] +fn layers_panel_selects_the_art_of_the_isolated_layer() { + let mut s = session(); + let a = rect(&mut s, 0.0, 0.0, 50.0, 50.0); + let b = rect(&mut s, 100.0, 0.0, 50.0, 50.0); + let layer = s.active().unwrap().doc.layers[0].id; + s.execute("object.isolate", &json!({"id": layer.0})).unwrap(); + s.execute("layer.selectAll", &json!({"id": layer.0})).unwrap(); + let mut got = selected(&s); + got.sort_by_key(|i| i.0); + assert_eq!(got, vec![a, b]); +} + /// In isolation mode a recalled selection leaves out the objects outside the isolated group, and /// Next Object Above selects nothing outside it. #[test] diff --git a/crates/ui-egui/src/panels/layers/rows.rs b/crates/ui-egui/src/panels/layers/rows.rs index 76f780dcb..94a231c23 100644 --- a/crates/ui-egui/src/panels/layers/rows.rs +++ b/crates/ui-egui/src/panels/layers/rows.rs @@ -318,7 +318,9 @@ pub(super) fn row(ui: &mut Ui, view: &View, item: &Row, out: &mut Out) { } else if resp.clicked() { out.click = Some((n.id, m)); // Alt-click on a layer's or sublayer's name also selects its art, as its selection square does. - if m.alt && !m.shift && !m.command && n.is_layer() && on_name { + // Only the drawn text counts, not the wider rename target of a short name. + let on_text = ui.input(|i| i.pointer.interact_pos()).is_some_and(|p| p.x >= name_rect.left() && p.x <= name_end.min(name_rect.right())); + if m.alt && !m.shift && !m.command && n.is_layer() && on_text { out.actions.push(("layer.selectAll".into(), json!({"id": n.id.0}))); } } diff --git a/crates/ui-egui/src/panels/layers/tests.rs b/crates/ui-egui/src/panels/layers/tests.rs index ec94adc44..e46df1a06 100644 --- a/crates/ui-egui/src/panels/layers/tests.rs +++ b/crates/ui-egui/src/panels/layers/tests.rs @@ -574,6 +574,20 @@ fn alt_clicking_a_layer_name_selects_its_art() { assert_eq!(state(&app).0, vec![], "Ctrl/Cmd+Alt"); } +/// Alt-click right of a one-letter layer name, inside the wider rename target, selects nothing. +#[test] +fn alt_clicking_beside_a_short_layer_name_selects_nothing() { + let (mut app, [_, sub, ..]) = nested(); + app.session.execute("layer.setProps", &json!({"ids": [sub.0], "name": "I"})).unwrap(); + let ctx = egui::Context::default(); + let (circles, _) = frame(&mut app, &ctx, vec![], false); + // The sublayer's name area starts here; "I" ends about 5 points in, the rename target 20 points in. + let name_left = 2.0 * COLUMN + 2.0 + 6.0 + INDENT + 40.0; + click_with(&mut app, &ctx, egui::pos2(name_left + 14.0, circles[1].y), egui::Modifiers::ALT); + let st = app.session.active().unwrap(); + assert_eq!((st.selection.objects.clone(), st.current_layer()), (vec![], Some(sub))); +} + #[test] fn eye_and_lock_toggle_nested_rows_and_drag_down_the_column() { let (mut app, [_, sub, g, b, a, _]) = nested(); diff --git a/docs/target-app-parity.md b/docs/target-app-parity.md index 9b53e3f84..8735f90b7 100644 --- a/docs/target-app-parity.md +++ b/docs/target-app-parity.md @@ -709,7 +709,7 @@ Moved from the ROADMAP's "Shipped so far" on 2026-10-10. Update it when a featur The panel menu's Save Selection submenu has Save Selection…, Update Selection and Edit Selection…, enabled and run as in the Select menu, and lists the document's saved selections: choosing one selects its objects again (`select.recall`). `object.setProps` with `visible: false` or `locked: true` deselects every selected object that is then hidden or locked, the key object included, as the eye and lock columns do. Ctrl/Cmd+Alt-clicking an eye switches the other layers to Outline and the row's layer to Preview, or switches all layers back to Preview when the others are in Outline (`layer.outlineOthers`, `layer.previewAll`). - Alt-clicking a layer's or sublayer's name makes it the current layer, as a click does, and selects its art, as its selection square does (`layer.selectAll`, then `layer.setCurrent`). The reference app's [Default keyboard shortcuts](https://web.archive.org/web/20260726060015/https://helpx.adobe.com/illustrator/using/default-keyboard-shortcuts.html) page lists Alt-click on the layer name for selecting all objects on the layer. + Alt-clicking a layer's or sublayer's name makes it the current layer, as a click does, and selects its visible, unlocked art, as its selection square does (`layer.selectAll`, then `layer.setCurrent`); on a hidden or locked layer it clears the selection. The reference app's [Default keyboard shortcuts](https://web.archive.org/web/20260726060015/https://helpx.adobe.com/illustrator/using/default-keyboard-shortcuts.html) page lists Alt-click on the layer name for selecting all objects on the layer. Object › Arrange › Send to Current Layer returns the error "the target layer is locked or hidden" and leaves the selected objects where they are when the current layer is hidden or locked, or is inside a hidden or locked layer. Selected objects are deselected, the key object included, when a row drag moves them into a hidden layer or group, when `node.move` moves them into a hidden or locked layer or group, when Merge Selected moves them into a hidden or locked layer, when Collect in New Layer moves them into a new layer inside a hidden or locked layer, when Flatten Artwork moves them into a locked layer, and when applying a data set hides them. Panel Options › Locate Selected Objects (beyond Illustrator, off by default): when the last selected object changes on the canvas or by a command, the panel opens the layers and groups around it and scrolls to its row, as Locate Object does, without highlighting the row; when Show Layers Only, a search or the filter leaves the object without a row, the panel opens no rows for it and scrolls as with the option off.