From af36dc399de32adc3c60c9a24f8c900c6f58bf28 Mon Sep 17 00:00:00 2001 From: moppeeer Date: Wed, 21 Oct 2026 02:38:12 +0200 Subject: [PATCH 1/5] Fitting: Clear Frame Fitting Options; the submenu grouped as InDesign's object.clearFittingOptions puts the frames' auto-fit, crop amounts and reference point back to their defaults and leaves the picture where it is. Object > Fitting (and the context menu) groups the proportional fits, the frame and content fits, Clear Frame Fitting Options and the dialog. Co-Authored-By: Claude Opus 5.5 --- ROADMAP.md | 1 + crates/engine/src/cmd/object.rs | 50 ++++++++++++++++++++++++++++++++ crates/ui-egui/src/i18n.rs | 10 +++++++ crates/ui-egui/src/i18n/ar.rs | 1 + crates/ui-egui/src/i18n/cs.rs | 1 + crates/ui-egui/src/i18n/de.rs | 1 + crates/ui-egui/src/i18n/it.rs | 1 + crates/ui-egui/src/i18n/ja.rs | 1 + crates/ui-egui/src/i18n/ka.rs | 1 + crates/ui-egui/src/i18n/pl.rs | 1 + crates/ui-egui/src/i18n/pt_br.rs | 1 + crates/ui-egui/src/i18n/ru.rs | 1 + crates/ui-egui/src/i18n/uk.rs | 1 + crates/ui-egui/src/menus.rs | 28 ++++++++++++++++++ 14 files changed, 99 insertions(+) diff --git a/ROADMAP.md b/ROADMAP.md index 0128924c0..7e0ff1b56 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -348,6 +348,7 @@ list) · [roadmap.md](docs/roadmap.md) (milestones, plan) · [parity-checklist.m Newest first. +- **2026-10-21** · Object › Fitting › Clear Frame Fitting Options (`object.clearFittingOptions`): the frames' auto-fit, crop amounts and reference point go back to their defaults, and the picture stays where it is. The Fitting submenu is grouped as InDesign's. Found in the Learn Skills Daily course, chapter 11. No readiness percentage change. - **2026-10-16** · Type › Reload Fonts (`font.reload`): fonts installed, edited or removed while DesignCraft runs are read again without a restart, and the open documents recompose with them (#328, #547). An edited font file is noticed by its length and modification time; bundled, added and document fonts stay as they are. InDesign does this by itself, so noticing changes automatically is still open (gap 6). No readiness percentage change. - **2026-10-16** · Parents can be deleted from their Pages-panel context menu or `layout.parents.delete {id}`. Applied-page and based-on references are cleared, local override copies survive, and Undo restores the parent. Addresses the deletion portion of #956; no readiness percentage change. - **2026-10-17** · File › Package writes the document's and the IDML's links relative to the package (`Links/logo.png`, `file:Links/logo.png`), so a package holds no path from the machine that made it; opening a document resolves them to the files beside it. Links › Copy Link(s) To still links by full path. (#340). No readiness percentage change. diff --git a/crates/engine/src/cmd/object.rs b/crates/engine/src/cmd/object.rs index 82f33a6d8..f709b6dec 100644 --- a/crates/engine/src/cmd/object.rs +++ b/crates/engine/src/cmd/object.rs @@ -638,6 +638,15 @@ pub fn specs() -> Vec { has_selection, fitting_options ), + cmd!( + "object.clearFittingOptions", + "Clear Frame Fitting Options", + ["Object", "Fitting"], + None, + "{ids?} — the frames' fitting options back to the defaults: no auto-fit, no crop amounts, the centre reference point; the content stays where it is", + has_selection, + clear_fitting_options + ), cmd!("object.rename", "Rename", [], None, "{id | ids?, name}", has_doc, |s, p| { let name = str_param(p, "name").unwrap_or("").to_string(); set_flag(s, p, move |i| i.name = name.clone(), false) @@ -2884,6 +2893,24 @@ fn fitting_options(s: &mut Session, p: &Value) -> Result { }) } +/// Clear Frame Fitting Options: auto-fit off, no crop, the centre reference point. The content +/// stays where it is, as in InDesign. +fn clear_fitting_options(s: &mut Session, p: &Value) -> Result { + let ids = targets(s, p)?; + s.edit(|d, _| { + let mut n = 0; + for id in &ids { + let Some(it) = d.item_mut(*id) else { continue }; + let Content::Graphic(g) = &mut it.content else { continue }; + g.auto_fit = designcraft_doc::Fitting::None; + g.crop = [0.0; 4]; + g.fit_align = 4; + n += 1; + } + Ok(json!({"changed": n})) + }) +} + fn fit(s: &mut Session, p: &Value) -> Result { let doc = &s.doc()?.doc; let ids: Vec<_> = @@ -4264,6 +4291,29 @@ mod fitting_tests { let g = back.spreads.iter().flat_map(|sp| sp.items.iter()).find_map(|i| i.graphic().cloned()).unwrap(); assert_eq!(g.auto_fit, designcraft_doc::Fitting::FillProportionally); } + + /// Clear Frame Fitting Options puts auto-fit, crop and the reference point back to their + /// defaults and leaves the picture where it is. + #[test] + fn clear_fitting_options_resets_the_frames_options_and_keeps_the_picture() { + let mut s = Session::new(); + s.execute("file.new", &json!({})).unwrap(); + let f = s.execute("frame.create", &json!({"rect": [72, 72, 272, 172]})).unwrap()["id"].as_u64().unwrap(); + let png = designcraft_render::Rendered { width: 40, height: 20, pixels: vec![200; 40 * 20 * 4] }.to_png(); + s.execute("file.place", &json!({"base64": crate::cmd::base64_encode(&png), "name": "p.png", "frame": f})).unwrap(); + s.execute("object.fittingOptions", &json!({"ids": [f], "autoFit": true, "fitting": "fitProportionally", "crop": 10, "align": 0})).unwrap(); + let graphic = |s: &Session| s.doc().unwrap().doc.item(designcraft_doc::ItemId(f)).unwrap().graphic().unwrap().clone(); + let before = graphic(&s); + assert_ne!(before.auto_fit, designcraft_doc::Fitting::None); + s.execute("object.clearFittingOptions", &json!({"ids": [f]})).unwrap(); + let g = graphic(&s); + assert_eq!(g.auto_fit, designcraft_doc::Fitting::None); + assert_eq!(g.crop, [0.0; 4]); + assert_eq!(g.fit_align, 4, "the centre reference point"); + assert_eq!(g.xf, before.xf, "the picture stays where it is"); + s.execute("edit.undo", &json!({})).unwrap(); + assert_eq!(graphic(&s).crop, [10.0; 4], "one undo step"); + } } #[cfg(test)] diff --git a/crates/ui-egui/src/i18n.rs b/crates/ui-egui/src/i18n.rs index efe089ef9..46ac7b73d 100644 --- a/crates/ui-egui/src/i18n.rs +++ b/crates/ui-egui/src/i18n.rs @@ -36,6 +36,16 @@ pub const LANGUAGES: &[(&str, &str)] = &[ /// English → [German, French, Spanish, Japanese, Simplified Chinese]. const TABLE: &[(&str, [&str; 5])] = &[ + ( + "Clear Frame Fitting Options", + [ + "Rahmeneinpassungsoptionen löschen", + "Effacer les options d’ajustement du bloc", + "Borrar opciones de encaje de marco", + "フレーム調整オプションを消去", + "清除框架适合选项", + ], + ), // Menus. ("File", ["Datei", "Fichier", "Archivo", "ファイル", "文件"]), ("Edit", ["Bearbeiten", "Édition", "Edición", "編集", "编辑"]), diff --git a/crates/ui-egui/src/i18n/ar.rs b/crates/ui-egui/src/i18n/ar.rs index b050de38b..41295ee7e 100644 --- a/crates/ui-egui/src/i18n/ar.rs +++ b/crates/ui-egui/src/i18n/ar.rs @@ -30,6 +30,7 @@ pub(super) const TABLE: &[(&str, &str)] = &[ ("Cut", "قص"), ("Copy", "نسخ"), ("Paste", "لصق"), + ("Clear Frame Fitting Options", "مسح خيارات ملاءمة الإطار"), ("Paste Vector Art", "لصق رسم متجه"), ("Baseline Options", "خيارات خط الأساس"), ("Fixed Number", "عدد ثابت"), diff --git a/crates/ui-egui/src/i18n/cs.rs b/crates/ui-egui/src/i18n/cs.rs index e77e72a1c..bc39aea28 100644 --- a/crates/ui-egui/src/i18n/cs.rs +++ b/crates/ui-egui/src/i18n/cs.rs @@ -31,6 +31,7 @@ pub(super) const TABLE: &[(&str, &str)] = &[ ("Cut", "Vyjmout"), ("Copy", "Kopírovat"), ("Paste", "Vložit"), + ("Clear Frame Fitting Options", "Vymazat volby přizpůsobení rámečku"), ("Reverse Path", "Obrátit cestu"), ("Set Anchor", "Nastavit kotvu"), ("Clear", "Vymazat"), diff --git a/crates/ui-egui/src/i18n/de.rs b/crates/ui-egui/src/i18n/de.rs index efc128858..626918117 100644 --- a/crates/ui-egui/src/i18n/de.rs +++ b/crates/ui-egui/src/i18n/de.rs @@ -31,6 +31,7 @@ pub(super) const TABLE: &[(&str, &str)] = &[ ("Cut", "Ausschneiden"), ("Copy", "Kopieren"), ("Paste", "Einfügen"), + ("Clear Frame Fitting Options", "Rahmeneinpassungsoptionen löschen"), ("Inches Decimal", "Zoll dezimal"), ("Back", "Zurück"), ("Warning", "Warnung"), diff --git a/crates/ui-egui/src/i18n/it.rs b/crates/ui-egui/src/i18n/it.rs index a918a9829..cf860b35c 100644 --- a/crates/ui-egui/src/i18n/it.rs +++ b/crates/ui-egui/src/i18n/it.rs @@ -28,6 +28,7 @@ pub(super) const TABLE: &[(&str, &str)] = &[ ("Cut", "Taglia"), ("Copy", "Copia"), ("Paste", "Incolla"), + ("Clear Frame Fitting Options", "Cancella opzioni di adattamento cornice"), ("Paste Vector Art", "Incolla grafica vettoriale"), ("Baseline Options", "Opzioni linea di base"), ("Fixed Number", "Numero fisso"), diff --git a/crates/ui-egui/src/i18n/ja.rs b/crates/ui-egui/src/i18n/ja.rs index 5647ca940..b39c78ca0 100644 --- a/crates/ui-egui/src/i18n/ja.rs +++ b/crates/ui-egui/src/i18n/ja.rs @@ -30,6 +30,7 @@ pub(super) const TABLE: &[(&str, &str)] = &[ ("Cut", "カット"), ("Copy", "コピー"), ("Paste", "ペースト"), + ("Clear Frame Fitting Options", "フレーム調整オプションを消去"), ("Paste Vector Art", "ベクトルアートをペースト"), ("Baseline Options", "ベースラインオプション"), ("Column Rules", "段落境界線"), diff --git a/crates/ui-egui/src/i18n/ka.rs b/crates/ui-egui/src/i18n/ka.rs index d938c2dc7..6ba9ed276 100644 --- a/crates/ui-egui/src/i18n/ka.rs +++ b/crates/ui-egui/src/i18n/ka.rs @@ -31,6 +31,7 @@ pub(super) const TABLE: &[(&str, &str)] = &[ ("Cut", "ამოჭრა"), ("Copy", "კოპირება"), ("Paste", "ჩასმა"), + ("Clear Frame Fitting Options", "ჩარჩოს მორგების პარამეტრების გასუფთავება"), ("Inches Decimal", "ინჩები (ათობითი)"), ("Back", "უკან"), ("Warning", "გაფრთხილება"), diff --git a/crates/ui-egui/src/i18n/pl.rs b/crates/ui-egui/src/i18n/pl.rs index 68d685d99..99b6de911 100644 --- a/crates/ui-egui/src/i18n/pl.rs +++ b/crates/ui-egui/src/i18n/pl.rs @@ -29,6 +29,7 @@ pub(super) const TABLE: &[(&str, &str)] = &[ ("Cut", "Wytnij"), ("Copy", "Kopiuj"), ("Paste", "Wklej"), + ("Clear Frame Fitting Options", "Wyczyść opcje dopasowania ramki"), ("Clear", "Wyczyść"), ("Duplicate", "Powiel"), ("Select All", "Zaznacz wszystko"), diff --git a/crates/ui-egui/src/i18n/pt_br.rs b/crates/ui-egui/src/i18n/pt_br.rs index 8521de594..e9f7acbfa 100644 --- a/crates/ui-egui/src/i18n/pt_br.rs +++ b/crates/ui-egui/src/i18n/pt_br.rs @@ -31,6 +31,7 @@ pub(super) const TABLE: &[(&str, &str)] = &[ ("Cut", "Recortar"), ("Copy", "Copiar"), ("Paste", "Colar"), + ("Clear Frame Fitting Options", "Limpar opções de ajuste do quadro"), ("Paste Vector Art", "Colar arte vetorial"), ("Baseline Options", "Opções de linha de base"), ("Fixed Number", "Número fixo"), diff --git a/crates/ui-egui/src/i18n/ru.rs b/crates/ui-egui/src/i18n/ru.rs index 251555ca5..0e43dc91f 100644 --- a/crates/ui-egui/src/i18n/ru.rs +++ b/crates/ui-egui/src/i18n/ru.rs @@ -33,6 +33,7 @@ pub(super) const TABLE: &[(&str, &str)] = &[ ("Cut", "Вырезать"), ("Copy", "Копировать"), ("Paste", "Вставить"), + ("Clear Frame Fitting Options", "Очистить параметры подгонки фрейма"), ("Clear", "Очистить"), ("Duplicate", "Дублировать"), ("Select All", "Выделить все"), diff --git a/crates/ui-egui/src/i18n/uk.rs b/crates/ui-egui/src/i18n/uk.rs index dd4a1434d..bf5a25a93 100644 --- a/crates/ui-egui/src/i18n/uk.rs +++ b/crates/ui-egui/src/i18n/uk.rs @@ -29,6 +29,7 @@ pub(super) const TABLE: &[(&str, &str)] = &[ ("Cut", "Вирізати"), ("Copy", "Копіювати"), ("Paste", "Вставити"), + ("Clear Frame Fitting Options", "Очистити параметри припасування фрейму"), ("Paste Vector Art", "Вставити векторну графіку"), ("Baseline Options", "Параметри базової лінії"), ("Fixed Number", "Фіксована кількість"), diff --git a/crates/ui-egui/src/menus.rs b/crates/ui-egui/src/menus.rs index 79b8b2c4e..4424f4f13 100644 --- a/crates/ui-egui/src/menus.rs +++ b/crates/ui-egui/src/menus.rs @@ -688,13 +688,17 @@ pub const MENUS: &[(&str, &[&str])] = &[ "cmd:anchored.options", "cmd:anchored.release", "<", + // InDesign's groups: proportional fits, frame and content fits, clearing, the dialog. ">Fitting", "ui:fit.fillFrameProportionally", "ui:fit.contentProportionally", + "-", "ui:fit.frameToContent", "ui:fit.contentToFrame", "ui:fit.centerContent", "-", + "cmd:object.clearFittingOptions", + "-", "ui:app.fittingOptions", "<", ">Content", @@ -3276,6 +3280,30 @@ mod tests { assert_eq!(ui_label("view.togglePreview").and_then(|c| c.1), Some("W")); } + /// Object › Fitting in InDesign's groups: the proportional fits, the frame and content fits, + /// Clear Frame Fitting Options, then the dialog. + #[test] + fn the_fitting_menu_is_grouped_as_indesigns() { + let items = MENUS.iter().find(|(t, _)| *t == "Object").map(|(_, items)| *items).unwrap(); + let start = items.iter().position(|e| *e == ">Fitting").unwrap() + 1; + let end = start + items[start..].iter().position(|e| *e == "<").unwrap(); + assert_eq!( + &items[start..end], + [ + "ui:fit.fillFrameProportionally", + "ui:fit.contentProportionally", + "-", + "ui:fit.frameToContent", + "ui:fit.contentToFrame", + "ui:fit.centerContent", + "-", + "cmd:object.clearFittingOptions", + "-", + "ui:app.fittingOptions", + ] + ); + } + /// The submenu paths of a menu bar menu ("View/Screen Mode"), as Edit › Menus keys them. fn submenu_paths(title: &str) -> Vec { let items = MENUS.iter().find(|(t, _)| *t == title).map(|(_, items)| *items).unwrap_or_default(); From e811b65e82c2565682ed18042cb3b4e7239a9825 Mon Sep 17 00:00:00 2001 From: paaspaas00 <151774837+paaspaas00@users.noreply.github.com> Date: Wed, 21 Oct 2026 12:38:29 +0200 Subject: [PATCH 2/5] Clear Fitting Options skips locked frames Co-Authored-By: Claude Opus 5.5 --- crates/engine/src/cmd/object.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/crates/engine/src/cmd/object.rs b/crates/engine/src/cmd/object.rs index f709b6dec..2fa9f4117 100644 --- a/crates/engine/src/cmd/object.rs +++ b/crates/engine/src/cmd/object.rs @@ -2900,6 +2900,10 @@ fn clear_fitting_options(s: &mut Session, p: &Value) -> Result { s.edit(|d, _| { let mut n = 0; for id in &ids { + // Locked frames (or frames on a locked layer) keep their options, as with Fit. + if !d.item(*id).is_some_and(|it| unlocked(d, it)) { + continue; + } let Some(it) = d.item_mut(*id) else { continue }; let Content::Graphic(g) = &mut it.content else { continue }; g.auto_fit = designcraft_doc::Fitting::None; @@ -4313,6 +4317,10 @@ mod fitting_tests { assert_eq!(g.xf, before.xf, "the picture stays where it is"); s.execute("edit.undo", &json!({})).unwrap(); assert_eq!(graphic(&s).crop, [10.0; 4], "one undo step"); + s.execute("object.lock", &json!({"ids": [f]})).unwrap(); + let r = s.execute("object.clearFittingOptions", &json!({"ids": [f]})).unwrap(); + assert_eq!(r["changed"], 0); + assert_eq!(graphic(&s).crop, [10.0; 4], "a locked frame keeps its options"); } } From ff56cdde4ec14646a2fe81d850de2c6afde4080a Mon Sep 17 00:00:00 2001 From: paaspaas00 <151774837+paaspaas00@users.noreply.github.com> Date: Wed, 21 Oct 2026 14:22:35 +0200 Subject: [PATCH 3/5] Clear Fitting Options: no edit, and no undo step, when nothing can change Co-Authored-By: Claude Opus 5.5 --- crates/engine/src/cmd/object.rs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/crates/engine/src/cmd/object.rs b/crates/engine/src/cmd/object.rs index 2fa9f4117..09e7324b4 100644 --- a/crates/engine/src/cmd/object.rs +++ b/crates/engine/src/cmd/object.rs @@ -2896,14 +2896,19 @@ fn fitting_options(s: &mut Session, p: &Value) -> Result { /// Clear Frame Fitting Options: auto-fit off, no crop, the centre reference point. The content /// stays where it is, as in InDesign. fn clear_fitting_options(s: &mut Session, p: &Value) -> Result { - let ids = targets(s, p)?; + // Locked frames (or frames on a locked layer) keep their options, as with Fit; with nothing + // to change, no edit (and no empty undo step). + let doc = &s.doc()?.doc; + let ids: Vec = targets(s, p)? + .into_iter() + .filter(|id| doc.item(*id).is_some_and(|it| unlocked(doc, it) && matches!(it.content, Content::Graphic(_)))) + .collect(); + if ids.is_empty() { + return Ok(json!({"changed": 0})); + } s.edit(|d, _| { let mut n = 0; for id in &ids { - // Locked frames (or frames on a locked layer) keep their options, as with Fit. - if !d.item(*id).is_some_and(|it| unlocked(d, it)) { - continue; - } let Some(it) = d.item_mut(*id) else { continue }; let Content::Graphic(g) = &mut it.content else { continue }; g.auto_fit = designcraft_doc::Fitting::None; @@ -4318,9 +4323,11 @@ mod fitting_tests { s.execute("edit.undo", &json!({})).unwrap(); assert_eq!(graphic(&s).crop, [10.0; 4], "one undo step"); s.execute("object.lock", &json!({"ids": [f]})).unwrap(); + let undo = s.doc().unwrap().history.undo.len(); let r = s.execute("object.clearFittingOptions", &json!({"ids": [f]})).unwrap(); assert_eq!(r["changed"], 0); assert_eq!(graphic(&s).crop, [10.0; 4], "a locked frame keeps its options"); + assert_eq!(s.doc().unwrap().history.undo.len(), undo, "no empty undo step"); } } From a401aba8c46ce724e7cd29e14f28f2d4cc5011ea Mon Sep 17 00:00:00 2001 From: paaspaas00 <151774837+paaspaas00@users.noreply.github.com> Date: Wed, 21 Oct 2026 15:28:11 +0200 Subject: [PATCH 4/5] Clear Fitting Options leaves frames whose options are already clear Co-Authored-By: Claude Opus 5.5 --- crates/engine/src/cmd/object.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/crates/engine/src/cmd/object.rs b/crates/engine/src/cmd/object.rs index 09e7324b4..c59acc2ff 100644 --- a/crates/engine/src/cmd/object.rs +++ b/crates/engine/src/cmd/object.rs @@ -2896,12 +2896,14 @@ fn fitting_options(s: &mut Session, p: &Value) -> Result { /// Clear Frame Fitting Options: auto-fit off, no crop, the centre reference point. The content /// stays where it is, as in InDesign. fn clear_fitting_options(s: &mut Session, p: &Value) -> Result { - // Locked frames (or frames on a locked layer) keep their options, as with Fit; with nothing - // to change, no edit (and no empty undo step). + // Locked frames (or frames on a locked layer) keep their options, as with Fit; frames whose + // options are already clear are left out; with nothing to change, no edit (and no empty undo + // step). let doc = &s.doc()?.doc; + let set = |g: &designcraft_doc::Graphic| g.auto_fit != designcraft_doc::Fitting::None || g.crop != [0.0; 4] || g.fit_align != 4; let ids: Vec = targets(s, p)? .into_iter() - .filter(|id| doc.item(*id).is_some_and(|it| unlocked(doc, it) && matches!(it.content, Content::Graphic(_)))) + .filter(|id| doc.item(*id).is_some_and(|it| unlocked(doc, it) && matches!(&it.content, Content::Graphic(g) if set(g)))) .collect(); if ids.is_empty() { return Ok(json!({"changed": 0})); @@ -4320,6 +4322,9 @@ mod fitting_tests { assert_eq!(g.crop, [0.0; 4]); assert_eq!(g.fit_align, 4, "the centre reference point"); assert_eq!(g.xf, before.xf, "the picture stays where it is"); + let undo = s.doc().unwrap().history.undo.len(); + let r = s.execute("object.clearFittingOptions", &json!({"ids": [f]})).unwrap(); + assert_eq!((r["changed"].as_u64(), s.doc().unwrap().history.undo.len()), (Some(0), undo), "already clear: no change, no step"); s.execute("edit.undo", &json!({})).unwrap(); assert_eq!(graphic(&s).crop, [10.0; 4], "one undo step"); s.execute("object.lock", &json!({"ids": [f]})).unwrap(); From 299a65c89042e8f0f14fc963c3b3be4984da9827 Mon Sep 17 00:00:00 2001 From: moppeeer Date: Thu, 29 Oct 2026 13:16:00 +0100 Subject: [PATCH 5/5] rustfmt Co-Authored-By: Claude Opus 5.5 --- crates/ui-egui/src/menus/tests.rs | 46 +++++++++++++++---------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/crates/ui-egui/src/menus/tests.rs b/crates/ui-egui/src/menus/tests.rs index d65a99afc..a4d907e7a 100644 --- a/crates/ui-egui/src/menus/tests.rs +++ b/crates/ui-egui/src/menus/tests.rs @@ -29,29 +29,29 @@ fn view_items_are_in_the_view_menu_as_in_indesign() { assert_eq!(ui_label("view.togglePreview").and_then(|c| c.1), Some("W")); } - /// Object › Fitting in InDesign's groups: the proportional fits, the frame and content fits, - /// Clear Frame Fitting Options, then the dialog. - #[test] - fn the_fitting_menu_is_grouped_as_indesigns() { - let items = MENUS.iter().find(|(t, _)| *t == "Object").map(|(_, items)| *items).unwrap(); - let start = items.iter().position(|e| *e == ">Fitting").unwrap() + 1; - let end = start + items[start..].iter().position(|e| *e == "<").unwrap(); - assert_eq!( - &items[start..end], - [ - "ui:fit.fillFrameProportionally", - "ui:fit.contentProportionally", - "-", - "ui:fit.frameToContent", - "ui:fit.contentToFrame", - "ui:fit.centerContent", - "-", - "cmd:object.clearFittingOptions", - "-", - "ui:app.fittingOptions", - ] - ); - } +/// Object › Fitting in InDesign's groups: the proportional fits, the frame and content fits, +/// Clear Frame Fitting Options, then the dialog. +#[test] +fn the_fitting_menu_is_grouped_as_indesigns() { + let items = MENUS.iter().find(|(t, _)| *t == "Object").map(|(_, items)| *items).unwrap(); + let start = items.iter().position(|e| *e == ">Fitting").unwrap() + 1; + let end = start + items[start..].iter().position(|e| *e == "<").unwrap(); + assert_eq!( + &items[start..end], + [ + "ui:fit.fillFrameProportionally", + "ui:fit.contentProportionally", + "-", + "ui:fit.frameToContent", + "ui:fit.contentToFrame", + "ui:fit.centerContent", + "-", + "cmd:object.clearFittingOptions", + "-", + "ui:app.fittingOptions", + ] + ); +} /// The submenu paths of a menu bar menu ("View/Screen Mode"), as Edit › Menus keys them. fn submenu_paths(title: &str) -> Vec {