Add a User Preferences page for six command-only settings

Zoom direction and factor, whether TEXTEDIT ends after one object, whether
continued dimensions inherit the base dimension's style, which points QDIM
measures from, and which annotative objects pick up a newly set scale. All
six work today; none had a control.

Two of them needed their meaning worked out rather than copied.

ANNOAUTOSCALE stores the mode in the magnitude and on/off in the sign, and
the four modes are not documented anywhere in the app — the command prompt
just says `[-4..4]`. Reading `add_annotation_scale_to_objects` gives them:
1 skips layers that are off, frozen, locked or frozen in the viewport, 2
keeps the locked ones, 3 skips only locked, 4 takes everything. The dropdown
names them instead of showing bare numbers, and choosing Off negates rather
than zeroing, so the mode survives being switched off and back on — which is
the convention the status-bar pill already follows.

The QDIM origin priority had no system variable at all; it could only be
reached through a keyword inside the running command.

Drawing units stay in their own dialog; this page links to it.

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
PanosandClaude Opus 5 committed 2026-09-10 08:29:48 +03:00
1 parent a0027a8977
commit 9c3f3625da
4 files changed
+218

No files matched your search

+12
View File
@@ -2017,6 +2017,18 @@ pub enum Message {
ClipromptLinesChanged(i32),
/// Change how long command-line history lines stay visible (COMMANDLINEFADETIME).
CommandLineFadeChanged(i32),
/// Toggle reversing the mouse-wheel zoom direction (ZOOMWHEEL).
ZoomWheelReversedChanged(bool),
/// Change how far one wheel notch zooms (ZOOMFACTOR, 3..=100).
ZoomFactorChanged(i32),
/// Toggle TEXTEDIT ending after one object (TEXTEDITMODE).
TextEditModeChanged(bool),
/// Toggle continued dimensions inheriting the base style (DIMCONTINUEMODE).
DimContinueModeChanged(bool),
/// Change which points QDIM measures from (0 endpoints, 1 intersections).
QdimSnapPriorityChanged(u8),
/// Change which annotative objects pick up a new scale (ANNOAUTOSCALE).
AnnoAutoScaleChanged(i8),
/// Restore Model Space display/canvas appearance to defaults.
RestoreModelSpaceDisplayDefaults,
/// Restore Selection visual effect settings to defaults.
+43
View File
@@ -6223,6 +6223,49 @@ impl OpenCADStudio {
Task::none()
}
Message::ZoomWheelReversedChanged(reversed) => {
self.zoom_wheel_reversed = reversed;
self.persist_settings_if_changed();
Task::none()
}
Message::ZoomFactorChanged(factor) => {
self.zoom_factor = factor.clamp(3, 100);
self.persist_settings_if_changed();
Task::none()
}
Message::TextEditModeChanged(single) => {
self.texteditmode = single;
self.persist_settings_if_changed();
Task::none()
}
Message::DimContinueModeChanged(inherit) => {
self.dimension_continue_mode = i16::from(inherit);
self.persist_settings_if_changed();
Task::none()
}
Message::QdimSnapPriorityChanged(priority) => {
self.quick_dimension_snap_priority = priority.min(1);
self.persist_settings_if_changed();
Task::none()
}
// The sign carries on/off and the magnitude the mode, so switching
// off and back on has to return to the mode that was chosen — the
// same convention the status-bar pill uses when it negates.
Message::AnnoAutoScaleChanged(mode) => {
self.annotation_auto_scale = if mode == 0 {
-self.annotation_auto_scale.abs().max(1)
} else {
mode.clamp(1, 4)
};
self.persist_settings_if_changed();
Task::none()
}
Message::PickDragRectToggled(rectangle) => {
self.pick_drag_rect = rectangle;
self.persist_settings_if_changed();
+6
View File
@@ -198,6 +198,12 @@ impl OpenCADStudio {
textfill: crate::scene::text::sdf_atlas::textfill(),
cliprompt_lines: self.cliprompt_lines,
commandline_fade_ms: self.commandline_fade_ms,
zoom_wheel_reversed: self.zoom_wheel_reversed,
zoom_factor: self.zoom_factor,
texteditmode: self.texteditmode,
dimension_continue_mode: self.dimension_continue_mode,
qdim_snap_priority: self.quick_dimension_snap_priority,
annotation_auto_scale: self.annotation_auto_scale,
},
self.double_click_block_refedit,
self.double_click_block_attedit,
+157
View File
@@ -28,6 +28,7 @@ pub enum OptionsTab {
OpenAndSave,
Display,
Selection,
UserPreferences,
Drawing,
}
@@ -48,6 +49,19 @@ pub struct AppPrefs {
pub cliprompt_lines: i32,
/// COMMANDLINEFADETIME: how long overlay history lines stay visible, in ms.
pub commandline_fade_ms: i32,
/// ZOOMWHEEL: reverse the mouse-wheel zoom direction.
pub zoom_wheel_reversed: bool,
/// ZOOMFACTOR, 3..=100.
pub zoom_factor: i32,
/// TEXTEDITMODE: TEXTEDIT keeps prompting for the next object.
pub texteditmode: bool,
/// DIMCONTINUEMODE: continued dimensions inherit the base dimension's style.
pub dimension_continue_mode: i16,
/// QDIM extension-origin priority: 0 endpoints, 1 intersections.
pub qdim_snap_priority: u8,
/// ANNOAUTOSCALE, -4..=4. The sign is on/off; the magnitude selects which
/// objects a newly added scale reaches.
pub annotation_auto_scale: i8,
}
/// The Selection-card settings that live on `UserSettings` rather than on the
@@ -995,11 +1009,153 @@ pub fn view_window<'a>(
.spacing(0)
.width(sizing.width);
// ANNOAUTOSCALE's magnitude decides which objects a newly added scale
// reaches — 1 skips layers that are off, frozen, locked or frozen in the
// viewport, 2 keeps locked ones, 3 skips only locked, 4 takes everything.
// The sign is the on/off the status-bar pill flips, so the mode survives
// being switched off and back on.
let auto_scale_options = [
(0i8, "Off"),
(1, "Skip objects on layers that are off, frozen or locked"),
(2, "Skip objects on layers that are off or frozen"),
(3, "Skip objects on locked layers"),
(4, "All annotative objects"),
]
.into_iter()
.map(|(value, label)| Labelled {
value,
label: crate::t!(label).into_owned(),
})
.collect::<Vec<_>>();
let selected_auto_scale = auto_scale_options
.iter()
.find(|choice| choice.value == prefs.annotation_auto_scale.max(0))
.cloned();
let qdim_options = [
(0u8, "Endpoints"),
(1, "Intersections"),
]
.into_iter()
.map(|(value, label)| Labelled {
value,
label: crate::t!(label).into_owned(),
})
.collect::<Vec<_>>();
let selected_qdim = qdim_options
.iter()
.find(|choice| choice.value == prefs.qdim_snap_priority)
.cloned();
let user_prefs = column![
text(crate::t!("User Preferences")).size(15),
Space::new().height(10),
text(crate::t!("Zoom")).size(15),
Space::new().height(10),
row![
iced::widget::checkbox(prefs.zoom_wheel_reversed)
.on_toggle(Message::ZoomWheelReversedChanged)
.size(15),
text(crate::t!("Reverse mouse wheel zoom (ZOOMWHEEL)")).size(12),
]
.spacing(8)
.align_y(iced::Center),
Space::new().height(12),
row![
text(crate::t!("Zoom factor")).size(12).width(150),
slider(3..=100, prefs.zoom_factor.clamp(3, 100), Message::ZoomFactorChanged)
.step(1)
.width(Fill),
text(prefs.zoom_factor.clamp(3, 100).to_string()).size(11).width(44),
]
.spacing(10)
.align_y(iced::Center),
Space::new().height(6),
text(crate::t!("How far one wheel notch zooms (ZOOMFACTOR)."))
.size(11)
.width(sizing.width),
Space::new().height(24),
text(crate::t!("Text and Dimensions")).size(15),
Space::new().height(10),
row![
iced::widget::checkbox(prefs.texteditmode)
.on_toggle(Message::TextEditModeChanged)
.size(15),
text(crate::t!("TEXTEDIT edits one object and ends (TEXTEDITMODE)")).size(12),
]
.spacing(8)
.align_y(iced::Center),
Space::new().height(12),
row![
iced::widget::checkbox(prefs.dimension_continue_mode == 1)
.on_toggle(Message::DimContinueModeChanged)
.size(15),
text(crate::t!(
"Continued dimensions inherit the base dimension's layer and style (DIMCONTINUEMODE)"
))
.size(12),
]
.spacing(8)
.align_y(iced::Center),
Space::new().height(12),
row![
text(crate::t!("QDIM origin priority")).size(12).width(150),
iced::widget::pick_list(selected_qdim, qdim_options, |choice| choice.label.clone())
.on_select(|choice| Message::QdimSnapPriorityChanged(choice.value))
.width(Fill),
]
.spacing(10)
.align_y(iced::Center),
Space::new().height(6),
text(crate::t!(
"Which points QDIM measures from. Also settable inside the command."
))
.size(11)
.width(sizing.width),
Space::new().height(24),
text(crate::t!("Annotation")).size(15),
Space::new().height(10),
row![
text(crate::t!("Add scales automatically")).size(12).width(150),
iced::widget::pick_list(selected_auto_scale, auto_scale_options, |choice| {
choice.label.clone()
})
.on_select(|choice| Message::AnnoAutoScaleChanged(choice.value))
.width(Fill),
]
.spacing(10)
.align_y(iced::Center),
Space::new().height(6),
text(crate::t!(
"Which annotative objects pick up a newly set annotation scale (ANNOAUTOSCALE)."
))
.size(11)
.width(sizing.width),
Space::new().height(24),
text(crate::t!("Drawing Units")).size(15),
Space::new().height(10),
row![
text(crate::t!("Length, angle and insertion units"))
.size(12)
.width(Fill),
button(text(crate::t!("Drawing Units…")).size(11))
.on_press(Message::OpenDrawingUnits)
.padding([4, 10])
.style(button::secondary),
]
.spacing(10)
.align_y(iced::Center),
]
.spacing(0)
.width(sizing.width);
let content: Element<'a, Message> = match active_tab {
OptionsTab::General => general.into(),
OptionsTab::Display => display_element.into(),
OptionsTab::Selection => selection.into(),
OptionsTab::OpenAndSave => open_and_save.into(),
OptionsTab::UserPreferences => user_prefs.into(),
OptionsTab::Drawing => drawing.into(),
};
@@ -1019,6 +1175,7 @@ pub fn view_window<'a>(
tab_button(crate::t!("Open and Save"), OptionsTab::OpenAndSave),
tab_button(crate::t!("Display"), OptionsTab::Display),
tab_button(crate::t!("Selection"), OptionsTab::Selection),
tab_button(crate::t!("User Preferences"), OptionsTab::UserPreferences),
tab_button(crate::t!("Drawing"), OptionsTab::Drawing),
]
.spacing(2)