mirror of
https://github.com/storytold/figcraft.git
synced 2026-11-13 22:02:38 +00:00
M12: a mind map in a section or frame without a place is centred on the view
board.mindMap's default x and y came from the view's centre, which is on the page, but x and y are the root's place in its parent: under a section at (1000, 500) the map landed 1000 right and 500 down of the view's centre. The default now takes the centre through the parent's inverse world transform (a parent that can't be inverted gives a non-finite centre, which the coordinate check refuses). Explicit x and y stay parent-local. Tests: two in board_mindmap_tests (a section; a frame turned 30 degrees, with a given place carried through the frame). Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Model-Effort: Opus 5.5 drove; Opus 5.5 briefed; Sonnet 5.5 wrote at medium
This commit is contained in:
1 parent
7b34dbab00
commit
e0e57dd42a
3 files changed
+45
-3
No files matched your search
@@ -383,3 +383,41 @@ fn the_caps_refuse_what_is_too_far_and_cut_what_is_too_long() {
|
||||
assert_eq!(text_data(&s, id(&out, "id")).characters.chars().count(), 500);
|
||||
assert_eq!(text_data(&s, id(&out["children"][0], "id")).characters.chars().count(), 500);
|
||||
}
|
||||
|
||||
/// Where a node's own origin (the place `x`/`y` name) is on the page.
|
||||
fn origin(s: &Session, n: NodeId) -> Point {
|
||||
s.doc().unwrap().world_transform(n) * Point::new(0.0, 0.0)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_mind_map_in_a_section_without_a_place_is_centred_on_the_view() {
|
||||
let mut s = board();
|
||||
let (vx, vy) = {
|
||||
let v = &s.ds().unwrap().view;
|
||||
(v.cx, v.cy)
|
||||
};
|
||||
let sec = id(&s.execute("node.create", &json!({"type": "section", "x": 1000, "y": 500, "width": 4000, "height": 4000})).unwrap(), "id");
|
||||
let out = s.execute("board.mindMap", &json!({"parent": sec})).unwrap();
|
||||
let c = origin(&s, id(&out, "id"));
|
||||
assert!(same(c.x, vx) && same(c.y, vy), "the root's place {c:?} is the view's centre ({vx}, {vy})");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_mind_map_in_a_turned_frame_without_a_place_is_centred_on_the_view_and_a_given_place_is_the_frames() {
|
||||
let mut s = board();
|
||||
let (vx, vy) = {
|
||||
let v = &s.ds().unwrap().view;
|
||||
(v.cx, v.cy)
|
||||
};
|
||||
let fr = id(&s.execute("node.create", &json!({"type": "frame", "x": 300, "y": 200, "width": 2000, "height": 2000})).unwrap(), "id");
|
||||
s.execute("node.set", &json!({"id": fr, "props": {"rotation": 30}})).unwrap();
|
||||
let out = s.execute("board.mindMap", &json!({"parent": fr})).unwrap();
|
||||
let c = origin(&s, id(&out, "id"));
|
||||
assert!(same(c.x, vx) && same(c.y, vy), "the root's place {c:?} is the view's centre ({vx}, {vy})");
|
||||
|
||||
// A given place is the frame's own, as on the page: (10, 20) of the frame, carried through it.
|
||||
let given = id(&s.execute("board.mindMap", &json!({"parent": fr, "x": 10, "y": 20})).unwrap(), "id");
|
||||
let want = s.doc().unwrap().world_transform(fr) * Point::new(10.0, 20.0);
|
||||
let got = origin(&s, given);
|
||||
assert!(same(got.x, want.x) && same(got.y, want.y), "{got:?} against {want:?}");
|
||||
}
|
||||
@@ -168,9 +168,13 @@ pub(super) fn mind_map_cmd(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
let cmd = "board.mindMap";
|
||||
require(s, cmd)?;
|
||||
let parent = parent_of(cmd, s, p)?;
|
||||
// The view's centre is on the page, and `x`/`y` are in the parent: a map in a section or frame
|
||||
// takes the centre in that parent's coordinates (a parent that can't be inverted gives a
|
||||
// non-finite centre, which `coord` refuses).
|
||||
let (vx, vy) = {
|
||||
let v = &s.ds()?.view;
|
||||
(v.cx, v.cy)
|
||||
let ds = s.ds()?;
|
||||
let c = ds.doc.world_transform(parent).inverse() * figcraft_geom::Point::new(ds.view.cx, ds.view.cy);
|
||||
(c.x, c.y)
|
||||
};
|
||||
let (x, y) = (coord(cmd, p, "x", vx)?, coord(cmd, p, "y", vy)?);
|
||||
let texts = starters(cmd, p)?;
|
||||
|
||||
+1
-1
@@ -498,7 +498,7 @@ one undo step and returns the ids it made:
|
||||
in the app does both).
|
||||
- `board.mindMap {x?, y?, text?, children?, parent?, edit?}` → `{id, text, children: [{id, text, connector}]}`:
|
||||
a mind map: a first node (`mindNode`, bold 24, no box; `text` defaults to `Topic`, `x`/`y` to the
|
||||
middle of the view) with up to 20 `children` (texts; default `Idea 1`, `Idea 2`, `Idea 3`)
|
||||
view's centre, in the parent's coordinates) with up to 20 `children` (texts; default `Idea 1`, `Idea 2`, `Idea 3`)
|
||||
on its right, each joined to it by a curved branch (a connector with `branch: true`: stroke 4,
|
||||
`#757575`, round caps). The map lays itself out: children stand in one column 88 units right of
|
||||
the widest node of their parent's column, 48 apart, centred on their parent; a node is its text,
|
||||
|
||||
Reference in new issue
Block a user