mirror of
https://github.com/storytold/deckcraft.git
synced 2026-11-02 06:57:04 -06:00
FIX-1621: cover locked and outline-free No Fill shapes
This commit is contained in:
+3
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
**Stage: alpha** · next: beta, ~20 points and ~120–210 h away
|
||||
|
||||
> **Last reviewed:** 2026-10-31 · **Last updated:** 2026-10-31 · **Change:** trivial (No Fill hit-testing follows resolved fill instead of the presence of a style (#1621); scores unchanged) · **Target:** Microsoft PowerPoint for Mac 16.113 (Microsoft 365)
|
||||
> **Last reviewed:** 2026-11-01 · **Last updated:** 2026-11-01 · **Change:** trivial (locked No Fill and no-outline click-through regression coverage added; No Fill hit-testing follows resolved fill instead of the presence of a style (#1621); scores unchanged) · **Target:** Microsoft PowerPoint for Mac 16.113 (Microsoft 365)
|
||||
> **Last reviewed:** 2026-10-14 · **Last updated:** 2026-10-30 · **Change:** trivial (progress log: read-only `slide.actions` lists shape and table text actions; parity scores unchanged) · **Target:** Microsoft PowerPoint for Mac 16.113 (Microsoft 365)
|
||||
> **Last reviewed:** 2026-10-14 · **Last updated:** 2026-10-27 · **Change:** trivial (progress log: Set Up Slide Show ▸ Keep mouse cursor visible, #1445; stage and scores unchanged) · **Target:** Microsoft PowerPoint for Mac 16.113 (Microsoft 365)
|
||||
> **Last reviewed:** 2026-10-14 · **Last updated:** 2026-10-26 · **Change:** trivial (progress log: dragging several selected slides moves them all; previous: trivial, progress log: Edit Points handle drags with Shift, Ctrl/Cmd or Alt/Option set the point type; previous: trivial, progress log: scroll bars on the zoomed slide pane, #1157; previous: minor, native chart payloads stored in bounded ZIP members; previous: major, community PR wave 2026-10-14: ~60 landed items in the progress log, among them the Font, Paragraph, Photo Album, theme colour and font and Date and Time dialogs, presenter and show controls, the SmartArt Text Pane and PPTX corpus slices; breadth 84% after `cargo xtask parity`, ready stays ~55%, stage stays alpha; duplicated rows and headers folded; previous: minor, hours to ~95% per audience added) · **Target:** Microsoft PowerPoint for Mac 16.113 (Microsoft 365)
|
||||
@@ -148,6 +148,7 @@ app's JSON control channel (`deckcraft --control PORT`).
|
||||
|
||||
| Date | What landed |
|
||||
|---|---|
|
||||
| 2026-11-01 | No Fill regression coverage now includes locked shapes (outline selectable, position unchanged by dragging) and empty shapes without an outline, locked or unlocked (#1621). Existing text, outline and interior-hit tests retained |
|
||||
| 2026-10-31 | No Fill shape interiors allow selection and editing of underlying objects, even when a quick style remains; hit-testing uses the renderer’s fill resolution. Outlines, rotation, text targets and actual fills keep their hit behaviour (#1621) |
|
||||
| 2026-10-30 | Print-preview tests use the URL emitted by egui and its exact file path; previews are explicitly removed before the macOS process exits |
|
||||
| 2026-10-30 | `slide.actions` lists shape click and hover actions and text-run hyperlinks (including table cells and grouped shapes) for audit; listing never runs an action. The UI pane is a follow-up |
|
||||
@@ -319,6 +320,7 @@ app's JSON control channel (`deckcraft --control PORT`).
|
||||
|
||||
| Date | Change | Summary |
|
||||
|---|---|---|
|
||||
| 2026-11-01 | trivial | No Fill tests cover locked outline selection without movement and click-through without an outline; fill row and parity scores unchanged (#1621) |
|
||||
| 2026-10-31 | trivial | No Fill hit-testing follows resolved fill instead of the presence of a style (#1621); scores unchanged |
|
||||
| 2026-10-30 | trivial | Progress log: read-only slide action inspection; parity scores unchanged |
|
||||
| 2026-10-29 | trivial | Progress log: going back in the slide show reverses the left slide's transition (#1531). Scores and milestone names unchanged |
|
||||
|
||||
@@ -5572,7 +5572,7 @@ fn edit_points_conversion_is_one_undo_step() {
|
||||
assert!(preset(&s), "the only step was the conversion");
|
||||
}
|
||||
|
||||
// #1621: No Fill changes hit-testing as well as rendering, even with a quick style.
|
||||
/// #1621: build overlapping objects with an ordinary quick style on the foreground shape.
|
||||
fn no_fill_overlap(s: &mut Session, text: bool) -> (ShapeId, ShapeId) {
|
||||
s.execute("slide.new", &json!({"layout": "blank"})).unwrap();
|
||||
let under = s
|
||||
@@ -5587,6 +5587,7 @@ fn no_fill_overlap(s: &mut Session, text: bool) -> (ShapeId, ShapeId) {
|
||||
(ShapeId(under as u32), ShapeId(over as u32))
|
||||
}
|
||||
|
||||
/// No Fill passes interior clicks through while preserving outline and actual-fill targets.
|
||||
#[test]
|
||||
fn no_fill_shape_allows_selecting_and_editing_underlying_text() {
|
||||
let mut s = session();
|
||||
@@ -5622,6 +5623,7 @@ fn no_fill_shape_allows_selecting_and_editing_underlying_text() {
|
||||
}
|
||||
}
|
||||
|
||||
/// Rotation and pointer tolerance must preserve both pass-through interiors and outline hits.
|
||||
#[test]
|
||||
fn no_fill_shape_hit_testing_respects_rotation_and_pointer_tolerance() {
|
||||
let mut s = session();
|
||||
@@ -5642,6 +5644,7 @@ fn no_fill_shape_hit_testing_respects_rotation_and_pointer_tolerance() {
|
||||
}
|
||||
}
|
||||
|
||||
/// Style, theme and absent fills follow rendering, with explicit fill taking precedence.
|
||||
#[test]
|
||||
fn no_fill_hit_testing_resolves_style_and_theme_fills() {
|
||||
use std::sync::Arc;
|
||||
@@ -5673,6 +5676,7 @@ fn no_fill_hit_testing_resolves_style_and_theme_fills() {
|
||||
}
|
||||
}
|
||||
|
||||
/// Text on a foreground No Fill shape retains its selection and editing target.
|
||||
#[test]
|
||||
fn no_fill_text_shapes_keep_their_interior_text_target() {
|
||||
let mut s = session();
|
||||
@@ -5686,6 +5690,52 @@ fn no_fill_text_shapes_keep_their_interior_text_target() {
|
||||
assert_eq!(text_sel(&s).unwrap().shape, over);
|
||||
}
|
||||
|
||||
/// A locked No Fill shape remains selectable on its outline, but dragging cannot move it.
|
||||
#[test]
|
||||
fn no_fill_locked_shape_keeps_outline_selection_without_moving() {
|
||||
let mut s = session();
|
||||
let (under, over) = no_fill_overlap(&mut s, true);
|
||||
s.execute("shape.fill", &json!({"none": true})).unwrap();
|
||||
s.execute("shape.lock", &json!({"locked": true})).unwrap();
|
||||
let before = s.doc().unwrap().shape(over).unwrap().xfrm;
|
||||
s.execute("edit.deselect", &json!({})).unwrap();
|
||||
let inside = deckcraft_geom::Point::new(200.0, 310.0);
|
||||
assert!(matches!(s.hit_test(inside, 3.0), Some(tools::Hit::Shape { id, .. }) if id == under));
|
||||
for kind in [PointerKind::Down, PointerKind::Up] {
|
||||
s.pointer(tev(kind, inside.x, inside.y)).unwrap();
|
||||
}
|
||||
assert_eq!(text_sel(&s).unwrap().shape, under);
|
||||
s.execute("edit.deselect", &json!({})).unwrap();
|
||||
let edge = deckcraft_geom::Point::new(80.0, 330.0);
|
||||
assert!(matches!(s.hit_test(edge, 3.0), Some(tools::Hit::Shape { id, .. }) if id == over));
|
||||
s.pointer(tev(PointerKind::Down, edge.x, edge.y)).unwrap();
|
||||
s.pointer(tev(PointerKind::Drag, edge.x + 40.0, edge.y + 20.0)).unwrap();
|
||||
s.pointer(tev(PointerKind::Up, edge.x + 40.0, edge.y + 20.0)).unwrap();
|
||||
let st = s.doc().unwrap();
|
||||
assert_eq!(st.selection.shapes, vec![over]);
|
||||
assert_eq!(st.shape(over).unwrap().xfrm, before);
|
||||
assert!(st.shape(over).unwrap().locked);
|
||||
}
|
||||
|
||||
/// Removing both fill and outline leaves the empty interior transparent to clicks, locked or not.
|
||||
#[test]
|
||||
fn no_fill_shape_without_text_or_outline_passes_interior_clicks() {
|
||||
for locked in [false, true] {
|
||||
let mut s = session();
|
||||
let (under, _) = no_fill_overlap(&mut s, false);
|
||||
s.execute("shape.fill", &json!({"none": true})).unwrap();
|
||||
s.execute("shape.line", &json!({"none": true})).unwrap();
|
||||
s.execute("shape.lock", &json!({"locked": locked})).unwrap();
|
||||
s.execute("edit.deselect", &json!({})).unwrap();
|
||||
let p = deckcraft_geom::Point::new(200.0, 310.0);
|
||||
assert!(matches!(s.hit_test(p, 3.0), Some(tools::Hit::Shape { id, .. }) if id == under));
|
||||
for kind in [PointerKind::Down, PointerKind::Up] {
|
||||
s.pointer(tev(kind, p.x, p.y)).unwrap();
|
||||
}
|
||||
assert_eq!(s.doc().unwrap().selection.shapes, vec![under]);
|
||||
}
|
||||
}
|
||||
|
||||
/// #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]
|
||||
|
||||
@@ -216,6 +216,7 @@ pub(super) fn in_table_cell(st: &crate::DocState, id: ShapeId, p: Point) -> bool
|
||||
})
|
||||
}
|
||||
|
||||
/// Resolve a shape's target at slide point `p`, using its effective fill for interior hits.
|
||||
pub(super) fn hit_shape(st: &crate::DocState, sh: &Shape, p: Point, tol: f64) -> Option<Hit> {
|
||||
let x = xfrm_of(&st.doc, &st.selection, sh);
|
||||
let inv = x.affine().inverse();
|
||||
|
||||
+2
-1
@@ -1,6 +1,6 @@
|
||||
# Where DeckCraft falls short of PowerPoint
|
||||
|
||||
> **Last reviewed:** 2026-10-31 · **Last updated:** 2026-10-31 · **Change:** trivial (No Fill hit-testing follows resolved fill instead of the presence of a style (#1621); scores unchanged) · **Target:** Microsoft PowerPoint for Mac 16.113 (Microsoft 365)
|
||||
> **Last reviewed:** 2026-11-01 · **Last updated:** 2026-11-01 · **Change:** trivial (locked No Fill and no-outline click-through regression coverage added; No Fill hit-testing follows resolved fill instead of the presence of a style (#1621); scores unchanged) · **Target:** Microsoft PowerPoint for Mac 16.113 (Microsoft 365)
|
||||
|
||||
Every known shortfall, one entry each, ranked by how much it stops someone who presents with
|
||||
PowerPoint from switching. This is the work list: pick from the top. Numbers are summarized in
|
||||
@@ -368,6 +368,7 @@ Detail in [localization-parity.md](localization-parity.md).
|
||||
|
||||
| Date | Change | Summary |
|
||||
|---|---|---|
|
||||
| 2026-11-01 | trivial | No Fill tests cover locked outline selection without movement and click-through without an outline; fill row and parity scores unchanged (#1621) |
|
||||
| 2026-10-31 | trivial | No Fill hit-testing follows resolved fill instead of the presence of a style (#1621); scores unchanged |
|
||||
| 2026-10-30 | minor | Slide-show click targets use each shape’s own animation state; scale and rotation test added |
|
||||
| 2026-10-28 | trivial | Automatic lists now run independently of Replace text as you type; proofing gap description updated |
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
> **Generated:** 2026-10-14 (bullets/numbering remain D after empty-line marker review; summary by `cargo xtask parity`; rows re-scored by the 2026-10-14 community PR wave, duplicate Thesaurus, AutoCorrect, Artistic effects and Corrections rows folded; Preview in editor re-scored 2026-10-13; earlier rows re-scored 2026-10-10 against PowerPoint for Mac 16.113.4; video/animated GIF row re-scored 2026-10-11, #171) · **Target:** Microsoft PowerPoint for Mac 16.113 (Microsoft 365)
|
||||
|
||||
> **Last updated:** 2026-10-31 · Fill row re-assessed after #1621: remains D; No Fill hit-testing now follows resolved appearance. Scores unchanged.
|
||||
> **Last updated:** 2026-11-01 · Locked-shape and no-outline regressions added for #1621; fill row re-assessed: remains D; No Fill hit-testing now follows resolved appearance. Scores unchanged.
|
||||
|
||||
The summary between `<!-- SUMMARY -->
|
||||
**Weighted breadth parity: 84%** over 191 features.
|
||||
@@ -240,4 +240,5 @@ Open P0 items: Contextual tabs (Shape Format, Picture Format, Table Design/Layou
|
||||
|
||||
| Date | Change | Summary |
|
||||
|---|---|---|
|
||||
| 2026-11-01 | trivial | No Fill tests cover locked outline selection without movement and click-through without an outline; fill row and parity scores unchanged (#1621) |
|
||||
| 2026-10-31 | trivial | No Fill interior hit-testing follows resolved fill (#1621); fill row remains D and summary scores are unchanged |
|
||||
|
||||
+3
-2
@@ -1,6 +1,6 @@
|
||||
# UI parity with PowerPoint
|
||||
|
||||
> **Last reviewed:** 2026-10-31 · **Last updated:** 2026-10-31 · **Change:** trivial (No Fill hit-testing follows resolved fill instead of the presence of a style (#1621); scores unchanged) · **Target:** Microsoft PowerPoint for Mac 16.113 (Microsoft 365)
|
||||
> **Last reviewed:** 2026-11-01 · **Last updated:** 2026-11-01 · **Change:** trivial (locked No Fill and no-outline click-through regression coverage added; No Fill hit-testing follows resolved fill instead of the presence of a style (#1621); scores unchanged) · **Target:** Microsoft PowerPoint for Mac 16.113 (Microsoft 365)
|
||||
> **Last reviewed:** 2026-10-14 · **Last updated:** 2026-10-26 · **Change:** trivial (dragging several selected slides moves them all; previous: trivial, Edit Points: Shift, Ctrl/Cmd or Alt/Option on a handle drag sets the point type; previous: trivial, scroll bars on the zoomed slide pane, #1157; previous: major, community PR wave 2026-10-14: 14 new dialogs (41 in all), Eyedropper, Export button, New Window, Grid Options, WordArt gallery and handles, Slide Sorter sections, Quick Access Toolbar, Format Background and Format Shape depth, rich-text clipboard; duplicated rows and headers folded; previous: minor, File tab / Backstage, #76) · **Target:** Microsoft PowerPoint for Mac 16.113 (Microsoft 365)
|
||||
> **Last reviewed:** 2026-10-14 · **Last updated:** 2026-10-22 · **Change:** trivial (group fill and outline edits reach members, #1079; scores unchanged) · **Target:** Microsoft PowerPoint for Mac 16.113 (Microsoft 365)
|
||||
> **Last reviewed:** 2026-10-14 · **Last updated:** 2026-10-24 · **Change:** trivial (Edit Points: Shift, Ctrl/Cmd or Alt/Option on a handle drag sets the point type; previous: trivial, scroll bars on the zoomed slide pane, #1157; previous: major, community PR wave 2026-10-14: 14 new dialogs (41 in all), Eyedropper, Export button, New Window, Grid Options, WordArt gallery and handles, Slide Sorter sections, Quick Access Toolbar, Format Background and Format Shape depth, rich-text clipboard; duplicated rows and headers folded; previous: minor, File tab / Backstage, #76) · **Target:** Microsoft PowerPoint for Mac 16.113 (Microsoft 365)
|
||||
@@ -81,7 +81,7 @@ menu colours taken from the theme tokens (menu `chrome`, page `card`).
|
||||
|
||||
| Behaviour | PowerPoint | DeckCraft |
|
||||
|---|---|---|
|
||||
| Selection handles, rotation handle, yellow adjustment handles | yes | yes; an empty No Fill shape passes interior clicks to underlying objects while its outline and handles remain selectable. Explicit, style and theme fills resolve as rendered (#1621) |
|
||||
| Selection handles, rotation handle, yellow adjustment handles | yes | yes; an empty No Fill shape passes interior clicks to underlying objects while its outline and handles remain selectable. Explicit, style and theme fills resolve as rendered; tests also cover locked outline targets and empty interiors without an outline (#1621) |
|
||||
| Marquee, Shift/Cmd multi-select, Tab to cycle | yes | yes |
|
||||
| Objects off the slide: drawn on the area around it in Normal view (full strength, master graphics too), selectable and movable there; clipped in the show, exports and thumbnails | yes | yes (#270) |
|
||||
| Scroll bars on the slide pane when the zoomed slide is larger than the window | yes | yes, on each axis that overflows: drag the thumb or click the track; the wheel and trackpad still pan. The vertical bar does not turn the page (#1157) |
|
||||
@@ -171,6 +171,7 @@ consistency is open (#73, #56).
|
||||
|
||||
| Date | Change | Summary |
|
||||
|---|---|---|
|
||||
| 2026-11-01 | trivial | No Fill tests cover locked outline selection without movement and click-through without an outline; fill row and parity scores unchanged (#1621) |
|
||||
| 2026-10-31 | trivial | No Fill hit-testing follows resolved fill instead of the presence of a style (#1621); scores unchanged |
|
||||
| 2026-10-29 | trivial | Picture Format: the Picture Styles row shows as many styles as fit beside the groups after it (at least two) and a More arrow with all 24, as the Transitions and Animations galleries do; Crop and Size are in view in the default window (#1232) |
|
||||
| 2026-10-26 | trivial | Thumbnail pane and Slide Sorter: dragging one of several selected slides moves the whole selection |
|
||||
|
||||
Reference in New Issue
Block a user