forked from kscience/visionforge
Migration to 1.3.70
This commit is contained in:
parent
150fdb2426
commit
d4dcd32b73
@ -18,6 +18,7 @@ allprojects {
|
|||||||
maven("https://dl.bintray.com/pdvrieze/maven")
|
maven("https://dl.bintray.com/pdvrieze/maven")
|
||||||
maven("http://maven.jzy3d.org/releases")
|
maven("http://maven.jzy3d.org/releases")
|
||||||
maven("https://kotlin.bintray.com/js-externals")
|
maven("https://kotlin.bintray.com/js-externals")
|
||||||
|
maven("https://kotlin.bintray.com/kotlin-js-wrappers/")
|
||||||
// maven("https://dl.bintray.com/gbaldeck/kotlin")
|
// maven("https://dl.bintray.com/gbaldeck/kotlin")
|
||||||
// maven("https://dl.bintray.com/rjaros/kotlin")
|
// maven("https://dl.bintray.com/rjaros/kotlin")
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
import scientifik.serialization
|
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("scientifik.mpp")
|
id("scientifik.mpp")
|
||||||
}
|
}
|
||||||
@ -7,35 +5,44 @@ plugins {
|
|||||||
val dataforgeVersion: String by rootProject.extra
|
val dataforgeVersion: String by rootProject.extra
|
||||||
//val kvisionVersion: String by rootProject.extra("2.0.0-M1")
|
//val kvisionVersion: String by rootProject.extra("2.0.0-M1")
|
||||||
|
|
||||||
serialization()
|
|
||||||
val fxVersion: String by rootProject.extra
|
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
sourceSets {
|
sourceSets {
|
||||||
commonMain{
|
commonMain {
|
||||||
dependencies {
|
dependencies {
|
||||||
api("hep.dataforge:dataforge-output:$dataforgeVersion")
|
api("hep.dataforge:dataforge-output:$dataforgeVersion")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
jvmMain{
|
jvmMain {
|
||||||
dependencies {
|
dependencies {
|
||||||
api("no.tornado:tornadofx:1.7.20")
|
api("no.tornado:tornadofx:1.7.20")
|
||||||
//api("no.tornado:tornadofx-controlsfx:0.1.1")
|
//api("no.tornado:tornadofx-controlsfx:0.1.1")
|
||||||
api("de.jensd:fontawesomefx-fontawesome:4.7.0-11"){
|
api("de.jensd:fontawesomefx-fontawesome:4.7.0-11") {
|
||||||
exclude(group = "org.openjfx")
|
exclude(group = "org.openjfx")
|
||||||
}
|
}
|
||||||
api("de.jensd:fontawesomefx-commons:11.0"){
|
api("de.jensd:fontawesomefx-commons:11.0") {
|
||||||
exclude(group = "org.openjfx")
|
exclude(group = "org.openjfx")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
jsMain{
|
jsMain {
|
||||||
dependencies {
|
dependencies {
|
||||||
api("hep.dataforge:dataforge-output-html:$dataforgeVersion")
|
api("hep.dataforge:dataforge-output-html:$dataforgeVersion")
|
||||||
//api(npm("bootstrap","4.4.1"))
|
|
||||||
implementation(npm("uri-js","4.2.2"))
|
//React, React DOM + Wrappers (chapter 3)
|
||||||
implementation(npm("jsoneditor","8.6.1"))
|
api("org.jetbrains:kotlin-react:16.13.0-pre.94-kotlin-1.3.70")
|
||||||
implementation(npm("file-saver"))
|
api("org.jetbrains:kotlin-react-dom:16.13.0-pre.94-kotlin-1.3.70")
|
||||||
|
api(npm("react", "16.13.0"))
|
||||||
|
api(npm("react-dom", "16.13.0"))
|
||||||
|
|
||||||
|
//Kotlin Styled (chapter 3)
|
||||||
|
api("org.jetbrains:kotlin-styled:1.0.0-pre.94-kotlin-1.3.70")
|
||||||
|
api(npm("styled-components"))
|
||||||
|
api(npm("inline-style-prefixer"))
|
||||||
|
|
||||||
|
|
||||||
|
api(npm("bootstrap","4.3.1"))
|
||||||
|
//api(npm("jsoneditor", "8.6.1"))
|
||||||
|
api(npm("file-saver","2.0.2"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,7 +68,7 @@ abstract class AbstractVisualObject : VisualObject {
|
|||||||
private var styleCache: Meta? = null
|
private var styleCache: Meta? = null
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Collect all styles for this object in a laminate
|
* Collect all styles for this object in a single cached meta
|
||||||
*/
|
*/
|
||||||
protected val mergedStyles: Meta
|
protected val mergedStyles: Meta
|
||||||
get() = styleCache ?: findAllStyles().merge().also {
|
get() = styleCache ?: findAllStyles().merge().also {
|
||||||
|
@ -1,16 +1,21 @@
|
|||||||
package hep.dataforge.vis
|
package hep.dataforge.vis
|
||||||
|
|
||||||
import hep.dataforge.meta.*
|
import hep.dataforge.meta.EmptyMeta
|
||||||
|
import hep.dataforge.meta.Meta
|
||||||
import hep.dataforge.meta.descriptors.ValueDescriptor
|
import hep.dataforge.meta.descriptors.ValueDescriptor
|
||||||
|
import hep.dataforge.meta.node
|
||||||
import hep.dataforge.meta.scheme.getProperty
|
import hep.dataforge.meta.scheme.getProperty
|
||||||
|
import hep.dataforge.meta.scheme.setProperty
|
||||||
|
import hep.dataforge.meta.string
|
||||||
|
import hep.dataforge.values.asValue
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extension property to access the "widget" key of [ValueDescriptor]
|
* Extension property to access the "widget" key of [ValueDescriptor]
|
||||||
*/
|
*/
|
||||||
var ValueDescriptor.widget: Meta
|
var ValueDescriptor.widget: Meta
|
||||||
get() = this.config["widget"].node?: EmptyMeta
|
get() = getProperty("widget").node ?: EmptyMeta
|
||||||
set(value) {
|
set(value) {
|
||||||
config["widget"] = value
|
setProperty("widget", value)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -19,5 +24,5 @@ var ValueDescriptor.widget: Meta
|
|||||||
var ValueDescriptor.widgetType: String?
|
var ValueDescriptor.widgetType: String?
|
||||||
get() = getProperty("widget.type").string
|
get() = getProperty("widget.type").string
|
||||||
set(value) {
|
set(value) {
|
||||||
config["widget.type"] = value
|
setProperty("widget.type", value?.asValue())
|
||||||
}
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package hep.dataforge.js
|
||||||
|
|
||||||
|
import react.RComponent
|
||||||
|
import kotlin.properties.ReadWriteProperty
|
||||||
|
import kotlin.reflect.KProperty
|
||||||
|
|
||||||
|
fun <T> RComponent<*, *>.initState(init: () -> T): ReadWriteProperty<RComponent<*, *>, T> =
|
||||||
|
object : ReadWriteProperty<RComponent<*, *>, T> {
|
||||||
|
val pair = react.useState(init)
|
||||||
|
override fun getValue(thisRef: RComponent<*, *>, property: KProperty<*>): T {
|
||||||
|
return pair.first
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setValue(thisRef: RComponent<*, *>, property: KProperty<*>, value: T) {
|
||||||
|
pair.second(value)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,178 @@
|
|||||||
|
package hep.dataforge.vis.editor
|
||||||
|
|
||||||
|
import hep.dataforge.js.initState
|
||||||
|
import hep.dataforge.meta.*
|
||||||
|
import hep.dataforge.meta.descriptors.NodeDescriptor
|
||||||
|
import hep.dataforge.meta.descriptors.defaultItem
|
||||||
|
import hep.dataforge.meta.descriptors.get
|
||||||
|
import hep.dataforge.names.Name
|
||||||
|
import hep.dataforge.names.NameToken
|
||||||
|
import hep.dataforge.names.plus
|
||||||
|
import hep.dataforge.values.asValue
|
||||||
|
import kotlinx.html.InputType
|
||||||
|
import kotlinx.html.classes
|
||||||
|
import kotlinx.html.js.onChangeFunction
|
||||||
|
import kotlinx.html.js.onClickFunction
|
||||||
|
import org.w3c.dom.Element
|
||||||
|
import react.*
|
||||||
|
import react.dom.*
|
||||||
|
|
||||||
|
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?
|
||||||
|
|
||||||
|
var listen: Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
class ConfigEditorComponent : RComponent<ConfigEditorProps, TreeState>() {
|
||||||
|
|
||||||
|
override fun TreeState.init() {
|
||||||
|
expanded = false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun componentDidMount() {
|
||||||
|
if (props.listen) {
|
||||||
|
props.root.onChange(this) { name, _, _ ->
|
||||||
|
if (name == props.name) {
|
||||||
|
forceUpdate()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun componentWillUnmount() {
|
||||||
|
props.root.removeListener(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun RBuilder.render() {
|
||||||
|
val item = props.root[props.name]
|
||||||
|
val descriptorItem = props.descriptor?.get(props.name)
|
||||||
|
val defaultItem = props.default?.get(props.name)
|
||||||
|
val actualItem = item ?: defaultItem ?: descriptorItem?.defaultItem()
|
||||||
|
val token = props.name.last()
|
||||||
|
|
||||||
|
div("d-inline-block text-truncate") {
|
||||||
|
when (actualItem) {
|
||||||
|
null -> {
|
||||||
|
}
|
||||||
|
is MetaItem.ValueItem -> {
|
||||||
|
i("tree-caret") { }
|
||||||
|
}
|
||||||
|
is MetaItem.NodeItem -> {
|
||||||
|
i("tree-caret fa fa-caret-right") {
|
||||||
|
attrs {
|
||||||
|
if (state.expanded) {
|
||||||
|
classes += "rotate"
|
||||||
|
}
|
||||||
|
onClickFunction = {
|
||||||
|
setState {
|
||||||
|
expanded = !expanded
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
label("tree-label") {
|
||||||
|
+token.toString()
|
||||||
|
attrs {
|
||||||
|
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) {
|
||||||
|
div("row") {
|
||||||
|
div("col") {
|
||||||
|
label("tree-label") {
|
||||||
|
+token.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
div("col") {
|
||||||
|
input(type = InputType.text) {
|
||||||
|
attrs {
|
||||||
|
value = actualItem.value.toString()
|
||||||
|
onChangeFunction = {
|
||||||
|
try {
|
||||||
|
props.root.setValue(props.name, value.asValue())
|
||||||
|
} catch (ex: Exception) {
|
||||||
|
console.error("Can't set config property $name to $value")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//+actualItem.value.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Element.configEditor(config: Config, descriptor: NodeDescriptor? = null, default: Meta? = null) {
|
||||||
|
render(this) {
|
||||||
|
child(ConfigEditorComponent::class) {
|
||||||
|
attrs {
|
||||||
|
root = config
|
||||||
|
name = Name.EMPTY
|
||||||
|
this.descriptor = descriptor
|
||||||
|
this.default = default
|
||||||
|
listen = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun RBuilder.configEditor(config: Config, descriptor: NodeDescriptor? = null, default: Meta? = null) {
|
||||||
|
child(ConfigEditorComponent::class) {
|
||||||
|
attrs {
|
||||||
|
root = config
|
||||||
|
name = Name.EMPTY
|
||||||
|
this.descriptor = descriptor
|
||||||
|
this.default = default
|
||||||
|
listen = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,81 @@
|
|||||||
|
package hep.dataforge.vis.editor
|
||||||
|
|
||||||
|
import hep.dataforge.js.initState
|
||||||
|
import hep.dataforge.meta.Meta
|
||||||
|
import hep.dataforge.meta.MetaItem
|
||||||
|
import hep.dataforge.meta.descriptors.NodeDescriptor
|
||||||
|
import hep.dataforge.names.NameToken
|
||||||
|
import kotlinx.html.classes
|
||||||
|
import kotlinx.html.js.onClickFunction
|
||||||
|
import react.*
|
||||||
|
import react.dom.*
|
||||||
|
|
||||||
|
interface MetaViewerProps : RProps {
|
||||||
|
var name: NameToken
|
||||||
|
var meta: Meta
|
||||||
|
var descriptor: NodeDescriptor?
|
||||||
|
}
|
||||||
|
|
||||||
|
class MetaViewerComponent : RComponent<MetaViewerProps, TreeState>() {
|
||||||
|
|
||||||
|
override fun TreeState.init() {
|
||||||
|
expanded = false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun RBuilder.render() {
|
||||||
|
div("d-inline-block text-truncate") {
|
||||||
|
if (props.meta.items.isNotEmpty()) {
|
||||||
|
span("objTree-caret") {
|
||||||
|
attrs {
|
||||||
|
classes = if (state.expanded) {
|
||||||
|
setOf("objTree-caret", "objTree-caret-down")
|
||||||
|
} else {
|
||||||
|
setOf("objTree-caret")
|
||||||
|
}
|
||||||
|
onClickFunction = {
|
||||||
|
setState {
|
||||||
|
expanded = !expanded
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
label("tree-label") {
|
||||||
|
+props.name.toString()
|
||||||
|
}
|
||||||
|
ul("tree") {
|
||||||
|
props.meta.items.forEach { (token, item) ->
|
||||||
|
//val descriptor = props.
|
||||||
|
li {
|
||||||
|
when (item) {
|
||||||
|
is MetaItem.NodeItem -> {
|
||||||
|
child(MetaViewerComponent::class) {
|
||||||
|
attrs {
|
||||||
|
name = token
|
||||||
|
meta = item.node
|
||||||
|
descriptor = props.descriptor?.nodes?.get(token.body)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is MetaItem.ValueItem -> {
|
||||||
|
div("row") {
|
||||||
|
div("col") {
|
||||||
|
label("tree-label") {
|
||||||
|
+token.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
div("col") {
|
||||||
|
label {
|
||||||
|
+item.value.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,108 @@
|
|||||||
|
package hep.dataforge.vis.editor
|
||||||
|
|
||||||
|
import hep.dataforge.names.Name
|
||||||
|
import hep.dataforge.names.plus
|
||||||
|
import hep.dataforge.vis.VisualGroup
|
||||||
|
import hep.dataforge.vis.VisualObject
|
||||||
|
import hep.dataforge.vis.isEmpty
|
||||||
|
import kotlinx.html.classes
|
||||||
|
import kotlinx.html.js.onClickFunction
|
||||||
|
import org.w3c.dom.Element
|
||||||
|
import react.*
|
||||||
|
import react.dom.*
|
||||||
|
|
||||||
|
interface ObjectTreeProps : RProps {
|
||||||
|
var name: Name
|
||||||
|
var obj: VisualObject
|
||||||
|
var clickCallback: (Name) -> Unit
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TreeState : RState {
|
||||||
|
var expanded: Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
class ObjectTreeComponent : RComponent<ObjectTreeProps, TreeState>() {
|
||||||
|
|
||||||
|
override fun TreeState.init() {
|
||||||
|
expanded = false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun RBuilder.render() {
|
||||||
|
val token = props.name.last()?.toString() ?: "World"
|
||||||
|
val obj = props.obj
|
||||||
|
|
||||||
|
//display as node if any child is visible
|
||||||
|
if (obj is VisualGroup && obj.children.keys.any { !it.body.startsWith("@") }) {
|
||||||
|
div("d-inline-block text-truncate") {
|
||||||
|
span("objTree-caret") {
|
||||||
|
attrs {
|
||||||
|
classes = if (state.expanded) {
|
||||||
|
setOf("objTree-caret", "objTree-caret-down")
|
||||||
|
} else {
|
||||||
|
setOf("objTree-caret")
|
||||||
|
}
|
||||||
|
onClickFunction = {
|
||||||
|
setState {
|
||||||
|
expanded = !expanded
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
label("objTree-label") {
|
||||||
|
+token
|
||||||
|
attrs {
|
||||||
|
onClickFunction = { props.clickCallback(props.name) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (state.expanded) {
|
||||||
|
ul("objTree-subtree") {
|
||||||
|
obj.children.entries
|
||||||
|
.filter { !it.key.toString().startsWith("@") } // ignore statics and other hidden children
|
||||||
|
.sortedBy { (it.value as? VisualGroup)?.isEmpty ?: true }
|
||||||
|
.forEach { (childToken, child) ->
|
||||||
|
li {
|
||||||
|
child(ObjectTreeComponent::class) {
|
||||||
|
attrs {
|
||||||
|
name = props.name + childToken
|
||||||
|
this.obj = child
|
||||||
|
clickCallback = props.clickCallback
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
div("d-inline-block text-truncate") {
|
||||||
|
span("objTree-leaf") {}
|
||||||
|
label("objTree-label") {
|
||||||
|
+token
|
||||||
|
attrs {
|
||||||
|
onClickFunction = { props.clickCallback(props.name) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun RBuilder.objectTree(
|
||||||
|
obj: VisualObject,
|
||||||
|
clickCallback: (Name) -> Unit = {}
|
||||||
|
) = child(ObjectTreeComponent::class) {
|
||||||
|
attrs {
|
||||||
|
name = Name.EMPTY
|
||||||
|
this.obj = obj
|
||||||
|
this.clickCallback = clickCallback
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Element.objectTree(
|
||||||
|
obj: VisualObject,
|
||||||
|
clickCallback: (Name) -> Unit = {}
|
||||||
|
) {
|
||||||
|
render(this) {
|
||||||
|
objectTree(obj, clickCallback)
|
||||||
|
}
|
||||||
|
}
|
@ -3,6 +3,10 @@ package hep.dataforge.vis.editor
|
|||||||
import kotlinx.html.*
|
import kotlinx.html.*
|
||||||
import kotlinx.html.js.div
|
import kotlinx.html.js.div
|
||||||
import org.w3c.dom.HTMLElement
|
import org.w3c.dom.HTMLElement
|
||||||
|
import react.RBuilder
|
||||||
|
import react.ReactElement
|
||||||
|
import react.dom.div
|
||||||
|
import react.dom.h3
|
||||||
|
|
||||||
inline fun TagConsumer<HTMLElement>.card(title: String, crossinline block: TagConsumer<HTMLElement>.() -> Unit) {
|
inline fun TagConsumer<HTMLElement>.card(title: String, crossinline block: TagConsumer<HTMLElement>.() -> Unit) {
|
||||||
div("card w-100") {
|
div("card w-100") {
|
||||||
@ -13,6 +17,14 @@ inline fun TagConsumer<HTMLElement>.card(title: String, crossinline block: TagCo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline fun RBuilder.card(title: String, crossinline block: RBuilder.() -> Unit): ReactElement = div("card w-100") {
|
||||||
|
div("card-body") {
|
||||||
|
h3(classes = "card-title") { +title }
|
||||||
|
block()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
fun TagConsumer<HTMLElement>.accordion(id: String, elements: Map<String, DIV.() -> Unit>) {
|
fun TagConsumer<HTMLElement>.accordion(id: String, elements: Map<String, DIV.() -> Unit>) {
|
||||||
div("container-fluid") {
|
div("container-fluid") {
|
||||||
div("accordion") {
|
div("accordion") {
|
||||||
|
@ -13,18 +13,18 @@ import org.w3c.dom.HTMLElement
|
|||||||
import org.w3c.dom.HTMLSpanElement
|
import org.w3c.dom.HTMLSpanElement
|
||||||
import kotlin.dom.clear
|
import kotlin.dom.clear
|
||||||
|
|
||||||
fun Element.displayObjectTree(
|
//fun Element.displayObjectTree(
|
||||||
obj: VisualObject,
|
// obj: VisualObject,
|
||||||
clickCallback: (Name) -> Unit = {}
|
// clickCallback: (Name) -> Unit = {}
|
||||||
) {
|
//) {
|
||||||
clear()
|
// clear()
|
||||||
append {
|
// append {
|
||||||
card("Object tree") {
|
// card("Object tree") {
|
||||||
subTree(Name.EMPTY, obj, clickCallback)
|
// subTree(Name.EMPTY, obj, clickCallback)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
//
|
||||||
private fun TagConsumer<HTMLElement>.subTree(
|
private fun TagConsumer<HTMLElement>.subTree(
|
||||||
name: Name,
|
name: Name,
|
||||||
obj: VisualObject,
|
obj: VisualObject,
|
||||||
|
@ -1,73 +1,102 @@
|
|||||||
package hep.dataforge.vis.editor
|
package hep.dataforge.vis.editor
|
||||||
|
|
||||||
import hep.dataforge.js.jsObject
|
|
||||||
import hep.dataforge.meta.DynamicMeta
|
|
||||||
import hep.dataforge.meta.Meta
|
import hep.dataforge.meta.Meta
|
||||||
import hep.dataforge.meta.toJson
|
import hep.dataforge.meta.MetaBuilder
|
||||||
import hep.dataforge.meta.update
|
|
||||||
import hep.dataforge.names.Name
|
import hep.dataforge.names.Name
|
||||||
import hep.dataforge.names.isEmpty
|
import hep.dataforge.names.isEmpty
|
||||||
import hep.dataforge.vis.VisualObject
|
import hep.dataforge.vis.VisualObject
|
||||||
import hep.dataforge.vis.findStyle
|
|
||||||
import kotlinx.html.dom.append
|
|
||||||
import kotlinx.html.js.*
|
|
||||||
import org.w3c.dom.Element
|
import org.w3c.dom.Element
|
||||||
|
import react.RBuilder
|
||||||
|
import react.ReactElement
|
||||||
|
import react.dom.li
|
||||||
|
import react.dom.nav
|
||||||
|
import react.dom.ol
|
||||||
|
import react.dom.render
|
||||||
import kotlin.collections.set
|
import kotlin.collections.set
|
||||||
import kotlin.dom.clear
|
|
||||||
|
|
||||||
//FIXME something rotten in JS-Meta converter
|
////FIXME something rotten in JS-Meta converter
|
||||||
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
|
||||||
|
//fun Element.displayPropertyEditor(
|
||||||
|
// name: Name,
|
||||||
|
// item: VisualObject,
|
||||||
|
// propertySelector: (VisualObject) -> Meta = { it.config }
|
||||||
|
//) {
|
||||||
|
// clear()
|
||||||
|
//
|
||||||
|
// append {
|
||||||
|
// 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 options: JSONEditorOptions = jsObject {
|
||||||
|
// mode = "form"
|
||||||
|
// onChangeJSON = { item.config.update(DynamicMeta(it.asDynamic())) }
|
||||||
|
// }
|
||||||
|
// JSONEditor(div(), options, dMeta)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// val styles = item.styles
|
||||||
|
// if (styles.isNotEmpty()) {
|
||||||
|
// card("Styles") {
|
||||||
|
// item.styles.forEach { style ->
|
||||||
|
// val styleMeta = item.findStyle(style)
|
||||||
|
// h4("container") { +style }
|
||||||
|
// if (styleMeta != null) {
|
||||||
|
// div("container").apply {
|
||||||
|
// val options: JSONEditorOptions = jsObject {
|
||||||
|
// mode = "view"
|
||||||
|
// }
|
||||||
|
// JSONEditor(
|
||||||
|
// this,
|
||||||
|
// options,
|
||||||
|
// styleMeta.toDynamic()
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
//TODO add node descriptor instead of configuring property selector
|
fun RBuilder.visualPropertyEditor(
|
||||||
fun Element.displayPropertyEditor(
|
path: Name,
|
||||||
name: Name,
|
|
||||||
item: VisualObject,
|
item: VisualObject,
|
||||||
propertySelector: (VisualObject) -> Meta = { it.config }
|
default: MetaBuilder.() -> Unit = {}
|
||||||
) {
|
): ReactElement = card("Properties") {
|
||||||
clear()
|
if (!path.isEmpty()) {
|
||||||
|
nav {
|
||||||
append {
|
attrs {
|
||||||
card("Properties") {
|
attributes["aria-label"] = "breadcrumb"
|
||||||
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()
|
ol("breadcrumb") {
|
||||||
val options: JSONEditorOptions = jsObject {
|
path.tokens.forEach { token ->
|
||||||
mode = "form"
|
li("breadcrumb-item") {
|
||||||
onChangeJSON = { item.config.update(DynamicMeta(it.asDynamic())) }
|
+token.toString()
|
||||||
}
|
|
||||||
JSONEditor(div(), options, dMeta)
|
|
||||||
}
|
|
||||||
|
|
||||||
val styles = item.styles
|
|
||||||
if (styles.isNotEmpty()) {
|
|
||||||
card("Styles") {
|
|
||||||
item.styles.forEach { style ->
|
|
||||||
val styleMeta = item.findStyle(style)
|
|
||||||
h4("container") { +style }
|
|
||||||
if (styleMeta != null) {
|
|
||||||
div("container").apply {
|
|
||||||
val options: JSONEditorOptions = jsObject {
|
|
||||||
mode = "view"
|
|
||||||
}
|
|
||||||
JSONEditor(
|
|
||||||
this,
|
|
||||||
options,
|
|
||||||
styleMeta.toDynamic()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
configEditor(item.config, item.descriptor, Meta(default))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Element.visualPropertyEditor(
|
||||||
|
path: Name,
|
||||||
|
item: VisualObject,
|
||||||
|
default: MetaBuilder.() -> Unit = {}
|
||||||
|
) = render(this) {
|
||||||
|
visualPropertyEditor(path, item, default)
|
||||||
}
|
}
|
@ -21,3 +21,20 @@ ul, .objTree-subtree {
|
|||||||
.objTree-caret-down::before {
|
.objTree-caret-down::before {
|
||||||
transform: rotate(90deg);
|
transform: rotate(90deg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ul, .tree {
|
||||||
|
list-style-type: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
i, .tree-caret{
|
||||||
|
display: inline-block;
|
||||||
|
margin-right: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rotate {
|
||||||
|
transform: rotate(90deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tree-label-inactive {
|
||||||
|
color: gray;
|
||||||
|
}
|
||||||
|
@ -108,8 +108,7 @@ interface ValueChooser {
|
|||||||
descriptor: ValueDescriptor? = null,
|
descriptor: ValueDescriptor? = null,
|
||||||
setter: (Value) -> Unit
|
setter: (Value) -> Unit
|
||||||
): ValueChooser {
|
): ValueChooser {
|
||||||
val chooser =
|
val chooser = build(context, descriptor)
|
||||||
build(context, descriptor)
|
|
||||||
chooser.setDisplayValue(value.value ?: Null)
|
chooser.setDisplayValue(value.value ?: Null)
|
||||||
value.onChange {
|
value.onChange {
|
||||||
chooser.setDisplayValue(it ?: Null)
|
chooser.setDisplayValue(it ?: Null)
|
||||||
|
@ -7,7 +7,7 @@ kotlin {
|
|||||||
val commonMain by getting {
|
val commonMain by getting {
|
||||||
dependencies {
|
dependencies {
|
||||||
api(project(":dataforge-vis-spatial"))
|
api(project(":dataforge-vis-spatial"))
|
||||||
api("scientifik:gdml:0.1.6")
|
api("scientifik:gdml:0.1.7")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,6 @@ import hep.dataforge.names.NameToken
|
|||||||
import hep.dataforge.names.asName
|
import hep.dataforge.names.asName
|
||||||
import hep.dataforge.names.plus
|
import hep.dataforge.names.plus
|
||||||
import hep.dataforge.vis.*
|
import hep.dataforge.vis.*
|
||||||
import hep.dataforge.vis.common.*
|
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.Transient
|
import kotlinx.serialization.Transient
|
||||||
|
@ -212,4 +212,8 @@ class ThreeCanvas(element: HTMLElement, val three: ThreePlugin, val canvas: Canv
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun ThreePlugin.output(element: HTMLElement, spec: Canvas = Canvas.empty()): ThreeCanvas =
|
fun ThreePlugin.output(element: HTMLElement, spec: Canvas = Canvas.empty()): ThreeCanvas =
|
||||||
ThreeCanvas(element, this, spec)
|
ThreeCanvas(element, this, spec)
|
||||||
|
|
||||||
|
fun ThreePlugin.render(element: HTMLElement, obj: VisualObject3D, spec: Canvas = Canvas.empty()): Unit =
|
||||||
|
output(element, spec).render(obj)
|
||||||
|
|
||||||
|
@ -0,0 +1,56 @@
|
|||||||
|
package hep.dataforge.vis.spatial.three
|
||||||
|
|
||||||
|
import hep.dataforge.context.Global
|
||||||
|
import hep.dataforge.vis.spatial.VisualObject3D
|
||||||
|
import hep.dataforge.vis.spatial.specifications.Canvas
|
||||||
|
import kotlinx.html.id
|
||||||
|
import org.w3c.dom.HTMLElement
|
||||||
|
import react.RBuilder
|
||||||
|
import react.RComponent
|
||||||
|
import react.RProps
|
||||||
|
import react.RState
|
||||||
|
import react.dom.div
|
||||||
|
import kotlin.browser.document
|
||||||
|
import kotlin.dom.clear
|
||||||
|
|
||||||
|
interface ThreeCanvasProps : RProps {
|
||||||
|
var obj: VisualObject3D
|
||||||
|
var canvasId: String
|
||||||
|
var options: Canvas
|
||||||
|
}
|
||||||
|
|
||||||
|
class ThreeCanvasComponent : RComponent<ThreeCanvasProps, RState>() {
|
||||||
|
|
||||||
|
private val three: ThreePlugin = Global.plugins.fetch(ThreePlugin)
|
||||||
|
|
||||||
|
override fun componentDidMount() {
|
||||||
|
val element = document.getElementById(props.canvasId) as? HTMLElement
|
||||||
|
?: error("Element with id 'canvas' not found on page")
|
||||||
|
val output = three.output(element, props.options)
|
||||||
|
output.render(props.obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun componentWillUnmount() {
|
||||||
|
val element = document.getElementById(props.canvasId) as? HTMLElement
|
||||||
|
?: error("Element with id 'canvas' not found on page")
|
||||||
|
element.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun RBuilder.render() {
|
||||||
|
div {
|
||||||
|
attrs {
|
||||||
|
id = props.canvasId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun RBuilder.threeCanvas(object3D: VisualObject3D, id: String = "threeCanvas", options: Canvas.() -> Unit = {}) {
|
||||||
|
child(ThreeCanvasComponent::class) {
|
||||||
|
attrs {
|
||||||
|
this.obj = object3D
|
||||||
|
this.canvasId = id
|
||||||
|
this.options = Canvas.invoke(options)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -9,8 +9,8 @@ import hep.dataforge.names.Name
|
|||||||
import hep.dataforge.names.isEmpty
|
import hep.dataforge.names.isEmpty
|
||||||
import hep.dataforge.vis.VisualGroup
|
import hep.dataforge.vis.VisualGroup
|
||||||
import hep.dataforge.vis.VisualObject
|
import hep.dataforge.vis.VisualObject
|
||||||
import hep.dataforge.vis.editor.displayObjectTree
|
import hep.dataforge.vis.editor.objectTree
|
||||||
import hep.dataforge.vis.editor.displayPropertyEditor
|
import hep.dataforge.vis.editor.visualPropertyEditor
|
||||||
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
|
||||||
import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_WIREFRAME_KEY
|
import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_WIREFRAME_KEY
|
||||||
@ -163,26 +163,35 @@ private class GDMLDemoApp : Application {
|
|||||||
visual is VisualGroup -> visual[name] ?: return
|
visual is VisualGroup -> visual[name] ?: return
|
||||||
else -> return
|
else -> return
|
||||||
}
|
}
|
||||||
editorElement.displayPropertyEditor(name, child) { item ->
|
|
||||||
//val descriptorMeta = Material3D.descriptor
|
|
||||||
|
|
||||||
val properties = item.allProperties()
|
editorElement.visualPropertyEditor(name, child) {
|
||||||
val bottom = Meta {
|
VISIBLE_KEY put true
|
||||||
VISIBLE_KEY put (item.visible ?: true)
|
if (child is VisualObject3D) {
|
||||||
if (item is VisualObject3D) {
|
MATERIAL_COLOR_KEY put "#ffffff"
|
||||||
MATERIAL_COLOR_KEY put "#ffffff"
|
MATERIAL_OPACITY_KEY put 1.0
|
||||||
MATERIAL_OPACITY_KEY put 1.0
|
MATERIAL_WIREFRAME_KEY put false
|
||||||
MATERIAL_WIREFRAME_KEY put false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
properties.withBottom(bottom)
|
|
||||||
}
|
}
|
||||||
|
// 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
|
||||||
|
|
||||||
//tree.visualObjectTree(visual, editor::propertyEditor)
|
//tree.visualObjectTree(visual, editor::propertyEditor)
|
||||||
treeElement.displayObjectTree(visual) { treeName ->
|
treeElement.objectTree(visual) { treeName ->
|
||||||
selectElement(treeName)
|
selectElement(treeName)
|
||||||
canvas.highlight(treeName)
|
canvas.highlight(treeName)
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ plugins {
|
|||||||
|
|
||||||
group = "ru.mipt.npm"
|
group = "ru.mipt.npm"
|
||||||
|
|
||||||
val ktor_version = "1.3.2"
|
val ktorVersion = "1.3.2"
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
|
|
||||||
@ -34,23 +34,28 @@ kotlin {
|
|||||||
jvmMain {
|
jvmMain {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("org.apache.commons:commons-math3:3.6.1")
|
implementation("org.apache.commons:commons-math3:3.6.1")
|
||||||
implementation("io.ktor:ktor-server-cio:$ktor_version")
|
implementation("io.ktor:ktor-server-cio:$ktorVersion")
|
||||||
implementation("io.ktor:ktor-serialization:$ktor_version")
|
implementation("io.ktor:ktor-serialization:$ktorVersion")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
jsMain {
|
jsMain {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("io.ktor:ktor-client-js:$ktor_version")
|
implementation("io.ktor:ktor-client-js:$ktorVersion")
|
||||||
implementation("io.ktor:ktor-client-serialization-js:$ktor_version")
|
implementation("io.ktor:ktor-client-serialization-js:$ktorVersion")
|
||||||
implementation(npm("text-encoding"))
|
implementation(npm("text-encoding"))
|
||||||
implementation(npm("abort-controller"))
|
implementation(npm("abort-controller"))
|
||||||
|
implementation(npm("bufferutil"))
|
||||||
|
implementation(npm("utf-8-validate"))
|
||||||
|
// implementation(npm("jquery"))
|
||||||
|
// implementation(npm("popper.js"))
|
||||||
|
// implementation(npm("react-is"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
application {
|
application {
|
||||||
mainClassName = "ru.mipt.npm.muon.monitor.server/MMServerKt"
|
mainClassName = "ru.mipt.npm.muon.monitor.server.MMServerKt"
|
||||||
}
|
}
|
||||||
|
|
||||||
//configure<JavaFXOptions> {
|
//configure<JavaFXOptions> {
|
||||||
|
@ -3,15 +3,13 @@ package ru.mipt.npm.muon.monitor
|
|||||||
import hep.dataforge.context.Global
|
import hep.dataforge.context.Global
|
||||||
import hep.dataforge.js.Application
|
import hep.dataforge.js.Application
|
||||||
import hep.dataforge.js.startApplication
|
import hep.dataforge.js.startApplication
|
||||||
import hep.dataforge.meta.Meta
|
|
||||||
import hep.dataforge.meta.withBottom
|
|
||||||
import hep.dataforge.names.Name
|
import hep.dataforge.names.Name
|
||||||
import hep.dataforge.names.isEmpty
|
import hep.dataforge.names.isEmpty
|
||||||
import hep.dataforge.vis.VisualGroup
|
import hep.dataforge.vis.VisualGroup
|
||||||
import hep.dataforge.vis.VisualObject
|
import hep.dataforge.vis.VisualObject
|
||||||
import hep.dataforge.vis.editor.card
|
import hep.dataforge.vis.editor.card
|
||||||
import hep.dataforge.vis.editor.displayObjectTree
|
import hep.dataforge.vis.editor.objectTree
|
||||||
import hep.dataforge.vis.editor.displayPropertyEditor
|
import hep.dataforge.vis.editor.visualPropertyEditor
|
||||||
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
|
||||||
import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_WIREFRAME_KEY
|
import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_WIREFRAME_KEY
|
||||||
@ -21,7 +19,6 @@ 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
|
||||||
import hep.dataforge.vis.spatial.visible
|
|
||||||
import info.laht.threekt.math.Vector3
|
import info.laht.threekt.math.Vector3
|
||||||
import io.ktor.client.HttpClient
|
import io.ktor.client.HttpClient
|
||||||
import io.ktor.client.features.json.JsonFeature
|
import io.ktor.client.features.json.JsonFeature
|
||||||
@ -66,7 +63,7 @@ private class MMDemoApp : Application {
|
|||||||
canvas.camera.layers.set(0)
|
canvas.camera.layers.set(0)
|
||||||
canvas.camera.position.z = -2000.0
|
canvas.camera.position.z = -2000.0
|
||||||
canvas.camera.position.y = 500.0
|
canvas.camera.position.y = 500.0
|
||||||
canvas.camera.lookAt(Vector3(0,0,0))
|
canvas.camera.lookAt(Vector3(0, 0, 0))
|
||||||
settingsElement.displayCanvasControls(canvas) {
|
settingsElement.displayCanvasControls(canvas) {
|
||||||
card("Events") {
|
card("Events") {
|
||||||
button {
|
button {
|
||||||
@ -94,26 +91,34 @@ private class MMDemoApp : Application {
|
|||||||
visual is VisualGroup -> visual[name] ?: return
|
visual is VisualGroup -> visual[name] ?: return
|
||||||
else -> return
|
else -> return
|
||||||
}
|
}
|
||||||
editorElement.displayPropertyEditor(name, child) { item ->
|
editorElement.visualPropertyEditor(name, child) {
|
||||||
//val descriptorMeta = Material3D.descriptor
|
VISIBLE_KEY put true
|
||||||
|
if (child is VisualObject3D) {
|
||||||
val properties = item.allProperties()
|
MATERIAL_COLOR_KEY put "#ffffff"
|
||||||
val bottom = Meta {
|
MATERIAL_OPACITY_KEY put 1.0
|
||||||
VISIBLE_KEY put (item.visible ?: true)
|
MATERIAL_WIREFRAME_KEY put false
|
||||||
if (item is VisualObject3D) {
|
|
||||||
MATERIAL_COLOR_KEY put "#ffffff"
|
|
||||||
MATERIAL_OPACITY_KEY put 1.0
|
|
||||||
MATERIAL_WIREFRAME_KEY put false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
properties.withBottom(bottom)
|
|
||||||
}
|
}
|
||||||
|
// 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
|
||||||
|
|
||||||
//tree.visualObjectTree(visual, editor::propertyEditor)
|
//tree.visualObjectTree(visual, editor::propertyEditor)
|
||||||
treeElement.displayObjectTree(visual) { name ->
|
treeElement.objectTree(visual) { name ->
|
||||||
selectElement(name)
|
selectElement(name)
|
||||||
canvas.highlight(name)
|
canvas.highlight(name)
|
||||||
}
|
}
|
||||||
|
@ -16,14 +16,6 @@ kotlin {
|
|||||||
withJava()
|
withJava()
|
||||||
}
|
}
|
||||||
|
|
||||||
js {
|
|
||||||
browser {
|
|
||||||
webpackTask {
|
|
||||||
sourceMaps = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sourceSets {
|
sourceSets {
|
||||||
commonMain {
|
commonMain {
|
||||||
dependencies {
|
dependencies {
|
||||||
|
@ -39,7 +39,6 @@ private class ThreeDemoApp : Application {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun dispose() = emptyMap<String, Any>()//mapOf("lines" put presenter.dispose())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
|
27
playground/build.gradle.kts
Normal file
27
playground/build.gradle.kts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
plugins {
|
||||||
|
kotlin("multiplatform")
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories{
|
||||||
|
jcenter()
|
||||||
|
maven("https://kotlin.bintray.com/kotlinx")
|
||||||
|
maven("https://dl.bintray.com/kotlin/kotlin-eap")
|
||||||
|
maven("https://dl.bintray.com/mipt-npm/dataforge")
|
||||||
|
maven("https://dl.bintray.com/mipt-npm/scientifik")
|
||||||
|
maven("https://dl.bintray.com/mipt-npm/dev")
|
||||||
|
}
|
||||||
|
|
||||||
|
kotlin {
|
||||||
|
js {
|
||||||
|
browser {}
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceSets {
|
||||||
|
commonMain {
|
||||||
|
dependencies {
|
||||||
|
api(project(":dataforge-vis-spatial"))
|
||||||
|
api(project(":dataforge-vis-spatial-gdml"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
56
playground/src/jsMain/kotlin/PlayGroundApp.kt
Normal file
56
playground/src/jsMain/kotlin/PlayGroundApp.kt
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
import hep.dataforge.context.Global
|
||||||
|
import hep.dataforge.js.Application
|
||||||
|
import hep.dataforge.js.startApplication
|
||||||
|
import hep.dataforge.names.Name
|
||||||
|
import hep.dataforge.vis.editor.objectTree
|
||||||
|
import hep.dataforge.vis.editor.visualPropertyEditor
|
||||||
|
import hep.dataforge.vis.spatial.Point3D
|
||||||
|
import hep.dataforge.vis.spatial.VisualGroup3D
|
||||||
|
import hep.dataforge.vis.spatial.box
|
||||||
|
import hep.dataforge.vis.spatial.group
|
||||||
|
import hep.dataforge.vis.spatial.three.ThreePlugin
|
||||||
|
import hep.dataforge.vis.spatial.three.threeCanvas
|
||||||
|
import org.w3c.dom.HTMLElement
|
||||||
|
import react.dom.div
|
||||||
|
import react.dom.render
|
||||||
|
import kotlin.browser.document
|
||||||
|
|
||||||
|
private class PlayGroundApp : Application {
|
||||||
|
|
||||||
|
private val three = Global.plugins.fetch(ThreePlugin)
|
||||||
|
|
||||||
|
override fun start(state: Map<String, Any>) {
|
||||||
|
|
||||||
|
val element =
|
||||||
|
document.getElementById("app") as? HTMLElement ?: error("Element with id 'canvas' not found on page")
|
||||||
|
|
||||||
|
val obj = VisualGroup3D().apply {
|
||||||
|
box(100, 100, 100)
|
||||||
|
group {
|
||||||
|
position = Point3D(120, 0, 0)
|
||||||
|
box(100, 100, 100)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render(element) {
|
||||||
|
div("row") {
|
||||||
|
div("col-3") {
|
||||||
|
objectTree(obj)
|
||||||
|
}
|
||||||
|
div("col-6") {
|
||||||
|
threeCanvas(obj)
|
||||||
|
}
|
||||||
|
div("col-3") {
|
||||||
|
visualPropertyEditor(Name.EMPTY, obj)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
startApplication(::PlayGroundApp)
|
||||||
|
}
|
40
playground/src/jsMain/resources/css/common.css
Normal file
40
playground/src/jsMain/resources/css/common.css
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/* Remove default bullets */
|
||||||
|
ul, .objTree-subtree {
|
||||||
|
list-style-type: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Style the caret/arrow */
|
||||||
|
.objTree-caret {
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none; /* Prevent text selection */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create the caret/arrow with a unicode, and style it */
|
||||||
|
.objTree-caret::before {
|
||||||
|
content: "\25B6";
|
||||||
|
color: black;
|
||||||
|
display: inline-block;
|
||||||
|
margin-right: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Rotate the caret/arrow icon when clicked on (using JavaScript) */
|
||||||
|
.objTree-caret-down::before {
|
||||||
|
transform: rotate(90deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
ul, .tree {
|
||||||
|
list-style-type: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
i, .tree-caret{
|
||||||
|
display: inline-block;
|
||||||
|
margin-right: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rotate {
|
||||||
|
transform: rotate(90deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tree-label-inactive {
|
||||||
|
color: gray;
|
||||||
|
}
|
16
playground/src/jsMain/resources/index.html
Normal file
16
playground/src/jsMain/resources/index.html
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Playground</title>
|
||||||
|
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
|
||||||
|
<link rel="stylesheet" href="css/common.css">
|
||||||
|
<script type="text/javascript" src="playground.js"></script>
|
||||||
|
</head>
|
||||||
|
<body class="testApp">
|
||||||
|
<div class="container">
|
||||||
|
<h1>Playground</h1>
|
||||||
|
</div>
|
||||||
|
<div id="app"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -30,7 +30,8 @@ include(
|
|||||||
":dataforge-vis-spatial-gdml",
|
":dataforge-vis-spatial-gdml",
|
||||||
":demo:spatial-showcase",
|
":demo:spatial-showcase",
|
||||||
":demo:gdml",
|
":demo:gdml",
|
||||||
":demo:muon-monitor"
|
":demo:muon-monitor",
|
||||||
|
":playground"
|
||||||
)
|
)
|
||||||
|
|
||||||
//if(file("../dataforge-core").exists()) {
|
//if(file("../dataforge-core").exists()) {
|
||||||
|
Loading…
Reference in New Issue
Block a user