mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-31 05:07:51 -06:00
Object: Unlock All and Show All with Shift+Alt act only within the selected object's group
Squashed from #4439 onto main.
This commit is contained in:
@@ -26,8 +26,8 @@ fn preview_bounds(s: &Session, p: &Value, cmd: &str) -> Result<bool> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Param `key` of the Align commands, Shear and `text.setFormat`'s lists: one of `values`, or
|
||||
/// `None` when it is missing or null. Any other value is an error that lists `values`.
|
||||
/// Param `key` of the Align commands, Shear, Unlock All, Show All and `text.setFormat`'s lists: one
|
||||
/// of `values`, or `None` when it is missing or null. Any other value is an error that lists `values`.
|
||||
pub(crate) fn choice<'a>(p: &'a Value, cmd: &str, key: &str, values: &[&str]) -> Result<Option<&'a str>> {
|
||||
let Some(v) = p.get(key).filter(|v| !v.is_null()) else { return Ok(None) };
|
||||
match v.as_str() {
|
||||
|
||||
@@ -172,8 +172,42 @@ fn collect_flag(d: &Document, f: impl Fn(&Node) -> bool) -> Vec<NodeId> {
|
||||
v
|
||||
}
|
||||
|
||||
pub(super) fn unlock_all(s: &mut Session, _: &Value) -> Result<Value> {
|
||||
let ids = collect_flag(&s.doc()?.doc, |n| n.locked);
|
||||
/// 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.
|
||||
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") {
|
||||
return Ok(collect_flag(d, f));
|
||||
}
|
||||
let is_group = |id: &NodeId| d.node(*id).is_some_and(|n| matches!(n.kind, NodeKind::Group { .. }));
|
||||
let mut groups: Vec<NodeId> = st.selection.objects.iter().filter_map(|id| d.ancestry(*id)?.into_iter().rev().find(is_group)).collect();
|
||||
groups.sort();
|
||||
groups.dedup();
|
||||
if groups.is_empty() {
|
||||
return Err(EngineError::Other("nothing selected is in a group".into()));
|
||||
}
|
||||
let mut v = vec![];
|
||||
for g in &groups {
|
||||
if d.ancestry(*g).is_some_and(|a| a.iter().any(|up| up != g && groups.contains(up))) {
|
||||
continue;
|
||||
}
|
||||
for c in d.node(*g).and_then(Node::children).into_iter().flatten() {
|
||||
c.walk(&mut |n| {
|
||||
if !n.is_layer() && f(n) {
|
||||
v.push(n.id)
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
Ok(v)
|
||||
}
|
||||
|
||||
pub(super) fn unlock_all(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
let ids = collect_flag_in_scope(s, "object.unlockAll", p, |n| n.locked)?;
|
||||
// With nothing locked, the document, the selection and the undo history stay as they are.
|
||||
if ids.is_empty() {
|
||||
return Ok(json!({ "count": 0 }));
|
||||
@@ -211,8 +245,8 @@ pub(super) fn hide(s: &mut Session, _: &Value) -> Result<Value> {
|
||||
ok()
|
||||
}
|
||||
|
||||
pub(super) fn show_all(s: &mut Session, _: &Value) -> Result<Value> {
|
||||
let ids = collect_flag(&s.doc()?.doc, |n| !n.visible);
|
||||
pub(super) fn show_all(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
let ids = collect_flag_in_scope(s, "object.showAll", p, |n| !n.visible)?;
|
||||
// With nothing hidden, the document, the selection and the undo history stay as they are.
|
||||
if ids.is_empty() {
|
||||
return Ok(json!({ "count": 0 }));
|
||||
|
||||
@@ -154,7 +154,15 @@ pub fn specs() -> Vec<CommandSpec> {
|
||||
has_selection_outside_isolation,
|
||||
lock
|
||||
),
|
||||
cmd!("object.unlockAll", "Unlock All", ["Object"], Some("Cmd+Alt+2"), "{}", outside_isolation, unlock_all),
|
||||
cmd!(
|
||||
"object.unlockAll",
|
||||
"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,
|
||||
unlock_all
|
||||
),
|
||||
cmd!(
|
||||
"object.hide",
|
||||
"Selection",
|
||||
@@ -164,7 +172,15 @@ pub fn specs() -> Vec<CommandSpec> {
|
||||
has_selection_outside_isolation,
|
||||
hide
|
||||
),
|
||||
cmd!("object.showAll", "Show All", ["Object"], Some("Cmd+Alt+3"), "{}", outside_isolation, show_all),
|
||||
cmd!(
|
||||
"object.showAll",
|
||||
"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,
|
||||
show_all
|
||||
),
|
||||
cmd!(
|
||||
"object.compoundPath.make",
|
||||
"Make",
|
||||
|
||||
Reference in New Issue
Block a user