From 4cc8e7db623b326f546547671d63a162cf4b47e7 Mon Sep 17 00:00:00 2001 From: Panos <25664832+mechpanos@users.noreply.github.com> Date: Thu, 10 Sep 2026 09:03:02 +0300 Subject: [PATCH] Fix four things the Options survey turned up MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **TEXTFILL marked the drawing modified.** It is an application preference — it lives in a process global and is snapshotted into settings.json — but it was missing from the list of names that persist, so setting it dirtied the open drawing instead and never reached the settings file through that path. **LTSCALE and CELTSCALE validated differently depending on the door.** The standalone commands reject a value of zero or less, because a non-positive linetype scale degenerates every dash pattern in the drawing. `SETVAR LTSCALE -5` accepted it. A test drives both entry points for both variables and fails on the SETVAR path without the fix. **ISAVEBAK, SAVETIME and FILEASSOC were missing from the autocomplete registry** although all three dispatch, so the command line never offered them. **`bg_color` and `paper_bg_color` were dead fields**, always written as `None` and ignored on load since the model-space configuration superseded them. Removing them is safe: the config is `#[serde(default)]` and ignores unknown keys, so existing settings files simply stop carrying them. One thing the survey flagged that turned out not to be a bug: on the Display page the model background row hides itself outside Custom mode while the paper and desk rows do not. That asymmetry is correct — the canvas mode governs only the model background, and the other two apply in every mode. Co-Authored-By: Claude Opus 5 --- src/app/commands/mod.rs | 5 +++ src/app/commands/styleprops.rs | 56 ++++++++++++++++++++++++++++++++-- src/app/settings.rs | 8 ----- src/app/update/file.rs | 3 -- 4 files changed, 59 insertions(+), 13 deletions(-) diff --git a/src/app/commands/mod.rs b/src/app/commands/mod.rs index 8efa97d5b..3c6a00624 100644 --- a/src/app/commands/mod.rs +++ b/src/app/commands/mod.rs @@ -554,6 +554,11 @@ inventory::submit!(crate::command::CommandRegistration { "GRIPHOT", "GRIPHOVER", "GRIPOBJLIMIT", + // Dispatched all along, but absent from the registry, so command-line + // completion never offered them. + "ISAVEBAK", + "SAVETIME", + "FILEASSOC", // Reset selected entities' overrides to follow their layer. "SETBYLAYER", // Remove duplicate objects; set drawing base point; audit integrity; diff --git a/src/app/commands/styleprops.rs b/src/app/commands/styleprops.rs index 12128fa88..b99da19b4 100644 --- a/src/app/commands/styleprops.rs +++ b/src/app/commands/styleprops.rs @@ -1167,24 +1167,37 @@ impl OpenCADStudio { let outcome: Result<(String, bool), String> = { let h = &mut self.tabs[i].scene.document.header; match name.as_str() { + // The standalone LTSCALE and CELTSCALE commands + // require a positive value; reaching the same + // variable through SETVAR used to accept zero or a + // negative one, which degenerates every dash + // pattern in the drawing. "LTSCALE" => match &value { Some(v) => v .parse::() + .ok() + .filter(|x| x.is_finite() && *x > 0.0) .map(|x| { h.linetype_scale = x; (format!("LTSCALE = {x}"), true) }) - .map_err(|_| "SETVAR: numeric value required.".into()), + .ok_or_else(|| { + "SETVAR: positive numeric value required.".into() + }), None => Ok((format!("LTSCALE = {}", h.linetype_scale), false)), }, "CELTSCALE" => match &value { Some(v) => v .parse::() + .ok() + .filter(|x| x.is_finite() && *x > 0.0) .map(|x| { h.current_entity_linetype_scale = x; (format!("CELTSCALE = {x}"), true) }) - .map_err(|_| "SETVAR: numeric value required.".into()), + .ok_or_else(|| { + "SETVAR: positive numeric value required.".into() + }), None => Ok(( format!("CELTSCALE = {}", h.current_entity_linetype_scale), false, @@ -2156,6 +2169,12 @@ impl OpenCADStudio { | "GRIPHOVER" | "GRIPOBJLIMIT" | "DELOBJ" + // App-level, not part of the drawing: + // it lives in a process global and is + // snapshotted into the settings file. + // Without this it marked the drawing + // modified instead of persisting. + | "TEXTFILL" ) { self.persist_settings_if_changed(); } else { @@ -3144,3 +3163,36 @@ mod tests { assert_eq!(app.delete_objects, 3); } } + +#[cfg(test)] +mod scale_validation_tests { + use crate::app::OpenCADStudio; + + /// A linetype scale of zero or less degenerates every dash pattern in the + /// drawing, which is why the standalone commands reject it. Reaching the + /// same variable through SETVAR used to accept it, so which door you came + /// through decided whether the drawing could be broken. + #[test] + fn both_doors_to_ltscale_refuse_a_non_positive_value() { + for name in ["LTSCALE", "CELTSCALE"] { + for entry in [format!("{name} -5"), format!("SETVAR {name} -5")] { + let mut app = OpenCADStudio::new_for_test(); + app.automation_op(r#"{"op":"new"}"#); + let i = app.active_tab; + let before = if name == "LTSCALE" { + app.tabs[i].scene.document.header.linetype_scale + } else { + app.tabs[i].scene.document.header.current_entity_linetype_scale + }; + let _ = app.run_command_line(&entry); + let after = if name == "LTSCALE" { + app.tabs[i].scene.document.header.linetype_scale + } else { + app.tabs[i].scene.document.header.current_entity_linetype_scale + }; + assert_eq!(before, after, "{entry} must be refused"); + } + } + } +} + diff --git a/src/app/settings.rs b/src/app/settings.rs index 3032b0a60..9db2d574c 100644 --- a/src/app/settings.rs +++ b/src/app/settings.rs @@ -269,12 +269,6 @@ pub struct UserSettings { pub pick_drag_rect: bool, /// Show the floating Quick Properties panel when objects are selected. pub quick_properties: bool, - /// Persisted viewport background colours (0–255 RGB); `None` = app default - /// (dark grey model / off-white paper). Applied to every drawing tab on - /// launch and to tabs opened later, so a chosen background survives restarts - /// (#188). - pub bg_color: Option<[u8; 3]>, - pub paper_bg_color: Option<[u8; 3]>, /// Interface language preference. `System` negotiates against the /// platform locale on every launch. pub language: crate::i18n::Language, @@ -384,8 +378,6 @@ impl Default for UserSettings { pick_add: true, pick_drag_rect: false, quick_properties: false, - bg_color: None, - paper_bg_color: None, language: crate::i18n::Language::default(), cliprompt_lines: 3, commandline_fade_ms: 3000, diff --git a/src/app/update/file.rs b/src/app/update/file.rs index 86694f6b2..a98df8247 100644 --- a/src/app/update/file.rs +++ b/src/app/update/file.rs @@ -435,8 +435,6 @@ impl OpenCADStudio { pick_add: self.pick_add, pick_drag_rect: self.pick_drag_rect, quick_properties: self.quick_properties, - bg_color: None, - paper_bg_color: None, language: self.language, cliprompt_lines: crate::app::settings::clamp_clipromptlines(self.cliprompt_lines), commandline_fade_ms: crate::app::settings::clamp_commandline_fade_ms( @@ -516,7 +514,6 @@ impl OpenCADStudio { self.pick_add = s.pick_add; self.pick_drag_rect = s.pick_drag_rect; self.quick_properties = s.quick_properties; - // Legacy settings.bg_color / paper_bg_color are superseded by model_space config. if crate::i18n::set_language(s.language).is_ok() { self.language = s.language; }