Use context instead of specialized plugins in JS rendering

This commit is contained in:
Alexander Nozik 2024-02-07 18:11:49 +03:00
parent 629923c03a
commit 30ad680688
32 changed files with 232 additions and 202 deletions

View File

@ -6,11 +6,11 @@ plugins {
// id("org.jetbrains.kotlinx.kover") version "0.5.0" // id("org.jetbrains.kotlinx.kover") version "0.5.0"
} }
val dataforgeVersion by extra("0.7.1") val dataforgeVersion by extra("0.8.0")
allprojects { allprojects {
group = "space.kscience" group = "space.kscience"
version = "0.4.0-dev-1" version = "0.4.0-dev-2"
} }
subprojects { subprojects {

View File

@ -38,30 +38,6 @@ kotlin {
explicitApi = null explicitApi = null
} }
//kotlin {
//
// sourceSets {
// commonMain {
// dependencies {
// implementation(project(":visionforge-solid"))
// implementation(project(":visionforge-gdml"))
// }
// }
// jvmMain {
// dependencies {
//// implementation(project(":visionforge-fx"))
// implementation("ch.qos.logback:logback-classic:1.2.11")
// }
// }
// jsMain {
// dependencies {
// implementation(project(":ui:ring"))
// implementation(project(":visionforge-threejs"))
// implementation(npm("react-file-drop", "3.0.6"))
// }
// }
// }
//}
//val convertGdmlToJson by tasks.creating(JavaExec::class) { //val convertGdmlToJson by tasks.creating(JavaExec::class) {
// group = "application" // group = "application"

View File

@ -9,6 +9,7 @@ import org.jetbrains.compose.web.dom.Text
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
import space.kscience.dataforge.context.Context
import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.Name
import space.kscience.gdml.Gdml import space.kscience.gdml.Gdml
import space.kscience.gdml.decodeFromString import space.kscience.gdml.decodeFromString
@ -17,17 +18,18 @@ import space.kscience.visionforge.gdml.markLayers
import space.kscience.visionforge.gdml.toVision import space.kscience.visionforge.gdml.toVision
import space.kscience.visionforge.setAsRoot import space.kscience.visionforge.setAsRoot
import space.kscience.visionforge.solid.Solid import space.kscience.visionforge.solid.Solid
import space.kscience.visionforge.solid.Solids
import space.kscience.visionforge.solid.ambientLight import space.kscience.visionforge.solid.ambientLight
import space.kscience.visionforge.solid.invoke import space.kscience.visionforge.solid.invoke
import space.kscience.visionforge.solid.three.compose.ThreeView import space.kscience.visionforge.solid.three.compose.ThreeView
import space.kscience.visionforge.visionManager
@Composable @Composable
fun GDMLApp(solids: Solids, initialVision: Solid?, selected: Name? = null) { fun GDMLApp(context: Context, initialVision: Solid?, selected: Name? = null) {
var vision: Solid? by remember { mutableStateOf(initialVision) } var vision: Solid? by remember { mutableStateOf(initialVision) }
fun readFileAsync(file: File) { fun readFileAsync(file: File) {
val visionManager = context.visionManager
FileReader().apply { FileReader().apply {
onload = { onload = {
val data = result as String val data = result as String
@ -36,7 +38,7 @@ fun GDMLApp(solids: Solids, initialVision: Solid?, selected: Name? = null) {
name.endsWith(".gdml") || name.endsWith(".xml") -> { name.endsWith(".gdml") || name.endsWith(".xml") -> {
val gdml = Gdml.decodeFromString(data) val gdml = Gdml.decodeFromString(data)
gdml.toVision().apply { gdml.toVision().apply {
setAsRoot(solids.visionManager) setAsRoot(visionManager)
console.info("Marking layers for file $name") console.info("Marking layers for file $name")
markLayers() markLayers()
ambientLight { ambientLight {
@ -45,7 +47,7 @@ fun GDMLApp(solids: Solids, initialVision: Solid?, selected: Name? = null) {
} }
} }
name.endsWith(".json") -> solids.visionManager.decodeFromString(data) name.endsWith(".json") -> visionManager.decodeFromString(data)
else -> { else -> {
window.alert("File extension is not recognized: $name") window.alert("File extension is not recognized: $name")
error("File extension is not recognized: $name") error("File extension is not recognized: $name")
@ -64,7 +66,7 @@ fun GDMLApp(solids: Solids, initialVision: Solid?, selected: Name? = null) {
width(100.vw) width(100.vw)
} }
}) { }) {
ThreeView(solids, vision, selected) { ThreeView(context, vision, selected) {
Tab("Load") { Tab("Load") {
P { P {
Text("Drag and drop .gdml or .json VisionForge files here") Text("Drag and drop .gdml or .json VisionForge files here")

View File

@ -5,13 +5,11 @@ import org.jetbrains.compose.web.dom.Style
import org.jetbrains.compose.web.renderComposable import org.jetbrains.compose.web.renderComposable
import org.w3c.dom.Document import org.w3c.dom.Document
import space.kscience.dataforge.context.Context import space.kscience.dataforge.context.Context
import space.kscience.dataforge.context.request
import space.kscience.gdml.GdmlShowCase import space.kscience.gdml.GdmlShowCase
import space.kscience.visionforge.Application import space.kscience.visionforge.Application
import space.kscience.visionforge.Colors import space.kscience.visionforge.Colors
import space.kscience.visionforge.compose.TreeStyles import space.kscience.visionforge.compose.TreeStyles
import space.kscience.visionforge.gdml.toVision import space.kscience.visionforge.gdml.toVision
import space.kscience.visionforge.solid.Solids
import space.kscience.visionforge.solid.ambientLight import space.kscience.visionforge.solid.ambientLight
import space.kscience.visionforge.solid.invoke import space.kscience.visionforge.solid.invoke
import space.kscience.visionforge.solid.three.ThreePlugin import space.kscience.visionforge.solid.three.ThreePlugin
@ -20,11 +18,12 @@ import space.kscience.visionforge.startApplication
private class GDMLDemoApp : Application { private class GDMLDemoApp : Application {
override fun start(document: Document, state: Map<String, Any>) {
val context = Context("gdml-demo") { val context = Context("gdml-demo") {
plugin(ThreePlugin) 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 { val vision = GdmlShowCase.cubes().toVision().apply {
@ -52,7 +51,7 @@ private class GDMLDemoApp : Application {
alignItems(AlignItems.Stretch) alignItems(AlignItems.Stretch)
} }
} }
GDMLApp(context.request(Solids), vision) GDMLApp(context, vision)
} }
} }
} }

View File

@ -1,5 +1,6 @@
plugins { plugins {
id("space.kscience.gradle.mpp") id("space.kscience.gradle.mpp")
alias(spclibs.plugins.compose)
} }
kscience { kscience {
@ -11,12 +12,20 @@ kotlin {
js { js {
browser { browser {
binaries.executable() binaries.executable()
commonWebpackConfig{
cssSupport{
enabled = true
}
scssSupport{
enabled = true
}
sourceMaps = true
}
} }
} }
} }
kscience { kscience {
dependencies { dependencies {
implementation(projects.visionforge.visionforgeGdml) implementation(projects.visionforge.visionforgeGdml)
implementation(projects.visionforge.visionforgePlotly) implementation(projects.visionforge.visionforgePlotly)

View File

@ -3,13 +3,13 @@ import org.jetbrains.compose.web.dom.Div
import org.jetbrains.compose.web.renderComposable import org.jetbrains.compose.web.renderComposable
import org.w3c.dom.Document import org.w3c.dom.Document
import space.kscience.dataforge.context.Context import space.kscience.dataforge.context.Context
import space.kscience.dataforge.context.request
import space.kscience.plotly.models.Trace import space.kscience.plotly.models.Trace
import space.kscience.plotly.scatter import space.kscience.plotly.scatter
import space.kscience.visionforge.Application import space.kscience.visionforge.Application
import space.kscience.visionforge.Colors import space.kscience.visionforge.Colors
import space.kscience.visionforge.JsVisionClient
import space.kscience.visionforge.compose.Tabs import space.kscience.visionforge.compose.Tabs
import space.kscience.visionforge.compose.TreeStyles
import space.kscience.visionforge.markup.MarkupPlugin
import space.kscience.visionforge.plotly.PlotlyPlugin import space.kscience.visionforge.plotly.PlotlyPlugin
import space.kscience.visionforge.solid.* import space.kscience.visionforge.solid.*
import space.kscience.visionforge.solid.three.ThreePlugin import space.kscience.visionforge.solid.three.ThreePlugin
@ -26,19 +26,21 @@ fun Trace.appendXYLatest(x: Number, y: Number, history: Int = 400, xErr: Number?
private class JsPlaygroundApp : Application { private class JsPlaygroundApp : Application {
override fun start(document: Document, state: Map<String, Any>) {
val playgroundContext = Context { val playgroundContext = Context {
plugin(ThreePlugin) plugin(ThreePlugin)
plugin(PlotlyPlugin) plugin(PlotlyPlugin)
plugin(MarkupPlugin)
} }
val solids = playgroundContext.request(Solids) override fun start(document: Document, state: Map<String, Any>) {
val client = playgroundContext.request(JsVisionClient)
// val solids = playgroundContext.request(Solids)
// val client = playgroundContext.request(JsVisionClient)
val element = document.getElementById("playground") ?: error("Element with id 'playground' not found on page") val element = document.getElementById("playground") ?: error("Element with id 'playground' not found on page")
renderComposable(element) { renderComposable(element) {
Style(TreeStyles)
Div({ Div({
style { style {
padding(0.pt) padding(0.pt)
@ -49,7 +51,7 @@ private class JsPlaygroundApp : Application {
}) { }) {
Tabs("gravity") { Tabs("gravity") {
Tab("gravity") { Tab("gravity") {
GravityDemo(solids, client) GravityDemo(playgroundContext)
} }
// Tab("D0") { // Tab("D0") {
@ -66,7 +68,7 @@ private class JsPlaygroundApp : Application {
height(100.vh - 50.pt) height(100.vh - 50.pt)
} }
}) { }) {
ThreeView(solids, SolidGroup { ThreeView(playgroundContext, SolidGroup {
ambientLight { ambientLight {
color(Colors.white) color(Colors.white)
} }
@ -85,7 +87,7 @@ private class JsPlaygroundApp : Application {
} }
} }
Tab("plotly") { Tab("plotly") {
Plot(client) { Plot(playgroundContext) {
scatter { scatter {
x(1, 2, 3) x(1, 2, 3)
y(5, 8, 7) y(5, 8, 7)

View File

@ -1,19 +1,20 @@
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import app.softwork.bootstrapcompose.Column
import app.softwork.bootstrapcompose.Row
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive import kotlinx.coroutines.isActive
import org.jetbrains.compose.web.css.* import org.jetbrains.compose.web.css.*
import org.jetbrains.compose.web.dom.AttrBuilderContext import org.jetbrains.compose.web.dom.AttrBuilderContext
import org.jetbrains.compose.web.dom.Div import org.jetbrains.compose.web.dom.Div
import org.w3c.dom.HTMLDivElement import org.w3c.dom.HTMLDivElement
import space.kscience.dataforge.context.Context
import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.Meta
import space.kscience.plotly.Plot import space.kscience.plotly.Plot
import space.kscience.plotly.layout import space.kscience.plotly.layout
import space.kscience.plotly.models.Trace import space.kscience.plotly.models.Trace
import space.kscience.visionforge.Colors import space.kscience.visionforge.Colors
import space.kscience.visionforge.VisionClient
import space.kscience.visionforge.compose.FlexRow
import space.kscience.visionforge.compose.Vision import space.kscience.visionforge.compose.Vision
import space.kscience.visionforge.compose.zIndex import space.kscience.visionforge.compose.zIndex
import space.kscience.visionforge.markup.VisionOfMarkup import space.kscience.visionforge.markup.VisionOfMarkup
@ -24,12 +25,12 @@ import kotlin.math.sqrt
@Composable @Composable
fun Plot( fun Plot(
client: VisionClient, context: Context,
meta: Meta = Meta.EMPTY, meta: Meta = Meta.EMPTY,
attrs: AttrBuilderContext<HTMLDivElement>? = null, attrs: AttrBuilderContext<HTMLDivElement>? = null,
block: Plot.() -> Unit, block: Plot.() -> Unit,
) = Vision( ) = Vision(
client = client, context = context,
attrs = attrs, attrs = attrs,
meta = meta, meta = meta,
vision = Plot().apply(block).asVision() vision = Plot().apply(block).asVision()
@ -37,12 +38,12 @@ fun Plot(
@Composable @Composable
fun Markup( fun Markup(
client: VisionClient, context: Context,
markup: VisionOfMarkup, markup: VisionOfMarkup,
meta: Meta = Meta.EMPTY, meta: Meta = Meta.EMPTY,
attrs: AttrBuilderContext<HTMLDivElement>? = null, attrs: AttrBuilderContext<HTMLDivElement>? = null,
) = Vision( ) = Vision(
client = client, context = context,
attrs = attrs, attrs = attrs,
meta = meta, meta = meta,
vision = markup vision = markup
@ -52,7 +53,7 @@ fun Markup(
private val h = 100.0 private val h = 100.0
@Composable @Composable
fun GravityDemo(solids: Solids, client: VisionClient) { fun GravityDemo(context: Context) {
val velocityTrace = remember { val velocityTrace = remember {
Trace { Trace {
name = "velocity" name = "velocity"
@ -128,22 +129,25 @@ fun GravityDemo(solids: Solids, client: VisionClient) {
height(50.vh) height(50.vh)
} }
}) { }) {
ThreeView(solids, solid) ThreeView(context, solid)
} }
FlexRow({ Row(attrs = {
style { style {
alignContent(AlignContent.Stretch) alignContent(AlignContent.Stretch)
alignItems(AlignItems.Stretch) alignItems(AlignItems.Stretch)
height(50.vh - 50.pt) height(50.vh - 50.pt)
} }
}) { }) {
Plot(client) { Column {
Plot(context) {
traces(velocityTrace, energyTrace) traces(velocityTrace, energyTrace)
layout { layout {
xaxis.title = "time" xaxis.title = "time"
} }
} }
Markup(client, markup, attrs = { }
Column {
Markup(context, markup, attrs = {
style { style {
width(100.percent) width(100.percent)
height(100.percent) height(100.percent)
@ -157,3 +161,4 @@ fun GravityDemo(solids: Solids, client: VisionClient) {
} }
} }
} }
}

View File

@ -17,10 +17,10 @@ import org.jetbrains.compose.web.dom.P
import org.jetbrains.compose.web.dom.Span import org.jetbrains.compose.web.dom.Span
import org.jetbrains.compose.web.dom.Text import org.jetbrains.compose.web.dom.Text
import org.w3c.fetch.RequestInit import org.w3c.fetch.RequestInit
import space.kscience.dataforge.context.Context
import space.kscience.dataforge.meta.invoke import space.kscience.dataforge.meta.invoke
import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.Name
import space.kscience.visionforge.Colors import space.kscience.visionforge.Colors
import space.kscience.visionforge.solid.Solids
import space.kscience.visionforge.solid.ambientLight import space.kscience.visionforge.solid.ambientLight
import space.kscience.visionforge.solid.edges import space.kscience.visionforge.solid.edges
import space.kscience.visionforge.solid.invoke import space.kscience.visionforge.solid.invoke
@ -29,7 +29,7 @@ import space.kscience.visionforge.solid.three.compose.ThreeView
import kotlin.math.PI import kotlin.math.PI
@Composable @Composable
fun MMApp(solids: Solids, model: Model, selected: Name? = null) { fun MMApp(context: Context, model: Model, selected: Name? = null) {
val mmOptions = remember { val mmOptions = remember {
Canvas3DOptions { Canvas3DOptions {
@ -60,7 +60,7 @@ fun MMApp(solids: Solids, model: Model, selected: Name? = null) {
} }
) { ) {
ThreeView( ThreeView(
solids = solids, context,
solid = root, solid = root,
initialSelected = selected, initialSelected = selected,
options = mmOptions, options = mmOptions,
@ -68,7 +68,7 @@ fun MMApp(solids: Solids, model: Model, selected: Name? = null) {
Tab("Events") { Tab("Events") {
ButtonGroup({ Layout.width = Width.Full }) { ButtonGroup({ Layout.width = Width.Full }) {
Button("Next") { Button("Next") {
solids.context.launch { context.launch {
val event = window.fetch( val event = window.fetch(
"http://localhost:8080/event", "http://localhost:8080/event",
RequestInit("GET") RequestInit("GET")

View File

@ -8,7 +8,6 @@ import space.kscience.dataforge.context.request
import space.kscience.visionforge.Application import space.kscience.visionforge.Application
import space.kscience.visionforge.VisionManager import space.kscience.visionforge.VisionManager
import space.kscience.visionforge.compose.VisionForgeStyles import space.kscience.visionforge.compose.VisionForgeStyles
import space.kscience.visionforge.solid.Solids
import space.kscience.visionforge.solid.three.ThreePlugin import space.kscience.visionforge.solid.three.ThreePlugin
import space.kscience.visionforge.startApplication import space.kscience.visionforge.startApplication
@ -26,7 +25,7 @@ private class MMDemoApp : Application {
renderComposable("app") { renderComposable("app") {
Style(VisionForgeStyles) Style(VisionForgeStyles)
MMApp(context.request(Solids), model) MMApp(context, model)
} }
} }
} }

View File

@ -2,7 +2,6 @@ package space.kscience.visionforge.examples
import kotlinx.html.h2 import kotlinx.html.h2
import space.kscience.dataforge.meta.ValueType import space.kscience.dataforge.meta.ValueType
import space.kscience.dataforge.meta.invoke
import space.kscience.plotly.layout import space.kscience.plotly.layout
import space.kscience.plotly.models.ScatterMode import space.kscience.plotly.models.ScatterMode
import space.kscience.plotly.models.TextPosition import space.kscience.plotly.models.TextPosition
@ -11,9 +10,9 @@ import space.kscience.tables.ColumnHeader
import space.kscience.visionforge.html.ResourceLocation import space.kscience.visionforge.html.ResourceLocation
import space.kscience.visionforge.markup.markdown import space.kscience.visionforge.markup.markdown
import space.kscience.visionforge.plotly.plotly import space.kscience.visionforge.plotly.plotly
import space.kscience.visionforge.solid.axes
import space.kscience.visionforge.solid.box import space.kscience.visionforge.solid.box
import space.kscience.visionforge.solid.solid import space.kscience.visionforge.solid.solid
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
import space.kscience.visionforge.solid.z import space.kscience.visionforge.solid.z
import space.kscience.visionforge.tables.columnTable import space.kscience.visionforge.tables.columnTable
import kotlin.io.path.Path import kotlin.io.path.Path
@ -34,14 +33,8 @@ fun main() = makeVisionFile(
h2 { +"3D visualization with Three-js" } h2 { +"3D visualization with Three-js" }
vision("3D") { vision("3D") {
solid( solid {
Canvas3DOptions { axes(200)
axes {
size = 200.0
visible = true
}
}
) {
box(100, 100, 100, name = "aBox") { box(100, 100, 100, name = "aBox") {
z = 50.0 z = 50.0
} }

View File

@ -0,0 +1,19 @@
package space.kscience.visionforge.examples
import space.kscience.visionforge.html.ResourceLocation
import space.kscience.visionforge.markup.markdown
fun main() = makeVisionFile(resourceLocation = ResourceLocation.SYSTEM) {
vision {
markdown{
content = """
# h1 Heading 8-)
## h2 Heading
### h3 Heading
#### h4 Heading
##### h5 Heading
###### h6 Heading
""".trimIndent()
}
}
}

View File

@ -38,10 +38,6 @@ val canvasOptions = Canvas3DOptions {
size { size {
minSize = 400 minSize = 400
} }
axes {
size = 500.0
visible = true
}
camera { camera {
distance = 600.0 distance = 600.0
latitude = PI / 6 latitude = PI / 6
@ -52,6 +48,8 @@ val canvasOptions = Canvas3DOptions {
fun VisionLayout<Solid>.showcase() { fun VisionLayout<Solid>.showcase() {
demo("shapes", "Basic shapes") { demo("shapes", "Basic shapes") {
ambientLight() ambientLight()
axes(size = 500.0)
box(100.0, 100.0, 100.0) { box(100.0, 100.0, 100.0) {
z = -110.0 z = -110.0
color("teal") color("teal")

View File

@ -8,6 +8,6 @@ org.gradle.jvmargs=-Xmx4G
org.jetbrains.compose.experimental.jscanvas.enabled=true org.jetbrains.compose.experimental.jscanvas.enabled=true
toolsVersion=0.15.2-kotlin-1.9.21 toolsVersion=0.15.2-kotlin-1.9.22
#kotlin.experimental.tryK2=true #kotlin.experimental.tryK2=true
#kscience.wasm.disabled=true #kscience.wasm.disabled=true

View File

@ -63,7 +63,7 @@ private fun MetaViewerItem(root: Meta, name: Name, rootDescriptor: MetaDescripto
classes(TreeStyles.tree) classes(TreeStyles.tree)
}) { }) {
val keys = buildSet { val keys = buildSet {
descriptorItem?.children?.keys?.forEach { descriptorItem?.nodes?.keys?.forEach {
add(NameToken(it)) add(NameToken(it))
} }
actualMeta!!.items.keys.let { addAll(it) } actualMeta!!.items.keys.let { addAll(it) }

View File

@ -55,7 +55,7 @@ public fun PropertyEditor(
val keys by derivedStateOf { val keys by derivedStateOf {
buildSet { buildSet {
descriptor?.children?.filterNot { descriptor?.nodes?.filterNot {
it.key.startsWith("@") || it.value.hidden it.key.startsWith("@") || it.value.hidden
}?.forEach { }?.forEach {
add(NameToken(it.key)) add(NameToken(it.key))

View File

@ -8,13 +8,13 @@ import kotlinx.dom.clear
import org.jetbrains.compose.web.dom.AttrBuilderContext import org.jetbrains.compose.web.dom.AttrBuilderContext
import org.jetbrains.compose.web.dom.Div import org.jetbrains.compose.web.dom.Div
import org.w3c.dom.HTMLDivElement import org.w3c.dom.HTMLDivElement
import space.kscience.dataforge.context.Context
import space.kscience.dataforge.context.gather import space.kscience.dataforge.context.gather
import space.kscience.dataforge.context.request
import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.asName import space.kscience.dataforge.names.asName
import space.kscience.visionforge.ElementVisionRenderer import space.kscience.visionforge.*
import space.kscience.visionforge.Vision
import space.kscience.visionforge.VisionClient
/** /**
@ -22,13 +22,20 @@ import space.kscience.visionforge.VisionClient
*/ */
@Composable @Composable
public fun Vision( public fun Vision(
client: VisionClient, context: Context,
vision: Vision, vision: Vision,
name: Name = "@vision[${vision.hashCode().toString(16)}]".asName(), name: Name = "@vision[${vision.hashCode().toString(16)}]".asName(),
meta: Meta = Meta.EMPTY, meta: Meta = Meta.EMPTY,
attrs: AttrBuilderContext<HTMLDivElement>? = null, attrs: AttrBuilderContext<HTMLDivElement>? = null,
): Unit = Div(attrs) { ): Unit = Div(attrs) {
val client: VisionClient = context.request(JsVisionClient)
// set vision root if necessary
if (vision.manager == null) {
vision.setAsRoot(client.visionManager)
}
val renderer by derivedStateOf { val renderer by derivedStateOf {
client.context.gather<ElementVisionRenderer>(ElementVisionRenderer.TYPE).values.mapNotNull { client.context.gather<ElementVisionRenderer>(ElementVisionRenderer.TYPE).values.mapNotNull {
val rating = it.rateVision(vision) val rating = it.rateVision(vision)

View File

@ -3,7 +3,7 @@ package space.kscience.visionforge
import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.meta.MutableMeta import space.kscience.dataforge.meta.MutableMeta
import space.kscience.dataforge.meta.Scheme import space.kscience.dataforge.meta.Scheme
import space.kscience.dataforge.meta.Specification import space.kscience.dataforge.meta.SchemeSpec
import kotlin.properties.ReadOnlyProperty import kotlin.properties.ReadOnlyProperty
/** /**
@ -36,7 +36,7 @@ public fun Vision.style(
@VisionBuilder @VisionBuilder
public fun <T : Scheme> Vision.style( public fun <T : Scheme> Vision.style(
spec: Specification<T>, spec: SchemeSpec<T>,
styleKey: String? = null, styleKey: String? = null,
builder: T.() -> Unit, builder: T.() -> Unit,
): ReadOnlyProperty<Any?, StyleReference> = ReadOnlyProperty { _, property -> ): ReadOnlyProperty<Any?, StyleReference> = ReadOnlyProperty { _, property ->

View File

@ -113,7 +113,7 @@ private class VisionPropertiesItem(
override val items: Map<NameToken, MutableMeta> override val items: Map<NameToken, MutableMeta>
get() { get() {
val metaKeys = properties.own?.get(nodeName)?.items?.keys ?: emptySet() val metaKeys = properties.own?.get(nodeName)?.items?.keys ?: emptySet()
val descriptorKeys = descriptor?.children?.map { NameToken(it.key) } ?: emptySet() val descriptorKeys = descriptor?.nodes?.map { NameToken(it.key) } ?: emptySet()
val defaultKeys = default?.get(nodeName)?.items?.keys ?: emptySet() val defaultKeys = default?.get(nodeName)?.items?.keys ?: emptySet()
val inheritFlag = descriptor?.inherited ?: inherit val inheritFlag = descriptor?.inherited ?: inherit
val stylesFlag = descriptor?.usesStyles ?: useStyles val stylesFlag = descriptor?.usesStyles ?: useStyles

View File

@ -55,7 +55,7 @@ public class VisionForge(
override val context: Context get() = visionManager.context override val context: Context get() = visionManager.context
public val configuration: ObservableMutableMeta = meta.toMutableMeta() public val configuration: ObservableMutableMeta = meta.toMutableMeta().asObservable()
private var counter = 0 private var counter = 0

View File

@ -2,7 +2,7 @@ plugins {
id("space.kscience.gradle.mpp") id("space.kscience.gradle.mpp")
} }
val plotlyVersion = "0.6.1" val plotlyVersion = "0.7.0"
kscience { kscience {
jvm() jvm()

View File

@ -1,22 +1,110 @@
package space.kscience.visionforge.plotly 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.Plotly
import space.kscience.plotly.scatter import space.kscience.plotly.layout
import space.kscience.plotly.models.*
import space.kscience.visionforge.visionManager
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertTrue import kotlin.test.assertEquals
class VisionOfPlotlyTest { class VisionOfPlotlyTest {
@Test @Test
fun conversion() { 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 { val plot = Plotly.plot {
scatter { traces(trace1, trace2)
x(1,2,3) layout {
y(1,2,3) width = 800
height = 800
title = "Advanced Violin Plot"
} }
} }
val vision = VisionOfPlotly(plot) val vision = VisionOfPlotly(plot)
// println(vision.plot.toJsonString()) val context = Context {
// println(vision.plot.data.toJsonString()) plugin(PlotlyPlugin)
assertTrue { vision.plot.data.first().x.doubles.size == 3} }
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)
} }
} }

View File

@ -1,35 +0,0 @@
package space.kscience.visionforge.solid.specifications
import space.kscience.dataforge.meta.Scheme
import space.kscience.dataforge.meta.SchemeSpec
import space.kscience.dataforge.meta.boolean
import space.kscience.dataforge.meta.descriptors.MetaDescriptor
import space.kscience.dataforge.meta.descriptors.value
import space.kscience.dataforge.meta.double
@Deprecated("Use separate axes object instead")
public class AxesScheme : Scheme() {
public var visible: Boolean by boolean(false)
public var size: Double by double(AXIS_SIZE)
public var width: Double by double(AXIS_WIDTH)
@Suppress("DEPRECATION")
public companion object : SchemeSpec<AxesScheme>(::AxesScheme) {
public const val AXIS_SIZE: Double = 1000.0
public const val AXIS_WIDTH: Double = 3.0
override val descriptor: MetaDescriptor by lazy {
MetaDescriptor {
value(AxesScheme::visible){
default(false)
}
value(AxesScheme::size){
default(AXIS_SIZE)
}
value(AxesScheme::width){
default(AXIS_WIDTH)
}
}
}
}
}

View File

@ -1,3 +1,5 @@
@file:OptIn(DFExperimental::class)
package space.kscience.visionforge.solid.specifications package space.kscience.visionforge.solid.specifications
import space.kscience.dataforge.meta.* import space.kscience.dataforge.meta.*
@ -5,6 +7,7 @@ import space.kscience.dataforge.meta.descriptors.MetaDescriptor
import space.kscience.dataforge.meta.descriptors.scheme import space.kscience.dataforge.meta.descriptors.scheme
import space.kscience.dataforge.meta.descriptors.value import space.kscience.dataforge.meta.descriptors.value
import space.kscience.dataforge.meta.set import space.kscience.dataforge.meta.set
import space.kscience.dataforge.misc.DFExperimental
import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.Name
import space.kscience.visionforge.hide import space.kscience.visionforge.hide
import space.kscience.visionforge.widgetType import space.kscience.visionforge.widgetType
@ -61,16 +64,14 @@ public class CanvasSize : Scheme() {
public class Canvas3DOptions : Scheme() { public class Canvas3DOptions : Scheme() {
public var canvasName: String by string("vision") public var canvasName: String by string("vision")
@Suppress("DEPRECATION") public var camera: CameraScheme by scheme(CameraScheme)
public var axes: AxesScheme by spec(AxesScheme) public var controls: Canvas3DUIScheme by scheme(Canvas3DUIScheme)
public var camera: CameraScheme by spec(CameraScheme)
public var controls: Canvas3DUIScheme by spec(Canvas3DUIScheme)
public var size: CanvasSize by spec(CanvasSize) public var size: CanvasSize by scheme(CanvasSize)
public var layers: List<Number> by numberList(0) public var layers: List<Number> by numberList(0)
public var clipping: PointScheme by spec(Clipping) public var clipping: PointScheme by scheme(Clipping)
public var onSelect: ((Name?) -> Unit)? = null public var onSelect: ((Name?) -> Unit)? = null
@ -78,9 +79,6 @@ public class Canvas3DOptions : Scheme() {
public companion object : SchemeSpec<Canvas3DOptions>(::Canvas3DOptions) { public companion object : SchemeSpec<Canvas3DOptions>(::Canvas3DOptions) {
override val descriptor: MetaDescriptor by lazy { override val descriptor: MetaDescriptor by lazy {
MetaDescriptor { MetaDescriptor {
@Suppress("DEPRECATION")
scheme(Canvas3DOptions::axes, AxesScheme)
value(Canvas3DOptions::layers) { value(Canvas3DOptions::layers) {
multiple = true multiple = true
default(listOf(0)) default(listOf(0))

View File

@ -1,21 +0,0 @@
package space.kscience.visionforge.solid
import space.kscience.dataforge.meta.ValueType
import space.kscience.dataforge.meta.descriptors.get
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
import kotlin.test.Test
import kotlin.test.assertNotNull
import kotlin.test.assertTrue
class DescriptorTest {
@Test
fun canvasDescriptor() {
val descriptor = Canvas3DOptions.descriptor
//println(descriptor.config)
val axesSize = descriptor["axes.size"]
assertNotNull(axesSize)
assertTrue {
ValueType.NUMBER in axesSize.valueTypes!!
}
}
}

View File

@ -2,7 +2,7 @@ plugins {
id("space.kscience.gradle.mpp") id("space.kscience.gradle.mpp")
} }
val tablesVersion = "0.3.0" val tablesVersion = "0.4.0"
kscience { kscience {
jvm() jvm()

View File

@ -70,7 +70,7 @@ public fun <T> Table<T>.toVision(
} else { } else {
Meta { Meta {
headers.forEach { headers.forEach {
it.name put converter(row[it.name]) it.name put converter(row.getOrNull(it.name))
} }
} }
} }

View File

@ -1,6 +1,6 @@
package space.kscience.visionforge.tables package space.kscience.visionforge.tables
import js.core.jso import js.objects.jso
import org.w3c.dom.Element import org.w3c.dom.Element
import org.w3c.dom.HTMLElement import org.w3c.dom.HTMLElement
import space.kscience.dataforge.context.AbstractPlugin import space.kscience.dataforge.context.AbstractPlugin

View File

@ -20,7 +20,6 @@ import three.core.Raycaster
import three.external.controls.OrbitControls import three.external.controls.OrbitControls
import three.external.controls.TrackballControls import three.external.controls.TrackballControls
import three.geometries.EdgesGeometry import three.geometries.EdgesGeometry
import three.helpers.AxesHelper
import three.materials.Material import three.materials.Material
import three.math.* import three.math.*
import three.meshline.MeshLine import three.meshline.MeshLine
@ -50,14 +49,7 @@ public class ThreeCanvas(
private val raycaster = Raycaster() private val raycaster = Raycaster()
private val mousePosition: Vector2 = Vector2() private val mousePosition: Vector2 = Vector2()
private val scene: Scene = Scene().apply { private val scene: Scene = Scene()
options.useProperty(Canvas3DOptions::axes, this) {
getObjectByName(AXES_NAME)?.let { remove(it) }
val axesObject = AxesHelper(axes.size.toInt()).apply { visible = axes.visible }
axesObject.name = AXES_NAME
add(axesObject)
}
}
private fun buildCamera(spec: CameraScheme) = PerspectiveCamera( private fun buildCamera(spec: CameraScheme) = PerspectiveCamera(

View File

@ -1,7 +1,7 @@
package space.kscience.visionforge.solid.three package space.kscience.visionforge.solid.three
import js.core.jso import js.objects.jso
import space.kscience.dataforge.context.logger import space.kscience.dataforge.context.logger
import space.kscience.dataforge.context.warn import space.kscience.dataforge.context.warn
import space.kscience.visionforge.onPropertyChange import space.kscience.visionforge.onPropertyChange

View File

@ -189,7 +189,7 @@ public class ThreePlugin : AbstractPlugin(), ComposeVisionRenderer {
@Composable @Composable
override fun DOMScope<Element>.render(client: VisionClient, name: Name, vision: Vision, meta: Meta) { override fun DOMScope<Element>.render(client: VisionClient, name: Name, vision: Vision, meta: Meta) {
require(vision is Solid) { "Expected Solid but found ${vision::class}" } require(vision is Solid) { "Expected Solid but found ${vision::class}" }
ThreeView(solids, vision, null, Canvas3DOptions.read(meta)) ThreeView(context, vision, null, Canvas3DOptions.read(meta))
} }
public companion object : PluginFactory<ThreePlugin> { public companion object : PluginFactory<ThreePlugin> {

View File

@ -17,7 +17,6 @@ import space.kscience.visionforge.compose.*
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.SolidGroup import space.kscience.visionforge.solid.SolidGroup
import space.kscience.visionforge.solid.Solids
import space.kscience.visionforge.solid.specifications.Canvas3DOptions import space.kscience.visionforge.solid.specifications.Canvas3DOptions
import space.kscience.visionforge.solid.three.ThreeCanvas import space.kscience.visionforge.solid.three.ThreeCanvas
import space.kscience.visionforge.solid.three.ThreePlugin import space.kscience.visionforge.solid.three.ThreePlugin
@ -63,7 +62,7 @@ private fun SimpleThreeView(
@Composable @Composable
public fun ThreeView( public fun ThreeView(
solids: Solids, context: Context,
solid: Solid?, solid: Solid?,
initialSelected: Name? = null, initialSelected: Name? = null,
options: Canvas3DOptions? = null, options: Canvas3DOptions? = null,
@ -114,7 +113,7 @@ public fun ThreeView(
} }
} }
} else { } else {
SimpleThreeView(solids.context, optionsSnapshot, solid, selected) SimpleThreeView(context, optionsSnapshot, solid, selected)
} }
key(selected) { key(selected) {
@ -136,7 +135,7 @@ public fun ThreeView(
NameCrumbs(selected) { selected = it } NameCrumbs(selected) { selected = it }
Hr() Hr()
PropertyEditor( PropertyEditor(
scope = solids.context, scope = context,
rootMeta = vision.properties.root(), rootMeta = vision.properties.root(),
getPropertyState = { name -> getPropertyState = { name ->
if (vision.properties.own?.get(name) != null) { if (vision.properties.own?.get(name) != null) {
@ -189,6 +188,6 @@ public fun ThreeView(
} }
} }
} else { } else {
SimpleThreeView(solids.context, optionsSnapshot, solid, selected) SimpleThreeView(context, optionsSnapshot, solid, selected)
} }
} }