diff --git a/crates/ui-egui/src/i18n.rs b/crates/ui-egui/src/i18n.rs index 48cfc032e..e11a5d51c 100644 --- a/crates/ui-egui/src/i18n.rs +++ b/crates/ui-egui/src/i18n.rs @@ -3131,16 +3131,6 @@ const TABLE: &[(&str, [&str; 5])] = &[ "空白文档预设", ], ), - ( - "No saved presets yet. Set the details, then click Save Document Preset.", - [ - "Noch keine gespeicherten Vorgaben. Legen Sie die Details fest und klicken Sie auf Dokumentvorgabe speichern.", - "Aucun paramètre prédéfini enregistré. Définissez les détails, puis cliquez sur Enregistrer le paramètre prédéfini de document.", - "Aún no hay ajustes preestablecidos guardados. Defina los detalles y haga clic en Guardar ajuste preestablecido de documento.", - "保存済みのプリセットはありません。詳細を設定してから「ドキュメントプリセットを保存」をクリックしてください。", - "尚无已保存的预设。请设置详细信息,然后单击“存储文档预设”。", - ], - ), ("Delete Preset", ["Vorgabe löschen", "Supprimer le paramètre prédéfini", "Eliminar ajuste preestablecido", "プリセットを削除", "删除预设"]), ( "Preset Details", diff --git a/crates/ui-egui/src/i18n/it.rs b/crates/ui-egui/src/i18n/it.rs index b1b8f9735..eca345698 100644 --- a/crates/ui-egui/src/i18n/it.rs +++ b/crates/ui-egui/src/i18n/it.rs @@ -1609,10 +1609,6 @@ pub(super) const TABLE: &[(&str, &str)] = &[ ("Your Recent Items", "Elementi recenti"), ("Saved Presets", "Predefiniti salvati"), ("Blank Document Presets", "Predefiniti documento vuoto"), - ( - "No saved presets yet. Set the details, then click Save Document Preset.", - "Nessun predefinito salvato. Imposta i dettagli, poi fai clic su Salva predefinito documento.", - ), ("Delete Preset", "Elimina predefinito"), ("Preset Details", "Dettagli predefinito"), ("Document Name", "Nome documento"), diff --git a/crates/ui-egui/src/new_document.rs b/crates/ui-egui/src/new_document.rs index b27e36b0c..5fd26f205 100644 --- a/crates/ui-egui/src/new_document.rs +++ b/crates/ui-egui/src/new_document.rs @@ -177,20 +177,19 @@ fn cards(app: &DesignApp, tab: &str) -> Vec { }; Card { key, label, nd, custom } }; + // Recent and Saved both start with the factory settings, as in InDesign. + let default = Card { key: DEFAULT_CARD.into(), label: crate::i18n::tr(lang, DEFAULT_CARD).into(), nd: NewDocument::default(), custom: false }; match tab { - "recent" => { - let default = - Card { key: DEFAULT_CARD.into(), label: crate::i18n::tr(lang, DEFAULT_CARD).into(), nd: NewDocument::default(), custom: false }; - std::iter::once(default) - .chain(app.ui.recent_new_documents.iter().enumerate().map(|(i, nd)| named(format!("recent:{i}"), nd.clone()))) - .collect() - } - "saved" => app - .session - .prefs - .document_presets - .iter() - .map(|nd| Card { key: format!("saved:{}", nd.title), label: nd.title.clone(), nd: nd.clone(), custom: preset_name(nd).is_none() }) + "recent" => std::iter::once(default) + .chain(app.ui.recent_new_documents.iter().enumerate().map(|(i, nd)| named(format!("recent:{i}"), nd.clone()))) + .collect(), + "saved" => std::iter::once(default) + .chain(app.session.prefs.document_presets.iter().map(|nd| Card { + key: format!("saved:{}", nd.title), + label: nd.title.clone(), + nd: nd.clone(), + custom: preset_name(nd).is_none(), + })) .collect(), tab => { let intent = match tab { @@ -303,8 +302,12 @@ fn tabs(app: &DesignApp, ui: &mut Ui, d: &mut Dialog) { t.text_strong, ); } - if resp.clicked() { + if resp.clicked() && !on { d.fields.insert("tab".into(), json!(key)); + // As in InDesign, a tab shows its first preset's details (Web and Mobile in pixels). + if let Some(c) = cards(app, key).into_iter().next() { + select(d, &c); + } } resp.widget_info(|| egui::WidgetInfo::selected(egui::WidgetType::SelectableLabel, true, on, text)); } @@ -314,6 +317,14 @@ fn tabs(app: &DesignApp, ui: &mut Ui, d: &mut Dialog) { ui.painter().line_segment([pos2(ui.min_rect().left(), y), pos2(ui.max_rect().right(), y)], Stroke::new(1.0, t.divider)); } +/// Fill the details from card `c`, keeping the typed document name. +fn select(d: &mut Dialog, c: &Card) { + let name = d.s("name"); + d.fields.extend(fields_for(&c.nd)); + d.fields.insert("name".into(), json!(name)); + d.fields.insert("preset".into(), json!(c.key)); +} + /// The cards of the current tab; true when one was double-clicked (create at once). fn presets(app: &mut DesignApp, ui: &mut Ui, d: &mut Dialog) -> bool { let t = Tokens::get(ui.ctx()); @@ -335,13 +346,6 @@ fn presets(app: &mut DesignApp, ui: &mut Ui, d: &mut Dialog) -> bool { ); }); ui.add_space(10.0); - if list.is_empty() { - crate::rtl::label( - ui, - egui::RichText::new(crate::i18n::tr(&lang, "No saved presets yet. Set the details, then click Save Document Preset.")).color(t.text_dim), - ); - return false; - } let current = d.s("preset"); let mut create = false; let mut delete = None; @@ -351,15 +355,12 @@ fn presets(app: &mut DesignApp, ui: &mut Ui, d: &mut Dialog) -> bool { for c in &list { let resp = card(ui, c, current == c.key); if resp.clicked() || resp.double_clicked() { - let name = d.s("name"); - d.fields.extend(fields_for(&c.nd)); - d.fields.insert("name".into(), json!(name)); - d.fields.insert("preset".into(), json!(c.key)); + select(d, c); } if resp.double_clicked() { create = true; } - if tab == "saved" { + if tab == "saved" && c.key != DEFAULT_CARD { resp.context_menu(|ui| { if ui.button(crate::rtl::widget(ui, crate::i18n::tr(&lang, "Delete Preset"))).clicked() { delete = Some(c.nd.title.clone()); @@ -816,6 +817,38 @@ mod tests { assert_eq!(recent[1].nd.start_page, 3); } + #[test] + fn a_tab_shows_its_first_preset_as_indesign_does() { + let mut app = app(); + let ctx = context(); + // A tab's name, a little above its painted text's box (which reaches below the strip). + let tab = |texts: &[(String, Rect)], name: &str| texts.iter().find(|(t, _)| t == name).map(|(_, r)| r.center() - vec2(0.0, 12.0)).unwrap(); + let texts = settle(&mut app, &ctx); + app.ui.dialog.as_mut().unwrap().fields.insert("name".into(), json!("Poster")); + click(&mut app, &ctx, tab(&texts, "Web"), 1); + let d = app.ui.dialog.as_ref().unwrap(); + assert_eq!((d.s("tab"), d.s("preset")), ("web".into(), "Web 1920 \u{d7} 1080".into())); + assert_eq!((d.s("width"), d.s("height"), units(d)), ("1920 px".into(), "1080 px".into(), Unit::Pixels), "Web is in pixels"); + assert!(!d.b("facingPages")); + assert_eq!(d.s("name"), "Poster", "the typed name stays"); + let texts = settle(&mut app, &ctx); + click(&mut app, &ctx, tab(&texts, "Print"), 1); + let d = app.ui.dialog.as_ref().unwrap(); + assert_eq!((d.s("preset"), units(d)), ("Letter".into(), Unit::Picas)); + // Clicking the open tab again keeps what was picked on it. + let texts = settle(&mut app, &ctx); + click(&mut app, &ctx, card_at(&texts, "A4"), 1); + click(&mut app, &ctx, tab(&texts, "Print"), 1); + assert_eq!(app.ui.dialog.as_ref().unwrap().s("preset"), "A4"); + // Saved starts with [Default], as in InDesign, and selects it. + let texts = settle(&mut app, &ctx); + click(&mut app, &ctx, tab(&texts, "Saved"), 1); + let d = app.ui.dialog.as_ref().unwrap(); + assert_eq!((d.s("preset"), d.s("width")), (DEFAULT_CARD.into(), "51p0".into())); + let texts = settle(&mut app, &ctx); + assert!(texts.iter().any(|(t, _)| t == "SAVED PRESETS (1)")); + } + #[test] fn double_clicking_a_card_creates_the_document() { let mut app = app(); @@ -905,7 +938,9 @@ mod tests { assert!(save_preset(&mut app, &mut d, "Letter").is_err(), "a built-in name is refused"); assert_eq!((d.s("tab"), d.s("preset")), ("saved".into(), "saved:Newsletter".into())); let saved = cards(&app, "saved"); - assert_eq!((saved.len(), saved[0].label.as_str(), saved[0].nd.pages), (1, "Newsletter", 8)); + assert_eq!(saved.len(), 2); + assert_eq!((saved[0].key.as_str(), saved[0].nd.pages), (DEFAULT_CARD, 1), "[Default] comes first, as in InDesign"); + assert_eq!((saved[1].label.as_str(), saved[1].nd.pages), ("Newsletter", 8)); let p = params(&d); remember(&mut app, &p); remember(&mut app, &p);