From bc945c634c75bfae3238ed49e416a768a75af30c Mon Sep 17 00:00:00 2001 From: Adam Berger Date: Thu, 31 Aug 2023 15:02:08 -0400 Subject: [PATCH] feat: support horizontal or vertical layout --- src/components/flow-graph/index.tsx | 9 ++++++++- src/transformers/elk.ts | 31 ++++++++++++++++++----------- 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/src/components/flow-graph/index.tsx b/src/components/flow-graph/index.tsx index bc79911..610a7c2 100644 --- a/src/components/flow-graph/index.tsx +++ b/src/components/flow-graph/index.tsx @@ -53,6 +53,7 @@ type Action = export type FlowGraphProps = { flow: DrawableFlow; selectedItems?: Array; + direction?: "horizontal" | "vertical"; editable?: { getAvailableStates: () => Array<{ id: schema.StateId; name: string }>; onUpdateTransitionTarget: ( @@ -125,6 +126,7 @@ export const FlowGraph = ({ selectedItems: providedSelectedItems, editable, header, + direction = "vertical", renderButtons, }: FlowGraphProps) => { const selectedItems = providedSelectedItems ?? emptySelectedItems; @@ -202,7 +204,12 @@ export const FlowGraph = ({ } const thisLayoutId = nextLayoutId(); - const graph = flowToElkGraph(sizeMap.current!, rootId, fullFlow); + const graph = flowToElkGraph( + sizeMap.current!, + rootId, + fullFlow, + direction + ); const elk = getElk(); elk.layout(graph).then((layout) => { dispatch({ diff --git a/src/transformers/elk.ts b/src/transformers/elk.ts index 341cf70..82b9e6d 100644 --- a/src/transformers/elk.ts +++ b/src/transformers/elk.ts @@ -16,26 +16,26 @@ export type EnrichedElkNode = ElkNode & { children?: EnrichedElkNode[]; }; -const rootNodeLayoutOptions = { +const rootNodeLayoutOptions = (direction: "horizontal" | "vertical") => ({ "elk.hierarchyHandling": "INCLUDE_CHILDREN", "elk.algorithm": "layered", "elk.layered.considerModelOrder": "NODES_AND_EDGES", "elk.layered.wrapping.strategy": "MULTI_EDGE", - "elk.aspectRatio": "0.5", - "elk.direction": "DOWN", + "elk.aspectRatio": direction === "vertical" ? "0.5" : "2", + "elk.direction": direction === "vertical" ? "DOWN" : "RIGHT", "elk.layered.spacing.baseValue": "25", //"elk.layered.compaction.postCompaction.strategy": "TOP", // TODO: this may fail -}; +}); -const nodeLayoutOptions = { +const nodeLayoutOptions = (direction: "horizontal" | "vertical") => ({ "elk​.alignment": "CENTER", - "elk.aspectRatio": "0.5", - "elk.direction": "DOWN", + "elk.aspectRatio": direction === "vertical" ? "0.5" : "2", + "elk.direction": direction === "vertical" ? "DOWN" : "RIGHT", "elk.layered.edgeRouting.selfLoopOrdering": "SEQUENCED", "elk.layered.edgeRouting.selfLoopDistribution": "EQUALLY", "elk.layered.spacing.baseValue": "25", //"elk.layered.compaction.postCompaction.strategy": "TOP", // TODO: this may fail -}; +}); export type PositionedItemId = string & { _BRAND: "positionedItem" }; @@ -168,7 +168,8 @@ export type Size = { export function flowToElkGraph( sizeMap: Map, rootId: schema.StateId, - flow: DrawableFlowWithTopLevelState + flow: DrawableFlowWithTopLevelState, + direction: "horizontal" | "vertical" ): EnrichedElkNode { const edgeIdsByTarget = getEdgeIdsByTarget(flow.states); const node = _flowToElkGraph( @@ -176,7 +177,9 @@ export function flowToElkGraph( rootId, edgeIdsByTarget, flow.states, - rootId + rootId, + rootNodeLayoutOptions(direction), + nodeLayoutOptions(direction) )[0]; return node; } @@ -230,7 +233,9 @@ export function _flowToElkGraph( rootId: schema.StateId, edgeIdsByTarget: EdgeIdsByTarget, states: DrawableFlow["states"], - stateId: schema.StateId + stateId: schema.StateId, + rootNodeLayoutOptions: Record, + nodeLayoutOptions: Record ): [EnrichedElkNode, Set] { const childNodes = Object.entries(states) .filter(([_stateId, state]) => state!.parent === stateId) @@ -318,7 +323,9 @@ export function _flowToElkGraph( rootId, edgeIdsByTarget, states, - stateId + stateId, + rootNodeLayoutOptions, + nodeLayoutOptions ); descendants = union(descendants, nodes);