mirror of
https://github.com/storytold/gridcraft.git
synced 2026-11-07 02:51:33 +00:00
Objects: dragging an object's body sends its position only, not its size
`drag_object` sent `width` and `height` with every step of a body drag, so moving a picture a file made 12,000 wide shrank it to the 10,000 that `object.move` gives a new size. Only a handle drag sends a size now; a body move leaves the engine's size alone. Tests (real input): dragging_the_body_of_an_oversized_imported_object_keeps_its_size reopens the workbook with a 12,000 by 60 picture, drags its body by 30 by 25 and checks the size is untouched, the picture moved with the pointer and the journaled `object.move` carries no width or height; it fails without the fix (the journaled command carries both, and without the engine's cap the picture is 10,000 wide). a_handle_drag_on_an_oversized_imported_object_resizes_by_the_drag_only moves the left handle 10 px right: the picture is 10 points narrower in the window and keeps a width near 12,000, with no jump to the limit.
This commit is contained in:
1 parent
381a121339
commit
af28f01bfd
2 files changed
+72
-2
No files matched your search
@@ -974,11 +974,19 @@ fn drag_object(app: &mut SheetApp, geo: &Geo, sh: &Sheet, p: Pos2) {
|
||||
};
|
||||
// Re-anchor at the cell under the new top-left.
|
||||
let nc = CellRef::new(sh.row_at(y0 as f64), sh.col_at(x0 as f64));
|
||||
let params = json!({
|
||||
let mut params = json!({
|
||||
"kind": obj.kind.name(), "id": obj.id, "at": nc.a1(),
|
||||
"dx": x0 - sh.col_left(nc.col) as f32, "dy": y0 - sh.row_top(nc.row) as f32,
|
||||
"width": x1 - x0, "height": y1 - y0,
|
||||
});
|
||||
// Only a handle changes the size. A body move sends none, so the engine keeps whatever the
|
||||
// object has: a file can make it larger than `object.move` accepts for a new size, and
|
||||
// moving it must not shrink it to that limit.
|
||||
if handle.is_some()
|
||||
&& let Some(p) = params.as_object_mut()
|
||||
{
|
||||
p.insert("width".into(), json!(x1 - x0));
|
||||
p.insert("height".into(), json!(y1 - y0));
|
||||
}
|
||||
let revision = app.session.active().map(|d| d.revision);
|
||||
let _ = app.session.run("object.move", params);
|
||||
if stepped {
|
||||
|
||||
@@ -362,3 +362,65 @@ fn dragging_an_unselected_object_by_its_edge_moves_it() {
|
||||
assert!((after.size() - before.size()).length() < 0.5, "not resized: {before:?} {after:?}");
|
||||
assert!((after.min - before.min - vec2(30.0, 20.0)).length() < 1.0, "moved with the pointer: {before:?} {after:?}");
|
||||
}
|
||||
|
||||
fn anchor(h: &Harness, o: ObjRef) -> gridcraft_engine::model::Anchor {
|
||||
h.state().session.doc().unwrap().wb.active().unwrap().object_anchor(o).unwrap()
|
||||
}
|
||||
|
||||
/// Makes the fixture's picture 12,000 by 60 and reopens the workbook from its XLSX bytes, the way
|
||||
/// a file can carry an object wider than the 10,000 points `object.move` gives a new size.
|
||||
/// Returns the picture as reopened.
|
||||
fn imported_oversized_picture(h: &mut Harness, o: &Objects) -> ObjRef {
|
||||
{
|
||||
let wb = std::sync::Arc::make_mut(&mut h.state_mut().session.doc_mut().unwrap().wb);
|
||||
let a = wb.sheet_mut(0).unwrap().object_anchor_mut(o.image).unwrap();
|
||||
a.width = 12_000.0;
|
||||
a.height = 60.0;
|
||||
}
|
||||
let saved = h.state_mut().run("file.saveBytes", json!({"format": "xlsx"})).unwrap();
|
||||
h.state_mut().run("file.open", json!({"name": "wide.xlsx", "base64": saved["base64"]})).unwrap();
|
||||
h.run_steps(4);
|
||||
let pic = ObjRef::new(ObjKind::Image, h.state().session.doc().unwrap().wb.active().unwrap().images[0].id);
|
||||
let a = anchor(h, pic);
|
||||
assert_eq!((a.width.round(), a.height.round()), (12_000.0, 60.0), "the reader keeps the file's size: {a:?}");
|
||||
pic
|
||||
}
|
||||
|
||||
/// Dragging the body of such a picture moves it and sends no size, so nothing shrinks it to the
|
||||
/// limit on the way.
|
||||
#[test]
|
||||
fn dragging_the_body_of_an_oversized_imported_object_keeps_its_size() {
|
||||
let (mut h, o) = fixture();
|
||||
let pic = imported_oversized_picture(&mut h, &o);
|
||||
let before = rect(&h, pic);
|
||||
// Well inside the body, on the part of the picture in view and clear of the handles' reach.
|
||||
let grab = before.left_top() + vec2(30.0, 30.0);
|
||||
click(&mut h, grab);
|
||||
assert_eq!(h.state().selected_object, Some(pic));
|
||||
drag(&mut h, grab, grab + vec2(30.0, 25.0));
|
||||
let a = anchor(&h, pic);
|
||||
assert_eq!((a.width.round(), a.height.round()), (12_000.0, 60.0), "the size is untouched: {a:?}");
|
||||
let after = rect(&h, pic);
|
||||
assert!((after.min - before.min - vec2(30.0, 25.0)).length() < 1.0, "moved with the pointer: {before:?} {after:?}");
|
||||
// The drag sent the position only: the engine saw no size to cap.
|
||||
let (_, p) = h.state().session.journal.iter().rev().find(|(id, _)| id == "object.move").unwrap();
|
||||
assert!(p.get("width").is_none() && p.get("height").is_none(), "a body move sends no size: {p}");
|
||||
}
|
||||
|
||||
/// A handle drag on such a picture resizes it by the drag only: the left handle moved 10 px to
|
||||
/// the right leaves it 11,990 wide, with no jump to 10,000.
|
||||
#[test]
|
||||
fn a_handle_drag_on_an_oversized_imported_object_resizes_by_the_drag_only() {
|
||||
let (mut h, o) = fixture();
|
||||
let pic = imported_oversized_picture(&mut h, &o);
|
||||
let before = rect(&h, pic);
|
||||
click(&mut h, before.left_top() + vec2(30.0, 30.0));
|
||||
let grab = Handle::Left.pos(before);
|
||||
drag(&mut h, grab, grab + vec2(10.0, 0.0));
|
||||
// In window points (the grid draws at its zoom): 10 narrower, the left edge 10 further right.
|
||||
let after = rect(&h, pic);
|
||||
assert!((before.width() - after.width() - 10.0).abs() < 1.0, "narrower by the drag only: {before:?} {after:?}");
|
||||
assert!((after.left() - before.left() - 10.0).abs() < 1.0 && (after.top() - before.top()).abs() < 0.5, "{before:?} {after:?}");
|
||||
let a = anchor(&h, pic);
|
||||
assert!(a.width > 11_900.0 && a.width < 12_000.0 && a.height.round() == 60.0, "no jump to the 10,000 limit: {a:?}");
|
||||
}
|
||||
Reference in new issue
Block a user