From 05b87857f421df90bd4232311ae2b2f6e2a20aca Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Wed, 6 Dec 2023 23:01:22 +0300 Subject: [PATCH] Add input listeners --- .../ThreeWithControlsPlugin.kt | 7 +++-- .../kscience/visionforge/inputRenderers.kt | 28 ++++++++++++++----- .../visionforge/markup/MarkupPlugin.kt | 2 +- .../kscience/visionforge/plotly/plotlyJs.kt | 7 ++--- .../visionforge/tables/TableVisionJsPlugin.kt | 3 +- .../visionforge/solid/three/ThreePlugin.kt | 2 +- 6 files changed, 31 insertions(+), 18 deletions(-) diff --git a/ui/ring/src/jsMain/kotlin/space.kscience.visionforge.ring/ThreeWithControlsPlugin.kt b/ui/ring/src/jsMain/kotlin/space.kscience.visionforge.ring/ThreeWithControlsPlugin.kt index 94259b2f..a2223692 100644 --- a/ui/ring/src/jsMain/kotlin/space.kscience.visionforge.ring/ThreeWithControlsPlugin.kt +++ b/ui/ring/src/jsMain/kotlin/space.kscience.visionforge.ring/ThreeWithControlsPlugin.kt @@ -13,6 +13,7 @@ import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.asName import space.kscience.visionforge.ElementVisionRenderer import space.kscience.visionforge.Vision +import space.kscience.visionforge.VisionClient import space.kscience.visionforge.react.render import space.kscience.visionforge.solid.Solid import space.kscience.visionforge.solid.specifications.Canvas3DOptions @@ -26,9 +27,9 @@ public class ThreeWithControlsPlugin : AbstractPlugin(), ElementVisionRenderer { override fun rateVision(vision: Vision): Int = if (vision is Solid) ElementVisionRenderer.DEFAULT_RATING * 2 else ElementVisionRenderer.ZERO_RATING - override fun render(element: Element, name: Name, vision: Vision, meta: Meta) { - if(meta["controls.enabled"].boolean == false){ - three.render(element, name, vision, meta) + override fun render(element: Element, client: VisionClient, name: Name, vision: Vision, meta: Meta) { + if (meta["controls.enabled"].boolean == false) { + three.render(element, client, name, vision, meta) } else { space.kscience.visionforge.react.createRoot(element).render { child(ThreeCanvasWithControls) { diff --git a/visionforge-core/src/jsMain/kotlin/space/kscience/visionforge/inputRenderers.kt b/visionforge-core/src/jsMain/kotlin/space/kscience/visionforge/inputRenderers.kt index f17ac78f..a43a99f1 100644 --- a/visionforge-core/src/jsMain/kotlin/space/kscience/visionforge/inputRenderers.kt +++ b/visionforge-core/src/jsMain/kotlin/space/kscience/visionforge/inputRenderers.kt @@ -1,8 +1,11 @@ package space.kscience.visionforge import kotlinx.browser.document +import kotlinx.coroutines.launch +import kotlinx.dom.clear import kotlinx.html.InputType import kotlinx.html.div +import kotlinx.html.dom.append import kotlinx.html.js.input import org.w3c.dom.HTMLElement import org.w3c.dom.HTMLFormElement @@ -13,6 +16,7 @@ import org.w3c.xhr.FormData import space.kscience.dataforge.context.debug import space.kscience.dataforge.context.logger import space.kscience.dataforge.meta.* +import space.kscience.dataforge.names.Name import space.kscience.visionforge.html.* /** @@ -27,6 +31,12 @@ private fun HTMLElement.subscribeToVision(vision: VisionOfHtml) { } +private fun VisionClient.sendInputEvent(name: Name, value: Value?) { + context.launch { + sendEvent(name, VisionValueChangeEvent(value)) + } +} + /** * Subscribes the HTML input element to a given vision. * @@ -44,6 +54,10 @@ internal val htmlVisionRenderer: ElementVisionRenderer = div {}.also { div -> div.subscribeToVision(vision) vision.useProperty(VisionOfPlainHtml::content) { + div.clear() + div.append { + + } div.textContent = it } } @@ -57,7 +71,7 @@ internal val inputVisionRenderer: ElementVisionRenderer = type = InputType.text }.also { htmlInputElement -> val onEvent: (Event) -> Unit = { - client.sendEvent(name, VisionValueChangeEvent(htmlInputElement.value.asValue())) + client.sendInputEvent(name, htmlInputElement.value.asValue()) } @@ -81,7 +95,7 @@ internal val checkboxVisionRenderer: ElementVisionRenderer = type = InputType.checkBox }.also { htmlInputElement -> val onEvent: (Event) -> Unit = { - client.sendEvent(name, VisionValueChangeEvent(htmlInputElement.checked.asValue())) + client.sendInputEvent(name, htmlInputElement.value.asValue()) } @@ -105,7 +119,7 @@ internal val textVisionRenderer: ElementVisionRenderer = type = InputType.text }.also { htmlInputElement -> val onEvent: (Event) -> Unit = { - client.sendEvent(name, VisionValueChangeEvent(htmlInputElement.value.asValue())) + client.sendInputEvent(name, htmlInputElement.value.asValue()) } @@ -131,7 +145,7 @@ internal val numberVisionRenderer: ElementVisionRenderer = val onEvent: (Event) -> Unit = { htmlInputElement.value.toDoubleOrNull()?.let { - client.sendEvent(name, VisionValueChangeEvent(it.asValue())) + client.sendInputEvent(name, htmlInputElement.value.asValue()) } } @@ -159,7 +173,7 @@ internal val rangeVisionRenderer: ElementVisionRenderer = val onEvent: (Event) -> Unit = { htmlInputElement.value.toDoubleOrNull()?.let { - client.sendEvent(name, VisionValueChangeEvent(it.asValue())) + client.sendInputEvent(name, htmlInputElement.value.asValue()) } } @@ -200,7 +214,7 @@ internal fun FormData.toMeta(): Meta { } internal val formVisionRenderer: ElementVisionRenderer = - ElementVisionRenderer { _, vision, _ -> + ElementVisionRenderer { name, client, vision, _ -> val form = document.getElementById(vision.formId) as? HTMLFormElement ?: error("An element with id = '${vision.formId} is not a form") @@ -220,7 +234,7 @@ internal val formVisionRenderer: ElementVisionRenderer = form.onsubmit = { event -> event.preventDefault() val formData = FormData(form).toMeta() - vision.values = formData + client.sendMetaEvent(name, formData) console.info("Sent: ${formData.toMap()}") false } 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 ef700466..0d5e0431 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 @@ -27,7 +27,7 @@ public actual class MarkupPlugin : VisionPlugin(), ElementVisionRenderer { else -> ElementVisionRenderer.ZERO_RATING } - override fun render(element: Element, name: Name, vision: Vision, meta: Meta) { + override fun render(element: Element, client: VisionClient, name: Name, vision: Vision, meta: Meta) { require(vision is VisionOfMarkup) { "The vision is not a markup vision" } val div = document.createElement("div") val flavour = when (vision.format) { diff --git a/visionforge-plotly/src/jsMain/kotlin/space/kscience/visionforge/plotly/plotlyJs.kt b/visionforge-plotly/src/jsMain/kotlin/space/kscience/visionforge/plotly/plotlyJs.kt index 074be6dc..99a0795e 100644 --- a/visionforge-plotly/src/jsMain/kotlin/space/kscience/visionforge/plotly/plotlyJs.kt +++ b/visionforge-plotly/src/jsMain/kotlin/space/kscience/visionforge/plotly/plotlyJs.kt @@ -10,10 +10,7 @@ import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.asName import space.kscience.plotly.PlotlyConfig import space.kscience.plotly.plot -import space.kscience.visionforge.ElementVisionRenderer -import space.kscience.visionforge.JsVisionClient -import space.kscience.visionforge.Vision -import space.kscience.visionforge.VisionPlugin +import space.kscience.visionforge.* public actual class PlotlyPlugin : VisionPlugin(), ElementVisionRenderer { public val visionClient: JsVisionClient by require(JsVisionClient) @@ -27,7 +24,7 @@ public actual class PlotlyPlugin : VisionPlugin(), ElementVisionRenderer { else -> ElementVisionRenderer.ZERO_RATING } - override fun render(element: Element, name: Name, vision: Vision, meta: Meta) { + override fun render(element: Element, client: VisionClient, name: Name, vision: Vision, meta: Meta) { val plot = (vision as? VisionOfPlotly)?.plot ?: error("VisionOfPlotly expected but ${vision::class} found") val config = PlotlyConfig.read(meta) element.plot(config, plot) diff --git a/visionforge-tables/src/jsMain/kotlin/space/kscience/visionforge/tables/TableVisionJsPlugin.kt b/visionforge-tables/src/jsMain/kotlin/space/kscience/visionforge/tables/TableVisionJsPlugin.kt index 75977d79..18170686 100644 --- a/visionforge-tables/src/jsMain/kotlin/space/kscience/visionforge/tables/TableVisionJsPlugin.kt +++ b/visionforge-tables/src/jsMain/kotlin/space/kscience/visionforge/tables/TableVisionJsPlugin.kt @@ -14,6 +14,7 @@ import space.kscience.dataforge.names.asName import space.kscience.visionforge.ElementVisionRenderer import space.kscience.visionforge.JsVisionClient import space.kscience.visionforge.Vision +import space.kscience.visionforge.VisionClient import tabulator.Tabulator import tabulator.TabulatorFull @@ -34,7 +35,7 @@ public class TableVisionJsPlugin : AbstractPlugin(), ElementVisionRenderer { else -> ElementVisionRenderer.ZERO_RATING } - override fun render(element: Element, name: Name, vision: Vision, meta: Meta) { + override fun render(element: Element, client: VisionClient, name: Name, vision: Vision, meta: Meta) { val table: VisionOfTable = (vision as? VisionOfTable) ?: error("VisionOfTable expected but ${vision::class} found") diff --git a/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreePlugin.kt b/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreePlugin.kt index 7051f887..84552dd4 100644 --- a/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreePlugin.kt +++ b/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreePlugin.kt @@ -150,7 +150,7 @@ public class ThreePlugin : AbstractPlugin(), ElementVisionRenderer { render(vision) } - override fun render(element: Element, name: Name, vision: Vision, meta: Meta) { + override fun render(element: Element, client: VisionClient, name: Name, vision: Vision, meta: Meta) { renderSolid( element, vision as? Solid ?: error("Solid expected but ${vision::class} found"),