test(ui): true docs and no dead code after the review of the routing

Found in review. No change in behaviour.

- The guard's `PAGE_HIT_CALLS` refused nothing once `main`'s press-handler
  check went; it only failed when it was stale, so it goes.
- The guard's notes said `canvas/image_pick.rs` uses none of the marks (it
  takes `PagePointer` now), that page modules read only
  `PagePointer::drag_started` (some ask for the primary button themselves),
  and left out the point tests that tell a tool a press began on its page.
- `content_ui`'s and the comments' notes said added text is its own with
  every tool, and that added content decides for itself.
- `object_ui`'s `!double_clicked()` can't fail (the page view re-routes
  that press), and Fill & Sign's preview recomputed `hovered`.
- `Capture` is private, and `top` is `canvas`'s.
- Test notes gave as history bugs that only this branch ever had.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
alehelandClaude Opus 5.5 committed 2026-11-04 19:37:47 +01:00
1 parent 8102109d19
commit a21f098049
8 files changed
+22 -51

No files matched your search

+2 -3
View File
@@ -168,7 +168,7 @@ pub(super) fn page_tool_input(ui: &mut egui::Ui, view: &mut DocView, frame: &mut
// page until its move ends; with no button down the Fill & Sign tool's preview hides where a
// press would be taken (a mark, its handles, a Prepare field).
let over_mark = matches!(tool, QuickTool::Fill(_))
&& (matches!(press, PagePress::Mine(_)) || comments::moving_on(view, i) || !ptr.any_down && top(under.iter().cloned(), tool).is_some());
&& (matches!(press, PagePress::Mine(_)) || comments::moving_on(view, i) || !ptr.any_down && hovered.is_some());
tool_input(ui, view, frame, slot, &pcx, press, over_mark);
let on_field = if preparing {
let o = crate::prepare::page_input(cx, form, field_tool, prepare_allowed, press, view);
@@ -241,8 +241,7 @@ pub(super) fn page_tool_input(ui: &mut egui::Ui, view: &mut DocView, frame: &mut
}
// Comments, every frame: their own presses, a commenting tool's, and a click elsewhere that
// leaves them unselected. A press nobody holds that another tool took this frame (Prepare's
// selection rectangle, added content, which still decide for themselves) is not also a
// commenting tool's, as before.
// selection rectangle, added content) is not also a commenting tool's, as before.
let taken = on_objects || on_edit_text || on_link || on_content || boxing || on_field;
let on_comment = comments::page_input(ui, resp, &pcx, press, taken, view);
let consumed = taken || on_comment;
@@ -207,7 +207,7 @@ const PAGE_MODULES: [&str; 37] = [
/// What a file that acts on the pages uses: the pointer, a tool's or the comments' page context,
/// what a press is to a page, the router's hits and owners, or the router itself. Such a file is a
/// page module. One that acts on the pages through the page view's response and a bare point alone
/// uses none of them (`canvas/image_pick.rs`): PAGE_MODULES lists it by hand.
/// would use none of them, and PAGE_MODULES would list it by hand.
const PAGE_MODULE_MARKS: [&str; 6] = ["PagePointer", "PageToolContext", "PageCx", "PagePress", "page_router::", ".router."];
/// The router's own files, which define what page modules use.
@@ -276,7 +276,8 @@ fn declares(line: &str) -> Option<&str> {
}
/// egui's drag start, which counts every button: a right-button drag would start what a left one
/// does. Page modules read `PagePointer::drag_started`, the primary button's.
/// does. Page modules read `PagePointer::drag_started`, the primary button's, or ask for that button
/// (`drag_started_by`).
const ANY_BUTTON_DRAG: [&str; 1] = [".drag_started()"];
/// Functions in the page modules that start a drag of a widget of their own, not of the pages:
@@ -550,11 +551,11 @@ fn hit_test_calls(line: &str) -> Vec<String> {
/// The functions that call a hit test: (file, function, why). Hit tests are found by name (a
/// function named `hit` or `…_hit`, called by path, bare or as a method). The comments' point test
/// has a list of its own (`COMMENT_POINT_TESTERS`). Point tests by other names are not seen: what is
/// left of them paints (a picture's hover outline) or keeps a behaviour no hit stands for (added
/// text's click with the tools that don't pick it up, crop mode's controls). `PageHits::hits` is the
/// one: the hits
/// at the press point decide its owner, and those under the pointer give its cursor, its tip, hover
/// painting and a right-click.
/// left of them paints (a picture's hover outline), keeps a behaviour no hit stands for (added
/// text's click with the tools that don't pick it up, crop mode's controls) or tells a tool that a
/// press nobody holds began on its page (the text layer's `press_here`, redaction's). `PageHits::hits`
/// is the one: the hits at the press point decide its owner, and those under the pointer give its
/// cursor, its tip, hover painting and a right-click.
const HIT_TESTERS: [(&str, &str, &str); 1] = [(
"canvas/page_input.rs",
"hits",
@@ -633,24 +634,6 @@ const PRESS_IGNORES: [&str; 1] = ["press_cancelled = true"];
const PRESS_IGNORERS: [(&str, &str, &str); 1] =
[("canvas/page_input.rs", "cancel_on_escape", "Escape abandons the gesture the press drives, whichever tool's")];
/// The module hit tests, called by path (HIT_TESTERS says who may): an entry no page module calls
/// any more fails the test.
const PAGE_HIT_CALLS: [&str; 13] = [
"link_ui::hit(",
"prepare::hit(",
"forms_ui::hit(",
"comments::hit(",
"comments::context_hit(",
"camera_ui::hit(",
"edit_text_ui::hit(",
"edit_text_ui::picture_hit(",
"edit_text_ui::picture_handle_hit(",
"edit_text_ui::crop_hit(",
"object_ui::hit(",
"object_ui::modified_hit(",
"content_ui::hit(",
];
/// Page modules act on a press only when the router says it is theirs. The hits at the press
/// point decide its owner once, in one place, and a `Hit` comes only from a module's hit test,
/// so what the cursor promised is what the press does. Where each module tested the press
@@ -742,14 +725,6 @@ fn page_modules_act_on_a_press_only_through_the_router() {
"calls no hit test any more: remove it from HIT_TESTERS.",
));
problems.extend(hit_test_aliases());
// An entry no page module calls any more no longer guards anything.
let called = page_module_uses(&PAGE_HIT_CALLS);
problems.extend(
PAGE_HIT_CALLS
.iter()
.filter(|call| !called.iter().any(|(_, _, _, name)| name == *call))
.map(|call| format!("no page module calls `{call}` any more: remove it from PAGE_HIT_CALLS.")),
);
let builds = page_module_uses(&HIT_BUILDS);
assert!(!builds.is_empty(), "no page module makes a `Hit` any more: update HIT_BUILDS");
problems.extend(builds.into_iter().filter(|(_, function, _, _)| !function.as_deref().is_some_and(is_hit_test)).map(|(file, _, n, name)| {
+2 -2
View File
@@ -135,7 +135,7 @@ impl Hit {
/// The hit that wins among `hits` with `tool`: the highest layer the tool reaches, the last of
/// equals (modules are asked bottom up, in paint order).
pub(crate) fn top(hits: impl IntoIterator<Item = Hit>, tool: QuickTool) -> Option<Hit> {
pub(in crate::canvas) fn top(hits: impl IntoIterator<Item = Hit>, tool: QuickTool) -> Option<Hit> {
hits.into_iter().filter(|h| h.layer.reached_by(tool)).fold(None, |best: Option<Hit>, h| match best {
Some(b) if b.layer > h.layer => Some(b),
_ => Some(h),
@@ -172,7 +172,7 @@ impl PagePress {
/// A press the pages hold, and who it belongs to.
#[derive(Clone, Debug, PartialEq)]
pub(crate) struct Capture {
struct Capture {
pub owner: Owner,
pub declines_drag: bool,
}
+2 -2
View File
@@ -12,8 +12,8 @@ use crate::page_router::{CommentPart, Hit, Owner, PagePress};
/// the press the pages hold: a press on a comment where the tool reaches it ([`hit`]: the Select
/// tool, Fill & Sign over its marks, a shape tool over the selected shape's handles) is that
/// comment's, and one nobody holds is a commenting tool's. When another tool took this frame
/// (`taken`: Prepare, added content, which still decide for themselves), the commenting tools leave
/// it to that tool, as before; the Select tool's click there still unselects. Returns `true` when
/// (`taken`: Prepare, added content), the commenting tools leave it to that tool, as before; the
/// Select tool's click there still unselects. Returns `true` when
/// the pointer gesture belongs to commenting (text selection must ignore it).
pub(crate) fn page_input(ui: &egui::Ui, resp: &egui::Response, cx: &PageCx<'_>, press: PagePress, taken: bool, view: &mut DocView) -> bool {
let (pointer, origin) = (cx.ptr.pos, cx.ptr.origin);
+1 -1
View File
@@ -385,7 +385,7 @@ pub(crate) fn hit(xf: &PageXform, info: &DocInfo, page: usize, added: &[Added],
pub(crate) struct ContentCx<'a> {
pub added: &'a [Added],
/// What the press the pages hold is to this page. With the Edit panel open, a press on added
/// text is its own with every tool ([`hit`]).
/// text is its own with the tools that pick it up ([`hit`]).
pub press: PagePress,
/// Edit text's input is open: no dialog, palette, other window or other tab has it.
pub gate: bool,
+1 -1
View File
@@ -375,7 +375,7 @@ fn input(s: &mut ObjectSelection, cx: PageToolContext<'_>, press: PagePress, vie
return true;
}
// The selection moves.
PagePress::Mine(Owner::Objects { part: ObjectsPart::Selection }) if !resp.double_clicked() => {
PagePress::Mine(Owner::Objects { part: ObjectsPart::Selection }) => {
s.gesture = Some(Gesture { start: p, now: p, marquee: false, additive: false });
return true;
}
+5 -8
View File
@@ -7337,7 +7337,7 @@ fn a_right_click_on_text_over_a_picture_selects_the_picture() {
}
/// With Edit text, a right-click on added text over a picture is the picture's, which is selected
/// for its menu: added text has no menu of its own. It unselected the picture and opened the page's.
/// for its menu: added text has no menu of its own.
#[test]
fn a_right_click_on_added_text_over_a_picture_selects_the_picture() {
let mut h = picture_pages(false);
@@ -7355,7 +7355,7 @@ fn a_right_click_on_added_text_over_a_picture_selects_the_picture() {
}
/// With Edit text, a right-click on the frame of a paragraph open for typing over a picture is the
/// picture's too. It unselected the picture and opened the page's menu.
/// picture's too.
#[test]
fn a_right_click_on_an_open_paragraphs_frame_over_a_picture_selects_the_picture() {
let mut h = picture_pages(false);
@@ -7594,8 +7594,7 @@ fn in_crop_mode_a_right_click_on_another_picture_selects_it() {
}
/// A drag from a hole in the selected picture (drawn through a clip with a hole in it) moves the
/// picture: its frame is its own. The press fell through the hole, started an area selection and
/// unselected it.
/// picture: its frame is its own.
#[test]
fn a_drag_from_a_hole_in_the_selected_picture_moves_it() {
// The picture shows at x 30..160, y 170..250, around a hole at x 70..120, y 190..230.
@@ -7618,8 +7617,7 @@ fn a_drag_from_a_hole_in_the_selected_picture_moves_it() {
}
/// A right-click on a crop grip past the page's edge, where those of a picture filling its page lie
/// half, is the crop's, as on the page: crop mode stays and no menu opens (#5835). No page took it,
/// which left crop mode.
/// half, is the crop's, as on the page: crop mode stays and no menu opens (#5835).
#[test]
fn a_right_click_on_a_crop_grip_past_the_page_edge_keeps_crop_mode() {
let mut png = Vec::new();
@@ -7648,8 +7646,7 @@ fn a_right_click_on_a_crop_grip_past_the_page_edge_keeps_crop_mode() {
}
/// Crop mode's grips reach past the page's edge, where those of a picture filling its page lie
/// half: a drag from just outside the page's corner trims the picture. Only the half on the page took
/// the press.
/// half: a drag from just outside the page's corner trims the picture.
#[test]
fn a_crop_grip_past_the_page_edge_drags() {
let mut png = Vec::new();
+1 -1
View File
@@ -440,7 +440,7 @@ fn a_press_just_outside_a_picture_starts_an_area_selection() {
}
/// A double-click on one of the objects selected together leaves the group and reaches that one:
/// added text opens for typing. The double-click only left the group.
/// added text opens for typing.
#[test]
fn a_double_click_on_a_grouped_object_reaches_it() {
let mut h = harness();