Merge pull request #946 from Zetenypapp/fix/edit-points-undo

# Conflicts:
#	crates/engine/src/tests.rs
This commit is contained in:
Brandon Thomas
2026-10-18 11:18:17 -04:00
4 changed files with 40 additions and 2 deletions
+1
View File
@@ -133,6 +133,7 @@ app's JSON control channel (`deckcraft --control PORT`).
|---|---|
| 2026-10-17 | Opening a file caps absurd effect sizes (glow, soft edges, shadows, reflections, on shapes, text and table text) at what Format Shape allows: a glow of 10^18 pt in a .pptx made rendering ask for 34 GB and abort |
| 2026-10-17 | Opening a .deckcraft file whose shapes repeat an id gives the repeats fresh ids (groups, layouts and masters too), so the deck validates and edits by id find one shape |
| 2026-10-17 | Edit Points: turning a shape into a freeform is one undo step, so Undo brings the original shape back (it used to stay a freeform) |
| 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-16 | Export: PNG with a transparent background — the slide background is left out, only the slide's content is drawn (Export… dialog, File › Export, web download, `file.export`/`file.render` `transparentBackground`, `deckcraft-cli render --transparent`) (#784) |
| 2026-10-15 | CLI: .txt and .md export includes table cell text, which it used to skip silently (#814) |
+1 -1
View File
@@ -16,7 +16,7 @@ use crate::{Result, Session};
pub fn specs() -> Vec<CommandSpec> {
vec![
cmd!(
noundo "shape.editPoints",
"shape.editPoints",
"Edit Points",
["Shape Format", "Insert Shapes", "Edit Shape"],
None,
+32
View File
@@ -3953,3 +3953,35 @@ fn shape_geometry_commands_limit_size_and_position() {
let x = xfrm(&s);
assert!(within(&s), "rotated resize stored {x:?}");
}
/// Edit Points turns a preset into a freeform: one undo step, so Undo brings the preset back
/// (and leaves Edit Points), Redo the freeform; leaving Edit Points adds no step.
#[test]
fn edit_points_conversion_is_one_undo_step() {
use deckcraft_model::Geom;
let mut s = Session::with_new();
s.execute("slide.new", &json!({"layout": "blank"})).unwrap();
s.execute("shape.insert", &json!({"preset": "star5", "rect": [100, 100, 200, 100]})).unwrap();
let preset = |s: &Session| matches!(s.doc().unwrap().selected_shapes()[0].geom, Geom::Preset { .. });
s.execute("shape.editPoints", &json!({"on": true})).unwrap();
assert!(!preset(&s), "Edit Points made a freeform");
assert!(s.tool.editing_points(s.doc().unwrap()).is_some());
s.execute("shape.editPoints", &json!({"on": false})).unwrap();
// Leaving changed nothing, so the next undo is the conversion itself.
s.execute("edit.undo", &json!({})).unwrap();
assert!(preset(&s), "Undo brings the star back");
s.execute("edit.redo", &json!({})).unwrap();
assert!(!preset(&s), "Redo makes it a freeform again");
// Undo while still editing points ends Edit Points: the star has no points to edit.
s.execute("edit.undo", &json!({})).unwrap();
s.execute("shape.editPoints", &json!({"on": true})).unwrap();
s.execute("edit.undo", &json!({})).unwrap();
assert!(preset(&s));
assert!(s.tool.editing_points(s.doc().unwrap()).is_none());
// A freeform needs no conversion: entering Edit Points again adds no undo step.
s.execute("edit.redo", &json!({})).unwrap();
s.execute("shape.editPoints", &json!({"on": false})).unwrap();
s.execute("shape.editPoints", &json!({"on": true})).unwrap();
s.execute("edit.undo", &json!({})).unwrap();
assert!(preset(&s), "the only step was the conversion");
}
+6 -1
View File
@@ -280,7 +280,12 @@ impl ToolState {
/// The shape in Edit Points, while it is still the one selected shape.
pub fn editing_points(&self, st: &crate::DocState) -> Option<ShapeId> {
self.edit_points.filter(|id| st.selection.shapes.as_slice() == [*id] && st.selection.text.is_none() && st.shape(*id).is_some())
// Only a freeform has points: after Undo takes the conversion back, Edit Points is over.
self.edit_points.filter(|id| {
st.selection.shapes.as_slice() == [*id]
&& st.selection.text.is_none()
&& st.shape(*id).is_some_and(|sh| matches!(sh.geom, deckcraft_model::Geom::Custom { .. }))
})
}
/// A freeform path is being drawn (Enter/Escape/double-click finish it).