Optimize UI
This commit is contained in:
parent
7871987df1
commit
da0f4c0ff0
@ -1,27 +1,36 @@
|
||||
plugins {
|
||||
id("space.kscience.gradle.mpp")
|
||||
alias(spclibs.plugins.compose)
|
||||
}
|
||||
|
||||
group = "demo"
|
||||
|
||||
kscience {
|
||||
jvm()
|
||||
// jvm()
|
||||
js {
|
||||
browser {
|
||||
binaries.executable()
|
||||
commonWebpackConfig{
|
||||
cssSupport{
|
||||
enabled = true
|
||||
}
|
||||
scssSupport{
|
||||
enabled = true
|
||||
}
|
||||
sourceMaps = true
|
||||
}
|
||||
}
|
||||
}
|
||||
dependencies {
|
||||
implementation(projects.visionforgeSolid)
|
||||
implementation(projects.visionforgeGdml)
|
||||
}
|
||||
jvmMain {
|
||||
// implementation(project(":visionforge-fx"))
|
||||
implementation(spclibs.logback.classic)
|
||||
}
|
||||
// jvmMain {
|
||||
//// implementation(project(":visionforge-fx"))
|
||||
// implementation(spclibs.logback.classic)
|
||||
// }
|
||||
jsMain {
|
||||
implementation(projects.visionforgeThreejs)
|
||||
implementation(npm("react-file-drop", "3.0.6"))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,12 +3,12 @@
|
||||
package space.kscience.visionforge.gdml.demo
|
||||
|
||||
import androidx.compose.runtime.*
|
||||
import app.softwork.bootstrapcompose.Container
|
||||
import app.softwork.bootstrapcompose.Icon
|
||||
import org.jetbrains.compose.web.ExperimentalComposeWebApi
|
||||
import org.jetbrains.compose.web.attributes.InputType
|
||||
import org.jetbrains.compose.web.attributes.name
|
||||
import org.jetbrains.compose.web.css.*
|
||||
import org.jetbrains.compose.web.dom.Div
|
||||
import org.jetbrains.compose.web.dom.Input
|
||||
import org.jetbrains.compose.web.dom.Text
|
||||
import org.w3c.files.FileList
|
||||
@ -22,7 +22,7 @@ fun FileDrop(
|
||||
) {
|
||||
var dragOver by remember { mutableStateOf(false) }
|
||||
|
||||
Div({
|
||||
Container(attrs = {
|
||||
id("dropzone")
|
||||
style {
|
||||
border(
|
||||
@ -69,7 +69,6 @@ fun FileDrop(
|
||||
}
|
||||
}
|
||||
}) {
|
||||
|
||||
Icon("cloud-upload"){ classes("dropzone-icon") }
|
||||
Text(title)
|
||||
Input(type = InputType.File, attrs = {
|
||||
|
@ -4,7 +4,7 @@ import androidx.compose.runtime.*
|
||||
import kotlinx.browser.window
|
||||
import org.jetbrains.compose.web.css.*
|
||||
import org.jetbrains.compose.web.dom.Div
|
||||
import org.jetbrains.compose.web.dom.H2
|
||||
import org.jetbrains.compose.web.dom.P
|
||||
import org.jetbrains.compose.web.dom.Text
|
||||
import org.w3c.files.File
|
||||
import org.w3c.files.FileReader
|
||||
@ -66,7 +66,7 @@ fun GDMLApp(solids: Solids, initialVision: Solid?, selected: Name? = null) {
|
||||
}) {
|
||||
ThreeView(solids, vision, selected) {
|
||||
Tab("Load") {
|
||||
H2 {
|
||||
P {
|
||||
Text("Drag and drop .gdml or .json VisionForge files here")
|
||||
}
|
||||
FileDrop("(drag file here)") { files ->
|
||||
|
@ -47,8 +47,7 @@ private class JsPlaygroundApp : Application {
|
||||
width(100.vw)
|
||||
}
|
||||
}) {
|
||||
Tabs {
|
||||
active = "gravity"
|
||||
Tabs("gravity") {
|
||||
Tab("gravity") {
|
||||
GravityDemo(solids, client)
|
||||
}
|
||||
|
@ -14,10 +14,12 @@ import space.kscience.dataforge.meta.Null
|
||||
import space.kscience.dataforge.names.Name
|
||||
import space.kscience.visionforge.Colors
|
||||
import space.kscience.visionforge.html.VisionPage
|
||||
import space.kscience.visionforge.html.meta
|
||||
import space.kscience.visionforge.server.close
|
||||
import space.kscience.visionforge.server.openInBrowser
|
||||
import space.kscience.visionforge.server.visionPage
|
||||
import space.kscience.visionforge.solid.*
|
||||
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
|
||||
import space.kscience.visionforge.three.threeJsHeader
|
||||
import kotlin.random.Random
|
||||
|
||||
@ -47,7 +49,12 @@ fun main() {
|
||||
) {
|
||||
div("flex-column") {
|
||||
h1 { +"Satellite detector demo" }
|
||||
vision { sat }
|
||||
vision {
|
||||
meta(Canvas3DOptions {
|
||||
controls.enabled = false
|
||||
})
|
||||
sat
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,7 @@ internal class VariableBox(val xSize: Number, val ySize: Number) : ThreeJsVision
|
||||
mesh.scale.z = properties.getValue(VALUE)?.number?.toDouble() ?: 1.0
|
||||
|
||||
//add listener to object properties
|
||||
onPropertyChange { name ->
|
||||
onPropertyChange(three.context) { name ->
|
||||
when {
|
||||
name == VALUE -> {
|
||||
val value = properties.getValue(VALUE)?.int ?: 0
|
||||
|
@ -0,0 +1,28 @@
|
||||
package space.kscience.visionforge.compose
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import org.jetbrains.compose.web.css.Style
|
||||
import org.jetbrains.compose.web.dom.DOMScope
|
||||
import org.jetbrains.compose.web.renderComposable
|
||||
import org.w3c.dom.Element
|
||||
import space.kscience.dataforge.meta.Meta
|
||||
import space.kscience.dataforge.names.Name
|
||||
import space.kscience.visionforge.ElementVisionRenderer
|
||||
import space.kscience.visionforge.Vision
|
||||
import space.kscience.visionforge.VisionClient
|
||||
|
||||
/**
|
||||
* An [ElementVisionRenderer] that could be used directly in Compose-html as well as a stand-alone renderer
|
||||
*/
|
||||
public interface ComposeVisionRenderer: ElementVisionRenderer {
|
||||
|
||||
@Composable
|
||||
public fun DOMScope<Element>.render(client: VisionClient, name: Name, vision: Vision, meta: Meta)
|
||||
|
||||
override fun render(element: Element, client: VisionClient, name: Name, vision: Vision, meta: Meta) {
|
||||
renderComposable(element) {
|
||||
Style(VisionForgeStyles)
|
||||
render(client, name, vision, meta)
|
||||
}
|
||||
}
|
||||
}
|
@ -28,9 +28,9 @@ import space.kscience.visionforge.hidden
|
||||
* The display state of a property
|
||||
*/
|
||||
public sealed class EditorPropertyState {
|
||||
public object Defined : EditorPropertyState()
|
||||
public class Default(public val source: String = "unknown") : EditorPropertyState()
|
||||
public object Undefined : EditorPropertyState()
|
||||
public data object Defined : EditorPropertyState()
|
||||
public data class Default(public val source: String = "unknown") : EditorPropertyState()
|
||||
public data object Undefined : EditorPropertyState()
|
||||
|
||||
}
|
||||
|
||||
|
@ -79,8 +79,8 @@ public var Vision.visible: Boolean?
|
||||
* Subscribe on property updates. The subscription is bound to the given scope and canceled when the scope is canceled
|
||||
*/
|
||||
public fun Vision.onPropertyChange(
|
||||
scope: CoroutineScope? = manager?.context,
|
||||
scope: CoroutineScope,
|
||||
callback: suspend (Name) -> Unit,
|
||||
): Job = properties.changes.onEach {
|
||||
callback(it)
|
||||
}.launchIn(scope ?: error("Orphan Vision can't observe properties"))
|
||||
}.launchIn(scope)
|
@ -4,10 +4,7 @@ import kotlinx.html.*
|
||||
import space.kscience.dataforge.context.Context
|
||||
import space.kscience.dataforge.context.ContextAware
|
||||
import space.kscience.dataforge.context.PluginFactory
|
||||
import space.kscience.dataforge.meta.Meta
|
||||
import space.kscience.dataforge.meta.MetaSerializer
|
||||
import space.kscience.dataforge.meta.MutableMeta
|
||||
import space.kscience.dataforge.meta.isEmpty
|
||||
import space.kscience.dataforge.meta.*
|
||||
import space.kscience.dataforge.names.Name
|
||||
import space.kscience.dataforge.names.NameToken
|
||||
import space.kscience.dataforge.names.asName
|
||||
@ -46,9 +43,14 @@ public class VisionOutput @PublishedApi internal constructor(override val contex
|
||||
newContext.visionManager
|
||||
}
|
||||
|
||||
public inline fun meta(block: MutableMeta.() -> Unit) {
|
||||
this.meta = Meta(block)
|
||||
}
|
||||
}
|
||||
|
||||
public inline fun VisionOutput.meta(block: MutableMeta.() -> Unit) {
|
||||
this.meta = Meta(block)
|
||||
}
|
||||
|
||||
public fun VisionOutput.meta(metaRepr: MetaRepr) {
|
||||
this.meta = metaRepr.toMeta()
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -19,7 +19,7 @@ public fun Vision.useProperty(
|
||||
propertyName: Name,
|
||||
inherit: Boolean? = null,
|
||||
includeStyles: Boolean? = null,
|
||||
scope: CoroutineScope? = manager?.context,
|
||||
scope: CoroutineScope = manager?.context ?: error("Orphan Vision can't observe properties"),
|
||||
callback: (Meta) -> Unit,
|
||||
): Job {
|
||||
//Pass initial value.
|
||||
@ -28,14 +28,14 @@ public fun Vision.useProperty(
|
||||
if (name.startsWith(propertyName)) {
|
||||
callback(properties.get(propertyName, inherit, includeStyles))
|
||||
}
|
||||
}.launchIn(scope ?: error("Orphan Vision can't observe properties"))
|
||||
}.launchIn(scope)
|
||||
}
|
||||
|
||||
public fun Vision.useProperty(
|
||||
propertyName: String,
|
||||
inherit: Boolean? = null,
|
||||
includeStyles: Boolean? = null,
|
||||
scope: CoroutineScope? = manager?.context,
|
||||
scope: CoroutineScope = manager?.context ?: error("Orphan Vision can't observe properties"),
|
||||
callback: (Meta) -> Unit,
|
||||
): Job = useProperty(propertyName.parseAsName(), inherit, includeStyles, scope, callback)
|
||||
|
||||
|
@ -52,7 +52,7 @@ public class ThreeCompositeFactory(public val three: ThreePlugin) : ThreeFactory
|
||||
applyProperties(vision)
|
||||
|
||||
if (observe) {
|
||||
vision.onPropertyChange { name ->
|
||||
vision.onPropertyChange(three.context) { name ->
|
||||
when {
|
||||
//name.startsWith(WIREFRAME_KEY) -> mesh.applyWireFrame(obj)
|
||||
name.startsWith(EDGES_KEY) -> applyEdges(vision)
|
||||
|
@ -1,14 +1,16 @@
|
||||
package space.kscience.visionforge.solid.three
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import org.jetbrains.compose.web.renderComposable
|
||||
import org.jetbrains.compose.web.dom.DOMScope
|
||||
import org.w3c.dom.Element
|
||||
import org.w3c.dom.HTMLElement
|
||||
import space.kscience.dataforge.context.*
|
||||
import space.kscience.dataforge.meta.Meta
|
||||
import space.kscience.dataforge.names.*
|
||||
import space.kscience.visionforge.*
|
||||
import space.kscience.visionforge.compose.ComposeVisionRenderer
|
||||
import space.kscience.visionforge.solid.*
|
||||
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
|
||||
import space.kscience.visionforge.solid.three.compose.ThreeView
|
||||
@ -21,7 +23,7 @@ import three.objects.Group as ThreeGroup
|
||||
/**
|
||||
* A plugin that handles Three Object3D representation of Visions.
|
||||
*/
|
||||
public class ThreePlugin : AbstractPlugin(), ElementVisionRenderer {
|
||||
public class ThreePlugin : AbstractPlugin(), ComposeVisionRenderer {
|
||||
override val tag: PluginTag get() = Companion.tag
|
||||
|
||||
public val solids: Solids by require(Solids)
|
||||
@ -75,7 +77,7 @@ public class ThreePlugin : AbstractPlugin(), ElementVisionRenderer {
|
||||
// disable tracking changes for statics
|
||||
group[token] = object3D
|
||||
} catch (ex: Throwable) {
|
||||
logger.error(ex) { "Failed to render $child" }
|
||||
logger.error(ex) { "Failed to render vision with token $token and type ${child::class}" }
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -115,7 +117,7 @@ public class ThreePlugin : AbstractPlugin(), ElementVisionRenderer {
|
||||
val object3D = buildObject3D(child)
|
||||
set(childName, object3D)
|
||||
} catch (ex: Throwable) {
|
||||
logger.error(ex) { "Failed to render $child" }
|
||||
logger.error(ex) { "Failed to render vision with name $childName" }
|
||||
}
|
||||
}
|
||||
}.launchIn(context)
|
||||
@ -185,11 +187,10 @@ public class ThreePlugin : AbstractPlugin(), ElementVisionRenderer {
|
||||
render(vision)
|
||||
}
|
||||
|
||||
override fun render(element: Element, client: VisionClient, name: Name, vision: Vision, meta: Meta) {
|
||||
@Composable
|
||||
override fun DOMScope<Element>.render(client: VisionClient, name: Name, vision: Vision, meta: Meta) {
|
||||
require(vision is Solid) { "Expected Solid but found ${vision::class}" }
|
||||
renderComposable(element) {
|
||||
ThreeView(solids, vision, null, Canvas3DOptions.read(meta))
|
||||
}
|
||||
ThreeView(solids, vision, null, Canvas3DOptions.read(meta))
|
||||
}
|
||||
|
||||
public companion object : PluginFactory<ThreePlugin> {
|
||||
|
@ -6,21 +6,33 @@ plugins {
|
||||
val ktorVersion: String by rootProject.extra
|
||||
|
||||
kscience {
|
||||
fullStack("js/visionforge-three.js")
|
||||
fullStack(
|
||||
bundleName = "js/visionforge-three.js",
|
||||
browserConfig = {
|
||||
webpackTask {
|
||||
cssSupport {
|
||||
enabled = true
|
||||
}
|
||||
scssSupport {
|
||||
enabled = true
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
commonMain {
|
||||
api(projects.visionforgeSolid)
|
||||
api(projects.visionforgeComposeHtml)
|
||||
}
|
||||
|
||||
jvmMain{
|
||||
jvmMain {
|
||||
api(projects.visionforgeServer)
|
||||
}
|
||||
|
||||
jsMain{
|
||||
jsMain {
|
||||
api(projects.visionforgeThreejs)
|
||||
implementation(npm("file-saver","2.0.5"))
|
||||
implementation(npm("file-saver", "2.0.5"))
|
||||
implementation(npm("@types/file-saver", "2.0.7"))
|
||||
compileOnly(npm("webpack-bundle-analyzer","4.5.0"))
|
||||
compileOnly(npm("webpack-bundle-analyzer", "4.5.0"))
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user