Name breadcrumbs in property editor for #10

This commit is contained in:
Alexander Nozik 2020-01-02 11:23:09 +03:00
parent d36542ac5b
commit 9e43d2c572
7 changed files with 73 additions and 55 deletions

View File

@ -61,6 +61,7 @@ data class StyleRef(val group: VisualGroup, val styleName: Name)
val VisualGroup.isEmpty: Boolean get() = this.children.isEmpty() val VisualGroup.isEmpty: Boolean get() = this.children.isEmpty()
interface MutableVisualGroup : VisualGroup { interface MutableVisualGroup : VisualGroup {
/** /**

View File

@ -1,6 +1,8 @@
package hep.dataforge.vis.js.editor package hep.dataforge.vis.js.editor
import hep.dataforge.names.Name
import hep.dataforge.names.NameToken import hep.dataforge.names.NameToken
import hep.dataforge.names.plus
import hep.dataforge.vis.common.VisualGroup import hep.dataforge.vis.common.VisualGroup
import hep.dataforge.vis.common.VisualObject import hep.dataforge.vis.common.VisualObject
import hep.dataforge.vis.common.isEmpty import hep.dataforge.vis.common.isEmpty
@ -15,58 +17,62 @@ import kotlin.dom.clear
fun Element.objectTree( fun Element.objectTree(
token: NameToken, token: NameToken,
obj: VisualObject, obj: VisualObject,
clickCallback: (VisualObject) -> Unit = {} clickCallback: (Name, VisualObject) -> Unit = {_,_->}
) { ) {
clear() clear()
append { append {
card("Object tree") { card("Object tree") {
subTree(token, obj, clickCallback) subTree(Name.EMPTY, token, obj, clickCallback)
} }
} }
} }
private fun TagConsumer<HTMLElement>.subTree( private fun TagConsumer<HTMLElement>.subTree(
parentName: Name,
token: NameToken, token: NameToken,
obj: VisualObject, obj: VisualObject,
clickCallback: (VisualObject) -> Unit clickCallback: (Name, VisualObject) -> Unit
) { ) {
val fullName = parentName + token
if (obj is VisualGroup && !obj.isEmpty) { //display as node if any child is visible
if (obj is VisualGroup && obj.children.keys.any { !it.body.startsWith("@") }) {
lateinit var toggle: HTMLSpanElement lateinit var toggle: HTMLSpanElement
div("d-inline-block text-truncate") { div("d-inline-block text-truncate") {
toggle = span("objTree-caret") toggle = span("objTree-caret")
label("objTree-label") { label("objTree-label") {
+token.toString() +token.toString()
onClickFunction = { clickCallback(obj) } onClickFunction = { clickCallback(fullName, obj) }
} }
} }
val subtree = ul("objTree-subtree") val subtree = ul("objTree-subtree")
toggle.onclick = { toggle.onclick = {
toggle.classList.toggle("objTree-caret-down") toggle.classList.toggle("objTree-caret-down")
subtree.apply { subtree.apply {
//If expanded, add children dynamically
if (toggle.classList.contains("objTree-caret-down")) { if (toggle.classList.contains("objTree-caret-down")) {
obj.children.entries obj.children.entries
.filter { !it.key.toString().startsWith("@") } .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 { (token, child) -> .forEach { (childToken, child) ->
append { append {
li().apply { li().apply {
subTree(token, child, clickCallback) subTree(fullName, childToken, child, clickCallback)
} }
} }
} }
} else { } else {
// if not, clear them to conserve memory on very long lists
this.clear() this.clear()
} }
} }
//jQuery(subtree).asDynamic().collapse("toggle")
} }
} else { } else {
div("d-inline-block text-truncate") { val div = div("d-inline-block text-truncate") {
span("objTree-leaf") span("objTree-leaf")
label("objTree-label") { label("objTree-label") {
+token.toString() +token.toString()
onClickFunction = { clickCallback(obj) } onClickFunction = { clickCallback(fullName, obj) }
} }
} }
} }

View File

@ -5,11 +5,12 @@ import hep.dataforge.js.jsObject
import hep.dataforge.meta.DynamicMeta import hep.dataforge.meta.DynamicMeta
import hep.dataforge.meta.Meta import hep.dataforge.meta.Meta
import hep.dataforge.meta.update import hep.dataforge.meta.update
import hep.dataforge.names.Name
import hep.dataforge.names.isEmpty
import hep.dataforge.vis.common.VisualObject import hep.dataforge.vis.common.VisualObject
import hep.dataforge.vis.common.findStyle import hep.dataforge.vis.common.findStyle
import kotlinx.html.dom.append import kotlinx.html.dom.append
import kotlinx.html.js.div import kotlinx.html.js.*
import kotlinx.html.js.h4
import org.w3c.dom.Element import org.w3c.dom.Element
import kotlin.dom.clear import kotlin.dom.clear
@ -17,11 +18,23 @@ import kotlin.dom.clear
fun Meta.toDynamic() = JSON.parse<dynamic>(toJson().toString()) fun Meta.toDynamic() = JSON.parse<dynamic>(toJson().toString())
//TODO add node descriptor instead of configuring property selector //TODO add node descriptor instead of configuring property selector
fun Element.propertyEditor(item: VisualObject?, propertySelector: (VisualObject) -> Meta = { it.config }) { fun Element.propertyEditor(name: Name, item: VisualObject, propertySelector: (VisualObject) -> Meta = { it.config }) {
clear() clear()
if (item != null) {
append { append {
card("Properties") { card("Properties") {
if(!name.isEmpty()) {
nav {
attributes["aria-label"] = "breadcrumb"
ol("breadcrumb") {
name.tokens.forEach {token->
li("breadcrumb-item") {
+token.toString()
}
}
}
}
}
val dMeta: dynamic = propertySelector(item).toDynamic() val dMeta: dynamic = propertySelector(item).toDynamic()
val options: JSONEditorOptions = jsObject { val options: JSONEditorOptions = jsObject {
mode = "form" mode = "form"
@ -52,5 +65,4 @@ fun Element.propertyEditor(item: VisualObject?, propertySelector: (VisualObject)
} }
} }
} }
}
} }

View File

@ -49,6 +49,7 @@ class Visual3DPlugin(meta: Meta) : AbstractPlugin(meta) {
Box::class with Box.serializer() Box::class with Box.serializer()
Convex::class with Convex.serializer() Convex::class with Convex.serializer()
Extruded::class with Extruded.serializer() Extruded::class with Extruded.serializer()
addSubclass(PolyLine.serializer())
addSubclass(Label3D.serializer()) addSubclass(Label3D.serializer())
} }
} }

View File

@ -2,11 +2,11 @@ package hep.dataforge.vis.spatial.gdml.demo
import hep.dataforge.context.Global import hep.dataforge.context.Global
import hep.dataforge.js.Application import hep.dataforge.js.Application
import hep.dataforge.vis.js.editor.objectTree
import hep.dataforge.js.startApplication import hep.dataforge.js.startApplication
import hep.dataforge.meta.buildMeta import hep.dataforge.meta.buildMeta
import hep.dataforge.meta.withBottom import hep.dataforge.meta.withBottom
import hep.dataforge.names.NameToken import hep.dataforge.names.NameToken
import hep.dataforge.vis.js.editor.objectTree
import hep.dataforge.vis.js.editor.propertyEditor import hep.dataforge.vis.js.editor.propertyEditor
import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_COLOR_KEY import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_COLOR_KEY
import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_OPACITY_KEY import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_OPACITY_KEY
@ -159,8 +159,8 @@ private class GDMLDemoApp : Application {
output.camera.layers.set(0) output.camera.layers.set(0)
configElement.threeSettings(output) configElement.threeSettings(output)
//tree.visualObjectTree(visual, editor::propertyEditor) //tree.visualObjectTree(visual, editor::propertyEditor)
treeElement.objectTree(NameToken("World"), visual) { treeElement.objectTree(NameToken("World"), visual) { objName, obj ->
editorElement.propertyEditor(it) { item -> editorElement.propertyEditor(objName, obj) { item ->
//val descriptorMeta = Material3D.descriptor //val descriptorMeta = Material3D.descriptor
val properties = item.allProperties() val properties = item.allProperties()

View File

@ -35,7 +35,7 @@ private class GDMLDemoApp : Application {
private val model = Model() private val model = Model()
private val connection = HttpClient{ private val connection = HttpClient {
install(JsonFeature) { install(JsonFeature) {
serializer = KotlinxSerializer(Visual3DPlugin.json) serializer = KotlinxSerializer(Visual3DPlugin.json)
} }
@ -52,7 +52,6 @@ private class GDMLDemoApp : Application {
document.getElementById("settings") ?: error("Element with id 'settings' not found on page") document.getElementById("settings") ?: error("Element with id 'settings' not found on page")
val treeElement = document.getElementById("tree") ?: error("Element with id 'tree' not found on page") val treeElement = document.getElementById("tree") ?: error("Element with id 'tree' not found on page")
val editorElement = document.getElementById("editor") ?: error("Element with id 'editor' not found on page") val editorElement = document.getElementById("editor") ?: error("Element with id 'editor' not found on page")
canvasElement.clear()
canvasElement.clear() canvasElement.clear()
val visual: VisualObject3D = model.root val visual: VisualObject3D = model.root
@ -63,7 +62,7 @@ private class GDMLDemoApp : Application {
output.camera.layers.set(0) output.camera.layers.set(0)
output.camera.position.z = -2000.0 output.camera.position.z = -2000.0
output.camera.position.y = 500.0 output.camera.position.y = 500.0
settingsElement.threeSettings(output){ settingsElement.threeSettings(output) {
card("Events") { card("Events") {
button { button {
+"Next" +"Next"
@ -83,8 +82,8 @@ private class GDMLDemoApp : Application {
} }
} }
//tree.visualObjectTree(visual, editor::propertyEditor) //tree.visualObjectTree(visual, editor::propertyEditor)
treeElement.objectTree(NameToken("World"), visual) { treeElement.objectTree(NameToken("World"), visual) { name, obj ->
editorElement.propertyEditor(it) { item -> editorElement.propertyEditor(name, obj) { item ->
//val descriptorMeta = Material3D.descriptor //val descriptorMeta = Material3D.descriptor
val properties = item.allProperties() val properties = item.allProperties()
@ -99,10 +98,7 @@ private class GDMLDemoApp : Application {
properties.withBottom(bottom) properties.withBottom(bottom)
} }
} }
output.render(visual) output.render(visual)
} }
} }

View File

@ -19,13 +19,15 @@
<div class="container-fluid"> <div class="container-fluid">
<div class="row"> <div class="row">
<div class="col-lg-3"> <div class="col-lg-3">
<div class="row" id ="settings"></div> <div class="row" id="tree"></div>
<div class="row" id ="tree"></div>
</div> </div>
<div class="col-lg-6"> <div class="col-lg-6">
<div class="container" id = "canvas"></div> <div id="canvas"></div>
</div>
<div class="col-lg-3">
<div class="row" id="settings"></div>
<div class="row" id="editor"></div>
</div> </div>
<div class="col-lg-3" id="editor"></div>
</div> </div>
</div> </div>
</body> </body>