feat(dyn): locked input fields constrain the preview and the click (#356)
A typed dynamic-input value (TAB-locked angle or distance) now shapes the rubber-band: the cursor point is routed through dyn_resolve_point — the same resolution Enter commits — in the mouse-move preview and the click commit, so a locked 30° pins the line's direction while the free field keeps tracking the cursor. The lock wins over osnap/ortho/polar. TAB (and the comma advance) reshape the preview immediately instead of waiting for the next mouse move. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
3dd27c6789
commit
7a93ba82b3
4 changed files with 39 additions and 0 deletions
|
|
@ -83,6 +83,7 @@ pub(super) fn on_tab_close(&mut self, idx: usize) -> Task<Message> {
|
||||||
if s == "," && self.dyn_input && !self.tabs[i].dyn_fields.is_empty() {
|
if s == "," && self.dyn_input && !self.tabs[i].dyn_fields.is_empty() {
|
||||||
self.dyn_comma_advance();
|
self.dyn_comma_advance();
|
||||||
self.command_line.autocomplete_cursor = None;
|
self.command_line.autocomplete_cursor = None;
|
||||||
|
self.refresh_active_cmd_preview(i);
|
||||||
return self.focus_cmd_input();
|
return self.focus_cmd_input();
|
||||||
}
|
}
|
||||||
// While dynamic input is showing fields, numeric and
|
// While dynamic input is showing fields, numeric and
|
||||||
|
|
|
||||||
|
|
@ -581,6 +581,15 @@ impl OpenCADStudio {
|
||||||
if self.tabs[i].active_cmd.is_none() {
|
if self.tabs[i].active_cmd.is_none() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// Re-resolve through the locked dyn fields first so a freshly typed
|
||||||
|
// value reshapes the preview immediately, without waiting for the
|
||||||
|
// next mouse move (#356). Idempotent for the polar/cartesian arms, so
|
||||||
|
// feeding the already-resolved cursor back in is stable.
|
||||||
|
if self.tabs[i].dyn_fields.iter().any(|f| f.buffer.is_some()) {
|
||||||
|
if let Some(r) = self.dyn_resolve_point() {
|
||||||
|
self.tabs[i].last_cursor_world = r;
|
||||||
|
}
|
||||||
|
}
|
||||||
let cur = self.tabs[i].last_cursor_world;
|
let cur = self.tabs[i].last_cursor_world;
|
||||||
let previews = self.tabs[i]
|
let previews = self.tabs[i]
|
||||||
.active_cmd
|
.active_cmd
|
||||||
|
|
|
||||||
|
|
@ -799,6 +799,9 @@ impl OpenCADStudio {
|
||||||
let n = self.tabs[i].dyn_fields.len();
|
let n = self.tabs[i].dyn_fields.len();
|
||||||
if n > 0 {
|
if n > 0 {
|
||||||
self.tabs[i].dyn_active = (self.tabs[i].dyn_active + 1) % n;
|
self.tabs[i].dyn_active = (self.tabs[i].dyn_active + 1) % n;
|
||||||
|
// TAB locks the value just typed — reshape the rubber-band
|
||||||
|
// to the constrained point now (#356).
|
||||||
|
self.refresh_active_cmd_preview(i);
|
||||||
}
|
}
|
||||||
self.focus_cmd_input()
|
self.focus_cmd_input()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1060,6 +1060,21 @@ pub(super) fn on_tick(&mut self, t: Instant) -> Task<Message> {
|
||||||
}
|
}
|
||||||
pt
|
pt
|
||||||
};
|
};
|
||||||
|
// Dynamic-input locked fields constrain the preview point
|
||||||
|
// (#356): a typed angle pins the direction, a typed
|
||||||
|
// distance pins the radius — the same resolution the Enter
|
||||||
|
// commit uses, so preview and commit agree. The lock wins
|
||||||
|
// over osnap/ortho/polar.
|
||||||
|
let effective = {
|
||||||
|
let locked = self.tabs[i].active_cmd.is_some()
|
||||||
|
&& self.tabs[i].dyn_fields.iter().any(|f| f.buffer.is_some());
|
||||||
|
if locked {
|
||||||
|
self.tabs[i].last_cursor_world = effective;
|
||||||
|
self.dyn_resolve_point().unwrap_or(effective)
|
||||||
|
} else {
|
||||||
|
effective
|
||||||
|
}
|
||||||
|
};
|
||||||
self.tabs[i].last_cursor_world = effective;
|
self.tabs[i].last_cursor_world = effective;
|
||||||
self.tabs[i].last_cursor_screen = p_full;
|
self.tabs[i].last_cursor_screen = p_full;
|
||||||
// Project the step anchor (an explicit `dyn_anchor` or the
|
// Project the step anchor (an explicit `dyn_anchor` or the
|
||||||
|
|
@ -1970,6 +1985,17 @@ pub(super) fn on_tick(&mut self, t: Instant) -> Task<Message> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// A click while dynamic-input fields hold typed values
|
||||||
|
// commits the CONSTRAINED point — the same resolution
|
||||||
|
// the preview shows and Enter would commit (#356).
|
||||||
|
if self.tabs[i].active_cmd.is_some()
|
||||||
|
&& self.tabs[i].dyn_fields.iter().any(|f| f.buffer.is_some())
|
||||||
|
{
|
||||||
|
self.tabs[i].last_cursor_world = pt;
|
||||||
|
if let Some(r) = self.dyn_resolve_point() {
|
||||||
|
pt = r;
|
||||||
|
}
|
||||||
|
}
|
||||||
pt
|
pt
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue