diff --git a/src/app/commands/dim.rs b/src/app/commands/dim.rs index 32ea43324..1f86f876d 100644 --- a/src/app/commands/dim.rs +++ b/src/app/commands/dim.rs @@ -920,30 +920,7 @@ impl OpenCADStudio { self.tabs[i].active_cmd = Some(Box::new(cmd)); } - // Bare ZOOM prompts with the mode options as clickable keywords; - // the sub-keyword forms (ZOOM EXTENTS / WINDOW / …) run directly. - "ZOOM" => { - use crate::command::KeywordCommand; - let c = KeywordCommand::new( - "ZOOM", - "ZOOM [Window / Extents / Previous / Object / All / Dynamic / Extents All / In / Out / Scale]:", - vec![ - ("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", "S", Some("ZOOM scale factor (e.g. 2 or 0.5):")), - ], - ); - self.command_line.push_info(&c.prompt()); - self.tabs[i].active_cmd = Some(Box::new(c)); - } - "ZOOM WINDOW" | "ZOOM W" | "ZW" => { + "ZOOM" | "ZOOM WINDOW" | "ZOOM W" | "ZW" => { use crate::modules::view::zoom_window::ZoomWindowCommand; let new_cmd = ZoomWindowCommand::new(); self.command_line.push_info(&new_cmd.prompt()); diff --git a/src/modules/view/zoom_window.rs b/src/modules/view/zoom_window.rs index fe24a7c16..76a7a09be 100644 --- a/src/modules/view/zoom_window.rs +++ b/src/modules/view/zoom_window.rs @@ -3,7 +3,7 @@ use glam::{DVec3, Vec3}; use crate::t; -use crate::command::{CadCommand, CmdResult}; +use crate::command::{CadCommand, CmdOption, CmdResult}; use crate::modules::{IconKind, ModuleEvent, ToolDef}; use crate::scene::model::wire_model::WireModel; @@ -22,11 +22,15 @@ pub fn tool() -> ToolDef { pub struct ZoomWindowCommand { first: Option, + scale_prompt: bool, } impl ZoomWindowCommand { pub fn new() -> Self { - Self { first: None } + Self { + first: None, + scale_prompt: false, + } } } @@ -36,14 +40,73 @@ impl CadCommand for ZoomWindowCommand { } fn prompt(&self) -> String { - if self.first.is_none() { + if self.scale_prompt { + t!("ZOOM scale factor (e.g. 2 or 0.5):").into_owned() + } else if self.first.is_none() { t!("ZOOM WINDOW Specify first corner:").into_owned() } else { t!("ZOOM WINDOW Specify opposite corner:").into_owned() } } - fn on_point(&mut self, pt: DVec3) -> CmdResult { let pt = pt.as_vec3(); + fn options(&self) -> Vec { + if self.first.is_some() || self.scale_prompt { + return Vec::new(); + } + vec![ + CmdOption::new("Window", "W"), + CmdOption::new("Extents", "E"), + CmdOption::new("Previous", "P"), + CmdOption::new("Object", "O"), + CmdOption::new("All", "A"), + CmdOption::new("Dynamic", "D"), + CmdOption::new("Extents All", "EA"), + CmdOption::new("In", "I"), + CmdOption::new("Out", "OUT"), + CmdOption::new("Scale", "S"), + ] + } + + fn wants_text_input(&self) -> bool { + true + } + + fn on_text_input(&mut self, text: &str) -> Option { + let text = text.trim(); + if text.is_empty() { + return None; + } + if self.scale_prompt { + return Some(CmdResult::Dispatch(format!("ZOOM SCALE {text}"))); + } + let command = match text.to_uppercase().as_str() { + "W" | "WINDOW" => { + self.first = None; + return Some(CmdResult::NeedPoint); + } + "E" | "EXTENTS" => "ZOOM EXTENTS", + "P" | "PREVIOUS" => "ZOOM PREVIOUS", + "O" | "OBJECT" => "ZOOM OBJECT", + "A" | "ALL" => "ZOOM ALL", + "D" | "DYNAMIC" => "ZOOM DYNAMIC", + "EA" | "EXTENTS ALL" => "ZOOM EXTENTS ALL", + "I" | "IN" => "ZOOM IN", + "OUT" => "ZOOM OUT", + "S" | "SCALE" => { + self.first = None; + self.scale_prompt = true; + return Some(CmdResult::NeedPoint); + } + _ => return None, + }; + Some(CmdResult::Dispatch(command.to_string())) + } + + fn on_point(&mut self, pt: DVec3) -> CmdResult { + if self.scale_prompt { + return CmdResult::NeedPoint; + } + let pt = pt.as_vec3(); if let Some(p1) = self.first { CmdResult::ZoomToWindow { p1: p1.as_dvec3(), p2: pt.as_dvec3() } } else {