Refactor VisionForge global

This commit is contained in:
Alexander Nozik 2021-02-26 13:03:40 +03:00
parent a5bfa0f147
commit bc15d9241b
26 changed files with 136 additions and 138 deletions
build.gradle.kts
demo
jupyter-playground/src/main/kotlin/hep/dataforge/playground
playground/src
settings.gradle.kts
visionforge-core/src
commonMain/kotlin/hep/dataforge/vision
jsMain/kotlin/hep/dataforge/vision
jvmMain/kotlin/hep/dataforge/vision
visionforge-plotly/src
commonMain/kotlin/hep/dataforge/vision/plotly
jsMain/kotlin/hep/dataforge/vision/plotly
jvmMain/kotlin/hep/dataforge/vision/plotly
visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid
visionforge-threejs
src/main/kotlin/hep/dataforge/vision/solid/three
visionforge-threejs-server/src
jsMain/kotlin/hep/dataforge/vision/three/server
jvmMain/kotlin/hep/dataforge/vision/three/server

@ -12,7 +12,6 @@ val fxVersion by extra("14")
allprojects {
repositories {
mavenLocal()
mavenCentral()
jcenter()
maven("https://kotlin.bintray.com/kotlin-js-wrappers")

@ -3,15 +3,14 @@ package hep.dataforge.playground
import hep.dataforge.misc.DFExperimental
import hep.dataforge.vision.Vision
import hep.dataforge.vision.VisionForge
import hep.dataforge.vision.VisionManager
import hep.dataforge.vision.gdml.toVision
import hep.dataforge.vision.html.HtmlVisionFragment
import hep.dataforge.vision.html.Page
import hep.dataforge.vision.html.embedVisionFragment
import hep.dataforge.vision.html.fragment
import hep.dataforge.vision.plotly.toVision
import hep.dataforge.vision.plotly.withPlotly
import hep.dataforge.vision.solid.withSolids
import hep.dataforge.vision.plotly.usePlotly
import hep.dataforge.vision.solid.useSolids
import hep.dataforge.vision.visionManager
import kotlinx.html.div
import kotlinx.html.id
@ -44,7 +43,7 @@ internal class VisionForgePlayGroundForJupyter : JupyterIntegration() {
}
script {
type = "text/javascript"
unsafe { +"renderVisionsAt(\"$id\");" }
unsafe { +"VisionForge.renderVisionsAt(\"$id\");" }
}
}
@ -52,7 +51,8 @@ internal class VisionForgePlayGroundForJupyter : JupyterIntegration() {
resource(jsResource)
onLoaded {
VisionForge.withPlotly().withSolids()
VisionForge.useSolids()
VisionForge.usePlotly()
}
import(
@ -66,14 +66,14 @@ internal class VisionForgePlayGroundForJupyter : JupyterIntegration() {
import("hep.dataforge.vision.VisionForge")
render<Gdml> { gdmlModel ->
val fragment = VisionManager.fragment {
val fragment = VisionForge.fragment {
vision(gdmlModel.toVision())
}
HTML(produceHtmlVisionString(fragment))
}
render<Vision> { vision ->
val fragment = VisionManager.fragment {
val fragment = VisionForge.fragment {
vision(vision)
}
@ -81,7 +81,7 @@ internal class VisionForgePlayGroundForJupyter : JupyterIntegration() {
}
render<Plot> { plot ->
val fragment = VisionManager.fragment {
val fragment = VisionForge.fragment {
vision(plot.toVision())
}

@ -1,9 +1,8 @@
//import hep.dataforge.vision.plotly.withPlotly
import hep.dataforge.vision.VisionForge
import hep.dataforge.vision.plotly.usePlotly
import hep.dataforge.vision.renderVisionsInWindow
import hep.dataforge.vision.solid.three.useThreeJs
fun main() {
fun main(): Unit = VisionForge.run{
usePlotly()
useThreeJs()
renderVisionsInWindow()

@ -2,11 +2,11 @@ package hep.dataforge.vision.examples
import hep.dataforge.misc.DFExperimental
import hep.dataforge.vision.VisionForge
import hep.dataforge.vision.VisionManager
import hep.dataforge.vision.gdml.toVision
import hep.dataforge.vision.html.ResourceLocation
import hep.dataforge.vision.html.fragment
import hep.dataforge.vision.solid.withSolids
import hep.dataforge.vision.invoke
import hep.dataforge.vision.solid.useSolids
import space.kscience.gdml.*
internal val cubes = Gdml {
@ -60,12 +60,12 @@ internal val cubes = Gdml {
}
@DFExperimental
fun main() {
val content = VisionManager.fragment {
fun main() = VisionForge {
val content = VisionForge.fragment {
vision("canvas") {
cubes.toVision()
}
}
VisionForge.withSolids().makeVisionFile(content, resourceLocation = ResourceLocation.SYSTEM)
useSolids()
makeVisionFile(content, resourceLocation = ResourceLocation.SYSTEM)
}

@ -2,25 +2,25 @@ package hep.dataforge.vision.examples
import hep.dataforge.misc.DFExperimental
import hep.dataforge.vision.VisionForge
import hep.dataforge.vision.VisionManager
import hep.dataforge.vision.html.ResourceLocation
import hep.dataforge.vision.html.fragment
import hep.dataforge.vision.invoke
import hep.dataforge.vision.plotly.plotly
import hep.dataforge.vision.plotly.withPlotly
import hep.dataforge.vision.plotly.usePlotly
import kscience.plotly.scatter
@DFExperimental
fun main() {
val fragment = VisionManager.fragment {
fun main() = VisionForge {
val fragment = fragment {
vision {
plotly {
scatter {
x(1,2,3)
y(5,8,7)
x(1, 2, 3)
y(5, 8, 7)
}
}
}
}
VisionForge.withPlotly().makeVisionFile(fragment, resourceLocation = ResourceLocation.SYSTEM)
usePlotly()
makeVisionFile(fragment, resourceLocation = ResourceLocation.SYSTEM)
}

@ -2,19 +2,19 @@ package hep.dataforge.vision.examples
import hep.dataforge.misc.DFExperimental
import hep.dataforge.vision.VisionForge
import hep.dataforge.vision.VisionManager
import hep.dataforge.vision.html.ResourceLocation
import hep.dataforge.vision.html.fragment
import hep.dataforge.vision.invoke
import hep.dataforge.vision.solid.*
import kotlinx.html.h1
import java.nio.file.Paths
import kotlin.random.Random
@OptIn(DFExperimental::class)
fun main() {
fun main() = VisionForge.invoke {
val random = Random(112233)
val fragment = VisionManager.fragment {
val fragment = fragment {
h1 { +"Happy new year!" }
vision {
solid {
@ -33,8 +33,8 @@ fun main() {
}
}
}
VisionForge.withSolids().makeVisionFile(
useSolids()
makeVisionFile(
fragment,
Paths.get("randomSpheres.html"),
resourceLocation = ResourceLocation.EMBED

@ -1,8 +1,8 @@
package hep.dataforge.vision.examples
import hep.dataforge.context.Context
import hep.dataforge.misc.DFExperimental
import hep.dataforge.vision.Vision
import hep.dataforge.vision.VisionForge
import hep.dataforge.vision.html.HtmlVisionFragment
import hep.dataforge.vision.html.ResourceLocation
import hep.dataforge.vision.html.page
@ -19,7 +19,7 @@ public fun VisionServer.usePlayground(): Unit {
}
@DFExperimental
public fun Context.makeVisionFile(
public fun VisionForge.makeVisionFile(
content: HtmlVisionFragment,
path: Path? = null,
title: String = "VisionForge page",
@ -33,7 +33,7 @@ public fun Context.makeVisionFile(
}
@DFExperimental
public fun Context.makeVisionFile(
public fun VisionForge.makeVisionFile(
vision: Vision,
path: Path? = null,
title: String = "VisionForge page",

@ -2,22 +2,22 @@ package hep.dataforge.vision.examples
import hep.dataforge.misc.DFExperimental
import hep.dataforge.vision.VisionForge
import hep.dataforge.vision.VisionManager
import hep.dataforge.vision.html.ResourceLocation
import hep.dataforge.vision.html.fragment
import hep.dataforge.vision.invoke
import hep.dataforge.vision.solid.box
import hep.dataforge.vision.solid.solid
import hep.dataforge.vision.solid.withSolids
import hep.dataforge.vision.solid.useSolids
@DFExperimental
fun main() {
val content = VisionManager.fragment {
fun main() = VisionForge.invoke {
val content = fragment {
vision("canvas") {
solid {
box(100, 100, 100)
}
}
}
VisionForge.withSolids().makeVisionFile(content, resourceLocation = ResourceLocation.SYSTEM)
useSolids()
makeVisionFile(content, resourceLocation = ResourceLocation.SYSTEM)
}

@ -3,10 +3,8 @@ pluginManagement {
val toolsVersion = "0.8.3"
repositories {
mavenLocal()
maven("https://repo.kotlin.link")
mavenCentral()
jcenter()
gradlePluginPortal()
}

@ -1,8 +1,12 @@
package hep.dataforge.vision
import hep.dataforge.context.Context
import hep.dataforge.context.PluginManager
/**
* A drop-in replacement for [Global] for VisionForge activities
*/
public expect val VisionForge: Context
public expect object VisionForge
public expect val VisionForge.context: Context
public val VisionForge.plugins: PluginManager get() = context.plugins
public val VisionForge.visionManager: VisionManager get() = plugins.fetch(VisionManager)

@ -26,8 +26,9 @@ public open class VisionGroupBase(
override val children: Map<NameToken, Vision> get() = childrenInternal
init {
childrenInternal.values.forEach {
it.parent = this
childrenInternal.forEach { (token, child) ->
if (child.parent != null && child.parent != this) error("Can't reassign existing parent for child $token")
child.parent = this
}
}
@ -78,7 +79,7 @@ public open class VisionGroupBase(
childrenInternal[token] = child
}
child.parent !== this -> {
error("Can't reassign existing parent for $child")
error("Can't reassign existing parent for child $token")
}
}
if (before != child) {

@ -1,7 +1,7 @@
package hep.dataforge.vision.html
import hep.dataforge.misc.DFExperimental
import hep.dataforge.vision.VisionManager
import hep.dataforge.vision.VisionForge
import kotlinx.html.FlowContent
import kotlinx.html.TagConsumer
@ -18,4 +18,4 @@ public fun FlowContent.fragment(fragment: HtmlFragment) {
public typealias HtmlVisionFragment = VisionTagConsumer<*>.() -> Unit
@DFExperimental
public fun VisionManager.Companion.fragment(content: HtmlVisionFragment): VisionTagConsumer<*>.() -> Unit = content
public fun VisionForge.fragment(content: HtmlVisionFragment): VisionTagConsumer<*>.() -> Unit = content

@ -2,9 +2,10 @@ package hep.dataforge.vision.html
import hep.dataforge.context.Context
import hep.dataforge.misc.DFExperimental
import hep.dataforge.vision.VisionForge
import hep.dataforge.vision.context
import hep.dataforge.vision.visionManager
import kotlinx.html.*
import kotlinx.html.stream.createHTML
public data class Page(
public val context: Context,
@ -30,8 +31,8 @@ public data class Page(
@DFExperimental
public fun Context.page(
public fun VisionForge.page(
title: String,
content: HtmlVisionFragment,
vararg headers: Pair<String, HtmlFragment>,
): Page = Page(this, title, mapOf(*headers), content)
): Page = Page(context, title, mapOf(*headers), content)

@ -1,11 +1,8 @@
package hep.dataforge.vision.client
package hep.dataforge.vision
import hep.dataforge.context.*
import hep.dataforge.meta.Meta
import hep.dataforge.meta.MetaSerializer
import hep.dataforge.vision.Vision
import hep.dataforge.vision.VisionChange
import hep.dataforge.vision.VisionManager
import hep.dataforge.vision.html.VisionTagConsumer
import hep.dataforge.vision.html.VisionTagConsumer.Companion.OUTPUT_CONNECT_ATTRIBUTE
import hep.dataforge.vision.html.VisionTagConsumer.Companion.OUTPUT_ENDPOINT_ATTRIBUTE

@ -1,38 +0,0 @@
package hep.dataforge.vision
import hep.dataforge.context.Context
import hep.dataforge.context.Global
import hep.dataforge.vision.client.VisionClient
import hep.dataforge.vision.client.renderAllVisions
import hep.dataforge.vision.client.renderAllVisionsAt
import kotlinx.browser.document
import kotlinx.browser.window
public actual val VisionForge: Context = Global.context("VisionForge").apply {
plugins.fetch(VisionManager)
plugins.fetch(VisionClient)
}
/**
* Render all visions in this [window] using current global state of [VisionForge]
*/
@JsExport
public fun renderVisionsInWindow() {
window.onload = {
VisionForge.plugins[VisionClient]?.renderAllVisions()
}
}
/**
* Render all visions in an element with a given [id]
*/
@JsExport
public fun renderVisionsAt(id: String) {
val element = document.getElementById(id)
if (element != null) {
VisionForge.plugins[VisionClient]?.renderAllVisionsAt(element)
} else {
console.warn("Element with id $id not found")
}
}

@ -1,8 +1,7 @@
package hep.dataforge.vision.client
package hep.dataforge.vision
import hep.dataforge.meta.Meta
import hep.dataforge.misc.Type
import hep.dataforge.vision.Vision
import org.w3c.dom.Element
@Type(ElementVisionRenderer.TYPE)

@ -0,0 +1,37 @@
package hep.dataforge.vision
import hep.dataforge.context.Context
import kotlinx.browser.document
import kotlinx.browser.window
@JsExport
public actual object VisionForge{
/**
* Render all visions in this [window] using current global state of [VisionForge]
*/
public fun renderVisionsInWindow() {
window.onload = {
visionClient.renderAllVisions()
}
}
/**
* Render all visions in an element with a given [id]
*/
public fun renderVisionsAt(id: String) {
val element = document.getElementById(id)
if (element != null) {
visionClient.renderAllVisionsAt(element)
} else {
console.warn("Element with id $id not found")
}
}
}
private val visionForgeContext = Context("VisionForge"){
plugin(VisionClient)
}
public actual val VisionForge.context: Context get() = visionForgeContext
public val VisionForge.visionClient: VisionClient get() = plugins.fetch(VisionClient)

@ -1,8 +0,0 @@
package hep.dataforge.vision
import hep.dataforge.context.Context
import hep.dataforge.context.Global
public actual val VisionForge: Context = Global.context("VisionForge").apply{
plugins.fetch(VisionManager)
}

@ -0,0 +1,13 @@
package hep.dataforge.vision
import hep.dataforge.context.Context
import hep.dataforge.misc.DFExperimental
public actual object VisionForge
private val visionForgeContext = Context("VisionForge")
public actual val VisionForge.context: Context get() = visionForgeContext
@DFExperimental
public operator fun VisionForge.invoke(block: VisionForge.() -> Unit): Unit = run(block)

@ -1,15 +1,27 @@
package hep.dataforge.vision.plotly
import hep.dataforge.context.PluginFactory
import hep.dataforge.vision.Vision
import hep.dataforge.vision.VisionForge
import hep.dataforge.vision.VisionPlugin
import hep.dataforge.vision.plugins
import kotlinx.serialization.modules.SerializersModule
import kotlinx.serialization.modules.polymorphic
import kotlinx.serialization.modules.subclass
public expect class PlotlyPlugin : VisionPlugin
public expect class PlotlyPlugin : VisionPlugin{
public companion object: PluginFactory<PlotlyPlugin>
}
internal val plotlySerializersModule = SerializersModule {
polymorphic(Vision::class) {
subclass(VisionOfPlotly.serializer())
}
}
/**
* Ensure that [PlotlyPlugin] is loaded in the global [VisionForge] context
*/
public fun VisionForge.usePlotly() {
plugins.fetch(PlotlyPlugin)
}

@ -6,11 +6,10 @@ import hep.dataforge.context.PluginTag
import hep.dataforge.meta.Meta
import hep.dataforge.names.Name
import hep.dataforge.names.asName
import hep.dataforge.vision.ElementVisionRenderer
import hep.dataforge.vision.Vision
import hep.dataforge.vision.VisionForge
import hep.dataforge.vision.VisionClient
import hep.dataforge.vision.VisionPlugin
import hep.dataforge.vision.client.ElementVisionRenderer
import hep.dataforge.vision.client.VisionClient
import kotlinx.serialization.modules.SerializersModule
import kscience.plotly.PlotlyConfig
import kscience.plotly.plot
@ -42,17 +41,9 @@ public actual class PlotlyPlugin : VisionPlugin(), ElementVisionRenderer {
}
}
public companion object : PluginFactory<PlotlyPlugin> {
public actual companion object : PluginFactory<PlotlyPlugin> {
override val tag: PluginTag = PluginTag("vision.plotly", PluginTag.DATAFORGE_GROUP)
override val type: KClass<PlotlyPlugin> = PlotlyPlugin::class
override fun invoke(meta: Meta, context: Context): PlotlyPlugin = PlotlyPlugin()
}
}
/**
* Ensure that [PlotlyPlugin] is loaded in the global [VisionForge] context
*/
@JsExport
public fun usePlotly() {
VisionForge.plugins.fetch(PlotlyPlugin)
}

@ -15,13 +15,9 @@ public actual class PlotlyPlugin : VisionPlugin(), Plugin {
override val visionSerializersModule: SerializersModule get() = plotlySerializersModule
public companion object : PluginFactory<PlotlyPlugin> {
public actual companion object : PluginFactory<PlotlyPlugin> {
override val tag: PluginTag = PluginTag("vision.plotly", PluginTag.DATAFORGE_GROUP)
override val type: KClass<PlotlyPlugin> = PlotlyPlugin::class
override fun invoke(meta: Meta, context: Context): PlotlyPlugin = PlotlyPlugin()
}
}
public fun Context.withPlotly(): Context = apply {
plugins.fetch(PlotlyPlugin)
}

@ -70,6 +70,7 @@ public class SolidManager(meta: Meta) : VisionPlugin(meta) {
@DFExperimental
public inline fun VisionOutput.solid(block: SolidGroup.() -> Unit): SolidGroup = SolidGroup().apply(block)
public fun Context.withSolids(): Context = apply {
@DFExperimental
public fun VisionForge.useSolids(): Unit{
plugins.fetch(SolidManager)
}
}

@ -3,13 +3,10 @@ package hep.dataforge.vision.solid.three
import hep.dataforge.context.*
import hep.dataforge.meta.Meta
import hep.dataforge.names.*
import hep.dataforge.vision.Vision
import hep.dataforge.vision.VisionForge
import hep.dataforge.vision.client.ElementVisionRenderer
import hep.dataforge.vision.onPropertyChange
import hep.dataforge.vision.*
import hep.dataforge.vision.solid.*
import hep.dataforge.vision.solid.specifications.Canvas3DOptions
import hep.dataforge.vision.visible
import hep.dataforge.vision.solid.three.set
import info.laht.threekt.core.Object3D
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.launchIn
@ -155,9 +152,8 @@ public class ThreePlugin : AbstractPlugin(), ElementVisionRenderer {
/**
* Ensure that [ThreePlugin] is loaded in the global [VisionForge] context
*/
@JsExport
public fun useThreeJs() {
VisionForge.plugins.fetch(ThreePlugin)
public fun VisionForge.useThreeJs() {
plugins.fetch(ThreePlugin)
}
public fun ThreePlugin.render(

@ -1,9 +1,9 @@
package hep.dataforge.vision.three.server
import hep.dataforge.vision.renderVisionsInWindow
import hep.dataforge.vision.VisionForge
import hep.dataforge.vision.solid.three.useThreeJs
public fun main() {
public fun main(): Unit = VisionForge.run {
useThreeJs()
renderVisionsInWindow()
}

@ -1,7 +1,7 @@
package hep.dataforge.vision.three.server
import hep.dataforge.context.Context
import hep.dataforge.misc.DFExperimental
import hep.dataforge.vision.VisionForge
import hep.dataforge.vision.html.HtmlVisionFragment
import hep.dataforge.vision.html.ResourceLocation
import hep.dataforge.vision.html.page
@ -16,7 +16,7 @@ public fun VisionServer.useThreeJs(): Unit {
}
@DFExperimental
public fun Context.makeThreeJsFile(
public fun VisionForge.makeThreeJsFile(
content: HtmlVisionFragment,
path: Path? = null,
title: String = "VisionForge page",