From a13c6dde6793b58c0da733e0cb9538d5ab6a58c7 Mon Sep 17 00:00:00 2001 From: moppeeer Date: Thu, 22 Oct 2026 00:42:28 +0200 Subject: [PATCH] Object Styles: objectStyle.dialog reports a style with no options; Polish Clear Overrides MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `objectStyle.dialog` with a style the document doesn't have, or with [None], returned success and opened nothing. `open_edit` now refuses them and the command passes the error on. Polish "Clear Overrides" reads "Wyczyść zastąpienia", as the table's other override action. Co-Authored-By: Claude Opus 5.5 --- crates/ui-egui/src/i18n/pl.rs | 2 +- crates/ui-egui/src/menus.rs | 12 +++++----- crates/ui-egui/src/object_style_dialog.rs | 29 ++++++++++++++++++----- crates/ui-egui/src/panels/styles.rs | 6 ++--- 4 files changed, 33 insertions(+), 16 deletions(-) diff --git a/crates/ui-egui/src/i18n/pl.rs b/crates/ui-egui/src/i18n/pl.rs index f0f7f58a1..41bfd2fe2 100644 --- a/crates/ui-egui/src/i18n/pl.rs +++ b/crates/ui-egui/src/i18n/pl.rs @@ -37,7 +37,7 @@ pub(super) const TABLE: &[(&str, &str)] = &[ ("Effects for:", "Efekty dla:"), ("Apply Style to Selection", "Zastosuj styl do zaznaczenia"), ("Create New Style", "Utwórz nowy styl"), - ("Clear Overrides", "Wyczyść zmiany"), + ("Clear Overrides", "Wyczyść zastąpienia"), ("Shape:", "Kształt:"), ("(no attributes)", "(brak atrybutów)"), ("Enter a style name.", "Wpisz nazwę stylu."), diff --git a/crates/ui-egui/src/menus.rs b/crates/ui-egui/src/menus.rs index 237e64f55..67d6708a6 100644 --- a/crates/ui-egui/src/menus.rs +++ b/crates/ui-egui/src/menus.rs @@ -1195,13 +1195,13 @@ fn run_ui_inner(app: &mut DesignApp, id: &str, p: &Value) -> Option { - match p.get("name").and_then(Value::as_str) { - Some(n) => crate::object_style_dialog::open_edit(app, n), - None => crate::object_style_dialog::open_new(app), + "objectStyle.dialog" => match p.get("name").and_then(Value::as_str) { + Some(n) => crate::object_style_dialog::open_edit(app, n).map(|()| Value::Null), + None => { + crate::object_style_dialog::open_new(app); + Ok(Value::Null) } - Ok(Value::Null) - } + }, "app.loadSwatches" => { if let Some(pick) = app.services.pick_open.as_mut() { return Some(match pick("swatches") { diff --git a/crates/ui-egui/src/object_style_dialog.rs b/crates/ui-egui/src/object_style_dialog.rs index 2a9a23ad4..9dc905b3c 100644 --- a/crates/ui-egui/src/object_style_dialog.rs +++ b/crates/ui-egui/src/object_style_dialog.rs @@ -39,11 +39,14 @@ pub fn open_new(app: &mut DesignApp) { app.ui.dialog = Some(Dialog::new(ID, fields)); } -/// Object Style Options for style `name`. -pub fn open_edit(app: &mut DesignApp, name: &str) { - let Some(os) = app.session.active().and_then(|st| st.doc.styles.object_style(name).cloned()) else { return }; +/// Object Style Options for style `name`; refused for a style the document doesn't have and for +/// `[None]`, which has no options. +pub fn open_edit(app: &mut DesignApp, name: &str) -> Result<(), String> { + let Some(os) = app.session.active().and_then(|st| st.doc.styles.object_style(name).cloned()) else { + return Err(format!("no object style `{name}`")); + }; if name == designcraft_doc::NO_OBJECT_STYLE { - return; + return Err(format!("`{name}` has no options")); } let fields = json!({ "new": false, @@ -60,6 +63,7 @@ pub fn open_edit(app: &mut DesignApp, name: &str) { "apply": false, }); app.ui.dialog = Some(Dialog::new(ID, fields)); + Ok(()) } /// The dialog's title: New Object Style or Object Style Options. @@ -480,7 +484,7 @@ mod tests { let b = app.run("frame.create", json!({"rect": [200, 72, 300, 172], "content": "graphic"})).unwrap()["id"].as_u64().unwrap(); app.run("style.object.apply", json!({"name": name, "ids": [b]})).unwrap(); - open_edit(&mut app, name); + open_edit(&mut app, name).unwrap(); if let Some(d) = app.ui.dialog.as_mut() { assert_eq!(title(d), "Object Style Options"); set(d, &["stroke", "weight"], json!(5.0)); @@ -493,6 +497,19 @@ mod tests { assert!(doc(&app).styles.object_style(name).unwrap().effects.as_ref().unwrap().drop_shadow.on, "effects kept"); } + /// `objectStyle.dialog` with a style the document lacks, or `[None]`, is an error and opens + /// nothing; without a name it opens New Object Style. + #[test] + fn the_dialog_command_refuses_a_style_with_no_options() { + let (mut app, _) = app_with_frame(); + for name in ["Nope", designcraft_doc::NO_OBJECT_STYLE] { + assert!(app.run("objectStyle.dialog", json!({"name": name})).is_err(), "{name}"); + assert!(app.ui.dialog.is_none(), "{name}"); + } + app.run("objectStyle.dialog", json!({})).unwrap(); + assert!(app.ui.dialog.as_ref().is_some_and(|d| d.b("new"))); + } + /// A refused OK (an empty name, a name another style has) keeps the dialog and its edits, /// with the reason shown. #[test] @@ -512,7 +529,7 @@ mod tests { assert_eq!(d.s("status"), "Enter a style name."); assert_eq!(get(d, &["stroke", "weight"]), &json!(7.0), "the edits are kept"); assert!(frame(&mut app, &ctx).iter().any(|t| t.trim() == "Enter a style name.")); - open_edit(&mut app, "Mine"); + open_edit(&mut app, "Mine").unwrap(); if let Some(d) = app.ui.dialog.as_mut() { d.fields.insert("name".into(), json!("Taken")); } diff --git a/crates/ui-egui/src/panels/styles.rs b/crates/ui-egui/src/panels/styles.rs index f1c057c84..1de6d53f6 100644 --- a/crates/ui-egui/src/panels/styles.rs +++ b/crates/ui-egui/src/panels/styles.rs @@ -157,14 +157,14 @@ pub fn object(app: &mut DesignApp, ui: &mut egui::Ui) { } let editable = n != designcraft_doc::NO_OBJECT_STYLE; if resp.double_clicked() && editable { - crate::object_style_dialog::open_edit(app, n); + let _ = crate::object_style_dialog::open_edit(app, n); } else if resp.clicked() && selected { let _ = app.run("style.object.apply", json!({"name": n})); } resp.context_menu(|ui| { let label = crate::i18n::style_name(&lang, n); if editable && ui.button(crate::rtl::widget(ui, crate::i18n::tr(&lang, "Edit \"{name}\"…").replace("{name}", label))).clicked() { - crate::object_style_dialog::open_edit(app, n); + let _ = crate::object_style_dialog::open_edit(app, n); ui.close(); } if ui @@ -202,7 +202,7 @@ pub fn object(app: &mut DesignApp, ui: &mut egui::Ui) { if let Some((n, _)) = current.as_ref().filter(|(n, _)| n != designcraft_doc::NO_OBJECT_STYLE) && ui.button(crate::rtl::widget(ui, crate::i18n::tr(&lang, "Object Style Options…"))).clicked() { - crate::object_style_dialog::open_edit(app, n); + let _ = crate::object_style_dialog::open_edit(app, n); ui.close(); } });