Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/point-scan.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ Physical validation should include forward/reverse escape with a real switch, pa

## Actions at a point

Choosing a point opens a native grid beside its marker. The rows are Left click / Right click / Double click; Scroll / Drag / More; New point / Close menu. The shared tree navigator handles row/item selection and row escape. The menu uses the current automatic/manual mode and block interval. After three automatic passes, it retains the target and shows Select to resume. That Select resumes scanning without executing an action. After a scroll or media item the menu stays on that item and keeps scanning; After a selection and Start again from change this for menus.
Choosing a point opens a native grid beside its marker. The marker is a crosshair in the scan colour with a small gap at its centre, so the exact point stays visible; it stays on screen while choosing a drag destination, and arms that would leave the display are cut short at its edge. The rows are Left click / Right click / Double click; Scroll / Drag / More; New point / Close menu. The shared tree navigator handles row/item selection and row escape. The menu uses the current automatic/manual mode and block interval. After three automatic passes, it retains the target and shows Select to resume. That Select resumes scanning without executing an action. After a scroll or media item the menu stays on that item and keeps scanning; After a selection and Start again from change this for menus.

Scroll offers Up / Down, Left / Right, and Back to actions. Each selection moves the pointer to the target and sends three wheel steps; the selected direction remains available. Back restores the main menu's Scroll item. Choose another point immediately restarts the configured technique on the original display. Clicks and completed drags return to armed idle, unless After a selection is set to Keep scanning for point scanning.

Expand Down
86 changes: 76 additions & 10 deletions src-tauri/src/point_workflow.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Point selection policy, menu navigation and execution requests. No OS input.
use crate::{
point_scan::{Engine, PointSettings},
scan_menu::{outline, Item, Kind, Menu},
scan_menu::{Item, Kind, Menu},
scanning::{Action, Frame, FrameLabel, Rect, Technique, UpdateContext},
};
use serde::Serialize;
Expand Down Expand Up @@ -1369,15 +1369,9 @@ impl Technique for Workflow {
}
if matches!(self.stage, Stage::Menu | Stage::Destination) && !self.home_open() {
let s = self.point.units_per_logical_pixel;
frame.strips.extend(outline(
Rect {
x: self.source.0 as f64 - 5.0 * s,
y: self.source.1 as f64 - 5.0 * s,
width: 10.0 * s,
height: 10.0 * s,
},
2.0 * s,
));
frame
.strips
.extend(crosshair(self.source, self.point.screen, s));
if self.stage == Stage::Destination {
frame.label = Some(FrameLabel {
text: "Choose drag destination".into(),
Expand Down Expand Up @@ -1407,6 +1401,43 @@ impl Technique for Workflow {
frame
}
}
/// Four arms around a chosen point, leaving its centre clear so the exact spot
/// stays visible. Arms keep their full thickness on screen, as scan lines do, and
/// are cut short at its edges; one too short to draw is left out.
fn crosshair(point: Point, screen: Rect, s: f64) -> Vec<Rect> {
let (x, y) = (point.0 as f64, point.1 as f64);
let (gap, reach, t) = (4.0 * s, 16.0 * s, 2.0 * s);
let (right, bottom) = (screen.x + screen.width, screen.y + screen.height);
let across_x = (x - t / 2.0).clamp(screen.x, (right - t).max(screen.x));
let across_y = (y - t / 2.0).clamp(screen.y, (bottom - t).max(screen.y));
let horizontal = |from: f64, to: f64| {
let from = from.max(screen.x);
Rect {
x: from,
y: across_y,
width: to.min(right) - from,
height: t,
}
};
let vertical = |from: f64, to: f64| {
let from = from.max(screen.y);
Rect {
x: across_x,
y: from,
width: t,
height: to.min(bottom) - from,
}
};
[
horizontal(x - reach, x - gap),
horizontal(x + gap, x + reach),
vertical(y - reach, y - gap),
vertical(y + gap, y + reach),
]
.into_iter()
.filter(|arm| arm.valid())
.collect()
}

#[cfg(test)]
mod tests {
Expand Down Expand Up @@ -3152,6 +3183,41 @@ mod tests {
}
assert_eq!(s.technique.phase(), Phase::Workflow(WorkflowPhase::Menu));
}
#[test]
fn a_chosen_point_is_marked_by_a_crosshair_that_stays_on_screen() {
let mut s = session(false);
open(&mut s);
s.technique.source = (-500, 400);
let rect = |x, y, width, height| Rect {
x,
y,
width,
height,
};
// The menu draws no strips of its own, so these are the whole marker.
assert_eq!(
s.technique.frame().strips,
vec![
rect(-516.0, 399.0, 12.0, 2.0),
rect(-496.0, 399.0, 12.0, 2.0),
rect(-501.0, 384.0, 2.0, 12.0),
rect(-501.0, 404.0, 2.0, 12.0),
]
);
// At the top-left corner only the arms pointing into the screen are
// drawn, at full thickness along its edges.
s.technique.source = (-1000, 20);
assert_eq!(
s.technique.frame().strips,
vec![
rect(-996.0, 20.0, 12.0, 2.0),
rect(-1000.0, 24.0, 2.0, 12.0)
]
);
// Home marks no point.
s.technique.selected(Item::Home);
assert!(s.technique.frame().strips.is_empty());
}
fn choose(s: &mut Session<Workflow>, row: usize, column: usize) -> Option<Request> {
for _ in 0..row {
s.action(Action::Next);
Expand Down
16 changes: 0 additions & 16 deletions src-tauri/src/scan_menu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -256,22 +256,6 @@ impl Menu {
frame
}
}
pub fn outline(r: Rect, t: f64) -> [Rect; 4] {
[
Rect { height: t, ..r },
Rect {
y: r.y + r.height - t,
height: t,
..r
},
Rect { width: t, ..r },
Rect {
x: r.x + r.width - t,
width: t,
..r
},
]
}
fn place(point: (i32, i32), screen: Rect, width: f64, height: f64, gap: f64) -> Rect {
let (x, y) = (point.0 as f64, point.1 as f64);
let candidates = [
Expand Down
Loading