diff --git a/ROADMAP.md b/ROADMAP.md index 188e55c1a..c0d64038e 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -465,6 +465,7 @@ Newest first. - **2026-10-20** · Properties › Appearance: the corner shape list shows each shape's glyph beside its name, drawn as InDesign draws them (Fancy has its own glyph now), and the stroke type list shows each type's line; both dropdowns are named for screen readers. No readiness percentage change. - **2026-10-21** · Properties › Align: the Align To button shows what the objects align to, one glyph each for the selection, the key object, the margins, the page and the spread, as InDesign's. Found in the Learn Skills Daily course, chapter 12. No readiness percentage change. - **2026-10-20** · Object › Corner Options opens a Corner Options dialog laid out as InDesign's: each corner's size and shape, the link button that makes all four the same, and Preview. The Corner link in Properties › Appearance opens it too (it opened a Rectangle size dialog). No readiness percentage change. +- **2026-10-20** · The Object menu is in InDesign's order and groups; Paths has Join, Open Path and Close Path (Convert Shape lists only shapes, as InDesign's does) and a Convert Point submenu (Plain, Corner, Smooth, Symmetrical) is added. No readiness percentage change. - **2026-10-21** · Properties › Character and Paragraph: ••• (More Options) expands the section in place, as InDesign's: Character adds vertical and horizontal scale, baseline shift, skew, language and OpenType, and All Caps, Small Caps, Superscript, Subscript, Underline and Strikethrough; Paragraph adds the left, right, first line and last line indents, space before and after, the drop cap's lines and characters, Align to Baseline Grid and Hyphenate. It used to open the Character or Paragraph panel; the language field moved under ••• as in InDesign. Found in the Learn Skills Daily course, chapter 16. No readiness percentage change. - **2026-10-21** · The text Control panel has InDesign's two modes: A (Character Formatting Controls: font and style, size and leading, All Caps/Superscript/Underline and Small Caps/Subscript/Strikethrough, kerning and tracking, vertical and horizontal scale, baseline shift and skew, character style and language) and ¶ (Paragraph Formatting Controls: the nine alignments, left/first line and right/last line indents, space before and after, the drop cap's lines and characters, paragraph style, Hyphenate and Align to Baseline Grid). It used to show a fixed mix of both. Found in the Learn Skills Daily course, chapter 16. No readiness percentage change. - **2026-10-20** · With the Type tool, the Control panel's font size, leading and tracking fields have a spinner and a list of common values, as in InDesign (auto leading in parentheses). No readiness percentage change. diff --git a/crates/ui-egui/src/i18n/ar.rs b/crates/ui-egui/src/i18n/ar.rs index f3af616ed..d432229d5 100644 --- a/crates/ui-egui/src/i18n/ar.rs +++ b/crates/ui-egui/src/i18n/ar.rs @@ -34,6 +34,8 @@ pub(super) const TABLE: &[(&str, &str)] = &[ ("Stroke Type", "نوع الحد"), ("Corner Shape", "شكل الزاوية"), ("Corner Size and Shape:", "حجم الزوايا وشكلها:"), + ("Join", "وصل"), + ("Convert Point", "تحويل النقطة"), ("Restart Numbering", "إعادة الترقيم"), ("Continue Numbering", "متابعة الترقيم"), ("Keep Options…", "خيارات الإبقاء…"), @@ -1978,6 +1980,7 @@ pub(super) const TABLE: &[(&str, &str)] = &[ ("Object/Fitting", "كائن/ملاءمة"), ("Object/Pathfinder", "كائن/باحث المسارات"), ("Object/Paths", "كائن/مسارات"), + ("Object/Convert Point", "كائن/تحويل النقطة"), ("Object/Select", "كائن/تحديد"), ("Object/Transform", "كائن/تحويل"), ("Object/Transform Again", "كائن/تحويل مجدداً"), diff --git a/crates/ui-egui/src/i18n/cs.rs b/crates/ui-egui/src/i18n/cs.rs index b0c02c4ff..14fb7a715 100644 --- a/crates/ui-egui/src/i18n/cs.rs +++ b/crates/ui-egui/src/i18n/cs.rs @@ -35,6 +35,10 @@ pub(super) const TABLE: &[(&str, &str)] = &[ ("Stroke Type", "Typ tahu"), ("Corner Shape", "Tvar rohu"), ("Corner Size and Shape:", "Velikost a tvar rohů:"), + ("Join", "Spojit"), + ("Convert Point", "Převést bod"), + ("Plain", "Obyčejný"), + ("Symmetrical", "Symetrický"), ("Restart Numbering", "Začít číslování znovu"), ("Continue Numbering", "Pokračovat v číslování"), ("Keep Options…", "Volby zachování…"), @@ -1659,6 +1663,7 @@ pub(super) const TABLE: &[(&str, &str)] = &[ ("Object/Fitting", "Objekt/Přizpůsobení"), ("Object/Pathfinder", "Objekt/Operace s cestami"), ("Object/Paths", "Objekt/Cesty"), + ("Object/Convert Point", "Objekt/Převést bod"), ("Object/Select", "Objekt/Vybrat"), ("Object/Transform", "Objekt/Transformace"), ("Object/Transform Again", "Objekt/Transformovat znovu"), diff --git a/crates/ui-egui/src/i18n/de.rs b/crates/ui-egui/src/i18n/de.rs index bed271778..1fd66162e 100644 --- a/crates/ui-egui/src/i18n/de.rs +++ b/crates/ui-egui/src/i18n/de.rs @@ -34,6 +34,10 @@ pub(super) const TABLE: &[(&str, &str)] = &[ ("Stroke Type", "Konturtyp"), ("Corner Shape", "Eckenform"), ("Corner Size and Shape:", "Eckengröße und -form:"), + ("Join", "Verbinden"), + ("Convert Point", "Punkt konvertieren"), + ("Plain", "Einfach"), + ("Symmetrical", "Symmetrisch"), ("Restart Numbering", "Nummerierung neu beginnen"), ("Continue Numbering", "Nummerierung fortführen"), ("Keep Options…", "Umbruchoptionen …"), @@ -1671,6 +1675,7 @@ pub(super) const TABLE: &[(&str, &str)] = &[ ("Object/Fitting", "Objekt/Anpassen"), ("Object/Pathfinder", "Objekt/Pathfinder"), ("Object/Paths", "Objekt/Pfade"), + ("Object/Convert Point", "Objekt/Punkt konvertieren"), ("Object/Select", "Objekt/Auswählen"), ("Object/Transform", "Objekt/Transformieren"), ("Object/Transform Again", "Objekt/Erneut transformieren"), diff --git a/crates/ui-egui/src/i18n/fr.rs b/crates/ui-egui/src/i18n/fr.rs index b7123a7ae..64368b30d 100644 --- a/crates/ui-egui/src/i18n/fr.rs +++ b/crates/ui-egui/src/i18n/fr.rs @@ -60,7 +60,6 @@ pub(super) const TABLE: &[(&str, &str)] = &[ ("Content Placer Tool", "Outil Placeur de contenu"), ("Contributors", "Contributeurs"), ("Convert Direction Point Tool", "Outil Conversion de point directeur"), - ("Convert Point", "Convertir le point"), ("Convert Rows", "Convertir les lignes"), ("Copyright Symbol", "Symbole du copyright"), ("Corner Options", "Options d'arrondi"), @@ -171,7 +170,6 @@ pub(super) const TABLE: &[(&str, &str)] = &[ ("Insert Pages", "Insérer des pages"), ("Internet Standard RGB (sRGB)", "RVB standard Internet (sRGB)"), ("Invalid panel layout; restored the default dock", "Disposition des panneaux non valide ; disposition par défaut restaurée"), - ("Join", "Joindre"), ("Join the ArtCraft Discord", "Rejoindre le Discord d'ArtCraft"), ("Join the community", "Rejoindre la communauté"), ("Kerning", "Crénage"), @@ -245,6 +243,7 @@ pub(super) const TABLE: &[(&str, &str)] = &[ ("Object/Fitting", "Objet/Ajustement"), ("Object/Pathfinder", "Objet/Pathfinder"), ("Object/Paths", "Objet/Tracés"), + ("Object/Convert Point", "Objet/Convertir le point"), ("Object/Select", "Objet/Sélectionner"), ("Object/Transform", "Objet/Transformation"), ("Object/Transform Again", "Objet/Répéter la transformation"), diff --git a/crates/ui-egui/src/i18n/it.rs b/crates/ui-egui/src/i18n/it.rs index c88f92b76..59e25619f 100644 --- a/crates/ui-egui/src/i18n/it.rs +++ b/crates/ui-egui/src/i18n/it.rs @@ -32,6 +32,8 @@ pub(super) const TABLE: &[(&str, &str)] = &[ ("Stroke Type", "Tipo traccia"), ("Corner Shape", "Forma angolo"), ("Corner Size and Shape:", "Dimensione e forma angoli:"), + ("Join", "Unisci"), + ("Convert Point", "Converti punto"), ("Restart Numbering", "Riavvia numerazione"), ("Continue Numbering", "Continua numerazione"), ("Keep Options…", "Opzioni di separazione…"), diff --git a/crates/ui-egui/src/i18n/ja.rs b/crates/ui-egui/src/i18n/ja.rs index b1ac2d62d..7ff470d58 100644 --- a/crates/ui-egui/src/i18n/ja.rs +++ b/crates/ui-egui/src/i18n/ja.rs @@ -33,6 +33,8 @@ pub(super) const TABLE: &[(&str, &str)] = &[ ("Stroke Type", "線の種類"), ("Corner Shape", "角のシェイプ"), ("Corner Size and Shape:", "角のサイズとシェイプ:"), + ("Join", "連結"), + ("Convert Point", "ポイントを切り換え"), ("Restart Numbering", "番号の振り直し"), ("Continue Numbering", "番号の継続"), ("Keep Options…", "段落分離禁止オプション…"), @@ -1875,6 +1877,7 @@ pub(super) const TABLE: &[(&str, &str)] = &[ ("Object/Fitting", "オブジェクト/オブジェクトサイズの調整"), ("Object/Pathfinder", "オブジェクト/パスファインダー"), ("Object/Paths", "オブジェクト/パス"), + ("Object/Convert Point", "オブジェクト/ポイントを切り換え"), ("Object/Select", "オブジェクト/選択"), ("Object/Transform", "オブジェクト/変形"), ("Object/Transform Again", "オブジェクト/変形を再適用"), diff --git a/crates/ui-egui/src/i18n/ka.rs b/crates/ui-egui/src/i18n/ka.rs index 5b7c5d72f..a263aefd1 100644 --- a/crates/ui-egui/src/i18n/ka.rs +++ b/crates/ui-egui/src/i18n/ka.rs @@ -1706,6 +1706,7 @@ pub(super) const TABLE: &[(&str, &str)] = &[ ("Object/Fitting", "ობიექტი/ზომაზე მორგება"), ("Object/Pathfinder", "ობიექტი/ტრაექტორიების ოპერაციები"), ("Object/Paths", "ობიექტი/ტრაექტორიები"), + ("Object/Convert Point", "ობიექტი/წერტილის გარდაქმნა"), ("Object/Select", "ობიექტი/მონიშვნა"), ("Object/Transform", "ობიექტი/გარდაქმნა"), ("Object/Transform Again", "ობიექტი/გარდაქმნის გამეორება"), diff --git a/crates/ui-egui/src/i18n/pl.rs b/crates/ui-egui/src/i18n/pl.rs index 0c8dc2355..f268f2a6b 100644 --- a/crates/ui-egui/src/i18n/pl.rs +++ b/crates/ui-egui/src/i18n/pl.rs @@ -33,6 +33,10 @@ pub(super) const TABLE: &[(&str, &str)] = &[ ("Stroke Type", "Rodzaj obrysu"), ("Corner Shape", "Kształt narożnika"), ("Corner Size and Shape:", "Rozmiar i kształt narożników:"), + ("Join", "Połącz"), + ("Convert Point", "Konwertuj punkt"), + ("Plain", "Zwykły"), + ("Symmetrical", "Symetryczny"), ("Restart Numbering", "Zacznij numerowanie od nowa"), ("Continue Numbering", "Kontynuuj numerowanie"), ("Keep Options…", "Opcje utrzymywania…"), @@ -1637,6 +1641,7 @@ pub(super) const TABLE: &[(&str, &str)] = &[ ("Object/Fitting", "Obiekt/Dopasowanie"), ("Object/Pathfinder", "Obiekt/Kształtowanie ścieżek"), ("Object/Paths", "Obiekt/Ścieżki"), + ("Object/Convert Point", "Obiekt/Konwertuj punkt"), ("Object/Select", "Obiekt/Zaznacz"), ("Object/Transform", "Obiekt/Przekształć"), ("Object/Transform Again", "Obiekt/Przekształć ponownie"), diff --git a/crates/ui-egui/src/i18n/pt_br.rs b/crates/ui-egui/src/i18n/pt_br.rs index f9a20c1ac..fa16fd8f7 100644 --- a/crates/ui-egui/src/i18n/pt_br.rs +++ b/crates/ui-egui/src/i18n/pt_br.rs @@ -35,6 +35,8 @@ pub(super) const TABLE: &[(&str, &str)] = &[ ("Stroke Type", "Tipo de traçado"), ("Corner Shape", "Forma do canto"), ("Corner Size and Shape:", "Tamanho e forma dos cantos:"), + ("Join", "Unir"), + ("Convert Point", "Converter ponto"), ("Restart Numbering", "Reiniciar numeração"), ("Continue Numbering", "Continuar numeração"), ("Keep Options…", "Opções de manutenção…"), diff --git a/crates/ui-egui/src/i18n/ru.rs b/crates/ui-egui/src/i18n/ru.rs index a013b87d9..6df9961f0 100644 --- a/crates/ui-egui/src/i18n/ru.rs +++ b/crates/ui-egui/src/i18n/ru.rs @@ -37,6 +37,10 @@ pub(super) const TABLE: &[(&str, &str)] = &[ ("Stroke Type", "Тип обводки"), ("Corner Shape", "Форма угла"), ("Corner Size and Shape:", "Размер и форма углов:"), + ("Join", "Соединить"), + ("Convert Point", "Преобразовать точку"), + ("Plain", "Простая"), + ("Symmetrical", "Симметричная"), ("Restart Numbering", "Начать нумерацию заново"), ("Continue Numbering", "Продолжить нумерацию"), ("Keep Options…", "Параметры удержания…"), @@ -1641,6 +1645,7 @@ pub(super) const TABLE: &[(&str, &str)] = &[ ("Object/Fitting", "Объект/Подгонка"), ("Object/Pathfinder", "Объект/Обработка контуров"), ("Object/Paths", "Объект/Контуры"), + ("Object/Convert Point", "Объект/Преобразовать точку"), ("Object/Select", "Объект/Выбрать"), ("Object/Transform", "Объект/Трансформирование"), ("Object/Transform Again", "Объект/Повторить трансформирование"), diff --git a/crates/ui-egui/src/i18n/table.rs b/crates/ui-egui/src/i18n/table.rs index 148fdd599..e428f3081 100644 --- a/crates/ui-egui/src/i18n/table.rs +++ b/crates/ui-egui/src/i18n/table.rs @@ -127,6 +127,8 @@ pub(super) const TABLE: &[(&str, [&str; 5])] = &[ "Corner Size and Shape:", ["Eckengröße und -form:", "Taille et forme des angles:", "Tamaño y forma de esquinas:", "角のサイズとシェイプ:", "角大小和形状:"], ), + ("Join", ["Join", "Joindre", "Unir", "Join", "连接"]), + ("Convert Point", ["Convert Point", "Convertir le point", "Convertir punto", "Convert Point", "转换点"]), ("Hide Rulers", ["Lineale ausblenden", "Masquer les règles", "Ocultar reglas", "定規を隠す", "隐藏标尺"]), ("Inches Decimal", ["Zoll dezimal", "Pouces décimaux", "Pulgadas decimales", "インチ(10 進)", "十进制英寸"]), ( diff --git a/crates/ui-egui/src/i18n/uk.rs b/crates/ui-egui/src/i18n/uk.rs index 686139909..85a1654df 100644 --- a/crates/ui-egui/src/i18n/uk.rs +++ b/crates/ui-egui/src/i18n/uk.rs @@ -33,6 +33,8 @@ pub(super) const TABLE: &[(&str, &str)] = &[ ("Stroke Type", "Тип обведення"), ("Corner Shape", "Форма кута"), ("Corner Size and Shape:", "Розмір і форма кутів:"), + ("Join", "Зʼєднати"), + ("Convert Point", "Перетворити точку"), ("Restart Numbering", "Почати нумерацію знову"), ("Continue Numbering", "Продовжити нумерацію"), ("Keep Options…", "Параметри утримання…"), diff --git a/crates/ui-egui/src/menus/tables.rs b/crates/ui-egui/src/menus/tables.rs index 4d63d485f..97ae2fd5a 100644 --- a/crates/ui-egui/src/menus/tables.rs +++ b/crates/ui-egui/src/menus/tables.rs @@ -299,57 +299,12 @@ pub const MENUS: &[(&str, &[&str])] = &[ "cmd:transform.again|Transform Sequence Again|{\"sequence\": true}", "cmd:transform.again|Transform Sequence Again Individually|{\"sequence\": true, \"individually\": true}", "<", - ">Flex Layout", - "cmd:flex.add", - "cmd:flex.convert", - "cmd:flex.remove", - "-", - "ui:window.panel|Show Flex Controls|{\"panel\": \"flexLayout\"}", - "<", - ">Paths", - "cmd:object.makeCompoundPath", - "cmd:object.releaseCompoundPath", - "-", - "cmd:path.reverse", - "<", - ">Pathfinder", - "cmd:object.pathfinder|Add|{\"op\": \"add\"}", - "cmd:object.pathfinder|Subtract|{\"op\": \"subtract\"}", - "cmd:object.pathfinder|Intersect|{\"op\": \"intersect\"}", - "cmd:object.pathfinder|Exclude Overlap|{\"op\": \"exclude\"}", - "cmd:object.pathfinder|Minus Back|{\"op\": \"minusBack\"}", - "<", ">Arrange", "cmd:object.bringToFront", "cmd:object.bringForward", "cmd:object.sendBackward", "cmd:object.sendToBack", "<", - "-", - "cmd:object.group", - "cmd:object.ungroup", - "cmd:object.lock", - "cmd:object.unlockAll", - "cmd:object.hide", - "cmd:object.showAll", - "-", - "cmd:object.textFrameOptions", - "ui:app.layerOptions", - "cmd:object.exportOptions", - "cmd:object.primaryTextFrame", - "cmd:object.cornerOptions", - "-", - ">Effects", - "ui:effects.dialog|Transparency…|{\"page\": \"transparency\"}", - "cmd:object.dropShadow", - "cmd:object.innerShadow", - "cmd:object.outerGlow", - "cmd:object.innerGlow", - "cmd:object.bevel", - "cmd:object.satin", - "cmd:object.feather", - "cmd:object.directionalFeather", - "<", ">Select", "cmd:select.firstAbove", "cmd:select.nextAbove", @@ -362,34 +317,23 @@ pub const MENUS: &[(&str, &[&str])] = &[ "cmd:select.previousInGroup", "cmd:select.nextInGroup", "<", - ">Convert Shape", - "cmd:object.convertShape|Rectangle|{\"to\": \"rectangle\"}", - "cmd:object.convertShape|Rounded Rectangle|{\"to\": \"roundedRectangle\"}", - "cmd:object.convertShape|Beveled Rectangle|{\"to\": \"beveledRectangle\"}", - "cmd:object.convertShape|Inverse Rounded Rectangle|{\"to\": \"inverseRoundedRectangle\"}", - "cmd:object.convertShape|Ellipse|{\"to\": \"ellipse\"}", - "cmd:object.convertShape|Triangle|{\"to\": \"triangle\"}", - "cmd:object.convertShape|Polygon|{\"to\": \"polygon\"}", - "cmd:object.convertShape|Line|{\"to\": \"line\"}", - "cmd:object.convertShape|Orthogonal Line|{\"to\": \"orthogonalLine\"}", "-", - "cmd:object.convertShape|Open Path|{\"to\": \"openPath\"}", - "cmd:object.convertShape|Closed Path|{\"to\": \"closedPath\"}", - "<", + "cmd:object.group", + "cmd:object.ungroup", + "cmd:object.lock", + "cmd:object.unlockAll", + "cmd:object.hide", + "cmd:object.showAll", + "-", "ui:app.qrCode", - ">Clipping Path", - "cmd:object.clippingPathOptions|None|{\"type\": \"none\"}", - "cmd:object.clippingPath|Alpha Channel|{\"type\": \"alpha\"}", - "cmd:object.clippingPath|Detect Edges|{\"type\": \"edges\"}", - "<", - ">Captions", - "cmd:object.caption", - "cmd:object.caption|Generate Live Caption|{\"live\": true}", - "<", + "-", + "cmd:object.textFrameOptions", + "cmd:object.primaryTextFrame", ">Anchored Object", "cmd:anchored.options", "cmd:anchored.release", "<", + "-", ">Fitting", "ui:fit.fillFrameProportionally", "ui:fit.contentProportionally", @@ -404,6 +348,73 @@ pub const MENUS: &[(&str, &[&str])] = &[ "cmd:object.content|Text|{\"type\":\"text\"}", "cmd:object.content|Unassigned|{\"type\":\"unassigned\"}", "<", + "-", + ">Effects", + "ui:effects.dialog|Transparency…|{\"page\": \"transparency\"}", + "cmd:object.dropShadow", + "cmd:object.innerShadow", + "cmd:object.outerGlow", + "cmd:object.innerGlow", + "cmd:object.bevel", + "cmd:object.satin", + "cmd:object.feather", + "cmd:object.directionalFeather", + "<", + "cmd:object.cornerOptions", + "-", + "ui:app.layerOptions", + "cmd:object.exportOptions", + ">Captions", + "cmd:object.caption", + "cmd:object.caption|Generate Live Caption|{\"live\": true}", + "<", + ">Clipping Path", + "cmd:object.clippingPathOptions|None|{\"type\": \"none\"}", + "cmd:object.clippingPath|Alpha Channel|{\"type\": \"alpha\"}", + "cmd:object.clippingPath|Detect Edges|{\"type\": \"edges\"}", + "<", + "-", + ">Flex Layout", + "cmd:flex.add", + "cmd:flex.convert", + "cmd:flex.remove", + "-", + "ui:window.panel|Show Flex Controls|{\"panel\": \"flexLayout\"}", + "<", + "-", + ">Paths", + "cmd:path.join", + "cmd:object.convertShape|Open Path|{\"to\": \"openPath\"}", + "cmd:object.convertShape|Close Path|{\"to\": \"closedPath\"}", + "cmd:path.reverse", + "-", + "cmd:object.makeCompoundPath", + "cmd:object.releaseCompoundPath", + "<", + ">Pathfinder", + "cmd:object.pathfinder|Add|{\"op\": \"add\"}", + "cmd:object.pathfinder|Subtract|{\"op\": \"subtract\"}", + "cmd:object.pathfinder|Intersect|{\"op\": \"intersect\"}", + "cmd:object.pathfinder|Exclude Overlap|{\"op\": \"exclude\"}", + "cmd:object.pathfinder|Minus Back|{\"op\": \"minusBack\"}", + "<", + ">Convert Shape", + "cmd:object.convertShape|Rectangle|{\"to\": \"rectangle\"}", + "cmd:object.convertShape|Rounded Rectangle|{\"to\": \"roundedRectangle\"}", + "cmd:object.convertShape|Beveled Rectangle|{\"to\": \"beveledRectangle\"}", + "cmd:object.convertShape|Inverse Rounded Rectangle|{\"to\": \"inverseRoundedRectangle\"}", + "cmd:object.convertShape|Ellipse|{\"to\": \"ellipse\"}", + "cmd:object.convertShape|Triangle|{\"to\": \"triangle\"}", + "cmd:object.convertShape|Polygon|{\"to\": \"polygon\"}", + "cmd:object.convertShape|Line|{\"to\": \"line\"}", + "cmd:object.convertShape|Orthogonal Line|{\"to\": \"orthogonalLine\"}", + "<", + ">Convert Point", + "cmd:path.convertPoints|Plain|{\"kind\": \"plain\"}", + "cmd:path.convertPoints|Corner|{\"kind\": \"corner\"}", + "cmd:path.convertPoints|Smooth|{\"kind\": \"smooth\"}", + "cmd:path.convertPoints|Symmetrical|{\"kind\": \"symmetrical\"}", + "<", ], ), ( diff --git a/crates/ui-egui/src/menus/tests.rs b/crates/ui-egui/src/menus/tests.rs index 5e82f6d3f..5f7f5b93d 100644 --- a/crates/ui-egui/src/menus/tests.rs +++ b/crates/ui-egui/src/menus/tests.rs @@ -6,6 +6,81 @@ fn menu_ids(title: &str) -> Vec<&'static str> { items.iter().filter_map(|e| e.split_once(':').map(|(_, rest)| rest.split('|').next().unwrap_or(rest))).collect() } +/// The Object menu's top level in InDesign's order and groups (as InDesign 2023 shows it in +/// Learn Skills Daily's course), with Paths holding Join, Open and Close Path, Convert Shape +/// only shapes, and a Convert Point submenu. +#[test] +fn the_object_menu_is_in_indesigns_order() { + let items = MENUS.iter().find(|(t, _)| *t == "Object").map(|(_, items)| *items).unwrap(); + // The top-level entries: submenus by name, separators as "-", items by command id. + let mut top = Vec::new(); + let mut depth = 0; + for e in items { + match *e { + "<" => depth -= 1, + e if e.starts_with('>') => { + if depth == 0 { + top.push(e.trim_start_matches('>')); + } + depth += 1; + } + e if depth == 0 => top.push(e.split_once(':').map_or(e, |(_, r)| r.split('|').next().unwrap_or(r))), + _ => {} + } + } + assert_eq!( + top, + [ + "Transform", + "Transform Again", + "Arrange", + "Select", + "-", + "object.group", + "object.ungroup", + "object.lock", + "object.unlockAll", + "object.hide", + "object.showAll", + "-", + "app.qrCode", + "-", + "object.textFrameOptions", + "object.primaryTextFrame", + "Anchored Object", + "-", + "Fitting", + "Content", + "-", + "Effects", + "object.cornerOptions", + "-", + "app.layerOptions", + "object.exportOptions", + "Captions", + "Clipping Path", + "-", + "Flex Layout", + "-", + "Paths", + "Pathfinder", + "Convert Shape", + "Convert Point", + ] + ); + let ids = menu_ids("Object"); + for id in ["path.join", "path.reverse", "path.convertPoints"] { + assert!(ids.contains(&id), "{id}"); + } + let sub = |name: &str| { + let i = items.iter().position(|e| *e == format!(">{name}")).unwrap(); + items[i + 1..].iter().take_while(|e| **e != "<").copied().collect::>() + }; + assert!(sub("Paths").iter().any(|e| e.contains("|Open Path|")) && sub("Paths").iter().any(|e| e.contains("|Close Path|"))); + assert!(!sub("Convert Shape").iter().any(|e| e.contains("openPath") || e.contains("closedPath")), "shapes only"); + assert_eq!(sub("Convert Point").len(), 4); +} + #[test] fn view_items_are_in_the_view_menu_as_in_indesign() { let (view, typ) = (menu_ids("View"), menu_ids("Type"));