From 80284a99ef7b7e4c79aa510e27f6a03b03a20225 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 24 Nov 2023 10:02:25 +0300 Subject: [PATCH] Add click handlers --- .../kscience/visionforge/ControlVision.kt | 52 +++++++++++++++++++ .../space/kscience/visionforge/Vision.kt | 15 ++---- .../space/kscience/visionforge/VisionEvent.kt | 14 +---- .../space/kscience/visionforge/VisionGroup.kt | 8 +-- .../visionforge/solid/VisionUpdateTest.kt | 2 +- 5 files changed, 63 insertions(+), 28 deletions(-) create mode 100644 visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/ControlVision.kt diff --git a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/ControlVision.kt b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/ControlVision.kt new file mode 100644 index 00000000..38ee4d7f --- /dev/null +++ b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/ControlVision.kt @@ -0,0 +1,52 @@ +package space.kscience.visionforge + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Job +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.filterIsInstance +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import space.kscience.dataforge.meta.Meta +import space.kscience.dataforge.meta.MetaRepr +import space.kscience.dataforge.meta.MutableMeta + +@Serializable +@SerialName("control") +public abstract class VisionControlEvent : VisionEvent, MetaRepr { + public abstract val meta: Meta + + override fun toMeta(): Meta = meta +} + +public interface ControlVision : Vision { + public val controlEventFlow: Flow + + public fun dispatchControlEvent(event: VisionControlEvent) + + override fun receiveEvent(event: VisionEvent) { + if (event is VisionControlEvent) { + dispatchControlEvent(event) + } else super.receiveEvent(event) + } +} + +@Serializable +@SerialName("control.click") +public class VisionClickEvent(override val meta: Meta) : VisionControlEvent() + + +public interface ClickControl : ControlVision { + public fun click(builder: MutableMeta.() -> Unit = {}) { + dispatchControlEvent(VisionClickEvent(Meta(builder))) + } + + public fun onClick(scope: CoroutineScope, block: suspend VisionClickEvent.() -> Unit): Job { + return controlEventFlow.filterIsInstance().onEach(block).launchIn(scope) + } + + public companion object { + + } +} \ No newline at end of file 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 b4e6cba7..29965944 100644 --- a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/Vision.kt +++ b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/Vision.kt @@ -4,7 +4,8 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach -import space.kscience.dataforge.meta.Meta +import space.kscience.dataforge.context.logger +import space.kscience.dataforge.context.warn import space.kscience.dataforge.meta.asValue import space.kscience.dataforge.meta.boolean import space.kscience.dataforge.meta.descriptors.Described @@ -37,7 +38,7 @@ public interface Vision : Described { /** * Update this vision using a dif represented by [VisionChange]. */ - public fun receiveChange(change: VisionChange) { + public fun update(change: VisionChange) { if (change.children?.isNotEmpty() == true) { error("Vision is not a group") } @@ -46,18 +47,12 @@ public interface Vision : Described { } } - public fun onMetaEvent(meta: Meta){ - //Do nothing by default - } - /** * Receive and process a generic [VisionEvent]. */ public fun receiveEvent(event: VisionEvent) { - when (event) { - is VisionChange -> receiveChange(event) - is VisionMetaEvent -> onMetaEvent(event.meta) - } + if(event is VisionChange) update(event) + else manager?.logger?.warn { "Undispatched event: $event" } } override val descriptor: MetaDescriptor? 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 84d36217..de0b2643 100644 --- a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/VisionEvent.kt +++ b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/VisionEvent.kt @@ -3,8 +3,6 @@ package space.kscience.visionforge import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import space.kscience.dataforge.meta.Meta -import space.kscience.dataforge.meta.MutableMeta -import space.kscience.dataforge.meta.set import space.kscience.dataforge.names.Name /** @@ -22,14 +20,4 @@ public sealed interface VisionEvent { */ @Serializable @SerialName("meta") -public class VisionMetaEvent(public val meta: Meta) : VisionEvent - - -public val Vision.Companion.CLICK_EVENT_KEY: Name get() = Name.of("events", "click", "payload") - -/** - * Set the payload to be sent to server on click - */ -public fun Vision.onClickPayload(payloadBuilder: MutableMeta.() -> Unit) { - properties[VisionEvent.CLICK_EVENT_KEY] = Meta(payloadBuilder) -} \ No newline at end of file +public class VisionMetaEvent(public val meta: Meta) : VisionEvent \ No newline at end of file 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 1edfa40a..fd8aaa16 100644 --- a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/VisionGroup.kt +++ b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/VisionGroup.kt @@ -17,12 +17,12 @@ import space.kscience.visionforge.Vision.Companion.STYLE_KEY public interface VisionGroup : Vision { public val children: VisionChildren - override fun receiveChange(change: VisionChange) { + override fun update(change: VisionChange) { change.children?.forEach { (name, change) -> if (change.vision != null || change.vision == NullVision) { error("VisionGroup is read-only") } else { - children.getChild(name)?.receiveChange(change) + children.getChild(name)?.update(change) } } change.properties?.let { @@ -37,12 +37,12 @@ public interface MutableVisionGroup : VisionGroup { public fun createGroup(): MutableVisionGroup - override fun receiveChange(change: VisionChange) { + override fun update(change: VisionChange) { change.children?.forEach { (name, change) -> when { change.vision == NullVision -> children.setChild(name, null) change.vision != null -> children.setChild(name, change.vision) - else -> children.getChild(name)?.receiveChange(change) + else -> children.getChild(name)?.update(change) } } change.properties?.let { diff --git a/visionforge-solid/src/commonTest/kotlin/space/kscience/visionforge/solid/VisionUpdateTest.kt b/visionforge-solid/src/commonTest/kotlin/space/kscience/visionforge/solid/VisionUpdateTest.kt index 898fae11..0e495aaa 100644 --- a/visionforge-solid/src/commonTest/kotlin/space/kscience/visionforge/solid/VisionUpdateTest.kt +++ b/visionforge-solid/src/commonTest/kotlin/space/kscience/visionforge/solid/VisionUpdateTest.kt @@ -28,7 +28,7 @@ internal class VisionUpdateTest { propertyChanged("top".asName(), SolidMaterial.MATERIAL_COLOR_KEY, Meta("red".asValue())) propertyChanged("origin".asName(), SolidMaterial.MATERIAL_COLOR_KEY, Meta("red".asValue())) } - targetVision.receiveChange(dif) + targetVision.update(dif) assertTrue { targetVision.children.getChild("top") is SolidGroup } assertEquals("red", (targetVision.children.getChild("origin") as Solid).color.string) // Should work assertEquals(