propertyEditor fix (not yet fully functional)

This commit is contained in:
Alexander Nozik 2020-04-13 17:09:44 +03:00
parent 8d3de8688f
commit 3aba8297e8
17 changed files with 197 additions and 164 deletions

View File

@ -39,8 +39,10 @@ kotlin {
api(npm("styled-components")) api(npm("styled-components"))
api(npm("inline-style-prefixer")) api(npm("inline-style-prefixer"))
api(npm("source-map-resolve","0.6.0"))
api(npm("bootstrap","4.3.1")) api(npm("bootstrap","4.3.1"))
api(npm("popper.js","1.14.7"))
api(npm("jquery","3.5.0"))
//api(npm("jsoneditor", "8.6.1")) //api(npm("jsoneditor", "8.6.1"))
api(npm("file-saver","2.0.2")) api(npm("file-saver","2.0.2"))
} }

View File

@ -1,6 +1,7 @@
package hep.dataforge.vis.editor package hep.dataforge.vis.editor
import hep.dataforge.meta.* import hep.dataforge.meta.*
import hep.dataforge.meta.descriptors.ItemDescriptor
import hep.dataforge.meta.descriptors.NodeDescriptor import hep.dataforge.meta.descriptors.NodeDescriptor
import hep.dataforge.meta.descriptors.defaultItem import hep.dataforge.meta.descriptors.defaultItem
import hep.dataforge.meta.descriptors.get import hep.dataforge.meta.descriptors.get
@ -13,6 +14,7 @@ import kotlinx.html.classes
import kotlinx.html.js.onChangeFunction import kotlinx.html.js.onChangeFunction
import kotlinx.html.js.onClickFunction import kotlinx.html.js.onClickFunction
import org.w3c.dom.Element import org.w3c.dom.Element
import org.w3c.dom.HTMLInputElement
import org.w3c.dom.events.Event import org.w3c.dom.events.Event
import react.RBuilder import react.RBuilder
import react.RComponent import react.RComponent
@ -47,7 +49,7 @@ interface ConfigEditorProps : RProps {
class ConfigEditorComponent : RComponent<ConfigEditorProps, TreeState>() { class ConfigEditorComponent : RComponent<ConfigEditorProps, TreeState>() {
override fun TreeState.init() { override fun TreeState.init() {
expanded = false expanded = true
} }
override fun componentDidMount() { override fun componentDidMount() {
@ -70,85 +72,96 @@ class ConfigEditorComponent : RComponent<ConfigEditorProps, TreeState>() {
} }
} }
private val onValueChange: (Event) -> Unit = {
val value = (it.target as HTMLInputElement).value
try {
if(value.isEmpty()){
props.root.remove(props.name)
}
props.root.setValue(props.name, value.asValue())
} catch (ex: Exception) {
console.error("Can't set config property ${props.name} to $value")
}
}
override fun RBuilder.render() { override fun RBuilder.render() {
val item = props.root[props.name] val item = props.root[props.name]
val descriptorItem = props.descriptor?.get(props.name) val descriptorItem: ItemDescriptor? = props.descriptor?.get(props.name)
val defaultItem = props.default?.get(props.name) val defaultItem = props.default?.get(props.name)
val actualItem = item ?: defaultItem ?: descriptorItem?.defaultItem() val actualItem = item ?: defaultItem ?: descriptorItem?.defaultItem()
val token = props.name.last() val token = props.name.last()?.toString() ?: "Properties"
div("d-inline-block text-truncate") { when (actualItem) {
when (actualItem) { is MetaItem.NodeItem -> {
null -> { div("d-inline-block text-truncate") {
} span("tree-caret") {
is MetaItem.ValueItem -> {
i("tree-caret") { }
}
is MetaItem.NodeItem -> {
i("tree-caret fa fa-caret-right") {
attrs { attrs {
if (state.expanded) { if (state.expanded) {
classes += "rotate" classes += "tree-caret-down"
} }
onClickFunction = onClick onClickFunction = onClick
} }
} }
} span("tree-label") {
} +token
label("tree-label") { attrs {
+token.toString() if (item == null) {
attrs { classes += "tree-label-inactive"
if (item == null) {
classes += "tree-label-inactive"
}
}
}
if (actualItem is MetaItem.NodeItem && state.expanded) {
ul("tree") {
val keys = buildList<NameToken> {
item?.node?.items?.keys?.let { addAll(it) }
defaultItem?.node?.items?.keys?.let { addAll(it) }
(descriptorItem as? NodeDescriptor)?.items?.keys?.forEach {
add(NameToken(it))
}
}
keys.forEach { token ->
li("tree-item") {
child(ConfigEditorComponent::class) {
attrs {
root = props.root
name = props.name + token
this.default = props.default
this.descriptor = props.descriptor
listen = false
}
} }
} }
} }
} }
} else if (actualItem is MetaItem.ValueItem) { if (state.expanded) {
div("row") { ul("tree") {
div("col") { val keys = buildSet<NameToken> {
label("tree-label") { item?.node?.items?.keys?.let { addAll(it) }
+token.toString() defaultItem?.node?.items?.keys?.let { addAll(it) }
(descriptorItem as? NodeDescriptor)?.items?.keys?.forEach {
add(NameToken(it))
}
} }
}
div("col") { keys.forEach { token ->
input(type = InputType.text) { li("tree-item") {
attrs { child(ConfigEditorComponent::class) {
value = actualItem.value.toString() attrs {
onChangeFunction = { root = props.root
try { name = props.name + token
props.root.setValue(props.name, value.asValue()) this.default = props.default
} catch (ex: Exception) { this.descriptor = props.descriptor
console.error("Can't set config property $name to $value") listen = false
} }
} }
} }
} }
//+actualItem.value.toString() }
}
}
is MetaItem.ValueItem -> {
div("d-inline-block text-truncate") {
div("row") {
div("col") {
p("tree-label") {
+token
attrs {
if (item == null) {
classes += "tree-label-inactive"
}
}
}
}
div("col") {
div("float-right") {
input(type = InputType.text) {
attrs {
defaultValue = actualItem.value.string
onChangeFunction = onValueChange
}
}
//+actualItem.value.toString()
}
}
} }
} }
} }
@ -182,3 +195,15 @@ fun RBuilder.configEditor(config: Config, descriptor: NodeDescriptor? = null, de
} }
} }
} }
fun RBuilder.configEditor(obj: Configurable, descriptor: NodeDescriptor? = obj.descriptor, default: Meta? = null) {
child(ConfigEditorComponent::class) {
attrs {
root = obj.config
name = Name.EMPTY
this.descriptor = descriptor
this.default = default
listen = true
}
}
}

View File

@ -41,15 +41,15 @@ class ObjectTreeComponent : RComponent<ObjectTreeProps, TreeState>() {
//display as node if any child is visible //display as node if any child is visible
if (obj is VisualGroup && obj.children.keys.any { !it.body.startsWith("@") }) { if (obj is VisualGroup && obj.children.keys.any { !it.body.startsWith("@") }) {
div("d-inline-block text-truncate") { div("d-inline-block text-truncate") {
span("objTree-caret") { span("tree-caret") {
attrs { attrs {
if (state.expanded) { if (state.expanded) {
classes += "objTree-caret-down" classes += "tree-caret-down"
} }
onClickFunction = onClick onClickFunction = onClick
} }
} }
label("objTree-label") { a("#",classes = "tree-label") {
+token +token
attrs { attrs {
onClickFunction = { props.clickCallback(props.name) } onClickFunction = { props.clickCallback(props.name) }
@ -57,12 +57,12 @@ class ObjectTreeComponent : RComponent<ObjectTreeProps, TreeState>() {
} }
} }
if (state.expanded) { if (state.expanded) {
ul("objTree-subtree") { 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 { li("tree-item") {
child(ObjectTreeComponent::class) { child(ObjectTreeComponent::class) {
attrs { attrs {
name = props.name + childToken name = props.name + childToken
@ -76,8 +76,8 @@ class ObjectTreeComponent : RComponent<ObjectTreeProps, TreeState>() {
} }
} else { } else {
div("d-inline-block text-truncate") { div("d-inline-block text-truncate") {
span("objTree-leaf") {} span("tree-leaf") {}
label("objTree-label") { a("#",classes = "tree-label") {
+token +token
attrs { attrs {
onClickFunction = { props.clickCallback(props.name) } onClickFunction = { props.clickCallback(props.name) }

View File

@ -93,7 +93,7 @@ fun RBuilder.visualPropertyEditor(
} }
} }
} }
configEditor(item.config, descriptor, Meta(default)) configEditor(item, descriptor, Meta(default))
} }
fun Element.visualPropertyEditor( fun Element.visualPropertyEditor(

View File

@ -1,40 +1,42 @@
/* Remove default bullets */ /* Remove default bullets */
ul, .objTree-subtree { ul, .tree {
list-style-type: none; list-style-type: none;
} }
/* Style the caret/arrow */ /* Style the caret/arrow */
.objTree-caret { .tree-caret {
cursor: pointer; cursor: pointer;
user-select: none; /* Prevent text selection */ user-select: none; /* Prevent text selection */
} }
/* Create the caret/arrow with a unicode, and style it */ /* Create the caret/arrow with a unicode, and style it */
.objTree-caret::before { .tree-caret::before {
content: "\25B6"; content: "\25B6";
color: black; color: black;
display: inline-block; display: inline-block;
margin-right: 6px; margin-right: 6px;
} }
/* Rotate the caret/arrow icon when clicked on (using JavaScript) */ .tree-leaf{
.objTree-caret-down::before { user-select: none;
transform: rotate(90deg); display: inline-block;
} }
ul, .tree { .tree-leaf::before {
list-style-type: none; content: "\25C6";
} color: black;
i, .tree-caret{
display: inline-block; display: inline-block;
margin-right: 6px; margin-right: 6px;
} }
.rotate {
/* Rotate the caret/arrow icon when clicked on (using JavaScript) */
.tree-caret-down::before {
transform: rotate(90deg); transform: rotate(90deg);
} }
.tree-label-inactive { .tree-label-inactive {
background-color: lightgrey;
color: gray; color: gray;
} display: inline-block;
}

View File

@ -26,4 +26,14 @@ class TestConvertor {
val visual = xml.toVisual() val visual = xml.toVisual()
// println(visual) // println(visual)
} }
@Test
fun testSimple() {
val stream = javaClass.getResourceAsStream("/gdml/simple1.gdml")
val xmlReader = StAXReader(stream, "UTF-8")
val xml = GDML.format.parse(GDML.serializer(), xmlReader)
val visual = xml.toVisual()
println(visual.stringify())
}
} }

View File

@ -0,0 +1,26 @@
<?xml version="1.0"?>
<gdml xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://service-spi.web.cern.ch/service-spi/app/releases/GDML/schema/gdml.xsd">
<define/>
<materials>
<material name="Vacuum" Z="1">
<D unit="g/cm3" value="0"/>
<atom unit="g/mole" value="0"/>
</material>
<material name="Al" Z="13">
<D unit="g/cm3" value="2.7000000000000002"/>
<atom unit="g/mole" value="26.98"/>
</material>
</materials>
<solids>
<box name="R" x="50" y="50" z="10" lunit="cm"/>
</solids>
<structure>
<volume name="R">
<materialref ref="Vacuum"/>
<solidref ref="R"/>
</volume>
</structure>
<setup name="default" version="1.0">
<world ref="R"/>
</setup>
</gdml>

View File

@ -47,23 +47,17 @@ class Material3D : Scheme() {
val descriptor by lazy { val descriptor by lazy {
//must be lazy to avoid initialization bug //must be lazy to avoid initialization bug
NodeDescriptor { NodeDescriptor {
defineValue(VisualObject3D.VISIBLE_KEY) { defineValue(COLOR_KEY) {
type(ValueType.BOOLEAN) type(ValueType.STRING, ValueType.NUMBER)
default(true) default("#ffffff")
} }
defineNode(MATERIAL_KEY) { defineValue(OPACITY_KEY) {
defineValue(COLOR_KEY) { type(ValueType.NUMBER)
type(ValueType.STRING, ValueType.NUMBER) default(1.0)
default("#ffffff") }
} defineValue(WIREFRAME_KEY) {
defineValue(OPACITY_KEY) { type(ValueType.BOOLEAN)
type(ValueType.NUMBER) default(false)
default(1.0)
}
defineValue(WIREFRAME_KEY) {
type(ValueType.BOOLEAN)
default(false)
}
} }
} }
} }

View File

@ -10,6 +10,7 @@ import hep.dataforge.names.toName
import hep.dataforge.vis.SimpleVisualGroup import hep.dataforge.vis.SimpleVisualGroup
import hep.dataforge.vis.Visual import hep.dataforge.vis.Visual
import hep.dataforge.vis.VisualObject import hep.dataforge.vis.VisualObject
import kotlinx.serialization.UnstableDefault
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonConfiguration import kotlinx.serialization.json.JsonConfiguration
import kotlinx.serialization.modules.SerializersModule import kotlinx.serialization.modules.SerializersModule
@ -53,6 +54,7 @@ class Visual3D(meta: Meta) : AbstractPlugin(meta) {
} }
} }
@OptIn(UnstableDefault::class)
internal val json = Json( internal val json = Json(
JsonConfiguration( JsonConfiguration(
prettyPrint = true, prettyPrint = true,

View File

@ -17,12 +17,12 @@
} }
/* Remove default bullets */ /* Remove default bullets */
ul, .objTree-subtree { ul, .tree {
list-style-type: none; list-style-type: none;
} }
/* Style the caret/arrow */ /* Style the caret/arrow */
.objTree-caret { .tree-caret {
cursor: pointer; cursor: pointer;
user-select: none; /* Prevent text selection */ user-select: none; /* Prevent text selection */
} }
@ -32,7 +32,7 @@ ul, .objTree-subtree {
} }
/* Create the caret/arrow with a unicode, and style it */ /* Create the caret/arrow with a unicode, and style it */
.objTree-caret::before { .tree-caret::before {
content: "\25B6"; content: "\25B6";
color: black; color: black;
display: inline-block; display: inline-block;
@ -47,6 +47,6 @@ ul, .objTree-subtree {
} }
/* Rotate the caret/arrow icon when clicked on (using JavaScript) */ /* Rotate the caret/arrow icon when clicked on (using JavaScript) */
.objTree-caret-down::before { .tree-caret-down::before {
transform: rotate(90deg); transform: rotate(90deg);
} }

View File

@ -13,9 +13,19 @@ kotlin {
val installJS = tasks.getByName("jsBrowserDistribution") val installJS = tasks.getByName("jsBrowserDistribution")
js{
browser {
dceTask {
dceOptions {
keep("ktor-ktor-io.\$\$importsForInline\$\$.ktor-ktor-io.io.ktor.utils.io")
}
}
}
}
jvm { jvm {
withJava() withJava()
compilations.findByName("jvmMain").apply { compilations.findByName("main").apply {
tasks.getByName<ProcessResources>("jvmProcessResources") { tasks.getByName<ProcessResources>("jvmProcessResources") {
dependsOn(installJS) dependsOn(installJS)
afterEvaluate { afterEvaluate {

View File

@ -10,12 +10,8 @@ import hep.dataforge.vis.VisualObject
import hep.dataforge.vis.editor.card import hep.dataforge.vis.editor.card
import hep.dataforge.vis.editor.objectTree import hep.dataforge.vis.editor.objectTree
import hep.dataforge.vis.editor.visualPropertyEditor import hep.dataforge.vis.editor.visualPropertyEditor
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_WIREFRAME_KEY
import hep.dataforge.vis.spatial.Visual3D import hep.dataforge.vis.spatial.Visual3D
import hep.dataforge.vis.spatial.VisualObject3D import hep.dataforge.vis.spatial.VisualObject3D
import hep.dataforge.vis.spatial.VisualObject3D.Companion.VISIBLE_KEY
import hep.dataforge.vis.spatial.three.ThreePlugin import hep.dataforge.vis.spatial.three.ThreePlugin
import hep.dataforge.vis.spatial.three.displayCanvasControls import hep.dataforge.vis.spatial.three.displayCanvasControls
import hep.dataforge.vis.spatial.three.output import hep.dataforge.vis.spatial.three.output
@ -92,28 +88,8 @@ private class MMDemoApp : Application {
visual is VisualGroup -> visual[name] ?: return visual is VisualGroup -> visual[name] ?: return
else -> return else -> return
} }
editorElement.visualPropertyEditor(name, child) { editorElement.visualPropertyEditor(name, child, descriptor = VisualObject3D.descriptor)
VISIBLE_KEY put true
if (child is VisualObject3D) {
MATERIAL_COLOR_KEY put "#ffffff"
MATERIAL_OPACITY_KEY put 1.0
MATERIAL_WIREFRAME_KEY put false
}
}
// editorElement.displayPropertyEditor(name, child) { item ->
// //val descriptorMeta = Material3D.descriptor
//
// val properties = item.allProperties()
// val bottom = Meta {
// VISIBLE_KEY put (item.visible ?: true)
// if (item is VisualObject3D) {
// MATERIAL_COLOR_KEY put "#ffffff"
// MATERIAL_OPACITY_KEY put 1.0
// MATERIAL_WIREFRAME_KEY put false
// }
// }
// properties.withBottom(bottom)
// }
} }
// canvas.clickListener = ::selectElement // canvas.clickListener = ::selectElement

File diff suppressed because one or more lines are too long

View File

@ -1,48 +1,40 @@
.loader {
border: 16px solid #f3f3f3; /* Light grey */
border-top: 16px solid #3498db; /* Blue */
border-radius: 50%;
width: 120px;
height: 120px;
animation: spin 2s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* Remove default bullets */ /* Remove default bullets */
ul, .objTree-subtree { ul, .tree {
list-style-type: none; list-style-type: none;
} }
/* Style the caret/arrow */ /* Style the caret/arrow */
.objTree-caret { .tree-caret {
cursor: pointer; cursor: pointer;
user-select: none; /* Prevent text selection */ user-select: none; /* Prevent text selection */
} }
.objTree-label {
cursor: pointer;
}
/* Create the caret/arrow with a unicode, and style it */ /* Create the caret/arrow with a unicode, and style it */
.objTree-caret::before { .tree-caret::before {
content: "\25B6"; content: "\25B6";
color: black; color: black;
display: inline-block; display: inline-block;
margin-right: 6px; margin-right: 6px;
} }
.objTree-leaf::before { .tree-leaf{
user-select: none;
display: inline-block;
}
.tree-leaf::before {
content: "\25C6"; content: "\25C6";
color: black; color: black;
display: inline-block; display: inline-block;
margin-right: 6px; margin-right: 6px;
} }
/* Rotate the caret/arrow icon when clicked on (using JavaScript) */ /* Rotate the caret/arrow icon when clicked on (using JavaScript) */
.objTree-caret-down::before { .tree-caret-down::before {
transform: rotate(90deg); transform: rotate(90deg);
} }
.tree-label-inactive {
color: gray;
}

View File

@ -4,10 +4,8 @@
<meta charset="utf-8"> <meta charset="utf-8">
<!-- <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">--> <!-- <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">-->
<title>Three js demo for particle physics</title> <title>Three js demo for particle physics</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<link rel="stylesheet" href="css/main.css"> <link rel="stylesheet" href="css/main.css">
<link rel="stylesheet" href="css/jsoneditor.min.css">
<script type="text/javascript" src="main.bundle.js"></script> <script type="text/javascript" src="main.bundle.js"></script>
</head> </head>
<body class="testApp"> <body class="testApp">

View File

@ -17,6 +17,7 @@ import io.ktor.routing.get
import io.ktor.serialization.json import io.ktor.serialization.json
import io.ktor.server.cio.CIO import io.ktor.server.cio.CIO
import io.ktor.server.engine.embeddedServer import io.ktor.server.engine.embeddedServer
import io.ktor.util.KtorExperimentalAPI
import org.apache.commons.math3.random.JDKRandomGenerator import org.apache.commons.math3.random.JDKRandomGenerator
import ru.mipt.npm.muon.monitor.Model import ru.mipt.npm.muon.monitor.Model
import ru.mipt.npm.muon.monitor.sim.Cos2TrackGenerator import ru.mipt.npm.muon.monitor.sim.Cos2TrackGenerator
@ -56,6 +57,7 @@ fun Application.module() {
} }
} }
@OptIn(KtorExperimentalAPI::class)
fun main() { fun main() {
embeddedServer(CIO, 8080, host = "localhost", module = Application::module).start(wait = true) embeddedServer(CIO, 8080, host = "localhost", module = Application::module).start(wait = true)
} }

View File

@ -1,16 +1,16 @@
/* Remove default bullets */ /* Remove default bullets */
ul, .objTree-subtree { ul, .tree {
list-style-type: none; list-style-type: none;
} }
/* Style the caret/arrow */ /* Style the caret/arrow */
.objTree-caret { .tree-caret {
cursor: pointer; cursor: pointer;
user-select: none; /* Prevent text selection */ user-select: none; /* Prevent text selection */
} }
/* Create the caret/arrow with a unicode, and style it */ /* Create the caret/arrow with a unicode, and style it */
.objTree-caret::before { .tree-caret::before {
content: "\25B6"; content: "\25B6";
color: black; color: black;
display: inline-block; display: inline-block;
@ -18,7 +18,7 @@ ul, .objTree-subtree {
} }
/* Rotate the caret/arrow icon when clicked on (using JavaScript) */ /* Rotate the caret/arrow icon when clicked on (using JavaScript) */
.objTree-caret-down::before { .tree-caret-down::before {
transform: rotate(90deg); transform: rotate(90deg);
} }