mirror of
https://github.com/storytold/deckcraft.git
synced 2026-10-24 10:37:03 -06:00
Canvas: a shape in front of edited text takes the click (#931)
While a placeholder's text was being edited, place_caret took every click inside the text box before the hit test, so a shape in front of it couldn't be selected. It now leaves the click to the hit test when a shape above the one holding the text is under the pointer; a click on the text where nothing is in front still moves the caret. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
22db9261f9
commit
a773fcfce9
@@ -131,6 +131,7 @@ app's JSON control channel (`deckcraft --control PORT`).
|
||||
|
||||
| Date | What landed |
|
||||
|---|---|
|
||||
| 2026-10-17 | While a placeholder's text is being edited, a click on a shape in front of it selects that shape instead of moving the caret, as in PowerPoint (#931) |
|
||||
| 2026-10-15 | PPTX trigger sequences keep separate On Click steps, including paragraph builds; synthetic import/edit/save/reopen and headless show regressions |
|
||||
| 2026-10-15 | CLI: .txt and .md export includes table cell text, which it used to skip silently (#814) |
|
||||
| 2026-10-15 | PDF export and rendering: `anchorCtr` centres the drawn text block — right-aligned text no longer ran past the box edge (#736) |
|
||||
|
||||
@@ -3623,3 +3623,30 @@ fn table_column_width_of_a_huge_column_is_ignored() {
|
||||
assert_eq!(table_of(&s, id).cols, vec![100.0, 100.0], "no column changes");
|
||||
}
|
||||
}
|
||||
|
||||
/// #931: while the text of a placeholder is being edited, a shape in front of it still takes a
|
||||
/// click (as in PowerPoint); a click on the text where nothing is in front still moves the caret.
|
||||
#[test]
|
||||
fn a_shape_in_front_of_edited_text_takes_the_click() {
|
||||
let mut s = Session::with_new();
|
||||
s.execute("slide.new", &json!({"layout": "titleAndContent"})).unwrap();
|
||||
let square = s.execute("shape.insert", &json!({"preset": "rect", "rect": [380, 260, 200, 120]})).unwrap()["id"].as_u64().unwrap();
|
||||
s.execute("edit.deselect", &json!({})).unwrap();
|
||||
let ev = |kind, x: f64, y: f64| tools::PointerEvent { kind, x, y, mods: Default::default(), tol: 4.0, pressure: None };
|
||||
let click = |s: &mut Session, x: f64, y: f64| {
|
||||
s.pointer(ev(tools::PointerKind::Down, x, y)).unwrap();
|
||||
s.pointer(ev(tools::PointerKind::Up, x, y)).unwrap();
|
||||
};
|
||||
// The content placeholder's edge: its (empty) text is now being edited.
|
||||
click(&mut s, 66.0, 300.0);
|
||||
let body = s.doc().unwrap().selection.text.as_ref().map(|t| t.shape).expect("editing the content placeholder");
|
||||
assert_ne!(body.0 as u64, square);
|
||||
// A click on the text away from the square keeps editing it.
|
||||
click(&mut s, 200.0, 300.0);
|
||||
assert_eq!(s.doc().unwrap().selection.text.as_ref().map(|t| t.shape), Some(body));
|
||||
// A click on the square, in front of the text, selects the square.
|
||||
click(&mut s, 480.0, 320.0);
|
||||
let st = s.doc().unwrap();
|
||||
assert_eq!(st.selection.shapes.iter().map(|id| id.0 as u64).collect::<Vec<_>>(), vec![square]);
|
||||
assert!(st.selection.text.as_ref().is_none_or(|t| t.shape.0 as u64 == square), "{:?}", st.selection.text);
|
||||
}
|
||||
|
||||
@@ -1228,7 +1228,16 @@ impl Session {
|
||||
None => edited_box(st).is_some_and(|e| edit_zone(&e.xfrm, p, tol) != EditZone::Outside),
|
||||
Some(_) => xfrm_of(&st.doc, &st.selection, sh).bounds().inflate(tol, tol).contains(p),
|
||||
};
|
||||
// A shape in front of the edited text takes the click, as in PowerPoint (#931): the shapes
|
||||
// above the one holding the text, topmost first.
|
||||
let in_front = st
|
||||
.shapes()
|
||||
.iter()
|
||||
.rev()
|
||||
.take_while(|s| deckcraft_model::find_shape(std::slice::from_ref(*s), t.shape).is_none())
|
||||
.any(|s| !s.hidden && hit_shape(st, s, p, tol).is_some());
|
||||
if !inside
|
||||
|| in_front
|
||||
|| matches!(
|
||||
self.hit_test(p, tol),
|
||||
Some(
|
||||
|
||||
Reference in New Issue
Block a user