From bb390cad5835afd3fb786ca17a62e8a0bfe62f0d Mon Sep 17 00:00:00 2001 From: Hakan Seven Date: Fri, 25 Sep 2026 15:18:33 +0300 Subject: [PATCH] fix(vpclip): drop the new boundary when the clip is refused; translate prompts Review of #1485: VPCLIP added the polygon it drew to the drawing before checking its area, so a boundary with no usable area was refused but left behind as a stray object. It is erased again. The VPCLIP prompts and messages go through t! like the rest of mview.rs. Co-Authored-By: Claude Opus 5.5 --- src/app/command_driver/viewport.rs | 8 +++++++- src/modules/layout/mview.rs | 24 ++++++++++++++---------- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/app/command_driver/viewport.rs b/src/app/command_driver/viewport.rs index 327d1256b..35ceafa46 100644 --- a/src/app/command_driver/viewport.rs +++ b/src/app/command_driver/viewport.rs @@ -74,13 +74,15 @@ impl OpenCADStudio { _ => false, }); if !closed { - self.command_line.push_error("Object is not a closed curve."); + self.command_line + .push_error(crate::t!("Object is not a closed curve.").as_ref()); return; } } self.push_undo_snapshot(i, "VPCLIP"); let old = vp.clip_boundary_handle; let scene = &mut self.tabs[i].scene; + let created = boundary.is_some(); let clip = match boundary { Some(entity) => scene.add_entity(entity), None => boundary_handle, @@ -93,6 +95,10 @@ impl OpenCADStudio { .map(|(lo, hi)| (glam::DVec2::from(lo), glam::DVec2::from(hi))) .unwrap_or((glam::DVec2::ZERO, glam::DVec2::ZERO)); if hi.x - lo.x < 1e-6 || hi.y - lo.y < 1e-6 { + // The polygon drawn for this clip must not stay behind. + if created { + scene.erase_entities(&[clip]); + } self.command_line .push_error(crate::t!("MVIEW: the clipping boundary has no usable area.").as_ref()); return; diff --git a/src/modules/layout/mview.rs b/src/modules/layout/mview.rs index e752d2574..e9c6aa396 100644 --- a/src/modules/layout/mview.rs +++ b/src/modules/layout/mview.rs @@ -233,11 +233,15 @@ impl MviewCommand { if self.chord_step() { let default = format!("{:.4}", self.tangent_degrees()); let default = default.trim_end_matches('0').trim_end_matches('.'); - return Some(format!( - "Specify direction of chord for arc (hold Ctrl to switch direction) <{default}>:" - )); + return Some( + t!( + "Specify direction of chord for arc (hold Ctrl to switch direction) <%{default}>:", + default = default + ) + .into_owned(), + ); } - Some(match self.arc_sub { + Some(t!(match self.arc_sub { Sub::ArcCenterAngle { .. } => "Specify included angle (hold Ctrl to switch direction):", Sub::ArcAngle | Sub::ArcRadiusAngle { .. } => "Specify included angle:", Sub::ArcAngleEnd { .. } => "Specify endpoint of arc (hold Ctrl to switch direction) or [CEnter/Radius]:", @@ -251,8 +255,8 @@ impl MviewCommand { Sub::ArcSecond => "Specify second point on arc:", Sub::ArcSecondEnd { .. } => "Specify end point of arc:", _ => return None, - } - .to_string()) + }) + .into_owned()) } fn clip_text(&mut self, upper: &str) -> Option { @@ -535,7 +539,7 @@ impl CadCommand for MviewCommand { } } if self.clip.is_some() { - return match self.step { + return t!(match self.step { Step::ClipSelect => "Select viewport to clip:", Step::ClipChoice => "Select clipping object or [Polygonal] :", Step::ClipLength => "Specify length of line:", @@ -545,8 +549,8 @@ impl CadCommand for MviewCommand { } Step::Polygon if self.polygon.len() < 3 => "Specify next point or [Arc/Length/Undo]:", _ => "Specify next point or [Arc/Close/Length/Undo]:", - } - .to_string(); + }) + .into_owned(); } match self.step { Step::RectangleFirst => t!( @@ -799,7 +803,7 @@ impl CadCommand for MviewCommand { self.step = Step::ClipChoice; CmdResult::NeedPoint } - _ => CmdResult::ReportError("Object selected was not a viewport\n.".to_string()), + _ => CmdResult::ReportError(t!("Object selected was not a viewport\n.").into_owned()), }; } CmdResult::MviewCreateClipped {