diff --git a/demo/gdml/src/jsMain/kotlin/space/kscience/visionforge/gdml/demo/GDMLAppComponent.kt b/demo/gdml/src/jsMain/kotlin/space/kscience/visionforge/gdml/demo/GDMLAppComponent.kt index 0c52257d..2bad5e8d 100644 --- a/demo/gdml/src/jsMain/kotlin/space/kscience/visionforge/gdml/demo/GDMLAppComponent.kt +++ b/demo/gdml/src/jsMain/kotlin/space/kscience/visionforge/gdml/demo/GDMLAppComponent.kt @@ -3,6 +3,9 @@ package space.kscience.visionforge.gdml.demo import kotlinx.browser.window import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.Deferred +import kotlinx.css.height +import kotlinx.css.pt +import kotlinx.css.vh import org.w3c.files.File import org.w3c.files.FileReader import org.w3c.files.get @@ -20,6 +23,8 @@ import space.kscience.visionforge.ring.tab import space.kscience.visionforge.root import space.kscience.visionforge.solid.Solid import space.kscience.visionforge.solid.Solids +import styled.css +import styled.styledDiv external interface GDMLAppProps : RProps { var context: Context @@ -63,24 +68,29 @@ val GDMLApp = functionalComponent("GDMLApp") { props -> return deferred } - child(ThreeCanvasWithControls) { - attrs { - this.context = props.context - this.builderOfSolid = deferredVision - this.selected = props.selected - tab("Load") { - h2 { - +"Drag and drop .gdml or .json VisionForge files here" - } - fileDrop("(drag file here)") { files -> - val file = files?.get(0) - if (file != null) { - deferredVision = readFileAsync(file) + styledDiv { + css { + height = 100.vh - 12.pt + } + child(ThreeCanvasWithControls) { + attrs { + this.context = props.context + this.builderOfSolid = deferredVision + this.selected = props.selected + tab("Load") { + h2 { + +"Drag and drop .gdml or .json VisionForge files here" + } + fileDrop("(drag file here)") { files -> + val file = files?.get(0) + if (file != null) { + deferredVision = readFileAsync(file) + } } } } - } + } } } diff --git a/demo/muon-monitor/build.gradle.kts b/demo/muon-monitor/build.gradle.kts index 3a8035ab..3818cada 100644 --- a/demo/muon-monitor/build.gradle.kts +++ b/demo/muon-monitor/build.gradle.kts @@ -17,6 +17,14 @@ kotlin { jvm { withJava() } + js { + useCommonJs() + browser { + commonWebpackConfig { + cssSupport.enabled = false + } + } + } afterEvaluate { val jsBrowserDistribution by tasks.getting @@ -43,7 +51,7 @@ kotlin { } jsMain { dependencies { - implementation(project(":ui:bootstrap")) + implementation(project(":ui:ring")) implementation("io.ktor:ktor-client-js:$ktorVersion") implementation("io.ktor:ktor-client-serialization:$ktorVersion") implementation(project(":visionforge-threejs")) 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 8450cb4a..1a7fe071 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 @@ -2,31 +2,27 @@ package ru.mipt.npm.muon.monitor import io.ktor.client.HttpClient import io.ktor.client.request.get +import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.DelicateCoroutinesApi -import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import kotlinx.css.* import kotlinx.html.js.onClickFunction import react.* -import react.dom.* +import react.dom.attrs +import react.dom.button +import react.dom.p import space.kscience.dataforge.context.Context import space.kscience.dataforge.names.Name -import space.kscience.dataforge.names.NameToken -import space.kscience.dataforge.names.isEmpty -import space.kscience.dataforge.names.length -import space.kscience.visionforge.Vision -import space.kscience.visionforge.bootstrap.canvasControls -import space.kscience.visionforge.bootstrap.card -import space.kscience.visionforge.bootstrap.gridRow -import space.kscience.visionforge.bootstrap.visionPropertyEditor -import space.kscience.visionforge.react.ThreeCanvasComponent import space.kscience.visionforge.react.flexColumn -import space.kscience.visionforge.react.visionTree +import space.kscience.visionforge.react.flexRow +import space.kscience.visionforge.ring.ThreeCanvasWithControls +import space.kscience.visionforge.ring.tab import space.kscience.visionforge.solid.specifications.Camera import space.kscience.visionforge.solid.specifications.Canvas3DOptions import space.kscience.visionforge.solid.three.edges import styled.css import styled.styledDiv +import styled.styledSpan import kotlin.math.PI external interface MMAppProps : RProps { @@ -39,11 +35,6 @@ external interface MMAppProps : RProps { @OptIn(DelicateCoroutinesApi::class) @JsExport val MMApp = functionalComponent("Muon monitor") { props -> - var selected by useState { props.selected } - - val onSelect: (Name?) -> Unit = { - selected = it - } val mmOptions = useMemo { Canvas3DOptions { @@ -52,7 +43,6 @@ val MMApp = functionalComponent("Muon monitor") { props -> latitude = PI / 6 azimuth = PI + PI / 6 } - this.onSelect = onSelect } } @@ -62,142 +52,210 @@ val MMApp = functionalComponent("Muon monitor") { props -> } } - gridRow { - flexColumn { - css { - +"col-lg-3" - +"order-lg-1" - +"order-2" - padding(0.px) - overflowY = Overflow.auto - height = 100.vh - } - //tree - card("Object tree") { - css { - flex(1.0, 1.0, FlexBasis.auto) - } - visionTree(root, selected, onSelect) - } - } - flexColumn { - css { - +"col-lg-6" - +"order-lg-2" - +"order-1" - height = 100.vh - } - h1("mx-auto page-header") { - +"Muon monitor demo" - } - //canvas + var events: Set by useState(emptySet()) - child(ThreeCanvasComponent) { - attrs { - this.context = props.context - this.solid = root - this.selected = selected - this.options = mmOptions - } - } + styledDiv { + css { + height = 100.vh - 12.pt } - flexColumn { - css { - +"col-lg-3" - +"order-3" - padding(0.px) - height = 100.vh - } - styledDiv { - css { - flex(0.0, 1.0, FlexBasis.zero) - } - //settings - card("Canvas configuration") { - canvasControls(mmOptions, root) - } - - card("Events") { - button { - +"Next" - attrs { - onClickFunction = { - GlobalScope.launch { - val event = props.connection.get("http://localhost:8080/event") - props.model.displayEvent(event) - } - } - } - } - button { - +"Clear" - attrs { - onClickFunction = { - props.model.reset() - } - } - } - } - } - styledDiv { - css { - padding(0.px) - } - nav { - attrs { - attributes["aria-label"] = "breadcrumb" - } - ol("breadcrumb") { - li("breadcrumb-item") { - button(classes = "btn btn-link p-0") { - +"World" + child(ThreeCanvasWithControls) { + attrs { + this.context = props.context + this.builderOfSolid = CompletableDeferred(root) + this.selected = props.selected + this.options = mmOptions + tab("Events") { + flexColumn { + flexRow { + button { + +"Next" attrs { onClickFunction = { - selected = Name.EMPTY - } - } - } - } - if (selected != null) { - val tokens = ArrayList(selected?.length ?: 1) - selected?.tokens?.forEach { token -> - tokens.add(token) - val fullName = Name(tokens.toList()) - li("breadcrumb-item") { - button(classes = "btn btn-link p-0") { - +token.toString() - attrs { - onClickFunction = { - console.log("Selected = $fullName") - selected = fullName - } + context.launch { + val event = props.connection.get( + "http://localhost:8080/event" + ) + events = events + event + props.model.displayEvent(event) } } } } + button { + +"Clear" + attrs { + onClickFunction = { + events = emptySet() + props.model.reset() + } + } + } + } + } + events.forEach { event -> + p { + styledSpan { + +event.id.toString() + } + +" : " + styledSpan { + css{ + color = Color.blue + } + +event.hits.toString() + } } } } } - styledDiv { - css { - overflowY = Overflow.auto - } - //properties - card("Properties") { - selected.let { selected -> - val selectedObject: Vision? = when { - selected == null -> null - selected.isEmpty() -> root - else -> root[selected] - } - if (selectedObject != null) { - visionPropertyEditor(selectedObject, key = selected) - } - } - } - } - } + } } + +// var selected by useState { props.selected } +// +// val onSelect: (Name?) -> Unit = { +// selected = it +// } +// + +// +// gridRow { +// flexColumn { +// css { +// +"col-lg-3" +// +"order-lg-1" +// +"order-2" +// padding(0.px) +// overflowY = Overflow.auto +// height = 100.vh +// } +// //tree +// card("Object tree") { +// css { +// flex(1.0, 1.0, FlexBasis.auto) +// } +// visionTree(root, selected, onSelect) +// } +// } +// flexColumn { +// css { +// +"col-lg-6" +// +"order-lg-2" +// +"order-1" +// height = 100.vh +// } +// h1("mx-auto page-header") { +// +"Muon monitor demo" +// } +// //canvas +// +// child(ThreeCanvasComponent) { +// attrs { +// this.context = props.context +// this.solid = root +// this.selected = selected +// this.options = mmOptions +// } +// } +// } +// flexColumn { +// css { +// +"col-lg-3" +// +"order-3" +// padding(0.px) +// height = 100.vh +// } +// styledDiv { +// css { +// flex(0.0, 1.0, FlexBasis.zero) +// } +// //settings +// card("Canvas configuration") { +// canvasControls(mmOptions, root) +// } +// +// card("Events") { +// button { +// +"Next" +// attrs { +// onClickFunction = { +// GlobalScope.launch { +// val event = props.connection.get("http://localhost:8080/event") +// props.model.displayEvent(event) +// } +// } +// } +// } +// button { +// +"Clear" +// attrs { +// onClickFunction = { +// props.model.reset() +// } +// } +// } +// } +// } +// styledDiv { +// css { +// padding(0.px) +// } +// nav { +// attrs { +// attributes["aria-label"] = "breadcrumb" +// } +// ol("breadcrumb") { +// li("breadcrumb-item") { +// button(classes = "btn btn-link p-0") { +// +"World" +// attrs { +// onClickFunction = { +// selected = Name.EMPTY +// } +// } +// } +// } +// if (selected != null) { +// val tokens = ArrayList(selected?.length ?: 1) +// selected?.tokens?.forEach { token -> +// tokens.add(token) +// val fullName = Name(tokens.toList()) +// li("breadcrumb-item") { +// button(classes = "btn btn-link p-0") { +// +token.toString() +// attrs { +// onClickFunction = { +// console.log("Selected = $fullName") +// selected = fullName +// } +// } +// } +// } +// } +// } +// } +// } +// } +// styledDiv { +// css { +// overflowY = Overflow.auto +// } +// //properties +// card("Properties") { +// selected.let { selected -> +// val selectedObject: Vision? = when { +// selected == null -> null +// selected.isEmpty() -> root +// else -> root[selected] +// } +// if (selectedObject != null) { +// visionPropertyEditor(selectedObject, key = selected) +// } +// } +// } +// } +// } +// +// } } \ No newline at end of file diff --git a/demo/muon-monitor/src/jsMain/kotlin/ru/mipt/npm/muon/monitor/MMDemoApp.kt b/demo/muon-monitor/src/jsMain/kotlin/ru/mipt/npm/muon/monitor/MMDemoApp.kt index 9daa6213..f777d383 100644 --- a/demo/muon-monitor/src/jsMain/kotlin/ru/mipt/npm/muon/monitor/MMDemoApp.kt +++ b/demo/muon-monitor/src/jsMain/kotlin/ru/mipt/npm/muon/monitor/MMDemoApp.kt @@ -10,7 +10,6 @@ import space.kscience.dataforge.context.Context import space.kscience.dataforge.context.fetch import space.kscience.visionforge.Application import space.kscience.visionforge.VisionManager -import space.kscience.visionforge.bootstrap.useBootstrap import space.kscience.visionforge.solid.three.ThreePlugin import space.kscience.visionforge.startApplication @@ -23,7 +22,6 @@ private class MMDemoApp : Application { } override fun start(state: Map) { - useBootstrap() val context = Context("MM-demo"){ plugin(ThreePlugin) diff --git a/demo/muon-monitor/webpack.config.d/01.ring.js b/demo/muon-monitor/webpack.config.d/01.ring.js new file mode 100644 index 00000000..41da041c --- /dev/null +++ b/demo/muon-monitor/webpack.config.d/01.ring.js @@ -0,0 +1,3 @@ +const ringConfig = require('@jetbrains/ring-ui/webpack.config').config; + +config.module.rules.push(...ringConfig.module.rules) \ No newline at end of file diff --git a/ui/react/src/main/kotlin/space/kscience/visionforge/react/valueChooser.kt b/ui/react/src/main/kotlin/space/kscience/visionforge/react/valueChooser.kt index 4727cde0..711710f6 100644 --- a/ui/react/src/main/kotlin/space/kscience/visionforge/react/valueChooser.kt +++ b/ui/react/src/main/kotlin/space/kscience/visionforge/react/valueChooser.kt @@ -70,7 +70,7 @@ public val BooleanValueChooser: FunctionComponent = } attrs { //this.attributes["indeterminate"] = (props.item == null).toString() - defaultChecked = props.actual.boolean ?: false + checked = props.actual.boolean ?: false onChangeFunction = handleChange } } diff --git a/ui/ring/src/main/kotlin/space.kscience.visionforge.ring/ThreeViewWithControls.kt b/ui/ring/src/main/kotlin/space.kscience.visionforge.ring/ThreeViewWithControls.kt index 06cffdd0..2cf552a2 100644 --- a/ui/ring/src/main/kotlin/space.kscience.visionforge.ring/ThreeViewWithControls.kt +++ b/ui/ring/src/main/kotlin/space.kscience.visionforge.ring/ThreeViewWithControls.kt @@ -30,6 +30,7 @@ public external interface ThreeCanvasWithControlsProps : RProps { public var context: Context public var builderOfSolid: Deferred public var selected: Name? + public var options: Canvas3DOptions? public var additionalTabs: Map Unit>? } @@ -92,8 +93,8 @@ public val ThreeCanvasWithControls: FunctionComponent