mirror of
https://github.com/storytold/designcraft.git
synced 2026-11-14 22:35:26 +00:00
Layers: Duplicate Layer numbers copies in story order and is translated
Duplicate Layer gave the copied stories' tables and anchored objects their new ids in hash-map order, so the ids differed from run to run. It now takes the stories in order. The Layers panel's "Duplicate Layer" menu item has a row in every interface language.
This commit is contained in:
1 parent
8522253d74
commit
d11a050a67
12 files changed
+62
-3
No files matched your search
@@ -1409,17 +1409,21 @@ fn duplicate_layer(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
d.insert_item(r, copy, None)?;
|
||||
}
|
||||
// A story copy holds the same anchored objects as the original: they get ids of their own, and the stories of
|
||||
// anchored text frames get copies in turn.
|
||||
// anchored text frames get copies in turn. The story copies are taken in story order.
|
||||
let mut pending: Vec<StoryId> = stories.values().copied().collect();
|
||||
pending.sort_unstable();
|
||||
pending.reverse();
|
||||
while let Some(new) = pending.pop() {
|
||||
let Some(mut st) = d.story(new).cloned() else { continue };
|
||||
renumber_anchored(d, &mut st, new_id, &mut stories, &mut ids, &mut pending);
|
||||
d.stories.insert(new, Arc::new(st));
|
||||
}
|
||||
// Each story copy gets its frames in the original order, text anchors of its own, which its cross-references
|
||||
// and those of the other copies point at, and tables with ids of their own.
|
||||
// and those of the other copies point at, and tables with ids of their own, allocated in story order.
|
||||
let mut anchors = HashMap::new();
|
||||
for (old, new) in &stories {
|
||||
let mut order: Vec<(StoryId, StoryId)> = stories.iter().map(|(old, new)| (*old, *new)).collect();
|
||||
order.sort_unstable_by_key(|(_, new)| *new);
|
||||
for (old, new) in &order {
|
||||
let Some(mut st) = d.story(*new).cloned() else { continue };
|
||||
st.frames = src.story(*old).map(|o| o.frames.iter().filter_map(|f| ids.get(f).copied()).collect()).unwrap_or_default();
|
||||
for (k, a) in (1..).zip(st.anchors.iter_mut()) {
|
||||
@@ -2116,6 +2120,33 @@ mod layer_tests {
|
||||
assert_eq!(d.story(copied).unwrap().tables[&new].nrows(), 2, "a command naming the copy's table changes the copy");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn duplicate_layer_numbers_copied_tables_and_anchored_objects_in_story_order() {
|
||||
let mut s = crate::Session::new();
|
||||
s.execute("file.new", &json!({})).unwrap();
|
||||
let base = s.doc().unwrap().doc.layers[0].id.0;
|
||||
for k in 0..8 {
|
||||
let y = 72 + 80 * k;
|
||||
let text = json!({"rect": [72, y, 400, y + 60], "content": "text", "text": "Rows"});
|
||||
let f = s.execute("frame.create", &text).unwrap()["id"].as_u64().unwrap();
|
||||
let sid = s.doc().unwrap().doc.item(designcraft_doc::ItemId(f)).unwrap().text_frame().unwrap().story;
|
||||
s.execute("text.select", &json!({"story": sid.0, "anchor": 4, "focus": 4})).unwrap();
|
||||
s.execute("table.insert", &json!({"rows": 1, "cols": 2})).unwrap();
|
||||
let b = s.execute("frame.create", &json!({"rect": [450, y, 474, y + 40]})).unwrap()["id"].as_u64().unwrap();
|
||||
s.execute("anchored.insert", &json!({"ids": [b], "story": sid.0, "pos": 0})).unwrap();
|
||||
}
|
||||
let copy = s.execute("layer.duplicate", &json!({"id": base})).unwrap()["id"].as_u64().unwrap();
|
||||
let d = &s.doc().unwrap().doc;
|
||||
d.check().unwrap();
|
||||
let mut stories: Vec<_> = on_layer(d, copy).iter().filter_map(|i| i.text_frame().map(|t| t.story)).collect();
|
||||
stories.sort_unstable();
|
||||
assert_eq!(stories.len(), 8);
|
||||
let tables: Vec<u64> = stories.iter().map(|sid| *d.story(*sid).unwrap().tables.keys().next().unwrap()).collect();
|
||||
let objects: Vec<u64> = stories.iter().map(|sid| d.story(*sid).unwrap().objects[0].item.id.0).collect();
|
||||
assert!(tables.is_sorted(), "the copied tables take ids in story order: {tables:?}");
|
||||
assert!(objects.is_sorted(), "the copied anchored objects take ids in story order: {objects:?}");
|
||||
}
|
||||
|
||||
/// 40 stories, each holding two anchored text frames threaded in the next: 2^40 paths, 40 stories.
|
||||
#[test]
|
||||
fn duplicate_layer_checks_each_shared_story_once() {
|
||||
|
||||
@@ -4562,6 +4562,10 @@ const TABLE: &[(&str, [&str; 5])] = &[
|
||||
"“{name}”的图层选项…",
|
||||
],
|
||||
),
|
||||
(
|
||||
"Duplicate Layer \"{name}\"",
|
||||
["Ebene „{name}“ duplizieren", "Dupliquer le calque « {name} »", "Duplicar capa «{name}»", "レイヤー「{name}」を複製", "复制图层“{name}”"],
|
||||
),
|
||||
("Swatch Name:", ["Farbfeldname:", "Nom de la nuance :", "Nombre de muestra:", "スウォッチ名:", "色板名称:"]),
|
||||
(
|
||||
"Name with Color Value",
|
||||
@@ -4968,6 +4972,20 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn duplicate_layer_menu_item_is_localized_in_every_interface_language() {
|
||||
let key = "Duplicate Layer \"{name}\"";
|
||||
for (code, name) in LANGUAGES {
|
||||
let label = tr(code, key);
|
||||
if code.is_empty() {
|
||||
assert_eq!(label, key, "{name}");
|
||||
} else {
|
||||
assert_ne!(label, key, "{name} shows the Layers panel's Duplicate Layer item in English");
|
||||
assert!(label.contains("{name}"), "{name}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn context_captions_come_from_their_context_or_the_plain_translation() {
|
||||
for (lang, table) in CONTEXT_TABLES {
|
||||
|
||||
@@ -1813,6 +1813,7 @@ pub(super) const TABLE: &[(&str, &str)] = &[
|
||||
("Color Group Options…", "خيارات مجموعة الألوان…"),
|
||||
("Layer Options", "خيارات الطبقة"),
|
||||
("Layer Options for \"{name}\"…", "خيارات الطبقة \"{name}\"…"),
|
||||
("Duplicate Layer \"{name}\"", "تكرار الطبقة \"{name}\""),
|
||||
("Swatch Name:", "اسم حامل اللون:"),
|
||||
("Name with Color Value", "التسمية بقيمة اللون"),
|
||||
("Color Type:", "نوع اللون:"),
|
||||
|
||||
@@ -210,6 +210,7 @@ pub(super) const TABLE: &[(&str, &str)] = &[
|
||||
("Delete Column", "Odstranit sloupec"),
|
||||
("Delete Condition", "Odstranit podmínku"),
|
||||
("Delete Layer", "Odstranit vrstvu"),
|
||||
("Duplicate Layer \"{name}\"", "Duplikovat vrstvu „{name}“"),
|
||||
("Delete Page", "Odstranit stránku"),
|
||||
("Delete Row", "Odstranit řádek"),
|
||||
("Delete Swatch", "Odstranit vzorek"),
|
||||
|
||||
@@ -2040,6 +2040,7 @@ pub(super) const TABLE: &[(&str, &str)] = &[
|
||||
("Color Group Options…", "Farbgruppenoptionen …"),
|
||||
("Layer Options", "Ebenenoptionen"),
|
||||
("Layer Options for \"{name}\"…", "Ebenenoptionen für „{name}“ …"),
|
||||
("Duplicate Layer \"{name}\"", "Ebene „{name}“ duplizieren"),
|
||||
("Swatch Name:", "Farbfeldname:"),
|
||||
("Name with Color Value", "Name mit Farbwert"),
|
||||
("Color Type:", "Farbtyp:"),
|
||||
|
||||
@@ -1865,6 +1865,7 @@ pub(super) const TABLE: &[(&str, &str)] = &[
|
||||
("Color Group Options…", "Opzioni gruppo colori…"),
|
||||
("Layer Options", "Opzioni livello"),
|
||||
("Layer Options for \"{name}\"…", "Opzioni livello \"{name}\"…"),
|
||||
("Duplicate Layer \"{name}\"", "Duplica livello \"{name}\""),
|
||||
("Swatch Name:", "Nome campione:"),
|
||||
("Name with Color Value", "Nome con valore colore"),
|
||||
("Color Type:", "Tipo colore:"),
|
||||
|
||||
@@ -2123,6 +2123,7 @@ pub(super) const TABLE: &[(&str, &str)] = &[
|
||||
("Color Group Options…", "カラーグループオプション…"),
|
||||
("Layer Options", "レイヤーオプション"),
|
||||
("Layer Options for \"{name}\"…", "「{name}」のレイヤーオプション…"),
|
||||
("Duplicate Layer \"{name}\"", "レイヤー「{name}」を複製"),
|
||||
("Swatch Name:", "スウォッチ名:"),
|
||||
("Name with Color Value", "カラー値を名前にする"),
|
||||
("Color Type:", "カラータイプ:"),
|
||||
|
||||
@@ -2155,6 +2155,7 @@ pub(super) const TABLE: &[(&str, &str)] = &[
|
||||
("Last commit", "ბოლო კომიტი"),
|
||||
("Layer Options", "შრის პარამეტრები"),
|
||||
("Layer Options for \"{name}\"…", "შრის პარამეტრები: „{name}“…"),
|
||||
("Duplicate Layer \"{name}\"", "შრის დუბლირება: „{name}“"),
|
||||
("Leader:", "მიმთითებელი:"),
|
||||
("Leading Model:", "სტრიქონთაშორისი ინტერვალის მოდელი:"),
|
||||
("Left-aligned tab", "მარცხნივ სწორებული ტაბულაცია"),
|
||||
|
||||
@@ -211,6 +211,7 @@ pub(super) const TABLE: &[(&str, &str)] = &[
|
||||
("Delete Column", "Usuń kolumnę"),
|
||||
("Delete Condition", "Usuń warunek"),
|
||||
("Delete Layer", "Usuń warstwę"),
|
||||
("Duplicate Layer \"{name}\"", "Powiel warstwę „{name}”"),
|
||||
("Delete Page", "Usuń stronę"),
|
||||
("Delete Row", "Usuń wiersz"),
|
||||
("Delete Swatch", "Usuń próbkę"),
|
||||
|
||||
@@ -1417,6 +1417,7 @@ pub(super) const TABLE: &[(&str, &str)] = &[
|
||||
("Color Group Options…", "Opções do grupo de cores…"),
|
||||
("Layer Options", "Opções de camada"),
|
||||
("Layer Options for \"{name}\"…", "Opções da camada \"{name}\"…"),
|
||||
("Duplicate Layer \"{name}\"", "Duplicar camada \"{name}\""),
|
||||
("Swatch Name:", "Nome da amostra:"),
|
||||
("Name with Color Value", "Nome com valor da cor"),
|
||||
("Color Type:", "Tipo de cor:"),
|
||||
|
||||
@@ -210,6 +210,7 @@ pub(super) const TABLE: &[(&str, &str)] = &[
|
||||
("Delete Column", "Удалить столбец"),
|
||||
("Delete Condition", "Удалить условие"),
|
||||
("Delete Layer", "Удалить слой"),
|
||||
("Duplicate Layer \"{name}\"", "Дублировать слой «{name}»"),
|
||||
("Delete Page", "Удалить страницу"),
|
||||
("Delete Row", "Удалить строку"),
|
||||
("Delete Swatch", "Удалить образец"),
|
||||
|
||||
@@ -1833,6 +1833,7 @@ pub(super) const TABLE: &[(&str, &str)] = &[
|
||||
("Color Group Options…", "Параметри групи кольорів…"),
|
||||
("Layer Options", "Параметри шару"),
|
||||
("Layer Options for \"{name}\"…", "Параметри шару «{name}»…"),
|
||||
("Duplicate Layer \"{name}\"", "Дублювати шар «{name}»"),
|
||||
("Swatch Name:", "Назва зразка:"),
|
||||
("Name with Color Value", "Назва за значенням кольору"),
|
||||
("Color Type:", "Тип кольору:"),
|
||||
|
||||
Reference in new issue
Block a user