diff --git a/demo/js-playground/build.gradle.kts b/demo/js-playground/build.gradle.kts index 4a908719..65539554 100644 --- a/demo/js-playground/build.gradle.kts +++ b/demo/js-playground/build.gradle.kts @@ -22,6 +22,7 @@ kotlin{ dependencies{ implementation(project(":visionforge-gdml")) implementation(project(":visionforge-plotly")) + implementation(projects.visionforge.visionforgeMarkdown) implementation(project(":visionforge-threejs")) implementation(project(":ui:ring")) } \ No newline at end of file diff --git a/demo/js-playground/src/main/kotlin/JsPlaygroundApp.kt b/demo/js-playground/src/main/kotlin/JsPlaygroundApp.kt index afd4e695..db9be953 100644 --- a/demo/js-playground/src/main/kotlin/JsPlaygroundApp.kt +++ b/demo/js-playground/src/main/kotlin/JsPlaygroundApp.kt @@ -12,7 +12,9 @@ import space.kscience.plotly.models.Trace import space.kscience.plotly.scatter import space.kscience.visionforge.Application import space.kscience.visionforge.VisionClient +import space.kscience.visionforge.markup.VisionOfMarkup import space.kscience.visionforge.plotly.PlotlyPlugin +import space.kscience.visionforge.react.flexRow import space.kscience.visionforge.ring.ThreeCanvasWithControls import space.kscience.visionforge.ring.ThreeWithControlsPlugin import space.kscience.visionforge.ring.solid @@ -30,7 +32,6 @@ fun Trace.appendXYLatest(x: Number, y: Number, history: Int = 400, xErr: Number? yErr?.let { error_y.array = (error_y.array + yErr).takeLast(history) } } - private class JsPlaygroundApp : Application { override fun start(state: Map) { @@ -44,6 +45,7 @@ private class JsPlaygroundApp : Application { val element = document.getElementById("playground") ?: error("Element with id 'playground' not found on page") val bouncingSphereTrace = Trace() + val bouncingSphereMarkup = VisionOfMarkup() render(element) { styledDiv { @@ -57,53 +59,68 @@ private class JsPlaygroundApp : Application { Tab("gravity") { styledDiv { css { - height = 50.vh + height = 100.vh - 50.pt } - child(ThreeCanvasWithControls) { - attrs { - context = playgroundContext - solid { - sphere(5.0, "ball") { - detail = 16 - color("red") - val h = 100.0 - y = h - launch { - val g = 10.0 - val dt = 0.1 - var time = 0.0 - var velocity = 0.0 - while (isActive) { - delay(20) - time += dt - velocity -= g * dt - y = y.toDouble() + velocity * dt - bouncingSphereTrace.appendXYLatest(time, y) - if (y.toDouble() <= 2.5) { - //conservation of energy - velocity = sqrt(2 * g * h) + styledDiv { + css { + height = 50.vh + } + child(ThreeCanvasWithControls) { + attrs { + context = playgroundContext + solid { + sphere(5.0, "ball") { + detail = 16 + color("red") + val h = 100.0 + y = h + launch { + val g = 10.0 + val dt = 0.1 + var time = 0.0 + var velocity = 0.0 + while (isActive) { + delay(20) + time += dt + velocity -= g * dt + val energy = g * y.toDouble() + velocity * velocity / 2 + y = y.toDouble() + velocity * dt + bouncingSphereTrace.appendXYLatest(time, y) + if (y.toDouble() <= 2.5) { + //conservation of energy + velocity = sqrt(2 * g * h) + } + + bouncingSphereMarkup.content = """ + ## Bouncing sphere parameters + + **velocity** = $velocity + + **energy** = $energy + """.trimIndent() } } } - } - box(200, 5, 200, name = "floor") { - y = -2.5 + box(200, 5, 200, name = "floor") { + y = -2.5 + } } } } } - } - styledDiv { - css { - height = 40.vh - } - - Plotly { - attrs { - context = playgroundContext - plot = space.kscience.plotly.Plotly.plot { - traces(bouncingSphereTrace) + flexRow { + css{ + alignContent = Align.stretch + alignItems = Align.stretch + height = 50.vh - 50.pt + } + plotly { + traces(bouncingSphereTrace) + } + Markup { + attrs { + markup = bouncingSphereMarkup } } } @@ -121,7 +138,7 @@ private class JsPlaygroundApp : Application { Tab("spheres") { styledDiv { css { - height = 90.vh + height = 100.vh - 50.pt } child(ThreeCanvasWithControls) { val random = Random(112233) @@ -147,7 +164,6 @@ private class JsPlaygroundApp : Application { Tab("plotly") { Plotly { attrs { - context = playgroundContext plot = space.kscience.plotly.Plotly.plot { scatter { x(1, 2, 3) diff --git a/demo/js-playground/src/main/kotlin/markupComponent.kt b/demo/js-playground/src/main/kotlin/markupComponent.kt new file mode 100644 index 00000000..73c7da29 --- /dev/null +++ b/demo/js-playground/src/main/kotlin/markupComponent.kt @@ -0,0 +1,56 @@ +import kotlinx.css.* +import kotlinx.css.properties.border +import kotlinx.dom.clear +import kotlinx.html.dom.append +import org.intellij.markdown.flavours.commonmark.CommonMarkFlavourDescriptor +import org.intellij.markdown.flavours.gfm.GFMFlavourDescriptor +import org.w3c.dom.Element +import org.w3c.dom.HTMLElement +import react.RProps +import react.functionalComponent +import react.useEffect +import react.useRef +import space.kscience.visionforge.markup.VisionOfMarkup +import space.kscience.visionforge.markup.markdown +import space.kscience.visionforge.useProperty +import styled.css +import styled.styledDiv + +external interface MarkupProps : RProps { + var markup: VisionOfMarkup? +} + +val Markup = functionalComponent("Markup") { props -> + val elementRef = useRef(null) + + useEffect(props.markup, elementRef) { + val element = elementRef.current as? HTMLElement ?: error("Markup element not found") + props.markup?.let { vision -> + val flavour = when (vision.format) { + VisionOfMarkup.COMMONMARK_FORMAT -> CommonMarkFlavourDescriptor() + VisionOfMarkup.GFM_FORMAT -> GFMFlavourDescriptor() + //TODO add new formats via plugins + else -> error("Format ${vision.format} not recognized") + } + vision.useProperty(VisionOfMarkup::content) { content -> + element.clear() + element.append { + markdown(flavour) { content ?: "" } + } + } + } + } + + styledDiv { + css { + width = 100.pct + height = 100.pct + border(2.pt, BorderStyle.solid, Color.blue) + padding(8.pt) + backgroundColor = Color.white + flex(1.0) + zIndex = 10000 + } + ref = elementRef + } +} \ No newline at end of file diff --git a/demo/js-playground/src/main/kotlin/plotlyComponent.kt b/demo/js-playground/src/main/kotlin/plotlyComponent.kt index 9480c68b..22f63ac8 100644 --- a/demo/js-playground/src/main/kotlin/plotlyComponent.kt +++ b/demo/js-playground/src/main/kotlin/plotlyComponent.kt @@ -1,34 +1,44 @@ -import kotlinx.css.flex +import kotlinx.css.* +import kotlinx.css.properties.border import org.w3c.dom.Element import org.w3c.dom.HTMLElement -import react.RProps -import react.functionalComponent -import react.useEffect -import react.useRef -import space.kscience.dataforge.context.Context +import react.* import space.kscience.plotly.Plot +import space.kscience.plotly.PlotlyConfig import space.kscience.plotly.plot import styled.css import styled.styledDiv -external interface PlotlyProps: RProps{ - var context: Context +external interface PlotlyProps : RProps { var plot: Plot? } -val Plotly = functionalComponent("Plotly"){props -> +val Plotly = functionalComponent("Plotly") { props -> val elementRef = useRef(null) useEffect(props.plot, elementRef) { val element = elementRef.current as? HTMLElement ?: error("Plotly element not found") - props.plot?.let { element.plot(it)} + props.plot?.let { + element.plot(it, PlotlyConfig { + responsive = true + }) + } } styledDiv { css { + width = 100.pct + height = 100.pct + border(2.pt, BorderStyle.solid, Color.blue) flex(1.0) } ref = elementRef } +} + +fun RBuilder.plotly(plotbuilder: Plot.() -> Unit) = Plotly { + attrs { + this.plot = Plot().apply(plotbuilder) + } } \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 05679dc3..ffed3a25 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.1.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/settings.gradle.kts b/settings.gradle.kts index d88c9b81..d4616ea7 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -18,6 +18,7 @@ pluginManagement { rootProject.name = "visionforge" +enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") include( // ":ui", diff --git a/ui/react/src/main/kotlin/space/kscience/visionforge/react/ThreeCanvasComponent.kt b/ui/react/src/main/kotlin/space/kscience/visionforge/react/ThreeCanvasComponent.kt index 41034773..6be75689 100644 --- a/ui/react/src/main/kotlin/space/kscience/visionforge/react/ThreeCanvasComponent.kt +++ b/ui/react/src/main/kotlin/space/kscience/visionforge/react/ThreeCanvasComponent.kt @@ -50,7 +50,8 @@ public val ThreeCanvasComponent: FunctionComponent = functiona css { maxWidth = 100.vw maxHeight = 100.vh - flex(1.0) + width = 100.pct + height = 100.pct } ref = elementRef } diff --git a/ui/ring/src/main/kotlin/space.kscience.visionforge.ring/ThreeViewWithControls.kt b/ui/ring/src/main/kotlin/space.kscience.visionforge.ring/ThreeViewWithControls.kt index 2cf552a2..e69b04c9 100644 --- a/ui/ring/src/main/kotlin/space.kscience.visionforge.ring/ThreeViewWithControls.kt +++ b/ui/ring/src/main/kotlin/space.kscience.visionforge.ring/ThreeViewWithControls.kt @@ -112,7 +112,7 @@ public val ThreeCanvasWithControls: FunctionComponent String) { + content = text() +} + internal val markupSerializersModule = SerializersModule { polymorphic(Vision::class) { subclass(VisionOfMarkup.serializer()) diff --git a/visionforge-markdown/src/jsMain/kotlin/space/kscience/visionforge/markup/MarkupPlugin.kt b/visionforge-markdown/src/jsMain/kotlin/space/kscience/visionforge/markup/MarkupPlugin.kt index d26488c5..4d7a1060 100644 --- a/visionforge-markdown/src/jsMain/kotlin/space/kscience/visionforge/markup/MarkupPlugin.kt +++ b/visionforge-markdown/src/jsMain/kotlin/space/kscience/visionforge/markup/MarkupPlugin.kt @@ -39,7 +39,6 @@ public class MarkupPlugin : VisionPlugin(), ElementVisionRenderer { div.clear() div.append { markdown(flavour) { vision.content ?: "" } - } } element.append(div) diff --git a/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeCanvas.kt b/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeCanvas.kt index 0d223987..3b5ae6ae 100644 --- a/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeCanvas.kt +++ b/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeCanvas.kt @@ -2,7 +2,6 @@ package space.kscience.visionforge.solid.three import info.laht.threekt.WebGLRenderer import info.laht.threekt.cameras.PerspectiveCamera -import info.laht.threekt.core.BufferGeometry import info.laht.threekt.core.Object3D import info.laht.threekt.core.Raycaster import info.laht.threekt.external.controls.OrbitControls @@ -276,7 +275,7 @@ public class ThreeCanvas( if (this is Mesh) { if (highlight) { val edges = LineSegments( - EdgesGeometry(geometry as BufferGeometry), + EdgesGeometry(geometry), material ).apply { name = edgesName