From 4c60dce81a917f014ef18f8e975571160de7d92a Mon Sep 17 00:00:00 2001 From: Hakan Seven Date: Thu, 28 May 2026 22:59:48 +0300 Subject: [PATCH] fix(cmd): refresh rubber-band preview after typed point (#32) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Typing a coordinate (e.g. \`25\`\\TAB\`45\` for polar input) and pressing Enter committed the point through \`on_point\` but never re-ran the preview hook. The mouse-move pipeline that normally publishes the rubber-band segment from the latest \`last_point\` didn't fire — no mouse motion occurred — so the active blue segment kept dangling from the *previous* point until the user nudged the mouse. Add \`refresh_active_cmd_preview\` and call it after the keyboard point commits (both the command-line path and the dynamic-input locked-field path) so the next segment starts from the just-committed point immediately. Closes #32 Co-Authored-By: Claude Opus 4.7 --- src/app/update.rs | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/src/app/update.rs b/src/app/update.rs index cd059edfa..545584746 100644 --- a/src/app/update.rs +++ b/src/app/update.rs @@ -1085,7 +1085,16 @@ impl OpenCADStudio { self.last_point = Some(wcs_pt); let result = self.tabs[i].active_cmd.as_mut().map(|c| c.on_point(wcs_pt)); if let Some(r) = result { - return self.apply_cmd_result(r); + let task = self.apply_cmd_result(r); + // The rubber-band preview that the command + // last published reflects the *previous* + // last_point — a typed coordinate doesn't + // fire a mouse-move, so re-run the preview + // hook now using the current cursor world + // pos so the next segment immediately starts + // from the just-committed point. See #32. + self.refresh_active_cmd_preview(i); + return task; } return Task::none(); } @@ -5377,6 +5386,25 @@ impl OpenCADStudio { } } + /// Re-run the active command's preview hook against the current + /// cursor world position. Keyboard-driven point commits (typed + /// coordinates in the command line or dynamic input) don't fire a + /// mouse-move event, so without this the rubber-band preview keeps + /// dangling from the previous `last_point` until the user actually + /// moves the mouse. See #32. + fn refresh_active_cmd_preview(&mut self, i: usize) { + if self.tabs[i].active_cmd.is_none() { + return; + } + let cur = self.tabs[i].last_cursor_world; + let previews = self.tabs[i] + .active_cmd + .as_mut() + .map(|c| c.on_preview_wires(cur)) + .unwrap_or_default(); + self.tabs[i].scene.set_preview_wires(previews); + } + /// Resolve the world point implied by the current dynamic-input field /// values. Locked fields use their typed buffer; the rest fall back to /// the live cursor-derived value. Returns `None` when the field set @@ -5451,7 +5479,13 @@ impl OpenCADStudio { f.buffer = None; } self.tabs[i].dyn_active = 0; - result.map(|r| self.apply_cmd_result(r)) + let task = result.map(|r| self.apply_cmd_result(r))?; + // Match the command-line path: refresh the rubber-band preview + // so the next segment immediately starts from the new + // last_point even though no mouse-move fires after a typed + // coordinate. See #32. + self.refresh_active_cmd_preview(i); + Some(task) } /// Populate all edit buffers from the currently selected dim style.