Objects on Path: Detach takes the chosen object off the path

With one Objects on Path group selected and an object chosen with its
Select/Move widget, Detach in the Properties panel's Objects on Path
Options section takes that object out of the group
(`object.objectsOnPath.detach {member?}`). The object goes just above
the group in the Layers panel, stays where it is drawn and is selected
alone. The other objects move up the path in their order: Auto Space
spreads them evenly again, and a Space value and the start are kept.
The group and its path stay with one object or none left. Hidden or
locked objects and groups are refused, and Detach is one undo step.
When the group is itself on another group's path, the object goes
above the outer group so it does not join that path.

Docs: docs/mcp.md, docs/target-app-parity.md. Detach and its undo name
have rows in every catalog, and the new message in the complete-message
catalogs.
This commit is contained in:
dotCooCoo
2026-11-13 07:54:06 -08:00
parent 77970c6924
commit 9fad6eb952
35 changed files with 412 additions and 7 deletions
+54 -2
View File
@@ -12,7 +12,8 @@
//! `object.objectsOnPath.selectMember` chooses one object of a selected group (its Select/Move
//! widget), and `object.objectsOnPath.moveMember` moves one object to another's place along the
//! path, the objects between it and that place each moving one place toward where it was; hidden
//! and locked objects keep their places.
//! and locked objects keep their places. `object.objectsOnPath.detach` takes one object out of its
//! group, just above it, and the others move up the path.
//!
//! After every edit, [`refresh`] puts the objects of each Objects on Path group that changed back
//! on its path: editing the path moves them, an object moved on its own goes back to its place,
@@ -21,7 +22,8 @@
//!
//! Behavior: <https://helpx.adobe.com/illustrator/using/objects-on-path.html> (the tool and
//! Object › Objects on Path › Attach; the order on the path, the attachment point, the distribution,
//! the objects squared to the path; Pivot and Rotate; path edits realign the objects; Expand).
//! the objects squared to the path; Pivot and Rotate; path edits realign the objects; Detach and
//! the objects that move up the path after it; Expand).
use std::collections::{HashMap, HashSet};
use std::sync::Arc;
@@ -75,6 +77,15 @@ pub fn specs() -> Vec<CommandSpec> {
has_doc,
move_member
),
cmd!(
"object.objectsOnPath.detach",
"Detach Object from Path",
[],
None,
"{member?: id of an object of an Objects on Path group (default: the object chosen with the selected group's Select/Move widget); neither the object nor the group may be hidden or locked} take one object off the path, out of its group and just above the group in the Layers panel, where it stays as drawn and is selected alone. The group's other objects move up the path in their order: with Auto Space they spread evenly again, and a Space value and the start are kept. The group and its path stay, even with one object or none left → {group, member}",
has_doc,
detach
),
cmd!(
"object.objectsOnPath.expand",
"Expand",
@@ -383,6 +394,47 @@ fn move_member(s: &mut Session, p: &Value) -> Result<Value> {
Ok(json!({ "group": g.0, "member": member.0, "index": index }))
}
// ---------- Detach ----------
/// The object chosen with the Select/Move widget of the one selected Objects on Path group.
fn chosen_member(s: &Session) -> Option<NodeId> {
let st = s.active()?;
match st.selection.objects[..] {
[_] => st.selection.on_path_member,
_ => None,
}
}
fn detach(s: &mut Session, p: &Value) -> Result<Value> {
const C: &str = "object.objectsOnPath.detach";
const CHOOSE: &str = "choose the object to detach with its Select/Move widget";
let (g, member) = if p.get("member").is_none_or(Value::is_null) {
let chosen = chosen_member(s).ok_or_else(|| bad(C, CHOOSE))?;
let found = member_param(s, &json!({ "member": chosen.0 }), "member", C)?;
if s.active().is_none_or(|st| st.selection.objects[..] != [found.0]) {
return Err(bad(C, CHOOSE));
}
found
} else {
member_param(s, p, "member", C)?
};
// The object goes just above the group, in the group's parent, and keeps where it is drawn.
// When the group is itself an object on another group's path, the object goes above that
// group instead (and so on outward), so it does not join that path. The refresh after the edit
// removes it from the group's record and moves the others up the path.
s.edit("Detach Object from Path", |d, sel| {
let mut above = g;
while let Some(p) = d.parent_of(above).filter(|p| d.node(*p).is_some_and(is_objects_on_path)) {
above = p;
}
let (parent, index, _) = d.position(above).ok_or(EngineError::NoNode(above))?;
d.move_node(member, parent, index + 1)?;
sel.set([member]);
Ok(())
})?;
Ok(json!({ "group": g.0, "member": member.0 }))
}
// ---------- Expand ----------
fn expand(s: &mut Session, p: &Value) -> Result<Value> {
@@ -314,6 +314,7 @@ pub(super) const ALLOWED: &[&str] = &[
"object.move",
"object.nudge",
"object.objectsOnPath.attach",
"object.objectsOnPath.detach",
"object.objectsOnPath.expand",
"object.objectsOnPath.moveMember",
"object.objectsOnPath.options",
+194
View File
@@ -681,3 +681,197 @@ fn the_space_saves_and_reopens_and_goes_with_a_copy() {
let copy = s.doc().unwrap().selection.objects.to_vec();
assert_eq!(space(&s, copy[0]), (Some(40.0), 25.0));
}
/// Where `id` is in the tree: its parent and its index there (0 at the bottom).
fn place_of(s: &Session, id: NodeId) -> (Option<NodeId>, usize) {
let (parent, index, _) = s.doc().unwrap().doc.position(id).unwrap();
(parent, index)
}
#[test]
fn detach_takes_the_chosen_object_off_the_path_and_the_others_move_up_in_one_undo_step() {
let mut s = session();
let ([left, middle, right], path) = squares_and_line(&mut s);
let g = attach(&mut s, path, &[left, middle, right], json!({"rotate": 30}));
let (layer, at) = place_of(&s, g);
s.execute("object.objectsOnPath.selectMember", &json!({"member": middle.0})).unwrap();
let drawn = s.doc().unwrap().doc.node(middle).unwrap().clone();
let steps = s.doc().unwrap().history.undo.len();
let v = s.execute("object.objectsOnPath.detach", &json!({})).unwrap();
assert_eq!(v, json!({"group": g.0, "member": middle.0}));
assert_eq!(s.doc().unwrap().history.undo.len(), steps + 1, "one undo step");
let (on_path, children) = orders(&s, g);
assert_eq!(on_path, [left, right]);
assert!(children.len() == 3 && !children.contains(&middle), "{children:?}");
assert_eq!(place_of(&s, middle), (layer, at + 1), "just above the group, in its layer");
assert_eq!(s.doc().unwrap().doc.node(middle), Some(&drawn), "the object keeps its art, place and rotation");
let sel = &s.doc().unwrap().selection;
assert_eq!((sel.objects.as_slice(), sel.on_path_member), (&[middle][..], None), "the detached object alone is selected");
// The two left stay on the ends of the path; the path stays.
assert_eq!(center(&s, left), Point::new(50.0, 300.0));
assert_eq!(center(&s, right), Point::new(350.0, 300.0));
assert_eq!(s.doc().unwrap().doc.node(g).unwrap().extras().objects_on_path.as_deref().unwrap().path, path);
// The detached object is free: moving it moves it, and the group does not take it back.
s.execute("object.move", &json!({"ids": [middle.0], "dx": 0, "dy": -100})).unwrap();
assert_eq!(center(&s, middle), Point::new(200.0, 200.0));
assert_eq!(orders(&s, g).0, [left, right]);
s.execute("edit.undo", &json!({})).unwrap();
s.execute("edit.undo", &json!({})).unwrap();
let (on_path, children) = orders(&s, g);
assert_eq!(on_path, [left, middle, right], "undo puts it back on the path");
assert!(children.contains(&middle), "{children:?}");
assert_eq!(center(&s, middle), Point::new(200.0, 300.0));
assert_eq!(center(&s, right), Point::new(350.0, 300.0));
let sel = &s.doc().unwrap().selection;
assert_eq!((sel.objects.as_slice(), sel.on_path_member), (&[g][..], Some(middle)), "and the choice back");
s.execute("edit.redo", &json!({})).unwrap();
assert_eq!(orders(&s, g).0, [left, right]);
assert_eq!(place_of(&s, middle), (layer, at + 1));
}
#[test]
fn after_the_first_object_is_detached_the_second_takes_the_start() {
let mut s = session();
let ([left, middle, right], path) = squares_and_line(&mut s);
let g = attach(&mut s, path, &[left, middle, right], json!({}));
select(&mut s, &[]);
let v = s.execute("object.objectsOnPath.detach", &json!({"member": left.0})).unwrap();
assert_eq!(v, json!({"group": g.0, "member": left.0}));
assert_eq!(orders(&s, g).0, [middle, right]);
assert_eq!(center(&s, middle), Point::new(50.0, 300.0), "the second object moves up to the start");
assert_eq!(center(&s, right), Point::new(350.0, 300.0));
assert_eq!(center(&s, left), Point::new(50.0, 300.0), "the detached object stays where it was drawn");
assert_eq!(s.doc().unwrap().selection.objects.to_vec(), [left]);
}
#[test]
fn detach_on_a_closed_path_spreads_the_others_all_the_way_round_again() {
let mut s = session();
let ids: Vec<NodeId> = (0..4).map(|i| rect(&mut s, 10.0 + 40.0 * f64::from(i), 0.0, 10.0, 10.0)).collect();
let ring = rect(&mut s, 100.0, 100.0, 200.0, 200.0);
let g = attach(&mut s, ring, &ids, json!({}));
s.execute("object.objectsOnPath.detach", &json!({"member": ids[1].0})).unwrap();
assert_eq!(orders(&s, g).0, [ids[0], ids[2], ids[3]]);
let data = s.doc().unwrap().doc.node(ring).unwrap().path_data().unwrap().clone();
let stops = vectorcraft_doc::objects_on_path::stops(&data, 3, None, 0.0).unwrap();
for (id, (p, _)) in [ids[0], ids[2], ids[3]].iter().zip(stops) {
let c = center(&s, *id);
assert!((c.x - p.x).abs() < 1e-3 && (c.y - p.y).abs() < 1e-3, "a third of the way round apart: {c:?} {p:?}");
}
}
#[test]
fn detach_keeps_a_space_value_and_the_start() {
let mut s = session();
let (g, [a, b, c], _) = three_on_a_line(&mut s);
s.execute("object.objectsOnPath.options", &json!({"start": 20})).unwrap();
s.execute("object.objectsOnPath.detach", &json!({"member": a.0})).unwrap();
assert_eq!(space(&s, g), (Some(100.0), 20.0));
assert_eq!(center(&s, b), Point::new(70.0, 300.0), "the second object moves up to the first place");
assert_eq!(center(&s, c), Point::new(170.0, 300.0));
// A Space value the path is too short for stays, and two objects get more of the path.
s.execute("edit.undo", &json!({})).unwrap();
s.execute("object.objectsOnPath.options", &json!({"spacing": 200, "start": 0})).unwrap();
assert_eq!(center(&s, c), Point::new(350.0, 300.0), "three objects drawn 150 pt apart");
s.execute("object.objectsOnPath.detach", &json!({"member": b.0})).unwrap();
assert_eq!(space(&s, g), (Some(200.0), 0.0));
assert_eq!(center(&s, a), Point::new(50.0, 300.0));
assert_eq!(center(&s, c), Point::new(250.0, 300.0), "two objects 200 pt apart");
}
#[test]
fn the_group_and_its_path_stay_with_one_object_or_none_left() {
let mut s = session();
let ([left, middle, _], path) = squares_and_line(&mut s);
let g = attach(&mut s, path, &[left, middle], json!({"pivot": 7}));
s.execute("object.objectsOnPath.options", &json!({"spacing": 30})).unwrap();
s.execute("object.objectsOnPath.detach", &json!({"member": left.0})).unwrap();
assert_eq!(orders(&s, g), (vec![middle], vec![path, middle]));
let b = bounds(&s, middle);
assert!((b.center().x - 50.0).abs() < 1e-6 && (b.y1 - 300.0).abs() < 1e-6, "the one left on the start, by its Pivot: {b:?}");
s.execute("object.objectsOnPath.detach", &json!({"member": middle.0})).unwrap();
let n = s.doc().unwrap().doc.node(g).unwrap().clone();
let rec = n.extras().objects_on_path.as_deref().unwrap();
assert_eq!((rec.path, rec.members.len(), rec.pivot, rec.spacing), (path, 0, 7, Some(30.0)), "a live group with no objects");
assert_eq!(orders(&s, g).1, [path]);
// An object moved back in joins the path.
s.execute("layer.move", &json!({"ids": [left.0], "target": g.0, "place": "inside"})).unwrap();
assert_eq!(orders(&s, g).0, [left]);
}
#[test]
fn detach_refuses_what_is_not_one_chosen_editable_object_on_a_path() {
let mut s = session();
let (g, [a, b, c], path) = three_on_a_line(&mut s);
let loose = rect(&mut s, 300.0, 20.0, 10.0, 10.0);
let err = |s: &mut Session, p: Value| s.execute("object.objectsOnPath.detach", &p).unwrap_err().to_string();
let choose = "choose the object to detach with its Select/Move widget";
let steps = s.doc().unwrap().history.undo.len();
select(&mut s, &[g]);
assert!(err(&mut s, json!({})).contains(choose), "the group without a chosen object");
select(&mut s, &[]);
assert!(err(&mut s, json!({})).contains(choose), "nothing selected");
assert!(err(&mut s, json!({"member": path.0})).contains("`member` must name an object attached"), "the path");
assert!(err(&mut s, json!({"member": g.0})).contains("`member` must name"), "the group itself");
assert!(err(&mut s, json!({"member": loose.0})).contains("`member` must name"), "an object on no path");
assert!(err(&mut s, json!({"member": 99999})).contains("no such object"));
assert!(err(&mut s, json!({"member": "a"})).contains("invalid object id"));
// Hidden and locked objects stay; a locked group keeps all of its objects.
select(&mut s, &[c]);
s.execute("object.lock", &json!({})).unwrap();
assert!(err(&mut s, json!({"member": c.0})).contains("`member` names an object that is hidden or locked"));
s.execute("object.unlockAll", &json!({})).unwrap();
select(&mut s, &[b]);
s.execute("object.hide", &json!({})).unwrap();
assert!(err(&mut s, json!({"member": b.0})).contains("hidden or locked"), "a hidden object");
s.execute("object.showAll", &json!({})).unwrap();
select(&mut s, &[g]);
s.execute("object.lock", &json!({})).unwrap();
assert!(err(&mut s, json!({"member": a.0})).contains("the Objects on Path group is hidden or locked"));
s.execute("object.unlockAll", &json!({})).unwrap();
assert_eq!(orders(&s, g).0, [a, b, c], "nothing refused detached anything");
let undone = s.doc().unwrap().history.undo.len();
assert_eq!(undone, steps + 6, "only the lock, hide and show steps");
}
#[test]
fn an_object_detached_from_a_group_on_another_path_does_not_join_that_path() {
let mut s = session();
let ([left, middle, right], path) = squares_and_line(&mut s);
let inner = attach(&mut s, path, &[left, middle], json!({}));
let outer_line = line(&mut s, (20.0, 380.0), (380.0, 380.0));
let outer = attach(&mut s, outer_line, &[inner, right], json!({}));
let outer_members = orders(&s, outer).0;
s.execute("object.objectsOnPath.detach", &json!({"member": left.0})).unwrap();
assert_eq!(orders(&s, inner).0, [middle]);
assert_eq!(orders(&s, outer).0, outer_members, "the outer path keeps its objects and takes no new one");
let (layer, at) = place_of(&s, outer);
assert_eq!(place_of(&s, left), (layer, at + 1), "above the outer group");
}
#[test]
fn hidden_and_locked_objects_left_on_the_path_move_up_too() {
let mut s = session();
let ([left, middle, right], path) = squares_and_line(&mut s);
let g = attach(&mut s, path, &[left, middle, right], json!({}));
select(&mut s, &[right]);
s.execute("object.lock", &json!({})).unwrap();
select(&mut s, &[middle]);
s.execute("object.hide", &json!({})).unwrap();
s.execute("object.objectsOnPath.detach", &json!({"member": left.0})).unwrap();
assert_eq!(orders(&s, g).0, [middle, right]);
assert_eq!(center(&s, middle), Point::new(50.0, 300.0), "the hidden object moves up to the start");
assert_eq!(center(&s, right), Point::new(350.0, 300.0));
}
#[test]
fn objects_moved_out_together_in_the_layers_panel_all_leave_the_path() {
let mut s = session();
let ([left, middle, right], path) = squares_and_line(&mut s);
let g = attach(&mut s, path, &[left, middle, right], json!({}));
s.execute("layer.move", &json!({"ids": [left.0, middle.0], "target": g.0, "place": "above"})).unwrap();
assert_eq!(orders(&s, g), (vec![right], vec![path, right]));
assert_eq!(center(&s, right), Point::new(50.0, 300.0), "the one left takes the start");
let (layer, at) = place_of(&s, g);
assert_eq!((place_of(&s, left), place_of(&s, middle)), ((layer, at + 1), (layer, at + 2)), "above the group, in their order");
}
+2
View File
@@ -1537,6 +1537,8 @@ font-technology Variable Променливи
Objects on Path Tool Инструмент „Обекти по пътя“
Attach Objects on Path Прикрепяне на обекти към пътя
Expand Objects on Path Разширяване на обекти по пътя
Detach Откачване
Detach Object from Path Откачване на обект от пътя
Release Live Paint Освобождаване на динамично оцветяване
Release Repeat Освобождаване на повторение
Release Slice Освобождаване на отрязък
Can't render this file because it contains an unexpected character in line 2 and column 73.
+3
View File
@@ -1809,6 +1809,8 @@ digits Malayalam Malajalam
Objects on Path Tool Alat objekti na putanji
Attach Objects on Path Priloži objekte na putanju
Expand Objects on Path Proširi objekte na putanji
Detach Odvoji
Detach Object from Path Odvoji objekat s putanje
Release Live Paint Oslobodi živo bojenje
Release Repeat Oslobodi ponavljanje
Release Slice Oslobodi isječak
@@ -4924,6 +4926,7 @@ imageTrace Outline Obris
@msg select a repeat odaberite ponavljanje
@msg select an Intertwine group odaberite Intertwine grupu
@msg select an Objects on Path group odaberite grupu objekata na putanji
@msg choose the object to detach with its Select/Move widget odaberite objekat koji želite odvojiti njegovom ručicom Odaberi/Pomjeri
@msg a path inside a compound path, blend, envelope, repeat or Intertwine group can't take objects putanja unutar složene putanje, stapanja, omotnice, ponavljanja ili Intertwine grupe ne može primiti objekte
@msg a clipping path can't take objects putanja isijecanja ne može primiti objekte
@msg objects inside a blend, envelope, repeat or Intertwine group can't be attached to a path objekti unutar stapanja, omotnice, ponavljanja ili Intertwine grupe ne mogu se priložiti putanji
Can't render this file because it contains an unexpected character in line 2 and column 73.
+3
View File
@@ -1542,6 +1542,8 @@ antiAlias Sharp Nítid
Expand Live Paint Expandeix la pintura interactiva
Expand Object Expandeix l’objecte
Expand Objects on Path Expandeix els objectes del traçat
Detach Separa
Detach Object from Path Separa l’objecte del traçat
Expand Options Opcions d’expansió
Expand Panels Expandeix els panells
Expand Repeat Expandeix la repetició
@@ -6000,6 +6002,7 @@ digits Malayalam Malaiàlam
@msg select an Intertwine group selecciona un grup Intertwine
@msg select an object in perspective selecciona un objecte en perspectiva
@msg select an Objects on Path group selecciona un grup d’objectes sobre un traçat
@msg choose the object to detach with its Select/Move widget tria l’objecte que vols separar amb el seu control Selecciona/Mou
@msg select artwork (or a colour group) to recolor selecciona la il·lustració (o un grup de colors) per recolorejar
@msg Recolor completed; {locked} and {hidden} were left unchanged Recoloració completada; sense canvis: {locked} i {hidden}
@msg Recolor completed; {objects} were left unchanged Recoloració completada; sense canvis: {objects}
Can't render this file because it contains an unexpected character in line 2 and column 73.
+3
View File
@@ -1840,6 +1840,8 @@ digits Malayalam Malajálamské
Objects on Path Tool Nástroj Objekty na cestě
Attach Objects on Path Připojit objekty na cestu
Expand Objects on Path Rozložit objekty na cestě
Detach Odpojit
Detach Object from Path Odpojit objekt od cesty
Release Live Paint Uvolnit živou malbu
Release Repeat Uvolnit opakování
Release Slice Uvolnit řez
@@ -5091,6 +5093,7 @@ imageTrace Outline Obrys
@msg select a repeat vyberte opakování
@msg select an Intertwine group vyberte skupinu propletení
@msg select an Objects on Path group vyberte skupinu objektů na cestě
@msg choose the object to detach with its Select/Move widget vyberte objekt k odpojení jeho ovládacím prvkem Vybrat/Přesunout
@msg a path inside a compound path, blend, envelope, repeat or Intertwine group can't take objects cesta uvnitř složené cesty, prolnutí, obálky, opakování nebo skupiny propletení nemůže přijmout objekty
@msg a clipping path can't take objects ořezová cesta nemůže přijmout objekty
@msg objects inside a blend, envelope, repeat or Intertwine group can't be attached to a path objekty uvnitř prolnutí, obálky, opakování nebo skupiny propletení nelze připojit na cestu
Can't render this file because it contains an unexpected character in line 2 and column 73.
+2
View File
@@ -5821,6 +5821,8 @@ swatch Bright Violet Kraftig violet
Objects on Path Tool Objekter på kurve-værktøj
Attach Objects on Path Tilknyt objekter til kurve
Expand Objects on Path Udvid objekter på kurve
Detach Frigør
Detach Object from Path Frigør objekt fra kurve
Release Live Paint Frigør live-maling
Release Repeat Frigør gentagelse
Release Slice Frigør udsnit
Can't render this file because it contains an unexpected character in line 2 and column 73.
+3
View File
@@ -1592,6 +1592,8 @@ file-filter Templates Vorlagen
Objects on Path Tool Objekte-auf-Pfad-Werkzeug
Attach Objects on Path Objekte an Pfad anhängen
Expand Objects on Path Objekte auf Pfad umwandeln
Detach Lösen
Detach Object from Path Objekt vom Pfad lösen
Release Live Paint „Interaktiv malen“ zurückwandeln
Release Repeat Wiederholung zurückwandeln
Release Slice Slice zurückwandeln
@@ -4706,6 +4708,7 @@ theme Appearance Erscheinungsbild
@msg select a repeat wählen Sie eine Wiederholung aus
@msg select an Intertwine group wählen Sie eine Verflechtungsgruppe aus
@msg select an Objects on Path group wählen Sie eine Gruppe „Objekte auf Pfad“ aus
@msg choose the object to detach with its Select/Move widget wählen Sie das zu lösende Objekt mit seinem Steuerelement „Auswählen/Verschieben“ aus
@msg a path inside a compound path, blend, envelope, repeat or Intertwine group can't take objects ein Pfad in einem zusammengesetzten Pfad, einer Angleichung, einer Hülle, einer Wiederholung oder einer Verflechtungsgruppe kann keine Objekte aufnehmen
@msg a clipping path can't take objects ein Schnittpfad kann keine Objekte aufnehmen
@msg objects inside a blend, envelope, repeat or Intertwine group can't be attached to a path die Objekte in einer Angleichung, einer Hülle, einer Wiederholung oder einer Verflechtungsgruppe können nicht an einen Pfad angehängt werden
Can't render this file because it contains an unexpected character in line 2 and column 73.
+3
View File
@@ -1512,6 +1512,8 @@ font-technology Variable Μεταβλητές
Objects on Path Tool Αντικείμενα σε διαδρομή (Objects on Path Tool)
Attach Objects on Path Προσάρτηση αντικειμένων σε διαδρομή
Expand Objects on Path Επέκταση αντικειμένων σε διαδρομή
Detach Αποσύνδεση
Detach Object from Path Αποσύνδεση αντικειμένου από διαδρομή
Release Live Paint Αποδέσμευση δυναμικής βαφής
Release Repeat Αποδέσμευση επανάληψης
Release Slice Αποδέσμευση τομής
@@ -6016,6 +6018,7 @@ effect Points Σημεία
@msg no bound object reports a value (locked objects and embedded images report none) κανένα συνδεδεμένο αντικείμενο δεν αναφέρει τιμή (τα κλειδωμένα αντικείμενα και οι ενσωματωμένες εικόνες δεν αναφέρουν καμία)
@msg select an Intertwine group επιλέξτε μια ομάδα διαπλοκής
@msg select an Objects on Path group επιλέξτε μια ομάδα αντικειμένων σε διαδρομή
@msg choose the object to detach with its Select/Move widget επιλέξτε το αντικείμενο προς αποσύνδεση με το στοιχείο ελέγχου Επιλογή/Μετακίνηση
@msg a path inside a compound path, blend, envelope, repeat or Intertwine group can't take objects μια διαδρομή μέσα σε σύνθετη διαδρομή, ανάμειξη, περίβλημα, επανάληψη ή ομάδα διαπλοκής δεν μπορεί να δεχτεί αντικείμενα
@msg a clipping path can't take objects μια διαδρομή αποκοπής δεν μπορεί να δεχτεί αντικείμενα
@msg objects inside a blend, envelope, repeat or Intertwine group can't be attached to a path τα αντικείμενα μέσα σε ανάμειξη, περίβλημα, επανάληψη ή ομάδα διαπλοκής δεν μπορούν να προσαρτηθούν σε διαδρομή
Can't render this file because it is too large.
+3
View File
@@ -1592,6 +1592,8 @@ font-technology Variable Variables
Objects on Path Tool Herramienta Objetos en trazado
Attach Objects on Path Adjuntar objetos al trazado
Expand Objects on Path Expandir objetos en trazado
Detach Separar
Detach Object from Path Separar objeto del trazado
Release Live Paint Soltar pintura interactiva
Release Repeat Soltar repetición
Release Slice Soltar sector
@@ -4783,6 +4785,7 @@ axis Both Ambos
@msg select a repeat selecciona una repetición
@msg select an Intertwine group selecciona un grupo entrelazado
@msg select an Objects on Path group selecciona un grupo de objetos en trazado
@msg choose the object to detach with its Select/Move widget elige el objeto que quieres separar con su control Seleccionar/Mover
@msg a path inside a compound path, blend, envelope, repeat or Intertwine group can't take objects un trazado dentro de un trazado compuesto, una fusión, una envolvente, una repetición o un grupo entrelazado no puede recibir objetos
@msg a clipping path can't take objects un trazado de recorte no puede recibir objetos
@msg objects inside a blend, envelope, repeat or Intertwine group can't be attached to a path los objetos dentro de una fusión, una envolvente, una repetición o un grupo entrelazado no se pueden adjuntar a un trazado
Can't render this file because it contains an unexpected character in line 2 and column 73.
+3
View File
@@ -1813,6 +1813,8 @@ digits Malayalam Malajalam
Objects on Path Tool Objektit polulla -työkalu
Attach Objects on Path Kiinnitä objektit polulle
Expand Objects on Path Laajenna objektit polulla
Detach Irrota
Detach Object from Path Irrota objekti polulta
Release Live Paint Vapauta elävä maalaus
Release Repeat Vapauta toisto
Release Slice Vapauta siivu
@@ -6028,6 +6030,7 @@ mark-style Japanese Japanilainen
@msg no bound object reports a value (locked objects and embedded images report none) mikään sidottu objekti ei ilmoita arvoa (lukitut objektit ja upotetut kuvat eivät ilmoita arvoa)
@msg select an Intertwine group valitse lomitusryhmä
@msg select an Objects on Path group valitse Objektit polulla -ryhmä
@msg choose the object to detach with its Select/Move widget valitse irrotettava objekti sen Valitse/Siirrä-säätimellä
@msg a path inside a compound path, blend, envelope, repeat or Intertwine group can't take objects yhdistelmäpolun, sulautuksen, vääristyskuoren, toiston tai lomitusryhmän sisällä olevaan polkuun ei voi kiinnittää objekteja
@msg a clipping path can't take objects leikkauspolkuun ei voi kiinnittää objekteja
@msg objects inside a blend, envelope, repeat or Intertwine group can't be attached to a path sulautuksen, vääristyskuoren, toiston tai lomitusryhmän sisällä olevia objekteja ei voi kiinnittää polulle
Can't render this file because it contains an unexpected character in line 2 and column 73.
+3
View File
@@ -1586,6 +1586,8 @@ font-technology Variable Variables
Objects on Path Tool Outil Objets sur tracé
Attach Objects on Path Attacher des objets au tracé
Expand Objects on Path Décomposer les objets sur tracé
Detach Détacher
Detach Object from Path Détacher l’objet du tracé
Release Live Paint Annuler la peinture dynamique
Release Repeat Annuler la répétition
Release Slice Annuler la tranche
@@ -4772,6 +4774,7 @@ axis Both Les deux
@msg select a repeat sélectionnez une répétition
@msg select an Intertwine group sélectionnez un groupe entrelacé
@msg select an Objects on Path group sélectionnez un groupe d’objets sur tracé
@msg choose the object to detach with its Select/Move widget choisissez l’objet à détacher avec sa commande Sélectionner/Déplacer
@msg a path inside a compound path, blend, envelope, repeat or Intertwine group can't take objects un tracé à l’intérieur d’un tracé transparent, d’un dégradé de formes, d’une enveloppe, d’une répétition ou d’un groupe entrelacé ne peut pas recevoir d’objets
@msg a clipping path can't take objects un tracé d’écrêtage ne peut pas recevoir d’objets
@msg objects inside a blend, envelope, repeat or Intertwine group can't be attached to a path les objets à l’intérieur d’un dégradé de formes, d’une enveloppe, d’une répétition ou d’un groupe entrelacé ne peuvent pas être attachés à un tracé
Can't render this file because it contains an unexpected character in line 2 and column 73.
+3
View File
@@ -1706,6 +1706,8 @@ antiAlias Sharp शार्प
Expand Live Paint लाइव पेंट एक्सपैंड करें
Expand Object ऑब्जेक्ट का विस्तार
Expand Objects on Path पाथ पर ऑब्जेक्ट्स एक्सपैंड करें
Detach अलग करें
Detach Object from Path पाथ से ऑब्जेक्ट अलग करें
Expand Options ऑप्शन्स एक्सपैंड करें
Expand Panels पैनलों का विस्तार
Expand Repeat रिपीट एक्सपैंड करें
@@ -7731,6 +7733,7 @@ antiAlias Sharp शार्प
@msg select an object with a freeform gradient एक फ्रीफॉर्म ग्रेडिएंट के साथ एक ऑब्जेक्ट सिलेक्ट करें
@msg select an object with an opacity mask एक opacity मास्क के साथ एक ऑब्जेक्ट सिलेक्ट करें
@msg select an Objects on Path group पाथ समूह पर एक ऑब्जेक्ट चुनें
@msg choose the object to detach with its Select/Move widget अलग करने वाले ऑब्जेक्ट को उसके चुनें/ले जाएँ विजेट से चुनें
@msg select area type क्षेत्र प्रकार सिलेक्ट करें
@msg select area type (text in a frame) क्षेत्र प्रकार (एक फ्रेम में टेक्स्ट) सिलेक्ट करें
@msg select area type and closed paths (at least one area type object) क्षेत्र प्रकार और बंद पाथ (कम से कम एक क्षेत्र प्रकार ऑब्जेक्ट) सिलेक्ट करें
Can't render this file because it is too large.
+3
View File
@@ -1999,6 +1999,8 @@ file-filter Templates Sablonok
Objects on Path Tool Objektumok útvonalon
Attach Objects on Path Objektumok csatolása útvonalhoz
Expand Objects on Path Objektumok útvonalon kibontása
Detach Leválasztás
Detach Object from Path Objektum leválasztása az útvonalról
Release Live Paint Élő festés megszüntetése
Release Repeat Ismétlés megszüntetése
Release Slice Szelet megszüntetése
@@ -5539,6 +5541,7 @@ imageTrace Outline Körvonal
@msg select a repeat jelölj ki egy ismétlést
@msg select an Intertwine group jelölj ki egy összefonási csoportot
@msg select an Objects on Path group jelölj ki egy Objektumok útvonalon csoportot
@msg choose the object to detach with its Select/Move widget válaszd ki a leválasztandó objektumot a Kijelölés/Mozgatás vezérlőjével
@msg a path inside a compound path, blend, envelope, repeat or Intertwine group can't take objects összetett útvonalban, összemosásban, burkolóban, ismétlésben vagy összefonási csoportban lévő útvonalhoz nem csatolhatók objektumok
@msg a clipping path can't take objects vágóútvonalhoz nem csatolhatók objektumok
@msg objects inside a blend, envelope, repeat or Intertwine group can't be attached to a path összemosásban, burkolóban, ismétlésben vagy összefonási csoportban lévő objektumok nem csatolhatók útvonalhoz
Can't render this file because it contains an unexpected character in line 2 and column 73.
+2
View File
@@ -5821,6 +5821,8 @@ swatch Bright Violet Violet cerah
Objects on Path Tool Alat objek pada jalur
Attach Objects on Path Tempelkan objek pada jalur
Expand Objects on Path Perluas objek pada jalur
Detach Lepaskan
Detach Object from Path Lepaskan objek dari jalur
Release Live Paint Lepaskan Live Paint
Release Repeat Lepaskan perulangan
Release Slice Lepaskan slice
Can't render this file because it contains an unexpected character in line 2418 and column 5.
+3
View File
@@ -1623,6 +1623,8 @@ file-filter Templates Modelli
Objects on Path Tool Strumento Oggetti su tracciato
Attach Objects on Path Aggancia oggetti al tracciato
Expand Objects on Path Espandi oggetti su tracciato
Detach Sgancia
Detach Object from Path Sgancia oggetto dal tracciato
Release Live Paint Rilascia pittura dinamica
Release Repeat Rilascia ripetizione
Release Slice Rilascia sezione
@@ -4834,6 +4836,7 @@ axis Both Entrambi
@msg select a repeat seleziona una ripetizione
@msg select an Intertwine group seleziona un gruppo intrecciato
@msg select an Objects on Path group seleziona un gruppo di oggetti su tracciato
@msg choose the object to detach with its Select/Move widget scegli l’oggetto da sganciare con il suo controllo Seleziona/Sposta
@msg a path inside a compound path, blend, envelope, repeat or Intertwine group can't take objects un tracciato all'interno di un tracciato composto, una fusione, un involucro, una ripetizione o un gruppo intrecciato non può ricevere oggetti
@msg a clipping path can't take objects un tracciato di ritaglio non può ricevere oggetti
@msg objects inside a blend, envelope, repeat or Intertwine group can't be attached to a path gli oggetti all'interno di una fusione, un involucro, una ripetizione o un gruppo intrecciato non possono essere agganciati a un tracciato
Can't render this file because it contains an unexpected character in line 2 and column 73.
+3
View File
@@ -1992,6 +1992,8 @@ antiAlias Sharp シャープ
Objects on Path Tool パス上のオブジェクトツール
Attach Objects on Path パス上のオブジェクトをアタッチ
Expand Objects on Path パス上のオブジェクトを拡張
Detach 切り離し
Detach Object from Path オブジェクトをパスから切り離し
Release Live Paint ライブペイントを解除
Release Repeat リピートを解除
Release Slice スライスを解除
@@ -4556,6 +4558,7 @@ swatch Bright Violet ビビッドバイオレット
@msg select a repeat リピートを選択してください
@msg select an Intertwine group 織り交ぜグループを選択してください
@msg select an Objects on Path group パス上のオブジェクトグループを選択してください
@msg choose the object to detach with its Select/Move widget 切り離すオブジェクトを選択/移動ウィジェットで選んでください
@msg a path inside a compound path, blend, envelope, repeat or Intertwine group can't take objects 複合パス、ブレンド、エンベロープ、リピートまたは織り交ぜグループ内のパスにはオブジェクトをアタッチできません
@msg a clipping path can't take objects クリッピングパスにはオブジェクトをアタッチできません
@msg objects inside a blend, envelope, repeat or Intertwine group can't be attached to a path ブレンド、エンベロープ、リピートまたは織り交ぜグループ内のオブジェクトはパスにアタッチできません
Can't render this file because it contains an unexpected character in line 2 and column 73.
+3
View File
@@ -5715,6 +5715,7 @@ imageTrace Outline კონტური
Arrange Intertwine Area გადახლართვის არის დალაგება
@msg select an Intertwine group მონიშნეთ გადახლართვის ჯგუფი
@msg select an Objects on Path group მონიშნეთ ტრაექტორიაზე ობიექტების ჯგუფი
@msg choose the object to detach with its Select/Move widget მოსახსნელი ობიექტი აირჩიეთ მისი არჩევა/გადატანის ვიჯეტით
@msg a path inside a compound path, blend, envelope, repeat or Intertwine group can't take objects შედგენილ ტრაექტორიაში, გადასვლაში, გარსში, გამეორებაში ან გადახლართვის ჯგუფში მყოფ ტრაექტორიაზე ობიექტების მიმაგრება ვერ ხერხდება
@msg a clipping path can't take objects მომჭრელ ტრაექტორიაზე ობიექტების მიმაგრება ვერ ხერხდება
@msg objects inside a blend, envelope, repeat or Intertwine group can't be attached to a path გადასვლაში, გარსში, გამეორებაში ან გადახლართვის ჯგუფში მყოფი ობიექტების ტრაექტორიაზე მიმაგრება ვერ ხერხდება
@@ -5977,6 +5978,8 @@ imageTrace Outline კონტური
Objects on Path Tool ტრაექტორიაზე ობიექტების ხელსაწყო
Attach Objects on Path ობიექტების ტრაექტორიაზე მიმაგრება
Expand Objects on Path ტრაექტორიაზე ობიექტების გაშლა
Detach მოხსნა
Detach Object from Path ობიექტის ტრაექტორიიდან მოხსნა
Release Live Paint ცოცხალი შეღებვის მოხსნა
Release Repeat გამეორების მოხსნა
Release Slice ნაჭრის მოხსნა
Can't render this file because it is too large.
+3
View File
@@ -1982,6 +1982,8 @@ antiAlias Sharp 날카롭게
Objects on Path Tool 패스 위 개체 도구
Attach Objects on Path 패스 위 개체 부착
Expand Objects on Path 패스 위 개체 확장
Detach 분리
Detach Object from Path 패스에서 개체 분리
Release Live Paint 라이브 페인트 해제
Release Repeat 반복 해제
Release Slice 분할 해제
@@ -4483,6 +4485,7 @@ theme Appearance 외관
@msg select a repeat 반복을 선택하세요
@msg select an Intertwine group 교차 그룹을 선택하세요
@msg select an Objects on Path group 패스 위 개체 그룹을 선택하세요
@msg choose the object to detach with its Select/Move widget 분리할 개체를 선택/이동 위젯으로 고르세요
@msg a path inside a compound path, blend, envelope, repeat or Intertwine group can't take objects 컴파운드 패스, 블렌드, 엔벨로프, 반복 또는 교차 그룹 안의 패스에는 개체를 부착할 수 없습니다
@msg a clipping path can't take objects 클리핑 패스에는 개체를 부착할 수 없습니다
@msg objects inside a blend, envelope, repeat or Intertwine group can't be attached to a path 블렌드, 엔벨로프, 반복 또는 교차 그룹 안의 개체는 패스에 부착할 수 없습니다
Can't render this file because it contains an unexpected character in line 2 and column 73.
+3
View File
@@ -185,6 +185,7 @@
@msg node {_1} is on a locked artboard knooppunt {_1} staat op een vergrendeld tekengebied
@msg thumbnail: no page {n} (the file has 1) miniatuur: geen pagina {n} (het bestand heeft er 1)
@msg select an Objects on Path group selecteer een groep Objecten op pad
@msg choose the object to detach with its Select/Move widget kies het object dat je wilt loskoppelen met zijn widget Selecteren/verplaatsen
@msg a path inside a compound path, blend, envelope, repeat or Intertwine group can't take objects een pad binnen een samengesteld pad, mengsel, omvorming, herhaling of verstrengelingsgroep kan geen objecten opnemen
@msg a clipping path can't take objects een knippad kan geen objecten opnemen
@msg objects inside a blend, envelope, repeat or Intertwine group can't be attached to a path objecten binnen een mengsel, omvorming, herhaling of verstrengelingsgroep kunnen niet aan een pad worden gekoppeld
@@ -6391,6 +6392,8 @@ swatch Bright Violet Felviolet
Objects on Path Tool Objecten-op-pad-gereedschap
Attach Objects on Path Objecten aan pad koppelen
Expand Objects on Path Objecten op pad uitbreiden
Detach Loskoppelen
Detach Object from Path Object van pad loskoppelen
Release Live Paint Live Paint vrijgeven
Release Repeat Herhaling vrijgeven
Release Slice Slice vrijgeven
Can't render this file because it contains an unexpected character in line 2 and column 73.
+3
View File
@@ -1757,6 +1757,8 @@ digits Malayalam Malajalam
Objects on Path Tool Narzędzie Obiekty na ścieżce
Attach Objects on Path Dołącz obiekty do ścieżki
Expand Objects on Path Rozszerz obiekty na ścieżce
Detach Odłącz
Detach Object from Path Odłącz obiekt od ścieżki
Release Live Paint Uwolnij aktywne malowanie
Release Repeat Uwolnij powtórzenie
Release Slice Uwolnij plasterek
@@ -4916,6 +4918,7 @@ imageTrace Outline Kontur
@msg select a repeat zaznacz powtórzenie
@msg select an Intertwine group zaznacz grupę przeplotu
@msg select an Objects on Path group zaznacz grupę obiektów na ścieżce
@msg choose the object to detach with its Select/Move widget wybierz obiekt do odłączenia jego uchwytem Zaznacz/Przesuń
@msg a path inside a compound path, blend, envelope, repeat or Intertwine group can't take objects do ścieżki wewnątrz ścieżki złożonej, przejścia, koperty, powtórzenia lub grupy przeplotu nie można dołączyć obiektów
@msg a clipping path can't take objects do ścieżki przycinającej nie można dołączyć obiektów
@msg objects inside a blend, envelope, repeat or Intertwine group can't be attached to a path obiektów wewnątrz przejścia, koperty, powtórzenia lub grupy przeplotu nie można dołączyć do ścieżki
Can't render this file because it contains an unexpected character in line 2 and column 73.
+3
View File
@@ -1410,6 +1410,8 @@ antiAlias Sharp Nítido
Objects on Path Tool Ferramenta Objetos no Caminho
Attach Objects on Path Anexar Objetos ao Caminho
Expand Objects on Path Expandir Objetos no Caminho
Detach Desanexar
Detach Object from Path Desanexar Objeto do Caminho
Release Live Paint Liberar Pintura ao Vivo
Release Repeat Liberar Repetição
Release Slice Liberar Fatia
@@ -4239,6 +4241,7 @@ axis Both Ambos
@msg select a repeat selecione uma repetição
@msg select an Intertwine group selecione um grupo entrelaçado
@msg select an Objects on Path group selecione um grupo de objetos no caminho
@msg choose the object to detach with its Select/Move widget escolha o objeto a desanexar com o controle Selecionar/Mover dele
@msg a path inside a compound path, blend, envelope, repeat or Intertwine group can't take objects um caminho dentro de um caminho composto, mesclagem, envelope, repetição ou grupo entrelaçado não pode receber objetos
@msg a clipping path can't take objects um caminho de recorte não pode receber objetos
@msg objects inside a blend, envelope, repeat or Intertwine group can't be attached to a path objetos dentro de uma mesclagem, envelope, repetição ou grupo entrelaçado não podem ser anexados a um caminho
Can't render this file because it contains an unexpected character in line 6 and column 47.
+3
View File
@@ -1612,6 +1612,8 @@ file-filter Templates Шаблоны
Objects on Path Tool Инструмент «Объекты на контуре»
Attach Objects on Path Прикрепить объекты к контуру
Expand Objects on Path Разобрать объекты на контуре
Detach Открепить
Detach Object from Path Открепить объект от контура
Release Live Paint Освободить быструю заливку
Release Repeat Освободить повтор
Release Slice Освободить фрагмент
@@ -4820,6 +4822,7 @@ axis Both Оба
@msg select a repeat выделите повтор
@msg select an Intertwine group выделите группу переплетения
@msg select an Objects on Path group выделите группу объектов на контуре
@msg choose the object to detach with its Select/Move widget выберите открепляемый объект его элементом «Выбрать/Переместить»
@msg a path inside a compound path, blend, envelope, repeat or Intertwine group can't take objects к контуру внутри составного контура, перехода, оболочки, повтора или группы переплетения нельзя прикрепить объекты
@msg a clipping path can't take objects к контуру обрезки нельзя прикрепить объекты
@msg objects inside a blend, envelope, repeat or Intertwine group can't be attached to a path объекты внутри перехода, оболочки, повтора или группы переплетения нельзя прикрепить к контуру
Can't render this file because it is too large.
+3
View File
@@ -1550,6 +1550,8 @@ font-technology Variable Variabla
Objects on Path Tool Verktyg för objekt på bana
Attach Objects on Path Fäst objekt på bana
Expand Objects on Path Expandera objekt på bana
Detach Lossa
Detach Object from Path Lossa objekt från bana
Release Live Paint Släpp direktmålning
Release Repeat Släpp upprepning
Release Slice Släpp skiva
@@ -6019,6 +6021,7 @@ theme Appearance Utseende
@msg no bound object reports a value (locked objects and embedded images report none) inget bundet objekt rapporterar ett värde (låsta objekt och inbäddade bilder rapporterar inget)
@msg select an Intertwine group markera en sammanflätningsgrupp
@msg select an Objects on Path group markera en grupp med objekt på bana
@msg choose the object to detach with its Select/Move widget välj objektet som ska lossas med dess Markera/Flytta-reglage
@msg a path inside a compound path, blend, envelope, repeat or Intertwine group can't take objects en bana inuti en sammansatt bana, en blandning, ett kuvert, en upprepning eller en sammanflätningsgrupp kan inte ta emot objekt
@msg a clipping path can't take objects en klippbana kan inte ta emot objekt
@msg objects inside a blend, envelope, repeat or Intertwine group can't be attached to a path objekt inuti en blandning, ett kuvert, en upprepning eller en sammanflätningsgrupp kan inte fästas på en bana
Can't render this file because it is too large.
+17
View File
@@ -184,6 +184,23 @@ fn font_height_reference_labels_are_in_complete_catalogs() {
}
}
/// The Objects on Path Options section's Detach button, its undo step and the message for a
/// Detach with no object chosen.
#[test]
fn objects_on_path_detach_strings_are_in_complete_catalogs() {
for lang in LANGUAGES.iter().filter(|lang| lang.complete_menus) {
for label in ["Detach", "Detach Object from Path"] {
assert!(lang.catalog().plain(label).is_some(), "{} is missing {label}", lang.code);
}
}
let choose = "choose the object to detach with its Select/Move widget";
assert!(message_literals().contains(choose));
for code in COMPLETE_MESSAGES {
let lang = Lang::from_code(code).expect("registered");
assert_ne!(message(lang, choose), choose, "{code}");
}
}
/// The Window › Brush Libraries menu, built from the built-in library table, names each library.
#[test]
fn built_in_brush_library_names_are_in_complete_catalogs() {
+3
View File
@@ -5977,6 +5977,7 @@ theme Appearance Görünüm
@msg nothing in data set {name} was applied: no object is bound to a variable it has a value for {name} veri kümesinden hiçbir şey uygulanmadı: değer içerdiği bir değişkene bağlı hiçbir nesne yok
@msg no bound object reports a value (locked objects and embedded images report none) bağlı hiçbir nesne bir değer bildirmiyor (kilitli nesneler ve gömülü görüntüler değer bildirmez)
@msg select an Objects on Path group bir Yol Üzerindeki Nesneler grubu seçin
@msg choose the object to detach with its Select/Move widget ayrılacak nesneyi Seç/Taşı denetimiyle seçin
@msg the Simplify slider is not open Basitleştirme kaydırıcısı açık değil
@msg the Smooth slider is not open Düzgünleştirme kaydırıcısı açık değil
@msg {_1} is an exporter (File › Export › Export As…) {_1} bir dışa aktarma eklentisidir (Dosya › Dışa Aktar › Farklı Dışa Aktar…)
@@ -6009,6 +6010,8 @@ theme Appearance Görünüm
Chrome Krom
Chrome… Krom…
Expand Objects on Path Yol Üzerindeki Nesneleri Genişlet
Detach Ayır
Detach Object from Path Nesneyi Yoldan Ayır
Graphic Pen Grafik Kalemi
Graphic Pen… Grafik Kalemi…
Move Anchor Point Bağlantı Noktasını Taşı
Can't render this file because it contains an unexpected character in line 5 and column 25.
+3
View File
@@ -1617,6 +1617,8 @@ file-filter Templates Шаблони
Objects on Path Tool Інструмент «Об’єкти на контурі»
Attach Objects on Path Прикріпити об’єкти до контуру
Expand Objects on Path Розібрати об’єкти на контурі
Detach Відкріпити
Detach Object from Path Відкріпити об’єкт від контуру
Release Live Paint Звільнити швидку заливку
Release Repeat Звільнити повтор
Release Slice Звільнити фрагмент
@@ -4818,6 +4820,7 @@ axis Both Обидві
@msg select a repeat виділіть повтор
@msg select an Intertwine group виділіть групу переплетення
@msg select an Objects on Path group виділіть групу об’єктів на контурі
@msg choose the object to detach with its Select/Move widget виберіть об’єкт для відкріплення його елементом «Вибрати/Перемістити»
@msg a path inside a compound path, blend, envelope, repeat or Intertwine group can't take objects до контуру всередині складеного контуру, переходу, оболонки, повтору або групи переплетення не можна прикріпити об’єкти
@msg a clipping path can't take objects до відсічного контуру не можна прикріпити об’єкти
@msg objects inside a blend, envelope, repeat or Intertwine group can't be attached to a path об’єкти всередині переходу, оболонки, повтору або групи переплетення не можна прикріпити до контуру
Can't render this file because it is too large.
+3
View File
@@ -1847,6 +1847,8 @@ digits Hindi Hindi
Objects on Path Tool Công cụ Đối tượng trên đường dẫn
Attach Objects on Path Gắn đối tượng lên đường dẫn
Expand Objects on Path Mở rộng đối tượng trên đường dẫn
Detach Tách
Detach Object from Path Tách đối tượng khỏi đường dẫn
Release Live Paint Giải phóng tô trực tiếp
Release Repeat Giải phóng lặp lại
Release Slice Giải phóng lát cắt
@@ -5202,6 +5204,7 @@ theme Appearance Giao diện
@msg select a repeat hãy chọn một đối tượng lặp
@msg select an Intertwine group hãy chọn một nhóm đan xen
@msg select an Objects on Path group hãy chọn một nhóm đối tượng trên đường dẫn
@msg choose the object to detach with its Select/Move widget hãy chọn đối tượng cần tách bằng tiện ích Chọn/Di chuyển của nó
@msg a path inside a compound path, blend, envelope, repeat or Intertwine group can't take objects không thể gắn đối tượng lên một đường dẫn nằm trong đường dẫn phức, đối tượng hòa trộn, Envelope, đối tượng lặp hoặc nhóm đan xen
@msg a clipping path can't take objects không thể gắn đối tượng lên đường dẫn cắt
@msg objects inside a blend, envelope, repeat or Intertwine group can't be attached to a path không thể gắn các đối tượng nằm trong đối tượng hòa trộn, Envelope, đối tượng lặp hoặc nhóm đan xen lên đường dẫn
Can't render this file because it contains an unexpected character in line 204 and column 5.
+3
View File
@@ -1543,6 +1543,8 @@ file-filter Templates 模板
Objects on Path Tool 路径上的对象工具
Attach Objects on Path 附加路径上的对象
Expand Objects on Path 扩展路径上的对象
Detach 分离
Detach Object from Path 将对象从路径分离
Release Live Paint 释放实时上色
Release Repeat 释放重复
Release Slice 释放切片
@@ -4259,6 +4261,7 @@ imageTrace Outline 轮廓
@msg select a repeat 请选择一个重复对象
@msg select an Intertwine group 请选择一个交织组
@msg select an Objects on Path group 请选择一个路径上的对象组
@msg choose the object to detach with its Select/Move widget 请用对象的“选择/移动”控件选择要分离的对象
@msg a path inside a compound path, blend, envelope, repeat or Intertwine group can't take objects 复合路径、混合对象、封套、重复对象或交织组中的路径无法附加对象
@msg a clipping path can't take objects 剪切路径无法附加对象
@msg objects inside a blend, envelope, repeat or Intertwine group can't be attached to a path 混合对象、封套、重复对象或交织组中的对象无法附加到路径
Can't render this file because it contains an unexpected character in line 2 and column 73.
+3
View File
@@ -1588,6 +1588,8 @@ file-filter Templates 範本
Objects on Path Tool 路徑上的物件工具
Attach Objects on Path 附加路徑上的物件
Expand Objects on Path 展開路徑上的物件
Detach 分離
Detach Object from Path 將物件從路徑分離
Release Live Paint 釋放即時上色
Release Repeat 釋放重複
Release Slice 釋放切片
@@ -2021,6 +2023,7 @@ file-filter Templates 範本
@msg select a repeat 請選取重複物件
@msg select an Intertwine group 請選取交織群組
@msg select an Objects on Path group 請選取路徑上的物件群組
@msg choose the object to detach with its Select/Move widget 請用物件的「選取/移動」控制項選取要分離的物件
@msg a path inside a compound path, blend, envelope, repeat or Intertwine group can't take objects 複合路徑、漸變物件、封套、重複物件或交織群組中的路徑無法附加物件
@msg a clipping path can't take objects 剪裁路徑無法附加物件
@msg objects inside a blend, envelope, repeat or Intertwine group can't be attached to a path 漸變物件、封套、重複物件或交織群組中的物件無法附加到路徑
Can't render this file because it contains an unexpected character in line 6 and column 47.
+18 -4
View File
@@ -389,12 +389,15 @@ fn trace_section(app: &mut VectorcraftApp, ui: &mut Ui, preset: &str, view: vect
});
}
/// The Objects on Path groups selected with nothing else: their ids, and the Pivot and Rotate they
/// share (`None` where they differ).
/// The Objects on Path groups selected with nothing else: their ids, the Pivot and Rotate they
/// share (`None` where they differ), and whether Detach can take an object off the path: one group,
/// neither hidden nor locked, with an object chosen with its Select/Move widget that is neither
/// hidden nor locked.
struct ObjectsOnPathSelection {
ids: Vec<u64>,
pivot: Option<u8>,
rotate: Option<f64>,
detachable: bool,
}
/// The selection as Objects on Path groups ([`ObjectsOnPathSelection`]), when every selected
@@ -405,7 +408,11 @@ fn selected_objects_on_path(app: &VectorcraftApp) -> Option<ObjectsOnPathSelecti
for id in &st.selection.objects {
let rec = st.doc.node(*id)?.extras().objects_on_path.as_deref()?;
match &mut out {
None => out = Some(ObjectsOnPathSelection { ids: vec![id.0], pivot: Some(rec.pivot), rotate: Some(rec.rotate) }),
None => {
let chosen = st.selection.on_path_member.filter(|m| st.selection.objects.len() == 1 && rec.members.iter().any(|x| x.id == *m));
let detachable = chosen.is_some_and(|m| st.doc.is_editable(*id) && st.doc.is_editable(m));
out = Some(ObjectsOnPathSelection { ids: vec![id.0], pivot: Some(rec.pivot), rotate: Some(rec.rotate), detachable });
}
Some(s) => {
s.ids.push(id.0);
if s.pivot != Some(rec.pivot) {
@@ -425,7 +432,8 @@ fn selected_objects_on_path(app: &VectorcraftApp) -> Option<ObjectsOnPathSelecti
/// path, as the help page places them in the Properties panel
/// (<https://helpx.adobe.com/illustrator/using/objects-on-path.html>). A change goes to every
/// selected group in one undo step (`object.objectsOnPath.options`). Where the groups differ, no
/// Pivot square is chosen and Rotate is blank.
/// Pivot square is chosen and Rotate is blank. Detach takes the object chosen with its Select/Move
/// widget off the path (`object.objectsOnPath.detach`), and is dimmed until one is chosen.
fn objects_on_path_section(app: &mut VectorcraftApp, ui: &mut Ui, oop: &ObjectsOnPathSelection) {
section_header(ui, tl!("Objects on Path Options"));
let fw = super::field_width(ui);
@@ -452,6 +460,12 @@ fn objects_on_path_section(app: &mut VectorcraftApp, ui: &mut Ui, oop: &ObjectsO
}
ui.end_row();
});
let w = ui.available_width();
if ui.add_enabled_ui(oop.detachable, |ui| widgets::flat_button(ui, tl!("Detach"), w)).inner.clicked()
&& let Err(e) = app.run("object.objectsOnPath.detach", json!({}))
{
app.status(e);
}
}
/// Whether the selection uses more than one colour (`recolor.colors`), which offers the Recolor
@@ -1879,6 +1879,39 @@ fn objects_on_path_options_set_pivot_and_rotate_in_one_undo_step() {
assert_eq!(undo_depth(&app), depth + 1, "one undo step for both groups");
}
/// The objects of the Objects on Path group `id`, in their order along the path.
fn on_path(app: &VectorcraftApp, id: &Value) -> Vec<u64> {
let d = &app.session.active().unwrap().doc;
let rec = d.node(vectorcraft_doc::NodeId(id.as_u64().unwrap())).unwrap().extras().objects_on_path.as_deref().unwrap();
rec.members.iter().map(|m| m.id.0).collect()
}
/// The help page's Detach in the Objects on Path Options section takes the object chosen with its
/// Select/Move widget off the path in one undo step and selects it. It is dimmed, and a click does
/// nothing, until one group is selected with an object chosen.
#[test]
fn detach_takes_the_chosen_object_off_the_path() {
let (mut app, ctx) = reference_setup(&[]);
let group = objects_on_path(&mut app, 150.0, 0.0);
let [first, second] = on_path(&app, &group)[..] else { panic!("two objects") };
assert!(shows(&panel_frame(&mut app, &ctx, vec![], objects_on_path_options), "Detach"));
let depth = undo_depth(&app);
click_named(&mut app, &ctx, objects_on_path_options, "Detach");
assert_eq!((on_path(&app, &group), undo_depth(&app)), (vec![first, second], depth), "no object chosen: dimmed");
let other = objects_on_path(&mut app, 250.0, 0.0);
app.run("object.objectsOnPath.selectMember", json!({"member": first})).unwrap();
app.run("select.add", json!({"ids": [other]})).unwrap();
click_named(&mut app, &ctx, objects_on_path_options, "Detach");
assert_eq!(on_path(&app, &group), [first, second], "two groups: dimmed");
app.run("object.objectsOnPath.selectMember", json!({"member": first})).unwrap();
let depth = undo_depth(&app);
click_named(&mut app, &ctx, objects_on_path_options, "Detach");
assert_eq!(on_path(&app, &group), [second]);
assert_eq!(undo_depth(&app), depth + 1, "one undo step");
let sel = &app.session.active().unwrap().selection;
assert_eq!((sel.objects.iter().map(|i| i.0).collect::<Vec<_>>(), sel.on_path_member), (vec![first], None));
}
/// #3759: with area type selected, the Properties panel's Paragraph section shows Align Top, Align
/// Center, Align Bottom and Justify Vertically; a click sets the alignment on every selected frame
/// in one undo step. Point type shows none; frames with rows or columns and threaded frames turn
+15
View File
@@ -9896,11 +9896,26 @@ order along the path changes: Space, the start, Pivot, Rotate and the children's
new place along the path counted from 0. `object.objectsOnPath.selectMember {member}` takes the same kind of `member`
and returns `{group, member}`.
`object.objectsOnPath.detach {member?}` takes one object off the path: `member`, or without it the object chosen with
the Select/Move widget of the one selected group (otherwise it fails with "choose the object to detach with its
Select/Move widget"). `member` takes the same kind of object as `moveMember`, and neither it nor the group may be
hidden or locked. The object leaves the group and goes just above it in the group's layer or group, staying where it
is drawn, and becomes the selection; when the group is itself an object on another group's path, the object goes just
above that outer group, so it does not join its path. The objects after it move up the path in their order: with Auto Space they spread
evenly again (on an open path the first and last on its ends while two or more are left), and a Space value and the
start are kept, drawn as close as the path has room for. Hidden and locked objects left in the group move up too. The
group, its path and its options stay even with one object or none left, and an object moved back into it joins the
path. It is one undo step, and undo puts the object back on the path with the choice it had. It returns
`{group, member}`. In the desktop app, Detach in the Properties panel's Objects on Path Options section sends it, and
is dimmed until one group is selected with an object chosen. To take several objects off at once, drag their rows out
of the group in the Layers panel (`layer.move`).
```json
{"name":"run_command","arguments":{"command":"tool.setOption","params":{"tool":"objectsOnPath","values":{"pivot":7,"rotate":30}}}}
{"name":"run_command","arguments":{"command":"object.objectsOnPath.attach","params":{"path":30,"ids":[12,15,18]}}}
{"name":"run_command","arguments":{"command":"object.objectsOnPath.options","params":{"pivot":7,"rotate":15}}}
{"name":"run_command","arguments":{"command":"object.objectsOnPath.options","params":{"spacing":24,"start":0}}}
{"name":"run_command","arguments":{"command":"object.objectsOnPath.detach","params":{"member":15}}}
{"name":"run_command","arguments":{"command":"object.objectsOnPath.expand","params":{}}}
```
+2 -1
View File
@@ -1367,10 +1367,11 @@ Moved from the ROADMAP's "Shipped so far" on 2026-10-10. Update it when a featur
Window › Blend opens the Blend panel: Make, the selected blend's Spacing and Orientation (with no blend selected, the options new blends start with), Reverse Front to Back, Reverse Spine, Replace Spine, Expand and Release, each running its Object › Blend command. Make is dimmed until two or more objects are selected. Spacing and Orientation are dimmed until a blend or two or more objects are selected, and the other buttons are dimmed until a blend is selected.
The Blend panel's Create Spine menu (Auto, Always, Never; `object.blend.createSpine`) sets whether new blends get a spine, from the Blend tool, Make and `object.blend.make` alike ([Blend panel overview](https://helpx.adobe.com/illustrator/desktop/manage-colors/apply-transparency-and-blending/blend-panel-overview.html)). Auto and Always give every new blend a straight spine, as before; Never makes blends without one, which keep their steps on the straight lines between the keys, have Type and Ramp dimmed, refuse Reverse Spine and spine edits, release without a spine path, and get a spine from Replace Spine. The setting is kept with the preferences and leaves blends already made as they are; Auto as the starting value and keeping the setting across sessions are VectorCraft's own rules. Builds on #5177 by adambelis. Evidence: `tests::blendopts::{create_spine_sets_whether_new_blends_get_a_spine, a_blend_without_a_spine_has_none_to_edit_reverse_ease_or_release, whether_a_blend_has_a_spine_is_saved_and_old_blends_have_one}` and `panels::tests_blend::create_spine_sets_what_new_blends_get_whatever_is_selected`.
With the Blend tool, Escape drops the object clicked first and stops the next click adding to the blend just made, so the next click picks a new first object; the document and the selection stay as they are. Regression tests: `escape_drops_the_blend_tools_first_pick` in `meshblend.rs` and `tests/blendopts.rs`.
Objects on Path (#2545): a click with the Objects on Path tool (in Edit Toolbar's Modify section and the Blend tool's flyout; Object › Objects on Path › Attach and the context menu with two or more objects selected choose it) attaches the selected objects to the path clicked, open or closed, in an Objects on Path group with the path at its bottom. The objects go along the path column by column from left to right, spread evenly from its first anchor (the last one sits on the end of an open path), each turned to the path at its attachment point; Pivot and Rotate set where each one attaches and how far it tilts (`object.objectsOnPath.attach`, `object.objectsOnPath.options`), and with Objects on Path groups selected the Properties panel's Objects on Path Options section shows them as a nine-point Pivot grid and a Rotate field with common angles, each change one undo step for every selected group. Editing the path moves the objects, an object moved on its own goes back, objects moved into or out of the group in the Layers panel join or leave the path, and Object › Objects on Path › Expand leaves a plain group. The group saves and reopens live and exports as plain art. With one Objects on Path group selected, the Selection and Objects on Path tools show the Rotate All widget beside its first object: dragging it turns every object about its attachment point by the angle the pointer turns, adding it to the group's Rotate in one undo step, in 15° steps with Shift ([Objects on Path](https://helpx.adobe.com/illustrator/using/objects-on-path.html)). Detach is missing.
Objects on Path (#2545): a click with the Objects on Path tool (in Edit Toolbar's Modify section and the Blend tool's flyout; Object › Objects on Path › Attach and the context menu with two or more objects selected choose it) attaches the selected objects to the path clicked, open or closed, in an Objects on Path group with the path at its bottom. The objects go along the path column by column from left to right, spread evenly from its first anchor (the last one sits on the end of an open path), each turned to the path at its attachment point; Pivot and Rotate set where each one attaches and how far it tilts (`object.objectsOnPath.attach`, `object.objectsOnPath.options`), and with Objects on Path groups selected the Properties panel's Objects on Path Options section shows them as a nine-point Pivot grid and a Rotate field with common angles, each change one undo step for every selected group. Editing the path moves the objects, an object moved on its own goes back, objects moved into or out of the group in the Layers panel join or leave the path, and Object › Objects on Path › Expand leaves a plain group. The group saves and reopens live and exports as plain art. With one Objects on Path group selected, the Selection and Objects on Path tools show the Rotate All widget beside its first object: dragging it turns every object about its attachment point by the angle the pointer turns, adding it to the group's Rotate in one undo step, in 15° steps with Shift ([Objects on Path](https://helpx.adobe.com/illustrator/using/objects-on-path.html)). Detach is in its own entry below.
Objects on Path Space widget: with one Objects on Path group of two or more objects selected, the Selection and Objects on Path tools show a square handle beyond its last object; dragging it along the path, round its bends, sets the distance between the objects' attachment points in one undo step, the first object staying where it is, and with Alt (Option on macOS) the objects spread from both ends toward the center; the distance shows next to the pointer during the drag, in the document's units ([Rearrange and edit objects on a path](https://helpx.adobe.com/illustrator/desktop/manage-objects/arrange-objects/rearrange-and-edit-objects-on-a-path.html), [Objects on Path](https://helpx.adobe.com/illustrator/using/objects-on-path.html)). The group keeps the distance (`object.objectsOnPath.options {spacing, start}`) through Pivot and Rotate changes, path edits, copies, saving and reopening, and scales it with the group; by default (`"auto"`) the objects are spread evenly as before. Evidence: `objects_on_path::tests::{space_sets_the_distance_between_the_stops, space_on_a_closed_path_wraps_at_the_first_anchor_and_stops_short_of_the_first_object}` in `crates/doc`, `tests::objects_on_path::space_sets_the_distance_between_the_objects_in_one_undo_step` in `crates/engine`, `objects_on_path::tests::dragging_the_space_widget_spaces_the_objects_from_the_first_one` in `crates/tools`.
Objects on Path Move All widget: with one Objects on Path group selected whose objects have room to move, the Selection and Objects on Path tools show a diamond below its first object; dragging it along the path, round its bends, moves every object along the path together in one undo step, keeping the distances between them (`object.objectsOnPath.options {start}`). On an open path the widget shows only when the distance from the first object to the last is shorter than the path, so not for objects spread evenly from end to end, and the objects stop at the path's ends; on a closed path they go on round across its first anchor. The first object's distance along the path shows next to the pointer during the drag, in the document's units ([Rearrange and edit objects on a path](https://helpx.adobe.com/illustrator/desktop/manage-objects/arrange-objects/rearrange-and-edit-objects-on-a-path.html), [Objects on Path](https://helpx.adobe.com/illustrator/using/objects-on-path.html)). Evidence: `objects_on_path::tests::{dragging_the_move_all_widget_moves_every_object_along_the_path, a_move_all_drag_on_a_closed_path_goes_round_across_the_first_anchor}` in `crates/tools`, `canvas::tests::a_selected_objects_on_path_group_shows_its_move_all_widget_when_it_has_room` in `crates/ui-egui`.
Objects on Path Select/Move widget: with one Objects on Path group selected, the Selection and Objects on Path tools show a small ring on each object's attachment point, highlighted under the pointer. A click on one chooses that object and fills its ring blue while the group stays selected (`object.objectsOnPath.selectMember`); a click on the object's art still selects the group. Dragging a ring along the path moves its object to the object's place nearest the pointer, and the objects between move one place toward where it was, in one undo step (`object.objectsOnPath.moveMember`); hidden and locked objects keep their places; only the order along the path changes, not the Layers panel's order or the Space. On an open path the drag stops at the ends, on a closed path it goes on round across the first anchor, and Escape cancels it ([Rearrange and edit objects on a path](https://helpx.adobe.com/illustrator/desktop/manage-objects/arrange-objects/rearrange-and-edit-objects-on-a-path.html), [Objects on Path](https://helpx.adobe.com/illustrator/using/objects-on-path.html)). Evidence: `objects_on_path::tests::moving_an_object_shifts_the_ones_between_it_and_its_new_place` in `crates/doc`, `tests::objects_on_path::move_member_takes_the_target_s_place_and_shifts_the_objects_between` in `crates/engine`, `objects_on_path::tests::{dragging_a_select_move_widget_moves_its_object_to_the_nearest_place, a_select_move_drag_goes_round_a_closed_path_across_its_first_anchor}` in `crates/tools`, `canvas::tests::a_selected_objects_on_path_group_shows_a_select_move_widget_per_object` in `crates/ui-egui`.
Objects on Path Detach: with one Objects on Path group selected and an object chosen with its Select/Move widget, Detach in the Properties panel's Objects on Path Options section takes that one object off the path (`object.objectsOnPath.detach`), and the objects after it move up the path in their order: with Auto Space they spread evenly again, the ends of an open path staying occupied while two or more are left, and a Space value is kept ([Objects on Path](https://helpx.adobe.com/illustrator/using/objects-on-path.html), [Rearrange and edit objects on a path](https://helpx.adobe.com/illustrator/desktop/manage-objects/arrange-objects/rearrange-and-edit-objects-on-a-path.html)). Detach is dimmed until an object is chosen. VectorCraft's own rules: the object stays where it is drawn, goes just above the group in the Layers panel and is selected alone; the start is kept; the group and its path stay with one object or none left; a hidden or locked object or group is not detached; and Detach is one undo step. Several objects still leave together by dragging their rows out of the group in the Layers panel. Evidence: `tests::objects_on_path::{detach_takes_the_chosen_object_off_the_path_and_the_others_move_up_in_one_undo_step, after_the_first_object_is_detached_the_second_takes_the_start, detach_on_a_closed_path_spreads_the_others_all_the_way_round_again, detach_keeps_a_space_value_and_the_start, the_group_and_its_path_stay_with_one_object_or_none_left, an_object_detached_from_a_group_on_another_path_does_not_join_that_path, detach_refuses_what_is_not_one_chosen_editable_object_on_a_path}` in `crates/engine`, `panels::properties::tests::detach_takes_the_chosen_object_off_the_path` in `crates/ui-egui`.
Double-clicking the Objects on Path tool opens Objects on Path Tool Options ([Objects on Path](https://helpx.adobe.com/illustrator/using/objects-on-path.html)): the nine-point Pivot grid and the Rotate field set the attachment point and angle of the objects attached next, and groups already attached keep theirs; Reset puts the center and 0° back. Save keeps the options across tool switches and saves them with the preferences (`tool.setOption {tool: "objectsOnPath"}`).
- **Paint and appearance (M3):**
- **CSS swatch libraries:** fractional linear and radial gradient stop positions are preserved, so nearby stops such as 12.5% and 12.890625% remain distinct instead of collapsing to 13%. Reference: [CSS Images 3 color stops](https://www.w3.org/TR/css-images-3/#color-stop-syntax). The original synthetic regression is `palette_io::tests::css_preserves_fractional_gradient_stop_positions` in `crates/color/src/palette_io.rs`. Scores and hours are unchanged.