forked from 1b-agent/opencadstudio-upstream
feat(view): complete ZOOM options
Add command-line navigation modes and persistent wheel controls.\n\nRefs #412
This commit is contained in:
1 parent
3f103d2f8b
commit
adb8ced8b5
17 files changed
+380
-23
No files matched your search
+70
-13
@@ -805,40 +805,94 @@ impl OpenCADStudio {
|
||||
self.tabs[i].active_cmd = Some(Box::new(cmd));
|
||||
}
|
||||
|
||||
"ZOOM EXTENTS ALL" | "ZOOM EXTENTS ALL VIEWPORTS" | "ZEA" => {
|
||||
"ZOOM EXTENTS ALL" | "ZOOM EXTENTS ALL VIEWPORTS" | "ZOOM EA" | "ZEA" => {
|
||||
self.tabs[i].scene.remember_current_view();
|
||||
self.tabs[i].scene.fit_all_model_viewports();
|
||||
self.command_line.push_output(crate::t!("Zoom Extents — All Viewports").as_ref());
|
||||
}
|
||||
|
||||
"ZOOM EXTENTS" | "ZOOMEXTENTS" | "ZE" => {
|
||||
"ZOOM EXTENTS" | "ZOOM E" | "ZOOMEXTENTS" | "ZE" => {
|
||||
self.tabs[i].scene.remember_current_view();
|
||||
self.tabs[i].scene.fit_all();
|
||||
self.command_line.push_output(crate::t!("Zoom Extents").as_ref());
|
||||
}
|
||||
|
||||
"ZOOM IN" | "ZI" => {
|
||||
"ZOOM IN" | "ZOOM I" | "ZI" => {
|
||||
self.tabs[i].scene.remember_current_view();
|
||||
self.tabs[i].scene.zoom_camera(1.0 / 1.5);
|
||||
self.command_line.push_output(crate::t!("Zoom In").as_ref());
|
||||
}
|
||||
|
||||
"ZOOM OUT" | "ZO" => {
|
||||
self.tabs[i].scene.remember_current_view();
|
||||
self.tabs[i].scene.zoom_camera(1.5);
|
||||
self.command_line.push_output(crate::t!("Zoom Out").as_ref());
|
||||
}
|
||||
|
||||
// ZOOM ALL — fit the configured drawing limits.
|
||||
"ZOOM ALL" | "ZOOM A" | "ZA" => {
|
||||
self.tabs[i].scene.remember_current_view();
|
||||
self.tabs[i].scene.fit_all_with_limits();
|
||||
self.command_line.push_output(crate::t!("Zoom All").as_ref());
|
||||
}
|
||||
|
||||
"ZOOM PREVIOUS" | "ZOOM P" | "ZP" => {
|
||||
if self.tabs[i].scene.restore_previous_view() {
|
||||
self.command_line.push_output(crate::t!("Zoom Previous").as_ref());
|
||||
} else {
|
||||
self.command_line
|
||||
.push_error(crate::t!("ZOOM: no previous view.").as_ref());
|
||||
}
|
||||
}
|
||||
|
||||
"ZOOM OBJECT" | "ZOOM O" | "ZOBJ" => {
|
||||
let handles: Vec<_> = self.tabs[i]
|
||||
.scene
|
||||
.selected_entities()
|
||||
.into_iter()
|
||||
.map(|(handle, _)| handle)
|
||||
.collect();
|
||||
if handles.is_empty() {
|
||||
use crate::modules::draw::select::SelectObjectsCommand;
|
||||
let command = SelectObjectsCommand::new("ZOOM OBJECT");
|
||||
self.command_line.push_info(&command.prompt());
|
||||
self.tabs[i].active_cmd = Some(Box::new(command));
|
||||
} else {
|
||||
self.tabs[i].scene.remember_current_view();
|
||||
if self.tabs[i].scene.zoom_to_entities(&handles) {
|
||||
self.command_line.push_output(crate::t!("Zoom Object").as_ref());
|
||||
} else {
|
||||
self.command_line.push_error(
|
||||
crate::t!("ZOOM: selected objects have no visible bounds.").as_ref(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"ZOOM DYNAMIC" | "ZOOM D" | "ZD" => {
|
||||
self.tabs[i].zoom_dynamic_mode = true;
|
||||
self.clear_navigation_hover(i);
|
||||
self.command_line.push_output(
|
||||
crate::t!(
|
||||
"ZOOM Dynamic: drag horizontally to pan and vertically to zoom. Press Esc to exit."
|
||||
)
|
||||
.as_ref(),
|
||||
);
|
||||
}
|
||||
|
||||
// ZOOM SCALE — set zoom factor (e.g. "ZOOM SCALE 2" or "ZS 0.5")
|
||||
cmd if cmd.starts_with("ZOOM SCALE ") || cmd.starts_with("ZS ") => {
|
||||
cmd if cmd.starts_with("ZOOM SCALE ")
|
||||
|| cmd.starts_with("ZOOM S ")
|
||||
|| cmd.starts_with("ZS ") =>
|
||||
{
|
||||
let rest = cmd
|
||||
.split_once(' ')
|
||||
.and_then(|(_, r)| r.split_once(' ').map(|(_, v)| v).or(Some(r)))
|
||||
.strip_prefix("ZOOM SCALE ")
|
||||
.or_else(|| cmd.strip_prefix("ZOOM S "))
|
||||
.or_else(|| cmd.strip_prefix("ZS "))
|
||||
.unwrap_or("1");
|
||||
if let Ok(factor) = rest.trim().parse::<f32>() {
|
||||
if factor > 0.0 {
|
||||
self.tabs[i].scene.remember_current_view();
|
||||
self.tabs[i].scene.zoom_camera(1.0 / factor);
|
||||
self.command_line
|
||||
.push_output(crate::tf!("Zoom Scale ×{factor:.3}").as_ref());
|
||||
@@ -866,15 +920,18 @@ impl OpenCADStudio {
|
||||
use crate::command::KeywordCommand;
|
||||
let c = KeywordCommand::new(
|
||||
"ZOOM",
|
||||
"ZOOM [Window / Extents / Extents All / All / In / Out / Scale]:",
|
||||
"ZOOM [Window / Extents / Previous / Object / All / Dynamic / Extents All / In / Out / Scale]:",
|
||||
vec![
|
||||
("Window", "WINDOW", None),
|
||||
("Extents", "EXTENTS", None),
|
||||
("Extents All", "EXTENTS ALL", None),
|
||||
("All", "ALL", None),
|
||||
("In", "IN", None),
|
||||
("Window", "W", None),
|
||||
("Extents", "E", None),
|
||||
("Previous", "P", None),
|
||||
("Object", "O", None),
|
||||
("All", "A", None),
|
||||
("Dynamic", "D", None),
|
||||
("Extents All", "EA", None),
|
||||
("In", "I", None),
|
||||
("Out", "OUT", None),
|
||||
("Scale", "SCALE", Some("ZOOM scale factor (e.g. 2 or 0.5):")),
|
||||
("Scale", "S", Some("ZOOM scale factor (e.g. 2 or 0.5):")),
|
||||
],
|
||||
);
|
||||
self.command_line.push_info(&c.prompt());
|
||||
|
||||
@@ -98,6 +98,7 @@ impl OpenCADStudio {
|
||||
// command arms below re-enable the selected one).
|
||||
self.tabs[i].pan_mode = false;
|
||||
self.tabs[i].orbit_mode = false;
|
||||
self.tabs[i].zoom_dynamic_mode = false;
|
||||
// Reset the last committed point so the first click of the new command
|
||||
// is not constrained by ortho/polar relative to a previous command's endpoint.
|
||||
self.last_point = None;
|
||||
@@ -445,6 +446,8 @@ inventory::submit!(crate::command::CommandRegistration {
|
||||
"FITSPLINE",
|
||||
// System variables (typeable directly).
|
||||
"MIRRTEXT",
|
||||
"ZOOMWHEEL",
|
||||
"ZOOMFACTOR",
|
||||
"ATTREQ",
|
||||
"ATTDIA",
|
||||
"DIMASSOC",
|
||||
|
||||
@@ -866,6 +866,8 @@ impl OpenCADStudio {
|
||||
cmd if matches!(
|
||||
cmd.split_whitespace().next().unwrap_or(""),
|
||||
"MIRRTEXT"
|
||||
| "ZOOMWHEEL"
|
||||
| "ZOOMFACTOR"
|
||||
| "TEXTFILL"
|
||||
| "ATTREQ"
|
||||
| "ATTDIA"
|
||||
@@ -936,7 +938,7 @@ impl OpenCADStudio {
|
||||
let value = it.next().map(|s| s.trim().to_string());
|
||||
if name.is_empty() || name == "?" {
|
||||
self.command_line.push_info(
|
||||
"SETVAR: LTSCALE CELTSCALE PDMODE PDSIZE TEXTSIZE ORTHOMODE FILLMODE MIRRTEXT ATTREQ ATTDIA DIMASSOC ANGBASE ANGDIR | CLAYER CELTYPE TEXTSTYLE (read-only)",
|
||||
"SETVAR: LTSCALE CELTSCALE PDMODE PDSIZE TEXTSIZE ORTHOMODE FILLMODE MIRRTEXT ZOOMWHEEL ZOOMFACTOR ATTREQ ATTDIA DIMASSOC ANGBASE ANGDIR | CLAYER CELTYPE TEXTSTYLE (read-only)",
|
||||
);
|
||||
} else {
|
||||
// Parse a boolean given as 0/1 or ON/OFF.
|
||||
@@ -1028,6 +1030,37 @@ impl OpenCADStudio {
|
||||
.ok_or_else(|| "SETVAR: 0 or 1 required.".into()),
|
||||
None => Ok((format!("MIRRTEXT = {}", h.mirror_text as i32), false)),
|
||||
},
|
||||
"ZOOMWHEEL" => match &value {
|
||||
Some(v) => match parse_bool(v) {
|
||||
Some(reversed) => {
|
||||
self.zoom_wheel_reversed = reversed;
|
||||
Ok((
|
||||
format!("ZOOMWHEEL = {}", reversed as i32),
|
||||
true,
|
||||
))
|
||||
}
|
||||
None => Err("SETVAR: 0 or 1 required.".into()),
|
||||
},
|
||||
None => Ok((
|
||||
format!(
|
||||
"ZOOMWHEEL = {}",
|
||||
self.zoom_wheel_reversed as i32
|
||||
),
|
||||
false,
|
||||
)),
|
||||
},
|
||||
"ZOOMFACTOR" => match &value {
|
||||
Some(v) => match v.parse::<i32>() {
|
||||
Ok(factor) if (3..=100).contains(&factor) => {
|
||||
self.zoom_factor = factor;
|
||||
Ok((format!("ZOOMFACTOR = {factor}"), true))
|
||||
}
|
||||
_ => Err("SETVAR: integer from 3 to 100 required.".into()),
|
||||
},
|
||||
None => {
|
||||
Ok((format!("ZOOMFACTOR = {}", self.zoom_factor), false))
|
||||
}
|
||||
},
|
||||
// Global (not stored in the drawing): fill vs. hollow
|
||||
// TrueType text. The active tab re-tessellates below.
|
||||
"TEXTFILL" => match &value {
|
||||
@@ -1579,7 +1612,11 @@ impl OpenCADStudio {
|
||||
match outcome {
|
||||
Ok((msg, changed)) => {
|
||||
if changed {
|
||||
self.tabs[i].dirty = true;
|
||||
if matches!(name.as_str(), "ZOOMWHEEL" | "ZOOMFACTOR") {
|
||||
self.persist_settings_if_changed();
|
||||
} else {
|
||||
self.tabs[i].dirty = true;
|
||||
}
|
||||
self.command_line.push_output(&msg);
|
||||
} else {
|
||||
// Queried with no value (`changed == false`):
|
||||
|
||||
Reference in new issue
Block a user