diff --git a/dataforge-vis-common/build.gradle.kts b/dataforge-vis-common/build.gradle.kts index 7ebb7feb..dbbee84a 100644 --- a/dataforge-vis-common/build.gradle.kts +++ b/dataforge-vis-common/build.gradle.kts @@ -31,21 +31,13 @@ kotlin { jsMain { dependencies { api("hep.dataforge:dataforge-output-html:$dataforgeVersion") - - api("org.jetbrains:kotlin-react:16.13.1-pre.104-kotlin-1.3.72") - api("org.jetbrains:kotlin-react-dom:16.13.1-pre.104-kotlin-1.3.72") api("org.jetbrains.kotlinx:kotlinx-html:0.6.12") - api("org.jetbrains:kotlin-extensions:1.0.1-pre.104-kotlin-1.3.72") - api("org.jetbrains:kotlin-css-js:1.0.0-pre.94-kotlin-1.3.70") + //api("org.jetbrains:kotlin-extensions:1.0.1-pre.105-kotlin-1.3.72") + //api("org.jetbrains:kotlin-css-js:1.0.0-pre.105-kotlin-1.3.72") api("org.jetbrains:kotlin-styled:1.0.0-pre.104-kotlin-1.3.72") api(npm("core-js", "2.6.5")) - - api(npm("react", "16.13.1")) - api(npm("react-dom", "16.13.1")) - - api(npm("react-is", "16.13.0")) api(npm("inline-style-prefixer", "5.1.0")) api(npm("styled-components", "4.3.2")) //api(project(":ringui-wrapper")) diff --git a/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/misc.kt b/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/misc.kt index f6ccc200..106e7545 100644 --- a/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/misc.kt +++ b/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/misc.kt @@ -2,9 +2,12 @@ package hep.dataforge.vis import hep.dataforge.meta.Laminate import hep.dataforge.meta.MetaItem +import hep.dataforge.meta.descriptors.NodeDescriptor import hep.dataforge.meta.node import hep.dataforge.names.Name import hep.dataforge.names.isEmpty +import hep.dataforge.values.ValueType +import hep.dataforge.values.asValue /** * Return nearest selectable parent [Name] @@ -21,7 +24,7 @@ tailrec fun Name.selectable(): Name? = when { } } -fun Sequence?>.merge(): MetaItem<*>?{ +fun Sequence?>.merge(): MetaItem<*>? { return when (val first = filterNotNull().firstOrNull()) { null -> null is MetaItem.ValueItem -> first //fast search for first entry if it is value @@ -31,4 +34,12 @@ fun Sequence?>.merge(): MetaItem<*>?{ MetaItem.NodeItem(laminate) } } +} + +inline fun > NodeDescriptor.enum(key: Name, default: E?) = value(key) { + type(ValueType.STRING) + default?.let { + default(default) + } + allowedValues = enumValues().map{it.asValue()} } \ No newline at end of file diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Visual3D.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Visual3D.kt index df97af9a..4cfa1cf2 100644 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Visual3D.kt +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Visual3D.kt @@ -69,13 +69,13 @@ class Visual3D(meta: Meta) : AbstractPlugin(meta) { internal fun VisualObject3D.update(meta: Meta) { fun Meta.toVector(default: Float = 0f) = Point3D( - this[VisualObject3D.x].float ?: default, - this[VisualObject3D.y].float ?: default, - this[VisualObject3D.z].float ?: default + this[VisualObject3D.X_KEY].float ?: default, + this[VisualObject3D.Y_KEY].float ?: default, + this[VisualObject3D.Z_KEY].float ?: default ) - meta[VisualObject3D.position].node?.toVector()?.let { position = it } - meta[VisualObject3D.rotation].node?.toVector()?.let { rotation = it } - meta[VisualObject3D.scale].node?.toVector(1f)?.let { scale = it } + meta[VisualObject3D.POSITION_KEY].node?.toVector()?.let { position = it } + meta[VisualObject3D.ROTATION].node?.toVector()?.let { rotation = it } + meta[VisualObject3D.SCALE_KEY].node?.toVector(1f)?.let { scale = it } meta["properties"].node?.let { configure(it) } } \ No newline at end of file diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/VisualObject3D.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/VisualObject3D.kt index 5c40d4fe..ba108c61 100644 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/VisualObject3D.kt +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/VisualObject3D.kt @@ -10,6 +10,7 @@ import hep.dataforge.output.Renderer import hep.dataforge.values.ValueType import hep.dataforge.values.asValue import hep.dataforge.vis.VisualObject +import hep.dataforge.vis.enum import hep.dataforge.vis.spatial.VisualObject3D.Companion.DETAIL_KEY import hep.dataforge.vis.spatial.VisualObject3D.Companion.IGNORE_KEY import hep.dataforge.vis.spatial.VisualObject3D.Companion.LAYER_KEY @@ -37,29 +38,29 @@ interface VisualObject3D : VisualObject { val GEOMETRY_KEY = "geometry".asName() - val x = "x".asName() - val y = "y".asName() - val z = "z".asName() + val X_KEY = "x".asName() + val Y_KEY = "y".asName() + val Z_KEY = "z".asName() - val position = "pos".asName() + val POSITION_KEY = "pos".asName() - val xPos = position + x - val yPos = position + y - val zPos = position + z + val X_POSITION_KEY = POSITION_KEY + X_KEY + val Y_POSITION_KEY = POSITION_KEY + Y_KEY + val Z_POSITION_KEY = POSITION_KEY + Z_KEY - val rotation = "rotation".asName() + val ROTATION = "rotation".asName() - val xRotation = rotation + x - val yRotation = rotation + y - val zRotation = rotation + z + val X_ROTATION_KEY = ROTATION + X_KEY + val Y_ROTATION_KEY = ROTATION + Y_KEY + val Z_ROTATION_KEY = ROTATION + Z_KEY - val rotationOrder = rotation + "order" + val ROTATION_ORDER_KEY = ROTATION + "order" - val scale = "scale".asName() + val SCALE_KEY = "scale".asName() - val xScale = scale + x - val yScale = scale + y - val zScale = scale + z + val X_SCALE_KEY = SCALE_KEY + X_KEY + val Y_SCALE_KEY = SCALE_KEY + Y_KEY + val Z_SCALE_KEY = SCALE_KEY + Z_KEY val descriptor by lazy { NodeDescriptor { @@ -69,12 +70,14 @@ interface VisualObject3D : VisualObject { } //TODO replace by descriptor merge - value(VisualObject.STYLE_KEY){ + value(VisualObject.STYLE_KEY) { type(ValueType.STRING) multiple = true } item(Material3D.MATERIAL_KEY.toString(), Material3D.descriptor) + + enum(ROTATION_ORDER_KEY,default = RotationOrder.XYZ) } } } @@ -107,8 +110,8 @@ enum class RotationOrder { * Rotation order */ var VisualObject3D.rotationOrder: RotationOrder - get() = getProperty(VisualObject3D.rotationOrder).enum() ?: RotationOrder.XYZ - set(value) = setProperty(VisualObject3D.rotationOrder, value.name.asValue()) + get() = getProperty(VisualObject3D.ROTATION_ORDER_KEY).enum() ?: RotationOrder.XYZ + set(value) = setProperty(VisualObject3D.ROTATION_ORDER_KEY, value.name.asValue()) /** @@ -141,21 +144,21 @@ var VisualObject3D.x: Number get() = position?.x ?: 0f set(value) { position().x = value.toDouble() - propertyInvalidated(VisualObject3D.xPos) + propertyInvalidated(VisualObject3D.X_POSITION_KEY) } var VisualObject3D.y: Number get() = position?.y ?: 0f set(value) { position().y = value.toDouble() - propertyInvalidated(VisualObject3D.yPos) + propertyInvalidated(VisualObject3D.Y_POSITION_KEY) } var VisualObject3D.z: Number get() = position?.z ?: 0f set(value) { position().z = value.toDouble() - propertyInvalidated(VisualObject3D.zPos) + propertyInvalidated(VisualObject3D.Z_POSITION_KEY) } private fun VisualObject3D.rotation(): Point3D = @@ -165,21 +168,21 @@ var VisualObject3D.rotationX: Number get() = rotation?.x ?: 0f set(value) { rotation().x = value.toDouble() - propertyInvalidated(VisualObject3D.xRotation) + propertyInvalidated(VisualObject3D.X_ROTATION_KEY) } var VisualObject3D.rotationY: Number get() = rotation?.y ?: 0f set(value) { rotation().y = value.toDouble() - propertyInvalidated(VisualObject3D.yRotation) + propertyInvalidated(VisualObject3D.Y_ROTATION_KEY) } var VisualObject3D.rotationZ: Number get() = rotation?.z ?: 0f set(value) { rotation().z = value.toDouble() - propertyInvalidated(VisualObject3D.zRotation) + propertyInvalidated(VisualObject3D.Z_ROTATION_KEY) } private fun VisualObject3D.scale(): Point3D = @@ -189,19 +192,19 @@ var VisualObject3D.scaleX: Number get() = scale?.x ?: 1f set(value) { scale().x = value.toDouble() - propertyInvalidated(VisualObject3D.xScale) + propertyInvalidated(VisualObject3D.X_SCALE_KEY) } var VisualObject3D.scaleY: Number get() = scale?.y ?: 1f set(value) { scale().y = value.toDouble() - propertyInvalidated(VisualObject3D.yScale) + propertyInvalidated(VisualObject3D.Y_SCALE_KEY) } var VisualObject3D.scaleZ: Number get() = scale?.z ?: 1f set(value) { scale().z = value.toDouble() - propertyInvalidated(VisualObject3D.zScale) + propertyInvalidated(VisualObject3D.Z_SCALE_KEY) } \ No newline at end of file diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/geometry.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/geometry.kt index f88528bb..5eb71cd2 100644 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/geometry.kt +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/geometry.kt @@ -21,8 +21,8 @@ operator fun Point2D.component1() = x operator fun Point2D.component2() = y fun Point2D.toMeta() = Meta { - VisualObject3D.x put x - VisualObject3D.y put y + VisualObject3D.X_KEY put x + VisualObject3D.Y_KEY put y } fun Meta.point2D() = Point2D(this["x"].number ?: 0, this["y"].number ?: 0) @@ -42,7 +42,7 @@ operator fun Point3D.component3() = z fun Meta.point3D() = Point3D(this["x"].number ?: 0, this["y"].number ?: 0, this["y"].number ?: 0) fun Point3D.toMeta() = Meta { - VisualObject3D.x put x - VisualObject3D.y put y - VisualObject3D.z put z + VisualObject3D.X_KEY put x + VisualObject3D.Y_KEY put y + VisualObject3D.Z_KEY put z } \ No newline at end of file diff --git a/dataforge-vis-spatial/src/commonTest/kotlin/hep/dataforge/vis/spatial/PropertyTest.kt b/dataforge-vis-spatial/src/commonTest/kotlin/hep/dataforge/vis/spatial/PropertyTest.kt index 9972b8c2..b7757b41 100644 --- a/dataforge-vis-spatial/src/commonTest/kotlin/hep/dataforge/vis/spatial/PropertyTest.kt +++ b/dataforge-vis-spatial/src/commonTest/kotlin/hep/dataforge/vis/spatial/PropertyTest.kt @@ -7,6 +7,7 @@ import hep.dataforge.vis.useStyle import kotlin.test.Test import kotlin.test.assertEquals +@Suppress("UNUSED_VARIABLE") class PropertyTest { @Test fun testInheritedProperty() { diff --git a/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreeFactory.kt b/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreeFactory.kt index 38d1bfb5..f12a0a47 100644 --- a/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreeFactory.kt +++ b/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreeFactory.kt @@ -60,9 +60,9 @@ fun Object3D.updateProperty(source: VisualObject, propertyName: Name) { if (this is Mesh && propertyName.startsWith(MATERIAL_KEY)) { this.material = getMaterial(source) } else if ( - propertyName.startsWith(VisualObject3D.position) - || propertyName.startsWith(VisualObject3D.rotation) - || propertyName.startsWith(VisualObject3D.scale) + propertyName.startsWith(VisualObject3D.POSITION_KEY) + || propertyName.startsWith(VisualObject3D.ROTATION) + || propertyName.startsWith(VisualObject3D.SCALE_KEY) ) { //update position of mesh using this object updatePosition(source) diff --git a/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreePlugin.kt b/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreePlugin.kt index 6c6aabeb..223ef6d6 100644 --- a/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreePlugin.kt +++ b/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreePlugin.kt @@ -57,9 +57,9 @@ class ThreePlugin : AbstractPlugin() { obj.onPropertyChange(this) { name, _, _ -> if ( - name.startsWith(VisualObject3D.position) || - name.startsWith(VisualObject3D.rotation) || - name.startsWith(VisualObject3D.scale) + name.startsWith(VisualObject3D.POSITION_KEY) || + name.startsWith(VisualObject3D.ROTATION) || + name.startsWith(VisualObject3D.SCALE_KEY) ) { //update position of mesh using this object updatePosition(obj) diff --git a/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/FX3DPlugin.kt b/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/FX3DPlugin.kt index 288174ea..df538b1a 100644 --- a/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/FX3DPlugin.kt +++ b/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/FX3DPlugin.kt @@ -19,12 +19,8 @@ import javafx.scene.transform.Rotate import org.fxyz3d.shapes.composites.PolyLine3D import org.fxyz3d.shapes.primitives.CuboidMesh import org.fxyz3d.shapes.primitives.SpheroidMesh -import kotlin.collections.HashMap import kotlin.collections.component1 import kotlin.collections.component2 -import kotlin.collections.find -import kotlin.collections.map -import kotlin.collections.mapNotNull import kotlin.collections.set import kotlin.math.PI import kotlin.reflect.KClass @@ -91,23 +87,23 @@ class FX3DPlugin : AbstractPlugin() { } } }.apply { - translateXProperty().bind(binding[VisualObject3D.xPos].float(obj.x.toFloat())) - translateYProperty().bind(binding[VisualObject3D.yPos].float(obj.y.toFloat())) - translateZProperty().bind(binding[VisualObject3D.zPos].float(obj.z.toFloat())) - scaleXProperty().bind(binding[VisualObject3D.xScale].float(obj.scaleX.toFloat())) - scaleYProperty().bind(binding[VisualObject3D.yScale].float(obj.scaleY.toFloat())) - scaleZProperty().bind(binding[VisualObject3D.zScale].float(obj.scaleZ.toFloat())) + translateXProperty().bind(binding[VisualObject3D.X_POSITION_KEY].float(obj.x.toFloat())) + translateYProperty().bind(binding[VisualObject3D.Y_POSITION_KEY].float(obj.y.toFloat())) + translateZProperty().bind(binding[VisualObject3D.Z_POSITION_KEY].float(obj.z.toFloat())) + scaleXProperty().bind(binding[VisualObject3D.X_SCALE_KEY].float(obj.scaleX.toFloat())) + scaleYProperty().bind(binding[VisualObject3D.Y_SCALE_KEY].float(obj.scaleY.toFloat())) + scaleZProperty().bind(binding[VisualObject3D.Z_SCALE_KEY].float(obj.scaleZ.toFloat())) val rotateX = Rotate(0.0, Rotate.X_AXIS).apply { - angleProperty().bind(binding[VisualObject3D.xRotation].float(obj.rotationX.toFloat()).multiply(180.0 / PI)) + angleProperty().bind(binding[VisualObject3D.X_ROTATION_KEY].float(obj.rotationX.toFloat()).multiply(180.0 / PI)) } val rotateY = Rotate(0.0, Rotate.Y_AXIS).apply { - angleProperty().bind(binding[VisualObject3D.yRotation].float(obj.rotationY.toFloat()).multiply(180.0 / PI)) + angleProperty().bind(binding[VisualObject3D.Y_ROTATION_KEY].float(obj.rotationY.toFloat()).multiply(180.0 / PI)) } val rotateZ = Rotate(0.0, Rotate.Z_AXIS).apply { - angleProperty().bind(binding[VisualObject3D.zRotation].float(obj.rotationZ.toFloat()).multiply(180.0 / PI)) + angleProperty().bind(binding[VisualObject3D.Z_ROTATION_KEY].float(obj.rotationZ.toFloat()).multiply(180.0 / PI)) } when (obj.rotationOrder) { diff --git a/demo/gdml/build.gradle.kts b/demo/gdml/build.gradle.kts index fdaeadc8..6604196d 100644 --- a/demo/gdml/build.gradle.kts +++ b/demo/gdml/build.gradle.kts @@ -1,4 +1,6 @@ -import scientifik.* +import scientifik.DependencyConfiguration +import scientifik.FXModule +import scientifik.useFx plugins { id("scientifik.mpp") @@ -16,11 +18,6 @@ kotlin { js { useCommonJs() - browser { - webpackTask { - //sourceMaps = false - } - } } sourceSets { diff --git a/demo/gdml/src/jsMain/kotlin/hep/dataforge/vis/spatial/gdml/demo/GDMLAppComponent.kt b/demo/gdml/src/jsMain/kotlin/hep/dataforge/vis/spatial/gdml/demo/GDMLAppComponent.kt index e929ce29..419ec1c0 100644 --- a/demo/gdml/src/jsMain/kotlin/hep/dataforge/vis/spatial/gdml/demo/GDMLAppComponent.kt +++ b/demo/gdml/src/jsMain/kotlin/hep/dataforge/vis/spatial/gdml/demo/GDMLAppComponent.kt @@ -7,6 +7,7 @@ import hep.dataforge.vis.VisualGroup import hep.dataforge.vis.VisualObject import hep.dataforge.vis.bootstrap.* import hep.dataforge.vis.react.component +import hep.dataforge.vis.react.configEditor import hep.dataforge.vis.react.flexColumn import hep.dataforge.vis.react.state import hep.dataforge.vis.spatial.VisualGroup3D @@ -80,7 +81,7 @@ val GDMLApp = component { props -> classes.add("p-1") overflow = Overflow.auto } - gridColumn(3) { + gridColumn(3, maxSize= GridMaxSize.XL, classes = "order-2 order-xl-1") { card("Load data") { fileDrop("(drag file here)") { files -> val file = files?.get(0) @@ -104,7 +105,7 @@ val GDMLApp = component { props -> } } - gridColumn(6) { + gridColumn(6, maxSize= GridMaxSize.XL, classes = "order-1 order-xl-2") { //canvas (visual as? VisualObject3D)?.let { visual3D -> child(ThreeCanvasComponent::class) { @@ -120,7 +121,7 @@ val GDMLApp = component { props -> } } } - gridColumn(3) { + gridColumn(3, maxSize= GridMaxSize.XL, classes = "order-3") { container { //settings canvas?.let { diff --git a/demo/gdml/src/jsMain/kotlin/hep/dataforge/vis/spatial/gdml/demo/GDMLDemoApp.kt b/demo/gdml/src/jsMain/kotlin/hep/dataforge/vis/spatial/gdml/demo/GDMLDemoApp.kt index 613a98ed..c5f2abd9 100644 --- a/demo/gdml/src/jsMain/kotlin/hep/dataforge/vis/spatial/gdml/demo/GDMLDemoApp.kt +++ b/demo/gdml/src/jsMain/kotlin/hep/dataforge/vis/spatial/gdml/demo/GDMLDemoApp.kt @@ -7,8 +7,10 @@ import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_OPACITY_KEY import hep.dataforge.vis.spatial.gdml.GDMLTransformer import hep.dataforge.vis.spatial.gdml.LUnit import hep.dataforge.vis.spatial.gdml.toVisual +import kotlinx.css.* import react.child import react.dom.render +import styled.injectGlobal import kotlin.browser.document @@ -42,6 +44,15 @@ private class GDMLDemoApp : Application { override fun start(state: Map) { + injectGlobal { + body { + height = 100.pct + width = 100.pct + margin(0.px) + padding(0.px) + } + } + val context = Global.context("demo") {} val element = document.getElementById("app") ?: error("Element with id 'app' not found on page") diff --git a/demo/muon-monitor/src/jsMain/kotlin/ru/mipt/npm/muon/monitor/MMAppComponent.kt b/demo/muon-monitor/src/jsMain/kotlin/ru/mipt/npm/muon/monitor/MMAppComponent.kt index d7a0a3af..4458e1d7 100644 --- a/demo/muon-monitor/src/jsMain/kotlin/ru/mipt/npm/muon/monitor/MMAppComponent.kt +++ b/demo/muon-monitor/src/jsMain/kotlin/ru/mipt/npm/muon/monitor/MMAppComponent.kt @@ -6,9 +6,9 @@ import hep.dataforge.names.NameToken import hep.dataforge.names.isEmpty import hep.dataforge.vis.VisualObject import hep.dataforge.vis.bootstrap.card -import hep.dataforge.vis.bootstrap.configEditor import hep.dataforge.vis.bootstrap.objectTree import hep.dataforge.vis.react.component +import hep.dataforge.vis.react.configEditor import hep.dataforge.vis.react.state import hep.dataforge.vis.spatial.specifications.Camera import hep.dataforge.vis.spatial.specifications.Canvas diff --git a/ui/bootstrap/build.gradle.kts b/ui/bootstrap/build.gradle.kts index 9a974d8d..598c1e56 100644 --- a/ui/bootstrap/build.gradle.kts +++ b/ui/bootstrap/build.gradle.kts @@ -11,6 +11,5 @@ kotlin { } dependencies{ - api(project(":dataforge-vis-common")) api(project(":ui:react")) } \ No newline at end of file diff --git a/ui/bootstrap/src/main/kotlin/hep/dataforge/vis/bootstrap/propertyEditor.kt b/ui/bootstrap/src/main/kotlin/hep/dataforge/vis/bootstrap/propertyEditor.kt index d4b69c48..07721392 100644 --- a/ui/bootstrap/src/main/kotlin/hep/dataforge/vis/bootstrap/propertyEditor.kt +++ b/ui/bootstrap/src/main/kotlin/hep/dataforge/vis/bootstrap/propertyEditor.kt @@ -5,6 +5,7 @@ import hep.dataforge.meta.descriptors.NodeDescriptor import hep.dataforge.names.Name import hep.dataforge.names.isEmpty import hep.dataforge.vis.VisualObject +import hep.dataforge.vis.react.configEditor import org.w3c.dom.Element import react.RBuilder import react.dom.li diff --git a/ui/material/build.gradle.kts b/ui/material/build.gradle.kts index 459380c5..78e48bc4 100644 --- a/ui/material/build.gradle.kts +++ b/ui/material/build.gradle.kts @@ -11,12 +11,11 @@ kotlin { } dependencies{ - api(project(":dataforge-vis-common")) api(project(":ui:react")) - api("subroh0508.net.kotlinmaterialui:core:0.3.16") - api("subroh0508.net.kotlinmaterialui:lab:0.3.16") - api(npm("@material-ui/core","4.9.13")) - api(npm("@material-ui/lab","4.0.0-alpha.52")) + api("subroh0508.net.kotlinmaterialui:core:0.4.0") + api("subroh0508.net.kotlinmaterialui:lab:0.4.0") + api(npm("@material-ui/core","4.9.14")) + api(npm("@material-ui/lab","4.0.0-alpha.51")) //api(npm("@material-ui/icons","4.9.1")) } \ No newline at end of file diff --git a/ui/material/src/main/kotlin/hep/dataforge/vis/material/configEditor.kt b/ui/material/src/main/kotlin/hep/dataforge/vis/material/configEditor.kt deleted file mode 100644 index 821a073f..00000000 --- a/ui/material/src/main/kotlin/hep/dataforge/vis/material/configEditor.kt +++ /dev/null @@ -1,193 +0,0 @@ -package hep.dataforge.vis.material - -import hep.dataforge.meta.* -import hep.dataforge.meta.descriptors.* -import hep.dataforge.names.Name -import hep.dataforge.names.NameToken -import hep.dataforge.names.isEmpty -import hep.dataforge.names.plus -import hep.dataforge.vis.react.component -import hep.dataforge.vis.react.state -import kotlinx.css.Display -import kotlinx.css.display -import kotlinx.css.flexGrow -import kotlinx.css.flexShrink -import kotlinx.html.js.onClickFunction -import materialui.components.button.button -import materialui.components.grid.enums.GridAlignItems -import materialui.components.grid.enums.GridJustify -import materialui.components.grid.grid -import materialui.components.typography.typographyH6 -import materialui.lab.components.treeItem.treeItem -import materialui.lab.components.treeView.treeView -import org.w3c.dom.Element -import org.w3c.dom.events.Event -import react.* -import react.dom.render -import react.dom.span -import styled.css -import styled.styledDiv - -interface ConfigEditorProps : RProps { - - /** - * Root config object - always non null - */ - var root: Config - - /** - * Full path to the displayed node in [root]. Could be empty - */ - var name: Name - - /** - * Root default - */ - var default: Meta? - - /** - * Root descriptor - */ - var descriptor: NodeDescriptor? -} - -private fun RBuilder.configEditorItem( - root: Config, - name: Name, - descriptor: NodeDescriptor?, - default: Meta? -) { - val item = root[name] - val descriptorItem: ItemDescriptor? = descriptor?.get(name) - val defaultItem = default?.get(name) - val actualItem: MetaItem? = item ?: defaultItem ?: descriptorItem?.defaultItem() - - val token = name.last()?.toString() ?: "Properties" - - val removeClick: (Event) -> Unit = { - root.remove(name) - } - - treeItem { - attrs { - nodeId = name.toString() - label { - row { - attrs { - alignItems = GridAlignItems.stretch - justify = GridJustify.spaceBetween - spacing(1) - } - grid { - typographyH6 { - +token - } - } - if (actualItem is MetaItem.ValueItem) { - styledDiv { - css { - display = Display.flex - flexGrow = 1.0 - } - valueChooser(root, name, actualItem.value, descriptorItem as? ValueDescriptor) - } - } - if (!name.isEmpty()) { - styledDiv { - css { - display = Display.flex - flexShrink = 1.0 - } - button { - +"\u00D7" - attrs { - if (item == null) { - disabled = true - } else { - onClickFunction = removeClick - } - } - } - } - } - } - } - } - if (actualItem is MetaItem.NodeItem) { - val keys = buildSet { - (descriptorItem as? NodeDescriptor)?.items?.keys?.forEach { - add(NameToken(it)) - } - item?.node?.items?.keys?.let { addAll(it) } - defaultItem?.node?.items?.keys?.let { addAll(it) } - } - - keys.forEach { token -> - configEditorItem(root, name + token, descriptor, default) - } - } - } -} - -val ConfigEditor: FunctionalComponent = component { props -> - var kostyl by state { false } - - fun update() { - kostyl = !kostyl - } - - useEffectWithCleanup(listOf(props.root)) { - props.root.onChange(this) { name, _, _ -> - if (name == props.name) { - update() - } - } - return@useEffectWithCleanup { props.root.removeListener(this) } - } - - treeView { - attrs { - defaultCollapseIcon { - span { - +"-" - } - //child(ExpandMoreIcon::class) {} - }//{} - defaultExpandIcon { - span { - +"+" - } - //child(ChevronRightIcon::class) {} - }//{} - set("disableSelection", true) - } - configEditorItem(props.root, props.name, props.descriptor, props.default) - } - -} - -fun RBuilder.configEditor( - config: Config, - name: Name = Name.EMPTY, - descriptor: NodeDescriptor? = null, - default: Meta? = null -) { - child(ConfigEditor) { - attrs { - this.root = config - this.name = name - this.descriptor = descriptor - this.default = default - } - } -} - -fun Element.configEditor(config: Config, descriptor: NodeDescriptor? = null, default: Meta? = null) { - render(this) { - configEditor(config, Name.EMPTY, descriptor, default) - } -} - -fun RBuilder.configEditor(obj: Configurable, descriptor: NodeDescriptor? = obj.descriptor, default: Meta? = null) { - configEditor(obj.config, Name.EMPTY, descriptor ?: obj.descriptor, default) -} diff --git a/ui/material/src/main/kotlin/hep/dataforge/vis/material/objectTree.kt b/ui/material/src/main/kotlin/hep/dataforge/vis/material/objectTree.kt index 976ae836..bb265c63 100644 --- a/ui/material/src/main/kotlin/hep/dataforge/vis/material/objectTree.kt +++ b/ui/material/src/main/kotlin/hep/dataforge/vis/material/objectTree.kt @@ -8,7 +8,9 @@ import hep.dataforge.vis.VisualObject import hep.dataforge.vis.isEmpty import hep.dataforge.vis.react.component import hep.dataforge.vis.react.state +import kotlinx.html.UL import materialui.lab.components.treeItem.treeItem +import materialui.lab.components.treeView.SingleSelectTreeViewElementBuilder import materialui.lab.components.treeView.treeView import react.FunctionalComponent import react.RBuilder @@ -49,11 +51,11 @@ private fun RBuilder.treeBranch(name: Name, obj: VisualObject): Unit { val ObjectTree: FunctionalComponent = component { props -> var selected: String? by state { props.selected.toString() } treeView { + this as SingleSelectTreeViewElementBuilder
    attrs { this.selected = selected - this.onNodeSelect = { _, selectedItem -> - @Suppress("CAST_NEVER_SUCCEEDS") - selected = (selectedItem as? String) + this.onNodeSelect{ _, selectedItem -> + selected = selectedItem val itemName = selected?.toName() props.clickCallback(itemName) Unit diff --git a/ui/material/src/main/kotlin/hep/dataforge/vis/material/valueChooser.kt b/ui/material/src/main/kotlin/hep/dataforge/vis/material/valueChooser.kt deleted file mode 100644 index 7ccf296d..00000000 --- a/ui/material/src/main/kotlin/hep/dataforge/vis/material/valueChooser.kt +++ /dev/null @@ -1,114 +0,0 @@ -package hep.dataforge.vis.material - -import hep.dataforge.meta.Config -import hep.dataforge.meta.descriptors.ValueDescriptor -import hep.dataforge.meta.get -import hep.dataforge.meta.number -import hep.dataforge.meta.setValue -import hep.dataforge.names.Name -import hep.dataforge.values.* -import hep.dataforge.vis.widgetType -import kotlinx.html.InputType -import kotlinx.html.js.onChangeFunction -import kotlinx.html.js.onKeyDownFunction -import materialui.components.input.input -import materialui.components.select.select -import materialui.components.slider.slider -import materialui.components.switches.switch -import materialui.components.textfield.textField -import org.w3c.dom.HTMLInputElement -import org.w3c.dom.HTMLSelectElement -import org.w3c.dom.events.Event -import org.w3c.dom.events.KeyboardEvent -import react.RBuilder -import react.dom.option - -internal fun RBuilder.valueChooser(root: Config, name: Name, value: Value, descriptor: ValueDescriptor?) { - val onValueChange: (Event) -> Unit = { event -> - if (event !is KeyboardEvent || event.key == "Enter") { - val res = when (val t = event.target) { - // (it.target as HTMLInputElement).value - is HTMLInputElement -> if (t.type == "checkbox") { - if (t.checked) True else False - } else { - t.value.asValue() - } - is HTMLSelectElement -> t.value.asValue() - else -> error("Unknown event target: $t") - } - - try { - root.setValue(name, res) - } catch (ex: Exception) { - console.error("Can't set config property ${name} to $res") - } - } - } - - - val type = descriptor?.type?.firstOrNull() - when { - descriptor?.widgetType == "slider" -> slider { - attrs { - descriptor.attributes["step"].number?.let { - step = it - } - descriptor.attributes["min"].number?.let { - min = it - } - descriptor.attributes["max"].number?.let { - max = it - } - this.defaultValue = value.number - onChangeFunction = onValueChange - } - } - descriptor?.widgetType == "color" -> input { - attrs { - fullWidth = true - this.type = InputType.color - this.value = value.string - onChangeFunction = onValueChange - } - } - - type == ValueType.BOOLEAN -> switch { - attrs { - defaultChecked = value.boolean - onChangeFunction = onValueChange - } - } - - type == ValueType.NUMBER -> textField { - attrs { - fullWidth = true - this.type = InputType.number - defaultValue = value.string - onChangeFunction = onValueChange - //onKeyDownFunction = onValueChange - } - } - descriptor?.allowedValues?.isNotEmpty() ?: false -> select { - descriptor!!.allowedValues.forEach { - option { - +it.string - } - } - attrs { - fullWidth = true - multiple = false - onChangeFunction = onValueChange - } - } - else -> textField { - attrs { - this.type = InputType.text - fullWidth = true - this.defaultValue = value.string - //onFocusOutFunction = onValueChange - onKeyDownFunction = onValueChange - } - } - } - -} \ No newline at end of file diff --git a/ui/react/build.gradle.kts b/ui/react/build.gradle.kts index 57aa27a6..3c250174 100644 --- a/ui/react/build.gradle.kts +++ b/ui/react/build.gradle.kts @@ -10,21 +10,12 @@ kotlin { dependencies{ + api(project(":dataforge-vis-common")) - api("org.jetbrains:kotlin-react:16.13.1-pre.104-kotlin-1.3.72") + //api("org.jetbrains:kotlin-react:16.13.1-pre.104-kotlin-1.3.72") api("org.jetbrains:kotlin-react-dom:16.13.1-pre.104-kotlin-1.3.72") - api("org.jetbrains.kotlinx:kotlinx-html:0.6.12") - - api("org.jetbrains:kotlin-extensions:1.0.1-pre.104-kotlin-1.3.72") - api("org.jetbrains:kotlin-css-js:1.0.0-pre.94-kotlin-1.3.70") - api("org.jetbrains:kotlin-styled:1.0.0-pre.104-kotlin-1.3.72") - - api(npm("core-js", "2.6.5")) api(npm("react", "16.13.1")) api(npm("react-dom", "16.13.1")) - - api(npm("react-is", "16.13.0")) - api(npm("inline-style-prefixer", "5.1.0")) - api(npm("styled-components", "4.3.2")) + api(npm("react-is", "16.13.1")) } \ No newline at end of file diff --git a/ui/react/src/main/kotlin/hep/dataforge/vis/react/TreeStyles.kt b/ui/react/src/main/kotlin/hep/dataforge/vis/react/TreeStyles.kt new file mode 100644 index 00000000..db6eb1fe --- /dev/null +++ b/ui/react/src/main/kotlin/hep/dataforge/vis/react/TreeStyles.kt @@ -0,0 +1,74 @@ +package hep.dataforge.vis.react + +import kotlinx.css.* +import kotlinx.css.properties.deg +import kotlinx.css.properties.rotate +import styled.StyleSheet + +object TreeStyles : StyleSheet("treeStyles", true) { + /** + * Remove default bullets + */ + val tree by css { + paddingLeft = 8.px + marginLeft = 0.px + listStyleType = ListStyleType.none + } + + /** + * Style the caret/arrow + */ + val treeCaret by css { + cursor = Cursor.pointer + userSelect = UserSelect.none + /* Create the caret/arrow with a unicode, and style it */ + before { + content = "\u25B6".quoted + color = Color.black + display = Display.inlineBlock + marginRight = 6.px + } + } + + val treeItem by css { + alignItems = Align.center + paddingLeft = 10.px + borderLeftStyle = BorderStyle.dashed + borderLeftWidth = 1.px + borderLeftColor = Color.lightGray + } + + val treeLeaf by css { + display = Display.flex + flexDirection = FlexDirection.row + userSelect = UserSelect.none + alignItems = Align.center + } + + + /** + * Rotate the caret/arrow icon when clicked on (using JavaScript) + */ + val treeCaredDown by css { + before { + content = "\u25B6".quoted + color = Color.black + display = Display.inlineBlock + marginRight = 6.px + transform.rotate(90.deg) + } + } + + val treeLabel by css { + overflow = Overflow.hidden + } + + val treeLabelInactive by css { + color = Color.lightGray + } + + val treeLabelSelected by css { + backgroundColor = Color.lightBlue + } + +} \ No newline at end of file diff --git a/ui/bootstrap/src/main/kotlin/hep/dataforge/vis/bootstrap/configEditor.kt b/ui/react/src/main/kotlin/hep/dataforge/vis/react/configEditor.kt similarity index 76% rename from ui/bootstrap/src/main/kotlin/hep/dataforge/vis/bootstrap/configEditor.kt rename to ui/react/src/main/kotlin/hep/dataforge/vis/react/configEditor.kt index f92e4e87..32789854 100644 --- a/ui/bootstrap/src/main/kotlin/hep/dataforge/vis/bootstrap/configEditor.kt +++ b/ui/react/src/main/kotlin/hep/dataforge/vis/react/configEditor.kt @@ -1,4 +1,4 @@ -package hep.dataforge.vis.bootstrap +package hep.dataforge.vis.react import hep.dataforge.meta.* import hep.dataforge.meta.descriptors.* @@ -6,19 +6,15 @@ import hep.dataforge.names.Name import hep.dataforge.names.NameToken import hep.dataforge.names.plus import hep.dataforge.values.Value -import hep.dataforge.vis.react.RFBuilder -import hep.dataforge.vis.react.component -import hep.dataforge.vis.react.flexRow -import hep.dataforge.vis.react.state import kotlinx.css.* -import kotlinx.html.classes +import kotlinx.css.properties.TextDecoration import kotlinx.html.js.onClickFunction import org.w3c.dom.Element import org.w3c.dom.events.Event import react.* -import react.dom.* -import styled.css -import styled.styledDiv +import react.dom.div +import react.dom.render +import styled.* interface ConfigEditorItemProps : RProps { @@ -91,25 +87,32 @@ private fun RFBuilder.configEditorItem(props: ConfigEditorItemProps) { when (actualItem) { is MetaItem.NodeItem -> { div { - span("tree-caret") { - attrs { + styledSpan { + css { + +TreeStyles.treeCaret if (expanded) { - classes += "tree-caret-down" + +TreeStyles.treeCaredDown } + } + attrs { onClickFunction = expanderClick } } - span("tree-label") { - +token - attrs { + styledSpan { + css { + +TreeStyles.treeLabel if (item == null) { - classes += "tree-label-inactive" + +TreeStyles.treeLabelInactive } } + +token } } if (expanded) { - ul("tree") { + styledUl { + css { + +TreeStyles.tree + } val keys = buildSet { (descriptorItem as? NodeDescriptor)?.items?.keys?.forEach { add(NameToken(it)) @@ -119,7 +122,10 @@ private fun RFBuilder.configEditorItem(props: ConfigEditorItemProps) { } keys.forEach { token -> - li("tree-item align-middle") { + styledLi { + css { + +TreeStyles.treeItem + } child(ConfigEditorItem) { attrs { this.key = props.name.toString() @@ -136,22 +142,23 @@ private fun RFBuilder.configEditorItem(props: ConfigEditorItemProps) { } } is MetaItem.ValueItem -> { - flexRow { + styledDiv { css { - alignItems = Align.center - justifyContent= JustifyContent.flexEnd + +TreeStyles.treeLeaf + justifyContent = JustifyContent.flexEnd } styledDiv { - css{ + css { flexGrow = 1.0 } - span("tree-label align-self-center") { - +token - attrs { + styledSpan { + css { + +TreeStyles.treeLabel if (item == null) { - classes += "tree-label-inactive" + +TreeStyles.treeLabelInactive } } + +token } } styledDiv { @@ -166,7 +173,23 @@ private fun RFBuilder.configEditorItem(props: ConfigEditorItemProps) { css { flexShrink = 1.0 } - button(classes = "btn btn-link align-self-center") { + styledButton { + css { + backgroundColor = Color.white + borderStyle = BorderStyle.solid + borderRadius = 2.px + padding(1.px, 5.px) + marginLeft = 4.px + textAlign = TextAlign.center + textDecoration = TextDecoration.none + display = Display.inlineBlock + cursor = Cursor.pointer + disabled { + cursor = Cursor.auto + borderStyle = BorderStyle.dashed + color = Color.lightGray + } + } +"\u00D7" attrs { if (item == null) { diff --git a/ui/react/src/main/kotlin/hep/dataforge/vis/react/styles.kt b/ui/react/src/main/kotlin/hep/dataforge/vis/react/styles.kt new file mode 100644 index 00000000..daa1043d --- /dev/null +++ b/ui/react/src/main/kotlin/hep/dataforge/vis/react/styles.kt @@ -0,0 +1,9 @@ +package hep.dataforge.vis.react + +import styled.StyleSheet + + +class MainStyle: StyleSheet("main", true){ + + +} \ No newline at end of file diff --git a/ui/bootstrap/src/main/kotlin/hep/dataforge/vis/bootstrap/valueChooser.kt b/ui/react/src/main/kotlin/hep/dataforge/vis/react/valueChooser.kt similarity index 94% rename from ui/bootstrap/src/main/kotlin/hep/dataforge/vis/bootstrap/valueChooser.kt rename to ui/react/src/main/kotlin/hep/dataforge/vis/react/valueChooser.kt index 1874350c..cae3e5ec 100644 --- a/ui/bootstrap/src/main/kotlin/hep/dataforge/vis/bootstrap/valueChooser.kt +++ b/ui/react/src/main/kotlin/hep/dataforge/vis/react/valueChooser.kt @@ -1,4 +1,4 @@ -package hep.dataforge.vis.bootstrap +package hep.dataforge.vis.react import hep.dataforge.meta.* import hep.dataforge.meta.descriptors.ValueDescriptor @@ -6,6 +6,8 @@ import hep.dataforge.names.Name import hep.dataforge.values.* import hep.dataforge.vis.Colors import hep.dataforge.vis.widgetType +import kotlinx.css.Align +import kotlinx.css.alignSelf import kotlinx.html.InputType import kotlinx.html.js.onChangeFunction import kotlinx.html.js.onKeyDownFunction @@ -14,7 +16,12 @@ import org.w3c.dom.HTMLInputElement import org.w3c.dom.HTMLSelectElement import org.w3c.dom.events.Event import react.* -import react.dom.* +import react.dom.defaultValue +import react.dom.input +import react.dom.option +import react.dom.select +import styled.css +import styled.styledDiv interface ValueChooserProps : RProps { var item: MetaItem<*>? @@ -66,9 +73,6 @@ class ValueChooserComponent(props: ValueChooserProps) : RComponent -// state.value?.let { element.value = it.string } -// } } private fun RBuilder.stringInput() = input(type = InputType.text) { @@ -80,7 +84,10 @@ class ValueChooserComponent(props: ValueChooserProps) : RComponent