Fix server change generator
This commit is contained in:
@@ -3,8 +3,8 @@
|
||||
package space.kscience.visionforge.gdml.demo
|
||||
|
||||
import androidx.compose.runtime.*
|
||||
import bootstrap.Container
|
||||
import bootstrap.Icon
|
||||
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
|
||||
|
||||
@@ -3,12 +3,10 @@ package space.kscience.visionforge.gdml.demo
|
||||
import org.jetbrains.compose.web.css.*
|
||||
import org.jetbrains.compose.web.dom.Style
|
||||
import org.jetbrains.compose.web.renderComposable
|
||||
import org.w3c.dom.Document
|
||||
import space.kscience.dataforge.context.Context
|
||||
import space.kscience.gdml.GdmlShowCase
|
||||
import space.kscience.visionforge.Colors
|
||||
import space.kscience.visionforge.gdml.toVision
|
||||
import space.kscience.visionforge.html.Application
|
||||
import space.kscience.visionforge.html.VisionForgeStyles
|
||||
import space.kscience.visionforge.html.startApplication
|
||||
import space.kscience.visionforge.solid.ambientLight
|
||||
@@ -16,46 +14,39 @@ import space.kscience.visionforge.solid.invoke
|
||||
import space.kscience.visionforge.solid.three.ThreePlugin
|
||||
|
||||
|
||||
private class GDMLDemoApp : Application {
|
||||
fun main() = startApplication { document ->
|
||||
|
||||
val context = Context("gdml-demo") {
|
||||
plugin(ThreePlugin)
|
||||
}
|
||||
|
||||
override fun start(document: Document, state: Map<String, Any>) {
|
||||
val element = document.getElementById("application") ?: error("Element with id 'application' not found on page")
|
||||
|
||||
val element = document.getElementById("application") ?: error("Element with id 'application' not found on page")
|
||||
|
||||
val vision = GdmlShowCase.cubes().toVision().apply {
|
||||
ambientLight {
|
||||
color(Colors.white)
|
||||
}
|
||||
}
|
||||
|
||||
renderComposable(element) {
|
||||
Style(VisionForgeStyles)
|
||||
Style {
|
||||
"html" {
|
||||
height(100.percent)
|
||||
}
|
||||
|
||||
"body" {
|
||||
height(100.percent)
|
||||
display(DisplayStyle.Flex)
|
||||
alignItems(AlignItems.Stretch)
|
||||
}
|
||||
|
||||
"#application" {
|
||||
width(100.percent)
|
||||
display(DisplayStyle.Flex)
|
||||
alignItems(AlignItems.Stretch)
|
||||
}
|
||||
}
|
||||
GDMLApp(context, vision)
|
||||
val vision = GdmlShowCase.cubes().toVision().apply {
|
||||
ambientLight {
|
||||
color(Colors.white)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun main() {
|
||||
startApplication(::GDMLDemoApp)
|
||||
}
|
||||
renderComposable(element) {
|
||||
Style(VisionForgeStyles)
|
||||
Style {
|
||||
"html" {
|
||||
height(100.percent)
|
||||
}
|
||||
|
||||
"body" {
|
||||
height(100.percent)
|
||||
display(DisplayStyle.Flex)
|
||||
alignItems(AlignItems.Stretch)
|
||||
}
|
||||
|
||||
"#application" {
|
||||
width(100.percent)
|
||||
display(DisplayStyle.Flex)
|
||||
alignItems(AlignItems.Stretch)
|
||||
}
|
||||
}
|
||||
GDMLApp(context, vision)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,7 +47,6 @@ kscience {
|
||||
}
|
||||
jsMain {
|
||||
implementation(projects.visionforgeThreejs)
|
||||
//implementation(devNpm("webpack-bundle-analyzer", "4.4.0"))
|
||||
}
|
||||
}
|
||||
kotlin {
|
||||
|
||||
@@ -54,7 +54,7 @@ kotlin {
|
||||
val jsMain by getting {
|
||||
dependencies {
|
||||
implementation(projects.visionforgeThreejs)
|
||||
compileOnly(npm("webpack-bundle-analyzer","4.5.0"))
|
||||
// compileOnly(npm("webpack-bundle-analyzer","4.5.0"))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ import java.awt.Desktop
|
||||
import java.nio.file.Path
|
||||
|
||||
|
||||
public suspend fun makeVisionFile(
|
||||
public fun makeVisionFile(
|
||||
path: Path? = null,
|
||||
title: String = "VisionForge page",
|
||||
resourceLocation: ResourceLocation = ResourceLocation.SYSTEM,
|
||||
|
||||
@@ -3,17 +3,22 @@ import org.jetbrains.kotlin.gradle.dsl.ExplicitApiMode
|
||||
|
||||
plugins {
|
||||
id("space.kscience.gradle.mpp")
|
||||
alias(spclibs.plugins.ktor)
|
||||
application
|
||||
// alias(spclibs.plugins.ktor)
|
||||
}
|
||||
|
||||
|
||||
group = "center.sciprog"
|
||||
|
||||
kscience {
|
||||
// useSerialization {
|
||||
// json()
|
||||
// }
|
||||
jvm{
|
||||
withJava()
|
||||
binaries {
|
||||
executable {
|
||||
mainClass.set("ru.mipt.npm.sat.SatServerKt")
|
||||
}
|
||||
}
|
||||
}
|
||||
jvmMain{
|
||||
implementation("io.ktor:ktor-server-cio")
|
||||
@@ -22,10 +27,4 @@ kscience {
|
||||
}
|
||||
}
|
||||
|
||||
group = "center.sciprog"
|
||||
|
||||
kotlin.explicitApi = ExplicitApiMode.Disabled
|
||||
|
||||
application {
|
||||
mainClass.set("ru.mipt.npm.sat.SatServerKt")
|
||||
}
|
||||
kotlin.explicitApi = ExplicitApiMode.Disabled
|
||||
@@ -1,19 +1,17 @@
|
||||
package space.kscience.visionforge.solid.demo
|
||||
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.isActive
|
||||
import kotlinx.coroutines.launch
|
||||
import org.w3c.dom.Document
|
||||
import space.kscience.visionforge.html.Application
|
||||
import space.kscience.visionforge.html.startApplication
|
||||
import space.kscience.visionforge.solid.x
|
||||
import space.kscience.visionforge.solid.y
|
||||
import kotlin.random.Random
|
||||
|
||||
private class ThreeDemoApp : Application {
|
||||
|
||||
override fun start(document: Document, state: Map<String, Any>) {
|
||||
|
||||
fun main() {
|
||||
startApplication { document ->
|
||||
val element = document.getElementById("demo") ?: error("Element with id 'demo' not found on page")
|
||||
|
||||
ThreeDemoGrid(element).run {
|
||||
@@ -30,7 +28,7 @@ private class ThreeDemoApp : Application {
|
||||
}
|
||||
}
|
||||
|
||||
launch {
|
||||
GlobalScope.launch {
|
||||
while (isActive) {
|
||||
delay(500)
|
||||
boxes.forEach { box ->
|
||||
@@ -41,8 +39,4 @@ private class ThreeDemoApp : Application {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun main() {
|
||||
startApplication(::ThreeDemoApp)
|
||||
}
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
package space.kscience.plotly.models
|
||||
|
||||
import com.benasher44.uuid.uuid4
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.Transient
|
||||
import space.kscience.dataforge.meta.*
|
||||
@@ -13,6 +12,7 @@ import space.kscience.dataforge.names.NameToken
|
||||
import space.kscience.dataforge.names.asName
|
||||
import space.kscience.plotly.*
|
||||
import space.kscience.visionforge.AbstractVision
|
||||
import space.kscience.visionforge.Vision
|
||||
import kotlin.js.JsName
|
||||
import kotlin.properties.ReadOnlyProperty
|
||||
|
||||
@@ -718,11 +718,11 @@ public class Hoverlabel : Scheme() {
|
||||
/**
|
||||
* A base class for Plotly traces
|
||||
*
|
||||
* @param uid an unique identifier for this trace
|
||||
* @param uid a unique identifier for this trace
|
||||
*/
|
||||
@Serializable
|
||||
public open class Trace(
|
||||
@Transient internal val uid: NameToken = NameToken("trace", uuid4().leastSignificantBits.toString(16))
|
||||
@Transient internal val uid: NameToken = NameToken("trace", Vision.randomId())
|
||||
) : AbstractVision(), MutableMetaProvider, MetaRepr {
|
||||
|
||||
override fun get(name: Name): MutableMeta? = properties.get(name)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package space.kscience.visionforge.plotly
|
||||
|
||||
import io.ktor.server.cio.CIO
|
||||
import io.ktor.server.engine.ApplicationEngine
|
||||
import io.ktor.server.engine.EmbeddedServer
|
||||
import io.ktor.server.engine.embeddedServer
|
||||
import io.ktor.server.http.content.staticResources
|
||||
import io.ktor.server.routing.routing
|
||||
@@ -27,7 +27,7 @@ public fun Plotly.servePage(
|
||||
title: String = "VisionForge Plotly page",
|
||||
port: Int = 7777,
|
||||
visionPage: HtmlVisionFragment
|
||||
): ApplicationEngine = embeddedServer(CIO, port = port) {
|
||||
): EmbeddedServer<*, *> = embeddedServer(CIO, port = port) {
|
||||
routing {
|
||||
staticResources("js", "js", null)
|
||||
}
|
||||
@@ -51,7 +51,7 @@ public fun Plotly.serve(
|
||||
port: Int = 7777,
|
||||
config: PlotlyConfig = PlotlyConfig(),
|
||||
makePlot: suspend Plot.() -> Unit,
|
||||
): ApplicationEngine = embeddedServer(CIO, port = port) {
|
||||
): EmbeddedServer<*, *> = embeddedServer(CIO, port = port) {
|
||||
routing {
|
||||
staticResources("js", "js", null)
|
||||
}
|
||||
@@ -62,7 +62,7 @@ include(
|
||||
":visionforge-jupyter:visionforge-jupyter-common",
|
||||
":plotly",
|
||||
":plotly:plotlykt-core",
|
||||
":plotly:plotly-kt-server",
|
||||
":plotly:plotlykt-server",
|
||||
":plotly:plotlykt-script",
|
||||
":plotly:examples",
|
||||
// ":plotly:examples:fx-demo",
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
package space.kscience.dataforge.meta
|
||||
|
||||
import space.kscience.dataforge.names.Name
|
||||
import space.kscience.dataforge.names.NameToken
|
||||
import space.kscience.dataforge.names.plus
|
||||
|
||||
/**
|
||||
* A [Meta] child proxy that creates required nodes on write
|
||||
*/
|
||||
public class MutableMetaProxy(
|
||||
public val upstream: MutableMeta,
|
||||
public val proxyName: Name
|
||||
) : MutableMeta {
|
||||
|
||||
override val items: Map<NameToken, MutableMeta>
|
||||
get() = upstream[proxyName]?.items ?: emptyMap()
|
||||
|
||||
override var value: Value?
|
||||
get() = upstream[proxyName]?.value
|
||||
set(value) {
|
||||
upstream[proxyName] = value
|
||||
}
|
||||
|
||||
override fun getOrCreate(name: Name): MutableMeta = upstream.getOrCreate(proxyName + name)
|
||||
|
||||
|
||||
override fun set(name: Name, node: Meta?) {
|
||||
set(proxyName + name, node)
|
||||
}
|
||||
|
||||
|
||||
override fun equals(other: Any?): Boolean = Meta.equals(this, other as? Meta)
|
||||
|
||||
|
||||
override fun hashCode(): Int = Meta.hashCode(this)
|
||||
|
||||
override fun toString(): String = Meta.toString(this)
|
||||
}
|
||||
@@ -62,21 +62,6 @@ public data class VisionChange(
|
||||
|
||||
public fun VisionChange.isEmpty(): Boolean = vision == null && properties == null && children == null
|
||||
|
||||
//@Serializable
|
||||
//public sealed interface ChangeVisionEvent : VisionEvent
|
||||
//
|
||||
//@Serializable
|
||||
//@SerialName("sepProperties")
|
||||
//public data class SetVisionPropertiesEvent(val properties: Meta) : ChangeVisionEvent
|
||||
//
|
||||
//@Serializable
|
||||
//@SerialName("setChild")
|
||||
//public data class SetVisionChildEvent(val nameToken: NameToken, val vision: Vision?) : ChangeVisionEvent
|
||||
//
|
||||
//@Serializable
|
||||
//@SerialName("setRoot")
|
||||
//public data class SetRootVisionEvent(val vision: Vision) : ChangeVisionEvent
|
||||
|
||||
|
||||
/**
|
||||
* An update for a [Vision]
|
||||
@@ -159,31 +144,9 @@ public class VisionChangeCollector : MutableVisionContainer<Vision> {
|
||||
|
||||
public fun collect(visionManager: VisionManager): VisionChange = VisionChange(
|
||||
vision = vision?.deepCopy(visionManager),
|
||||
properties = properties,
|
||||
children = children.mapValues { it.value.collect(visionManager) }
|
||||
properties = properties.takeIf { !it.isEmpty() },
|
||||
children = children.takeIf { !it.isEmpty() }?.mapValues { it.value.collect(visionManager) }
|
||||
)
|
||||
|
||||
// private fun build(visionManager: VisionManager): VisionChange = VisionChange(
|
||||
// vision,
|
||||
// if (propertyChange.isEmpty()) null else propertyChange,
|
||||
// if (children.isEmpty()) null else children.mapValues { it.value.build(visionManager) }
|
||||
// )
|
||||
//
|
||||
// /**
|
||||
// * Isolate collected changes by creating detached copies of given visions
|
||||
// */
|
||||
// public fun deepCopy(visionManager: VisionManager): VisionChange = VisionChange(
|
||||
// vision?.deepCopy(visionManager),
|
||||
// if (propertyChange.isEmpty()) null else propertyChange.seal(),
|
||||
// if (children.isEmpty()) null else children.mapValues { it.value.deepCopy(visionManager) }
|
||||
// )
|
||||
//
|
||||
// /**
|
||||
// * Transform current change directly to Json string without protective copy
|
||||
// */
|
||||
// public fun toJsonString(visionManager: VisionManager): String = visionManager.encodeToString(
|
||||
// build(visionManager)
|
||||
// )
|
||||
}
|
||||
|
||||
public operator fun VisionChangeCollector.get(name: Name): VisionChangeCollector? = when (name.length) {
|
||||
@@ -214,9 +177,20 @@ public fun Vision.flowChanges(
|
||||
coroutineScope {
|
||||
val collector = VisionChangeCollector()
|
||||
val mutex = Mutex()
|
||||
eventFlow.onEach {
|
||||
collector.consumeEvent(it)
|
||||
}.launchIn(this)
|
||||
|
||||
fun collectVisionEvents(vision: Vision, prefix: Name) {
|
||||
vision.eventFlow.onEach {
|
||||
val event = if (prefix.isEmpty()) it else VisionEventForChild(prefix, it)
|
||||
collector.consumeEvent(event)
|
||||
}.launchIn(this)
|
||||
if (vision is VisionGroup<*>) {
|
||||
vision.visions.forEach { (token, child) ->
|
||||
collectVisionEvents(child, prefix + token)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
collectVisionEvents(this@flowChanges, Name.EMPTY)
|
||||
|
||||
if (sendInitial) {
|
||||
//Send initial vision state
|
||||
|
||||
@@ -112,6 +112,7 @@ public class VisionManager(meta: Meta) : AbstractPlugin(meta), Vision {
|
||||
useArrayPolymorphism = false
|
||||
ignoreUnknownKeys = true
|
||||
explicitNulls = false
|
||||
encodeDefaults = false
|
||||
}
|
||||
|
||||
private val visionSerializer: PolymorphicSerializer<Vision> = PolymorphicSerializer(Vision::class)
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
# Module visionforge-plotly
|
||||
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
## Artifact:
|
||||
|
||||
The Maven coordinates of this project are `space.kscience:visionforge-plotly:0.4.2`.
|
||||
|
||||
**Gradle Kotlin DSL:**
|
||||
```kotlin
|
||||
repositories {
|
||||
maven("https://repo.kotlin.link")
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("space.kscience:visionforge-plotly:0.4.2")
|
||||
}
|
||||
```
|
||||
@@ -1,44 +0,0 @@
|
||||
public final class space/kscience/visionforge/plotly/PlotlyPlugin : space/kscience/visionforge/VisionPlugin {
|
||||
public static final field Companion Lspace/kscience/visionforge/plotly/PlotlyPlugin$Companion;
|
||||
public fun <init> ()V
|
||||
public fun getTag ()Lspace/kscience/dataforge/context/PluginTag;
|
||||
}
|
||||
|
||||
public final class space/kscience/visionforge/plotly/PlotlyPlugin$Companion : space/kscience/dataforge/context/PluginFactory {
|
||||
public synthetic fun build (Lspace/kscience/dataforge/context/Context;Lspace/kscience/dataforge/meta/Meta;)Ljava/lang/Object;
|
||||
public fun build (Lspace/kscience/dataforge/context/Context;Lspace/kscience/dataforge/meta/Meta;)Lspace/kscience/visionforge/plotly/PlotlyPlugin;
|
||||
public fun getTag ()Lspace/kscience/dataforge/context/PluginTag;
|
||||
}
|
||||
|
||||
public final class space/kscience/visionforge/plotly/VisionOfPlotly : space/kscience/visionforge/Vision {
|
||||
public static final field Companion Lspace/kscience/visionforge/plotly/VisionOfPlotly$Companion;
|
||||
public fun <init> (Lspace/kscience/plotly/Plot;)V
|
||||
public fun getDescriptor ()Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;
|
||||
public final fun getMeta ()Lspace/kscience/dataforge/meta/MutableMeta;
|
||||
public fun getParent ()Lspace/kscience/visionforge/Vision;
|
||||
public final fun getPlot ()Lspace/kscience/plotly/Plot;
|
||||
public fun getProperties ()Lspace/kscience/visionforge/MutableVisionProperties;
|
||||
public fun setParent (Lspace/kscience/visionforge/Vision;)V
|
||||
}
|
||||
|
||||
public synthetic class space/kscience/visionforge/plotly/VisionOfPlotly$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
|
||||
public static final field INSTANCE Lspace/kscience/visionforge/plotly/VisionOfPlotly$$serializer;
|
||||
public final fun childSerializers ()[Lkotlinx/serialization/KSerializer;
|
||||
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
|
||||
public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lspace/kscience/visionforge/plotly/VisionOfPlotly;
|
||||
public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
|
||||
public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
|
||||
public final fun serialize (Lkotlinx/serialization/encoding/Encoder;Lspace/kscience/visionforge/plotly/VisionOfPlotly;)V
|
||||
public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer;
|
||||
}
|
||||
|
||||
public final class space/kscience/visionforge/plotly/VisionOfPlotly$Companion {
|
||||
public final fun serializer ()Lkotlinx/serialization/KSerializer;
|
||||
}
|
||||
|
||||
public final class space/kscience/visionforge/plotly/VisionOfPlotlyKt {
|
||||
public static final fun asVision (Lspace/kscience/plotly/Plot;)Lspace/kscience/visionforge/plotly/VisionOfPlotly;
|
||||
public static final fun plotly (Lspace/kscience/visionforge/html/VisionOutput;Lspace/kscience/plotly/PlotlyConfig;Lkotlin/jvm/functions/Function1;)Lspace/kscience/visionforge/plotly/VisionOfPlotly;
|
||||
public static synthetic fun plotly$default (Lspace/kscience/visionforge/html/VisionOutput;Lspace/kscience/plotly/PlotlyConfig;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/visionforge/plotly/VisionOfPlotly;
|
||||
}
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
plugins {
|
||||
id("space.kscience.gradle.mpp")
|
||||
}
|
||||
|
||||
kscience {
|
||||
jvm()
|
||||
js {
|
||||
binaries.library()
|
||||
}
|
||||
dependencies {
|
||||
api(projects.visionforgeCore)
|
||||
api(projects.plotly.plotlyktCore)
|
||||
}
|
||||
useSerialization()
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
package space.kscience.visionforge.plotly
|
||||
|
||||
import kotlinx.serialization.modules.SerializersModule
|
||||
import kotlinx.serialization.modules.polymorphic
|
||||
import kotlinx.serialization.modules.subclass
|
||||
import space.kscience.dataforge.context.Context
|
||||
import space.kscience.dataforge.context.PluginFactory
|
||||
import space.kscience.dataforge.context.PluginTag
|
||||
import space.kscience.dataforge.meta.Meta
|
||||
import space.kscience.visionforge.Vision
|
||||
import space.kscience.visionforge.VisionPlugin
|
||||
|
||||
public expect class PlotlyPlugin : VisionPlugin {
|
||||
|
||||
override val tag: PluginTag
|
||||
override val visionSerializersModule: SerializersModule
|
||||
|
||||
public companion object : PluginFactory<PlotlyPlugin>{
|
||||
override fun build(context: Context, meta: Meta): PlotlyPlugin
|
||||
|
||||
override val tag: PluginTag
|
||||
}
|
||||
}
|
||||
|
||||
internal val plotlySerializersModule = SerializersModule {
|
||||
polymorphic(Vision::class) {
|
||||
subclass(VisionOfPlotly.serializer())
|
||||
}
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
package space.kscience.visionforge.plotly
|
||||
|
||||
import kotlinx.coroutines.channels.awaitClose
|
||||
import kotlinx.coroutines.flow.callbackFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.Transient
|
||||
import space.kscience.dataforge.meta.*
|
||||
import space.kscience.dataforge.meta.descriptors.MetaDescriptor
|
||||
import space.kscience.dataforge.names.Name
|
||||
import space.kscience.plotly.Plot
|
||||
import space.kscience.plotly.Plotly
|
||||
import space.kscience.plotly.PlotlyConfig
|
||||
import space.kscience.visionforge.MutableVisionProperties
|
||||
import space.kscience.visionforge.Vision
|
||||
import space.kscience.visionforge.VisionBuilder
|
||||
import space.kscience.visionforge.html.VisionOutput
|
||||
|
||||
@Serializable
|
||||
@SerialName("vision.plotly")
|
||||
public class VisionOfPlotly private constructor(
|
||||
@Serializable(MutableMetaSerializer::class) public val meta: MutableMeta,
|
||||
) : Vision {
|
||||
public constructor(plot: Plot) : this(plot.meta)
|
||||
|
||||
@Transient
|
||||
public val plot: Plot = Plot(meta.asObservable())
|
||||
|
||||
@Transient
|
||||
override var parent: Vision? = null
|
||||
|
||||
@Transient
|
||||
override val properties: MutableVisionProperties = object : MutableVisionProperties {
|
||||
override val own: Meta get() = plot.meta
|
||||
|
||||
override val changes = callbackFlow {
|
||||
plot.meta.onChange(this) {
|
||||
launch {
|
||||
send(it)
|
||||
}
|
||||
}
|
||||
awaitClose {
|
||||
plot.meta.removeListener(this)
|
||||
}
|
||||
}
|
||||
|
||||
override fun invalidate(propertyName: Name) {
|
||||
//do nothing, updates to source already counted
|
||||
// manager?.context?.launch {
|
||||
// changes.emit(propertyName)
|
||||
// }
|
||||
}
|
||||
|
||||
override fun getValue(name: Name, inherit: Boolean?, includeStyles: Boolean?): Value? = plot.meta[name]?.value
|
||||
|
||||
override fun set(name: Name, item: Meta?, notify: Boolean) {
|
||||
plot.meta[name] = item
|
||||
if (notify) invalidate(name)
|
||||
}
|
||||
|
||||
override fun setValue(name: Name, value: Value?, notify: Boolean) {
|
||||
plot.meta[name] = value
|
||||
if (notify) invalidate(name)
|
||||
}
|
||||
|
||||
override val descriptor: MetaDescriptor get() = plot.descriptor
|
||||
}
|
||||
|
||||
|
||||
override val descriptor: MetaDescriptor = Plot.descriptor
|
||||
}
|
||||
|
||||
public fun Plot.asVision(): VisionOfPlotly = VisionOfPlotly(this)
|
||||
|
||||
/**
|
||||
* Embed a dynamic plotly plot in a vision
|
||||
*/
|
||||
@VisionBuilder
|
||||
public inline fun VisionOutput.plotly(
|
||||
config: PlotlyConfig = PlotlyConfig(),
|
||||
block: Plot.() -> Unit,
|
||||
): VisionOfPlotly {
|
||||
requirePlugin(PlotlyPlugin)
|
||||
meta = config.meta
|
||||
return VisionOfPlotly(Plotly.plot(block))
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
package space.kscience.visionforge.plotly
|
||||
|
||||
import space.kscience.dataforge.context.Context
|
||||
import space.kscience.dataforge.meta.Value
|
||||
import space.kscience.plotly.Plotly
|
||||
import space.kscience.plotly.layout
|
||||
import space.kscience.plotly.models.*
|
||||
import space.kscience.visionforge.visionManager
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class VisionOfPlotlyTest {
|
||||
@Test
|
||||
fun conversion() {
|
||||
val trace1 = Violin {
|
||||
text("sample length: 32")
|
||||
marker {
|
||||
line {
|
||||
width = 2
|
||||
color("#bebada")
|
||||
}
|
||||
symbol = Symbol.valueOf("line-ns")
|
||||
}
|
||||
orientation = Orientation.h
|
||||
hoveron = ViolinHoveron.`points+kde`
|
||||
meanline {
|
||||
visible = true
|
||||
}
|
||||
legendgroup = "F"
|
||||
scalegroup = "F"
|
||||
points = ViolinPoints.all
|
||||
pointpos = 1.2
|
||||
jitter = 0
|
||||
box {
|
||||
visible = true
|
||||
}
|
||||
scalemode = ViolinScaleMode.count
|
||||
showlegend = false
|
||||
side = ViolinSide.positive
|
||||
y0 = Value.of(0)
|
||||
line {
|
||||
color("#bebada")
|
||||
}
|
||||
name = "F"
|
||||
|
||||
x(10.07, 34.83, 10.65, 12.43, 24.08, 13.42, 12.48, 29.8, 14.52, 11.38,
|
||||
20.27, 11.17, 12.26, 18.26, 8.51, 10.33, 14.15, 13.16, 17.47, 27.05, 16.43,
|
||||
8.35, 18.64, 11.87, 19.81, 43.11, 13.0, 12.74, 13.0, 16.4, 16.47, 18.78)
|
||||
}
|
||||
|
||||
val trace2 = Violin {
|
||||
text("sample length: 30")
|
||||
marker {
|
||||
line {
|
||||
width = 2
|
||||
color("#8dd3c7")
|
||||
}
|
||||
symbol = Symbol.valueOf("line-ns")
|
||||
}
|
||||
orientation = Orientation.h
|
||||
hoveron = ViolinHoveron.`points+kde`
|
||||
meanline {
|
||||
visible = true
|
||||
}
|
||||
legendgroup = "M"
|
||||
scalegroup = "M"
|
||||
points = ViolinPoints.all
|
||||
pointpos = -1.2
|
||||
jitter = 0
|
||||
box {
|
||||
visible = true
|
||||
}
|
||||
scalemode = ViolinScaleMode.count
|
||||
showlegend = false
|
||||
side = ViolinSide.negative
|
||||
y0 = Value.of(0)
|
||||
|
||||
line {
|
||||
color("#8dd3c7")
|
||||
}
|
||||
name = "M"
|
||||
|
||||
x(27.2, 22.76, 17.29, 19.44, 16.66, 32.68, 15.98, 13.03, 18.28, 24.71,
|
||||
21.16, 11.69, 14.26, 15.95, 8.52, 22.82, 19.08, 16.0, 34.3, 41.19, 9.78,
|
||||
7.51, 28.44, 15.48, 16.58, 7.56, 10.34, 13.51, 18.71, 20.53)
|
||||
}
|
||||
|
||||
val plot = Plotly.plot {
|
||||
traces(trace1, trace2)
|
||||
layout {
|
||||
width = 800
|
||||
height = 800
|
||||
title = "Advanced Violin Plot"
|
||||
}
|
||||
}
|
||||
val vision = VisionOfPlotly(plot)
|
||||
val context = Context {
|
||||
plugin(PlotlyPlugin)
|
||||
}
|
||||
val serialized = context.visionManager.encodeToString(vision)
|
||||
|
||||
val deserialized: VisionOfPlotly = context.visionManager.decodeFromString(serialized) as VisionOfPlotly
|
||||
|
||||
println(deserialized.plot.meta)
|
||||
|
||||
assertEquals(62, deserialized.plot.data.sumOf { it.x.doubles.size})
|
||||
|
||||
assertEquals("Advanced Violin Plot", deserialized.plot.layout.title)
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
package space.kscience.visionforge.plotly
|
||||
|
||||
import kotlinx.serialization.modules.SerializersModule
|
||||
import org.w3c.dom.Element
|
||||
import space.kscience.dataforge.context.Context
|
||||
import space.kscience.dataforge.context.PluginFactory
|
||||
import space.kscience.dataforge.context.PluginTag
|
||||
import space.kscience.dataforge.meta.Meta
|
||||
import space.kscience.dataforge.names.Name
|
||||
import space.kscience.dataforge.names.asName
|
||||
import space.kscience.plotly.PlotlyConfig
|
||||
import space.kscience.plotly.plot
|
||||
import space.kscience.visionforge.Vision
|
||||
import space.kscience.visionforge.VisionPlugin
|
||||
import space.kscience.visionforge.html.ElementVisionRenderer
|
||||
import space.kscience.visionforge.html.JsVisionClient
|
||||
|
||||
public actual class PlotlyPlugin : VisionPlugin(), ElementVisionRenderer {
|
||||
public val visionClient: JsVisionClient by require(JsVisionClient)
|
||||
|
||||
actual override val tag: PluginTag get() = Companion.tag
|
||||
|
||||
actual override val visionSerializersModule: SerializersModule get() = plotlySerializersModule
|
||||
|
||||
override fun rateVision(vision: Vision): Int = when (vision) {
|
||||
is VisionOfPlotly -> ElementVisionRenderer.DEFAULT_RATING
|
||||
else -> ElementVisionRenderer.ZERO_RATING
|
||||
}
|
||||
|
||||
override fun render(element: Element, name: Name, vision: Vision, meta: Meta) {
|
||||
val plot = (vision as? VisionOfPlotly)?.plot ?: error("VisionOfPlotly expected but ${vision::class} found")
|
||||
val config = PlotlyConfig.read(meta)
|
||||
element.plot(config, plot)
|
||||
}
|
||||
|
||||
override fun toString(): String = "Plotly"
|
||||
|
||||
override fun content(target: String): Map<Name, Any> = when (target) {
|
||||
ElementVisionRenderer.TYPE -> mapOf("plotly".asName() to this)
|
||||
else -> super.content(target)
|
||||
}
|
||||
|
||||
public actual companion object : PluginFactory<PlotlyPlugin> {
|
||||
actual override val tag: PluginTag = PluginTag("vision.plotly.js", PluginTag.DATAFORGE_GROUP)
|
||||
|
||||
actual override fun build(context: Context, meta: Meta): PlotlyPlugin = PlotlyPlugin()
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
package space.kscience.visionforge.plotly
|
||||
|
||||
import kotlinx.serialization.modules.SerializersModule
|
||||
import space.kscience.dataforge.context.Context
|
||||
import space.kscience.dataforge.context.PluginFactory
|
||||
import space.kscience.dataforge.context.PluginTag
|
||||
import space.kscience.dataforge.meta.Meta
|
||||
import space.kscience.visionforge.VisionPlugin
|
||||
|
||||
public actual class PlotlyPlugin : VisionPlugin() {
|
||||
|
||||
actual override val tag: PluginTag get() = Companion.tag
|
||||
|
||||
actual override val visionSerializersModule: SerializersModule get() = plotlySerializersModule
|
||||
|
||||
public actual companion object : PluginFactory<PlotlyPlugin> {
|
||||
actual override val tag: PluginTag = PluginTag("vision.plotly", PluginTag.DATAFORGE_GROUP)
|
||||
|
||||
actual override fun build(context: Context, meta: Meta): PlotlyPlugin = PlotlyPlugin()
|
||||
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import io.ktor.http.path
|
||||
import io.ktor.server.application.Application
|
||||
import io.ktor.server.application.install
|
||||
import io.ktor.server.application.log
|
||||
import io.ktor.server.application.pluginOrNull
|
||||
import io.ktor.server.engine.ConnectorType
|
||||
import io.ktor.server.engine.EngineConnectorConfig
|
||||
import io.ktor.server.html.respondHtml
|
||||
@@ -102,7 +103,9 @@ public fun Application.serveVisionData(
|
||||
configuration: VisionRoute,
|
||||
resolveVision: (Name) -> Vision?,
|
||||
) {
|
||||
install(WebSockets)
|
||||
if (pluginOrNull(WebSockets) == null) {
|
||||
install(WebSockets)
|
||||
}
|
||||
routing {
|
||||
route(configuration.route) {
|
||||
//TODO do more precise CORS policy
|
||||
@@ -208,7 +211,8 @@ public fun Application.visionPage(
|
||||
embedData = configuration.dataMode == VisionRoute.Mode.EMBED,
|
||||
fetchDataUrl = if (configuration.dataMode != VisionRoute.Mode.EMBED) {
|
||||
url {
|
||||
this.protocol = if (schema == ConnectorType.HTTPS) URLProtocol.HTTPS else URLProtocol.HTTP
|
||||
this.protocol =
|
||||
if (schema == ConnectorType.HTTPS) URLProtocol.HTTPS else URLProtocol.HTTP
|
||||
this.host = host
|
||||
this.port = port
|
||||
path(route, "data")
|
||||
|
||||
@@ -12,10 +12,7 @@ import kotlinx.serialization.builtins.serializer
|
||||
import kotlinx.serialization.descriptors.SerialDescriptor
|
||||
import kotlinx.serialization.encoding.Decoder
|
||||
import kotlinx.serialization.encoding.Encoder
|
||||
import space.kscience.dataforge.meta.Laminate
|
||||
import space.kscience.dataforge.meta.Meta
|
||||
import space.kscience.dataforge.meta.MutableMeta
|
||||
import space.kscience.dataforge.meta.MutableMetaProxy
|
||||
import space.kscience.dataforge.meta.*
|
||||
import space.kscience.dataforge.meta.descriptors.MetaDescriptor
|
||||
import space.kscience.dataforge.names.*
|
||||
import space.kscience.dataforge.provider.Path
|
||||
@@ -112,85 +109,37 @@ public class SolidReference(
|
||||
return if (listOfMeta.all { it == null }) null else Laminate(listOfMeta)
|
||||
}
|
||||
|
||||
//
|
||||
// override val properties: MutableVisionProperties by lazy {
|
||||
// object : AbstractVisionProperties(this, propertiesInternal) {
|
||||
//
|
||||
// override fun getValue(name: Name, inherit: Boolean?, includeStyles: Boolean?): Value? {
|
||||
// if (name == Vision.STYLE_KEY) {
|
||||
// return buildList {
|
||||
// own.getValue(Vision.STYLE_KEY)?.list?.forEach {
|
||||
// add(it)
|
||||
// }
|
||||
// prototype.styles.forEach {
|
||||
// add(it.asValue())
|
||||
// }
|
||||
// }.distinct().asValue()
|
||||
// }
|
||||
// //1. resolve own properties
|
||||
// own.getValue(name)?.let { return it }
|
||||
//
|
||||
// val descriptor = descriptor?.get(name)
|
||||
// val inheritFlag = inherit ?: descriptor?.inherited ?: false
|
||||
// val stylesFlag = includeStyles ?: descriptor?.usesStyles ?: true
|
||||
//
|
||||
// //2. Resolve prototype onw properties
|
||||
// prototype.properties.own.getValue(name)?.let { return it }
|
||||
//
|
||||
// if (stylesFlag) {
|
||||
// //3. own styles
|
||||
// own.getValue(Vision.STYLE_KEY)?.list?.forEach { styleName ->
|
||||
// getStyle(styleName.string)?.getValue(name)?.let { return it }
|
||||
// }
|
||||
// //4. prototype styles
|
||||
// prototype.getStyleProperty(name)?.value?.let { return it }
|
||||
// }
|
||||
//
|
||||
// if (inheritFlag) {
|
||||
// //5. own inheritance
|
||||
// parent?.properties?.getValue(name, inheritFlag, includeStyles)?.let { return it }
|
||||
// //6. prototype inheritance
|
||||
// prototype.parent?.properties?.getValue(name, inheritFlag, includeStyles)?.let { return it }
|
||||
// }
|
||||
//
|
||||
// return descriptor?.defaultValue
|
||||
// }
|
||||
//
|
||||
//
|
||||
// override fun invalidate(propertyName: Name) {
|
||||
// //send update signal
|
||||
// @OptIn(DelicateCoroutinesApi::class)
|
||||
// (manager?.context ?: GlobalScope).launch {
|
||||
// changesInternal.emit(propertyName)
|
||||
// }
|
||||
//
|
||||
// // update styles
|
||||
// if (propertyName == Vision.STYLE_KEY) {
|
||||
// styles.asSequence()
|
||||
// .mapNotNull { getStyle(it) }
|
||||
// .flatMap { it.items.asSequence() }
|
||||
// .distinctBy { it.key }
|
||||
// .forEach {
|
||||
// invalidate(it.key.asName())
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// val items: VisionChildren
|
||||
// get() = object : VisionChildren {
|
||||
// override val parent: Vision get() = this@SolidReference
|
||||
//
|
||||
// override val keys: Set<NameToken> get() = prototype.children?.keys ?: emptySet()
|
||||
//
|
||||
// override val changes: Flow<Name> get() = emptyFlow()
|
||||
//
|
||||
// override fun get(token: NameToken): SolidReferenceChild? {
|
||||
// if (token !in (prototype.children?.keys ?: emptySet())) return null
|
||||
// return SolidReferenceChild(this@SolidReference, this@SolidReference, token.asName())
|
||||
// }
|
||||
// }
|
||||
override fun writeProperty(
|
||||
name: Name,
|
||||
inherited: Boolean,
|
||||
useStyles: Boolean
|
||||
): MutableMeta {
|
||||
val mutable = properties.getOrCreate(name)
|
||||
|
||||
val default = buildList {
|
||||
//2. Resolve prototype own properties
|
||||
add(prototype.properties[name])
|
||||
|
||||
if (useStyles) {
|
||||
//3. own styles
|
||||
add(getStyleProperty(name))
|
||||
//4. prototype styles
|
||||
add(prototype.getStyleProperty(name))
|
||||
}
|
||||
|
||||
if (inherited) {
|
||||
//5. own inheritance
|
||||
add(parent?.readProperty(name, inherited, useStyles))
|
||||
//6. prototype inheritance
|
||||
add(prototype.parent?.readProperty(name, inherited, useStyles))
|
||||
}
|
||||
|
||||
add(descriptor.defaultNode[name])
|
||||
}
|
||||
return mutable.withDefault { name ->
|
||||
default.firstNotNullOfOrNull { it[name] }
|
||||
}
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public const val REFERENCE_CHILD_PROPERTY_PREFIX: String = "@child"
|
||||
@@ -221,7 +170,38 @@ private class SolidReferenceChild(
|
||||
VisionPropertyChangedEvent(it.propertyName.cutFirst(), it.propertyValue)
|
||||
}
|
||||
|
||||
override val properties: MutableMeta = MutableMetaProxy(owner.properties, childToken.asName())
|
||||
override val properties: MutableMeta = owner.properties.view(childToken.asName())
|
||||
|
||||
override fun writeProperty(
|
||||
name: Name,
|
||||
inherited: Boolean,
|
||||
useStyles: Boolean
|
||||
): MutableMeta {
|
||||
val mutable = properties.getOrCreate(name)
|
||||
val default = buildList {
|
||||
//2. Resolve prototype own properties
|
||||
add(prototype.properties[name])
|
||||
|
||||
if (useStyles) {
|
||||
//3. own styles
|
||||
add(getStyleProperty(name))
|
||||
//4. prototype styles
|
||||
add(prototype.getStyleProperty(name))
|
||||
}
|
||||
|
||||
if (inherited) {
|
||||
//5. own inheritance
|
||||
add(parent?.readProperty(name, inherited, useStyles))
|
||||
//6. prototype inheritance
|
||||
add(prototype.parent?.readProperty(name, inherited, useStyles))
|
||||
}
|
||||
|
||||
add(descriptor.defaultNode[name])
|
||||
}
|
||||
return mutable.withDefault { name ->
|
||||
default.firstNotNullOfOrNull { it[name] }
|
||||
}
|
||||
}
|
||||
|
||||
override fun readProperty(
|
||||
name: Name,
|
||||
@@ -259,34 +239,6 @@ private class SolidReferenceChild(
|
||||
SolidReferenceChild(owner, this, childName + key)
|
||||
} ?: emptyMap()
|
||||
|
||||
// @Transient
|
||||
// override val properties: MutableVisionProperties = object : MutableVisionProperties {
|
||||
// override val descriptor: MetaDescriptor get() = this@SolidReferenceChild.descriptor
|
||||
//
|
||||
// override val own: MutableMeta by lazy { owner.properties[childToken(childName).asName()] }
|
||||
//
|
||||
// override fun getValue(
|
||||
// name: Name,
|
||||
// inherit: Boolean?,
|
||||
// includeStyles: Boolean?,
|
||||
// ): Value? = own.getValue(name) ?: prototype.properties.getValue(name, inherit, includeStyles)
|
||||
//
|
||||
// override fun set(name: Name, item: Meta?, notify: Boolean) {
|
||||
// own[name] = item
|
||||
// }
|
||||
//
|
||||
// override fun setValue(name: Name, value: Value?, notify: Boolean) {
|
||||
// own.setValue(name, value)
|
||||
// }
|
||||
//
|
||||
// override val changes: Flow<Name>
|
||||
// get() = owner.properties.changes.filter { it.startsWith(childToken(childName)) }
|
||||
//
|
||||
// override fun invalidate(propertyName: Name) {
|
||||
// owner.properties.invalidate(childPropertyName(childName, propertyName))
|
||||
// }
|
||||
// }
|
||||
|
||||
companion object {
|
||||
|
||||
private fun childToken(childName: Name): NameToken =
|
||||
|
||||
@@ -33,6 +33,6 @@ kscience {
|
||||
|
||||
jsMain {
|
||||
api(projects.visionforgeThreejs)
|
||||
compileOnly(npm("webpack-bundle-analyzer", "4.5.0"))
|
||||
// compileOnly(npm("webpack-bundle-analyzer", "4.5.0"))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user