mirror of
https://github.com/storytold/designcraft.git
synced 2026-11-07 02:51:37 +00:00
Merge PR #1433: Fitting: Clear Frame Fitting Options, and the submenu grouped as the reference app's
Conflicts: crates/ui-egui/src/menus/tables.rs: kept the Fitting separator from the Object menu order (#1413); #1433's own comment line dropped crates/ui-egui/src/i18n/*.rs (ar, cs, de, it, ja, ka, pl, pt_br, ru, uk): kept both sides' keys, plus #1433's Clear Frame Fitting Options
This commit is contained in:
commit
3fa5fbbbc7
15 files changed
+118
No files matched your search
@@ -468,6 +468,7 @@ Newest first.
|
||||
- **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-14** · Numbering & Section Options opened on a page that doesn't start a section is New Section, as in InDesign: Start Section on, 1 offered, and the start numbers stay editable (typing one chooses it). No readiness percentage change.
|
||||
- **2026-10-20** · Layout › Create Guides puts its guides on both pages of the spread in view, as InDesign does; "This page" in Apply to narrows them to one page. No readiness percentage change.
|
||||
- **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-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.
|
||||
|
||||
@@ -638,6 +638,15 @@ pub fn specs() -> Vec<CommandSpec> {
|
||||
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)
|
||||
@@ -2968,6 +2977,35 @@ fn fitting_options(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
})
|
||||
}
|
||||
|
||||
/// 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<Value> {
|
||||
// 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<ItemId> = targets(s, p)?
|
||||
.into_iter()
|
||||
.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}));
|
||||
}
|
||||
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<Value> {
|
||||
let doc = &s.doc()?.doc;
|
||||
let ids: Vec<_> =
|
||||
@@ -4373,6 +4411,38 @@ 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");
|
||||
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();
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -37,6 +37,7 @@ pub(super) const TABLE: &[(&str, &str)] = &[
|
||||
("Join", "وصل"),
|
||||
("Convert Point", "تحويل النقطة"),
|
||||
("New Section", "قسم جديد"),
|
||||
("Clear Frame Fitting Options", "مسح خيارات ملاءمة الإطار"),
|
||||
("Restart Numbering", "إعادة الترقيم"),
|
||||
("Continue Numbering", "متابعة الترقيم"),
|
||||
("Keep Options…", "خيارات الإبقاء…"),
|
||||
|
||||
@@ -40,6 +40,7 @@ pub(super) const TABLE: &[(&str, &str)] = &[
|
||||
("Plain", "Obyčejný"),
|
||||
("Symmetrical", "Symetrický"),
|
||||
("New Section", "Nový oddíl"),
|
||||
("Clear Frame Fitting Options", "Vymazat volby přizpůsobení rámečku"),
|
||||
("Restart Numbering", "Začít číslování znovu"),
|
||||
("Continue Numbering", "Pokračovat v číslování"),
|
||||
("Keep Options…", "Volby zachování…"),
|
||||
|
||||
@@ -39,6 +39,7 @@ pub(super) const TABLE: &[(&str, &str)] = &[
|
||||
("Plain", "Einfach"),
|
||||
("Symmetrical", "Symmetrisch"),
|
||||
("New Section", "Neuer Abschnitt"),
|
||||
("Clear Frame Fitting Options", "Rahmeneinpassungsoptionen löschen"),
|
||||
("Restart Numbering", "Nummerierung neu beginnen"),
|
||||
("Continue Numbering", "Nummerierung fortführen"),
|
||||
("Keep Options…", "Umbruchoptionen …"),
|
||||
|
||||
@@ -35,6 +35,7 @@ pub(super) const TABLE: &[(&str, &str)] = &[
|
||||
("Join", "Unisci"),
|
||||
("Convert Point", "Converti punto"),
|
||||
("New Section", "Nuova sezione"),
|
||||
("Clear Frame Fitting Options", "Cancella opzioni di adattamento cornice"),
|
||||
("Restart Numbering", "Riavvia numerazione"),
|
||||
("Continue Numbering", "Continua numerazione"),
|
||||
("Keep Options…", "Opzioni di separazione…"),
|
||||
|
||||
@@ -36,6 +36,7 @@ pub(super) const TABLE: &[(&str, &str)] = &[
|
||||
("Join", "連結"),
|
||||
("Convert Point", "ポイントを切り換え"),
|
||||
("New Section", "新規セクション"),
|
||||
("Clear Frame Fitting Options", "フレーム調整オプションを消去"),
|
||||
("Restart Numbering", "番号の振り直し"),
|
||||
("Continue Numbering", "番号の継続"),
|
||||
("Keep Options…", "段落分離禁止オプション…"),
|
||||
|
||||
@@ -36,6 +36,7 @@ pub(super) const TABLE: &[(&str, &str)] = &[
|
||||
("Corner Shape", "კუთხის ფორმა"),
|
||||
("Corner Size and Shape:", "კუთხეების ზომა და ფორმა:"),
|
||||
("New Section", "ახალი სექცია"),
|
||||
("Clear Frame Fitting Options", "ჩარჩოს მორგების პარამეტრების გასუფთავება"),
|
||||
("Restart Numbering", "ნუმერაციის თავიდან დაწყება"),
|
||||
("Continue Numbering", "ნუმერაციის გაგრძელება"),
|
||||
("Keep Options…", "შენარჩუნების პარამეტრები…"),
|
||||
|
||||
@@ -38,6 +38,7 @@ pub(super) const TABLE: &[(&str, &str)] = &[
|
||||
("Plain", "Zwykły"),
|
||||
("Symmetrical", "Symetryczny"),
|
||||
("New Section", "Nowa sekcja"),
|
||||
("Clear Frame Fitting Options", "Wyczyść opcje dopasowania ramki"),
|
||||
("Restart Numbering", "Zacznij numerowanie od nowa"),
|
||||
("Continue Numbering", "Kontynuuj numerowanie"),
|
||||
("Keep Options…", "Opcje utrzymywania…"),
|
||||
|
||||
@@ -38,6 +38,7 @@ pub(super) const TABLE: &[(&str, &str)] = &[
|
||||
("Join", "Unir"),
|
||||
("Convert Point", "Converter ponto"),
|
||||
("New Section", "Nova seção"),
|
||||
("Clear Frame Fitting Options", "Limpar opções de ajuste do quadro"),
|
||||
("Restart Numbering", "Reiniciar numeração"),
|
||||
("Continue Numbering", "Continuar numeração"),
|
||||
("Keep Options…", "Opções de manutenção…"),
|
||||
|
||||
@@ -42,6 +42,7 @@ pub(super) const TABLE: &[(&str, &str)] = &[
|
||||
("Plain", "Простая"),
|
||||
("Symmetrical", "Симметричная"),
|
||||
("New Section", "Новый раздел"),
|
||||
("Clear Frame Fitting Options", "Очистить параметры подгонки фрейма"),
|
||||
("Restart Numbering", "Начать нумерацию заново"),
|
||||
("Continue Numbering", "Продолжить нумерацию"),
|
||||
("Keep Options…", "Параметры удержания…"),
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
/// English → [German, French, Spanish, Japanese, Simplified Chinese].
|
||||
pub(super) 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",
|
||||
"フレーム調整オプションを消去",
|
||||
"清除框架适合选项",
|
||||
],
|
||||
),
|
||||
(
|
||||
"Character Formatting Controls",
|
||||
[
|
||||
|
||||
@@ -36,6 +36,7 @@ pub(super) const TABLE: &[(&str, &str)] = &[
|
||||
("Join", "Зʼєднати"),
|
||||
("Convert Point", "Перетворити точку"),
|
||||
("New Section", "Новий розділ"),
|
||||
("Clear Frame Fitting Options", "Очистити параметри припасування фрейму"),
|
||||
("Restart Numbering", "Почати нумерацію знову"),
|
||||
("Continue Numbering", "Продовжити нумерацію"),
|
||||
("Keep Options…", "Параметри утримання…"),
|
||||
|
||||
@@ -337,10 +337,13 @@ pub const MENUS: &[(&str, &[&str])] = &[
|
||||
">Fitting",
|
||||
"ui:fit.fillFrameProportionally",
|
||||
"ui:fit.contentProportionally",
|
||||
"-",
|
||||
"ui:fit.frameToContent",
|
||||
"ui:fit.contentToFrame",
|
||||
"ui:fit.centerContent",
|
||||
"-",
|
||||
"cmd:object.clearFittingOptions",
|
||||
"-",
|
||||
"ui:app.fittingOptions",
|
||||
"<",
|
||||
">Content",
|
||||
|
||||
@@ -104,6 +104,30 @@ 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",
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/// The submenu paths of a menu bar menu ("View/Screen Mode"), as Edit › Menus keys them.
|
||||
fn submenu_paths(title: &str) -> Vec<String> {
|
||||
let items = MENUS.iter().find(|(t, _)| *t == title).map(|(_, items)| *items).unwrap_or_default();
|
||||
|
||||
Reference in new issue
Block a user