mirror of
https://github.com/AdrianKuta/Tree-Data-Structure.git
synced 2026-06-19 19:00:14 +02:00
Add the `android` target to the Compose Multiplatform library and a sensible
default renderer, so the largest Compose audience is a first-class consumer.
- Core `tree-structure` and `tree-structure-compose` now build and publish an
`-android` variant (compileSdk 35, minSdk 21). The core needs it too: its
inline `tree { }` DSL is built per target, and Android consumers (JVM 11/17)
cannot inline a JVM-21 build.
- `TreeNodeRow`: a foundation-only default node row (clickable, indented, with a
`▾`/`▸` marker, no Material dependency), plus a no-content `LazyTree(root,
label = …)` overload that uses it. The existing lambda overload is unchanged.
- New `samples` Android app module demonstrating `LazyTree` + `@Preview`
(not published; excluded from API validation).
- Toolchain: Gradle wrapper 8.5 -> 8.10.2, Android Gradle Plugin 8.7.2.
- binary-compatibility-validator now emits per-target dumps (api/jvm, api/android)
for the two multi-JVM-target modules; CI assembles the Android outputs.
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
public final class com/github/adriankuta/datastructure/tree/compose/LazyTreeKt {
|
||||
public static final fun LazyTree (Lcom/github/adriankuta/datastructure/tree/TreeNode;Landroidx/compose/ui/Modifier;ZLkotlin/jvm/functions/Function6;Landroidx/compose/runtime/Composer;II)V
|
||||
public static final fun LazyTree-hGBTI10 (Lcom/github/adriankuta/datastructure/tree/TreeNode;Landroidx/compose/ui/Modifier;ZFLkotlin/jvm/functions/Function1;Landroidx/compose/runtime/Composer;II)V
|
||||
}
|
||||
|
||||
public final class com/github/adriankuta/datastructure/tree/compose/TreeNodeRowKt {
|
||||
public static final fun TreeNodeRow-PfoAEA0 (Lcom/github/adriankuta/datastructure/tree/TreeNode;IZLkotlin/jvm/functions/Function0;Landroidx/compose/ui/Modifier;FLkotlin/jvm/functions/Function1;Landroidx/compose/runtime/Composer;II)V
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
public final class com/github/adriankuta/datastructure/tree/compose/LazyTreeKt {
|
||||
public static final fun LazyTree (Lcom/github/adriankuta/datastructure/tree/TreeNode;Landroidx/compose/ui/Modifier;ZLkotlin/jvm/functions/Function6;Landroidx/compose/runtime/Composer;II)V
|
||||
public static final fun LazyTree-hGBTI10 (Lcom/github/adriankuta/datastructure/tree/TreeNode;Landroidx/compose/ui/Modifier;ZFLkotlin/jvm/functions/Function1;Landroidx/compose/runtime/Composer;II)V
|
||||
}
|
||||
|
||||
public final class com/github/adriankuta/datastructure/tree/compose/TreeNodeRowKt {
|
||||
public static final fun TreeNodeRow-PfoAEA0 (Lcom/github/adriankuta/datastructure/tree/TreeNode;IZLkotlin/jvm/functions/Function0;Landroidx/compose/ui/Modifier;FLkotlin/jvm/functions/Function1;Landroidx/compose/runtime/Composer;II)V
|
||||
}
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
public final class com/github/adriankuta/datastructure/tree/compose/LazyTreeKt {
|
||||
public static final fun LazyTree (Lcom/github/adriankuta/datastructure/tree/TreeNode;Landroidx/compose/ui/Modifier;ZLkotlin/jvm/functions/Function6;Landroidx/compose/runtime/Composer;II)V
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
|
||||
|
||||
plugins {
|
||||
alias(libs.plugins.kotlinMultiplatform)
|
||||
alias(libs.plugins.androidLibrary)
|
||||
alias(libs.plugins.composeMultiplatform)
|
||||
alias(libs.plugins.composeCompiler)
|
||||
alias(libs.plugins.dokka)
|
||||
@@ -68,6 +69,14 @@ kotlin {
|
||||
|
||||
jvm()
|
||||
|
||||
androidTarget {
|
||||
publishLibraryVariants("release")
|
||||
// Match the Android variant's Kotlin bytecode to the Java level set in compileOptions.
|
||||
compilerOptions {
|
||||
jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17)
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalWasmDsl::class)
|
||||
wasmJs {
|
||||
browser()
|
||||
@@ -85,3 +94,15 @@ kotlin {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "com.github.adriankuta.datastructure.tree.compose"
|
||||
compileSdk = libs.versions.androidCompileSdk.get().toInt()
|
||||
defaultConfig {
|
||||
minSdk = libs.versions.androidMinSdk.get().toInt()
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.mutableStateMapOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.github.adriankuta.datastructure.tree.TreeNode
|
||||
|
||||
/**
|
||||
@@ -49,6 +51,35 @@ public fun <T> LazyTree(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience overload of [LazyTree] that renders each node with the built-in [TreeNodeRow], so the
|
||||
* common case is a single call:
|
||||
*
|
||||
* ```
|
||||
* LazyTree(root)
|
||||
* ```
|
||||
*
|
||||
* Use the overload that takes a `nodeContent` lambda when you need full control over a node's look.
|
||||
*
|
||||
* @param root the root of the tree to display.
|
||||
* @param modifier the [Modifier] applied to the underlying [LazyColumn].
|
||||
* @param initiallyExpanded whether nodes start expanded.
|
||||
* @param indent the horizontal indentation applied per depth level.
|
||||
* @param label maps a node's value to the text shown. Defaults to `toString()`.
|
||||
*/
|
||||
@Composable
|
||||
public fun <T> LazyTree(
|
||||
root: TreeNode<T>,
|
||||
modifier: Modifier = Modifier,
|
||||
initiallyExpanded: Boolean = true,
|
||||
indent: Dp = 16.dp,
|
||||
label: (T) -> String = { it.toString() },
|
||||
) {
|
||||
LazyTree(root, modifier, initiallyExpanded) { node, depth, expanded, toggle ->
|
||||
TreeNodeRow(node, depth, expanded, toggle, indent = indent, label = label)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Flattens the tree into the list of currently-visible `(node, depth)` pairs in pre-order, skipping
|
||||
* the subtrees of collapsed nodes. Iterative, so it is safe on deep trees.
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.github.adriankuta.datastructure.tree.compose
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.text.BasicText
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.github.adriankuta.datastructure.tree.TreeNode
|
||||
|
||||
/**
|
||||
* A sensible default row for a single node in a [LazyTree]. The whole row is clickable to expand or
|
||||
* collapse, indentation reflects [depth], and a `▾`/`▸` marker precedes non-leaf nodes.
|
||||
*
|
||||
* It is intentionally foundation-only (no Material), so using it does not pull a theming dependency
|
||||
* into your app. For full control over a node's appearance, use the `LazyTree` overload that takes a
|
||||
* `nodeContent` lambda instead.
|
||||
*
|
||||
* ```
|
||||
* LazyTree(root) { node, depth, expanded, toggle ->
|
||||
* TreeNodeRow(node, depth, expanded, toggle)
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param node the node to render.
|
||||
* @param depth the node's depth in the tree (root = 0), used for indentation.
|
||||
* @param expanded whether the node is currently expanded.
|
||||
* @param toggle flips this node's expansion state; invoked when the row is clicked.
|
||||
* @param modifier the [Modifier] applied to the row.
|
||||
* @param indent the horizontal indentation applied per depth level.
|
||||
* @param label maps the node's value to the text shown. Defaults to `toString()`.
|
||||
*/
|
||||
@Composable
|
||||
public fun <T> TreeNodeRow(
|
||||
node: TreeNode<T>,
|
||||
depth: Int,
|
||||
expanded: Boolean,
|
||||
toggle: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
indent: Dp = 16.dp,
|
||||
label: (T) -> String = { it.toString() },
|
||||
) {
|
||||
val marker = when {
|
||||
node.children.isEmpty() -> ""
|
||||
expanded -> "▾ "
|
||||
else -> "▸ "
|
||||
}
|
||||
Row(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.clickable(onClick = toggle)
|
||||
.padding(start = indent * depth, top = 8.dp, bottom = 8.dp, end = 8.dp),
|
||||
) {
|
||||
BasicText(text = marker + label(node.value))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user