From 54c8a4f4d756afd8adc431157aad9e6a2bbaf79a Mon Sep 17 00:00:00 2001 From: George Thomas Date: Tue, 4 Jul 2023 12:58:59 +0100 Subject: [PATCH 1/3] refactor: Split up forest layout Signed-off-by: George Thomas --- src/components/TreeReactFlow/index.tsx | 67 +++++++++++++++----------- 1 file changed, 39 insertions(+), 28 deletions(-) diff --git a/src/components/TreeReactFlow/index.tsx b/src/components/TreeReactFlow/index.tsx index 244e2701..67811a77 100644 --- a/src/components/TreeReactFlow/index.tsx +++ b/src/components/TreeReactFlow/index.tsx @@ -997,32 +997,14 @@ const typeDefToTree = async ( * It ensures that these are clearly displayed as "one atomic thing", * i.e. to avoid confused readings that group the type of 'foo' with the body of 'bar' (etc). */ -export const TreeReactFlow = (p: PropsWithChildren) => ( - - typeDefToTree(def, { ...p.defParams, ...p }).then((t) => - layoutTree(t, p.layout).then(({ tree, width, height }) => ({ - // All we're doing here is adding `nested: []` to all type def nodes. - // We just have to be very explicit here in order to please the typechecker. - width, - height, - tree: treeMap(tree, ({ position, ...n }) => ({ - position, - ...primerNodeWith(n, { nested: [], ...n.data }), - })), - })) - ) - ), - ...p.defs.map((def) => - defToTree(def, { ...p.defParams, ...p }).then((t) => - layoutTree(t, p.layout) - ) - ), - ]).then( - // Space out the forest. - (sizedTrees) => +export const TreeReactFlow = (p: PropsWithChildren) => { + const spaceForest = ( + sizedTrees: { + tree: Tree, PrimerEdge>; + width: number; + height: number; + }[], + ) => sizedTrees.reduce< [Tree, PrimerEdge>[], number] >( @@ -1055,8 +1037,36 @@ export const TreeReactFlow = (p: PropsWithChildren) => ( ]; }, [[], 0] - )[0] - )} + )[0]; + return ( + { + const typeDefTrees = await Promise.all( + p.typeDefs.map((def) => + typeDefToTree(def, { ...p.defParams, ...p }).then((t) => + layoutTree(t, p.layout).then(({ tree, width, height }) => ({ + // All we're doing here is adding `nested: []` to all type def nodes. + // We just have to be very explicit here in order to please the typechecker. + width, + height, + tree: treeMap(tree, ({ position, ...n }) => ({ + position, + ...primerNodeWith(n, { nested: [], ...n.data }), + })), + })) + ) + ) + ); + const termDefTrees = await Promise.all( + p.defs.map((def) => + defToTree(def, { ...p.defParams, ...p }).then((t) => + layoutTree(t, p.layout) + ) + ) + ); + return spaceForest([...typeDefTrees, ...termDefTrees]); + })()} onNodeClick={(mouseEvent, node) => p.onNodeClick(mouseEvent, makeSelectionFromNode(node)) } @@ -1069,6 +1079,7 @@ export const TreeReactFlow = (p: PropsWithChildren) => ( {p.children} ); +}; export default TreeReactFlow; export type TreeReactFlowOneProps = { From b960665759f12d41572c1cb35d6e397ca739d713 Mon Sep 17 00:00:00 2001 From: George Thomas Date: Tue, 4 Jul 2023 12:59:16 +0100 Subject: [PATCH 2/3] chore: Formatting Signed-off-by: George Thomas --- src/components/TreeReactFlow/index.tsx | 92 +++++++++++++------------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/src/components/TreeReactFlow/index.tsx b/src/components/TreeReactFlow/index.tsx index 67811a77..33c9f377 100644 --- a/src/components/TreeReactFlow/index.tsx +++ b/src/components/TreeReactFlow/index.tsx @@ -1003,41 +1003,41 @@ export const TreeReactFlow = (p: PropsWithChildren) => { tree: Tree, PrimerEdge>; width: number; height: number; - }[], + }[] ) => - sizedTrees.reduce< - [Tree, PrimerEdge>[], number] - >( - ([trees, offset], { tree, width, height }) => { - const { increment, offsetVector } = (() => { - switch (p.forestLayout) { - case "Horizontal": - return { - increment: width, - offsetVector: { x: offset, y: 0 }, - }; - case "Vertical": - return { - increment: height, - offsetVector: { x: 0, y: offset }, - }; - } - })(); - return [ - trees.concat( - treeMap(tree, (n) => ({ - ...n, - position: { - x: n.position.x + p.layout.margins.sibling + offsetVector.x, - y: n.position.y + p.layout.margins.child + offsetVector.y, - }, - })) - ), - offset + increment + p.treePadding, - ]; - }, - [[], 0] - )[0]; + sizedTrees.reduce< + [Tree, PrimerEdge>[], number] + >( + ([trees, offset], { tree, width, height }) => { + const { increment, offsetVector } = (() => { + switch (p.forestLayout) { + case "Horizontal": + return { + increment: width, + offsetVector: { x: offset, y: 0 }, + }; + case "Vertical": + return { + increment: height, + offsetVector: { x: 0, y: offset }, + }; + } + })(); + return [ + trees.concat( + treeMap(tree, (n) => ({ + ...n, + position: { + x: n.position.x + p.layout.margins.sibling + offsetVector.x, + y: n.position.y + p.layout.margins.child + offsetVector.y, + }, + })) + ), + offset + increment + p.treePadding, + ]; + }, + [[], 0] + )[0]; return ( ) => { ); return spaceForest([...typeDefTrees, ...termDefTrees]); })()} - onNodeClick={(mouseEvent, node) => - p.onNodeClick(mouseEvent, makeSelectionFromNode(node)) - } - zoomBarProps={p.zoomBarProps} - > - - {p.children} - -); + onNodeClick={(mouseEvent, node) => + p.onNodeClick(mouseEvent, makeSelectionFromNode(node)) + } + zoomBarProps={p.zoomBarProps} + > + + {p.children} + + ); }; export default TreeReactFlow; From dc9385fa26a83ab0500e45040cb723593adafb12 Mon Sep 17 00:00:00 2001 From: George Thomas Date: Tue, 4 Jul 2023 13:05:50 +0100 Subject: [PATCH 3/3] feat: Show type defs on separate row above terms Until we have a smarter approach to forest layout, this at least allows us to make reasonable use of 2D space for typical programs. Signed-off-by: George Thomas --- src/components/TreeReactFlow/index.tsx | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/components/TreeReactFlow/index.tsx b/src/components/TreeReactFlow/index.tsx index 33c9f377..b861e017 100644 --- a/src/components/TreeReactFlow/index.tsx +++ b/src/components/TreeReactFlow/index.tsx @@ -1065,7 +1065,19 @@ export const TreeReactFlow = (p: PropsWithChildren) => { ) ) ); - return spaceForest([...typeDefTrees, ...termDefTrees]); + const typeRowHeight = + typeDefTrees.length > 0 + ? Math.max(...typeDefTrees.map((x) => x.height)) + p.treePadding + : 0; + return [ + ...spaceForest(typeDefTrees), + ...spaceForest(termDefTrees).map((t) => + treeMap(t, ({ position, ...n }) => ({ + position: { x: position.x, y: position.y + typeRowHeight }, + ...n, + })) + ), + ]; })()} onNodeClick={(mouseEvent, node) => p.onNodeClick(mouseEvent, makeSelectionFromNode(node))