forked from kscience/visionforge
Add direct event processing to Vision
This commit is contained in:
parent
1ea5ef86e6
commit
c7d4bdfa5f
@ -45,7 +45,7 @@ include(
|
||||
":ui:ring",
|
||||
// ":ui:material",
|
||||
":ui:bootstrap",
|
||||
":ui:compose",
|
||||
// ":ui:compose",
|
||||
":visionforge-core",
|
||||
":visionforge-solid",
|
||||
// ":visionforge-fx",
|
||||
|
@ -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,14 +49,10 @@ 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)
|
||||
is VisionChange -> receiveChange(event)
|
||||
else -> TODO()
|
||||
}
|
||||
} else {
|
||||
error("Vision is not a group and can't process an event with non-empty target")
|
||||
}
|
||||
}
|
||||
|
||||
override val descriptor: MetaDescriptor?
|
||||
|
@ -63,8 +63,7 @@ public data class VisionChange(
|
||||
public val vision: Vision? = null,
|
||||
public val properties: Meta? = null,
|
||||
public val children: Map<Name, VisionChange>? = null,
|
||||
)
|
||||
|
||||
) : VisionEvent
|
||||
|
||||
/**
|
||||
* An update for a [Vision]
|
||||
|
@ -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()))
|
||||
}
|
||||
}
|
@ -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")
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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<VisionEvent>(meta["feedback.eventCache"].int ?: 100)
|
||||
MutableSharedFlow<Pair<Name, VisionEvent>>(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()
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user