NodeTreeView¶
@Composable
fun <T> NodeTreeView(
roots: List<T>,
children: (T) -> List<T>,
parents: (T) -> List<T>? = null,
modifier: Modifier = Modifier,
columnGap: Int = DEFAULT_COLUMN_GAP,
rowGap: Int = DEFAULT_ROW_GAP,
connectorStyle: (T) -> ConnectorStyle = { ConnectorStyle.SOLID },
connectorColor: (T) -> Int = { DEFAULT_LINE_COLOR },
connectorThickness: (T) -> Int = { DEFAULT_LINE_THICKNESS },
connectorAnimation: (T) -> ConnectorAnimation = { ConnectorAnimation.NONE },
connectorShape: (T) -> ConnectorShape = { ConnectorShape.ELBOW },
connectorDirection: (T) -> ConnectorDirection = { ConnectorDirection.CHILD_TO_PARENT },
nodeAnimation: (T) -> NodeAnimation = { NodeAnimation.NONE },
rootAlignment: RootAlignment = RootAlignment.START,
dedupe: Boolean = false,
showNodeHints: Boolean = true,
key: (T) -> Any? = { it },
visible: (T) -> Boolean = { true },
onVisibilityChanged: (T, Boolean) -> Unit = { _, _ -> },
state: PannableCanvasState = rememberPannableCanvasState(),
backgroundTexture: ResourceLocation? = null,
backgroundTextureSize: Int = 32,
backgroundTint: Int = -1,
backgroundParallax: Float = 1.0f,
panelTexture: String = "surface",
panelVariant: String? = "inset_transparent",
panelContentPadding: Int = 2,
content: @Composable
(T) -> Unit
)
A pannable, zoomable, node-based forest view - one or more independent trees (roots, plural), one column per depth, tidily packed rows connected by elbow connectors (see assignRows). children extracts a node's own children; content draws one node's own visual content at its measured natural size. Connectors draw (and, for ConnectorStyle.ARROW/ ConnectorAnimation.FLOWING, animate) child-to-parent by default - see connectorDirection to flip that - and route around, never behind, whatever else sits between their two ends (see pointsFor). Draws a genuine tree by default (a node reachable through more than one parent is drawn once per parent); pass dedupe = true (with key) to collapse repeats into one visual node with multiple incoming connectors instead.
Parameters¶
-
parents: An optional second way to declare an edge, alongside
children- a caller whose own domain model tracks both directions can declare a node's extra prerequisites from that node itself. Only adds connectors between nodeschildrenalready reached fromroots; a declared parent it never reaches draws as a short dead-end stub instead of being dropped. -
connectorStyle: Chooses a
ConnectorStyleper node, keyed by the child end of its own connector to its parent. Overridden byConnectorStyle.DISCONNECTEDwhenever either end is rejected byvisible. -
connectorColor: /
connectorThicknessPer-node color/thickness for that node's connector. -
connectorAnimation: Per-node
ConnectorAnimation, layered on top ofconnectorStyle. -
connectorShape: Per-node
ConnectorShape- the connector's path shape, orthogonal toconnectorStyle/connectorAnimation. -
connectorDirection: Per-node
ConnectorDirection- which end the arrowhead/flow lands on. -
nodeAnimation: Per-node
NodeAnimationtinting that node's owncontentdirectly. -
rootAlignment: Which side of the drawn forest every tree's root sits on.
-
visible: A node this rejects is still fully discovered/measured/laid out, so the forest's shape never shifts depending on what's hidden - see
layoutForest. Itscontentnever draws, and every connector touching it draws asConnectorStyle.DISCONNECTEDinstead. -
onVisibilityChanged: Called whenever a node already admitted by
visiblescrolls into or out of the current pan/zoom viewport - a screen-space fact, unrelated to tree membership. -
state: Exposed so a caller can reset/center the pan/zoom itself.
-
backgroundParallax: /
backgroundTint/panelTexture/panelVariant/panelContentPaddingForwarded straight toPannableCanvas's own parameters of the same names.
@Composable
fun <K : Any, V, B : NodeBuilder<K, V, B>> NodeTreeView(
roots: TreeRegistry<K, V, B>,
modifier: Modifier = Modifier,
columnGap: Int = 26,
rowGap: Int = 6,
connectorStyle: (TreeNode<K, V>) -> ConnectorStyle = { ConnectorStyle.SOLID },
connectorColor: (TreeNode<K, V>) -> Int = { 0xFF808080.toInt() },
connectorThickness: (TreeNode<K, V>) -> Int = { 1 },
connectorAnimation: (TreeNode<K, V>) -> ConnectorAnimation = { ConnectorAnimation.NONE },
connectorShape: (TreeNode<K, V>) -> ConnectorShape = { ConnectorShape.ELBOW },
connectorDirection: (TreeNode<K, V>) -> ConnectorDirection = { ConnectorDirection.CHILD_TO_PARENT },
nodeAnimation: (TreeNode<K, V>) -> NodeAnimation = { NodeAnimation.NONE },
rootAlignment: RootAlignment = RootAlignment.START,
visible: (TreeNode<K, V>) -> Boolean = { true },
onVisibilityChanged: (TreeNode<K, V>, Boolean) -> Unit = { _, _ -> },
state: PannableCanvasState = rememberPannableCanvasState(),
backgroundTexture: ResourceLocation? = null,
backgroundTextureSize: Int = 32,
backgroundTint: Int = -1,
backgroundParallax: Float = 1.0f,
panelTexture: String = "surface",
panelVariant: String? = "inset_transparent",
panelContentPadding: Int = 5,
content: @Composable
(TreeNode<K, V>) -> Unit
)
NodeTreeView's general-purpose List<T>/children:/parents:/key: surface, specialized for a forest already built as a TreeRegistry. Every structural parameter reads TreeNode.children/ TreeNode.parents/TreeNode.id directly; a caller only supplies cosmetic per-node callbacks and content. dedupe is always on, since a TreeNode's own id already identifies it.
Parameters¶
-
roots: The
TreeRegistryreturned. -
visible: See
NodeTreeView's ownvisibleparameter. -
backgroundParallax: /
backgroundTint/panelTexture/panelVariant/panelContentPaddingForwarded straight to the generalNodeTreeViewoverload's own parameters of the same names.