Перекомпоновка триггера вниз по составляемой иерархии
Я пытаюсь реализовать представление графа (узлы графа как
Card
s) с перемещаемым (перетаскиванием) рабочим пространством и узлами графа с помощью Jetbrains Compose (рабочий стол /JVM).
Мне удалось сделать перетаскиваемые узлы графа (
GraphNodeBox
), а затем я хотел переместить все узлы при обнаружении перетаскивания во внешнем контейнере узлов (
ViewBox
), но изменение состояния не вызывает перекомпоновку узлов графа. Я отлаживал, зарегистрировал изменение состояния (когда все смещения узлов обновлено), и оно выполняется при перетаскивании, но пользовательский интерфейс не перерисовывается.
@Composable
fun ViewBox() {
var graphNodes by remember {
mutableStateOf(listOf(GraphNode(Item("Test Item")), GraphNode(Item("Test Item 2"))))
}
Box(
modifier = Modifier.fillMaxSize()
.background(Color.Magenta)
.pointerInput(Unit) {
detectDragGestures { change, dragAmount ->
change.consumeAllChanges()
graphNodes = graphNodes.map { graphNode ->
GraphNode.OffsetLens.modify(graphNode) { it + dragAmount }
}
}
}
) {
graphNodes.forEach { // it happens only once initially and is not called again when `graphNodes` state is changed
GraphNodeBox(it)
}
}
}
@Composable
fun GraphNodeBox(graphNode: GraphNode) {
var offset by remember { mutableStateOf(IntOffset(0, 0)) }
Card(
modifier = Modifier.padding(5.dp)
.offset { offset }
.pointerInput(Unit) {
detectDragGestures { change, dragAmount ->
change.consumeAllChanges()
offset += IntOffset(dragAmount.x.toInt(), dragAmount.y.toInt()) // this works like a charm and the offset update triggers recomposition
}
}
) {
Row {
Column(modifier = Modifier.padding(10.dp)) {
Text(
text = graphNode.item.name,
style = MaterialTheme.typography.subtitle1
)
Text(
text = graphNode.item.stereotypes.joinToString { it.toString() },
style = MaterialTheme.typography.subtitle2
)
}
}
}
}
data class GraphNode(
val item: Item,
val offset: Offset = Offset(0f, 0f)
) {
companion object {
val OffsetLens: Lens<GraphNode, Offset> = PLens(
get = { it.offset },
set = { graphNode, value -> graphNode.copy(offset = value) }
)
}
}
Похоже, что обновление состояния внешнего компонента не влияет на вложенные компоненты.
Мне, вероятно, не хватает идеи Jetbrains Compose, и ее нужно реализовать каким-то другим способом, но я не могу придумать правильную реализацию.