Fix #5526: select images by link status

Selection Tools add-on: addon.select.byLinkStatus selects the image
objects and placed documents whose link is linked, embedded, missing or
modified (one status or several), as links.list reports it. Optional ids
limit the search, add adds to the selection, and zoom runs the existing
Zoom to Selection in the desktop app. Objects that are hidden, locked, on
a template layer or outside the isolated group are left out and returned
with the reason. Only the selection changes.

Select Linked / Embedded / Missing / Modified are in Object > Plug-ins >
Selection Tools and the Links panel menu. Each is off when no image has
that status, and Shift adds to the selection. Select by Link Status...
lists the images with name, status and format, with a name search, a
status filter, checkboxes with All / None and Zoom to Selection. The
status bar says what was selected and how many were left out, with
plural rows in every catalog.

Tests: engine (statuses, ids, add, zoom, skip reasons, bad params),
command sweep, and UI (message, list filtering, menu items, Links panel
menu, headless dialog frame). Docs: mcp, target-app-parity, ui-parity,
roadmap.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ruchirguitar
2026-11-05 14:12:10 +07:00
committed by bflatastic
co-authored by Claude Opus 5.5
parent d735add956
commit 7dc66d660a
45 changed files with 1370 additions and 25 deletions
+141 -15
View File
@@ -1,31 +1,51 @@
//! Selection Tools (`addon.select.*`), a built-in add-on: Select by Artboards selects the objects
//! overlapping, fully inside or fully outside one or more chosen artboards (#5525). Its submenu
//! (Object › Plug-ins › Selection Tools) and dialog are the UI's.
//! overlapping, fully inside or fully outside one or more chosen artboards (#5525), and Select by
//! Link Status selects the images and placed documents whose file is linked, embedded, missing or
//! modified (#5526), saying which ones it had to leave out and why. Its submenu (Object › Plug-ins
//! › Selection Tools), the Links panel's menu items and the dialogs are the UI's.
#[cfg(test)]
mod tests;
use std::collections::BTreeSet;
use serde_json::{Value, json};
use vectorcraft_doc::NodeId;
use vectorcraft_doc::{LockedArtboards, Node, NodeId, NodeKind};
use vectorcraft_geom::Point;
use super::super::select::{on_artboard, selectable};
use super::super::{CommandSpec, bad, cmd, has_doc, point_indices, text_param};
use crate::{Result, Session};
use super::super::links::{Status, statuses};
use super::super::select::{is_selectable, on_artboard, selectable};
use super::super::{CommandSpec, bad, checked_ids_param, cmd, has_doc, point_indices, switch_or, text_param};
use crate::{DocState, Result, Session};
/// How Select by Artboards relates an object to the chosen artboards (`relation`).
pub const RELATIONS: [&str; 3] = ["overlap", "inside", "outside"];
/// The link statuses Select by Link Status takes (`status`): a file found unchanged, pixels kept
/// in the document, a file not found, a file changed since it was read.
pub const LINK_STATUSES: [&str; 4] = ["linked", "embedded", "missing", "modified"];
pub fn specs() -> Vec<CommandSpec> {
vec![cmd!(
"addon.select.byArtboards",
"Select by Artboards",
["Object", "Plug-ins", "Selection Tools"],
None,
"{artboards: [index…] (0-based, at least one), relation?: \"overlap\" (default: on at least one of them, as select.allOnArtboard takes it: the bounds overlap the artboard or the centre is on it) | \"inside\" (the bounds lie wholly within one of them, edges included) | \"outside\" (on none of them)} select those objects among the ones Select All takes (in isolation mode, the isolated container's); hidden and locked objects, objects on hidden, locked or template layers and art held by a locked artboard are left out. Bounds are geometric, a symbol instance's measured by its art → {count}",
has_doc,
by_artboards
)]
vec![
cmd!(
"addon.select.byArtboards",
"Select by Artboards",
["Object", "Plug-ins", "Selection Tools"],
None,
"{artboards: [index…] (0-based, at least one), relation?: \"overlap\" (default: on at least one of them, as select.allOnArtboard takes it: the bounds overlap the artboard or the centre is on it) | \"inside\" (the bounds lie wholly within one of them, edges included) | \"outside\" (on none of them)} select those objects among the ones Select All takes (in isolation mode, the isolated container's); hidden and locked objects, objects on hidden, locked or template layers and art held by a locked artboard are left out. Bounds are geometric, a symbol instance's measured by its art → {count}",
has_doc,
by_artboards
),
cmd!(
"addon.select.byLinkStatus",
"Select by Link Status",
["Object", "Plug-ins", "Selection Tools"],
None,
"{status: \"linked\" (its file found unchanged) | \"embedded\" | \"missing\" | \"modified\" (its file changed since it was read) | [several of them] (at least one), ids?: [object ids] (pick only among these; default: every image and placed document in the layers), add?: false (add to the selection instead of replacing it), zoom?: false (then zoom to the selection: the desktop app runs addon.arrange.zoomSelection when something was selected; elsewhere the result's zoom flag asks the caller to)} select the image objects and placed documents whose link has that status, as links.list reports it. Those that are hidden or locked, inside a hidden or locked object or layer, on a template layer, on a locked artboard while nothing is isolated, or outside the isolated group or layer are left out and listed with the reason. Only the selection changes, not the document → {count (how many it selected), selected: [ids] (in stacking order, bottom first), skipped: [{id, reason: hidden|locked|template|isolation}], zoom?: true}",
has_doc,
by_link_status
),
]
}
fn by_artboards(s: &mut Session, p: &Value) -> Result<Value> {
@@ -61,3 +81,109 @@ fn by_artboards(s: &mut Session, p: &Value) -> Result<Value> {
s.select(|_, sel| sel.set(ids))?;
Ok(json!({ "count": s.doc()?.selection.objects.len() }))
}
/// The link statuses `p` asks for (`status`: one, or a list of them), each once.
fn link_statuses(p: &Value, cmd: &str) -> Result<Vec<&'static str>> {
let given: Vec<&Value> = match p.get("status") {
None | Some(Value::Null) => return Err(bad(cmd, "missing `status`: linked, embedded, missing or modified")),
Some(Value::Array(v)) => v.iter().collect(),
Some(v) => vec![v],
};
let mut out = vec![];
for v in given {
let s = v.as_str().ok_or_else(|| bad(cmd, "`status` must be linked, embedded, missing or modified, or a list of them"))?;
let known =
LINK_STATUSES.iter().find(|k| **k == s).ok_or_else(|| bad(cmd, format!("status `{s}`: linked, embedded, missing or modified")))?;
if !out.contains(known) {
out.push(*known);
}
}
if out.is_empty() {
return Err(bad(cmd, "choose at least one status"));
}
Ok(out)
}
/// The link status of every image object and placed document in the layers of `st`, as
/// `links.list` reports it (`ok` named `linked`), in stacking order (bottom first). Each file is
/// looked at once.
pub(crate) fn link_status_of_objects(st: &DocState) -> Vec<(NodeId, &'static str)> {
let linked = statuses(st);
let mut out = vec![];
st.doc.walk(|n| {
if matches!(n.kind, NodeKind::Image(_) | NodeKind::PlacedDocument(_)) {
let status = match linked.get(&n.id).map(|(s, ..)| *s) {
Some(Status::Ok) => "linked",
Some(Status::Modified) => "modified",
Some(Status::Missing) => "missing",
None => "embedded",
};
out.push((n.id, status));
}
});
out
}
/// Why object `id` of `st` can't be selected now ([`is_selectable`]): it is outside the isolated
/// group or layer, on a template layer, hidden (or inside something hidden), or locked (or inside
/// something locked, or on a locked artboard); `None` when it can be. `locks` is the document's
/// [`vectorcraft_doc::Document::locked_artboards`].
fn skip_reason(st: &DocState, locks: &LockedArtboards, id: NodeId) -> Option<&'static str> {
let d = &st.doc;
if is_selectable(d, st.isolation, locks, id) {
return None;
}
let ancestry = d.ancestry(id).unwrap_or_default();
// Outside the isolated container, or the isolated container itself (its art is what's taken).
if let Some(c) = st.isolation.and_then(|i| d.node(i))
&& ancestry.iter().position(|i| *i == c.id).is_none_or(|at| at + 1 == ancestry.len() && c.is_container())
{
return Some("isolation");
}
let held: Vec<&Node> = ancestry.iter().filter_map(|i| d.node(*i)).collect();
Some(if held.iter().any(|n| n.is_template()) {
"template"
} else if held.iter().any(|n| !n.visible) {
"hidden"
} else {
// A locked object, group or layer, or the locked artboard that holds it.
"locked"
})
}
fn by_link_status(s: &mut Session, p: &Value) -> Result<Value> {
const C: &str = "addon.select.byLinkStatus";
let wanted = link_statuses(p, C)?;
let add = switch_or(p, "add", false, C)?;
let zoom = switch_or(p, "zoom", false, C)?;
let only: Option<BTreeSet<NodeId>> = match p.get("ids") {
None | Some(Value::Null) => None,
Some(_) => Some(checked_ids_param(s, p, "ids", C)?.into_iter().collect()),
};
let st = s.doc()?;
let locks = st.doc.locked_artboards();
let (mut picked, mut skipped) = (vec![], vec![]);
for (id, status) in link_status_of_objects(st) {
if !wanted.contains(&status) || only.as_ref().is_some_and(|o| !o.contains(&id)) {
continue;
}
match skip_reason(st, &locks, id) {
None => picked.push(id),
Some(reason) => skipped.push(json!({ "id": id.0, "reason": reason })),
}
}
s.select(|_, sel| {
if add {
for id in &picked {
sel.add(*id);
}
} else {
sel.set(picked.iter().copied());
}
})?;
let mut out = json!({ "count": picked.len(), "selected": picked.iter().map(|id| id.0).collect::<Vec<_>>(), "skipped": skipped });
if zoom {
out["zoom"] = json!(true);
}
Ok(out)
}
@@ -126,3 +126,179 @@ fn a_symbol_instance_is_measured_by_its_art() {
assert_eq!(pick(&mut s, json!({"artboards": [0], "relation": "inside"})), vec![instance]);
assert_eq!(pick(&mut s, json!({"artboards": [0], "relation": "outside"})), vec![]);
}
/// Select by Link Status.
mod by_link_status {
use serde_json::{Value, json};
use vectorcraft_doc::{Document, NodeId};
use crate::Session;
use crate::tests_links::{BLUE, Folder, RED, place, png, session, write};
const C: &str = "addon.select.byLinkStatus";
/// One linked image whose file stays as it is (`ok`), one whose file changes (`modified`),
/// one whose file goes (`missing`), an embedded one, and a placed document whose file goes
/// (missing too), bottom to top.
struct Links {
s: Session,
ok: NodeId,
modified: NodeId,
missing: NodeId,
embedded: NodeId,
document: NodeId,
_dir: Folder,
}
fn links(name: &str) -> Links {
let dir = Folder::new(name);
let (a, b, c, e, d) = (dir.file("ok.png"), dir.file("changes.png"), dir.file("goes.png"), dir.file("kept.png"), dir.file("page.vectorcraft"));
write(&a, &png(10, 10, RED));
write(&b, &png(12, 10, RED));
write(&c, &png(14, 10, BLUE));
write(&e, &png(16, 10, BLUE));
write(&d, &vectorcraft_format::save_file(&Document::new(80.0, 50.0)));
let mut s = session();
let (ok, modified, missing) = (place(&mut s, &a), place(&mut s, &b), place(&mut s, &c));
let embedded = NodeId(s.execute("file.place", &json!({"path": e, "at": [100, 100], "link": false})).unwrap()["ids"][0].as_u64().unwrap());
let document = place(&mut s, &d);
write(&b, &png(13, 10, BLUE));
std::fs::remove_file(&c).unwrap();
std::fs::remove_file(&d).unwrap();
Links { s, ok, modified, missing, embedded, document, _dir: dir }
}
fn run(s: &mut Session, p: Value) -> Value {
s.execute(C, &p).unwrap_or_else(|e| panic!("{p}: {e}"))
}
fn sorted(mut v: Vec<NodeId>) -> Vec<NodeId> {
v.sort();
v
}
fn selection(s: &Session) -> Vec<NodeId> {
sorted(s.doc().unwrap().selection.objects.clone())
}
fn ids(v: &Value) -> Vec<NodeId> {
sorted(v.as_array().unwrap().iter().map(|i| NodeId(i.as_u64().unwrap())).collect())
}
#[test]
fn each_status_selects_its_images_and_placed_documents() {
let Links { mut s, ok, modified, missing, embedded, document, _dir } = links("select-status");
// As the Links panel lists them.
let listed = s.execute("links.list", &json!({})).unwrap();
let status = |id: NodeId| listed["links"].as_array().unwrap().iter().find(|r| r["id"] == id.0).unwrap()["status"].clone();
assert_eq!([ok, modified, missing, embedded, document].map(status), ["ok", "modified", "missing", "embedded", "missing"].map(|s| json!(s)));
let undo = s.doc().unwrap().history.undo.len();
for (status, want) in [("linked", vec![ok]), ("modified", vec![modified]), ("missing", vec![missing, document]), ("embedded", vec![embedded])]
{
s.execute("select.none", &json!({})).unwrap();
let r = run(&mut s, json!({"status": status}));
assert_eq!((ids(&r["selected"]), r["count"].as_u64()), (sorted(want.clone()), Some(want.len() as u64)), "{status}: {r}");
assert_eq!(selection(&s), sorted(want), "{status}");
assert_eq!(r["skipped"], json!([]));
assert!(r.get("zoom").is_none());
}
// Several at once, in stacking order (bottom first); a status listed twice counts once.
let r = run(&mut s, json!({"status": ["missing", "linked", "missing"]}));
assert_eq!(r["selected"], json!([ok.0, missing.0, document.0]));
assert_eq!(s.doc().unwrap().history.undo.len(), undo, "only the selection changes");
}
#[test]
fn ids_add_and_zoom() {
let Links { mut s, ok, modified, embedded, document, _dir, .. } = links("select-options");
// Only among the ids given; other objects among them (a rectangle) are passed over.
let rect = s.execute("shape.rectangle", &json!({"x": 0, "y": 0, "width": 5, "height": 5})).unwrap()["id"].as_u64().unwrap();
let r = run(&mut s, json!({"status": "missing", "ids": [document.0, ok.0, rect]}));
assert_eq!(r["selected"], json!([document.0]));
assert_eq!(selection(&s), vec![document]);
// Added to the selection.
let r = run(&mut s, json!({"status": "embedded", "add": true}));
assert_eq!((r["count"].as_u64(), r["selected"].clone()), (Some(1), json!([embedded.0])));
assert_eq!(selection(&s), sorted(vec![document, embedded]));
// Replacing it by default.
run(&mut s, json!({"status": "modified"}));
assert_eq!(selection(&s), vec![modified]);
// Nothing to select: added, the selection stays; replacing, it empties.
let r = run(&mut s, json!({"status": "linked", "ids": [embedded.0], "add": true}));
assert_eq!((r["count"].as_u64(), r["selected"].clone(), r["skipped"].clone()), (Some(0), json!([]), json!([])));
assert_eq!(selection(&s), vec![modified]);
run(&mut s, json!({"status": "linked", "ids": [embedded.0]}));
assert_eq!(selection(&s), vec![]);
// Zoom is reported for the caller (the desktop app zooms).
assert_eq!(run(&mut s, json!({"status": "linked", "zoom": true}))["zoom"], true);
assert!(run(&mut s, json!({"status": "linked", "zoom": false})).get("zoom").is_none());
}
#[test]
fn hidden_locked_template_and_isolated_ones_are_skipped_with_the_reason() {
let dir = Folder::new("select-skipped");
let files: Vec<String> = (0..6).map(|i| dir.file(&format!("img{i}.png"))).collect();
for (i, f) in files.iter().enumerate() {
write(f, &png(10 + i as u32, 10, RED));
}
let mut s = session();
let [free, hidden, locked, in_group, mate] = [0, 1, 2, 3, 4].map(|i| place(&mut s, &files[i]));
s.execute("object.setProps", &json!({"ids": [hidden.0], "visible": false})).unwrap();
s.execute("object.setProps", &json!({"ids": [locked.0], "locked": true})).unwrap();
// Inside a locked group.
s.execute("select.set", &json!({"ids": [in_group.0]})).unwrap();
let g = s.execute("object.group", &json!({})).unwrap()["id"].as_u64().unwrap();
s.execute("object.setProps", &json!({"ids": [g], "locked": true})).unwrap();
// On a template layer.
let layer = s.execute("layer.new", &json!({"name": "Trace"})).unwrap()["id"].as_u64().unwrap();
let on_template = place(&mut s, &files[5]);
s.execute("layer.setProps", &json!({"id": layer, "template": true})).unwrap();
let r = run(&mut s, json!({"status": "linked"}));
assert_eq!(ids(&r["selected"]), sorted(vec![free, mate]), "{r}");
let mut reasons: Vec<(u64, String)> =
r["skipped"].as_array().unwrap().iter().map(|k| (k["id"].as_u64().unwrap(), k["reason"].as_str().unwrap().to_string())).collect();
reasons.sort();
let mut want: Vec<(u64, String)> = [(hidden, "hidden"), (locked, "locked"), (in_group, "locked"), (on_template, "template")]
.into_iter()
.map(|(id, why)| (id.0, why.to_string()))
.collect();
want.sort();
assert_eq!(reasons, want, "{r}");
assert!(reasons.iter().all(|(_, why)| ["hidden", "locked", "template", "isolation"].contains(&why.as_str())));
// In isolation mode, those outside the isolated group are left out.
s.execute("select.set", &json!({"ids": [mate.0]})).unwrap();
let iso = s.execute("object.group", &json!({})).unwrap()["id"].as_u64().unwrap();
s.execute("object.isolate", &json!({"id": iso})).unwrap();
let r = run(&mut s, json!({"status": "linked"}));
assert_eq!(r["selected"], json!([mate.0]), "{r}");
let why = |id: NodeId| r["skipped"].as_array().unwrap().iter().find(|k| k["id"] == id.0).map(|k| k["reason"].clone());
assert_eq!(why(free), Some(json!("isolation")));
assert_eq!(why(hidden), Some(json!("isolation")));
}
#[test]
fn bad_params_are_errors_and_leave_the_selection() {
let Links { mut s, ok, _dir, .. } = links("select-bad");
for p in [
json!({}),
json!({"status": null}),
json!({"status": []}),
json!({"status": "lost"}),
json!({"status": ["linked", "lost"]}),
json!({"status": 3}),
json!({"status": [true]}),
json!({"status": "linked", "add": "yes"}),
json!({"status": "linked", "zoom": 1}),
json!({"status": "linked", "ids": "1"}),
json!({"status": "linked", "ids": [999_999]}),
json!({"status": "linked", "ids": [-1]}),
json!({"status": "linked", "stauts": "missing"}),
] {
s.execute("select.set", &json!({"ids": [ok.0]})).unwrap();
assert!(s.execute(C, &p).is_err(), "{p}");
assert_eq!(s.doc().unwrap().selection.objects, vec![ok], "{p}");
}
// Without a document it is off, not a crash.
assert!(Session::new().execute(C, &json!({"status": "linked"})).is_err());
}
}
+1 -1
View File
@@ -1110,7 +1110,7 @@ fn linked_param(st: &crate::DocState, p: &Value, cmd: &str) -> Result<NodeId> {
/// Per linked image in the layers of `st`: its file's status, where it was found when away from
/// its path, and whether the image shows its preview (each file probed once).
fn statuses(st: &crate::DocState) -> BTreeMap<NodeId, (Status, Option<String>, bool)> {
pub(crate) fn statuses(st: &crate::DocState) -> BTreeMap<NodeId, (Status, Option<String>, bool)> {
let mut out = BTreeMap::new();
for g in groups(&st.doc, None).iter().filter(|g| !g.ids.is_empty()) {
let (status, found) = probe(g, st.path.as_deref());
+4
View File
@@ -239,6 +239,10 @@ fn structured_junk() {
("addon.select.byArtboards", json!({"artboards": [0, u64::MAX, -1, "x", null, 1.5], "relation": "inside"})),
("addon.select.byArtboards", json!({"artboards": [1e308], "relation": [1]})),
("addon.select.byArtboards", json!({"artboards": {"a": 1}, "relation": "outside"})),
("addon.select.byLinkStatus", json!({"status": ["linked", "missing", null, 7, {"a": 1}], "ids": [2, u64::MAX, -1, "x", 1.5]})),
("addon.select.byLinkStatus", json!({"status": "embedded", "ids": {"a": 1}, "add": [1], "zoom": "yes"})),
("addon.select.byLinkStatus", json!({"status": ["modified", "embedded"], "ids": [], "add": true, "zoom": true})),
("addon.select.byLinkStatus", json!({"status": [[["linked"]]], "ids": null})),
("object.transform", json!({"matrix": [0, 0, 0, 0, 0, 0]})),
("object.transform", json!({"matrix": [1e308, 1e308, 1e308, 1e308, 1e308, 1e308]})),
("object.transform", json!({"matrix": [1, 2, 3]})),
+7 -2
View File
@@ -1,7 +1,8 @@
//! Selection Tools in the interface: its submenu (Object › Plug-ins › Selection Tools) and the
//! Select by Artboards dialog (#5548), which lists the artboards with their number, name and size,
//! filters them by name, picks several, fits one in the window on double-click (#5549), and on OK
//! runs `addon.select.byArtboards` with the relation chosen.
//! runs `addon.select.byArtboards` with the relation chosen; and Select by Link Status
//! ([`link_status`], #5526).
use egui::{Sense, Ui, vec2};
use serde_json::{Value, json};
@@ -13,6 +14,8 @@ use crate::state::Dialog;
use crate::theme::Tokens;
use crate::widgets;
pub mod link_status;
/// Select by Artboards, and its dialog's kind.
pub const COMMAND: &str = "addon.select.byArtboards";
pub const KIND: &str = "selectByArtboards";
@@ -25,7 +28,9 @@ const LIST_H: f32 = 220.0;
/// Object › Plug-ins › Selection Tools.
pub fn menu() -> Vec<Item> {
vec![Item::Cmd("Select by Artboards…", COMMAND, Value::Null)]
let mut v = vec![Item::Cmd("Select by Artboards…", COMMAND, Value::Null), Item::Sep];
v.extend(link_status::menu());
v
}
/// The dialog's fields to start with: the active artboard chosen, Overlapping.
@@ -0,0 +1,286 @@
//! Select by Link Status in the interface (#5526): Select Linked, Embedded, Missing and Modified
//! (in Object › Plug-ins › Selection Tools and the Links panel's menu; Shift adds to the
//! selection), the Select by Link Status dialog, and the status bar's line saying what was
//! selected and what was left out. Everything goes through `addon.select.byLinkStatus`; the dialog
//! lists what `links.list` reports.
use egui::{Ui, vec2};
use serde_json::{Value, json};
use crate::VectorcraftApp;
use crate::dialogs::{DialogSpec, form};
use crate::menus::Item;
use crate::state::Dialog;
use crate::theme::Tokens;
use crate::widgets;
/// Select by Link Status, and its dialog's kind.
pub const COMMAND: &str = "addon.select.byLinkStatus";
pub const KIND: &str = "selectByLinkStatus";
/// The statuses, as the command names them, with their menu items' and the dialog's labels.
pub const STATUSES: [(&str, &str, &str); 4] = [
("linked", "Select Linked", "Linked"),
("embedded", "Select Embedded", "Embedded"),
("missing", "Select Missing", "Missing"),
("modified", "Select Modified", "Modified"),
];
/// The dialog's Show choices: (value, label).
const SHOW: [(&str, &str); 5] = [("all", "All"), ("linked", "Linked"), ("embedded", "Embedded"), ("missing", "Missing"), ("modified", "Modified")];
/// How often the statuses are looked at again while the document stays as it is (s): files
/// change on disk without the document knowing.
const RECHECK: f64 = 2.0;
/// The least time between two looks while the document keeps changing (s).
const SETTLE: f64 = 0.5;
const ROW_H: f32 = 22.0;
const LIST_H: f32 = 240.0;
const STATUS_W: f32 = 80.0;
const FORMAT_W: f32 = 70.0;
/// The menu items: one per status, then the dialog.
pub fn menu() -> Vec<Item> {
let mut v: Vec<Item> = STATUSES.iter().map(|&(status, label, _)| Item::Cmd(label, COMMAND, json!({ "status": status }))).collect();
v.push(Item::Cmd("Select by Link Status…", COMMAND, Value::Null));
v
}
/// Which statuses ([`STATUSES`] order) the active document's images and placed documents have,
/// for the document and revision it was read for and when.
#[derive(Clone, Debug, Default)]
pub struct Present {
key: Option<(u64, u64)>,
at: f64,
pub has: [bool; 4],
}
/// The statuses the `links.list` result `list` holds, in [`STATUSES`] order.
pub(crate) fn statuses_in(list: &Value) -> [bool; 4] {
let rows = list["links"].as_array().map_or(&[][..], Vec::as_slice);
STATUSES.map(|(status, ..)| rows.iter().any(|r| command_status(r) == status))
}
/// The status of a `links.list` row as the command names it (`ok` is `linked`).
fn command_status(row: &Value) -> &str {
match row["status"].as_str().unwrap_or_default() {
"ok" => "linked",
s => s,
}
}
/// Keep [`Present`] up to date: at once when another document comes to the front, at most every
/// [`SETTLE`] seconds while its revision changes (a drag changes it every frame, and each look
/// asks the file system about every linked file), and every [`RECHECK`] seconds while it has
/// linked files.
pub fn refresh(app: &mut VectorcraftApp, now: f64) {
let key = app.session.active().map(|st| (st.uid, st.revision));
let p = &app.ui.link_statuses;
let linked = p.has.iter().zip(STATUSES).any(|(on, (status, ..))| *on && status != "embedded");
let other_document = p.key.map(|k| k.0) != key.map(|k| k.0);
let due = if p.key == key { linked && now - p.at >= RECHECK } else { other_document || now - p.at >= SETTLE };
if !due {
return;
}
let has = if key.is_some() { app.session.execute("links.list", &json!({})).map(|l| statuses_in(&l)).unwrap_or_default() } else { [false; 4] };
app.ui.link_statuses = Present { key, at: now, has };
}
/// Is menu item `status` (a [`STATUSES`] value) on: does an image or placed document have it?
pub(crate) fn enabled(app: &VectorcraftApp, p: &Value) -> bool {
let Some(status) = p.get("status").and_then(Value::as_str) else { return true };
STATUSES.iter().position(|(s, ..)| *s == status).and_then(|i| app.ui.link_statuses.has.get(i).copied()).unwrap_or(false)
}
/// A menu item's params with Shift held: add to the selection.
pub(crate) fn with_shift(mut p: Value) -> Value {
if let Some(o) = p.as_object_mut()
&& o.contains_key("status")
{
o.insert("add".into(), json!(true));
}
p
}
/// Run the command; with `zoom` and something selected, Zoom to Selection; the status bar says
/// what was selected and what was left out. Without params (the menu's "Select by Link Status…")
/// it opens the dialog instead.
pub(crate) fn run(app: &mut VectorcraftApp, p: &Value) -> Result<Value, String> {
if p.as_object().is_none_or(serde_json::Map::is_empty) {
if app.session.active().is_none() {
return Err("no document".into());
}
let fields = fields(app);
app.ui.dialog = Some(Dialog::new(KIND, fields));
return Ok(json!({ "dialog": KIND }));
}
let r = app.session.execute(COMMAND, p).map_err(|e| e.to_string())?;
let count = r["count"].as_u64().unwrap_or(0);
if r["zoom"] == true && count > 0 {
crate::addons::arrange::zoom(app)?;
}
let statuses: Vec<&str> = match &p["status"] {
Value::Array(v) => v.iter().filter_map(Value::as_str).collect(),
v => v.as_str().into_iter().collect(),
};
let reasons: Vec<&str> = r["skipped"].as_array().map_or(vec![], |v| v.iter().filter_map(|k| k["reason"].as_str()).collect());
app.status(message(&statuses, count, &reasons));
Ok(r)
}
/// The status bar's line: `count` objects of `statuses` selected, and the `reasons` the others
/// were left out for (e.g. "Selected 9 missing images; 3 more are hidden or locked").
pub(crate) fn message(statuses: &[&str], count: u64, reasons: &[&str]) -> String {
let n = count;
let selected = match statuses {
["linked"] => crate::i18n::msg_n(n, "Selected {n} linked image", "Selected {n} linked images", &[]),
["embedded"] => crate::i18n::msg_n(n, "Selected {n} embedded image", "Selected {n} embedded images", &[]),
["missing"] => crate::i18n::msg_n(n, "Selected {n} missing image", "Selected {n} missing images", &[]),
["modified"] => crate::i18n::msg_n(n, "Selected {n} modified image", "Selected {n} modified images", &[]),
_ => crate::i18n::msg_n(n, "Selected {n} image", "Selected {n} images", &[]),
};
let Some(first) = reasons.first() else { return selected };
// Hidden and locked go together; a template layer, or the isolated group, alone.
fn kind(r: &str) -> &str {
match r {
"hidden" | "locked" => "locked",
r => r,
}
}
let (one, other) = match kind(first) {
k if reasons.iter().any(|r| kind(r) != k) => ("{selected}; {n} more can't be selected now", "{selected}; {n} more can't be selected now"),
"template" => ("{selected}; {n} more is on a template layer", "{selected}; {n} more are on template layers"),
"isolation" => ("{selected}; {n} more is outside the isolated group", "{selected}; {n} more are outside the isolated group"),
_ => ("{selected}; {n} more is hidden or locked", "{selected}; {n} more are hidden or locked"),
};
crate::i18n::msg_n(reasons.len() as u64, one, other, &[("selected", &selected)])
}
/// The dialog's fields to start with: every image and placed document (`__rows`, as `links.list`
/// lists them, read once), those selected chosen, All shown, Zoom to Selection on.
pub(crate) fn fields(app: &mut VectorcraftApp) -> Value {
let list = app.session.execute("links.list", &json!({})).unwrap_or_default();
let rows: Vec<Value> = list["links"].as_array().cloned().unwrap_or_default();
let selected: Vec<u64> = app.session.active().map(|st| st.selection.objects.iter().map(|id| id.0).collect()).unwrap_or_default();
let chosen: Vec<u64> = rows.iter().filter_map(|r| r["id"].as_u64()).filter(|id| selected.contains(id)).collect();
json!({ "__rows": rows, "ids": chosen, "show": "all", "zoom": true })
}
pub(crate) const SPEC: DialogSpec = DialogSpec {
heading: |_| tl!("Select by Link Status").to_string(),
body,
confirm,
ok: Some("Select"),
min_width: 420.0,
max_width: Some(480.0),
ok_enabled: Some(|_, d| !chosen(d).is_empty()),
..DialogSpec::FORM
};
/// The ids chosen in dialog `d`.
pub(crate) fn chosen(d: &Dialog) -> Vec<u64> {
d.fields.get("ids").and_then(Value::as_array).into_iter().flatten().filter_map(Value::as_u64).collect()
}
/// The rows of `rows` the name search `query` (ignoring case) and the Show choice `show` let through.
pub(crate) fn shown<'a>(rows: &'a [Value], query: &str, show: &str) -> Vec<&'a Value> {
let q = query.trim().to_lowercase();
rows.iter()
.filter(|r| show == "all" || command_status(r) == show)
.filter(|r| q.is_empty() || r["name"].as_str().unwrap_or_default().to_lowercase().contains(&q))
.collect()
}
/// All (`on`) or None: choose every row `shown`, or none of them; rows the search or Show hides
/// keep their state.
pub(crate) fn choose_shown(chosen: &mut Vec<u64>, shown: &[u64], on: bool) {
if on {
for id in shown {
if !chosen.contains(id) {
chosen.push(*id);
}
}
} else {
chosen.retain(|id| !shown.contains(id));
}
}
/// Tick or untick row `id`.
pub(crate) fn toggle(chosen: &mut Vec<u64>, id: u64) {
match chosen.iter().position(|c| *c == id) {
Some(i) => {
chosen.remove(i);
}
None => chosen.push(id),
}
}
/// A status's label in the list.
fn status_label(status: &str) -> &'static str {
STATUSES.iter().find(|(s, ..)| *s == status).map_or("", |&(.., label)| tl!(label))
}
fn body(_app: &mut VectorcraftApp, ui: &mut Ui, d: &mut Dialog) -> bool {
let t = Tokens::get(ui.ctx());
let rows: Vec<Value> = d.fields.get("__rows").and_then(Value::as_array).cloned().unwrap_or_default();
let query = widgets::search_field(ui, ui.scope_id().with("select-by-link-status-search"), tl!("Search images"));
d.fields.insert("__search".into(), json!(query));
ui.add_space(4.0);
form::choice(ui, d, "show", tl!("Show:"), (60.0, 140.0), &SHOW);
let show = d.str("show");
let visible = shown(&rows, &query, &show);
let mut picked = chosen(d);
ui.add_space(4.0);
egui::ScrollArea::vertical().max_height(LIST_H).auto_shrink([false, true]).show(ui, |ui| {
if visible.is_empty() {
ui.label(egui::RichText::new(tl!("No images match.")).color(t.text_dim));
}
for r in &visible {
let Some(id) = r["id"].as_u64() else { continue };
let name = r["name"].as_str().unwrap_or_default();
let status = status_label(command_status(r));
let format = r["format"].as_str().unwrap_or_default();
ui.horizontal(|ui| {
ui.set_min_height(ROW_H);
let on = picked.contains(&id);
let name_w = (ui.available_width() - STATUS_W - FORMAT_W - 40.0).max(60.0);
let check = ui.scope(|ui| {
ui.set_width(name_w + 24.0);
widgets::check_name(ui, name, on)
});
if check.inner {
toggle(&mut picked, id);
}
ui.add_sized(vec2(STATUS_W, ROW_H), egui::Label::new(egui::RichText::new(status).color(t.text_dim)).truncate());
ui.add_sized(vec2(FORMAT_W, ROW_H), egui::Label::new(egui::RichText::new(format).color(t.text_dim)).truncate());
});
}
});
ui.add_space(4.0);
let ids: Vec<u64> = visible.iter().filter_map(|r| r["id"].as_u64()).collect();
ui.horizontal(|ui| {
if widgets::flat_button_fit(ui, "All", 50.0).clicked() {
choose_shown(&mut picked, &ids, true);
}
if widgets::flat_button_fit(ui, "None", 50.0).clicked() {
choose_shown(&mut picked, &ids, false);
}
let count = crate::i18n::fmt(tl!("Chosen: {n} of {total}"), &[("n", &picked.len().to_string()), ("total", &rows.len().to_string())]);
ui.label(egui::RichText::new(count).color(t.text_dim));
});
d.fields.insert("ids".into(), json!(picked));
ui.add_space(6.0);
form::check(ui, d, "zoom", tl!("Zoom to Selection"));
false
}
/// The command's params for dialog `d`: the rows chosen, whatever their status.
pub(crate) fn params(d: &Dialog) -> Value {
json!({ "status": STATUSES.map(|(s, ..)| s), "ids": chosen(d), "zoom": d.bool("zoom") })
}
/// Select: select the rows chosen (and zoom to them) and close.
fn confirm(app: &mut VectorcraftApp, d: &Dialog) -> Result<Value, String> {
app.ui.dialog = None;
app.run(COMMAND, params(d))
}
#[cfg(test)]
mod tests;
@@ -0,0 +1,199 @@
use serde_json::{Value, json};
use vectorcraft_engine::Session;
use super::{COMMAND, KIND, choose_shown, message, refresh, shown, toggle};
use crate::tests_labels::painted_text;
use crate::{VectorcraftApp, menus};
/// A fresh folder for one test (removed when dropped).
struct Folder(std::path::PathBuf);
impl Folder {
fn new(name: &str) -> Self {
let dir = std::env::temp_dir().join(format!("vectorcraft-ui-select-links-{name}-{}", std::process::id()));
let _ = std::fs::remove_dir_all(&dir);
std::fs::create_dir_all(&dir).unwrap();
Self(dir)
}
fn file(&self, name: &str, bytes: &[u8]) -> String {
let p = self.0.join(name);
std::fs::write(&p, bytes).unwrap();
p.to_string_lossy().into_owned()
}
}
impl Drop for Folder {
fn drop(&mut self) {
let _ = std::fs::remove_dir_all(&self.0);
}
}
fn png(w: u32, h: u32) -> Vec<u8> {
let mut out = vec![];
image::RgbaImage::from_pixel(w, h, image::Rgba([200, 40, 40, 255]))
.write_to(&mut std::io::Cursor::new(&mut out), image::ImageFormat::Png)
.unwrap();
out
}
/// A document with `river.png` linked, `harbour.png` linked and then deleted (missing), and
/// `stamp.png` embedded → (app, river, harbour, stamp).
fn app(dir: &Folder) -> (VectorcraftApp, u64, u64, u64) {
let mut app = VectorcraftApp::new(Session::new(), Default::default());
app.run("file.new", json!({"width": 400, "height": 300})).unwrap();
let place = |app: &mut VectorcraftApp, path: &str, at: [u32; 2], link: bool| {
app.run("file.place", json!({"path": path, "at": at, "link": link})).unwrap()["ids"][0].as_u64().unwrap()
};
let (a, b, c) = (dir.file("river.png", &png(40, 30)), dir.file("harbour.png", &png(30, 20)), dir.file("stamp.png", &png(20, 20)));
let river = place(&mut app, &a, [100, 100], true);
let harbour = place(&mut app, &b, [300, 100], true);
let stamp = place(&mut app, &c, [200, 220], false);
std::fs::remove_file(&b).unwrap();
app.run("select.none", json!({})).unwrap();
(app, river, harbour, stamp)
}
fn selected(app: &VectorcraftApp) -> Vec<u64> {
let mut ids: Vec<u64> = app.session.active().unwrap().selection.objects.iter().map(|id| id.0).collect();
ids.sort_unstable();
ids
}
#[test]
fn the_message_says_what_was_selected_and_what_was_left_out() {
assert_eq!(message(&["missing"], 9, &[]), "Selected 9 missing images");
assert_eq!(message(&["linked"], 1, &[]), "Selected 1 linked image");
assert_eq!(message(&["embedded", "modified"], 2, &[]), "Selected 2 images");
assert_eq!(message(&["missing"], 9, &["hidden", "locked", "hidden"]), "Selected 9 missing images; 3 more are hidden or locked");
assert_eq!(message(&["modified"], 0, &["template"]), "Selected 0 modified images; 1 more is on a template layer");
assert_eq!(message(&["embedded"], 2, &["isolation", "isolation"]), "Selected 2 embedded images; 2 more are outside the isolated group");
assert_eq!(message(&["linked"], 1, &["isolation", "locked"]), "Selected 1 linked image; 2 more can't be selected now");
}
#[test]
fn the_list_filters_by_name_and_status_and_all_and_none_act_on_the_rows_shown() {
let rows = vec![
json!({"id": 1, "name": "River.png", "status": "ok"}),
json!({"id": 2, "name": "harbour.png", "status": "missing"}),
json!({"id": 3, "name": "Stamp.png", "status": "embedded"}),
json!({"id": 4, "name": "river-2.tif", "status": "modified"}),
];
let ids = |v: Vec<&Value>| v.iter().map(|r| r["id"].as_u64().unwrap()).collect::<Vec<_>>();
assert_eq!(ids(shown(&rows, "", "all")), vec![1, 2, 3, 4]);
assert_eq!(ids(shown(&rows, " RIVER ", "all")), vec![1, 4]);
assert_eq!(ids(shown(&rows, "river", "linked")), vec![1], "ok is Linked");
assert_eq!(ids(shown(&rows, "", "missing")), vec![2]);
assert_eq!(ids(shown(&rows, "zzz", "all")), Vec::<u64>::new());
// Row 3 is chosen but hidden: neither All nor None touches it.
let mut c = vec![3];
choose_shown(&mut c, &[1, 4], true);
assert_eq!(c, vec![3, 1, 4]);
choose_shown(&mut c, &[1, 4], false);
assert_eq!(c, vec![3]);
toggle(&mut c, 2);
toggle(&mut c, 3);
assert_eq!(c, vec![2]);
}
#[test]
fn menu_items_are_on_for_the_statuses_present_and_shift_adds() {
let dir = Folder::new("menu");
let (mut app, river, harbour, stamp) = app(&dir);
refresh(&mut app, 0.0);
let entries = menus::menu_entries(&app);
let item = |label: &str| entries.iter().find(|e| e.path == ["Object", "Plug-ins", "Selection Tools"] && e.label == label).unwrap();
for (label, on) in
[("Select Linked", true), ("Select Embedded", true), ("Select Missing", true), ("Select Modified", false), ("Select by Link Status…", true)]
{
assert_eq!(item(label).enabled, on, "{label}");
}
let run = |app: &mut VectorcraftApp, label: &str, shift: bool| {
let e = item(label);
let target = menus::click_target(&e.label, e.command.as_deref().unwrap(), &e.params);
let held = if shift { egui::Modifiers::SHIFT } else { egui::Modifiers::NONE };
let (cmd, p) = menus::with_held_keys(target, held);
menus::invoke(app, &cmd, p);
};
run(&mut app, "Select Missing", false);
assert_eq!(selected(&app), vec![harbour]);
assert_eq!(app.ui.status, "Selected 1 missing image");
run(&mut app, "Select Embedded", true);
assert_eq!(selected(&app), vec![harbour, stamp], "Shift adds");
run(&mut app, "Select Linked", false);
assert_eq!(selected(&app), vec![river], "without Shift it replaces");
// A hidden image is left out, and the status bar says so.
app.run("object.setProps", json!({"ids": [river], "visible": false})).unwrap();
run(&mut app, "Select Linked", false);
assert_eq!(selected(&app), Vec::<u64>::new());
assert_eq!(app.ui.status, "Selected 0 linked images; 1 more is hidden or locked");
// The document changes: the items follow on the next refresh.
app.run("select.set", json!({"ids": [harbour]})).unwrap();
app.run("edit.clear", json!({})).unwrap();
refresh(&mut app, 1.0);
let entries = menus::menu_entries(&app);
let on = |label: &str| entries.iter().find(|e| e.path == ["Object", "Plug-ins", "Selection Tools"] && e.label == label).unwrap().enabled;
assert!(!on("Select Missing"));
assert!(on("Select Embedded"));
}
#[test]
fn the_links_panel_menu_lists_the_select_items() {
let dir = Folder::new("flyout");
let (mut app, ..) = app(&dir);
refresh(&mut app, 0.0);
let shown = painted_text(&mut app, crate::panels::links::menu);
for s in ["Select Linked", "Select Embedded", "Select Missing", "Select Modified"] {
assert!(shown.contains(s), "{s} in {shown}");
}
}
#[test]
fn the_dialog_lists_filters_and_selects_with_zoom() {
let dir = Folder::new("dialog");
let (mut app, river, harbour, stamp) = app(&dir);
app.canvas_rect = Some(egui::Rect::from_min_size(egui::Pos2::ZERO, egui::vec2(560.0, 460.0)));
let zoom_before = app.view().unwrap().zoom;
menus::invoke(&mut app, COMMAND, Value::Null);
let d = app.ui.dialog.as_ref().unwrap();
assert_eq!((d.kind.as_str(), &d.fields["zoom"], &d.fields["show"]), (KIND, &json!(true), &json!("all")));
let shown = painted_text(&mut app, |app, ui| crate::dialogs::show(app, ui.ctx()));
for s in [
"Select by Link Status",
"river.png",
"harbour.png",
"stamp.png",
"Linked",
"Missing",
"Embedded",
"PNG",
"Zoom to Selection",
"Chosen: 0 of 3",
"All",
"None",
"Select",
] {
assert!(shown.contains(s), "{s} in {shown}");
}
assert!(!(super::SPEC.ok_enabled.unwrap())(&app, app.ui.dialog.as_ref().unwrap()), "Select is off with nothing chosen");
// Show: Missing lists only the missing image.
app.ui.dialog.as_mut().unwrap().fields.insert("show".into(), json!("missing"));
let shown = painted_text(&mut app, |app, ui| crate::dialogs::show(app, ui.ctx()));
assert!(shown.contains("harbour.png") && !shown.contains("river.png") && !shown.contains("stamp.png"), "{shown}");
// Choose two and Select: they are selected and the view zooms to them.
let d = app.ui.dialog.as_mut().unwrap();
d.fields.insert("ids".into(), json!([river, stamp]));
crate::dialogs::confirm(&mut app).unwrap();
assert!(app.ui.dialog.is_none());
assert_eq!(selected(&app), vec![river, stamp]);
assert_eq!(app.ui.status, "Selected 2 images");
assert_ne!(app.view().unwrap().zoom, zoom_before, "zoomed to the selection");
// Without Zoom to Selection the view stays.
menus::invoke(&mut app, COMMAND, Value::Null);
let zoom = app.view().unwrap().zoom;
let d = app.ui.dialog.as_mut().unwrap();
d.fields.insert("ids".into(), json!([harbour]));
d.fields.insert("zoom".into(), json!(false));
crate::dialogs::confirm(&mut app).unwrap();
assert_eq!(selected(&app), vec![harbour]);
assert_eq!(app.view().unwrap().zoom, zoom);
}
+1
View File
@@ -314,6 +314,7 @@ impl VectorcraftApp {
placing::poll(self);
#[cfg(not(target_arch = "wasm32"))]
self.tick_link_updates(ctx, now);
crate::addons::select::link_status::refresh(self, now);
if !self.background.jobs.is_empty()
|| !self.opening.pending.is_empty()
|| !self.plugin_runs.running.is_empty()
+1
View File
@@ -422,6 +422,7 @@ registry! {
SwatchLegend: [crate::addons::color::legend::KIND] => crate::addons::color::legend::SPEC,
TextTweaker: [crate::addons::typetools::KIND] => crate::addons::typetools::SPEC,
SelectByArtboards: [crate::addons::select::KIND] => crate::addons::select::SPEC,
SelectByLinkStatus: [crate::addons::select::link_status::KIND] => crate::addons::select::link_status::SPEC,
ArrangeTools: [crate::addons::arrange::GRID, crate::addons::arrange::REPLACE, crate::addons::arrange::SIZE, crate::addons::arrange::OPACITY, crate::addons::arrange::SORT] => crate::addons::arrange::SPEC,
ShortcutImport: [shortcut_import::KIND] => DialogSpec::window(shortcut_import::show, shortcut_import::confirm),
}
+19
View File
@@ -6215,6 +6215,25 @@ breakText Glyphs Глифи
Minimum angle Минимален ъгъл
Maximum angle Максимален ъгъл
# Selection Tools add-on: Select by Link Status (Object › Plug-ins › Selection Tools, the Links panel menu, #5526).
Select Linked Избиране на свързаните
Select Embedded Избиране на вградените
Select Missing Избиране на липсващите
Select Modified Избиране на модифицираните
Select by Link Status Избиране по състояние на връзката
Select by Link Status… Избиране по състояние на връзката…
Search images Търсене на изображения
No images match. Няма съвпадащи изображения.
@msgplural Selected {n} linked image|Selected {n} linked images Избрано е {n} свързано изображение|Избрани са {n} свързани изображения
@msgplural Selected {n} embedded image|Selected {n} embedded images Избрано е {n} вградено изображение|Избрани са {n} вградени изображения
@msgplural Selected {n} missing image|Selected {n} missing images Избрано е {n} липсващо изображение|Избрани са {n} липсващи изображения
@msgplural Selected {n} modified image|Selected {n} modified images Избрано е {n} модифицирано изображение|Избрани са {n} модифицирани изображения
@msgplural Selected {n} image|Selected {n} images Избрано е {n} изображение|Избрани са {n} изображения
@msgplural {selected}; {n} more is hidden or locked|{selected}; {n} more are hidden or locked {selected}; още {n} е скрито или заключено|{selected}; още {n} са скрити или заключени
@msgplural {selected}; {n} more is on a template layer|{selected}; {n} more are on template layers {selected}; още {n} е в шаблонен слой|{selected}; още {n} са в шаблонни слоеве
@msgplural {selected}; {n} more is outside the isolated group|{selected}; {n} more are outside the isolated group {selected}; още {n} е извън изолираната група|{selected}; още {n} са извън изолираната група
@msgplural {selected}; {n} more can't be selected now|{selected}; {n} more can't be selected now {selected}; още {n} не може да бъде избрано сега|{selected}; още {n} не могат да бъдат избрани сега
# Compound Shapes add-on
Compound Shapes Съставни фигури
Shape Mode Buttons Make Compound Shapes Бутоните за режими на фигури създават съставни фигури
Can't render this file because it contains an unexpected character in line 2 and column 73.
+19
View File
@@ -6250,6 +6250,25 @@ shape Open Otvoren
Minimum angle Najmanji ugao
Maximum angle Najveći ugao
# Selection Tools add-on: Select by Link Status (Object › Plug-ins › Selection Tools, the Links panel menu, #5526).
Select Linked Odaberi povezane
Select Embedded Odaberi ugrađene
Select Missing Odaberi nedostajuće
Select Modified Odaberi izmijenjene
Select by Link Status Odabir po statusu veze
Select by Link Status… Odabir po statusu veze…
Search images Pretraži slike
No images match. Nijedna slika ne odgovara.
@msgplural Selected {n} linked image|Selected {n} linked images Odabrana je {n} povezana slika|Odabrane su {n} povezane slike|Odabrano je {n} povezanih slika
@msgplural Selected {n} embedded image|Selected {n} embedded images Odabrana je {n} ugrađena slika|Odabrane su {n} ugrađene slike|Odabrano je {n} ugrađenih slika
@msgplural Selected {n} missing image|Selected {n} missing images Odabrana je {n} nedostajuća slika|Odabrane su {n} nedostajuće slike|Odabrano je {n} nedostajućih slika
@msgplural Selected {n} modified image|Selected {n} modified images Odabrana je {n} izmijenjena slika|Odabrane su {n} izmijenjene slike|Odabrano je {n} izmijenjenih slika
@msgplural Selected {n} image|Selected {n} images Odabrana je {n} slika|Odabrane su {n} slike|Odabrano je {n} slika
@msgplural {selected}; {n} more is hidden or locked|{selected}; {n} more are hidden or locked {selected}; još {n} je skrivena ili zaključana|{selected}; još {n} su skrivene ili zaključane|{selected}; još {n} je skriveno ili zaključano
@msgplural {selected}; {n} more is on a template layer|{selected}; {n} more are on template layers {selected}; još {n} je na sloju predloška|{selected}; još {n} su na slojevima predloška|{selected}; još {n} je na slojevima predloška
@msgplural {selected}; {n} more is outside the isolated group|{selected}; {n} more are outside the isolated group {selected}; još {n} je izvan izolirane grupe|{selected}; još {n} su izvan izolirane grupe|{selected}; još {n} je izvan izolirane grupe
@msgplural {selected}; {n} more can't be selected now|{selected}; {n} more can't be selected now {selected}; još {n} se sada ne može odabrati|{selected}; još {n} se sada ne mogu odabrati|{selected}; još {n} se sada ne može odabrati
# Compound Shapes add-on
Compound Shapes Složeni oblici
Shape Mode Buttons Make Compound Shapes Tasteri načina oblika prave složene oblike
Can't render this file because it contains an unexpected character in line 2 and column 73.
+19
View File
@@ -6351,6 +6351,25 @@ breakText Glyphs Glifs
Minimum angle Angle mínim
Maximum angle Angle màxim
# Selection Tools add-on: Select by Link Status (Object › Plug-ins › Selection Tools, the Links panel menu, #5526).
Select Linked Selecciona les enllaçades
Select Embedded Selecciona les incrustades
Select Missing Selecciona les que falten
Select Modified Selecciona les modificades
Select by Link Status Selecciona per estat de l’enllaç
Select by Link Status… Selecciona per estat de l’enllaç…
Search images Cerca imatges
No images match. Cap imatge no coincideix.
@msgplural Selected {n} linked image|Selected {n} linked images S’ha seleccionat {n} imatge enllaçada|S’han seleccionat {n} imatges enllaçades
@msgplural Selected {n} embedded image|Selected {n} embedded images S’ha seleccionat {n} imatge incrustada|S’han seleccionat {n} imatges incrustades
@msgplural Selected {n} missing image|Selected {n} missing images S’ha seleccionat {n} imatge que falta|S’han seleccionat {n} imatges que falten
@msgplural Selected {n} modified image|Selected {n} modified images S’ha seleccionat {n} imatge modificada|S’han seleccionat {n} imatges modificades
@msgplural Selected {n} image|Selected {n} images S’ha seleccionat {n} imatge|S’han seleccionat {n} imatges
@msgplural {selected}; {n} more is hidden or locked|{selected}; {n} more are hidden or locked {selected}; {n} més està oculta o bloquejada|{selected}; {n} més estan ocultes o bloquejades
@msgplural {selected}; {n} more is on a template layer|{selected}; {n} more are on template layers {selected}; {n} més és en una capa de plantilla|{selected}; {n} més són en capes de plantilla
@msgplural {selected}; {n} more is outside the isolated group|{selected}; {n} more are outside the isolated group {selected}; {n} més és fora del grup aïllat|{selected}; {n} més són fora del grup aïllat
@msgplural {selected}; {n} more can't be selected now|{selected}; {n} more can't be selected now {selected}; {n} més no es pot seleccionar ara|{selected}; {n} més no es poden seleccionar ara
# Compound Shapes add-on
Compound Shapes Formes compostes
Shape Mode Buttons Make Compound Shapes Els botons de mode de forma creen formes compostes
Can't render this file because it contains an unexpected character in line 2 and column 73.
+19
View File
@@ -6365,6 +6365,25 @@ breakText Glyphs Glyfy
Minimum angle Minimální úhel
Maximum angle Maximální úhel
# Selection Tools add-on: Select by Link Status (Object › Plug-ins › Selection Tools, the Links panel menu, #5526).
Select Linked Vybrat propojené
Select Embedded Vybrat vložené
Select Missing Vybrat chybějící
Select Modified Vybrat upravené
Select by Link Status Vybrat podle stavu propojení
Select by Link Status… Vybrat podle stavu propojení…
Search images Hledat obrazy
No images match. Žádný obraz neodpovídá.
@msgplural Selected {n} linked image|Selected {n} linked images Vybrán {n} propojený obraz|Vybrány {n} propojené obrazy|Vybráno {n} propojených obrazů
@msgplural Selected {n} embedded image|Selected {n} embedded images Vybrán {n} vložený obraz|Vybrány {n} vložené obrazy|Vybráno {n} vložených obrazů
@msgplural Selected {n} missing image|Selected {n} missing images Vybrán {n} chybějící obraz|Vybrány {n} chybějící obrazy|Vybráno {n} chybějících obrazů
@msgplural Selected {n} modified image|Selected {n} modified images Vybrán {n} upravený obraz|Vybrány {n} upravené obrazy|Vybráno {n} upravených obrazů
@msgplural Selected {n} image|Selected {n} images Vybrán {n} obraz|Vybrány {n} obrazy|Vybráno {n} obrazů
@msgplural {selected}; {n} more is hidden or locked|{selected}; {n} more are hidden or locked {selected}; další {n} je skrytý nebo zamčený|{selected}; další {n} jsou skryté nebo zamčené|{selected}; dalších {n} je skrytých nebo zamčených
@msgplural {selected}; {n} more is on a template layer|{selected}; {n} more are on template layers {selected}; další {n} je na vrstvě šablony|{selected}; další {n} jsou na vrstvách šablony|{selected}; dalších {n} je na vrstvách šablony
@msgplural {selected}; {n} more is outside the isolated group|{selected}; {n} more are outside the isolated group {selected}; další {n} je mimo izolovanou skupinu|{selected}; další {n} jsou mimo izolovanou skupinu|{selected}; dalších {n} je mimo izolovanou skupinu
@msgplural {selected}; {n} more can't be selected now|{selected}; {n} more can't be selected now {selected}; další {n} teď nelze vybrat|{selected}; další {n} teď nelze vybrat|{selected}; dalších {n} teď nelze vybrat
# Compound Shapes add-on
Compound Shapes Složené tvary
Shape Mode Buttons Make Compound Shapes Tlačítka režimů tvarů vytvářejí složené tvary
Can't render this file because it contains an unexpected character in line 2 and column 73.
+19
View File
@@ -6231,6 +6231,25 @@ breakText Glyphs Glyffer
Minimum angle Mindste vinkel
Maximum angle Største vinkel
# Selection Tools add-on: Select by Link Status (Object › Plug-ins › Selection Tools, the Links panel menu, #5526).
Select Linked Markér linkede
Select Embedded Markér integrerede
Select Missing Markér manglende
Select Modified Markér ændrede
Select by Link Status Markér efter linkstatus
Select by Link Status… Markér efter linkstatus…
Search images Søg i billeder
No images match. Ingen billeder passer.
@msgplural Selected {n} linked image|Selected {n} linked images Markerede {n} linket billede|Markerede {n} linkede billeder
@msgplural Selected {n} embedded image|Selected {n} embedded images Markerede {n} integreret billede|Markerede {n} integrerede billeder
@msgplural Selected {n} missing image|Selected {n} missing images Markerede {n} manglende billede|Markerede {n} manglende billeder
@msgplural Selected {n} modified image|Selected {n} modified images Markerede {n} ændret billede|Markerede {n} ændrede billeder
@msgplural Selected {n} image|Selected {n} images Markerede {n} billede|Markerede {n} billeder
@msgplural {selected}; {n} more is hidden or locked|{selected}; {n} more are hidden or locked {selected}; {n} mere er skjult eller låst|{selected}; {n} mere er skjult eller låst
@msgplural {selected}; {n} more is on a template layer|{selected}; {n} more are on template layers {selected}; {n} mere er på et skabelonlag|{selected}; {n} mere er på skabelonlag
@msgplural {selected}; {n} more is outside the isolated group|{selected}; {n} more are outside the isolated group {selected}; {n} mere er uden for den isolerede gruppe|{selected}; {n} mere er uden for den isolerede gruppe
@msgplural {selected}; {n} more can't be selected now|{selected}; {n} more can't be selected now {selected}; {n} mere kan ikke markeres nu|{selected}; {n} mere kan ikke markeres nu
# Compound Shapes add-on
Compound Shapes Sammensatte figurer
Shape Mode Buttons Make Compound Shapes Knapper til formtilstande opretter sammensatte figurer
Can't render this file because it contains an unexpected character in line 2 and column 73.
+19
View File
@@ -5951,6 +5951,25 @@ breakText Glyphs Glyphen
Minimum angle Minimaler Winkel
Maximum angle Maximaler Winkel
# Selection Tools add-on: Select by Link Status (Object › Plug-ins › Selection Tools, the Links panel menu, #5526).
Select Linked Verknüpfte auswählen
Select Embedded Eingebettete auswählen
Select Missing Fehlende auswählen
Select Modified Geänderte auswählen
Select by Link Status Nach Verknüpfungsstatus auswählen
Select by Link Status… Nach Verknüpfungsstatus auswählen…
Search images Bilder suchen
No images match. Kein Bild passt.
@msgplural Selected {n} linked image|Selected {n} linked images {n} verknüpftes Bild ausgewählt|{n} verknüpfte Bilder ausgewählt
@msgplural Selected {n} embedded image|Selected {n} embedded images {n} eingebettetes Bild ausgewählt|{n} eingebettete Bilder ausgewählt
@msgplural Selected {n} missing image|Selected {n} missing images {n} fehlendes Bild ausgewählt|{n} fehlende Bilder ausgewählt
@msgplural Selected {n} modified image|Selected {n} modified images {n} geändertes Bild ausgewählt|{n} geänderte Bilder ausgewählt
@msgplural Selected {n} image|Selected {n} images {n} Bild ausgewählt|{n} Bilder ausgewählt
@msgplural {selected}; {n} more is hidden or locked|{selected}; {n} more are hidden or locked {selected}; {n} weiteres ist ausgeblendet oder gesperrt|{selected}; {n} weitere sind ausgeblendet oder gesperrt
@msgplural {selected}; {n} more is on a template layer|{selected}; {n} more are on template layers {selected}; {n} weiteres liegt auf einer Vorlagenebene|{selected}; {n} weitere liegen auf Vorlagenebenen
@msgplural {selected}; {n} more is outside the isolated group|{selected}; {n} more are outside the isolated group {selected}; {n} weiteres liegt außerhalb der isolierten Gruppe|{selected}; {n} weitere liegen außerhalb der isolierten Gruppe
@msgplural {selected}; {n} more can't be selected now|{selected}; {n} more can't be selected now {selected}; {n} weiteres kann gerade nicht ausgewählt werden|{selected}; {n} weitere können gerade nicht ausgewählt werden
# Compound Shapes add-on
Compound Shapes Zusammengesetzte Formen
Shape Mode Buttons Make Compound Shapes Formmodus-Schaltflächen erstellen zusammengesetzte Formen
Can't render this file because it contains an unexpected character in line 2 and column 73.
+19
View File
@@ -6317,6 +6317,25 @@ breakText Glyphs Γλύφοι
Minimum angle Ελάχιστη γωνία
Maximum angle Μέγιστη γωνία
# Selection Tools add-on: Select by Link Status (Object › Plug-ins › Selection Tools, the Links panel menu, #5526).
Select Linked Επιλογή συνδεδεμένων
Select Embedded Επιλογή ενσωματωμένων
Select Missing Επιλογή όσων λείπουν
Select Modified Επιλογή τροποποιημένων
Select by Link Status Επιλογή κατά κατάσταση σύνδεσης
Select by Link Status… Επιλογή κατά κατάσταση σύνδεσης…
Search images Αναζήτηση εικόνων
No images match. Καμία εικόνα δεν ταιριάζει.
@msgplural Selected {n} linked image|Selected {n} linked images Επιλέχθηκε {n} συνδεδεμένη εικόνα|Επιλέχθηκαν {n} συνδεδεμένες εικόνες
@msgplural Selected {n} embedded image|Selected {n} embedded images Επιλέχθηκε {n} ενσωματωμένη εικόνα|Επιλέχθηκαν {n} ενσωματωμένες εικόνες
@msgplural Selected {n} missing image|Selected {n} missing images Επιλέχθηκε {n} εικόνα που λείπει|Επιλέχθηκαν {n} εικόνες που λείπουν
@msgplural Selected {n} modified image|Selected {n} modified images Επιλέχθηκε {n} τροποποιημένη εικόνα|Επιλέχθηκαν {n} τροποποιημένες εικόνες
@msgplural Selected {n} image|Selected {n} images Επιλέχθηκε {n} εικόνα|Επιλέχθηκαν {n} εικόνες
@msgplural {selected}; {n} more is hidden or locked|{selected}; {n} more are hidden or locked {selected}· {n} ακόμη είναι κρυφή ή κλειδωμένη|{selected}· {n} ακόμη είναι κρυφές ή κλειδωμένες
@msgplural {selected}; {n} more is on a template layer|{selected}; {n} more are on template layers {selected}· {n} ακόμη είναι σε επίπεδο προτύπου|{selected}· {n} ακόμη είναι σε επίπεδα προτύπου
@msgplural {selected}; {n} more is outside the isolated group|{selected}; {n} more are outside the isolated group {selected}· {n} ακόμη είναι εκτός της απομονωμένης ομάδας|{selected}· {n} ακόμη είναι εκτός της απομονωμένης ομάδας
@msgplural {selected}; {n} more can't be selected now|{selected}; {n} more can't be selected now {selected}· {n} ακόμη δεν μπορεί να επιλεγεί τώρα|{selected}· {n} ακόμη δεν μπορούν να επιλεγούν τώρα
# Compound Shapes add-on
Compound Shapes Σύνθετα σχήματα
Shape Mode Buttons Make Compound Shapes Τα κουμπιά λειτουργιών σχημάτων δημιουργούν σύνθετα σχήματα
Can't render this file because it contains an unexpected character in line 163 and column 5.
+19
View File
@@ -6307,6 +6307,25 @@ breakText Glyphs Glifos
Minimum angle Ángulo mínimo
Maximum angle Ángulo máximo
# Selection Tools add-on: Select by Link Status (Object › Plug-ins › Selection Tools, the Links panel menu, #5526).
Select Linked Seleccionar vinculadas
Select Embedded Seleccionar incrustadas
Select Missing Seleccionar ausentes
Select Modified Seleccionar modificadas
Select by Link Status Seleccionar por estado de vínculo
Select by Link Status… Seleccionar por estado de vínculo…
Search images Buscar imágenes
No images match. Ninguna imagen coincide.
@msgplural Selected {n} linked image|Selected {n} linked images Se seleccionó {n} imagen vinculada|Se seleccionaron {n} imágenes vinculadas
@msgplural Selected {n} embedded image|Selected {n} embedded images Se seleccionó {n} imagen incrustada|Se seleccionaron {n} imágenes incrustadas
@msgplural Selected {n} missing image|Selected {n} missing images Se seleccionó {n} imagen ausente|Se seleccionaron {n} imágenes ausentes
@msgplural Selected {n} modified image|Selected {n} modified images Se seleccionó {n} imagen modificada|Se seleccionaron {n} imágenes modificadas
@msgplural Selected {n} image|Selected {n} images Se seleccionó {n} imagen|Se seleccionaron {n} imágenes
@msgplural {selected}; {n} more is hidden or locked|{selected}; {n} more are hidden or locked {selected}; {n} más está oculta o bloqueada|{selected}; {n} más están ocultas o bloqueadas
@msgplural {selected}; {n} more is on a template layer|{selected}; {n} more are on template layers {selected}; {n} más está en una capa de plantilla|{selected}; {n} más están en capas de plantilla
@msgplural {selected}; {n} more is outside the isolated group|{selected}; {n} more are outside the isolated group {selected}; {n} más está fuera del grupo aislado|{selected}; {n} más están fuera del grupo aislado
@msgplural {selected}; {n} more can't be selected now|{selected}; {n} more can't be selected now {selected}; {n} más no se puede seleccionar ahora|{selected}; {n} más no se pueden seleccionar ahora
# Compound Shapes add-on
Compound Shapes Formas compuestas
Shape Mode Buttons Make Compound Shapes Los botones de modo de forma crean formas compuestas
Can't render this file because it contains an unexpected character in line 2 and column 73.
+19
View File
@@ -6400,6 +6400,25 @@ breakText Glyphs Merkit
Minimum angle Pienin kulma
Maximum angle Suurin kulma
# Selection Tools add-on: Select by Link Status (Object › Plug-ins › Selection Tools, the Links panel menu, #5526).
Select Linked Valitse linkitetyt
Select Embedded Valitse upotetut
Select Missing Valitse puuttuvat
Select Modified Valitse muokatut
Select by Link Status Valitse linkin tilan mukaan
Select by Link Status… Valitse linkin tilan mukaan…
Search images Hae kuvia
No images match. Mikään kuva ei vastaa hakua.
@msgplural Selected {n} linked image|Selected {n} linked images Valittiin {n} linkitetty kuva|Valittiin {n} linkitettyä kuvaa
@msgplural Selected {n} embedded image|Selected {n} embedded images Valittiin {n} upotettu kuva|Valittiin {n} upotettua kuvaa
@msgplural Selected {n} missing image|Selected {n} missing images Valittiin {n} puuttuva kuva|Valittiin {n} puuttuvaa kuvaa
@msgplural Selected {n} modified image|Selected {n} modified images Valittiin {n} muokattu kuva|Valittiin {n} muokattua kuvaa
@msgplural Selected {n} image|Selected {n} images Valittiin {n} kuva|Valittiin {n} kuvaa
@msgplural {selected}; {n} more is hidden or locked|{selected}; {n} more are hidden or locked {selected}; {n} muu on piilotettu tai lukittu|{selected}; {n} muuta on piilotettu tai lukittu
@msgplural {selected}; {n} more is on a template layer|{selected}; {n} more are on template layers {selected}; {n} muu on mallitasolla|{selected}; {n} muuta on mallitasoilla
@msgplural {selected}; {n} more is outside the isolated group|{selected}; {n} more are outside the isolated group {selected}; {n} muu on eristetyn ryhmän ulkopuolella|{selected}; {n} muuta on eristetyn ryhmän ulkopuolella
@msgplural {selected}; {n} more can't be selected now|{selected}; {n} more can't be selected now {selected}; {n} muuta ei voi valita nyt|{selected}; {n} muuta ei voi valita nyt
# Compound Shapes add-on
Compound Shapes Yhdistelmämuodot
Shape Mode Buttons Make Compound Shapes Muototilapainikkeet luovat yhdistelmämuotoja
Can't render this file because it contains an unexpected character in line 2 and column 73.
+19
View File
@@ -6360,6 +6360,25 @@ breakText Glyphs Glyphes
Minimum angle Angle minimal
Maximum angle Angle maximal
# Selection Tools add-on: Select by Link Status (Object › Plug-ins › Selection Tools, the Links panel menu, #5526).
Select Linked Sélectionner les images liées
Select Embedded Sélectionner les images incorporées
Select Missing Sélectionner les images manquantes
Select Modified Sélectionner les images modifiées
Select by Link Status Sélectionner par état de lien
Select by Link Status… Sélectionner par état de lien…
Search images Rechercher des images
No images match. Aucune image ne correspond.
@msgplural Selected {n} linked image|Selected {n} linked images {n} image liée sélectionnée|{n} images liées sélectionnées
@msgplural Selected {n} embedded image|Selected {n} embedded images {n} image incorporée sélectionnée|{n} images incorporées sélectionnées
@msgplural Selected {n} missing image|Selected {n} missing images {n} image manquante sélectionnée|{n} images manquantes sélectionnées
@msgplural Selected {n} modified image|Selected {n} modified images {n} image modifiée sélectionnée|{n} images modifiées sélectionnées
@msgplural Selected {n} image|Selected {n} images {n} image sélectionnée|{n} images sélectionnées
@msgplural {selected}; {n} more is hidden or locked|{selected}; {n} more are hidden or locked {selected} ; {n} autre est masquée ou verrouillée|{selected} ; {n} autres sont masquées ou verrouillées
@msgplural {selected}; {n} more is on a template layer|{selected}; {n} more are on template layers {selected} ; {n} autre est sur un calque modèle|{selected} ; {n} autres sont sur des calques modèles
@msgplural {selected}; {n} more is outside the isolated group|{selected}; {n} more are outside the isolated group {selected} ; {n} autre est hors du groupe isolé|{selected} ; {n} autres sont hors du groupe isolé
@msgplural {selected}; {n} more can't be selected now|{selected}; {n} more can't be selected now {selected} ; {n} autre ne peut pas être sélectionnée pour l’instant|{selected} ; {n} autres ne peuvent pas être sélectionnées pour l’instant
# Compound Shapes add-on
Compound Shapes Formes composées
Shape Mode Buttons Make Compound Shapes Les boutons de mode de forme créent des formes composées
Can't render this file because it contains an unexpected character in line 2 and column 73.
+19
View File
@@ -6349,6 +6349,25 @@ breakText Glyphs Glifák
Minimum angle Legkisebb szög
Maximum angle Legnagyobb szög
# Selection Tools add-on: Select by Link Status (Object › Plug-ins › Selection Tools, the Links panel menu, #5526).
Select Linked Csatoltak kijelölése
Select Embedded Beágyazottak kijelölése
Select Missing Hiányzók kijelölése
Select Modified Módosítottak kijelölése
Select by Link Status Kijelölés csatolási állapot szerint
Select by Link Status… Kijelölés csatolási állapot szerint…
Search images Képek keresése
No images match. Nincs egyező kép.
@msgplural Selected {n} linked image|Selected {n} linked images Kijelölt csatolt képek: {n}
@msgplural Selected {n} embedded image|Selected {n} embedded images Kijelölt beágyazott képek: {n}
@msgplural Selected {n} missing image|Selected {n} missing images Kijelölt hiányzó képek: {n}
@msgplural Selected {n} modified image|Selected {n} modified images Kijelölt módosított képek: {n}
@msgplural Selected {n} image|Selected {n} images Kijelölt képek: {n}
@msgplural {selected}; {n} more is hidden or locked|{selected}; {n} more are hidden or locked {selected}; további rejtett vagy zárolt: {n}
@msgplural {selected}; {n} more is on a template layer|{selected}; {n} more are on template layers {selected}; további sablonrétegen: {n}
@msgplural {selected}; {n} more is outside the isolated group|{selected}; {n} more are outside the isolated group {selected}; további az elkülönített csoporton kívül: {n}
@msgplural {selected}; {n} more can't be selected now|{selected}; {n} more can't be selected now {selected}; további most nem jelölhető ki: {n}
# Compound Shapes add-on
Compound Shapes Összetett alakzatok
Shape Mode Buttons Make Compound Shapes Az alakzatmód-gombok összetett alakzatokat hoznak létre
Can't render this file because it contains an unexpected character in line 2 and column 73.
+19
View File
@@ -6231,6 +6231,25 @@ breakText Glyphs Glif
Minimum angle Sudut minimum
Maximum angle Sudut maksimum
# Selection Tools add-on: Select by Link Status (Object › Plug-ins › Selection Tools, the Links panel menu, #5526).
Select Linked Pilih yang Tertaut
Select Embedded Pilih yang Tersemat
Select Missing Pilih yang Hilang
Select Modified Pilih yang Diubah
Select by Link Status Pilih menurut Status Tautan
Select by Link Status… Pilih menurut Status Tautan…
Search images Cari gambar
No images match. Tidak ada gambar yang cocok.
@msgplural Selected {n} linked image|Selected {n} linked images Telah memilih {n} gambar tertaut
@msgplural Selected {n} embedded image|Selected {n} embedded images Telah memilih {n} gambar tersemat
@msgplural Selected {n} missing image|Selected {n} missing images Telah memilih {n} gambar yang hilang
@msgplural Selected {n} modified image|Selected {n} modified images Telah memilih {n} gambar yang diubah
@msgplural Selected {n} image|Selected {n} images Telah memilih {n} gambar
@msgplural {selected}; {n} more is hidden or locked|{selected}; {n} more are hidden or locked {selected}; {n} lainnya tersembunyi atau terkunci
@msgplural {selected}; {n} more is on a template layer|{selected}; {n} more are on template layers {selected}; {n} lainnya berada di layer templat
@msgplural {selected}; {n} more is outside the isolated group|{selected}; {n} more are outside the isolated group {selected}; {n} lainnya berada di luar grup yang diisolasi
@msgplural {selected}; {n} more can't be selected now|{selected}; {n} more can't be selected now {selected}; {n} lainnya tidak dapat dipilih sekarang
# Compound Shapes add-on
Compound Shapes Bentuk majemuk
Shape Mode Buttons Make Compound Shapes Tombol mode bentuk membuat bentuk majemuk
Can't render this file because it contains an unexpected character in line 2235 and column 5.
+19
View File
@@ -5985,6 +5985,25 @@ breakText Glyphs Glifi
Minimum angle Angolo minimo
Maximum angle Angolo massimo
# Selection Tools add-on: Select by Link Status (Object › Plug-ins › Selection Tools, the Links panel menu, #5526).
Select Linked Seleziona collegate
Select Embedded Seleziona incorporate
Select Missing Seleziona mancanti
Select Modified Seleziona modificate
Select by Link Status Seleziona per stato del collegamento
Select by Link Status… Seleziona per stato del collegamento…
Search images Cerca immagini
No images match. Nessuna immagine corrisponde.
@msgplural Selected {n} linked image|Selected {n} linked images Selezionata {n} immagine collegata|Selezionate {n} immagini collegate
@msgplural Selected {n} embedded image|Selected {n} embedded images Selezionata {n} immagine incorporata|Selezionate {n} immagini incorporate
@msgplural Selected {n} missing image|Selected {n} missing images Selezionata {n} immagine mancante|Selezionate {n} immagini mancanti
@msgplural Selected {n} modified image|Selected {n} modified images Selezionata {n} immagine modificata|Selezionate {n} immagini modificate
@msgplural Selected {n} image|Selected {n} images Selezionata {n} immagine|Selezionate {n} immagini
@msgplural {selected}; {n} more is hidden or locked|{selected}; {n} more are hidden or locked {selected}; altra {n} è nascosta o bloccata|{selected}; altre {n} sono nascoste o bloccate
@msgplural {selected}; {n} more is on a template layer|{selected}; {n} more are on template layers {selected}; altra {n} è su un livello modello|{selected}; altre {n} sono su livelli modello
@msgplural {selected}; {n} more is outside the isolated group|{selected}; {n} more are outside the isolated group {selected}; altra {n} è fuori dal gruppo isolato|{selected}; altre {n} sono fuori dal gruppo isolato
@msgplural {selected}; {n} more can't be selected now|{selected}; {n} more can't be selected now {selected}; altra {n} non può essere selezionata ora|{selected}; altre {n} non possono essere selezionate ora
# Compound Shapes add-on
Compound Shapes Forme composte
Shape Mode Buttons Make Compound Shapes I pulsanti dei metodi forma creano forme composte
Can't render this file because it contains an unexpected character in line 2 and column 73.
+19
View File
@@ -6050,6 +6050,25 @@ breakText Glyphs 字形
Minimum angle 最小角度
Maximum angle 最大角度
# Selection Tools add-on: Select by Link Status (Object › Plug-ins › Selection Tools, the Links panel menu, #5526).
Select Linked リンク済みを選択
Select Embedded 埋め込みを選択
Select Missing 見つからない画像を選択
Select Modified 変更された画像を選択
Select by Link Status リンクの状態で選択
Select by Link Status… リンクの状態で選択…
Search images 画像を検索
No images match. 一致する画像はありません。
@msgplural Selected {n} linked image|Selected {n} linked images リンク済みの画像を {n} 個選択しました
@msgplural Selected {n} embedded image|Selected {n} embedded images 埋め込み画像を {n} 個選択しました
@msgplural Selected {n} missing image|Selected {n} missing images 見つからない画像を {n} 個選択しました
@msgplural Selected {n} modified image|Selected {n} modified images 変更された画像を {n} 個選択しました
@msgplural Selected {n} image|Selected {n} images 画像を {n} 個選択しました
@msgplural {selected}; {n} more is hidden or locked|{selected}; {n} more are hidden or locked {selected}。ほかに {n} 個が非表示またはロックされています
@msgplural {selected}; {n} more is on a template layer|{selected}; {n} more are on template layers {selected}。ほかに {n} 個がテンプレートレイヤー上にあります
@msgplural {selected}; {n} more is outside the isolated group|{selected}; {n} more are outside the isolated group {selected}。ほかに {n} 個が分離したグループの外にあります
@msgplural {selected}; {n} more can't be selected now|{selected}; {n} more can't be selected now {selected}。ほかに {n} 個は今は選択できません
# Compound Shapes add-on
Compound Shapes 複合シェイプ
Shape Mode Buttons Make Compound Shapes シェイプモードボタンで複合シェイプを作成
Can't render this file because it contains an unexpected character in line 2 and column 73.
+19
View File
@@ -6376,6 +6376,25 @@ font-script Japanese იაპონური
Minimum angle მინიმალური კუთხე
Maximum angle მაქსიმალური კუთხე
# Selection Tools add-on: Select by Link Status (Object › Plug-ins › Selection Tools, the Links panel menu, #5526).
Select Linked დაკავშირებულების არჩევა
Select Embedded ჩაშენებულების არჩევა
Select Missing დაკარგულების არჩევა
Select Modified შეცვლილების არჩევა
Select by Link Status კავშირის მდგომარეობით არჩევა
Select by Link Status… კავშირის მდგომარეობით არჩევა…
Search images გამოსახულებების ძებნა
No images match. შესაბამისი გამოსახულება არ არის.
@msgplural Selected {n} linked image|Selected {n} linked images არჩეულია დაკავშირებული გამოსახულებები: {n}
@msgplural Selected {n} embedded image|Selected {n} embedded images არჩეულია ჩაშენებული გამოსახულებები: {n}
@msgplural Selected {n} missing image|Selected {n} missing images არჩეულია დაკარგული გამოსახულებები: {n}
@msgplural Selected {n} modified image|Selected {n} modified images არჩეულია შეცვლილი გამოსახულებები: {n}
@msgplural Selected {n} image|Selected {n} images არჩეულია გამოსახულებები: {n}
@msgplural {selected}; {n} more is hidden or locked|{selected}; {n} more are hidden or locked {selected}; დამალული ან ჩაკეტილია კიდევ: {n}
@msgplural {selected}; {n} more is on a template layer|{selected}; {n} more are on template layers {selected}; შაბლონის ფენაზეა კიდევ: {n}
@msgplural {selected}; {n} more is outside the isolated group|{selected}; {n} more are outside the isolated group {selected}; იზოლირებული ჯგუფის გარეთაა კიდევ: {n}
@msgplural {selected}; {n} more can't be selected now|{selected}; {n} more can't be selected now {selected}; ახლა ვერ აირჩევა კიდევ: {n}
# Compound Shapes add-on
Compound Shapes შედგენილი ფიგურები
Shape Mode Buttons Make Compound Shapes ფიგურის რეჟიმის ღილაკები ქმნის შედგენილ ფიგურებს
Can't render this file because it is too large.
+19
View File
@@ -5946,6 +5946,25 @@ breakText Glyphs 글리프
Minimum angle 최소 각도
Maximum angle 최대 각도
# Selection Tools add-on: Select by Link Status (Object › Plug-ins › Selection Tools, the Links panel menu, #5526).
Select Linked 연결됨 선택
Select Embedded 포함됨 선택
Select Missing 없는 이미지 선택
Select Modified 수정된 이미지 선택
Select by Link Status 링크 상태로 선택
Select by Link Status… 링크 상태로 선택…
Search images 이미지 검색
No images match. 일치하는 이미지가 없습니다.
@msgplural Selected {n} linked image|Selected {n} linked images 연결된 이미지 {n}개를 선택했습니다
@msgplural Selected {n} embedded image|Selected {n} embedded images 포함된 이미지 {n}개를 선택했습니다
@msgplural Selected {n} missing image|Selected {n} missing images 없는 이미지 {n}개를 선택했습니다
@msgplural Selected {n} modified image|Selected {n} modified images 수정된 이미지 {n}개를 선택했습니다
@msgplural Selected {n} image|Selected {n} images 이미지 {n}개를 선택했습니다
@msgplural {selected}; {n} more is hidden or locked|{selected}; {n} more are hidden or locked {selected}. {n}개는 숨겨졌거나 잠겨 있습니다
@msgplural {selected}; {n} more is on a template layer|{selected}; {n} more are on template layers {selected}. {n}개는 템플릿 레이어에 있습니다
@msgplural {selected}; {n} more is outside the isolated group|{selected}; {n} more are outside the isolated group {selected}. {n}개는 격리된 그룹 밖에 있습니다
@msgplural {selected}; {n} more can't be selected now|{selected}; {n} more can't be selected now {selected}. {n}개는 지금 선택할 수 없습니다
# Compound Shapes add-on
Compound Shapes 컴파운드 모양
Shape Mode Buttons Make Compound Shapes 모양 모드 버튼으로 컴파운드 모양 만들기
Can't render this file because it contains an unexpected character in line 2 and column 73.
+19
View File
@@ -6275,6 +6275,25 @@ breakText Glyphs Glyphs
Minimum angle Minimale hoek
Maximum angle Maximale hoek
# Selection Tools add-on: Select by Link Status (Object › Plug-ins › Selection Tools, the Links panel menu, #5526).
Select Linked Gekoppelde selecteren
Select Embedded Ingesloten selecteren
Select Missing Ontbrekende selecteren
Select Modified Gewijzigde selecteren
Select by Link Status Selecteren op koppelingsstatus
Select by Link Status… Selecteren op koppelingsstatus…
Search images Afbeeldingen zoeken
No images match. Geen afbeelding komt overeen.
@msgplural Selected {n} linked image|Selected {n} linked images {n} gekoppelde afbeelding geselecteerd|{n} gekoppelde afbeeldingen geselecteerd
@msgplural Selected {n} embedded image|Selected {n} embedded images {n} ingesloten afbeelding geselecteerd|{n} ingesloten afbeeldingen geselecteerd
@msgplural Selected {n} missing image|Selected {n} missing images {n} ontbrekende afbeelding geselecteerd|{n} ontbrekende afbeeldingen geselecteerd
@msgplural Selected {n} modified image|Selected {n} modified images {n} gewijzigde afbeelding geselecteerd|{n} gewijzigde afbeeldingen geselecteerd
@msgplural Selected {n} image|Selected {n} images {n} afbeelding geselecteerd|{n} afbeeldingen geselecteerd
@msgplural {selected}; {n} more is hidden or locked|{selected}; {n} more are hidden or locked {selected}; nog {n} is verborgen of vergrendeld|{selected}; nog {n} zijn verborgen of vergrendeld
@msgplural {selected}; {n} more is on a template layer|{selected}; {n} more are on template layers {selected}; nog {n} staat op een sjabloonlaag|{selected}; nog {n} staan op sjabloonlagen
@msgplural {selected}; {n} more is outside the isolated group|{selected}; {n} more are outside the isolated group {selected}; nog {n} staat buiten de geïsoleerde groep|{selected}; nog {n} staan buiten de geïsoleerde groep
@msgplural {selected}; {n} more can't be selected now|{selected}; {n} more can't be selected now {selected}; nog {n} kan nu niet worden geselecteerd|{selected}; nog {n} kunnen nu niet worden geselecteerd
# Compound Shapes add-on
Compound Shapes Samengestelde vormen
Shape Mode Buttons Make Compound Shapes Vormmodus-knoppen maken samengestelde vormen
Can't render this file because it contains an unexpected character in line 2 and column 73.
+19
View File
@@ -6220,6 +6220,25 @@ breakText Glyphs Glify
Minimum angle Kąt minimalny
Maximum angle Kąt maksymalny
# Selection Tools add-on: Select by Link Status (Object › Plug-ins › Selection Tools, the Links panel menu, #5526).
Select Linked Zaznacz połączone
Select Embedded Zaznacz osadzone
Select Missing Zaznacz brakujące
Select Modified Zaznacz zmodyfikowane
Select by Link Status Zaznacz według stanu połączenia
Select by Link Status… Zaznacz według stanu połączenia…
Search images Szukaj obrazów
No images match. Żaden obraz nie pasuje.
@msgplural Selected {n} linked image|Selected {n} linked images Zaznaczono {n} połączony obraz|Zaznaczono {n} połączone obrazy|Zaznaczono {n} połączonych obrazów
@msgplural Selected {n} embedded image|Selected {n} embedded images Zaznaczono {n} osadzony obraz|Zaznaczono {n} osadzone obrazy|Zaznaczono {n} osadzonych obrazów
@msgplural Selected {n} missing image|Selected {n} missing images Zaznaczono {n} brakujący obraz|Zaznaczono {n} brakujące obrazy|Zaznaczono {n} brakujących obrazów
@msgplural Selected {n} modified image|Selected {n} modified images Zaznaczono {n} zmodyfikowany obraz|Zaznaczono {n} zmodyfikowane obrazy|Zaznaczono {n} zmodyfikowanych obrazów
@msgplural Selected {n} image|Selected {n} images Zaznaczono {n} obraz|Zaznaczono {n} obrazy|Zaznaczono {n} obrazów
@msgplural {selected}; {n} more is hidden or locked|{selected}; {n} more are hidden or locked {selected}; jeszcze {n} jest ukryty lub zablokowany|{selected}; jeszcze {n} są ukryte lub zablokowane|{selected}; jeszcze {n} jest ukrytych lub zablokowanych
@msgplural {selected}; {n} more is on a template layer|{selected}; {n} more are on template layers {selected}; jeszcze {n} jest na warstwie szablonu|{selected}; jeszcze {n} są na warstwach szablonu|{selected}; jeszcze {n} jest na warstwach szablonu
@msgplural {selected}; {n} more is outside the isolated group|{selected}; {n} more are outside the isolated group {selected}; jeszcze {n} jest poza izolowaną grupą|{selected}; jeszcze {n} są poza izolowaną grupą|{selected}; jeszcze {n} jest poza izolowaną grupą
@msgplural {selected}; {n} more can't be selected now|{selected}; {n} more can't be selected now {selected}; jeszcze {n} nie można teraz zaznaczyć|{selected}; jeszcze {n} nie można teraz zaznaczyć|{selected}; jeszcze {n} nie można teraz zaznaczyć
# Compound Shapes add-on
Compound Shapes Kształty złożone
Shape Mode Buttons Make Compound Shapes Przyciski trybów kształtu tworzą kształty złożone
Can't render this file because it contains an unexpected character in line 2 and column 73.
+19
View File
@@ -6438,6 +6438,25 @@ swatch Yellow Green Verde-amarelado
Minimum angle Ângulo Mínimo
Maximum angle Ângulo Máximo
# Selection Tools add-on: Select by Link Status (Object › Plug-ins › Selection Tools, the Links panel menu, #5526).
Select Linked Selecionar vinculadas
Select Embedded Selecionar incorporadas
Select Missing Selecionar ausentes
Select Modified Selecionar modificadas
Select by Link Status Selecionar por status do vínculo
Select by Link Status… Selecionar por status do vínculo…
Search images Pesquisar imagens
No images match. Nenhuma imagem corresponde.
@msgplural Selected {n} linked image|Selected {n} linked images {n} imagem vinculada selecionada|{n} imagens vinculadas selecionadas
@msgplural Selected {n} embedded image|Selected {n} embedded images {n} imagem incorporada selecionada|{n} imagens incorporadas selecionadas
@msgplural Selected {n} missing image|Selected {n} missing images {n} imagem ausente selecionada|{n} imagens ausentes selecionadas
@msgplural Selected {n} modified image|Selected {n} modified images {n} imagem modificada selecionada|{n} imagens modificadas selecionadas
@msgplural Selected {n} image|Selected {n} images {n} imagem selecionada|{n} imagens selecionadas
@msgplural {selected}; {n} more is hidden or locked|{selected}; {n} more are hidden or locked {selected}; mais {n} está oculta ou bloqueada|{selected}; mais {n} estão ocultas ou bloqueadas
@msgplural {selected}; {n} more is on a template layer|{selected}; {n} more are on template layers {selected}; mais {n} está em uma camada de modelo|{selected}; mais {n} estão em camadas de modelo
@msgplural {selected}; {n} more is outside the isolated group|{selected}; {n} more are outside the isolated group {selected}; mais {n} está fora do grupo isolado|{selected}; mais {n} estão fora do grupo isolado
@msgplural {selected}; {n} more can't be selected now|{selected}; {n} more can't be selected now {selected}; mais {n} não pode ser selecionada agora|{selected}; mais {n} não podem ser selecionadas agora
# Compound Shapes add-on
Compound Shapes Formas Compostas
Shape Mode Buttons Make Compound Shapes Os Botões de Modo de Forma Criam Formas Compostas
Can't render this file because it contains an unexpected character in line 6 and column 47.
+19
View File
@@ -6454,6 +6454,25 @@ shape Open Открытый
Minimum angle Минимальный угол
Maximum angle Максимальный угол
# Selection Tools add-on: Select by Link Status (Object › Plug-ins › Selection Tools, the Links panel menu, #5526).
Select Linked Выделить связанные
Select Embedded Выделить внедрённые
Select Missing Выделить отсутствующие
Select Modified Выделить изменённые
Select by Link Status Выделить по состоянию связи
Select by Link Status… Выделить по состоянию связи…
Search images Поиск изображений
No images match. Нет подходящих изображений.
@msgplural Selected {n} linked image|Selected {n} linked images Выделено {n} связанное изображение|Выделено {n} связанных изображения|Выделено {n} связанных изображений
@msgplural Selected {n} embedded image|Selected {n} embedded images Выделено {n} внедрённое изображение|Выделено {n} внедрённых изображения|Выделено {n} внедрённых изображений
@msgplural Selected {n} missing image|Selected {n} missing images Выделено {n} отсутствующее изображение|Выделено {n} отсутствующих изображения|Выделено {n} отсутствующих изображений
@msgplural Selected {n} modified image|Selected {n} modified images Выделено {n} изменённое изображение|Выделено {n} изменённых изображения|Выделено {n} изменённых изображений
@msgplural Selected {n} image|Selected {n} images Выделено {n} изображение|Выделено {n} изображения|Выделено {n} изображений
@msgplural {selected}; {n} more is hidden or locked|{selected}; {n} more are hidden or locked {selected}; ещё {n} скрыто или заблокировано|{selected}; ещё {n} скрыты или заблокированы|{selected}; ещё {n} скрыты или заблокированы
@msgplural {selected}; {n} more is on a template layer|{selected}; {n} more are on template layers {selected}; ещё {n} на слое-шаблоне|{selected}; ещё {n} на слоях-шаблонах|{selected}; ещё {n} на слоях-шаблонах
@msgplural {selected}; {n} more is outside the isolated group|{selected}; {n} more are outside the isolated group {selected}; ещё {n} вне изолированной группы|{selected}; ещё {n} вне изолированной группы|{selected}; ещё {n} вне изолированной группы
@msgplural {selected}; {n} more can't be selected now|{selected}; {n} more can't be selected now {selected}; ещё {n} сейчас нельзя выделить|{selected}; ещё {n} сейчас нельзя выделить|{selected}; ещё {n} сейчас нельзя выделить
# Compound Shapes add-on
Compound Shapes Составные фигуры
Shape Mode Buttons Make Compound Shapes Кнопки режимов фигур создают составные фигуры
Can't render this file because it contains an unexpected character in line 2 and column 73.
+19
View File
@@ -6421,6 +6421,25 @@ digits Hindi Hindi
Minimum angle Minsta vinkel
Maximum angle Största vinkel
# Selection Tools add-on: Select by Link Status (Object › Plug-ins › Selection Tools, the Links panel menu, #5526).
Select Linked Markera länkade
Select Embedded Markera inbäddade
Select Missing Markera saknade
Select Modified Markera ändrade
Select by Link Status Markera efter länkstatus
Select by Link Status… Markera efter länkstatus…
Search images Sök bilder
No images match. Ingen bild matchar.
@msgplural Selected {n} linked image|Selected {n} linked images Markerade {n} länkad bild|Markerade {n} länkade bilder
@msgplural Selected {n} embedded image|Selected {n} embedded images Markerade {n} inbäddad bild|Markerade {n} inbäddade bilder
@msgplural Selected {n} missing image|Selected {n} missing images Markerade {n} saknad bild|Markerade {n} saknade bilder
@msgplural Selected {n} modified image|Selected {n} modified images Markerade {n} ändrad bild|Markerade {n} ändrade bilder
@msgplural Selected {n} image|Selected {n} images Markerade {n} bild|Markerade {n} bilder
@msgplural {selected}; {n} more is hidden or locked|{selected}; {n} more are hidden or locked {selected}; {n} till är dold eller låst|{selected}; {n} till är dolda eller låsta
@msgplural {selected}; {n} more is on a template layer|{selected}; {n} more are on template layers {selected}; {n} till ligger på ett mallager|{selected}; {n} till ligger på mallager
@msgplural {selected}; {n} more is outside the isolated group|{selected}; {n} more are outside the isolated group {selected}; {n} till ligger utanför den isolerade gruppen|{selected}; {n} till ligger utanför den isolerade gruppen
@msgplural {selected}; {n} more can't be selected now|{selected}; {n} more can't be selected now {selected}; {n} till kan inte markeras nu|{selected}; {n} till kan inte markeras nu
# Compound Shapes add-on
Compound Shapes Sammansatta former
Shape Mode Buttons Make Compound Shapes Formlägesknapparna skapar sammansatta former
Can't render this file because it contains an unexpected character in line 5 and column 25.
+19
View File
@@ -6322,6 +6322,25 @@ breakText Glyphs Glifler
Minimum angle En Küçük Açı
Maximum angle En Büyük Açı
# Selection Tools add-on: Select by Link Status (Object › Plug-ins › Selection Tools, the Links panel menu, #5526).
Select Linked Bağlantılıları Seç
Select Embedded Gömülüleri Seç
Select Missing Eksikleri Seç
Select Modified Değiştirilenleri Seç
Select by Link Status Bağlantı Durumuna Göre Seç
Select by Link Status… Bağlantı Durumuna Göre Seç…
Search images Görüntülerde ara
No images match. Eşleşen görüntü yok.
@msgplural Selected {n} linked image|Selected {n} linked images {n} bağlantılı görüntü seçildi
@msgplural Selected {n} embedded image|Selected {n} embedded images {n} gömülü görüntü seçildi
@msgplural Selected {n} missing image|Selected {n} missing images {n} eksik görüntü seçildi
@msgplural Selected {n} modified image|Selected {n} modified images {n} değiştirilmiş görüntü seçildi
@msgplural Selected {n} image|Selected {n} images {n} görüntü seçildi
@msgplural {selected}; {n} more is hidden or locked|{selected}; {n} more are hidden or locked {selected}; {n} tane daha gizli veya kilitli
@msgplural {selected}; {n} more is on a template layer|{selected}; {n} more are on template layers {selected}; {n} tane daha şablon katmanında
@msgplural {selected}; {n} more is outside the isolated group|{selected}; {n} more are outside the isolated group {selected}; {n} tane daha izole grubun dışında
@msgplural {selected}; {n} more can't be selected now|{selected}; {n} more can't be selected now {selected}; {n} tane daha şu anda seçilemiyor
# Compound Shapes add-on
Compound Shapes Bileşik Şekiller
Shape Mode Buttons Make Compound Shapes Şekil Modu Düğmeleri Bileşik Şekiller Yapar
Can't render this file because it contains an unexpected character in line 5 and column 25.
+19
View File
@@ -5965,6 +5965,25 @@ breakText Glyphs Гліфи
Minimum angle Мінімальний кут
Maximum angle Максимальний кут
# Selection Tools add-on: Select by Link Status (Object › Plug-ins › Selection Tools, the Links panel menu, #5526).
Select Linked Виділити пов’язані
Select Embedded Виділити вбудовані
Select Missing Виділити відсутні
Select Modified Виділити змінені
Select by Link Status Виділити за станом зв’язку
Select by Link Status… Виділити за станом зв’язку…
Search images Пошук зображень
No images match. Немає відповідних зображень.
@msgplural Selected {n} linked image|Selected {n} linked images Виділено {n} пов’язане зображення|Виділено {n} пов’язані зображення|Виділено {n} пов’язаних зображень
@msgplural Selected {n} embedded image|Selected {n} embedded images Виділено {n} вбудоване зображення|Виділено {n} вбудовані зображення|Виділено {n} вбудованих зображень
@msgplural Selected {n} missing image|Selected {n} missing images Виділено {n} відсутнє зображення|Виділено {n} відсутні зображення|Виділено {n} відсутніх зображень
@msgplural Selected {n} modified image|Selected {n} modified images Виділено {n} змінене зображення|Виділено {n} змінені зображення|Виділено {n} змінених зображень
@msgplural Selected {n} image|Selected {n} images Виділено {n} зображення|Виділено {n} зображення|Виділено {n} зображень
@msgplural {selected}; {n} more is hidden or locked|{selected}; {n} more are hidden or locked {selected}; ще {n} приховане або заблоковане|{selected}; ще {n} приховані або заблоковані|{selected}; ще {n} приховані або заблоковані
@msgplural {selected}; {n} more is on a template layer|{selected}; {n} more are on template layers {selected}; ще {n} на шарі-шаблоні|{selected}; ще {n} на шарах-шаблонах|{selected}; ще {n} на шарах-шаблонах
@msgplural {selected}; {n} more is outside the isolated group|{selected}; {n} more are outside the isolated group {selected}; ще {n} поза ізольованою групою|{selected}; ще {n} поза ізольованою групою|{selected}; ще {n} поза ізольованою групою
@msgplural {selected}; {n} more can't be selected now|{selected}; {n} more can't be selected now {selected}; ще {n} зараз не можна виділити|{selected}; ще {n} зараз не можна виділити|{selected}; ще {n} зараз не можна виділити
# Compound Shapes add-on
Compound Shapes Складені фігури
Shape Mode Buttons Make Compound Shapes Кнопки режимів фігур створюють складені фігури
Can't render this file because it contains an unexpected character in line 177 and column 5.
+19
View File
@@ -5966,6 +5966,25 @@ breakText Glyphs Glyph
Minimum angle Góc tối thiểu
Maximum angle Góc tối đa
# Selection Tools add-on: Select by Link Status (Object › Plug-ins › Selection Tools, the Links panel menu, #5526).
Select Linked Chọn ảnh đã liên kết
Select Embedded Chọn ảnh đã nhúng
Select Missing Chọn ảnh bị thiếu
Select Modified Chọn ảnh đã sửa đổi
Select by Link Status Chọn theo trạng thái liên kết
Select by Link Status… Chọn theo trạng thái liên kết…
Search images Tìm ảnh
No images match. Không có ảnh nào khớp.
@msgplural Selected {n} linked image|Selected {n} linked images Đã chọn {n} ảnh đã liên kết
@msgplural Selected {n} embedded image|Selected {n} embedded images Đã chọn {n} ảnh đã nhúng
@msgplural Selected {n} missing image|Selected {n} missing images Đã chọn {n} ảnh bị thiếu
@msgplural Selected {n} modified image|Selected {n} modified images Đã chọn {n} ảnh đã sửa đổi
@msgplural Selected {n} image|Selected {n} images Đã chọn {n} ảnh
@msgplural {selected}; {n} more is hidden or locked|{selected}; {n} more are hidden or locked {selected}; thêm {n} ảnh bị ẩn hoặc khóa
@msgplural {selected}; {n} more is on a template layer|{selected}; {n} more are on template layers {selected}; thêm {n} ảnh nằm trên lớp mẫu
@msgplural {selected}; {n} more is outside the isolated group|{selected}; {n} more are outside the isolated group {selected}; thêm {n} ảnh nằm ngoài nhóm đã tách biệt
@msgplural {selected}; {n} more can't be selected now|{selected}; {n} more can't be selected now {selected}; thêm {n} ảnh hiện không thể chọn
# Compound Shapes add-on
Compound Shapes Hình phức hợp
Shape Mode Buttons Make Compound Shapes Nút chế độ hình dạng tạo hình phức hợp
Can't render this file because it contains an unexpected character in line 199 and column 5.
+19
View File
@@ -6206,6 +6206,25 @@ breakText Glyphs 字形
Minimum angle 最小角度
Maximum angle 最大角度
# Selection Tools add-on: Select by Link Status (Object › Plug-ins › Selection Tools, the Links panel menu, #5526).
Select Linked 选择已链接
Select Embedded 选择嵌入
Select Missing 选择缺失
Select Modified 选择已修改
Select by Link Status 按链接状态选择
Select by Link Status… 按链接状态选择…
Search images 搜索图像
No images match. 没有匹配的图像。
@msgplural Selected {n} linked image|Selected {n} linked images 已选择 {n} 个已链接的图像
@msgplural Selected {n} embedded image|Selected {n} embedded images 已选择 {n} 个嵌入的图像
@msgplural Selected {n} missing image|Selected {n} missing images 已选择 {n} 个缺失的图像
@msgplural Selected {n} modified image|Selected {n} modified images 已选择 {n} 个已修改的图像
@msgplural Selected {n} image|Selected {n} images 已选择 {n} 个图像
@msgplural {selected}; {n} more is hidden or locked|{selected}; {n} more are hidden or locked {selected};另有 {n} 个已隐藏或锁定
@msgplural {selected}; {n} more is on a template layer|{selected}; {n} more are on template layers {selected};另有 {n} 个位于模板图层上
@msgplural {selected}; {n} more is outside the isolated group|{selected}; {n} more are outside the isolated group {selected};另有 {n} 个位于隔离的编组之外
@msgplural {selected}; {n} more can't be selected now|{selected}; {n} more can't be selected now {selected};另有 {n} 个现在无法选择
# Compound Shapes add-on
Compound Shapes 复合形状
Shape Mode Buttons Make Compound Shapes 形状模式按钮创建复合形状
Can't render this file because it contains an unexpected character in line 2 and column 73.
+19
View File
@@ -6003,6 +6003,25 @@ breakText Glyphs 字符
Minimum angle 最小角度
Maximum angle 最大角度
# Selection Tools add-on: Select by Link Status (Object › Plug-ins › Selection Tools, the Links panel menu, #5526).
Select Linked 選取已連結
Select Embedded 選取已內嵌
Select Missing 選取遺失
Select Modified 選取已修改
Select by Link Status 依連結狀態選取
Select by Link Status… 依連結狀態選取…
Search images 搜尋影像
No images match. 沒有符合的影像。
@msgplural Selected {n} linked image|Selected {n} linked images 已選取 {n} 個已連結的影像
@msgplural Selected {n} embedded image|Selected {n} embedded images 已選取 {n} 個已內嵌的影像
@msgplural Selected {n} missing image|Selected {n} missing images 已選取 {n} 個遺失的影像
@msgplural Selected {n} modified image|Selected {n} modified images 已選取 {n} 個已修改的影像
@msgplural Selected {n} image|Selected {n} images 已選取 {n} 個影像
@msgplural {selected}; {n} more is hidden or locked|{selected}; {n} more are hidden or locked {selected};另有 {n} 個已隱藏或鎖定
@msgplural {selected}; {n} more is on a template layer|{selected}; {n} more are on template layers {selected};另有 {n} 個位於範本圖層上
@msgplural {selected}; {n} more is outside the isolated group|{selected}; {n} more are outside the isolated group {selected};另有 {n} 個位於隔離的群組之外
@msgplural {selected}; {n} more can't be selected now|{selected}; {n} more can't be selected now {selected};另有 {n} 個現在無法選取
# Compound Shapes add-on
Compound Shapes 複合形狀
Shape Mode Buttons Make Compound Shapes 形狀模式按鈕製作複合形狀
Can't render this file because it contains an unexpected character in line 6 and column 47.
+2
View File
@@ -64,6 +64,8 @@ use bar::{menu_body, pointer_reaches_title};
pub use context::{context_items, context_menu_body, ruler_menu_body, ruler_unit_items};
pub use entries::{MenuEntry, Row, context_entries, entry, menu_entries, pretty_shortcut, shown_shortcut};
pub(crate) use invoke::graph_dialog;
#[cfg(test)]
pub(crate) use invoke::with_held_keys;
pub use invoke::{click_target, invoke, invoke_from_system_menu};
#[cfg(test)]
pub(crate) use labels::lists_plugin;
+5 -2
View File
@@ -15,10 +15,13 @@ pub fn click_target(label: &str, id: &str, p: &Value) -> (String, Value) {
/// 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) {
/// that hold the selected objects (`scope: "group"`); Select Linked, Embedded, Missing and Modified
/// chosen with Shift add to the selection (`add: true`).
pub(crate) 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"})),
// Select Linked, Embedded, Missing and Modified with Shift add to the selection.
crate::addons::select::link_status::COMMAND if held.shift => (target.0, crate::addons::select::link_status::with_shift(target.1)),
_ => target,
}
}
+1
View File
@@ -578,6 +578,7 @@ fn run_ui_part6(app: &mut VectorcraftApp, id: &str, p: &Value) -> Option<Result<
crate::addons::pathtools::corner::COMMAND => crate::addons::pathtools::corner::open(app),
crate::addons::pathtools::shared_edge::COMMAND => crate::addons::pathtools::shared_edge::open(app),
crate::addons::arrange::ZOOM => crate::addons::arrange::zoom(app),
crate::addons::select::link_status::COMMAND => crate::addons::select::link_status::run(app, p),
crate::addons::document::SAVE_COPY => crate::addons::document::save_copy(app, p),
crate::addons::document::EXPORT_ALL => crate::addons::document::export_all(app, p),
crate::addons::document::BATCH_TRACE => crate::addons::document::batch_trace(app, p),
+1 -1
View File
@@ -135,7 +135,7 @@ fn swapped_out(app: &VectorcraftApp, id: &str) -> bool {
/// or off), or `None` while they leave it out: an empty slot ([`hidden_when_disabled`]) or an item
/// another stands in for ([`swapped_out`]).
pub fn shown_state(app: &VectorcraftApp, id: &str, p: &Value) -> Option<(bool, Option<bool>)> {
let en = enabled(app, id);
let en = enabled(app, id) && (id != crate::addons::select::link_status::COMMAND || crate::addons::select::link_status::enabled(app, p));
if (!en && hidden_when_disabled(id)) || swapped_out(app, id) {
return None;
}
+13 -1
View File
@@ -4,7 +4,8 @@
//! from the last row clicked without Shift to it (with Ctrl/Cmd, adds them); the buttons Relink,
//! Go To, Update and Edit Original act on the selected rows; Link Info shows the details of the
//! first. The flyout adds Relink to Folder, Find in Folder (Find Linked Files:
//! `ui.findLinksInFolder`), Embed / Unembed, Placement Options, Show filters, Sort, thumbnail size
//! `ui.findLinksInFolder`), Embed / Unembed, Placement Options, Select Linked / Embedded / Missing /
//! Modified (`addon.select.byLinkStatus`, Shift adds), Show filters, Sort, thumbnail size
//! and Show in Folder.
//!
//! Everything runs through the `links.*` commands (`links.editOriginal` and `links.reveal` are UI
@@ -597,6 +598,17 @@ pub fn menu(app: &mut VectorcraftApp, ui: &mut Ui) {
crate::menus::invoke(app, "links.reveal", json!({}));
}
ui.separator();
// Select Linked, Embedded, Missing and Modified: every such image in the document, not only
// the rows shown; with Shift, added to the selection.
use crate::addons::select::link_status;
for (i, (status, label, _)) in link_status::STATUSES.iter().enumerate() {
if menu_item(ui, tl!(label), app.ui.link_statuses.has.get(i).copied().unwrap_or(false), false) {
let p = json!({ "status": status });
let p = if ui.input(|i| i.modifiers.shift) { link_status::with_shift(p) } else { p };
crate::menus::invoke(app, link_status::COMMAND, p);
}
}
ui.separator();
for (id, label) in SHOW {
if menu_item(ui, tl!(label), true, o.show == id) {
set_options(ui.ctx(), |o| o.show = id);
+6
View File
@@ -382,6 +382,11 @@ pub struct UiState {
/// is open. Not saved.
#[serde(skip)]
pub context_intertwine: Option<(u64, vectorcraft_doc::NodeId, vectorcraft_geom::Point, vectorcraft_doc::NodeId)>,
/// Which link statuses the active document's images and placed documents have, for Select ›
/// Linked, Embedded, Missing and Modified to be on only when some do (refreshed by
/// [`crate::addons::select::link_status::refresh`]). Not saved.
#[serde(skip)]
pub link_statuses: crate::addons::select::link_status::Present,
/// Last tool shown in each toolbar slot (keyed by the slot's first tool id).
#[serde(default)]
pub slot_tool: std::collections::BTreeMap<String, String>,
@@ -942,6 +947,7 @@ impl Default for UiState {
shape_modes_compound: false,
context_locked: None,
context_intertwine: None,
link_statuses: Default::default(),
slot_tool: Default::default(),
floating_flyouts: vec![],
toolbar_edits: ToolbarEdits::default(),
+24
View File
@@ -6864,6 +6864,30 @@ The dialog lists every artboard with its number, name and size in the document's
name; a click chooses one artboard, Shift-click adds a range and Cmd/Ctrl-click toggles one, and Select All / None act
on the rows shown (rows hidden by the search stay chosen). It opens with the active artboard chosen and Overlapping.
`addon.select.byLinkStatus {status, ids?, add?, zoom?}` (Select Linked / Embedded / Missing / Modified and Select by
Link Status…, #5526) selects the image objects and placed documents whose link has a status, as `links.list` reports
it: `linked` (its file found unchanged; `links.list` says `ok`), `embedded`, `missing` or `modified` (its file changed
since it was read). `status` is one of them or a list of them (at least one; one listed twice counts once). `ids` picks
only among those objects (other objects among them are passed over); `add: true` adds them to the selection instead of
replacing it; `zoom: true` asks for Zoom to Selection afterwards, which the desktop app runs (`addon.arrange.zoomSelection`)
when something was selected, and which other callers get back as `zoom: true`. Objects that are hidden or locked, inside
a hidden or locked object or layer, on a template layer, on a locked artboard while nothing is isolated, or outside the
isolated group or layer are left out and listed with the reason. Only the selection changes, so there is nothing to
undo. It returns `{count, selected: [ids] (bottom first), skipped: [{id, reason: hidden|locked|template|isolation}]}`.
A missing or unknown status, an id naming no object, or a value of the wrong type is an error, and the selection is left
as it was.
```json
{"name":"run_command","arguments":{"command":"addon.select.byLinkStatus","params":{"status":["missing","modified"],"zoom":true}}}
```
In the desktop app, Object › Plug-ins › Selection Tools and the Links panel menu have Select Linked, Select Embedded,
Select Missing and Select Modified, each off when no image has that status; with Shift held they add to the selection.
The status bar says what was selected and what was left out, e.g. "Selected 9 missing images; 3 more are hidden or
locked". Select by Link Status… lists every image and placed document with its name, status and format, searches by
name and filters by status (Show), chooses rows with checkboxes (All / None act on the rows shown), and on Select
selects the rows chosen, zooming to them when Zoom to Selection is on (the default).
### Vector Halftone (live)
`addon.color.halftone` (Effect › Color Effects › Vector Halftone…, also in Object › Plug-ins › Color Effects) draws its
+2 -1
View File
@@ -1,6 +1,6 @@
# Roadmap: milestones and what's next
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-11-04 · **Change:** minor (Select by Artboards add-on selects by overlap, inside or outside several artboards; scores and estimates unchanged) · **Target:** Adobe Illustrator 2026 (30.x)
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-11-05 · **Change:** minor (Selection Tools add-on: Select by Link Status selects images and placed documents that are linked, embedded, missing or modified, #5526; scores and estimates unchanged) · **Target:** Adobe Illustrator 2026 (30.x)
## Feature submission evidence
@@ -28,6 +28,7 @@ M7 type: Touch Type moves a right-to-left character along its line and up from i
| Date | Change | Summary |
|---|---|---|
| 2026-11-05 | minor | Selection Tools add-on: Select Linked, Embedded, Missing and Modified select the images and placed documents with that link status (Object › Plug-ins › Selection Tools and the Links panel menu; Shift adds), and Select by Link Status… lists them by name, status and format to pick from, optionally zooming to them; what is hidden, locked, on a template layer or outside the isolated group is left out and the status bar says how many (#5526, a VectorCraft addition); scores and estimates unchanged (estimated). |
| 2026-11-04 | minor | M7: Find Font's Replace With Font lists family and style rows with a search, and the list and the document's font list scroll on their own (#4972); 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. |
| 2026-11-04 | minor | New Document: the units chosen in Preset Details belong to the chosen preset; Recent and Saved cards keep the units their document or preset was made in, and the built-in tabs still follow the chosen units (#2078). Scores and estimates unchanged. |
+3 -1
View File
@@ -1,6 +1,6 @@
# Parity with Adobe Illustrator
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-11-05 · **Change:** minor (Compound Shapes add-on, beyond Illustrator; scores and estimates unchanged; Contour add-on, beyond Illustrator; scores and estimates unchanged; Optical kerning spaces pairs by the font's own stem spacing instead of a fixed tight gap; scores and estimates unchanged) · **Target:** Adobe Illustrator 2026 (30.x; public release notes through 30.7, August 2026)
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-11-05 · **Change:** minor (Selection Tools add-on: Select by Link Status selects images and placed documents that are linked, embedded, missing or modified, #5526; scores and estimates unchanged) · **Target:** Adobe Illustrator 2026 (30.x; public release notes through 30.7, August 2026)
## Feature submission evidence
@@ -23,6 +23,7 @@ Artboard Options forwards the active Artboard tool's Scale Artwork with Artboard
| Date | Change | Summary |
|---|---|---|
| 2026-11-05 | minor | Selection Tools add-on: Select Linked, Embedded, Missing and Modified select the images and placed documents with that link status (Object › Plug-ins › Selection Tools and the Links panel menu; Shift adds), and Select by Link Status… lists them by name, status and format to pick from, optionally zooming to them; what is hidden, locked, on a template layer or outside the isolated group is left out and the status bar says how many (#5526, a VectorCraft addition); scores and estimates unchanged (estimated). |
| 2026-11-05 | minor | G12: Hyphenation › Default Language sets the language of new type unless Document Setup chose one, stored as a tag; each run hyphenates in its own language, English only so far, so 2 Preferences options stay unused (#394) |
| 2026-11-05 | minor | Type Tools add-on: Release Type on a Path (a VectorCraft addition, #5532): evidence added; scores unchanged. |
| 2026-11-04 | minor | Path Precision Tools add-on (a VectorCraft addition): Set Corners… and `addon.pathtools.cornerSet` `minAngle`/`maxAngle` round only the corners whose angle is in a range (#5545); evidence added; scores unchanged. |
@@ -736,6 +737,7 @@ Moved from the ROADMAP's "Shipped so far" on 2026-10-10. Update it when a featur
The Lasso picks anchor points only on art a click can pick, and the Add Anchor Point, Delete Anchor Point, Anchor Point and Scissors tools pick anchor points and segments only on the selected paths and on art a click can pick: not on a Shaper Group's original shapes outside Construction mode, and in isolation mode only inside the isolated group or object. Smart Guides and Snap to Point do not snap to a Shaper Group's original shapes, and the reference point of the transform tools snaps to one only when it is selected, or under the pointer in Construction mode.
Enclosing Lasso provides whole-object enclosure selection under Object › Plug-ins and its own heading in All Tools. It has no default shortcut or Basic toolbar slot. It follows path curves and keeps partially enclosed objects out, including objects crossing a concave part of the loop. Ordinary group members can be selected individually; compound paths remain whole. This is a VectorCraft addition; scores and estimates are unchanged.
Select by Artboards (Object › Plug-ins › Selection Tools, a VectorCraft addition: #5525, #5548, #5549) selects the objects overlapping, fully inside or fully outside one or more chosen artboards (`addon.select.byArtboards {artboards, relation}`). Overlapping is All on Active Artboard's test, shared as `select::on_artboard`; Fully inside means within one artboard, edges included; Fully outside means on none. It looks at what Select All takes, so hidden, locked and locked-artboard art stays out. Its dialog lists each artboard's number, name and size in the document's units, filters by name, chooses rows with click, Shift-click and Cmd/Ctrl-click, and fits a row's artboard in the window on double-click (`view.goToArtboard`). Tests: `crates/engine/src/cmd/addons/select/tests.rs`, `crates/ui-egui/src/addons/select/tests.rs`, `crates/engine/tests/command_sweep.rs`.
Select by Link Status (Object › Plug-ins › Selection Tools and the Links panel menu, a VectorCraft addition: #5526) selects the image objects and placed documents whose link is linked (its file found unchanged), embedded, missing or modified, as `links.list` reports it (`addon.select.byLinkStatus {status, ids?, add?, zoom?}`); Select Linked, Embedded, Missing and Modified are off when no image has that status and add to the selection with Shift. Objects that are hidden or locked, inside a hidden or locked object or layer, on a template layer, on a locked artboard, or outside the isolated group are left out (the `select::is_selectable` test) and returned with the reason, and the status bar says how many, in plural forms of every catalog. Select by Link Status… lists each image and placed document with its name, status and format, searches by name, filters by status, picks rows with checkboxes and All / None, and zooms to the selection with the existing Zoom to Selection (`addon.arrange.zoomSelection`). Missing-link markers on the canvas are #5547. Tests: `crates/engine/src/cmd/addons/select/tests.rs` (`by_link_status`), `crates/ui-egui/src/addons/select/link_status/tests.rs`, `crates/engine/tests/command_sweep.rs`.
A marquee selects a clip group, or an object on a layer with a clipping mask, only when it reaches the area inside the clipping path, and it measures the art only within that path's bounds. Within the bounds of a mask that is not a rectangle, it can still select art that the mask hides. Direct Selection's marquee still selects the hidden anchor points inside it (#2345).
A marquee selects a Shaper Group only when it reaches the art the group shows, not the original shapes kept under it, and Direct Selection's clicks and marquee do not select those shapes' anchor points. In Construction mode a marquee selects the original shapes, and Direct Selection selects their anchor points.
While an opacity mask or a pattern is edited, a Shaper double-click on a Shaper Group in the mask or pattern art selects the original shape under the pointer without entering Construction mode, the Shaper Group's mode widget does not show, and a Shaper scribble, Release and Expand keep the editing layer isolated.
+3 -1
View File
@@ -1,6 +1,6 @@
# UI and interaction parity
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-11-05 · **Change:** minor (Compound Shapes add-on, beyond Illustrator; scores and estimates unchanged; Contour add-on, beyond Illustrator; scores and estimates unchanged; Select by Artboards add-on selects by overlap, inside or outside several artboards; Cmd+Space keeps the active drawing cursor during its drag; scores and estimates 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-05 · **Change:** minor (Selection Tools add-on: Select by Link Status selects images and placed documents that are linked, embedded, missing or modified, #5526; scores and estimates 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-05 | minor | Selection Tools add-on: Select Linked, Embedded, Missing and Modified select the images and placed documents with that link status (Object › Plug-ins › Selection Tools and the Links panel menu; Shift adds), and Select by Link Status… lists them by name, status and format to pick from, optionally zooming to them; what is hidden, locked, on a template layer or outside the isolated group is left out and the status bar says how many (#5526, a VectorCraft addition); scores and estimates unchanged (estimated). |
| 2026-11-05 | minor | G12: Hyphenation › Default Language sets the language of new type unless Document Setup chose one, stored as a tag; each run hyphenates in its own language, English only so far, so 2 Preferences options stay unused (#394) |
| 2026-11-05 | minor | Gradient panel: Delete Stop sits at the right end of the ramp, so it shows whenever the ramp does instead of under the stop fields, where a short panel hid it (#5403); scores and estimates unchanged |
| 2026-11-04 | minor | Artboards panel: a Shift- or Ctrl/Cmd-click on a row selects several artboards with any tool, switching to the Artboard tool first, so a preset, orientation, size or Fill set in Properties or the Control bar goes to every selected artboard; Fill used to set the active artboard only (#5698); scores and estimates unchanged |
@@ -395,6 +396,7 @@ next unit in the order a right-click on a ruler lists them, from Feet back to Po
| Color Effects add-on (VectorCraft addition): live Exposure, Desaturate and Invert Colors in Effect › Color Effects and Object › Plug-ins › Color Effects; its panel picks a colour adjustment and its values and adds it as a live effect or applies it as a filter, into the colours, as one undo step; Select by Color Kind selects the objects that use spot colours, carry colour effects, or are RGB, CMYK or grayscale images; Vector Halftone draws an object as halftone dots live (the dots Object › Vector Halftone makes), which Expand Appearance and the exporters write as paths; Duotone prints each colour's tone with one to four inks (a tint of a spot tone's swatch, or the CMYK mix of several), live or as a filter, its dialog a row per tone and the picked tone's curve; Print Ink Fixes (a CMYK document's ink limit, white overprint removed, black overprint set) opens its options from the submenu and the panel's Inks | done | `addon.color.*`, `crates/ui-egui/src/addons/color.rs` and its tests; not a feature of the reference app, so it is not scored |
| Color Effects add-on (VectorCraft addition): Object › Plug-ins › Color Effects › Find Nearest Swatch… picks a Library (Document Swatches, a built-in library, or a library or colour book the user saved or loaded) and Fill and Stroke, lists each colour of the selection with its three closest swatches (chip, name, ΔE 2000), and Apply gives each colour its nearest swatch (global and spot swatches linked; a library's swatches added to the document first), one undo step | done | #4923; `addon.color.nearestSwatch`, `addon.color.applyNearestSwatch`, `crates/engine/src/cmd/addons/color/nearest.rs`, `crates/ui-egui/src/addons/color/nearest.rs` and their tests; not a feature of the reference app, so it is not scored |
| Selection Tools add-on (VectorCraft addition): Object › Plug-ins › Selection Tools › Select by Artboards… lists every artboard (number, name, width × height in the document's units), filters them by name, chooses several (click, Shift-click for a range, Cmd/Ctrl-click to toggle; Select All / None act on the rows shown; a count of those chosen), fits a row's artboard in the window on double-click and makes it active, and on OK selects the objects overlapping, fully inside or fully outside the chosen artboards (Overlapping is All on Active Artboard's test) | done | #5525, #5548, #5549; `addon.select.byArtboards`, `crates/engine/src/cmd/addons/select.rs`, `crates/ui-egui/src/addons/select.rs` and their tests; not a feature of the reference app |
| Selection Tools add-on (VectorCraft addition): Select Linked, Select Embedded, Select Missing and Select Modified in Object › Plug-ins › Selection Tools and the Links panel menu (off when no image has that status; Shift adds to the selection) select the images and placed documents with that link status, leaving out hidden, locked, template-layer and outside-isolation ones, which the status bar counts (e.g. "Selected 9 missing images; 3 more are hidden or locked"); Select by Link Status… lists them with name, status and format, searches by name, filters by status, picks with checkboxes and All / None, and selects with Zoom to Selection on by default | done | #5526; `addon.select.byLinkStatus`, `crates/engine/src/cmd/addons/select.rs`, `crates/ui-egui/src/addons/select/link_status.rs` and their tests; not a feature of the reference app |
## Look and feel