Add click handlers
This commit is contained in:
parent
e6bdb67262
commit
80284a99ef
@ -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<VisionControlEvent>
|
||||||
|
|
||||||
|
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<VisionClickEvent>().onEach(block).launchIn(scope)
|
||||||
|
}
|
||||||
|
|
||||||
|
public companion object {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -4,7 +4,8 @@ import kotlinx.coroutines.CoroutineScope
|
|||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.onEach
|
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.asValue
|
||||||
import space.kscience.dataforge.meta.boolean
|
import space.kscience.dataforge.meta.boolean
|
||||||
import space.kscience.dataforge.meta.descriptors.Described
|
import space.kscience.dataforge.meta.descriptors.Described
|
||||||
@ -37,7 +38,7 @@ public interface Vision : Described {
|
|||||||
/**
|
/**
|
||||||
* Update this vision using a dif represented by [VisionChange].
|
* Update this vision using a dif represented by [VisionChange].
|
||||||
*/
|
*/
|
||||||
public fun receiveChange(change: VisionChange) {
|
public fun update(change: VisionChange) {
|
||||||
if (change.children?.isNotEmpty() == true) {
|
if (change.children?.isNotEmpty() == true) {
|
||||||
error("Vision is not a group")
|
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].
|
* Receive and process a generic [VisionEvent].
|
||||||
*/
|
*/
|
||||||
public fun receiveEvent(event: VisionEvent) {
|
public fun receiveEvent(event: VisionEvent) {
|
||||||
when (event) {
|
if(event is VisionChange) update(event)
|
||||||
is VisionChange -> receiveChange(event)
|
else manager?.logger?.warn { "Undispatched event: $event" }
|
||||||
is VisionMetaEvent -> onMetaEvent(event.meta)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override val descriptor: MetaDescriptor?
|
override val descriptor: MetaDescriptor?
|
||||||
|
@ -3,8 +3,6 @@ package space.kscience.visionforge
|
|||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import space.kscience.dataforge.meta.Meta
|
import space.kscience.dataforge.meta.Meta
|
||||||
import space.kscience.dataforge.meta.MutableMeta
|
|
||||||
import space.kscience.dataforge.meta.set
|
|
||||||
import space.kscience.dataforge.names.Name
|
import space.kscience.dataforge.names.Name
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -22,14 +20,4 @@ public sealed interface VisionEvent {
|
|||||||
*/
|
*/
|
||||||
@Serializable
|
@Serializable
|
||||||
@SerialName("meta")
|
@SerialName("meta")
|
||||||
public class VisionMetaEvent(public val meta: Meta) : VisionEvent
|
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)
|
|
||||||
}
|
|
@ -17,12 +17,12 @@ import space.kscience.visionforge.Vision.Companion.STYLE_KEY
|
|||||||
public interface VisionGroup : Vision {
|
public interface VisionGroup : Vision {
|
||||||
public val children: VisionChildren
|
public val children: VisionChildren
|
||||||
|
|
||||||
override fun receiveChange(change: VisionChange) {
|
override fun update(change: VisionChange) {
|
||||||
change.children?.forEach { (name, change) ->
|
change.children?.forEach { (name, change) ->
|
||||||
if (change.vision != null || change.vision == NullVision) {
|
if (change.vision != null || change.vision == NullVision) {
|
||||||
error("VisionGroup is read-only")
|
error("VisionGroup is read-only")
|
||||||
} else {
|
} else {
|
||||||
children.getChild(name)?.receiveChange(change)
|
children.getChild(name)?.update(change)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
change.properties?.let {
|
change.properties?.let {
|
||||||
@ -37,12 +37,12 @@ public interface MutableVisionGroup : VisionGroup {
|
|||||||
|
|
||||||
public fun createGroup(): MutableVisionGroup
|
public fun createGroup(): MutableVisionGroup
|
||||||
|
|
||||||
override fun receiveChange(change: VisionChange) {
|
override fun update(change: VisionChange) {
|
||||||
change.children?.forEach { (name, change) ->
|
change.children?.forEach { (name, change) ->
|
||||||
when {
|
when {
|
||||||
change.vision == NullVision -> children.setChild(name, null)
|
change.vision == NullVision -> children.setChild(name, null)
|
||||||
change.vision != null -> children.setChild(name, change.vision)
|
change.vision != null -> children.setChild(name, change.vision)
|
||||||
else -> children.getChild(name)?.receiveChange(change)
|
else -> children.getChild(name)?.update(change)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
change.properties?.let {
|
change.properties?.let {
|
||||||
|
@ -28,7 +28,7 @@ internal class VisionUpdateTest {
|
|||||||
propertyChanged("top".asName(), SolidMaterial.MATERIAL_COLOR_KEY, Meta("red".asValue()))
|
propertyChanged("top".asName(), SolidMaterial.MATERIAL_COLOR_KEY, Meta("red".asValue()))
|
||||||
propertyChanged("origin".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 }
|
assertTrue { targetVision.children.getChild("top") is SolidGroup }
|
||||||
assertEquals("red", (targetVision.children.getChild("origin") as Solid).color.string) // Should work
|
assertEquals("red", (targetVision.children.getChild("origin") as Solid).color.string) // Should work
|
||||||
assertEquals(
|
assertEquals(
|
||||||
|
Loading…
Reference in New Issue
Block a user