Refactor ObjectTree to functional component

This commit is contained in:
Alexander Nozik 2020-04-18 17:51:26 +03:00
parent ac86832616
commit 28ca287ccd
2 changed files with 51 additions and 54 deletions

View File

@ -1,17 +1,17 @@
package hep.dataforge.js package hep.dataforge.js
import react.RComponent import react.RBuilder
import kotlin.properties.ReadWriteProperty import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty import kotlin.reflect.KProperty
fun <T> RComponent<*, *>.initState(init: () -> T): ReadWriteProperty<RComponent<*, *>, T> = fun <T> RBuilder.initState(init: () -> T): ReadWriteProperty<Any?, T> =
object : ReadWriteProperty<RComponent<*, *>, T> { object : ReadWriteProperty<Any?, T> {
val pair = react.useState(init) val pair = react.useState(init)
override fun getValue(thisRef: RComponent<*, *>, property: KProperty<*>): T { override fun getValue(thisRef: Any?, property: KProperty<*>): T {
return pair.first return pair.first
} }
override fun setValue(thisRef: RComponent<*, *>, property: KProperty<*>, value: T) { override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
pair.second(value) pair.second(value)
} }
} }

View File

@ -1,6 +1,7 @@
package hep.dataforge.vis.editor package hep.dataforge.vis.editor
import hep.dataforge.js.card import hep.dataforge.js.card
import hep.dataforge.js.initState
import hep.dataforge.names.Name import hep.dataforge.names.Name
import hep.dataforge.names.plus import hep.dataforge.names.plus
import hep.dataforge.names.startsWith import hep.dataforge.names.startsWith
@ -25,20 +26,14 @@ interface TreeState : RState {
var expanded: Boolean var expanded: Boolean
} }
class ObjectTree : RComponent<ObjectTreeProps, TreeState>() { private fun RBuilder.objectTree(props: ObjectTreeProps): Unit {
var expanded: Boolean by initState{ props.selected?.startsWith(props.name) ?: false }
override fun TreeState.init(props: ObjectTreeProps) { val onClick: (Event) -> Unit = {
expanded = props.selected?.startsWith(props.name) ?: false
}
private val onClick: (Event) -> Unit = {
setState {
expanded = !expanded expanded = !expanded
} }
}
private fun RBuilder.treeLabel(text: String) { fun RBuilder.treeLabel(text: String) {
button(classes = "btn btn-link tree-label p-0") { button(classes = "btn btn-link tree-label p-0") {
+text +text
attrs { attrs {
@ -50,7 +45,6 @@ class ObjectTree : RComponent<ObjectTreeProps, TreeState>() {
} }
} }
override fun RBuilder.render() {
val token = props.name.last()?.toString() ?: "World" val token = props.name.last()?.toString() ?: "World"
val obj = props.obj val obj = props.obj
@ -60,7 +54,7 @@ class ObjectTree : RComponent<ObjectTreeProps, TreeState>() {
if (obj.children.any { !it.key.body.startsWith("@") }) { if (obj.children.any { !it.key.body.startsWith("@") }) {
span("tree-caret") { span("tree-caret") {
attrs { attrs {
if (state.expanded) { if (expanded) {
classes += "tree-caret-down" classes += "tree-caret-down"
} }
onClickFunction = onClick onClickFunction = onClick
@ -69,14 +63,14 @@ class ObjectTree : RComponent<ObjectTreeProps, TreeState>() {
} }
treeLabel(token) treeLabel(token)
} }
if (state.expanded) { if (expanded) {
ul("tree") { ul("tree") {
obj.children.entries obj.children.entries
.filter { !it.key.toString().startsWith("@") } // ignore statics and other hidden children .filter { !it.key.toString().startsWith("@") } // ignore statics and other hidden children
.sortedBy { (it.value as? VisualGroup)?.isEmpty ?: true } .sortedBy { (it.value as? VisualGroup)?.isEmpty ?: true }
.forEach { (childToken, child) -> .forEach { (childToken, child) ->
li("tree-item") { li("tree-item") {
child(ObjectTree::class) { child(ObjectTree) {
attrs { attrs {
name = props.name + childToken name = props.name + childToken
this.obj = child this.obj = child
@ -95,6 +89,9 @@ class ObjectTree : RComponent<ObjectTreeProps, TreeState>() {
} }
} }
} }
val ObjectTree: FunctionalComponent<ObjectTreeProps> = functionalComponent { props ->
objectTree(props)
} }
fun Element.renderObjectTree( fun Element.renderObjectTree(
@ -102,7 +99,7 @@ fun Element.renderObjectTree(
clickCallback: (Name) -> Unit = {} clickCallback: (Name) -> Unit = {}
) = render(this) { ) = render(this) {
card("Object tree") { card("Object tree") {
child(ObjectTree::class) { child(ObjectTree) {
attrs { attrs {
this.name = Name.EMPTY this.name = Name.EMPTY
this.obj = visualObject this.obj = visualObject
@ -118,7 +115,7 @@ fun RBuilder.objectTree(
selected: Name? = null, selected: Name? = null,
clickCallback: (Name) -> Unit = {} clickCallback: (Name) -> Unit = {}
) { ) {
child(ObjectTree::class) { child(ObjectTree) {
attrs { attrs {
this.name = Name.EMPTY this.name = Name.EMPTY
this.obj = visualObject this.obj = visualObject