mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-29 12:17:14 -06:00
Merge pull request #4439 from dotCooCoo/feat/unlock-show-all-within-group
Object: Unlock All and Show All with Shift+Alt act only within the selected object's group
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() {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use super::align::choice;
|
||||
use super::{Document, EngineError, Node, NodeId, NodeKind, Result, Session, Value, bad, id_param, json, ok, selected_roots};
|
||||
|
||||
pub(super) enum Arrange {
|
||||
@@ -172,8 +173,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 +246,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",
|
||||
|
||||
@@ -1671,6 +1671,71 @@ fn lock_hide_unlock_all_and_show_all_with_nothing_to_do_record_no_undo_step() {
|
||||
}
|
||||
}
|
||||
|
||||
/// Unlock All and Show All with `scope: "group"` unlock or show only the objects inside the groups
|
||||
/// that hold the selected objects: the group nearest above a selected object, or a selected group
|
||||
/// itself. With no selected object in a group they are refused and change nothing.
|
||||
#[test]
|
||||
fn unlock_all_and_show_all_within_the_groups_of_the_selection() {
|
||||
let mut s = session();
|
||||
let ids = |s: &mut Session, cmd: &str| NodeId(s.execute(cmd, &json!({})).unwrap()["id"].as_u64().unwrap());
|
||||
let [a, b, m, k, h, s1, s2, j, j2] = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0].map(|i| rect(&mut s, i * 30.0, 0.0, 20.0, 20.0));
|
||||
// `g` holds `m`, `k`, `h` and the group `sub`, which holds `s1` and `s2`; `other` holds `j` and `j2`.
|
||||
s.execute("select.set", &json!({"ids": [s1.0, s2.0]})).unwrap();
|
||||
let sub = ids(&mut s, "object.group");
|
||||
s.execute("select.set", &json!({"ids": [m.0, k.0, h.0, sub.0]})).unwrap();
|
||||
let g = ids(&mut s, "object.group");
|
||||
s.execute("select.set", &json!({"ids": [j.0, j2.0]})).unwrap();
|
||||
let other = ids(&mut s, "object.group");
|
||||
for id in [a, k, s1, j] {
|
||||
s.execute("layer.setProps", &json!({"id": id.0, "locked": true})).unwrap();
|
||||
}
|
||||
s.execute("layer.setProps", &json!({"id": h.0, "visible": false})).unwrap();
|
||||
let locked = |s: &Session| [a, k, s1, j].map(|id| s.doc().unwrap().doc.node(id).unwrap().locked);
|
||||
let group = json!({"scope": "group"});
|
||||
|
||||
// A member of `g`, or `g` itself, selected: `k` and `s1` inside `sub` are unlocked and selected.
|
||||
for selected in [m, g] {
|
||||
s.execute("select.set", &json!({"ids": [selected.0]})).unwrap();
|
||||
let before = history(&s);
|
||||
assert_eq!(s.execute("object.unlockAll", &group).unwrap(), json!({"count": 2}), "{selected:?}");
|
||||
assert_eq!(locked(&s), [true, false, false, true], "{selected:?}");
|
||||
assert_eq!(s.doc().unwrap().selection.objects, [k, s1], "{selected:?}");
|
||||
assert_eq!(history(&s).0, before.0 + 1, "{selected:?}");
|
||||
s.execute("edit.undo", &json!({})).unwrap();
|
||||
}
|
||||
// `s2` selected: only `sub` counts. With `m` selected too, `sub`'s objects are taken once.
|
||||
for (selected, count) in [(vec![s2.0], 1), (vec![m.0, s2.0], 2)] {
|
||||
s.execute("select.set", &json!({"ids": selected})).unwrap();
|
||||
assert_eq!(s.execute("object.unlockAll", &group).unwrap(), json!({"count": count}), "{selected:?}");
|
||||
assert!(!s.doc().unwrap().doc.node(s1).unwrap().locked, "{selected:?}");
|
||||
s.execute("edit.undo", &json!({})).unwrap();
|
||||
}
|
||||
// Show All within `g` shows `h` and selects it; `other` holds nothing hidden.
|
||||
s.execute("select.set", &json!({"ids": [m.0]})).unwrap();
|
||||
assert_eq!(s.execute("object.showAll", &group).unwrap(), json!({"count": 1}));
|
||||
assert_eq!(s.doc().unwrap().selection.objects, [h]);
|
||||
s.execute("edit.undo", &json!({})).unwrap();
|
||||
s.execute("select.set", &json!({"ids": [other.0]})).unwrap();
|
||||
assert_eq!(s.execute("object.showAll", &group).unwrap(), json!({"count": 0}));
|
||||
|
||||
// `b`, outside every group, or nothing selected: refused, and nothing changes.
|
||||
for selected in [vec![b.0], vec![]] {
|
||||
s.execute("select.set", &json!({"ids": selected})).unwrap();
|
||||
let (doc, before) = (s.doc().unwrap().doc.clone(), history(&s));
|
||||
for cmd in ["object.unlockAll", "object.showAll"] {
|
||||
let e = s.execute(cmd, &group).unwrap_err();
|
||||
assert!(matches!(&e, EngineError::Other(msg) if msg == "nothing selected is in a group"), "{cmd}: {e:?}");
|
||||
}
|
||||
assert!(s.doc().unwrap().doc == doc && history(&s) == before, "{selected:?}");
|
||||
}
|
||||
// Any other scope is refused; `scope: "document"` and no scope take the whole document.
|
||||
let e = s.execute("object.unlockAll", &json!({"scope": "layer"})).unwrap_err();
|
||||
assert!(matches!(&e, EngineError::BadParams { msg, .. } if msg == "`scope` must be one of document, group"), "{e:?}");
|
||||
assert_eq!(s.execute("object.unlockAll", &json!({"scope": "document"})).unwrap(), json!({"count": 4}));
|
||||
s.execute("edit.undo", &json!({})).unwrap();
|
||||
assert_eq!(s.execute("object.showAll", &json!({})).unwrap(), json!({"count": 1}));
|
||||
}
|
||||
|
||||
/// Set Bounds with the current position and size records no undo step on a rotated object, with
|
||||
/// and without Use Preview Bounds, and on an unrotated object with Use Preview Bounds. In these
|
||||
/// cases computing the transform can leave a rounding error in it.
|
||||
|
||||
@@ -4088,6 +4088,7 @@ axis Both И двете
|
||||
@msg not in pattern editing mode не е в режим на редактиране на мостра
|
||||
@msg nothing encoded нищо не е кодирано
|
||||
@msg nothing selected нищо не е избрано
|
||||
@msg nothing selected is in a group нищо от избраното не е в група
|
||||
@msg nothing to align няма нищо за подравняване
|
||||
@msg nothing to distort няма нищо за изкривяване
|
||||
@msg nothing to export: the document has no visible art (or turn on Use Artboards) няма нищо за експортиране: документът няма видима графика (или включете „Използване на работни области“)
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4488,6 +4488,7 @@ imageTrace Outline Obrys
|
||||
@msg not in pattern editing mode není aktivní režim úprav vzorku
|
||||
@msg nothing encoded nic nebylo zakódováno
|
||||
@msg nothing selected nic není vybráno
|
||||
@msg nothing selected is in a group nic z výběru není ve skupině
|
||||
@msg nothing to align není co zarovnat
|
||||
@msg nothing to distort není co deformovat
|
||||
@msg nothing to export: the document has no visible art (or turn on Use Artboards) není co exportovat: dokument nemá žádnou viditelnou kresbu (nebo zapněte Použít pracovní plochy)
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4193,6 +4193,7 @@ imageTrace Outline Kontur
|
||||
@msg not in pattern editing mode ikke i mønsterredigeringstilstand
|
||||
@msg nothing encoded intet kodet
|
||||
@msg nothing selected intet markeret
|
||||
@msg nothing selected is in a group intet af det markerede er i en gruppe
|
||||
@msg nothing to align intet at justere
|
||||
@msg nothing to distort intet at forvrænge
|
||||
@msg nothing to export: the document has no visible art (or turn on Use Artboards) intet at eksportere: dokumentet har ingen synlig grafik (eller aktivér Brug artboards)
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4111,6 +4111,7 @@ theme Appearance Erscheinungsbild
|
||||
@msg not in pattern editing mode nicht im Musterbearbeitungsmodus
|
||||
@msg nothing encoded nichts kodiert
|
||||
@msg nothing selected nichts ausgewählt
|
||||
@msg nothing selected is in a group nichts Ausgewähltes befindet sich in einer Gruppe
|
||||
@msg nothing to align nichts auszurichten
|
||||
@msg nothing to distort nichts zu verzerren
|
||||
@msg nothing to export: the document has no visible art (or turn on Use Artboards) nichts zu exportieren: Das Dokument enthält keine sichtbare Grafik (oder aktivieren Sie „Zeichenflächen verwenden“)
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4150,6 +4150,7 @@ theme Appearance Εμφάνιση
|
||||
@msg not in pattern editing mode δεν βρίσκεστε σε λειτουργία επεξεργασίας μοτίβου
|
||||
@msg nothing encoded δεν κωδικοποιήθηκε τίποτα
|
||||
@msg nothing selected δεν έχει επιλεγεί τίποτα
|
||||
@msg nothing selected is in a group τίποτα από τα επιλεγμένα δεν βρίσκεται σε ομάδα
|
||||
@msg nothing to align δεν υπάρχει τίποτα για στοίχιση
|
||||
@msg nothing to distort δεν υπάρχει τίποτα για παραμόρφωση
|
||||
@msg nothing to export: the document has no visible art (or turn on Use Artboards) δεν υπάρχει τίποτα για εξαγωγή: το έγγραφο δεν έχει ορατό σχέδιο (ή ενεργοποιήστε Χρήση πινάκων σχεδίασης)
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2070 and column 19.
|
@@ -4186,6 +4186,7 @@ axis Both Ambos
|
||||
@msg not in pattern editing mode no está en el modo de edición de motivos
|
||||
@msg nothing encoded no se codificó nada
|
||||
@msg nothing selected no hay nada seleccionado
|
||||
@msg nothing selected is in a group nada de lo seleccionado está en un grupo
|
||||
@msg nothing to align no hay nada que alinear
|
||||
@msg nothing to distort no hay nada que distorsionar
|
||||
@msg nothing to export: the document has no visible art (or turn on Use Artboards) no hay nada que exportar: el documento no tiene ilustración visible (o activa Usar mesas de trabajo)
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4401,6 +4401,7 @@ imageTrace Outline Ääriviiva
|
||||
@msg not in pattern editing mode ei kuvion muokkaustilassa
|
||||
@msg nothing encoded mitään ei koodattu
|
||||
@msg nothing selected mitään ei ole valittu
|
||||
@msg nothing selected is in a group mikään valituista ei ole ryhmässä
|
||||
@msg nothing to align ei tasattavaa
|
||||
@msg nothing to distort ei vääristettävää
|
||||
@msg nothing to export: the document has no visible art (or turn on Use Artboards) ei vietävää: asiakirjassa ei ole näkyvää kuvitusta (tai ota Käytä piirtoalustoja käyttöön)
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4183,6 +4183,7 @@ axis Both Les deux
|
||||
@msg not in pattern editing mode pas en mode d’édition de motif
|
||||
@msg nothing encoded rien n’a été encodé
|
||||
@msg nothing selected aucune sélection
|
||||
@msg nothing selected is in a group aucun élément sélectionné ne se trouve dans un groupe
|
||||
@msg nothing to align rien à aligner
|
||||
@msg nothing to distort rien à déformer
|
||||
@msg nothing to export: the document has no visible art (or turn on Use Artboards) rien à exporter : le document n’a aucune illustration visible (ou activez Utiliser les plans de travail)
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4855,6 +4855,7 @@ imageTrace Outline Körvonal
|
||||
@msg not in pattern editing mode nem mintázatszerkesztő módban vagy
|
||||
@msg nothing encoded nincs kódolt adat
|
||||
@msg nothing selected nincs kijelölés
|
||||
@msg nothing selected is in a group a kijelölésből semmi sincs csoportban
|
||||
@msg nothing to align nincs mit igazítani
|
||||
@msg nothing to distort nincs mit torzítani
|
||||
@msg nothing to export: the document has no visible art (or turn on Use Artboards) nincs mit exportálni: a dokumentumban nincs látható grafika (vagy kapcsold be a Rajztáblák használata beállítást)
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4193,6 +4193,7 @@ imageTrace Outline Kontur
|
||||
@msg not in pattern editing mode tidak dalam mode pengeditan pola
|
||||
@msg nothing encoded tidak ada yang dikodekan
|
||||
@msg nothing selected tidak ada yang dipilih
|
||||
@msg nothing selected is in a group tidak ada yang dipilih yang berada dalam grup
|
||||
@msg nothing to align tidak ada yang dapat disejajarkan
|
||||
@msg nothing to distort tidak ada yang dapat didistorsi
|
||||
@msg nothing to export: the document has no visible art (or turn on Use Artboards) tidak ada yang dapat diekspor: dokumen tidak memiliki karya seni yang terlihat (atau aktifkan Gunakan Artboard)
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 3857 and column 19.
|
@@ -4226,6 +4226,7 @@ axis Both Entrambi
|
||||
@msg not in pattern editing mode non sei in modalità modifica motivo
|
||||
@msg nothing encoded nessun dato codificato
|
||||
@msg nothing selected nessuna selezione
|
||||
@msg nothing selected is in a group nessun elemento selezionato si trova in un gruppo
|
||||
@msg nothing to align niente da allineare
|
||||
@msg nothing to distort niente da distorcere
|
||||
@msg nothing to export: the document has no visible art (or turn on Use Artboards) niente da esportare: il documento non ha grafica visibile (oppure attiva Usa tavole da disegno)
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4554,6 +4554,7 @@ swatch Bright Violet ビビッドバイオレット
|
||||
@msg Couldn't copy to the system clipboard: {e} システムのクリップボードにコピーできませんでした: {e}
|
||||
@msg Couldn't paste from the clipboard: {e} クリップボードから貼り付けられませんでした: {e}
|
||||
@msg nothing selected 何も選択されていません
|
||||
@msg nothing selected is in a group 選択したオブジェクトはどれもグループ内にありません
|
||||
@msg the {tool} tool has no options {tool} ツールにはオプションがありません
|
||||
@msg unknown tool `{tool}` `{tool}` は不明なツールです
|
||||
@msg {tool} isn't in a toolbar group of several tools {tool} は複数のツールからなるツールグループに含まれていません
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -3960,6 +3960,7 @@ font-technology Variable ცვლადი
|
||||
@msg not in pattern editing mode პატერნის რედაქტირების რეჟიმი არ არის ჩართული
|
||||
@msg nothing encoded არაფერია კოდირებული
|
||||
@msg nothing selected არაფერია მონიშნული
|
||||
@msg nothing selected is in a group მონიშნულთაგან არაფერია ჯგუფში
|
||||
@msg nothing to align გასასწორებელი არაფერია
|
||||
@msg nothing to distort დასადეფორმირებელი არაფერია
|
||||
@msg nothing to export: the document has no visible art (or turn on Use Artboards) ექსპორტისთვის არაფერია: დოკუმენტს ხილული ნახატი არ აქვს (ან ჩართეთ სამუშაო დაფების გამოყენება)
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4486,6 +4486,7 @@ theme Appearance 외관
|
||||
@msg Couldn't copy to the system clipboard: {e} 시스템 클립보드로 복사할 수 없습니다: {e}
|
||||
@msg Couldn't paste from the clipboard: {e} 클립보드에서 붙여넣을 수 없습니다: {e}
|
||||
@msg nothing selected 선택된 항목이 없습니다
|
||||
@msg nothing selected is in a group 선택한 항목 중 그룹에 속한 항목이 없습니다
|
||||
@msg the {tool} tool has no options {tool} 도구에는 옵션이 없습니다
|
||||
@msg unknown tool `{tool}` 알 수 없는 도구 `{tool}`
|
||||
@msg {tool} isn't in a toolbar group of several tools {tool}은(는) 여러 도구가 있는 도구 모음 그룹에 속하지 않습니다
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4205,6 +4205,7 @@ imageTrace Outline Contour
|
||||
@msg not in pattern editing mode niet in patroonbewerkingsmodus
|
||||
@msg nothing encoded niets gecodeerd
|
||||
@msg nothing selected niets geselecteerd
|
||||
@msg nothing selected is in a group niets van de selectie zit in een groep
|
||||
@msg nothing to align niets om uit te lijnen
|
||||
@msg nothing to distort niets om te vervormen
|
||||
@msg nothing to export: the document has no visible art (or turn on Use Artboards) niets om te exporteren: het document heeft geen zichtbare illustratie (of schakel Tekengebieden gebruiken in)
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4314,6 +4314,7 @@ imageTrace Outline Kontur
|
||||
@msg not in pattern editing mode nie jest w trybie edycji wzorka
|
||||
@msg nothing encoded nic nie zakodowano
|
||||
@msg nothing selected nic nie zaznaczono
|
||||
@msg nothing selected is in a group nic z zaznaczenia nie należy do grupy
|
||||
@msg nothing to align nie ma czego wyrównać
|
||||
@msg nothing to distort nie ma czego zniekształcić
|
||||
@msg nothing to export: the document has no visible art (or turn on Use Artboards) nie ma czego eksportować: dokument nie ma widocznej kompozycji (lub włącz Użyj obszarów kompozycji)
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -3759,6 +3759,7 @@ axis Both Ambos
|
||||
@msg not in pattern editing mode não está no modo de edição de padrão
|
||||
@msg nothing encoded nada codificado
|
||||
@msg nothing selected nada selecionado
|
||||
@msg nothing selected is in a group nada do que está selecionado está em um grupo
|
||||
@msg nothing to align nada para alinhar
|
||||
@msg nothing to distort nada para distorcer
|
||||
@msg nothing to export: the document has no visible art (or turn on Use Artboards) nada para exportar: o documento não tem arte visível (ou ative Usar pranchetas)
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
@@ -4222,6 +4222,7 @@ axis Both Оба
|
||||
@msg not in pattern editing mode не в режиме редактирования узора
|
||||
@msg nothing encoded ничего не закодировано
|
||||
@msg nothing selected ничего не выделено
|
||||
@msg nothing selected is in a group ничего из выделенного не находится в группе
|
||||
@msg nothing to align нечего выравнивать
|
||||
@msg nothing to distort нечего искажать
|
||||
@msg nothing to export: the document has no visible art (or turn on Use Artboards) нечего экспортировать: в документе нет видимого рисунка (или включите «Использовать монтажные области»)
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4101,6 +4101,7 @@ axis Both Båda
|
||||
@msg not in pattern editing mode inte i läget för mönsterredigering
|
||||
@msg nothing encoded inget kodat
|
||||
@msg nothing selected inget markerat
|
||||
@msg nothing selected is in a group inget av det markerade ligger i en grupp
|
||||
@msg nothing to align inget att justera
|
||||
@msg nothing to distort inget att förvränga
|
||||
@msg nothing to export: the document has no visible art (or turn on Use Artboards) inget att exportera: dokumentet har ingen synlig grafik (eller aktivera Använd ritytor)
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 5 and column 25.
|
@@ -3959,6 +3959,7 @@ axis Both Her İkisi
|
||||
@msg not in pattern editing mode desen düzenleme modunda değil
|
||||
@msg nothing encoded kodlanmış hiçbir şey yok
|
||||
@msg nothing selected hiçbir şey seçilmedi
|
||||
@msg nothing selected is in a group seçilenlerin hiçbiri bir grupta değil
|
||||
@msg nothing to align hizalanacak hiçbir şey yok
|
||||
@msg nothing to distort çarpıtılacak hiçbir şey yok
|
||||
@msg nothing to export: the document has no visible art (or turn on Use Artboards) dışa aktarılacak bir şey yok: belgede görünür resim yok (veya Çalışma Yüzeylerini Kullan'ı açın)
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 5 and column 25.
|
@@ -4210,6 +4210,7 @@ axis Both Обидві
|
||||
@msg not in pattern editing mode не в режимі редагування візерунка
|
||||
@msg nothing encoded нічого не закодовано
|
||||
@msg nothing selected нічого не виділено
|
||||
@msg nothing selected is in a group нічого з виділеного не перебуває в групі
|
||||
@msg nothing to align нічого вирівнювати
|
||||
@msg nothing to distort нічого спотворювати
|
||||
@msg nothing to export: the document has no visible art (or turn on Use Artboards) нема чого експортувати: у документі немає видимого малюнка (або увімкніть «Використовувати монтажні області»)
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 749 and column 40.
|
@@ -4506,6 +4506,7 @@ theme Appearance Giao diện
|
||||
@msg not in pattern editing mode không ở chế độ chỉnh sửa họa tiết
|
||||
@msg nothing encoded không có gì được mã hóa
|
||||
@msg nothing selected chưa chọn gì
|
||||
@msg nothing selected is in a group không mục nào được chọn nằm trong nhóm
|
||||
@msg nothing to align không có gì để căn chỉnh
|
||||
@msg nothing to distort không có gì để làm méo
|
||||
@msg nothing to export: the document has no visible art (or turn on Use Artboards) không có gì để xuất: tài liệu không có tác phẩm hiển thị (hoặc bật Dùng bảng vẽ)
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 4073 and column 10.
|
@@ -4278,6 +4278,7 @@ imageTrace Outline 轮廓
|
||||
@msg Couldn't copy to the system clipboard: {e} 无法复制到系统剪贴板:{e}
|
||||
@msg Couldn't paste from the clipboard: {e} 无法从剪贴板粘贴:{e}
|
||||
@msg nothing selected 未选择任何对象
|
||||
@msg nothing selected is in a group 所选对象均不在编组中
|
||||
@msg the {tool} tool has no options {tool} 工具没有选项
|
||||
@msg unknown tool `{tool}` 未知工具 `{tool}`
|
||||
@msg {tool} isn't in a toolbar group of several tools {tool} 不在包含多个工具的工具栏组中
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -2239,6 +2239,7 @@ file-filter Templates 範本
|
||||
@msg Couldn't copy to the system clipboard: {e} 無法複製到系統剪貼簿:{e}
|
||||
@msg Couldn't paste from the clipboard: {e} 無法從剪貼簿貼上:{e}
|
||||
@msg nothing selected 未選取任何物件
|
||||
@msg nothing selected is in a group 選取的物件都不在群組中
|
||||
@msg the {tool} tool has no options {tool} 工具沒有選項
|
||||
@msg unknown tool `{tool}` 未知的工具 `{tool}`
|
||||
@msg {tool} isn't in a toolbar group of several tools {tool} 不在包含多個工具的工具列群組中
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
@@ -1,5 +1,5 @@
|
||||
use super::entries::{Row, entry, pretty_shortcut};
|
||||
use super::invoke::{field_event, focused_text_field, invoke, to_field};
|
||||
use super::invoke::{field_event, focused_text_field, invoke, to_field, with_held_keys};
|
||||
use super::tree::menu_tree_named;
|
||||
use super::{Entry, Item, Tokens, Value, VectorcraftApp, widgets};
|
||||
|
||||
@@ -153,7 +153,7 @@ fn render_row(app: &VectorcraftApp, ui: &mut egui::Ui, row: &Row, checks: bool,
|
||||
None => ui.add_enabled(row.enabled, egui::Button::new(text).shortcut_text(sc)),
|
||||
};
|
||||
if r.clicked() {
|
||||
*clicked = row.target();
|
||||
*clicked = row.target().map(|target| with_held_keys(target, ui.input(|i| i.modifiers)));
|
||||
ui.close();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,16 @@ pub fn click_target(label: &str, id: &str, p: &Value) -> (String, Value) {
|
||||
(id.to_string(), if p.is_null() { json!({}) } else { p.clone() })
|
||||
}
|
||||
|
||||
/// What an in-window menu click on `target` (a [`click_target`]) runs with `held` held: Object ›
|
||||
/// Unlock All and Object › Show All chosen with Shift+Alt (Shift+Option) act only inside the groups
|
||||
/// that hold the selected objects (`scope: "group"`).
|
||||
pub(super) fn with_held_keys(target: (String, Value), held: egui::Modifiers) -> (String, Value) {
|
||||
match target.0.as_str() {
|
||||
"object.unlockAll" | "object.showAll" if held.shift && held.alt => (target.0, json!({"scope": "group"})),
|
||||
_ => target,
|
||||
}
|
||||
}
|
||||
|
||||
/// The dialog of command `id` that shows the selection's current values (its query): its heading
|
||||
/// and the queried values it doesn't show. Type on a Path Options leaves the brackets where they
|
||||
/// are.
|
||||
|
||||
@@ -758,6 +758,59 @@ fn long_menus_scroll_inside_a_short_window() {
|
||||
assert!(tall.bottom() < 3000.0);
|
||||
}
|
||||
|
||||
/// Object › Unlock All and Object › Show All clicked with Shift+Alt held run with
|
||||
/// `scope: "group"`; clicked without them, or with only one of the two, they run on the whole
|
||||
/// document as before.
|
||||
#[test]
|
||||
fn unlock_all_and_show_all_clicked_with_shift_alt_act_within_the_group() {
|
||||
let mut app = VectorcraftApp::new(vectorcraft_engine::Session::new(), crate::Services::default());
|
||||
app.run("file.new", json!({"width": 200, "height": 200})).unwrap();
|
||||
let ctx = egui::Context::default();
|
||||
crate::theme::install_fonts(&ctx);
|
||||
let tree = menu_tree();
|
||||
let (_, object) = tree.iter().find(|(t, _)| *t == "Object").unwrap();
|
||||
let id = egui::Id::unique("test-object-menu");
|
||||
let screen = egui::Rect::from_min_size(egui::Pos2::ZERO, egui::vec2(1600.0, 3000.0));
|
||||
let frame = |events: Vec<egui::Event>, modifiers: egui::Modifiers| {
|
||||
let mut clicked = None;
|
||||
let events = std::iter::once(egui::Event::ModifiersChanged(modifiers)).chain(events).collect();
|
||||
let input = egui::RawInput { screen_rect: Some(screen), events, ..Default::default() };
|
||||
let mut out = ctx.run_ui(input, |ui| {
|
||||
egui::Area::new(id).fixed_pos(egui::pos2(0.0, 0.0)).show(ui.ctx(), |ui| {
|
||||
egui::containers::menu::menu_style(ui.style_mut());
|
||||
ui.with_layout(egui::Layout::top_down_justified(egui::Align::Min), |ui| menu_body(&app, ui, object, &mut clicked));
|
||||
});
|
||||
});
|
||||
out.textures_delta.clear();
|
||||
(clicked, out.shapes)
|
||||
};
|
||||
// Where the menu draws `label`.
|
||||
fn find(s: &egui::Shape, label: &str) -> Option<egui::Pos2> {
|
||||
match s {
|
||||
egui::Shape::Text(t) if t.galley.text() == label => Some(t.pos + t.galley.rect.center().to_vec2()),
|
||||
egui::Shape::Vec(v) => v.iter().find_map(|s| find(s, label)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
let click = |label: &str, modifiers: egui::Modifiers| {
|
||||
let (_, shapes) = frame(vec![], Default::default());
|
||||
let at = shapes.iter().find_map(|c| find(&c.shape, label)).unwrap_or_else(|| panic!("{label} is not in the Object menu"));
|
||||
let button = |pressed| egui::Event::PointerButton { pos: at, button: egui::PointerButton::Primary, pressed, modifiers };
|
||||
frame(vec![egui::Event::PointerMoved(at)], modifiers);
|
||||
frame(vec![button(true)], modifiers);
|
||||
frame(vec![button(false)], modifiers).0
|
||||
};
|
||||
frame(vec![], Default::default());
|
||||
let shift_alt = egui::Modifiers { shift: true, alt: true, ..Default::default() };
|
||||
let group = json!({"scope": "group"});
|
||||
for (label, command) in [("Unlock All", "object.unlockAll"), ("Show All", "object.showAll")] {
|
||||
assert_eq!(click(label, shift_alt), Some((command.to_string(), group.clone())), "{label} with Shift+Alt");
|
||||
for held in [egui::Modifiers::NONE, egui::Modifiers::SHIFT, egui::Modifiers::ALT] {
|
||||
assert_eq!(click(label, held), Some((command.to_string(), json!({}))), "{label} with {held:?}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// #3724: Window › New Window is greyed out until VectorCraft can open a second window on a
|
||||
/// document, instead of being enabled and answering with an internal milestone note.
|
||||
#[test]
|
||||
|
||||
@@ -1345,6 +1345,14 @@ that were already hidden or locked. The key object is cleared when it is one of
|
||||
them again with the key object. When the call changes nothing, it records no undo step and still deselects them.
|
||||
Other `object.setProps` calls leave the selection unchanged.
|
||||
|
||||
`object.unlockAll` and `object.showAll` unlock or show every locked or hidden object in the document and select
|
||||
them → `{count}`. With `scope: "group"` they take only the objects inside the groups that hold the selected objects:
|
||||
for each selected object, the group nearest above it, or the object itself when it is a group. The objects of a
|
||||
group inside another such group are counted once. With no selected object in a group, the call returns the error
|
||||
"nothing selected is in a group" and changes nothing. `scope: "document"` is the default, and any other value is
|
||||
refused. Object › Unlock All and Object › Show All clicked in the in-window menu bar with Shift+Alt (Shift+Option)
|
||||
held run with `scope: "group"`.
|
||||
|
||||
`layer.move`, `node.move`, `layer.merge`, `layer.flatten`, `layer.collectInNew`, `dataset.select`, `dataset.next`
|
||||
and `dataset.prev` also deselect every selected object that is hidden or locked after the call, such as objects
|
||||
moved into a hidden or locked layer or group, or objects that a data set hides. The key object is cleared when it
|
||||
|
||||
@@ -910,6 +910,7 @@ Moved from the ROADMAP's "Shipped so far" on 2026-10-10. Update it when a featur
|
||||
In isolation mode, the items of Object › Lock and Object › Hide, Unlock All and Show All are greyed out ([lock, hide, and delete objects](https://web.archive.org/web/20220303070637/https://helpx.adobe.com/illustrator/using/locking-hiding-deleting-objects.html)); the Contextual Task Bar's Lock button is greyed out too, the Properties panel's Quick Actions have no Lock, and the commands return an error. Pattern editing mode and opacity mask editing do not count as isolation mode for them.
|
||||
Liquify (its brush Width, Height and Angle, Intensity, Detail, Simplify, Twirl Rate, Complexity, Horizontal and Vertical), Puppet Warp (its Expand and each pin's angle), Transform in Perspective (its depth), Nudge in Perspective (its direction) and Move Plane (its location or distance) refuse a value other than a number or null, such as "40", Draw in Perspective refuses a click point that is not two numbers, and Width Profile refuses a point that is not three numbers; each leaves the document and its undo history as they were.
|
||||
Object › Lock › All Artwork Above and Object › Hide › All Artwork Above go through each top-level layer once, checking each object that is not selected against the selected objects below it: with 100 tiles selected under 25,000 rectangles, Lock took 6.4 s and now takes under 0.1 s, and with all of 5,001 objects selected it took 8.8 s and now takes under 0.1 s.
|
||||
Object › Unlock All and Object › Show All clicked in the in-window menu bar with Shift+Alt (Shift+Option) held unlock or show only the objects inside the groups that hold the selected objects ([lock, hide, and delete objects](https://web.archive.org/web/20230623025912/https://helpx.adobe.com/illustrator/using/locking-hiding-deleting-objects.html)); `object.unlockAll` and `object.showAll` take `scope: "group"` for it.
|
||||
Lock Grid, Lock Station Point, Snap to Grid and Show Rulers (View › Perspective Grid) and Import Perspective Grid Presets (its choice to replace saved presets of the same names) refuse a value other than true, false or null, such as "true", and leave the grid and the saved presets as they were.
|
||||
All Artwork Above and Other Layers (Object › Lock and Object › Hide), Transform Each, Rearrange All Artboards, the width point and width profile commands, Liquify, Puppet Warp, Define Perspective Grid, Attach to Active Plane, Release with Perspective, moves and transforms in perspective, Move Plane and Move Plane to Match Object record no undo step when they change nothing.
|
||||
Move in Perspective (its copy, perpendicular and Snap to Grid choices), Transform in Perspective (its copy), Nudge in Perspective (its ×10 and copy), Draw in Perspective (Snap to Grid), Define Perspective Grid (its reproject choice), Show Perspective Grid, Width Point (Adjust Adjoining Width Points), Liquify (its pen pressure, Simplify and Affect choices) and Puppet Warp (its pins' rest shape) refuse a value other than true, false or null, such as "true", and leave the document and its undo history as they were.
|
||||
|
||||
Reference in New Issue
Block a user