diff --git a/pdl-live-react/src/view/timeline/Timeline.tsx b/pdl-live-react/src/view/timeline/Timeline.tsx index 15ad4d28..e429bf33 100644 --- a/pdl-live-react/src/view/timeline/Timeline.tsx +++ b/pdl-live-react/src/view/timeline/Timeline.tsx @@ -55,34 +55,64 @@ function positionOf( : "pop" } -/* function nextSibling(row: TimelineRowModel, idx: number, A: TimelineRowModel[]) { +function nextSibling( + row: TimelineRowModel, + idx: number, + A: TimelineRowModel[], +) { let sidx = idx + 1 while (sidx < A.length && A[sidx].depth > row.depth) { sidx++ } return sidx < A.length && A[sidx].depth === row.depth ? sidx : -1 -} */ +} + +type PushPop = { prefix: boolean[]; position: Position } + +function pushPopsFor(model: TimelineRowModel[]): PushPop[] { + if (model.length === 0) { + return [] + } -/*function pushPopsFor(model: TimelineRowModel[]): { prefix: string, position: Position }[] { - return model.reduce((Ps, row, idx) => { - const position = positionOf(row, idx, model) - if (Ps.parent === -1) { - return {prefix: "", position} + const result: PushPop[] = [] + const stack: number[] = [0] + const prefix: boolean[] = [] + let n = 0 + while (stack.length > 0) { + if (n++ > model.length * 2) { + break } + const rootIdx = stack.pop() - //const siblingIdx = nextSibling(model[Ps.parent], Ps.parent, model) - const prefix = Ps.parentPrefix - if (position === 'push' && Ps.parentHasSibling) { - prefix += "│ " + if (rootIdx === undefined) { + break + } else if (rootIdx < 0) { + prefix.pop() + continue + } - return { - prefix, - position, + const root = model[rootIdx] + const mine = { + prefix: prefix.slice(0), + position: positionOf(root, rootIdx, model), } - }) -} -*/ + result.push(mine) + + stack.push(-rootIdx) + for (let idx = model.length - 1; idx >= rootIdx + 1; idx--) { + if (model[idx].parent === root) { + stack.push(idx) + } + } + + const nextSibIdx = nextSibling(root, rootIdx, model) + if (nextSibIdx < 0) { + prefix.push(false) + mine.position = "pop" + } else { + prefix.push(true) + } + } -function pushPopsFor(model: TimelineRowModel[]): { position: Position }[] { - return model.map((row, idx, A) => ({ position: positionOf(row, idx, A) })) + return result } diff --git a/pdl-live-react/src/view/timeline/TimelineRow.tsx b/pdl-live-react/src/view/timeline/TimelineRow.tsx index 465fe29b..bd5c3bea 100644 --- a/pdl-live-react/src/view/timeline/TimelineRow.tsx +++ b/pdl-live-react/src/view/timeline/TimelineRow.tsx @@ -6,6 +6,7 @@ import { capitalizeAndUnSnakeCase } from "../../helpers" export type Position = "push" | "middle" | "pop" type Props = import("./model").TimelineRowWithExtrema & { + prefix: boolean[] position: Position } @@ -35,12 +36,7 @@ function treeSymbols(row: Props) { } function prefixSymbols(row: Props) { - return row.depth === 0 - ? "" - : Array(row.depth - 1) - .fill("") - .map(() => "│ ") - .join("") + return row.prefix.slice(1).reduce((s, p) => s + (p ? "│ " : " "), "") } function finalSymbol(row: Props) { diff --git a/pdl-live-react/src/view/timeline/model.ts b/pdl-live-react/src/view/timeline/model.ts index 616b3930..65765d10 100644 --- a/pdl-live-react/src/view/timeline/model.ts +++ b/pdl-live-react/src/view/timeline/model.ts @@ -14,6 +14,9 @@ export type TimelineRow = Pick< > & { /** Call tree depth */ depth: number + + /** Parent node */ + parent: null | TimelineRow } export type TimelineRowWithExtrema = TimelineRow & { @@ -29,16 +32,18 @@ export type TimelineModel = TimelineRow[] export function computeModel( block: unknown | PdlBlock, depth = 0, + parent?: TimelineRow, ): TimelineModel { if (!hasTimingInformation(block)) { return [] } + const root = Object.assign({ depth, parent: parent || null }, block) return [ - Object.assign({ depth }, block), + root, ...childrenOf(block) .filter(nonNullable) - .flatMap((child) => computeModel(child, depth + 1)), + .flatMap((child) => computeModel(child, depth + 1, root)), ] }