diff --git a/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/DisplayObject.kt b/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/DisplayObject.kt index 1f40a835..e6e7b4ea 100644 --- a/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/DisplayObject.kt +++ b/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/DisplayObject.kt @@ -21,7 +21,7 @@ interface DisplayObject { // */ // val type: String - val properties: MutableMeta<*> + val properties: Styled companion object { const val DEFAULT_TYPE = "" @@ -63,15 +63,14 @@ val DisplayObject.meta: Meta get() = properties[META_KEY]?.node ?: EmptyMeta val DisplayObject.tags: List get() = properties[TAGS_KEY].stringList -///** -// * Basic [DisplayObject] leaf element -// */ -//open class DisplayLeaf( -// override val parent: DisplayObject?, -//// override val type: String, -// meta: Meta = EmptyMeta -//) : DisplayObject { -// final override val properties = Styled(meta) -//} +/** + * Basic [DisplayObject] leaf element + */ +open class DisplayLeaf( + override val parent: DisplayObject?, + meta: Meta = EmptyMeta +) : DisplayObject { + final override val properties = Styled(meta) +} interface DisplayGroup: DisplayObject, Iterable diff --git a/dataforge-vis-fx/src/main/kotlin/hep/dataforge/vis/fx/demo/MetaEditorDemo.kt b/dataforge-vis-fx/src/main/kotlin/hep/dataforge/vis/fx/demo/MetaEditorDemo.kt index 73419942..35dfbb67 100644 --- a/dataforge-vis-fx/src/main/kotlin/hep/dataforge/vis/fx/demo/MetaEditorDemo.kt +++ b/dataforge-vis-fx/src/main/kotlin/hep/dataforge/vis/fx/demo/MetaEditorDemo.kt @@ -20,7 +20,7 @@ class MetaEditorDemo : View("Meta editor demo") { "innerNode" to { "innerValue" to true } - "b" to 22 + "b" to 223 "c" to "StringValue" } }.toConfig() @@ -40,6 +40,10 @@ class MetaEditorDemo : View("Meta editor demo") { } } } + value("multiple"){ + info = "A sns value" + multiple = true + } } private val rootNode = FXMeta.root(meta,descriptor) diff --git a/dataforge-vis-fx/src/main/kotlin/hep/dataforge/vis/fx/meta/ConfigEditor.kt b/dataforge-vis-fx/src/main/kotlin/hep/dataforge/vis/fx/meta/ConfigEditor.kt index ea5e21c9..71635489 100644 --- a/dataforge-vis-fx/src/main/kotlin/hep/dataforge/vis/fx/meta/ConfigEditor.kt +++ b/dataforge-vis-fx/src/main/kotlin/hep/dataforge/vis/fx/meta/ConfigEditor.kt @@ -19,12 +19,13 @@ import org.controlsfx.glyphfont.Glyph import tornadofx.* /** - * FXML Controller class + * A configuration editor fragment * * @author Alexander Nozik */ class ConfigEditor( val rootNode: FXMetaNode, + val allowNew: Boolean = true, title: String = "Configuration editor" ) : Fragment(title = title, icon = dfIconView) { @@ -129,26 +130,30 @@ class ConfigEditor( graphic = chooser.node } is FXMetaNode -> { - text = null - graphic = hbox { - button("node", Glyph("FontAwesome", "PLUS_CIRCLE")) { - hgrow = Priority.ALWAYS - maxWidth = Double.POSITIVE_INFINITY - action { - showNodeDialog()?.let { - item.addNode(it) - } - } - } - button("value", Glyph("FontAwesome", "PLUS_SQUARE")) { - hgrow = Priority.ALWAYS - maxWidth = Double.POSITIVE_INFINITY - action { - showValueDialog()?.let { - item.addValue(it) + if(allowNew) { + text = null + graphic = hbox { + button("node", Glyph("FontAwesome", "PLUS_CIRCLE")) { + hgrow = Priority.ALWAYS + maxWidth = Double.POSITIVE_INFINITY + action { + showNodeDialog()?.let { + item.addNode(it) + } + } + } + button("value", Glyph("FontAwesome", "PLUS_SQUARE")) { + hgrow = Priority.ALWAYS + maxWidth = Double.POSITIVE_INFINITY + action { + showValueDialog()?.let { + item.addValue(it) + } } } } + } else { + text = "" } } } diff --git a/dataforge-vis-fx/src/main/kotlin/hep/dataforge/vis/fx/meta/FXMeta.kt b/dataforge-vis-fx/src/main/kotlin/hep/dataforge/vis/fx/meta/FXMeta.kt index 625c1ba3..7010b044 100644 --- a/dataforge-vis-fx/src/main/kotlin/hep/dataforge/vis/fx/meta/FXMeta.kt +++ b/dataforge-vis-fx/src/main/kotlin/hep/dataforge/vis/fx/meta/FXMeta.kt @@ -168,7 +168,7 @@ fun > FXMetaNode.remove(name: NameToken) { children.invalidate() } -private fun > M.createEmptyNode(token: NameToken): M { +private fun > M.createEmptyNode(token: NameToken, append: Boolean): M { this.setNode(token.asName(), EmptyMeta) //FIXME possible concurrency bug return get(token).node!! @@ -178,7 +178,7 @@ fun > FXMetaNode.getOrCreateNode(): M { val node = node return when { node != null -> node - parent != null -> parent.getOrCreateNode().createEmptyNode(this.name).also { + parent != null -> parent.getOrCreateNode().createEmptyNode(this.name, descriptor?.multiple == true).also { parent.children.invalidate() } else -> kotlin.error("Orphan empty node is not allowed") @@ -191,13 +191,27 @@ fun > FXMeta.remove() { } fun > FXMetaNode.addValue(key: String) { - getOrCreateNode()[key] = Null + val parent = getOrCreateNode() + if(descriptor?.multiple == true){ + parent.append(key, Null) + } else{ + parent[key] = Null + } } fun > FXMetaNode.addNode(key: String) { - getOrCreateNode()[key] = EmptyMeta + val parent = getOrCreateNode() + if(descriptor?.multiple == true){ + parent.append(key, EmptyMeta) + } else{ + parent[key] = EmptyMeta + } } fun > FXMetaValue.set(value: Value?) { - parent.getOrCreateNode()[this.name] = value + if(descriptor?.multiple == true){ + parent.getOrCreateNode().append(this.name.body, value) + } else { + parent.getOrCreateNode()[this.name] = value + } } \ No newline at end of file diff --git a/dataforge-vis-spatial-fx/src/main/kotlin/hep/dataforge/vis/DisplayObjectFXListener.kt b/dataforge-vis-spatial-fx/src/main/kotlin/hep/dataforge/vis/spatial/DisplayObjectFXListener.kt similarity index 90% rename from dataforge-vis-spatial-fx/src/main/kotlin/hep/dataforge/vis/DisplayObjectFXListener.kt rename to dataforge-vis-spatial-fx/src/main/kotlin/hep/dataforge/vis/spatial/DisplayObjectFXListener.kt index a66ad8ca..f7c626fa 100644 --- a/dataforge-vis-spatial-fx/src/main/kotlin/hep/dataforge/vis/DisplayObjectFXListener.kt +++ b/dataforge-vis-spatial-fx/src/main/kotlin/hep/dataforge/vis/spatial/DisplayObjectFXListener.kt @@ -1,8 +1,11 @@ -package hep.dataforge.vis +package hep.dataforge.vis.spatial import hep.dataforge.meta.* import hep.dataforge.names.Name import hep.dataforge.names.toName +import hep.dataforge.vis.DisplayObject +import hep.dataforge.vis.getProperty +import hep.dataforge.vis.onChange import javafx.beans.binding.ObjectBinding import tornadofx.* @@ -21,7 +24,7 @@ class DisplayObjectFXListener(val obj: DisplayObject) { operator fun get(key: Name): ObjectBinding?> { return binndings.getOrPut(key) { object : ObjectBinding?>() { - override fun computeValue(): MetaItem<*>? = obj.get(key) + override fun computeValue(): MetaItem<*>? = obj.getProperty(key) } } } diff --git a/dataforge-vis-spatial-fx/src/main/kotlin/hep/dataforge/vis/spatial/FX3DOutput.kt b/dataforge-vis-spatial-fx/src/main/kotlin/hep/dataforge/vis/spatial/FX3DOutput.kt index 04a67005..b8186b13 100644 --- a/dataforge-vis-spatial-fx/src/main/kotlin/hep/dataforge/vis/spatial/FX3DOutput.kt +++ b/dataforge-vis-spatial-fx/src/main/kotlin/hep/dataforge/vis/spatial/FX3DOutput.kt @@ -3,7 +3,8 @@ package hep.dataforge.vis.spatial import hep.dataforge.context.Context import hep.dataforge.meta.Meta import hep.dataforge.output.Output -import hep.dataforge.vis.* +import hep.dataforge.vis.DisplayGroup +import hep.dataforge.vis.DisplayObject import javafx.scene.Group import javafx.scene.Node import org.fxyz3d.shapes.primitives.CuboidMesh @@ -26,7 +27,7 @@ class FX3DOutput(override val context: Context) : Output { org.fxyz3d.geometry.Point3D(x.value ?: 0f, y.value ?: 0f, z.value ?: 0f) } return when (obj) { - is DisplayGroup -> Group(obj.children.map { buildNode(it) }).apply { + is DisplayGroup -> Group(obj.map { buildNode(it) }).apply { this.translateXProperty().bind(x) this.translateYProperty().bind(y) this.translateZProperty().bind(z) diff --git a/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/ThreeFactory.kt b/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/ThreeFactory.kt index 118c6126..92d866c4 100644 --- a/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/ThreeFactory.kt +++ b/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/ThreeFactory.kt @@ -3,7 +3,7 @@ package hep.dataforge.vis.spatial import hep.dataforge.meta.boolean import hep.dataforge.provider.Type import hep.dataforge.vis.DisplayObject -import hep.dataforge.vis.get +import hep.dataforge.vis.getProperty import hep.dataforge.vis.onChange import hep.dataforge.vis.spatial.ThreeFactory.Companion.TYPE import hep.dataforge.vis.spatial.ThreeFactory.Companion.buildMesh @@ -20,7 +20,7 @@ import info.laht.threekt.objects.LineSegments import info.laht.threekt.objects.Mesh import kotlin.reflect.KClass -internal val DisplayObject.material get() = this["color"].material() +internal val DisplayObject.material get() = getProperty("color").material() /** * Builder and updater for three.js object @@ -49,13 +49,13 @@ interface ThreeFactory { internal fun buildMesh(obj: DisplayObject, geometry: BufferGeometry): Mesh { val mesh = Mesh(geometry, obj.material) - if (obj["edges.enabled"]?.boolean != false) { - val material = obj["edges.material"]?.material() ?: Materials.DEFAULT + if (obj.getProperty("edges.enabled")?.boolean != false) { + val material = obj.getProperty("edges.material")?.material() ?: Materials.DEFAULT mesh.add(LineSegments(EdgesGeometry(mesh.geometry as BufferGeometry), material)) } - if (obj["wireframe.enabled"]?.boolean == true) { - val material = obj["edges.material"]?.material() ?: Materials.DEFAULT + if (obj.getProperty("wireframe.enabled")?.boolean == true) { + val material = obj.getProperty("edges.material")?.material() ?: Materials.DEFAULT mesh.add(LineSegments(WireframeGeometry(mesh.geometry as BufferGeometry), material)) } return mesh diff --git a/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/ThreeOutput.kt b/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/ThreeOutput.kt index c9d2592e..71c7b1c8 100644 --- a/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/ThreeOutput.kt +++ b/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/ThreeOutput.kt @@ -64,7 +64,7 @@ class ThreeOutput(override val context: Context, val meta: Meta = EmptyMeta) : O private fun buildNode(obj: DisplayObject): Object3D? { return when (obj) { - is DisplayGroup -> Group(obj.children.mapNotNull { buildNode(it) }).apply { + is DisplayGroup -> Group(obj.mapNotNull { buildNode(it) }).apply { ThreeFactory.updatePosition(obj, this) } //is Box -> ThreeBoxFactory(obj) diff --git a/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/gdml/ThreeGDMLFactory.kt b/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/gdml/ThreeGDMLFactory.kt index add4c71f..39de3382 100644 --- a/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/gdml/ThreeGDMLFactory.kt +++ b/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/gdml/ThreeGDMLFactory.kt @@ -16,7 +16,7 @@ import info.laht.threekt.core.BufferGeometry class GDMLShape(parent: DisplayObject?, meta: Meta, val shape: GDMLSolid) : - DisplayLeaf(parent, "$TYPE.${shape.type}", meta) { + DisplayLeaf(parent, meta) { var facesLimit by int(0) diff --git a/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/jsroot/JSRootGeometry.kt b/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/jsroot/JSRootGeometry.kt index 7351b23c..a5550d87 100644 --- a/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/jsroot/JSRootGeometry.kt +++ b/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/jsroot/JSRootGeometry.kt @@ -8,7 +8,7 @@ import hep.dataforge.vis.* import hep.dataforge.vis.spatial.MeshThreeFactory import info.laht.threekt.core.BufferGeometry -class JSRootGeometry(parent: DisplayObject?, meta: Meta) : DisplayLeaf(parent, TYPE, meta) { +class JSRootGeometry(parent: DisplayObject?, meta: Meta) : DisplayLeaf(parent, meta) { var shape by node() @@ -53,7 +53,7 @@ class JSRootGeometry(parent: DisplayObject?, meta: Meta) : DisplayLeaf(parent, T } } -fun DisplayGroup.jsRootGeometry(meta: Meta = EmptyMeta, action: JSRootGeometry.() -> Unit = {}) = +fun DisplayObjectList.jsRootGeometry(meta: Meta = EmptyMeta, action: JSRootGeometry.() -> Unit = {}) = JSRootGeometry(this, meta).apply(action).also { addChild(it) } //fun Meta.toDynamic(): dynamic { diff --git a/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/jsroot/JSRootObject.kt b/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/jsroot/JSRootObject.kt index f049b959..54252826 100644 --- a/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/jsroot/JSRootObject.kt +++ b/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/jsroot/JSRootObject.kt @@ -3,14 +3,14 @@ package hep.dataforge.vis.spatial.jsroot import hep.dataforge.meta.EmptyMeta import hep.dataforge.meta.Meta import hep.dataforge.meta.toDynamic -import hep.dataforge.vis.DisplayGroup import hep.dataforge.vis.DisplayLeaf import hep.dataforge.vis.DisplayObject +import hep.dataforge.vis.DisplayObjectList import hep.dataforge.vis.node import hep.dataforge.vis.spatial.ThreeFactory import info.laht.threekt.core.Object3D -class JSRootObject(parent: DisplayObject?, meta: Meta, val data: dynamic) : DisplayLeaf(parent, TYPE, meta) { +class JSRootObject(parent: DisplayObject?, meta: Meta, val data: dynamic) : DisplayLeaf(parent, meta) { var options by node() @@ -28,7 +28,7 @@ object ThreeJSRootObjectFactory : ThreeFactory { } } -fun DisplayGroup.jsRootObject(str: String) { +fun DisplayObjectList.jsRootObject(str: String) { val json = JSON.parse(str) JSRootObject(this, EmptyMeta, json).also { addChild(it) } } \ No newline at end of file diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Box.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Box.kt index 92d40a08..fdbe24d3 100644 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Box.kt +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Box.kt @@ -2,10 +2,12 @@ package hep.dataforge.vis.spatial import hep.dataforge.meta.EmptyMeta import hep.dataforge.meta.Meta +import hep.dataforge.vis.DisplayLeaf import hep.dataforge.vis.DisplayObject import hep.dataforge.vis.DisplayObjectList +import hep.dataforge.vis.double -class Box(parent: DisplayObject?, meta: Meta) : DisplayLeaf(parent, TYPE, meta) { +class Box(parent: DisplayObject?, meta: Meta) : DisplayLeaf(parent, meta) { var xSize by double(1.0) var ySize by double(1.0) var zSize by double(1.0) diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Convex.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Convex.kt index 9b921e22..70b1fe3e 100644 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Convex.kt +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Convex.kt @@ -2,10 +2,11 @@ package hep.dataforge.vis.spatial import hep.dataforge.meta.* import hep.dataforge.names.toName +import hep.dataforge.vis.DisplayLeaf import hep.dataforge.vis.DisplayObject import hep.dataforge.vis.DisplayObjectList -class Convex(parent: DisplayObject?, meta: Meta) : DisplayLeaf(parent, TYPE, meta) { +class Convex(parent: DisplayObject?, meta: Meta) : DisplayLeaf(parent, meta) { val points = points(properties["points"] ?: error("Vertices not defined")) diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Extruded.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Extruded.kt index 6cdd04c8..3c027e36 100644 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Extruded.kt +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Extruded.kt @@ -2,10 +2,11 @@ package hep.dataforge.vis.spatial import hep.dataforge.meta.* import hep.dataforge.names.toName +import hep.dataforge.vis.DisplayLeaf import hep.dataforge.vis.DisplayObject import hep.dataforge.vis.DisplayObjectList -class Extruded(parent: DisplayObject?, meta: Meta) : DisplayLeaf(parent, TYPE, meta) { +class Extruded(parent: DisplayObject?, meta: Meta) : DisplayLeaf(parent, meta) { val shape get() = shape(properties["shape"] ?: error("Shape not defined")) diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/displayObject3D.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/displayObject3D.kt index bd5d2e6d..75507d5e 100644 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/displayObject3D.kt +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/displayObject3D.kt @@ -4,16 +4,15 @@ import hep.dataforge.meta.* import hep.dataforge.output.Output import hep.dataforge.vis.DisplayGroup import hep.dataforge.vis.DisplayObject -import hep.dataforge.vis.DisplayObject.Companion.DEFAULT_TYPE import hep.dataforge.vis.DisplayObjectList import hep.dataforge.vis.getProperty fun DisplayObjectList.group(meta: Meta = EmptyMeta, action: DisplayObjectList.() -> Unit = {}): DisplayGroup = - DisplayObjectList(this, DEFAULT_TYPE, meta).apply(action).also { addChild(it) } + DisplayObjectList(this, meta).apply(action).also { addChild(it) } fun Output.render(meta: Meta = EmptyMeta, action: DisplayObjectList.() -> Unit) = - render(DisplayObjectList(null, DEFAULT_TYPE, EmptyMeta).apply(action), meta) + render(DisplayObjectList(null, EmptyMeta).apply(action), meta) //TODO replace properties by containers? diff --git a/dataforge-vis-spatial/src/commonTest/kotlin/hep/dataforge/vis/spatial/ConvexTest.kt b/dataforge-vis-spatial/src/commonTest/kotlin/hep/dataforge/vis/spatial/ConvexTest.kt index 7d8fbb58..b5da0d3b 100644 --- a/dataforge-vis-spatial/src/commonTest/kotlin/hep/dataforge/vis/spatial/ConvexTest.kt +++ b/dataforge-vis-spatial/src/commonTest/kotlin/hep/dataforge/vis/spatial/ConvexTest.kt @@ -1,5 +1,8 @@ package hep.dataforge.vis.spatial +import hep.dataforge.meta.get +import hep.dataforge.meta.getAll +import hep.dataforge.meta.node import hep.dataforge.names.toName import hep.dataforge.vis.DisplayObjectList import kotlin.test.Test