| 73 | } |
| 74 | |
| 75 | export function renderTree( |
| 76 | builder: DrawlistBuilder, |
| 77 | focusState: FocusState, |
| 78 | layoutTree: LayoutTree, |
| 79 | idRectIndex: IdRectIndex, |
| 80 | viewport: Readonly<{ cols: number; rows: number }>, |
| 81 | theme: Theme, |
| 82 | tick: number, |
| 83 | inheritedStyle: ResolvedTextStyle, |
| 84 | tree: RuntimeInstance, |
| 85 | animatedRectByInstanceId: ReadonlyMap<InstanceId, Rect> | undefined, |
| 86 | animatedOpacityByInstanceId: ReadonlyMap<InstanceId, number> | undefined, |
| 87 | cursorInfo: CursorInfo | undefined, |
| 88 | virtualListStore: VirtualListStateStore | undefined, |
| 89 | tableStore: TableStateStore | undefined, |
| 90 | treeStore: TreeStateStore | undefined, |
| 91 | loadedTreeChildrenById: ReadonlyMap<string, ReadonlyMap<string, readonly unknown[]>> | undefined, |
| 92 | commandPaletteItemsById: ReadonlyMap<string, readonly CommandItem[]> | undefined, |
| 93 | commandPaletteLoadingById: ReadonlyMap<string, boolean> | undefined, |
| 94 | toolApprovalFocusedActionById: ReadonlyMap<string, "allow" | "deny" | "allowSession"> | undefined, |
| 95 | dropdownSelectedIndexById: ReadonlyMap<string, number> | undefined, |
| 96 | dropdownWindowStartById: ReadonlyMap<string, number> | undefined, |
| 97 | diffViewerFocusedHunkById: ReadonlyMap<string, number> | undefined, |
| 98 | diffViewerExpandedHunksById: ReadonlyMap<string, ReadonlySet<number>> | undefined, |
| 99 | tableRenderCacheById: ReadonlyMap<string, TableRenderCache> | undefined, |
| 100 | logsConsoleRenderCacheById: ReadonlyMap<string, LogsConsoleRenderCache> | undefined, |
| 101 | diffRenderCacheById: ReadonlyMap<string, DiffRenderCache> | undefined, |
| 102 | codeEditorRenderCacheById: ReadonlyMap<string, CodeEditorRenderCache> | undefined, |
| 103 | focusAnnouncement: string | null | undefined, |
| 104 | opts: RenderTreeOptions | undefined = undefined, |
| 105 | terminalProfile: TerminalProfile | undefined = undefined, |
| 106 | pressedId: string | null = null, |
| 107 | ): ResolvedCursor | null { |
| 108 | let resolvedCursor: ResolvedCursor | null = null; |
| 109 | let lastRenderedNodeKind = tree.vnode.kind; |
| 110 | const damageRect = opts?.damageRect; |
| 111 | const skipCleanSubtrees = opts?.skipCleanSubtrees ?? damageRect !== undefined; |
| 112 | const hasAnimatedRects = |
| 113 | animatedRectByInstanceId !== undefined && animatedRectByInstanceId.size > 0; |
| 114 | const hasAnimatedOpacity = |
| 115 | animatedOpacityByInstanceId !== undefined && animatedOpacityByInstanceId.size > 0; |
| 116 | |
| 117 | const nodeStack: RenderNodeTask[] = [tree]; |
| 118 | const styleStack: ResolvedTextStyle[] = [inheritedStyle]; |
| 119 | const layoutStack: LayoutTree[] = [layoutTree]; |
| 120 | const clipStack: (ClipRect | undefined)[] = [undefined]; |
| 121 | const themeStack: Theme[] = [theme]; |
| 122 | |
| 123 | while (nodeStack.length > 0) { |
| 124 | const nodeOrPop = nodeStack.pop(); |
| 125 | if (nodeOrPop === null) { |
| 126 | builder.popClip(); |
| 127 | continue; |
| 128 | } |
| 129 | if (!nodeOrPop) continue; |
| 130 | const currentTheme = themeStack.pop() ?? theme; |
| 131 | const parentStyle = styleStack.pop(); |
| 132 | if (!parentStyle) continue; |