mirror of
https://github.com/storytold/cadcraft.git
synced 2026-10-24 10:56:51 -06:00
MEASUREINIT: choose the units of new drawings, kept in the profile (#1792)
* MEASUREINIT: choose the units of new drawings, kept in the profile
NEW, QNEW and the first drawing at startup were always imperial unless a
template or {"metric": true} was given, and nothing kept a metric choice
across restarts. MEASUREINIT (0 imperial, the default; 1 metric) is now a
profile variable: NEW without `metric` or a template follows it, the app's
startup drawing follows it, and Options > Files shows it as "Units of new
drawings". QNEWTEMPLATE and an explicit `metric` still win.
Part of #1182.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dxn7PD9WzP4ET2LU7BRLDK
* contributors: add Richard Sauer (aussieboer61)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dxn7PD9WzP4ET2LU7BRLDK
---------
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
Brandon Thomas
parent
7db656fdc7
commit
fde62a39ab
@@ -163,7 +163,7 @@ pub fn specs() -> Vec<CommandSpec> {
|
||||
.menu(&["File", "New Drawing..."])
|
||||
.key("Cmd+N")
|
||||
.alias(&["qnew"])
|
||||
.params("{metric?: bool, template?: path to a .dwt/.dxf template (\".\" for none; default QNEWTEMPLATE)}")
|
||||
.params("{metric?: bool (default MEASUREINIT), template?: path to a .dwt/.dxf template (\".\" for none; default QNEWTEMPLATE)}")
|
||||
.enabled(always)
|
||||
.noundo(),
|
||||
CommandSpec::new("open", "Open...", run_open)
|
||||
@@ -252,7 +252,8 @@ fn run_new(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
if let Some(r) = template::run_new(s, p)? {
|
||||
return Ok(r);
|
||||
}
|
||||
let i = s.new_drawing(bool_or(p, "metric", false));
|
||||
let metric = s.settings.measureinit;
|
||||
let i = s.new_drawing(bool_or(p, "metric", metric));
|
||||
Ok(json!({ "index": i, "title": s.docs.get(i).map(|d| d.title.clone()) }))
|
||||
}
|
||||
|
||||
|
||||
@@ -52,6 +52,7 @@ pub const PROFILE_VARS: &[&str] = &[
|
||||
"PICKADD",
|
||||
"PICKDRAG",
|
||||
"MAXARRAY",
|
||||
"MEASUREINIT",
|
||||
];
|
||||
|
||||
/// The most profile entries [`restore`] reads (a saved profile is untrusted input).
|
||||
|
||||
@@ -359,6 +359,9 @@ pub struct Settings {
|
||||
pub gridmajor: u32,
|
||||
/// ZOOMFACTOR: how far one mouse wheel step zooms (3..=100).
|
||||
pub zoomfactor: u32,
|
||||
/// MEASUREINIT: the units of a new drawing made without a template (NEW, QNEW and the first
|
||||
/// drawing at startup): `false` (0, the default) imperial, `true` (1) metric.
|
||||
pub measureinit: bool,
|
||||
/// -VIEW sEttings > Layer snapshot: named views save the layer settings with them.
|
||||
pub view_layer_snapshot: bool,
|
||||
pub dynmode: bool,
|
||||
@@ -477,6 +480,7 @@ impl Default for Settings {
|
||||
gridunit: Vec2::new(0.5, 0.5),
|
||||
gridmajor: 5,
|
||||
zoomfactor: 60,
|
||||
measureinit: false,
|
||||
view_layer_snapshot: true,
|
||||
dynmode: true,
|
||||
dyndigrip: 31,
|
||||
|
||||
@@ -64,6 +64,7 @@ const SESSION_VARS: &[&str] = &[
|
||||
"CURSORSIZE",
|
||||
"MAXARRAY",
|
||||
"ZOOMFACTOR",
|
||||
"MEASUREINIT",
|
||||
"LASTPOINT",
|
||||
"FONTALT",
|
||||
"FONTFALLBACK",
|
||||
@@ -140,6 +141,7 @@ pub fn get(s: &Session, name: &str) -> Option<Value> {
|
||||
"CURSORSIZE" => json!(st.cursorsize),
|
||||
"MAXARRAY" => json!(st.maxarray),
|
||||
"ZOOMFACTOR" => json!(st.zoomfactor),
|
||||
"MEASUREINIT" => json!(i32::from(st.measureinit)),
|
||||
"LASTPOINT" => json!([s.last_point.x, s.last_point.y, 0.0]),
|
||||
// Held in radians (`$ANGBASE` in DXF is in degrees); reported in degrees, like POLARANG.
|
||||
"ANGBASE" => json!(s.doc().ok()?.header.f64("ANGBASE", 0.0).to_degrees()),
|
||||
@@ -355,6 +357,7 @@ pub fn set(s: &mut Session, name: &str, v: &Value) -> Result<()> {
|
||||
"CURSORSIZE" => st.cursorsize = as_f64(v).ok_or_else(bad)?.clamp(1.0, 100.0),
|
||||
"MAXARRAY" => st.maxarray = as_f64(v).ok_or_else(bad)?.clamp(100.0, 10_000_000.0) as u64,
|
||||
"ZOOMFACTOR" => st.zoomfactor = as_i(v).filter(|z| (3..=100).contains(z)).ok_or_else(bad)? as u32,
|
||||
"MEASUREINIT" => st.measureinit = small(v, 1).ok_or_else(bad)? == 1,
|
||||
"FONTALT" => cadcraft_fonts::ttf::set_font_alt(v.as_str().ok_or_else(bad)?),
|
||||
"FONTFALLBACK" => cadcraft_fonts::ttf::set_fallback_fonts(v.as_str().ok_or_else(bad)?),
|
||||
"SAVETIME" => crate::autosave::set_savetime(
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
//! MEASUREINIT: the units of a new drawing made without a template (issue #1182). It is a profile
|
||||
//! setting, so a metric choice survives restarts; an explicit `metric` or template still wins.
|
||||
|
||||
use cadcraft_engine::Session;
|
||||
use serde_json::json;
|
||||
|
||||
fn var(s: &mut Session, name: &str) -> serde_json::Value {
|
||||
s.execute("getvar", &json!({ "name": name })).unwrap()["value"].clone()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn imperial_by_default() {
|
||||
let mut s = Session::empty();
|
||||
assert_eq!(var(&mut s, "MEASUREINIT"), json!(0));
|
||||
s.execute("new", &json!({})).unwrap();
|
||||
assert_eq!(var(&mut s, "INSUNITS"), json!(1));
|
||||
assert_eq!(var(&mut s, "MEASUREMENT"), json!(0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn new_follows_measureinit() {
|
||||
let mut s = Session::empty();
|
||||
s.execute("options", &json!({ "MEASUREINIT": 1 })).unwrap();
|
||||
s.execute("new", &json!({})).unwrap();
|
||||
assert_eq!(var(&mut s, "INSUNITS"), json!(4));
|
||||
assert_eq!(var(&mut s, "MEASUREMENT"), json!(1));
|
||||
assert_eq!(var(&mut s, "DIMSTYLE"), json!("ISO-25"));
|
||||
// An explicit choice still wins.
|
||||
s.execute("new", &json!({ "metric": false })).unwrap();
|
||||
assert_eq!(var(&mut s, "INSUNITS"), json!(1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn only_zero_or_one() {
|
||||
let mut s = Session::empty();
|
||||
for bad in [json!(2), json!(-1), json!("metric")] {
|
||||
assert!(s.execute("options", &json!({ "MEASUREINIT": bad })).is_err(), "{bad}");
|
||||
}
|
||||
assert_eq!(var(&mut s, "MEASUREINIT"), json!(0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn kept_in_the_profile() {
|
||||
let mut s = Session::empty();
|
||||
s.execute("options", &json!({ "MEASUREINIT": 1 })).unwrap();
|
||||
let saved = cadcraft_engine::cmd::options::profile(&s);
|
||||
assert_eq!(saved["MEASUREINIT"], json!(1));
|
||||
let mut restarted = Session::empty();
|
||||
cadcraft_engine::cmd::options::restore(&mut restarted, &saved);
|
||||
assert_eq!(var(&mut restarted, "MEASUREINIT"), json!(1));
|
||||
}
|
||||
Reference in New Issue
Block a user