0.2.0 #71
@ -36,13 +36,13 @@ internal class VisionForgePlayGroundForJupyter : JupyterPluginBase(
|
|||||||
|
|
||||||
render<Gdml> { gdmlModel ->
|
render<Gdml> { gdmlModel ->
|
||||||
handler.produceHtml {
|
handler.produceHtml {
|
||||||
vision(gdmlModel.toVision())
|
vision { gdmlModel.toVision() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render<Plot> { plot ->
|
render<Plot> { plot ->
|
||||||
handler.produceHtml {
|
handler.produceHtml {
|
||||||
vision(plot.asVision())
|
vision { plot.asVision() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package space.kscience.visionforge.examples
|
package space.kscience.visionforge.examples
|
||||||
|
|
||||||
import kotlinx.html.h2
|
import kotlinx.html.h2
|
||||||
import space.kscience.dataforge.context.Context
|
|
||||||
import space.kscience.dataforge.values.ValueType
|
import space.kscience.dataforge.values.ValueType
|
||||||
import space.kscience.plotly.layout
|
import space.kscience.plotly.layout
|
||||||
import space.kscience.plotly.models.ScatterMode
|
import space.kscience.plotly.models.ScatterMode
|
||||||
@ -10,25 +9,15 @@ import space.kscience.plotly.scatter
|
|||||||
import space.kscience.tables.ColumnHeader
|
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.PlotlyPlugin
|
|
||||||
import space.kscience.visionforge.plotly.plotly
|
import space.kscience.visionforge.plotly.plotly
|
||||||
import space.kscience.visionforge.solid.Solids
|
|
||||||
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.z
|
import space.kscience.visionforge.solid.z
|
||||||
import space.kscience.visionforge.tables.TableVisionPlugin
|
|
||||||
import space.kscience.visionforge.tables.columnTable
|
import space.kscience.visionforge.tables.columnTable
|
||||||
import java.nio.file.Paths
|
import java.nio.file.Paths
|
||||||
|
|
||||||
|
|
||||||
fun main() {
|
fun main() = makeVisionFile(
|
||||||
val context = Context {
|
|
||||||
plugin(Solids)
|
|
||||||
plugin(PlotlyPlugin)
|
|
||||||
plugin(TableVisionPlugin)
|
|
||||||
}
|
|
||||||
|
|
||||||
context.makeVisionFile(
|
|
||||||
Paths.get("VisionForgeDemo.html"),
|
Paths.get("VisionForgeDemo.html"),
|
||||||
resourceLocation = ResourceLocation.EMBED
|
resourceLocation = ResourceLocation.EMBED
|
||||||
) {
|
) {
|
||||||
@ -183,4 +172,3 @@ fun main() {
|
|||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
@ -3,21 +3,19 @@ package space.kscience.visionforge.examples
|
|||||||
import kotlinx.html.*
|
import kotlinx.html.*
|
||||||
import space.kscience.dataforge.context.Global
|
import space.kscience.dataforge.context.Global
|
||||||
import space.kscience.dataforge.context.fetch
|
import space.kscience.dataforge.context.fetch
|
||||||
import space.kscience.dataforge.names.asName
|
|
||||||
import space.kscience.visionforge.VisionManager
|
import space.kscience.visionforge.VisionManager
|
||||||
|
import space.kscience.visionforge.html.Page
|
||||||
import space.kscience.visionforge.html.formFragment
|
import space.kscience.visionforge.html.formFragment
|
||||||
import space.kscience.visionforge.onPropertyChange
|
import space.kscience.visionforge.onPropertyChange
|
||||||
import space.kscience.visionforge.three.server.close
|
import space.kscience.visionforge.server.close
|
||||||
import space.kscience.visionforge.three.server.openInBrowser
|
import space.kscience.visionforge.server.openInBrowser
|
||||||
import space.kscience.visionforge.three.server.serve
|
import space.kscience.visionforge.server.serve
|
||||||
import space.kscience.visionforge.three.server.useScript
|
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
val visionManager = Global.fetch(VisionManager)
|
val visionManager = Global.fetch(VisionManager)
|
||||||
|
|
||||||
val server = visionManager.serve {
|
val server = visionManager.serve {
|
||||||
useScript("js/visionforge-playground.js")
|
page(header = Page.scriptHeader("js/visionforge-playground.js")) {
|
||||||
page {
|
|
||||||
val form = formFragment("form") {
|
val form = formFragment("form") {
|
||||||
label {
|
label {
|
||||||
htmlFor = "fname"
|
htmlFor = "fname"
|
||||||
@ -50,7 +48,7 @@ fun main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vision("form".asName(), form)
|
vision("form") { form }
|
||||||
form.onPropertyChange {
|
form.onPropertyChange {
|
||||||
println(this)
|
println(this)
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,13 @@
|
|||||||
package space.kscience.visionforge.examples
|
package space.kscience.visionforge.examples
|
||||||
|
|
||||||
import space.kscience.dataforge.context.Context
|
|
||||||
import space.kscience.gdml.GdmlShowCase
|
import space.kscience.gdml.GdmlShowCase
|
||||||
import space.kscience.visionforge.gdml.toVision
|
import space.kscience.visionforge.gdml.toVision
|
||||||
import space.kscience.visionforge.html.ResourceLocation
|
import space.kscience.visionforge.html.ResourceLocation
|
||||||
import space.kscience.visionforge.solid.Solids
|
import space.kscience.visionforge.solid.Solids
|
||||||
|
|
||||||
fun main() {
|
fun main() = makeVisionFile(resourceLocation = ResourceLocation.SYSTEM){
|
||||||
val context = Context {
|
|
||||||
plugin(Solids)
|
|
||||||
}
|
|
||||||
|
|
||||||
context.makeVisionFile(resourceLocation = ResourceLocation.SYSTEM){
|
|
||||||
vision("canvas") {
|
vision("canvas") {
|
||||||
|
requirePlugin(Solids)
|
||||||
GdmlShowCase.cubes().toVision()
|
GdmlShowCase.cubes().toVision()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
@ -1,6 +1,5 @@
|
|||||||
package space.kscience.visionforge.examples
|
package space.kscience.visionforge.examples
|
||||||
|
|
||||||
import space.kscience.dataforge.context.Context
|
|
||||||
import space.kscience.gdml.*
|
import space.kscience.gdml.*
|
||||||
import space.kscience.visionforge.gdml.toVision
|
import space.kscience.visionforge.gdml.toVision
|
||||||
import space.kscience.visionforge.html.ResourceLocation
|
import space.kscience.visionforge.html.ResourceLocation
|
||||||
@ -10,13 +9,9 @@ import space.kscience.visionforge.solid.invoke
|
|||||||
import space.kscience.visionforge.visible
|
import space.kscience.visionforge.visible
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
|
|
||||||
fun main() {
|
fun main() = makeVisionFile(Path.of("curves.html"), resourceLocation = ResourceLocation.EMBED) {
|
||||||
val context = Context {
|
|
||||||
plugin(Solids)
|
|
||||||
}
|
|
||||||
|
|
||||||
context.makeVisionFile(Path.of("curves.html"), resourceLocation = ResourceLocation.EMBED) {
|
|
||||||
vision("canvas") {
|
vision("canvas") {
|
||||||
|
requirePlugin(Solids)
|
||||||
Gdml {
|
Gdml {
|
||||||
// geometry variables
|
// geometry variables
|
||||||
val worldSize = 500
|
val worldSize = 500
|
||||||
@ -241,4 +236,3 @@ fun main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
@ -1,16 +1,12 @@
|
|||||||
package space.kscience.visionforge.examples
|
package space.kscience.visionforge.examples
|
||||||
|
|
||||||
import space.kscience.dataforge.context.Context
|
|
||||||
import space.kscience.gdml.GdmlShowCase
|
import space.kscience.gdml.GdmlShowCase
|
||||||
import space.kscience.visionforge.gdml.toVision
|
import space.kscience.visionforge.gdml.toVision
|
||||||
import space.kscience.visionforge.solid.Solids
|
import space.kscience.visionforge.solid.Solids
|
||||||
|
|
||||||
fun main() {
|
fun main() = makeVisionFile {
|
||||||
val context = Context {
|
vision("canvas") {
|
||||||
plugin(Solids)
|
requirePlugin(Solids)
|
||||||
}
|
GdmlShowCase.babyIaxo().toVision()
|
||||||
|
|
||||||
context.makeVisionFile {
|
|
||||||
vision("canvas") { GdmlShowCase.babyIaxo().toVision() }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,16 +1,10 @@
|
|||||||
package space.kscience.visionforge.examples
|
package space.kscience.visionforge.examples
|
||||||
|
|
||||||
import space.kscience.dataforge.context.Context
|
|
||||||
import space.kscience.plotly.scatter
|
import space.kscience.plotly.scatter
|
||||||
import space.kscience.visionforge.html.ResourceLocation
|
import space.kscience.visionforge.html.ResourceLocation
|
||||||
import space.kscience.visionforge.plotly.PlotlyPlugin
|
|
||||||
import space.kscience.visionforge.plotly.plotly
|
import space.kscience.visionforge.plotly.plotly
|
||||||
|
|
||||||
fun main() {
|
fun main() = makeVisionFile(resourceLocation = ResourceLocation.SYSTEM) {
|
||||||
val context = Context {
|
|
||||||
plugin(PlotlyPlugin)
|
|
||||||
}
|
|
||||||
context.makeVisionFile(resourceLocation = ResourceLocation.SYSTEM){
|
|
||||||
vision {
|
vision {
|
||||||
plotly {
|
plotly {
|
||||||
scatter {
|
scatter {
|
||||||
@ -20,4 +14,3 @@ fun main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
@ -2,20 +2,14 @@ package space.kscience.visionforge.examples
|
|||||||
|
|
||||||
import kotlinx.html.div
|
import kotlinx.html.div
|
||||||
import kotlinx.html.h1
|
import kotlinx.html.h1
|
||||||
import space.kscience.dataforge.context.Context
|
|
||||||
import space.kscience.visionforge.html.ResourceLocation
|
import space.kscience.visionforge.html.ResourceLocation
|
||||||
import space.kscience.visionforge.solid.*
|
import space.kscience.visionforge.solid.*
|
||||||
import java.nio.file.Paths
|
import java.nio.file.Paths
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
|
|
||||||
fun main() {
|
private val random = Random(112233)
|
||||||
val context = Context {
|
|
||||||
plugin(Solids)
|
|
||||||
}
|
|
||||||
|
|
||||||
val random = Random(112233)
|
fun main() = makeVisionFile(
|
||||||
|
|
||||||
context.makeVisionFile(
|
|
||||||
Paths.get("randomSpheres.html"),
|
Paths.get("randomSpheres.html"),
|
||||||
resourceLocation = ResourceLocation.SYSTEM
|
resourceLocation = ResourceLocation.SYSTEM
|
||||||
) {
|
) {
|
||||||
@ -38,4 +32,3 @@ fun main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
@ -3,7 +3,6 @@ package space.kscience.visionforge.examples
|
|||||||
import ru.mipt.npm.root.DGeoManager
|
import ru.mipt.npm.root.DGeoManager
|
||||||
import ru.mipt.npm.root.serialization.TGeoManager
|
import ru.mipt.npm.root.serialization.TGeoManager
|
||||||
import ru.mipt.npm.root.toSolid
|
import ru.mipt.npm.root.toSolid
|
||||||
import space.kscience.dataforge.context.Context
|
|
||||||
import space.kscience.dataforge.meta.Meta
|
import space.kscience.dataforge.meta.Meta
|
||||||
import space.kscience.dataforge.meta.get
|
import space.kscience.dataforge.meta.get
|
||||||
import space.kscience.dataforge.meta.isLeaf
|
import space.kscience.dataforge.meta.isLeaf
|
||||||
@ -22,11 +21,6 @@ private fun Meta.countTypes(): Sequence<String> = sequence {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
val context = Context {
|
|
||||||
plugin(Solids)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
val string = ZipInputStream(TGeoManager::class.java.getResourceAsStream("/root/BM@N_geometry.zip")!!).use {
|
val string = ZipInputStream(TGeoManager::class.java.getResourceAsStream("/root/BM@N_geometry.zip")!!).use {
|
||||||
it.nextEntry
|
it.nextEntry
|
||||||
it.readAllBytes().decodeToString()
|
it.readAllBytes().decodeToString()
|
||||||
@ -45,8 +39,9 @@ fun main() {
|
|||||||
Paths.get("BM@N.vf.json").writeText(Solids.encodeToString(solid))
|
Paths.get("BM@N.vf.json").writeText(Solids.encodeToString(solid))
|
||||||
//println(Solids.encodeToString(solid))
|
//println(Solids.encodeToString(solid))
|
||||||
|
|
||||||
context.makeVisionFile {
|
makeVisionFile {
|
||||||
vision("canvas") {
|
vision("canvas") {
|
||||||
|
requirePlugin(Solids)
|
||||||
solid
|
solid
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,34 +1,25 @@
|
|||||||
package space.kscience.visionforge.examples
|
package space.kscience.visionforge.examples
|
||||||
|
|
||||||
import space.kscience.dataforge.context.Context
|
import space.kscience.dataforge.context.Global
|
||||||
import space.kscience.dataforge.misc.DFExperimental
|
import space.kscience.visionforge.html.HtmlVisionFragment
|
||||||
|
import space.kscience.visionforge.html.Page
|
||||||
import space.kscience.visionforge.html.ResourceLocation
|
import space.kscience.visionforge.html.ResourceLocation
|
||||||
import space.kscience.visionforge.html.VisionTagConsumer
|
import space.kscience.visionforge.html.importScriptHeader
|
||||||
import space.kscience.visionforge.html.page
|
|
||||||
import space.kscience.visionforge.html.scriptHeader
|
|
||||||
import space.kscience.visionforge.makeFile
|
import space.kscience.visionforge.makeFile
|
||||||
import space.kscience.visionforge.three.server.VisionServer
|
|
||||||
import space.kscience.visionforge.three.server.useScript
|
|
||||||
import space.kscience.visionforge.visionManager
|
|
||||||
import java.awt.Desktop
|
import java.awt.Desktop
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
|
|
||||||
|
public fun makeVisionFile(
|
||||||
public fun VisionServer.usePlayground(): Unit {
|
|
||||||
useScript("js/visionforge-playground.js")
|
|
||||||
}
|
|
||||||
|
|
||||||
@OptIn(DFExperimental::class)
|
|
||||||
public fun Context.makeVisionFile(
|
|
||||||
path: Path? = null,
|
path: Path? = null,
|
||||||
title: String = "VisionForge page",
|
title: String = "VisionForge page",
|
||||||
resourceLocation: ResourceLocation = ResourceLocation.SYSTEM,
|
resourceLocation: ResourceLocation = ResourceLocation.SYSTEM,
|
||||||
show: Boolean = true,
|
show: Boolean = true,
|
||||||
content: VisionTagConsumer<*>.() -> Unit,
|
content: HtmlVisionFragment,
|
||||||
): Unit {
|
): Unit {
|
||||||
val actualPath = visionManager.page(title, content = content).makeFile(path) { actualPath ->
|
val actualPath = Page(Global, content = content).makeFile(path) { actualPath ->
|
||||||
mapOf(
|
mapOf(
|
||||||
"playground" to scriptHeader("js/visionforge-playground.js", resourceLocation, actualPath),
|
"title" to Page.title(title),
|
||||||
|
"playground" to Page.importScriptHeader("js/visionforge-playground.js", resourceLocation, actualPath),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (show) Desktop.getDesktop().browse(actualPath.toFile().toURI())
|
if (show) Desktop.getDesktop().browse(actualPath.toFile().toURI())
|
||||||
|
@ -1,15 +1,12 @@
|
|||||||
package space.kscience.visionforge.examples
|
package space.kscience.visionforge.examples
|
||||||
|
|
||||||
import space.kscience.dataforge.context.Context
|
|
||||||
import space.kscience.visionforge.html.ResourceLocation
|
import space.kscience.visionforge.html.ResourceLocation
|
||||||
import space.kscience.visionforge.solid.*
|
import space.kscience.visionforge.solid.box
|
||||||
|
import space.kscience.visionforge.solid.invoke
|
||||||
|
import space.kscience.visionforge.solid.material
|
||||||
|
import space.kscience.visionforge.solid.solid
|
||||||
|
|
||||||
fun main() {
|
fun main() = makeVisionFile(resourceLocation = ResourceLocation.SYSTEM) {
|
||||||
val context = Context {
|
|
||||||
plugin(Solids)
|
|
||||||
}
|
|
||||||
|
|
||||||
context.makeVisionFile(resourceLocation = ResourceLocation.SYSTEM){
|
|
||||||
vision("canvas") {
|
vision("canvas") {
|
||||||
solid {
|
solid {
|
||||||
box(100, 100, 100)
|
box(100, 100, 100)
|
||||||
@ -19,4 +16,3 @@ fun main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
@ -1,22 +1,17 @@
|
|||||||
package space.kscience.visionforge.examples
|
package space.kscience.visionforge.examples
|
||||||
|
|
||||||
import space.kscience.dataforge.context.Context
|
|
||||||
import space.kscience.dataforge.values.ValueType
|
import space.kscience.dataforge.values.ValueType
|
||||||
import space.kscience.tables.ColumnHeader
|
import space.kscience.tables.ColumnHeader
|
||||||
import space.kscience.tables.valueRow
|
import space.kscience.tables.valueRow
|
||||||
import space.kscience.visionforge.html.ResourceLocation
|
import space.kscience.visionforge.html.ResourceLocation
|
||||||
import space.kscience.visionforge.tables.TableVisionPlugin
|
|
||||||
import space.kscience.visionforge.tables.table
|
import space.kscience.visionforge.tables.table
|
||||||
import kotlin.math.pow
|
import kotlin.math.pow
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
val context = Context {
|
|
||||||
plugin(TableVisionPlugin)
|
|
||||||
}
|
|
||||||
val x by ColumnHeader.value(ValueType.NUMBER)
|
val x by ColumnHeader.value(ValueType.NUMBER)
|
||||||
val y by ColumnHeader.value(ValueType.NUMBER)
|
val y by ColumnHeader.value(ValueType.NUMBER)
|
||||||
|
|
||||||
context.makeVisionFile(resourceLocation = ResourceLocation.SYSTEM) {
|
makeVisionFile(resourceLocation = ResourceLocation.SYSTEM) {
|
||||||
vision {
|
vision {
|
||||||
table(x, y) {
|
table(x, y) {
|
||||||
repeat(100) {
|
repeat(100) {
|
||||||
|
@ -1,19 +1,22 @@
|
|||||||
package ru.mipt.npm.sat
|
package ru.mipt.npm.sat
|
||||||
|
|
||||||
|
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.*
|
||||||
import kotlinx.coroutines.delay
|
|
||||||
import kotlinx.coroutines.isActive
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlinx.html.div
|
import kotlinx.html.div
|
||||||
import kotlinx.html.h1
|
import kotlinx.html.h1
|
||||||
import space.kscience.dataforge.context.Context
|
import space.kscience.dataforge.context.Context
|
||||||
import space.kscience.dataforge.names.Name
|
import space.kscience.dataforge.names.Name
|
||||||
|
import space.kscience.visionforge.html.Page
|
||||||
|
import space.kscience.visionforge.html.plus
|
||||||
|
import space.kscience.visionforge.server.close
|
||||||
|
import space.kscience.visionforge.server.openInBrowser
|
||||||
|
import space.kscience.visionforge.server.serve
|
||||||
import space.kscience.visionforge.solid.*
|
import space.kscience.visionforge.solid.*
|
||||||
import space.kscience.visionforge.three.server.*
|
import space.kscience.visionforge.three.threeJsHeader
|
||||||
import space.kscience.visionforge.visionManager
|
import space.kscience.visionforge.visionManager
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
|
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
val satContext = Context("sat") {
|
val satContext = Context("sat") {
|
||||||
plugin(Solids)
|
plugin(Solids)
|
||||||
@ -23,20 +26,17 @@ fun main() {
|
|||||||
val sat = visionOfSatellite(ySegments = 3)
|
val sat = visionOfSatellite(ySegments = 3)
|
||||||
|
|
||||||
val server = satContext.visionManager.serve {
|
val server = satContext.visionManager.serve {
|
||||||
//use client library
|
page(header = Page.threeJsHeader + Page.styleSheetHeader("css/styles.css")) {
|
||||||
useThreeJs()
|
|
||||||
//use css
|
|
||||||
useCss("css/styles.css")
|
|
||||||
page {
|
|
||||||
div("flex-column") {
|
div("flex-column") {
|
||||||
h1 { +"Satellite detector demo" }
|
h1 { +"Satellite detector demo" }
|
||||||
vision(sat)
|
vision { sat }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
server.openInBrowser()
|
server.openInBrowser()
|
||||||
|
|
||||||
|
@OptIn(DelicateCoroutinesApi::class)
|
||||||
GlobalScope.launch {
|
GlobalScope.launch {
|
||||||
while (isActive) {
|
while (isActive) {
|
||||||
val randomLayer = Random.nextInt(1, 11)
|
val randomLayer = Random.nextInt(1, 11)
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package space.kscience.visionforge.solid.demo
|
package space.kscience.visionforge.solid.demo
|
||||||
|
|
||||||
import kotlinx.browser.document
|
import kotlinx.browser.document
|
||||||
import kotlinx.coroutines.GlobalScope
|
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.isActive
|
import kotlinx.coroutines.isActive
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@ -30,7 +29,8 @@ private class ThreeDemoApp : Application {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GlobalScope.launch {
|
|
||||||
|
launch {
|
||||||
while (isActive) {
|
while (isActive) {
|
||||||
delay(500)
|
delay(500)
|
||||||
boxes.forEach { box ->
|
boxes.forEach { box ->
|
||||||
|
@ -44,7 +44,7 @@ public abstract class JupyterPluginBase(final override val context: Context) : J
|
|||||||
|
|
||||||
render<Vision> { vision ->
|
render<Vision> { vision ->
|
||||||
handler.produceHtml {
|
handler.produceHtml {
|
||||||
vision(vision)
|
vision { vision }
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -62,7 +62,7 @@ public abstract class JupyterPluginBase(final override val context: Context) : J
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
fragment(fragment.formBody)
|
fragment(fragment.formBody)
|
||||||
vision(fragment.vision)
|
vision { fragment.vision }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,8 +18,8 @@ import space.kscience.dataforge.meta.string
|
|||||||
import space.kscience.visionforge.html.HtmlFormFragment
|
import space.kscience.visionforge.html.HtmlFormFragment
|
||||||
import space.kscience.visionforge.html.HtmlVisionFragment
|
import space.kscience.visionforge.html.HtmlVisionFragment
|
||||||
import space.kscience.visionforge.html.visionFragment
|
import space.kscience.visionforge.html.visionFragment
|
||||||
import space.kscience.visionforge.three.server.VisionServer
|
import space.kscience.visionforge.server.VisionServer
|
||||||
import space.kscience.visionforge.three.server.serve
|
import space.kscience.visionforge.server.serve
|
||||||
import space.kscience.visionforge.visionManager
|
import space.kscience.visionforge.visionManager
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -75,7 +75,7 @@ public class VisionForgeForNotebook(override val context: Context) : ContextAwar
|
|||||||
fragment: HtmlVisionFragment,
|
fragment: HtmlVisionFragment,
|
||||||
): String = server?.serveVisionsFromFragment("content[${counter++}]", fragment)
|
): String = server?.serveVisionsFromFragment("content[${counter++}]", fragment)
|
||||||
?: createHTML().apply {
|
?: createHTML().apply {
|
||||||
visionFragment(context.visionManager, fragment = fragment)
|
visionFragment(context, fragment = fragment)
|
||||||
}.finalize()
|
}.finalize()
|
||||||
|
|
||||||
public fun produceHtml(isolated: Boolean? = null, fragment: HtmlVisionFragment): MimeTypedResult =
|
public fun produceHtml(isolated: Boolean? = null, fragment: HtmlVisionFragment): MimeTypedResult =
|
||||||
|
@ -29,7 +29,9 @@ internal class GdmlForJupyter : JupyterPluginBase(
|
|||||||
)
|
)
|
||||||
|
|
||||||
render<Gdml> { gdmlModel ->
|
render<Gdml> { gdmlModel ->
|
||||||
handler.produceHtml { vision(gdmlModel.toVision()) }
|
handler.produceHtml {
|
||||||
|
vision { gdmlModel.toVision() }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ import kotlinx.html.stream.createHTML
|
|||||||
|
|
||||||
public typealias HtmlFragment = TagConsumer<*>.() -> Unit
|
public typealias HtmlFragment = TagConsumer<*>.() -> Unit
|
||||||
|
|
||||||
public fun HtmlFragment.render(): String = createHTML().apply(this).finalize()
|
public fun HtmlFragment.renderToString(): String = createHTML().apply(this).finalize()
|
||||||
|
|
||||||
public fun TagConsumer<*>.fragment(fragment: HtmlFragment) {
|
public fun TagConsumer<*>.fragment(fragment: HtmlFragment) {
|
||||||
fragment()
|
fragment()
|
||||||
@ -15,3 +15,8 @@ public fun TagConsumer<*>.fragment(fragment: HtmlFragment) {
|
|||||||
public fun FlowContent.fragment(fragment: HtmlFragment) {
|
public fun FlowContent.fragment(fragment: HtmlFragment) {
|
||||||
fragment(consumer)
|
fragment(consumer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public operator fun HtmlFragment.plus(other: HtmlFragment): HtmlFragment = {
|
||||||
|
this@plus()
|
||||||
|
other()
|
||||||
|
}
|
@ -1,6 +1,8 @@
|
|||||||
package space.kscience.visionforge.html
|
package space.kscience.visionforge.html
|
||||||
|
|
||||||
import kotlinx.html.*
|
import kotlinx.html.*
|
||||||
|
import space.kscience.dataforge.context.Context
|
||||||
|
import space.kscience.dataforge.context.Global
|
||||||
import space.kscience.dataforge.meta.Meta
|
import space.kscience.dataforge.meta.Meta
|
||||||
import space.kscience.dataforge.misc.DFExperimental
|
import space.kscience.dataforge.misc.DFExperimental
|
||||||
import space.kscience.dataforge.names.Name
|
import space.kscience.dataforge.names.Name
|
||||||
@ -28,7 +30,7 @@ internal const val RENDER_FUNCTION_NAME = "renderAllVisionsById"
|
|||||||
* @param renderScript if true add rendering script after the fragment
|
* @param renderScript if true add rendering script after the fragment
|
||||||
*/
|
*/
|
||||||
public fun TagConsumer<*>.visionFragment(
|
public fun TagConsumer<*>.visionFragment(
|
||||||
manager: VisionManager,
|
context: Context = Global,
|
||||||
embedData: Boolean = true,
|
embedData: Boolean = true,
|
||||||
fetchDataUrl: String? = null,
|
fetchDataUrl: String? = null,
|
||||||
fetchUpdatesUrl: String? = null,
|
fetchUpdatesUrl: String? = null,
|
||||||
@ -37,8 +39,8 @@ public fun TagConsumer<*>.visionFragment(
|
|||||||
fragment: HtmlVisionFragment,
|
fragment: HtmlVisionFragment,
|
||||||
): Map<Name, Vision> {
|
): Map<Name, Vision> {
|
||||||
val visionMap = HashMap<Name, Vision>()
|
val visionMap = HashMap<Name, Vision>()
|
||||||
val consumer = object : VisionTagConsumer<Any?>(this@visionFragment, manager, idPrefix) {
|
val consumer = object : VisionTagConsumer<Any?>(this@visionFragment, context, idPrefix) {
|
||||||
override fun DIV.renderVision(name: Name, vision: Vision, outputMeta: Meta) {
|
override fun DIV.renderVision(manager: VisionManager, name: Name, vision: Vision, outputMeta: Meta) {
|
||||||
visionMap[name] = vision
|
visionMap[name] = vision
|
||||||
// Toggle update mode
|
// Toggle update mode
|
||||||
|
|
||||||
@ -78,19 +80,19 @@ public fun TagConsumer<*>.visionFragment(
|
|||||||
}
|
}
|
||||||
|
|
||||||
public fun FlowContent.visionFragment(
|
public fun FlowContent.visionFragment(
|
||||||
manager: VisionManager,
|
context: Context = Global,
|
||||||
embedData: Boolean = true,
|
embedData: Boolean = true,
|
||||||
fetchDataUrl: String? = null,
|
fetchDataUrl: String? = null,
|
||||||
fetchUpdatesUrl: String? = null,
|
fetchUpdatesUrl: String? = null,
|
||||||
idPrefix: String? = null,
|
idPrefix: String? = null,
|
||||||
renderSctipt: Boolean = true,
|
renderScript: Boolean = true,
|
||||||
fragment: HtmlVisionFragment,
|
fragment: HtmlVisionFragment,
|
||||||
): Map<Name, Vision> = consumer.visionFragment(
|
): Map<Name, Vision> = consumer.visionFragment(
|
||||||
manager,
|
context,
|
||||||
embedData,
|
embedData,
|
||||||
fetchDataUrl,
|
fetchDataUrl,
|
||||||
fetchUpdatesUrl,
|
fetchUpdatesUrl,
|
||||||
idPrefix,
|
idPrefix,
|
||||||
renderSctipt,
|
renderScript,
|
||||||
fragment
|
fragment
|
||||||
)
|
)
|
@ -1,37 +1,52 @@
|
|||||||
package space.kscience.visionforge.html
|
package space.kscience.visionforge.html
|
||||||
|
|
||||||
import kotlinx.html.*
|
import kotlinx.html.*
|
||||||
import space.kscience.dataforge.misc.DFExperimental
|
import space.kscience.dataforge.context.Context
|
||||||
import space.kscience.visionforge.VisionManager
|
|
||||||
|
|
||||||
//data class HeaderContainer
|
|
||||||
|
|
||||||
public data class Page(
|
public data class Page(
|
||||||
public val visionManager: VisionManager,
|
public val context: Context,
|
||||||
public val title: String,
|
public val headers: Map<String, HtmlFragment> = emptyMap(),
|
||||||
public val headers: Map<String, HtmlFragment>,
|
|
||||||
public val content: HtmlVisionFragment,
|
public val content: HtmlVisionFragment,
|
||||||
) {
|
) {
|
||||||
public fun <R> render(root: TagConsumer<R>): R = root.apply {
|
public fun <R> render(root: TagConsumer<R>): R = root.apply {
|
||||||
head {
|
head {
|
||||||
meta {
|
meta {
|
||||||
charset = "utf-8"
|
charset = "utf-8"
|
||||||
|
}
|
||||||
headers.values.forEach {
|
headers.values.forEach {
|
||||||
fragment(it)
|
fragment(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
title(this@Page.title)
|
|
||||||
}
|
|
||||||
body {
|
body {
|
||||||
visionFragment(visionManager, fragment = content)
|
visionFragment(context, fragment = content)
|
||||||
}
|
}
|
||||||
}.finalize()
|
}.finalize()
|
||||||
|
|
||||||
|
public companion object{
|
||||||
|
/**
|
||||||
|
* Use a script with given [src] as a global header for all pages.
|
||||||
|
*/
|
||||||
|
public fun scriptHeader(src: String, block: SCRIPT.() -> Unit = {}): HtmlFragment = {
|
||||||
|
script {
|
||||||
|
type = "text/javascript"
|
||||||
|
this.src = src
|
||||||
|
block()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use css with given stylesheet link as a global header for all pages.
|
||||||
|
*/
|
||||||
|
public fun styleSheetHeader(href: String, block: LINK.() -> Unit = {}): HtmlFragment = {
|
||||||
|
link {
|
||||||
|
rel = "stylesheet"
|
||||||
|
this.href = href
|
||||||
|
block()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@DFExperimental
|
public fun title(title:String): HtmlFragment = {
|
||||||
public fun VisionManager.page(
|
title(title)
|
||||||
title: String = "VisionForge page",
|
}
|
||||||
vararg headers: Pair<String, HtmlFragment>,
|
}
|
||||||
content: HtmlVisionFragment,
|
}
|
||||||
): Page = Page(this, title, mapOf(*headers), content)
|
|
@ -1,6 +1,8 @@
|
|||||||
package space.kscience.visionforge.html
|
package space.kscience.visionforge.html
|
||||||
|
|
||||||
import kotlinx.html.*
|
import kotlinx.html.*
|
||||||
|
import space.kscience.dataforge.context.Context
|
||||||
|
import space.kscience.dataforge.context.PluginFactory
|
||||||
import space.kscience.dataforge.meta.Meta
|
import space.kscience.dataforge.meta.Meta
|
||||||
import space.kscience.dataforge.meta.MetaSerializer
|
import space.kscience.dataforge.meta.MetaSerializer
|
||||||
import space.kscience.dataforge.meta.MutableMeta
|
import space.kscience.dataforge.meta.MutableMeta
|
||||||
@ -9,9 +11,12 @@ import space.kscience.dataforge.misc.DFExperimental
|
|||||||
import space.kscience.dataforge.names.Name
|
import space.kscience.dataforge.names.Name
|
||||||
import space.kscience.dataforge.names.NameToken
|
import space.kscience.dataforge.names.NameToken
|
||||||
import space.kscience.dataforge.names.asName
|
import space.kscience.dataforge.names.asName
|
||||||
|
import space.kscience.dataforge.names.parseAsName
|
||||||
import space.kscience.visionforge.Vision
|
import space.kscience.visionforge.Vision
|
||||||
import space.kscience.visionforge.VisionManager
|
import space.kscience.visionforge.VisionManager
|
||||||
|
import space.kscience.visionforge.html.VisionTagConsumer.Companion.DEFAULT_VISION_NAME
|
||||||
import space.kscience.visionforge.setAsRoot
|
import space.kscience.visionforge.setAsRoot
|
||||||
|
import space.kscience.visionforge.visionManager
|
||||||
import kotlin.collections.set
|
import kotlin.collections.set
|
||||||
|
|
||||||
@DslMarker
|
@DslMarker
|
||||||
@ -22,10 +27,25 @@ public annotation class VisionDSL
|
|||||||
*/
|
*/
|
||||||
@DFExperimental
|
@DFExperimental
|
||||||
@VisionDSL
|
@VisionDSL
|
||||||
public class VisionOutput @PublishedApi internal constructor(public val manager: VisionManager) {
|
public class VisionOutput @PublishedApi internal constructor(public val context: Context, public val name: Name?) {
|
||||||
public var meta: Meta = Meta.EMPTY
|
public var meta: Meta = Meta.EMPTY
|
||||||
|
|
||||||
//TODO expose a way to define required plugins.
|
private val requirements: MutableSet<PluginFactory<*>> = HashSet()
|
||||||
|
|
||||||
|
public fun requirePlugin(factory: PluginFactory<*>) {
|
||||||
|
requirements.add(factory)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun buildVisionManager(): VisionManager =
|
||||||
|
if (requirements.all { req -> context.plugins.find(true) { it.tag == req.tag } != null }) {
|
||||||
|
context.visionManager
|
||||||
|
} else {
|
||||||
|
val newContext = context.buildContext(NameToken(DEFAULT_VISION_NAME, name.toString()).asName()) {
|
||||||
|
plugin(VisionManager)
|
||||||
|
requirements.forEach { plugin(it) }
|
||||||
|
}
|
||||||
|
newContext.visionManager
|
||||||
|
}
|
||||||
|
|
||||||
public inline fun meta(block: MutableMeta.() -> Unit) {
|
public inline fun meta(block: MutableMeta.() -> Unit) {
|
||||||
this.meta = Meta(block)
|
this.meta = Meta(block)
|
||||||
@ -36,9 +56,10 @@ public class VisionOutput @PublishedApi internal constructor(public val manager:
|
|||||||
* Modified [TagConsumer] that allows rendering output fragments and visions in them
|
* Modified [TagConsumer] that allows rendering output fragments and visions in them
|
||||||
*/
|
*/
|
||||||
@VisionDSL
|
@VisionDSL
|
||||||
|
@OptIn(DFExperimental::class)
|
||||||
public abstract class VisionTagConsumer<R>(
|
public abstract class VisionTagConsumer<R>(
|
||||||
private val root: TagConsumer<R>,
|
private val root: TagConsumer<R>,
|
||||||
public val manager: VisionManager,
|
public val context: Context,
|
||||||
private val idPrefix: String? = null,
|
private val idPrefix: String? = null,
|
||||||
) : TagConsumer<R> by root {
|
) : TagConsumer<R> by root {
|
||||||
|
|
||||||
@ -46,23 +67,26 @@ public abstract class VisionTagConsumer<R>(
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Render a vision inside the output fragment
|
* Render a vision inside the output fragment
|
||||||
|
* @param manager a [VisionManager] to be used in renderer
|
||||||
* @param name name of the output container
|
* @param name name of the output container
|
||||||
* @param vision an object to be rendered
|
* @param vision an object to be rendered
|
||||||
* @param outputMeta optional configuration for the output container
|
* @param outputMeta optional configuration for the output container
|
||||||
*/
|
*/
|
||||||
protected abstract fun DIV.renderVision(name: Name, vision: Vision, outputMeta: Meta)
|
protected abstract fun DIV.renderVision(manager: VisionManager, name: Name, vision: Vision, outputMeta: Meta)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a placeholder for a vision output with optional [Vision] in it
|
* Create a placeholder for a vision output with optional [Vision] in it
|
||||||
* TODO with multi-receivers could be replaced by [VisionTagConsumer, TagConsumer] extension
|
* TODO with multi-receivers could be replaced by [VisionTagConsumer, TagConsumer] extension
|
||||||
*/
|
*/
|
||||||
public fun <T> TagConsumer<T>.vision(
|
private fun <T> TagConsumer<T>.vision(
|
||||||
name: Name,
|
name: Name,
|
||||||
vision: Vision? = null,
|
manager: VisionManager,
|
||||||
|
vision: Vision,
|
||||||
outputMeta: Meta = Meta.EMPTY,
|
outputMeta: Meta = Meta.EMPTY,
|
||||||
): T = div {
|
): T = div {
|
||||||
id = resolveId(name)
|
id = resolveId(name)
|
||||||
classes = setOf(OUTPUT_CLASS)
|
classes = setOf(OUTPUT_CLASS)
|
||||||
|
vision.setAsRoot(manager)
|
||||||
attributes[OUTPUT_NAME_ATTRIBUTE] = name.toString()
|
attributes[OUTPUT_NAME_ATTRIBUTE] = name.toString()
|
||||||
if (!outputMeta.isEmpty()) {
|
if (!outputMeta.isEmpty()) {
|
||||||
//Hard-code output configuration
|
//Hard-code output configuration
|
||||||
@ -73,9 +97,7 @@ public abstract class VisionTagConsumer<R>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vision?.let {
|
renderVision(manager, name, vision, outputMeta)
|
||||||
renderVision(name, it, outputMeta)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -83,14 +105,14 @@ public abstract class VisionTagConsumer<R>(
|
|||||||
* TODO replace by multi-receiver
|
* TODO replace by multi-receiver
|
||||||
*/
|
*/
|
||||||
@OptIn(DFExperimental::class)
|
@OptIn(DFExperimental::class)
|
||||||
public inline fun <T> TagConsumer<T>.vision(
|
public fun <T> TagConsumer<T>.vision(
|
||||||
name: Name,
|
name: Name? = null,
|
||||||
@OptIn(DFExperimental::class) visionProvider: VisionOutput.() -> Vision,
|
@OptIn(DFExperimental::class) visionProvider: VisionOutput.() -> Vision,
|
||||||
): T {
|
): T {
|
||||||
val output = VisionOutput(manager)
|
val output = VisionOutput(context, name)
|
||||||
val vision = output.visionProvider()
|
val vision = output.visionProvider()
|
||||||
vision.setAsRoot(manager)
|
val actualName = name ?: NameToken(DEFAULT_VISION_NAME, vision.hashCode().toUInt().toString()).asName()
|
||||||
return vision(name, vision, output.meta)
|
return vision(actualName, output.buildVisionManager(), vision, output.meta)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -98,14 +120,10 @@ public abstract class VisionTagConsumer<R>(
|
|||||||
*/
|
*/
|
||||||
@OptIn(DFExperimental::class)
|
@OptIn(DFExperimental::class)
|
||||||
@VisionDSL
|
@VisionDSL
|
||||||
public inline fun <T> TagConsumer<T>.vision(
|
|
||||||
name: String = DEFAULT_VISION_NAME,
|
|
||||||
visionProvider: VisionOutput.() -> Vision,
|
|
||||||
): T = vision(Name.parse(name), visionProvider)
|
|
||||||
|
|
||||||
public fun <T> TagConsumer<T>.vision(
|
public fun <T> TagConsumer<T>.vision(
|
||||||
vision: Vision,
|
name: String?,
|
||||||
): T = vision(NameToken("vision", vision.hashCode().toString()).asName(), vision)
|
@OptIn(DFExperimental::class) visionProvider: VisionOutput.() -> Vision,
|
||||||
|
): T = vision(name?.parseAsName(), visionProvider)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process the resulting object produced by [TagConsumer]
|
* Process the resulting object produced by [TagConsumer]
|
||||||
@ -114,9 +132,7 @@ public abstract class VisionTagConsumer<R>(
|
|||||||
//do nothing by default
|
//do nothing by default
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun finalize(): R {
|
override fun finalize(): R = root.finalize().also { processResult(it) }
|
||||||
return root.finalize().also { processResult(it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
public companion object {
|
public companion object {
|
||||||
public const val OUTPUT_CLASS: String = "visionforge-output"
|
public const val OUTPUT_CLASS: String = "visionforge-output"
|
||||||
|
@ -3,7 +3,6 @@ package space.kscience.visionforge.html
|
|||||||
import kotlinx.html.*
|
import kotlinx.html.*
|
||||||
import kotlinx.html.stream.createHTML
|
import kotlinx.html.stream.createHTML
|
||||||
import space.kscience.dataforge.context.Global
|
import space.kscience.dataforge.context.Global
|
||||||
import space.kscience.dataforge.context.fetch
|
|
||||||
import space.kscience.dataforge.meta.Meta
|
import space.kscience.dataforge.meta.Meta
|
||||||
import space.kscience.dataforge.meta.configure
|
import space.kscience.dataforge.meta.configure
|
||||||
import space.kscience.dataforge.meta.set
|
import space.kscience.dataforge.meta.set
|
||||||
@ -23,8 +22,8 @@ fun FlowContent.renderVisionFragment(
|
|||||||
fragment: HtmlVisionFragment,
|
fragment: HtmlVisionFragment,
|
||||||
): Map<Name, Vision> {
|
): Map<Name, Vision> {
|
||||||
val visionMap = HashMap<Name, Vision>()
|
val visionMap = HashMap<Name, Vision>()
|
||||||
val consumer = object : VisionTagConsumer<Any?>(consumer, Global.fetch(VisionManager), idPrefix) {
|
val consumer = object : VisionTagConsumer<Any?>(consumer, Global, idPrefix) {
|
||||||
override fun DIV.renderVision(name: Name, vision: Vision, outputMeta: Meta) {
|
override fun DIV.renderVision(manager: VisionManager, name: Name, vision: Vision, outputMeta: Meta) {
|
||||||
visionMap[name] = vision
|
visionMap[name] = vision
|
||||||
renderer(name, vision, outputMeta)
|
renderer(name, vision, outputMeta)
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@ import kotlinx.html.link
|
|||||||
import kotlinx.html.script
|
import kotlinx.html.script
|
||||||
import kotlinx.html.unsafe
|
import kotlinx.html.unsafe
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import space.kscience.dataforge.misc.DFExperimental
|
|
||||||
import space.kscience.visionforge.VisionManager
|
import space.kscience.visionforge.VisionManager
|
||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
@ -113,10 +112,9 @@ internal fun fileCssHeader(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make a script header, automatically copying file to appropriate location
|
* Make a script header from a resource file, automatically copying file to appropriate location
|
||||||
*/
|
*/
|
||||||
@DFExperimental
|
public fun Page.Companion.importScriptHeader(
|
||||||
public fun scriptHeader(
|
|
||||||
scriptResource: String,
|
scriptResource: String,
|
||||||
resourceLocation: ResourceLocation,
|
resourceLocation: ResourceLocation,
|
||||||
htmlPath: Path? = null,
|
htmlPath: Path? = null,
|
||||||
|
@ -390,4 +390,7 @@ public fun SolidGroup.gdml(gdml: Gdml, key: String? = null, transformer: GdmlLoa
|
|||||||
|
|
||||||
@VisionBuilder
|
@VisionBuilder
|
||||||
@DFExperimental
|
@DFExperimental
|
||||||
public inline fun VisionOutput.gdml(block: Gdml.() -> Unit): SolidGroup = Gdml(block).toVision()
|
public inline fun VisionOutput.gdml(block: Gdml.() -> Unit): SolidGroup {
|
||||||
|
requirePlugin(Solids)
|
||||||
|
return Gdml(block).toVision()
|
||||||
|
}
|
@ -24,4 +24,7 @@ public fun Plot.asVision(): VisionOfPlotly = VisionOfPlotly(this)
|
|||||||
@DFExperimental
|
@DFExperimental
|
||||||
public inline fun VisionOutput.plotly(
|
public inline fun VisionOutput.plotly(
|
||||||
block: Plot.() -> Unit,
|
block: Plot.() -> Unit,
|
||||||
): VisionOfPlotly = VisionOfPlotly(Plotly.plot(block))
|
): VisionOfPlotly {
|
||||||
|
requirePlugin(PlotlyPlugin)
|
||||||
|
return VisionOfPlotly(Plotly.plot(block))
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package space.kscience.visionforge.three.server
|
package space.kscience.visionforge.server
|
||||||
|
|
||||||
import io.ktor.application.*
|
import io.ktor.application.*
|
||||||
import io.ktor.features.CORS
|
import io.ktor.features.CORS
|
||||||
@ -14,9 +14,9 @@ import io.ktor.routing.*
|
|||||||
import io.ktor.server.cio.CIO
|
import io.ktor.server.cio.CIO
|
||||||
import io.ktor.server.engine.ApplicationEngine
|
import io.ktor.server.engine.ApplicationEngine
|
||||||
import io.ktor.server.engine.embeddedServer
|
import io.ktor.server.engine.embeddedServer
|
||||||
|
import io.ktor.util.getOrFail
|
||||||
import io.ktor.websocket.WebSockets
|
import io.ktor.websocket.WebSockets
|
||||||
import io.ktor.websocket.webSocket
|
import io.ktor.websocket.webSocket
|
||||||
import kotlinx.coroutines.CoroutineScope
|
|
||||||
import kotlinx.coroutines.channels.consumeEach
|
import kotlinx.coroutines.channels.consumeEach
|
||||||
import kotlinx.coroutines.flow.collect
|
import kotlinx.coroutines.flow.collect
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@ -32,9 +32,8 @@ import space.kscience.visionforge.VisionManager
|
|||||||
import space.kscience.visionforge.flowChanges
|
import space.kscience.visionforge.flowChanges
|
||||||
import space.kscience.visionforge.html.HtmlFragment
|
import space.kscience.visionforge.html.HtmlFragment
|
||||||
import space.kscience.visionforge.html.HtmlVisionFragment
|
import space.kscience.visionforge.html.HtmlVisionFragment
|
||||||
import space.kscience.visionforge.html.fragment
|
|
||||||
import space.kscience.visionforge.html.visionFragment
|
import space.kscience.visionforge.html.visionFragment
|
||||||
import space.kscience.visionforge.three.server.VisionServer.Companion.DEFAULT_PAGE
|
import space.kscience.visionforge.server.VisionServer.Companion.DEFAULT_PAGE
|
||||||
import java.awt.Desktop
|
import java.awt.Desktop
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
import kotlin.time.Duration.Companion.milliseconds
|
import kotlin.time.Duration.Companion.milliseconds
|
||||||
@ -48,7 +47,10 @@ public class VisionServer internal constructor(
|
|||||||
private val visionManager: VisionManager,
|
private val visionManager: VisionManager,
|
||||||
private val serverUrl: Url,
|
private val serverUrl: Url,
|
||||||
private val root: Route,
|
private val root: Route,
|
||||||
) : Configurable, CoroutineScope by root.application {
|
) : Configurable {
|
||||||
|
|
||||||
|
public val application: Application get() = root.application
|
||||||
|
|
||||||
override val meta: ObservableMutableMeta = MutableMeta()
|
override val meta: ObservableMutableMeta = MutableMeta()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -76,22 +78,10 @@ public class VisionServer internal constructor(
|
|||||||
*/
|
*/
|
||||||
public var dataUpdate: Boolean by meta.boolean(true, Name.parse("data.update"))
|
public var dataUpdate: Boolean by meta.boolean(true, Name.parse("data.update"))
|
||||||
|
|
||||||
/**
|
|
||||||
* a list of headers that should be applied to all pages
|
|
||||||
*/
|
|
||||||
private val globalHeaders: ArrayList<HtmlFragment> = ArrayList()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a header to all pages produced by this server
|
|
||||||
*/
|
|
||||||
public fun header(block: TagConsumer<*>.() -> Unit) {
|
|
||||||
globalHeaders.add(block)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun HTML.visionPage(
|
private fun HTML.visionPage(
|
||||||
title: String,
|
title: String,
|
||||||
pagePath: String,
|
pagePath: String,
|
||||||
headers: List<HtmlFragment>,
|
header: HtmlFragment,
|
||||||
visionFragment: HtmlVisionFragment,
|
visionFragment: HtmlVisionFragment,
|
||||||
): Map<Name, Vision> {
|
): Map<Name, Vision> {
|
||||||
var visionMap: Map<Name, Vision>? = null
|
var visionMap: Map<Name, Vision>? = null
|
||||||
@ -99,16 +89,14 @@ public class VisionServer internal constructor(
|
|||||||
head {
|
head {
|
||||||
meta {
|
meta {
|
||||||
charset = "utf-8"
|
charset = "utf-8"
|
||||||
(globalHeaders + headers).forEach {
|
header()
|
||||||
fragment(it)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
title(title)
|
title(title)
|
||||||
}
|
}
|
||||||
body {
|
body {
|
||||||
//Load the fragment and remember all loaded visions
|
//Load the fragment and remember all loaded visions
|
||||||
visionMap = visionFragment(
|
visionMap = visionFragment(
|
||||||
manager = visionManager,
|
context = visionManager.context,
|
||||||
embedData = true,
|
embedData = true,
|
||||||
fetchUpdatesUrl = "$serverUrl$pagePath/ws",
|
fetchUpdatesUrl = "$serverUrl$pagePath/ws",
|
||||||
fragment = visionFragment
|
fragment = visionFragment
|
||||||
@ -127,9 +115,7 @@ public class VisionServer internal constructor(
|
|||||||
|
|
||||||
//Update websocket
|
//Update websocket
|
||||||
webSocket("ws") {
|
webSocket("ws") {
|
||||||
val name: String = call.request.queryParameters["name"]
|
val name: String = call.request.queryParameters.getOrFail("name")
|
||||||
?: error("Vision name is not defined in parameters")
|
|
||||||
|
|
||||||
application.log.debug("Opened server socket for $name")
|
application.log.debug("Opened server socket for $name")
|
||||||
val vision: Vision = visions[Name.parse(name)] ?: error("Plot with id='$name' not registered")
|
val vision: Vision = visions[Name.parse(name)] ?: error("Plot with id='$name' not registered")
|
||||||
|
|
||||||
@ -158,8 +144,7 @@ public class VisionServer internal constructor(
|
|||||||
}
|
}
|
||||||
//Plots in their json representation
|
//Plots in their json representation
|
||||||
get("data") {
|
get("data") {
|
||||||
val name: String = call.request.queryParameters["name"]
|
val name: String = call.request.queryParameters.getOrFail("name")
|
||||||
?: error("Vision name is not defined in parameters")
|
|
||||||
|
|
||||||
val vision: Vision? = visions[Name.parse(name)]
|
val vision: Vision? = visions[Name.parse(name)]
|
||||||
if (vision == null) {
|
if (vision == null) {
|
||||||
@ -178,7 +163,7 @@ public class VisionServer internal constructor(
|
|||||||
/**
|
/**
|
||||||
* Serve visions in a given [route] without providing a page template
|
* Serve visions in a given [route] without providing a page template
|
||||||
*/
|
*/
|
||||||
public fun serveVisions(route: String, visions: Map<Name, Vision>): Unit {
|
public fun serveVisions(route: String, visions: Map<Name, Vision>) {
|
||||||
root.route(route) {
|
root.route(route) {
|
||||||
serveVisions(this, visions)
|
serveVisions(this, visions)
|
||||||
}
|
}
|
||||||
@ -192,7 +177,7 @@ public class VisionServer internal constructor(
|
|||||||
fragment: HtmlVisionFragment,
|
fragment: HtmlVisionFragment,
|
||||||
): String = createHTML().apply {
|
): String = createHTML().apply {
|
||||||
val visions = visionFragment(
|
val visions = visionFragment(
|
||||||
visionManager,
|
visionManager.context,
|
||||||
embedData = true,
|
embedData = true,
|
||||||
fetchUpdatesUrl = "$serverUrl$route/ws",
|
fetchUpdatesUrl = "$serverUrl$route/ws",
|
||||||
renderScript = true,
|
renderScript = true,
|
||||||
@ -203,12 +188,11 @@ public class VisionServer internal constructor(
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Serve a page, potentially containing any number of visions at a given [pagePath] with given [headers].
|
* Serve a page, potentially containing any number of visions at a given [pagePath] with given [headers].
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public fun page(
|
public fun page(
|
||||||
pagePath: String = DEFAULT_PAGE,
|
pagePath: String = DEFAULT_PAGE,
|
||||||
title: String = "VisionForge server page '$pagePath'",
|
title: String = "VisionForge server page '$pagePath'",
|
||||||
headers: List<HtmlFragment> = emptyList(),
|
header: HtmlFragment = {},
|
||||||
visionFragment: HtmlVisionFragment,
|
visionFragment: HtmlVisionFragment,
|
||||||
) {
|
) {
|
||||||
val visions = HashMap<Name, Vision>()
|
val visions = HashMap<Name, Vision>()
|
||||||
@ -216,7 +200,7 @@ public class VisionServer internal constructor(
|
|||||||
val cachedHtml: String? = if (cacheFragments) {
|
val cachedHtml: String? = if (cacheFragments) {
|
||||||
//Create and cache page html and map of visions
|
//Create and cache page html and map of visions
|
||||||
createHTML(true).html {
|
createHTML(true).html {
|
||||||
visions.putAll(visionPage(title, pagePath, headers, visionFragment))
|
visions.putAll(visionPage(title, pagePath, header, visionFragment))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
@ -230,7 +214,7 @@ public class VisionServer internal constructor(
|
|||||||
//re-create html and vision list on each call
|
//re-create html and vision list on each call
|
||||||
call.respondHtml {
|
call.respondHtml {
|
||||||
visions.clear()
|
visions.clear()
|
||||||
visions.putAll(visionPage(title, pagePath, headers, visionFragment))
|
visions.putAll(visionPage(title, pagePath, header, visionFragment))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//Use cached html
|
//Use cached html
|
||||||
@ -249,32 +233,6 @@ public class VisionServer internal constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Use a script with given [src] as a global header for all pages.
|
|
||||||
*/
|
|
||||||
public inline fun VisionServer.useScript(src: String, crossinline block: SCRIPT.() -> Unit = {}) {
|
|
||||||
header {
|
|
||||||
script {
|
|
||||||
type = "text/javascript"
|
|
||||||
this.src = src
|
|
||||||
block()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Use css with given stylesheet link as a global header for all pages.
|
|
||||||
*/
|
|
||||||
public inline fun VisionServer.useCss(href: String, crossinline block: LINK.() -> Unit = {}) {
|
|
||||||
header {
|
|
||||||
link {
|
|
||||||
rel = "stylesheet"
|
|
||||||
this.href = href
|
|
||||||
block()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attach VisionForge server application to given server
|
* Attach VisionForge server application to given server
|
||||||
*/
|
*/
|
@ -69,5 +69,7 @@ public class Solids(meta: Meta) : VisionPlugin(meta) {
|
|||||||
|
|
||||||
@VisionBuilder
|
@VisionBuilder
|
||||||
@DFExperimental
|
@DFExperimental
|
||||||
public inline fun VisionOutput.solid(block: SolidGroup.() -> Unit): SolidGroup =
|
public inline fun VisionOutput.solid(block: SolidGroup.() -> Unit): SolidGroup {
|
||||||
SolidGroup().apply(block)
|
requirePlugin(Solids)
|
||||||
|
return SolidGroup().apply(block)
|
||||||
|
}
|
||||||
|
@ -87,7 +87,10 @@ public fun Table<Number>.toVision(): VisionOfTable = toVision { (it ?: Double.Na
|
|||||||
public inline fun VisionOutput.table(
|
public inline fun VisionOutput.table(
|
||||||
vararg headers: ColumnHeader<Value>,
|
vararg headers: ColumnHeader<Value>,
|
||||||
block: MutableRowTable<Value>.() -> Unit,
|
block: MutableRowTable<Value>.() -> Unit,
|
||||||
): VisionOfTable = RowTable(*headers, block = block).toVision()
|
): VisionOfTable {
|
||||||
|
requirePlugin(TableVisionPlugin)
|
||||||
|
return RowTable(*headers, block = block).toVision()
|
||||||
|
}
|
||||||
|
|
||||||
@DFExperimental
|
@DFExperimental
|
||||||
public inline fun VisionOutput.columnTable(
|
public inline fun VisionOutput.columnTable(
|
||||||
@ -99,6 +102,7 @@ public inline fun VisionOutput.columnTable(
|
|||||||
public fun VisionOutput.columnTable(
|
public fun VisionOutput.columnTable(
|
||||||
vararg dataAndHeaders: Pair<ColumnHeader<Value>, List<Any?>>,
|
vararg dataAndHeaders: Pair<ColumnHeader<Value>, List<Any?>>,
|
||||||
): VisionOfTable {
|
): VisionOfTable {
|
||||||
|
requirePlugin(TableVisionPlugin)
|
||||||
val columns = dataAndHeaders.map { (header, data) ->
|
val columns = dataAndHeaders.map { (header, data) ->
|
||||||
ListColumn(header, data.map { Value.of(it) })
|
ListColumn(header, data.map { Value.of(it) })
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package space.kscience.visionforge.three.server
|
package space.kscience.visionforge.three
|
||||||
|
|
||||||
import space.kscience.dataforge.misc.DFExperimental
|
import space.kscience.dataforge.misc.DFExperimental
|
||||||
import space.kscience.visionforge.runVisionClient
|
import space.kscience.visionforge.runVisionClient
|
@ -1,30 +0,0 @@
|
|||||||
package space.kscience.visionforge.three.server
|
|
||||||
|
|
||||||
import space.kscience.dataforge.misc.DFExperimental
|
|
||||||
import space.kscience.visionforge.VisionManager
|
|
||||||
import space.kscience.visionforge.html.HtmlVisionFragment
|
|
||||||
import space.kscience.visionforge.html.ResourceLocation
|
|
||||||
import space.kscience.visionforge.html.page
|
|
||||||
import space.kscience.visionforge.html.scriptHeader
|
|
||||||
import space.kscience.visionforge.makeFile
|
|
||||||
import java.awt.Desktop
|
|
||||||
import java.nio.file.Path
|
|
||||||
|
|
||||||
|
|
||||||
public fun VisionServer.useThreeJs(): Unit {
|
|
||||||
useScript("js/visionforge-three.js")
|
|
||||||
}
|
|
||||||
|
|
||||||
@DFExperimental
|
|
||||||
public fun VisionManager.makeThreeJsFile(
|
|
||||||
content: HtmlVisionFragment,
|
|
||||||
path: Path? = null,
|
|
||||||
title: String = "VisionForge page",
|
|
||||||
resourceLocation: ResourceLocation = ResourceLocation.SYSTEM,
|
|
||||||
show: Boolean = true,
|
|
||||||
): Unit {
|
|
||||||
val actualPath = page(title, content = content).makeFile(path) { actualPath ->
|
|
||||||
mapOf("threeJs" to scriptHeader("js/visionforge-three.js", resourceLocation, actualPath))
|
|
||||||
}
|
|
||||||
if (show) Desktop.getDesktop().browse(actualPath.toFile().toURI())
|
|
||||||
}
|
|
@ -0,0 +1,29 @@
|
|||||||
|
package space.kscience.visionforge.three
|
||||||
|
|
||||||
|
import space.kscience.dataforge.context.Global
|
||||||
|
import space.kscience.dataforge.misc.DFExperimental
|
||||||
|
import space.kscience.visionforge.html.*
|
||||||
|
import space.kscience.visionforge.makeFile
|
||||||
|
import java.awt.Desktop
|
||||||
|
import java.nio.file.Path
|
||||||
|
|
||||||
|
|
||||||
|
public val Page.Companion.threeJsHeader: HtmlFragment get() = scriptHeader("js/visionforge-three.js")
|
||||||
|
|
||||||
|
|
||||||
|
@DFExperimental
|
||||||
|
public fun makeThreeJsFile(
|
||||||
|
path: Path? = null,
|
||||||
|
title: String = "VisionForge page",
|
||||||
|
resourceLocation: ResourceLocation = ResourceLocation.SYSTEM,
|
||||||
|
show: Boolean = true,
|
||||||
|
content: HtmlVisionFragment,
|
||||||
|
): Unit {
|
||||||
|
val actualPath = Page(Global, content = content).makeFile(path) { actualPath ->
|
||||||
|
mapOf(
|
||||||
|
"title" to Page.title(title),
|
||||||
|
"threeJs" to Page.importScriptHeader("js/visionforge-three.js", resourceLocation, actualPath)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (show) Desktop.getDesktop().browse(actualPath.toFile().toURI())
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user