mirror of
https://github.com/storytold/cadcraft.git
synced 2026-10-24 02:46: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
@@ -357,7 +357,9 @@ fn main() -> eframe::Result {
|
||||
app.open_path(f);
|
||||
}
|
||||
if app.session.docs.is_empty() {
|
||||
app.session.new_drawing(false);
|
||||
// In the units the profile asks for (MEASUREINIT, restored above).
|
||||
let metric = app.session.settings.measureinit;
|
||||
app.session.new_drawing(metric);
|
||||
}
|
||||
let ctx = cc.egui_ctx.clone();
|
||||
let desktop_theme = desktop_theme::DesktopTheme::start(move || ctx.request_repaint());
|
||||
|
||||
@@ -80,3 +80,7 @@ sync_github_name = true
|
||||
real_name = "Rodrigo Gressler"
|
||||
display_name = "Rodrigo"
|
||||
sync_github_name = false
|
||||
|
||||
[people.aussieboer61]
|
||||
real_name = "Richard Sauer"
|
||||
display_name = "Richard Sauer"
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
@@ -980,6 +980,10 @@
|
||||
Reset keeps the interface language. Скидання не змінює мову інтерфейсу.
|
||||
Reset to Defaults Скинути до типових
|
||||
Save new drawings as Зберігати нові креслення як
|
||||
Units of new drawings Одиниці нових креслень
|
||||
Imperial (inches) Імперські (дюйми)
|
||||
Metric (millimetres) Метричні (міліметри)
|
||||
New and the first drawing at startup use these units unless a default template is set (QNEWTEMPLATE). Команда «Створити» і перше креслення під час запуску використовують ці одиниці, якщо не задано типовий шаблон (QNEWTEMPLATE).
|
||||
Screen magnifiers, screen readers and recorders follow the system cursor. Екранні лупи, програми читання з екрана та запису стежать за системним курсором.
|
||||
Select objects first, then choose a command Спочатку вибирати об'єкти, потім команду
|
||||
Selection Вибір
|
||||
|
||||
|
@@ -233,6 +233,18 @@ fn files(app: &CadApp, ui: &mut egui::Ui, changes: &mut Map<String, Value>) {
|
||||
}
|
||||
ui.end_row();
|
||||
|
||||
ui.label(crate::tl!("Units of new drawings"));
|
||||
ui.horizontal(|ui| {
|
||||
let metric = app.session.settings.measureinit;
|
||||
if ui.radio(!metric, crate::tl!("Imperial (inches)")).clicked() && metric {
|
||||
changes.insert("MEASUREINIT".into(), json!(0));
|
||||
}
|
||||
if ui.radio(metric, crate::tl!("Metric (millimetres)")).clicked() && !metric {
|
||||
changes.insert("MEASUREINIT".into(), json!(1));
|
||||
}
|
||||
});
|
||||
ui.end_row();
|
||||
|
||||
ui.label(crate::tl!("Automatic save every"));
|
||||
let mut minutes = cadcraft_engine::autosave::savetime();
|
||||
let max = cadcraft_engine::autosave::MAX_SAVETIME;
|
||||
@@ -258,6 +270,7 @@ fn files(app: &CadApp, ui: &mut egui::Ui, changes: &mut Map<String, Value>) {
|
||||
}
|
||||
ui.end_row();
|
||||
});
|
||||
hint(ui, crate::tl!("New and the first drawing at startup use these units unless a default template is set (QNEWTEMPLATE)."));
|
||||
hint(ui, crate::tl!("A drawing opened from a file keeps that file's format."));
|
||||
hint(ui, crate::tl!("Drawings with no file yet are saved in the default version. 0 minutes turns automatic save off."));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user