mirror of
https://github.com/storytold/wordcraft.git
synced 2026-10-24 10:27:44 -06:00
* test(engine): drop a needless drop() that clippy 1.97 rejects (drop_non_drop) * Comments: a click inside a selected balloon moves the caret in its text (#1013) - The canvas under the markup area also "contains" the pointer, so a press on the balloon counted as a click on the page and left it - Presses over a balloon card now belong to the card, in both the deselect check and the document click in mouse() - Test: press, drag and release inside the selected balloon; a click on the page still leaves it --------- Co-authored-by: Brandon Thomas <echelon@gmail.com>
This commit is contained in:
co-authored by
Brandon Thomas
parent
a4870128b5
commit
896c1bbebf
+3
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
**Stage: alpha** · next: beta, ~15 points (60% → 75% ready for real work) and ~150–230 h away
|
||||
|
||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-14 · **Change:** trivial (progress log: a press on the ribbon no longer scrolls the document, #1019; previously trivial: title rename and account settings; previously trivial: progress log: Down and Up no longer skip a table, #1007; previously trivial: progress log: privacy options on save, #1062; previously trivial: progress log: equation pictures in theme colours on Windows, #1002; previously trivial: symbol fonts, #776; previously trivial: the save prompt answers from the keyboard, #861; previously trivial: table column and row markers on the rulers, #700; previously trivial: table borders and the resize handle drag on the page, #217; previously trivial: formatting revisions landed, #41; previously trivial: Draw tab ink, #307, and Draw Table and Eraser, #303, landed: catalog 402/434; previously minor: readiness table with hours per audience; full number back to the additive weighted sum, 60%; mainstream and essentials numbers added; alpha gate checked; previously major: full re-measure against Word for Mac 16.113.4; restructured to the craftrules progress-docs standard) · **Target:** Microsoft Word (Microsoft 365) for Mac 16.113.4
|
||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-14 · **Change:** trivial (progress log: clicking in a comment's text moves its caret, #1013; previously trivial: progress log: a press on the ribbon no longer scrolls the document, #1019; previously trivial: title rename and account settings; previously trivial: progress log: Down and Up no longer skip a table, #1007; previously trivial: progress log: privacy options on save, #1062; previously trivial: progress log: equation pictures in theme colours on Windows, #1002; previously trivial: symbol fonts, #776; previously trivial: the save prompt answers from the keyboard, #861; previously trivial: table column and row markers on the rulers, #700; previously trivial: table borders and the resize handle drag on the page, #217; previously trivial: formatting revisions landed, #41; previously trivial: Draw tab ink, #307, and Draw Table and Eraser, #303, landed: catalog 402/434; previously minor: readiness table with hours per audience; full number back to the additive weighted sum, 60%; mainstream and essentials numbers added; alpha gate checked; previously major: full re-measure against Word for Mac 16.113.4; restructured to the craftrules progress-docs standard) · **Target:** Microsoft Word (Microsoft 365) for Mac 16.113.4
|
||||
|
||||
> **Printing update:** 2026-10-12 · direct desktop printing through craft-print; details below.
|
||||
|
||||
@@ -136,6 +136,7 @@ Ranked, to beta (detail and remaining milestones in [docs/roadmap.md](docs/roadm
|
||||
|
||||
| Date | What landed |
|
||||
|---|---|
|
||||
| 2026-10-12 | Clicking inside a selected comment's balloon moves the caret in its text (#1013); the click used to leave the balloon, so the caret could only be moved with the arrow keys. A press on any balloon now belongs to the balloon, not the page behind it |
|
||||
| 2026-10-12 | Page background pictures and textures (Design › Page Color › Fill Effects) are drawn (tiled or stretched) and kept on save instead of being dropped from the package (#999); PDF export paints them too |
|
||||
| 2026-10-12 | Holding a click on the ribbon or toolbar no longer scrolls the document up (#1019): a double-click in the header or footer area left a text drag running, so the next press anywhere drove the edge auto-scroll; a drag now ends with the button, wherever it's released |
|
||||
| 2026-10-12 | Tracked insertions and deletions inside a field result (a `=SUM(ABOVE)` subtotal) are kept as revisions: Accept All and Reject All act on them and a save writes the `w:del` back (#1037) |
|
||||
@@ -335,6 +336,7 @@ Ranked, to beta (detail and remaining milestones in [docs/roadmap.md](docs/roadm
|
||||
|
||||
| Date | Change | Summary |
|
||||
|---|---|---|
|
||||
| 2026-10-12 | trivial | Progress log: clicking in a comment's text moves its caret (#1013) |
|
||||
| 2026-10-12 | trivial | Progress log: a press on the ribbon no longer scrolls the document (#1019) |
|
||||
| 2026-10-12 | trivial | Progress log: Ctrl+drag copies an object (#1014) |
|
||||
| 2026-10-12 | trivial | Document title opens Rename Document; the account badge opens Options › General for user name and initials. |
|
||||
|
||||
@@ -1248,10 +1248,12 @@ pub fn show(app: &mut WordApp, ui: &mut Ui) {
|
||||
// the scroll area is built, so it reads last frame's viewport.
|
||||
app.canvas.viewport = Some(out.inner_rect);
|
||||
let (resp, rects) = out.inner;
|
||||
// A click on the page leaves the selected comment balloon; a click inside a balloon (its
|
||||
// Delete or Resolve button, say) does not (#1085).
|
||||
let in_balloon = ui.input(|i| i.pointer.interact_pos()).is_some_and(|p| app.canvas.balloon_rects.iter().any(|(_, r)| r.contains(p)));
|
||||
if app.canvas.balloon.is_some() && ui.input(|i| i.pointer.any_pressed()) && resp.contains_pointer() && !in_balloon {
|
||||
// A click on the page leaves the selected comment balloon.
|
||||
if app.canvas.balloon.is_some()
|
||||
&& ui.input(|i| i.pointer.any_pressed())
|
||||
&& resp.contains_pointer()
|
||||
&& !ui.input(|i| i.pointer.latest_pos()).is_some_and(|p| over_balloon(app, p))
|
||||
{
|
||||
deselect_balloon(app, ui.ctx());
|
||||
}
|
||||
// Space and Enter also set `Response::clicked` on a focused click-sensing widget
|
||||
@@ -1710,6 +1712,11 @@ pub fn select_balloon(app: &mut WordApp, ctx: &egui::Context, id: u32) {
|
||||
app.canvas.balloon_h = 0.0;
|
||||
}
|
||||
|
||||
/// A press over a balloon card belongs to the card, though the canvas under it also contains the pointer (#1013).
|
||||
fn over_balloon(app: &WordApp, p: Pos2) -> bool {
|
||||
app.canvas.balloon_rects.iter().any(|(_, r)| r.contains(p))
|
||||
}
|
||||
|
||||
/// Leave the selected balloon, writing back what was typed in it (its fields may not be drawn
|
||||
/// again to notice they lost focus).
|
||||
pub fn deselect_balloon(app: &mut WordApp, ctx: &egui::Context) {
|
||||
@@ -1888,7 +1895,7 @@ fn mouse(app: &mut WordApp, ui: &Ui, resp: &egui::Response, rects: &[Rect], layo
|
||||
let _ = app.run("select.paragraph", json!({}));
|
||||
return;
|
||||
}
|
||||
let pressed = ui.input(|i| i.pointer.primary_pressed()) && resp.contains_pointer();
|
||||
let pressed = ui.input(|i| i.pointer.primary_pressed()) && resp.contains_pointer() && !over_balloon(app, p);
|
||||
if pressed {
|
||||
let now = ui.input(|i| i.time);
|
||||
let (delay, dist) = ui.ctx().options(|o| (o.input_options.max_double_click_delay, o.input_options.max_click_dist));
|
||||
|
||||
@@ -3153,6 +3153,63 @@ mod tests {
|
||||
assert!(!a.session.sel.is_collapsed(), "the drag left a selection");
|
||||
}
|
||||
|
||||
/// #1013: a press inside the selected comment's balloon (to move the caret in its text) left
|
||||
/// the balloon, because the canvas under it also "contained" the pointer.
|
||||
#[test]
|
||||
fn a_press_inside_the_selected_comment_keeps_it_selected() {
|
||||
let ctx = egui::Context::default();
|
||||
let mut a = app();
|
||||
a.run("text.insert", json!({"text": "Some text to comment on. ".repeat(40)})).unwrap();
|
||||
a.run("select.word", json!({})).unwrap();
|
||||
a.run("review.newComment", json!({"text": "A comment with a few words in it"})).unwrap();
|
||||
a.session.view.comments_pane = false;
|
||||
let screen = egui::Rect::from_min_size(egui::Pos2::ZERO, egui::vec2(1400.0, 700.0));
|
||||
let mut t = 0.0;
|
||||
let mut frame = |a: &mut WordApp, events: Vec<egui::Event>| {
|
||||
t += 1.0 / 60.0;
|
||||
let input = egui::RawInput { events, time: Some(t), screen_rect: Some(screen), ..Default::default() };
|
||||
ctx.run_ui(input, |ui| {
|
||||
a.logic(ui.ctx());
|
||||
a.ui(ui);
|
||||
})
|
||||
.drop_without_applying_deltas();
|
||||
};
|
||||
let btn = |pos, pressed| egui::Event::PointerButton { pos, button: egui::PointerButton::Primary, pressed, modifiers: Default::default() };
|
||||
for _ in 0..30 {
|
||||
frame(&mut a, Vec::new());
|
||||
}
|
||||
let (id, card) = *a.canvas.balloon_rects.first().expect("the comment has a balloon");
|
||||
frame(&mut a, vec![egui::Event::PointerMoved(card.center())]);
|
||||
frame(&mut a, vec![btn(card.center(), true)]);
|
||||
frame(&mut a, vec![btn(card.center(), false)]);
|
||||
for _ in 0..5 {
|
||||
frame(&mut a, Vec::new());
|
||||
}
|
||||
assert_eq!(a.canvas.balloon, Some(id), "a click on the balloon selects it");
|
||||
let (_, card) = *a.canvas.balloon_rects.iter().find(|(i, _)| *i == id).unwrap();
|
||||
let (focus, scroll) = (a.session.sel.clone(), a.canvas.scroll_offset);
|
||||
// Press, drag a little and release inside the comment's text.
|
||||
let (from, to) = (card.left_top() + egui::vec2(30.0, 30.0), card.left_top() + egui::vec2(80.0, 30.0));
|
||||
frame(&mut a, vec![egui::Event::PointerMoved(from)]);
|
||||
frame(&mut a, vec![btn(from, true)]);
|
||||
assert_eq!(a.canvas.balloon, Some(id), "the press stays in the balloon");
|
||||
for _ in 0..3 {
|
||||
frame(&mut a, vec![egui::Event::PointerMoved(to)]);
|
||||
}
|
||||
assert!(!a.canvas.drag_selecting(), "the press didn't start a drag in the document");
|
||||
frame(&mut a, vec![btn(to, false)]);
|
||||
assert_eq!(a.canvas.balloon, Some(id), "still selected after the release");
|
||||
assert_eq!(a.session.sel, focus, "the document's caret didn't move");
|
||||
assert_eq!(a.canvas.scroll_offset, scroll);
|
||||
// A press on the page itself still leaves the balloon.
|
||||
let page = a.canvas.page_rects.first().copied().unwrap();
|
||||
let body = page.left_top() + egui::vec2(120.0, 160.0);
|
||||
frame(&mut a, vec![egui::Event::PointerMoved(body)]);
|
||||
frame(&mut a, vec![btn(body, true)]);
|
||||
frame(&mut a, vec![btn(body, false)]);
|
||||
assert_eq!(a.canvas.balloon, None, "a click on the page leaves the balloon");
|
||||
}
|
||||
|
||||
/// #1019: a double-click in the header area returned before the release ended the drag, so
|
||||
/// a later press held on the ribbon edge-scrolled the document up.
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user