forked from 1b-agent/opencadstudio-upstream
feat(input): scalar entry via dynamic input
Text-input steps (OFFSET distance, POLYGON sides, radii, counts) were swallowed by the dynamic-input overlay: typed digits landed in the field buffer and Enter committed a point pick, so the value never reached on_text_input (issue #61). Now each text step shows one scalar box whose value routes to on_text_input on commit; non-numeric prompts (names, keywords) keep going to the command line so mixed text like "Bolt12" isn't split. OFFSET reworked: object first, then through-mode by default — the offset follows the cursor at the perpendicular distance to the object. Typing a number locks the magnitude (cursor then only picks the side); a value typed and clicked without Enter is applied before the point pick. The dynamic-input overlay and the command line now show the active step's prompt and hold it until the step completes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
1 parent
c9c6e45793
commit
4b878b88c4
15 files changed
+405
-70
No files matched your search
+34
-1
@@ -1188,10 +1188,15 @@ pub struct DynBox {
|
||||
pub locked: bool,
|
||||
}
|
||||
|
||||
pub fn dynamic_input_overlay<'a>(cursor_screen: Point, boxes: Vec<DynBox>) -> Element<'a, Message> {
|
||||
pub fn dynamic_input_overlay<'a>(
|
||||
cursor_screen: Point,
|
||||
boxes: Vec<DynBox>,
|
||||
prompt: String,
|
||||
) -> Element<'a, Message> {
|
||||
canvas(DynInputCanvas {
|
||||
cursor_screen,
|
||||
boxes,
|
||||
prompt,
|
||||
})
|
||||
.width(Length::Fill)
|
||||
.height(Length::Fill)
|
||||
@@ -1201,6 +1206,9 @@ pub fn dynamic_input_overlay<'a>(cursor_screen: Point, boxes: Vec<DynBox>) -> El
|
||||
struct DynInputCanvas {
|
||||
cursor_screen: Point,
|
||||
boxes: Vec<DynBox>,
|
||||
/// The active command's current prompt — tells the user what this step
|
||||
/// is asking for, drawn just above the input boxes.
|
||||
prompt: String,
|
||||
}
|
||||
|
||||
impl canvas::Program<Message> for DynInputCanvas {
|
||||
@@ -1258,6 +1266,31 @@ impl canvas::Program<Message> for DynInputCanvas {
|
||||
by = (self.cursor_screen.y - BOX_H - 4.0).max(0.0);
|
||||
}
|
||||
|
||||
// Prompt line above the boxes — what this step wants right now.
|
||||
// Drawn on an opaque pill so the viewport behind it stays legible.
|
||||
if !self.prompt.is_empty() {
|
||||
let py = (by - BOX_H - 2.0).max(0.0);
|
||||
let pw = (self.prompt.len() as f32 * CHAR_W) + PAD * 2.0;
|
||||
let prect = canvas::Path::rectangle(
|
||||
Point { x: bx, y: py },
|
||||
Size { width: pw, height: BOX_H },
|
||||
);
|
||||
frame.fill(&prect, Color { r: 0.10, g: 0.10, b: 0.12, a: 1.0 });
|
||||
frame.stroke(
|
||||
&prect,
|
||||
canvas::Stroke::default()
|
||||
.with_color(Color { r: 0.35, g: 0.55, b: 0.90, a: 0.9 })
|
||||
.with_width(1.0),
|
||||
);
|
||||
frame.fill_text(canvas::Text {
|
||||
content: self.prompt.clone(),
|
||||
position: Point { x: bx + PAD, y: py + PAD },
|
||||
color: Color { r: 0.70, g: 0.85, b: 0.70, a: 1.0 },
|
||||
size: iced::Pixels(FONT_SIZE),
|
||||
..Default::default()
|
||||
});
|
||||
}
|
||||
|
||||
let mut x = bx;
|
||||
for (i, b) in self.boxes.iter().enumerate() {
|
||||
let w = widths[i];
|
||||
|
||||
Reference in new issue
Block a user