From c7d4bdfa5f989c320412bca67ab90e8be2b0e17c Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Wed, 15 Nov 2023 10:42:56 +0300 Subject: [PATCH] Add direct event processing to Vision --- settings.gradle.kts | 2 +- .../space/kscience/visionforge/Vision.kt | 11 +++-------- .../space/kscience/visionforge/VisionChange.kt | 3 +-- .../space/kscience/visionforge/VisionClient.kt | 6 +++--- .../space/kscience/visionforge/VisionEvent.kt | 16 +--------------- .../space/kscience/visionforge/VisionGroup.kt | 14 ++++---------- .../kscience/visionforge/JsVisionClient.kt | 18 ++++++++---------- .../visionforge/server/VisionServer.kt | 3 +-- 8 files changed, 22 insertions(+), 51 deletions(-) diff --git a/settings.gradle.kts b/settings.gradle.kts index 8611d0aa..31119a06 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -45,7 +45,7 @@ include( ":ui:ring", // ":ui:material", ":ui:bootstrap", - ":ui:compose", +// ":ui:compose", ":visionforge-core", ":visionforge-solid", // ":visionforge-fx", diff --git a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/Vision.kt b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/Vision.kt index 8cfe7a27..06cd6d8f 100644 --- a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/Vision.kt +++ b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/Vision.kt @@ -11,7 +11,6 @@ import space.kscience.dataforge.meta.descriptors.MetaDescriptor import space.kscience.dataforge.misc.Type import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.asName -import space.kscience.dataforge.names.isEmpty import space.kscience.visionforge.AbstractVisionGroup.Companion.updateProperties import space.kscience.visionforge.Vision.Companion.TYPE @@ -50,13 +49,9 @@ public interface Vision : Described { * Receive and process a generic [VisionEvent]. */ public fun receiveEvent(event: VisionEvent) { - if(event.targetName.isEmpty()) { - when (event) { - is VisionChangeEvent -> receiveChange(event.change) - else -> TODO() - } - } else { - error("Vision is not a group and can't process an event with non-empty target") + when (event) { + is VisionChange -> receiveChange(event) + else -> TODO() } } diff --git a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/VisionChange.kt b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/VisionChange.kt index 9915c035..87bff794 100644 --- a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/VisionChange.kt +++ b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/VisionChange.kt @@ -63,8 +63,7 @@ public data class VisionChange( public val vision: Vision? = null, public val properties: Meta? = null, public val children: Map? = null, -) - +) : VisionEvent /** * An update for a [Vision] diff --git a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/VisionClient.kt b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/VisionClient.kt index cc1c38b8..76d8aa80 100644 --- a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/VisionClient.kt +++ b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/VisionClient.kt @@ -13,7 +13,7 @@ import space.kscience.dataforge.names.parseAsName public interface VisionClient: Plugin { public val visionManager: VisionManager - public suspend fun sendEvent(event: VisionEvent) + public suspend fun sendEvent(targetName: Name, event: VisionEvent) public fun notifyPropertyChanged(visionName: Name, propertyName: Name, item: Meta?) } @@ -35,8 +35,8 @@ public fun VisionClient.notifyPropertyChanged(visionName: Name, propertyName: St notifyPropertyChanged(visionName, propertyName.parseAsName(true), Meta(item)) } -public fun VisionClient.sendEvent(visionName: Name, event: MetaRepr): Unit { +public fun VisionClient.sendEvent(targetName: Name, payload: MetaRepr): Unit { context.launch { - sendEvent(VisionMetaEvent(visionName, event.toMeta())) + sendEvent(targetName, VisionMetaEvent(payload.toMeta())) } } \ No newline at end of file diff --git a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/VisionEvent.kt b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/VisionEvent.kt index f1d8d3ed..84d36217 100644 --- a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/VisionEvent.kt +++ b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/VisionEvent.kt @@ -12,13 +12,6 @@ import space.kscience.dataforge.names.Name */ @Serializable public sealed interface VisionEvent { - public val targetName: Name - - /** - * Create a copy of this event with the same type and content, but different [targetName] - */ - public fun changeTarget(newTarget: Name): VisionEvent - public companion object { public val CLICK_EVENT_KEY: Name get() = Name.of("events", "click", "payload") } @@ -29,15 +22,8 @@ public sealed interface VisionEvent { */ @Serializable @SerialName("meta") -public data class VisionMetaEvent(override val targetName: Name, public val meta: Meta) : VisionEvent { - override fun changeTarget(newTarget: Name): VisionMetaEvent = VisionMetaEvent(newTarget, meta) -} +public class VisionMetaEvent(public val meta: Meta) : VisionEvent -@Serializable -@SerialName("change") -public data class VisionChangeEvent(override val targetName: Name, public val change: VisionChange) : VisionEvent { - override fun changeTarget(newTarget: Name): VisionChangeEvent = VisionChangeEvent(newTarget, change) -} public val Vision.Companion.CLICK_EVENT_KEY: Name get() = Name.of("events", "click", "payload") diff --git a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/VisionGroup.kt b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/VisionGroup.kt index ca3d6338..1edfa40a 100644 --- a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/VisionGroup.kt +++ b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/VisionGroup.kt @@ -6,7 +6,10 @@ import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.ValueType import space.kscience.dataforge.meta.descriptors.MetaDescriptor import space.kscience.dataforge.meta.descriptors.value -import space.kscience.dataforge.names.* +import space.kscience.dataforge.names.Name +import space.kscience.dataforge.names.NameToken +import space.kscience.dataforge.names.parseAsName +import space.kscience.dataforge.names.plus import space.kscience.visionforge.AbstractVisionGroup.Companion.updateProperties import space.kscience.visionforge.Vision.Companion.STYLE_KEY @@ -26,15 +29,6 @@ public interface VisionGroup : Vision { updateProperties(it, Name.EMPTY) } } - - override fun receiveEvent(event: VisionEvent) { - if (event.targetName.isEmpty()) { - super.receiveEvent(event) - } else { - val target = children[event.targetName] ?: error("Child vision with name ${event.targetName} not found") - target.receiveEvent(event.changeTarget(Name.EMPTY)) - } - } } public interface MutableVisionGroup : VisionGroup { diff --git a/visionforge-core/src/jsMain/kotlin/space/kscience/visionforge/JsVisionClient.kt b/visionforge-core/src/jsMain/kotlin/space/kscience/visionforge/JsVisionClient.kt index 3042be5a..b9e0ef93 100644 --- a/visionforge-core/src/jsMain/kotlin/space/kscience/visionforge/JsVisionClient.kt +++ b/visionforge-core/src/jsMain/kotlin/space/kscience/visionforge/JsVisionClient.kt @@ -20,7 +20,6 @@ import space.kscience.dataforge.meta.MetaSerializer import space.kscience.dataforge.meta.get import space.kscience.dataforge.meta.int import space.kscience.dataforge.names.Name -import space.kscience.dataforge.names.isEmpty import space.kscience.dataforge.names.parseAsName import space.kscience.visionforge.html.VisionTagConsumer import space.kscience.visionforge.html.VisionTagConsumer.Companion.OUTPUT_CONNECT_ATTRIBUTE @@ -82,15 +81,14 @@ public class JsVisionClient : AbstractPlugin(), VisionClient { } private val eventCollector by lazy { - MutableSharedFlow(meta["feedback.eventCache"].int ?: 100) + MutableSharedFlow>(meta["feedback.eventCache"].int ?: 100) } - /** * Send a custom feedback event */ - override suspend fun sendEvent(event: VisionEvent) { - eventCollector.emit(event) + override suspend fun sendEvent(targetName: Name, event: VisionEvent) { + eventCollector.emit(targetName to event) } private fun renderVision(element: Element, name: Name, vision: Vision, outputMeta: Meta) { @@ -127,8 +125,8 @@ public class JsVisionClient : AbstractPlugin(), VisionClient { ) // If change contains root vision replacement, do it - if(event is VisionChangeEvent && event.targetName.isEmpty()) { - event.change.vision?.let { vision -> + if(event is VisionChange) { + event.vision?.let { vision -> renderVision(element, name, vision, outputMeta) } } @@ -150,8 +148,8 @@ public class JsVisionClient : AbstractPlugin(), VisionClient { onopen = { feedbackJob = visionManager.context.launch { - eventCollector.filter { it.targetName == name }.onEach { - send(visionManager.jsonFormat.encodeToString(VisionEvent.serializer(), it)) + eventCollector.filter { it.first == name }.onEach { + send(visionManager.jsonFormat.encodeToString(VisionEvent.serializer(), it.second)) }.launchIn(this) while (isActive) { @@ -159,7 +157,7 @@ public class JsVisionClient : AbstractPlugin(), VisionClient { val change = changeCollector[name] ?: continue if (!change.isEmpty()) { mutex.withLock { - eventCollector.emit(VisionChangeEvent(name, change.deepCopy(visionManager))) + eventCollector.emit(name to change.deepCopy(visionManager)) change.reset() } } diff --git a/visionforge-server/src/main/kotlin/space/kscience/visionforge/server/VisionServer.kt b/visionforge-server/src/main/kotlin/space/kscience/visionforge/server/VisionServer.kt index 1831d641..4c5e093a 100644 --- a/visionforge-server/src/main/kotlin/space/kscience/visionforge/server/VisionServer.kt +++ b/visionforge-server/src/main/kotlin/space/kscience/visionforge/server/VisionServer.kt @@ -107,8 +107,7 @@ public fun Application.serveVisionData( try { withContext(configuration.context.coroutineContext) { - vision.flowChanges(configuration.updateInterval.milliseconds).onEach { update -> - val event = VisionChangeEvent(Name.EMPTY, update) + vision.flowChanges(configuration.updateInterval.milliseconds).onEach { event -> val json = configuration.visionManager.jsonFormat.encodeToString( VisionEvent.serializer(), event