Isolation mode: Lock, Unlock All, Hide and Show All work on the isolated art

Squashed from #4849 onto main.
This commit is contained in:
dotCooCoo
2026-11-01 01:21:53 +07:00
committed by bflatastic
parent f1a6a9ff67
commit b46cdc4e4d
12 changed files with 511 additions and 226 deletions
+34 -6
View File
@@ -143,7 +143,7 @@ pub(super) fn ungroup(s: &mut Session, _: &Value) -> Result<Value> {
}
pub(super) fn lock(s: &mut Session, _: &Value) -> Result<Value> {
let ids = selected_roots(s)?;
let ids = selected_lock_hide_roots(s)?;
// With every selected object already locked, the document and its undo history stay as they
// are, and the objects are deselected.
let d = &s.doc()?.doc;
@@ -163,6 +163,16 @@ pub(super) fn lock(s: &mut Session, _: &Value) -> Result<Value> {
ok()
}
/// The selected objects ([`selected_roots`]) that Lock › Selection and Hide › Selection change: in
/// isolation mode, only those inside the isolated object, where a path of the isolated compound
/// path is an object of its own.
fn selected_lock_hide_roots(s: &Session) -> Result<Vec<NodeId>> {
match crate::cmd::ordinary_isolation(s.doc()?) {
Some(root) => crate::cmd::edit::selected_roots_inside(s, root, false),
None => selected_roots(s),
}
}
fn collect_flag(d: &Document, f: impl Fn(&Node) -> bool) -> Vec<NodeId> {
let mut v = vec![];
d.walk(|n| {
@@ -174,14 +184,28 @@ fn collect_flag(d: &Document, f: impl Fn(&Node) -> bool) -> Vec<NodeId> {
}
/// The objects that `f` picks for `object.unlockAll` and `object.showAll` (`cmd`): in the whole
/// document, or with `scope: "group"` inside the groups that hold the selected objects. A selected
/// group is the group that holds its own members, and the objects of a group inside another such
/// group are taken once. With `scope: "group"` and no selected object in a group, it returns an
/// error.
/// document, inside the isolated object in isolation mode, or with `scope: "group"` inside the
/// groups that hold the selected objects (in isolation mode, only the objects of those groups
/// that are inside the isolated object). A selected group is the group that holds its own
/// members, and the objects of a group inside another such group are taken once. With
/// `scope: "group"` and no selected object in a group, it returns an error.
fn collect_flag_in_scope(s: &Session, cmd: &str, p: &Value, f: impl Fn(&Node) -> bool) -> Result<Vec<NodeId>> {
let st = s.doc()?;
let d = &st.doc;
if choice(p, cmd, "scope", &["document", "group"])? != Some("group") {
if let Some(root) = crate::cmd::ordinary_isolation(st) {
let mut ids = vec![];
if let Some(node) = d.node(root) {
for child in node.children().into_iter().flatten() {
child.walk(&mut |n| {
if !n.is_layer() && f(n) {
ids.push(n.id);
}
});
}
}
return Ok(ids);
}
return Ok(collect_flag(d, f));
}
let is_group = |id: &NodeId| d.node(*id).is_some_and(|n| matches!(n.kind, NodeKind::Group { .. }));
@@ -204,6 +228,10 @@ fn collect_flag_in_scope(s: &Session, cmd: &str, p: &Value, f: impl Fn(&Node) ->
});
}
}
// In isolation mode only the objects inside the isolated object are taken.
if let Some(root) = crate::cmd::ordinary_isolation(st) {
v.retain(|id| crate::cmd::inside_isolation(d, root, *id));
}
Ok(v)
}
@@ -226,7 +254,7 @@ pub(super) fn unlock_all(s: &mut Session, p: &Value) -> Result<Value> {
}
pub(super) fn hide(s: &mut Session, _: &Value) -> Result<Value> {
let ids = selected_roots(s)?;
let ids = selected_lock_hide_roots(s)?;
// With every selected object already hidden, the document and its undo history stay as they
// are, and the objects are deselected.
let d = &s.doc()?.doc;
+9 -9
View File
@@ -6,7 +6,7 @@ use super::props::set_props;
use super::shape::{expand_shape, set_live_shape};
use super::transform::{move_cmd, nudge, reflect, rotate, scale, shear, transform, transform_again};
use super::{CommandSpec, cmd, has_doc, has_multi, has_selection, has_selection_or_guides};
use crate::cmd::{has_selection_outside_isolation, outside_isolation};
use crate::cmd::has_selected_member;
pub fn specs() -> Vec<CommandSpec> {
vec![
@@ -150,8 +150,8 @@ pub fn specs() -> Vec<CommandSpec> {
"Selection",
["Object", "Lock"],
Some("Cmd+2"),
"{ids?: [id…] (selected first; default: the selection)}",
has_selection_outside_isolation,
"{ids?: [id…] (selected first; default: the selection; in isolation mode, only those inside the isolated object)}",
has_selected_member,
lock
),
cmd!(
@@ -159,8 +159,8 @@ pub fn specs() -> Vec<CommandSpec> {
"Unlock All",
["Object"],
Some("Cmd+Alt+2"),
"{scope?: \"document\"|\"group\" (default document; group: only the objects inside the groups that hold the selected objects, a selected group holding its own; the in-window menu item chosen with Shift+Alt)} unlock the locked objects and select them → {count}",
outside_isolation,
"{scope?: \"document\"|\"group\" (default document, which in isolation mode is the isolated object; group: only the objects inside the groups that hold the selected objects, a selected group holding its own; the in-window menu item chosen with Shift+Alt)} unlock the locked objects and select them → {count}",
has_doc,
unlock_all
),
cmd!(
@@ -168,8 +168,8 @@ pub fn specs() -> Vec<CommandSpec> {
"Selection",
["Object", "Hide"],
Some("Cmd+3"),
"{ids?: [id…] (selected first; default: the selection)}",
has_selection_outside_isolation,
"{ids?: [id…] (selected first; default: the selection; in isolation mode, only those inside the isolated object)}",
has_selected_member,
hide
),
cmd!(
@@ -177,8 +177,8 @@ pub fn specs() -> Vec<CommandSpec> {
"Show All",
["Object"],
Some("Cmd+Alt+3"),
"{scope?: \"document\"|\"group\" (default document; group: only the objects inside the groups that hold the selected objects, a selected group holding its own; the in-window menu item chosen with Shift+Alt)} show the hidden objects and select them → {count}",
outside_isolation,
"{scope?: \"document\"|\"group\" (default document, which in isolation mode is the isolated object; group: only the objects inside the groups that hold the selected objects, a selected group holding its own; the in-window menu item chosen with Shift+Alt)} show the hidden objects and select them → {count}",
has_doc,
show_all
),
cmd!(