0.2.0 #71

Merged
altavir merged 139 commits from dev into master 2022-01-24 09:44:18 +03:00
7 changed files with 242 additions and 162 deletions
Showing only changes of commit cbc67cb16b - Show all commits

View File

@ -3,6 +3,9 @@ package space.kscience.visionforge.gdml.demo
import kotlinx.browser.window import kotlinx.browser.window
import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.Deferred 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.File
import org.w3c.files.FileReader import org.w3c.files.FileReader
import org.w3c.files.get import org.w3c.files.get
@ -20,6 +23,8 @@ import space.kscience.visionforge.ring.tab
import space.kscience.visionforge.root import space.kscience.visionforge.root
import space.kscience.visionforge.solid.Solid import space.kscience.visionforge.solid.Solid
import space.kscience.visionforge.solid.Solids import space.kscience.visionforge.solid.Solids
import styled.css
import styled.styledDiv
external interface GDMLAppProps : RProps { external interface GDMLAppProps : RProps {
var context: Context var context: Context
@ -63,24 +68,29 @@ val GDMLApp = functionalComponent<GDMLAppProps>("GDMLApp") { props ->
return deferred return deferred
} }
child(ThreeCanvasWithControls) { styledDiv {
attrs { css {
this.context = props.context height = 100.vh - 12.pt
this.builderOfSolid = deferredVision }
this.selected = props.selected child(ThreeCanvasWithControls) {
tab("Load") { attrs {
h2 { this.context = props.context
+"Drag and drop .gdml or .json VisionForge files here" this.builderOfSolid = deferredVision
} this.selected = props.selected
fileDrop("(drag file here)") { files -> tab("Load") {
val file = files?.get(0) h2 {
if (file != null) { +"Drag and drop .gdml or .json VisionForge files here"
deferredVision = readFileAsync(file) }
fileDrop("(drag file here)") { files ->
val file = files?.get(0)
if (file != null) {
deferredVision = readFileAsync(file)
}
} }
} }
} }
}
}
} }
} }

View File

@ -17,6 +17,14 @@ kotlin {
jvm { jvm {
withJava() withJava()
} }
js {
useCommonJs()
browser {
commonWebpackConfig {
cssSupport.enabled = false
}
}
}
afterEvaluate { afterEvaluate {
val jsBrowserDistribution by tasks.getting val jsBrowserDistribution by tasks.getting
@ -43,7 +51,7 @@ kotlin {
} }
jsMain { jsMain {
dependencies { dependencies {
implementation(project(":ui:bootstrap")) implementation(project(":ui:ring"))
implementation("io.ktor:ktor-client-js:$ktorVersion") implementation("io.ktor:ktor-client-js:$ktorVersion")
implementation("io.ktor:ktor-client-serialization:$ktorVersion") implementation("io.ktor:ktor-client-serialization:$ktorVersion")
implementation(project(":visionforge-threejs")) implementation(project(":visionforge-threejs"))

View File

@ -2,31 +2,27 @@ package ru.mipt.npm.muon.monitor
import io.ktor.client.HttpClient import io.ktor.client.HttpClient
import io.ktor.client.request.get import io.ktor.client.request.get
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.css.* import kotlinx.css.*
import kotlinx.html.js.onClickFunction import kotlinx.html.js.onClickFunction
import react.* 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.context.Context
import space.kscience.dataforge.names.Name 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.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.Camera
import space.kscience.visionforge.solid.specifications.Canvas3DOptions import space.kscience.visionforge.solid.specifications.Canvas3DOptions
import space.kscience.visionforge.solid.three.edges import space.kscience.visionforge.solid.three.edges
import styled.css import styled.css
import styled.styledDiv import styled.styledDiv
import styled.styledSpan
import kotlin.math.PI import kotlin.math.PI
external interface MMAppProps : RProps { external interface MMAppProps : RProps {
@ -39,11 +35,6 @@ external interface MMAppProps : RProps {
@OptIn(DelicateCoroutinesApi::class) @OptIn(DelicateCoroutinesApi::class)
@JsExport @JsExport
val MMApp = functionalComponent<MMAppProps>("Muon monitor") { props -> val MMApp = functionalComponent<MMAppProps>("Muon monitor") { props ->
var selected by useState { props.selected }
val onSelect: (Name?) -> Unit = {
selected = it
}
val mmOptions = useMemo { val mmOptions = useMemo {
Canvas3DOptions { Canvas3DOptions {
@ -52,7 +43,6 @@ val MMApp = functionalComponent<MMAppProps>("Muon monitor") { props ->
latitude = PI / 6 latitude = PI / 6
azimuth = PI + PI / 6 azimuth = PI + PI / 6
} }
this.onSelect = onSelect
} }
} }
@ -62,142 +52,210 @@ val MMApp = functionalComponent<MMAppProps>("Muon monitor") { props ->
} }
} }
gridRow { var events: Set<Event> by useState(emptySet())
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) { styledDiv {
attrs { css {
this.context = props.context height = 100.vh - 12.pt
this.solid = root
this.selected = selected
this.options = mmOptions
}
}
} }
flexColumn { child(ThreeCanvasWithControls) {
css { attrs {
+"col-lg-3" this.context = props.context
+"order-3" this.builderOfSolid = CompletableDeferred(root)
padding(0.px) this.selected = props.selected
height = 100.vh this.options = mmOptions
} tab("Events") {
styledDiv { flexColumn {
css { flexRow {
flex(0.0, 1.0, FlexBasis.zero) button {
} +"Next"
//settings
card("Canvas configuration") {
canvasControls(mmOptions, root)
}
card("Events") {
button {
+"Next"
attrs {
onClickFunction = {
GlobalScope.launch {
val event = props.connection.get<Event>("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 { attrs {
onClickFunction = { onClickFunction = {
selected = Name.EMPTY context.launch {
} val event = props.connection.get<Event>(
} "http://localhost:8080/event"
} )
} events = events + event
if (selected != null) { props.model.displayEvent(event)
val tokens = ArrayList<NameToken>(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
}
} }
} }
} }
} }
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<Event>("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<NameToken>(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)
// }
// }
// }
// }
// }
//
// }
} }

View File

@ -10,7 +10,6 @@ import space.kscience.dataforge.context.Context
import space.kscience.dataforge.context.fetch import space.kscience.dataforge.context.fetch
import space.kscience.visionforge.Application import space.kscience.visionforge.Application
import space.kscience.visionforge.VisionManager import space.kscience.visionforge.VisionManager
import space.kscience.visionforge.bootstrap.useBootstrap
import space.kscience.visionforge.solid.three.ThreePlugin import space.kscience.visionforge.solid.three.ThreePlugin
import space.kscience.visionforge.startApplication import space.kscience.visionforge.startApplication
@ -23,7 +22,6 @@ private class MMDemoApp : Application {
} }
override fun start(state: Map<String, Any>) { override fun start(state: Map<String, Any>) {
useBootstrap()
val context = Context("MM-demo"){ val context = Context("MM-demo"){
plugin(ThreePlugin) plugin(ThreePlugin)

View File

@ -0,0 +1,3 @@
const ringConfig = require('@jetbrains/ring-ui/webpack.config').config;
config.module.rules.push(...ringConfig.module.rules)

View File

@ -70,7 +70,7 @@ public val BooleanValueChooser: FunctionComponent<ValueChooserProps> =
} }
attrs { attrs {
//this.attributes["indeterminate"] = (props.item == null).toString() //this.attributes["indeterminate"] = (props.item == null).toString()
defaultChecked = props.actual.boolean ?: false checked = props.actual.boolean ?: false
onChangeFunction = handleChange onChangeFunction = handleChange
} }
} }

View File

@ -30,6 +30,7 @@ public external interface ThreeCanvasWithControlsProps : RProps {
public var context: Context public var context: Context
public var builderOfSolid: Deferred<Solid?> public var builderOfSolid: Deferred<Solid?>
public var selected: Name? public var selected: Name?
public var options: Canvas3DOptions?
public var additionalTabs: Map<String, RBuilder.() -> Unit>? public var additionalTabs: Map<String, RBuilder.() -> Unit>?
} }
@ -92,8 +93,8 @@ public val ThreeCanvasWithControls: FunctionComponent<ThreeCanvasWithControlsPro
selected = it selected = it
} }
val options = useMemo(props.context) { val options = useMemo(props.options) {
Canvas3DOptions.invoke { (props.options?: Canvas3DOptions()).apply {
this.onSelect = onSelect this.onSelect = onSelect
} }
} }
@ -172,6 +173,8 @@ public val ThreeCanvasWithControls: FunctionComponent<ThreeCanvasWithControlsPro
css { css {
padding(4.px) padding(4.px)
minWidth = 400.px minWidth = 400.px
height = 100.pct
overflowY = Overflow.auto
flex(1.0, 10.0, FlexBasis("300px")) flex(1.0, 10.0, FlexBasis("300px"))
} }
ringThreeControls(options, solid, selected, onSelect, additionalTabs = props.additionalTabs) ringThreeControls(options, solid, selected, onSelect, additionalTabs = props.additionalTabs)