From 673a7c89a6e6e06a089da89c60492f559284c745 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 21 May 2024 13:31:01 +0300 Subject: [PATCH] [WIP] working on constructor --- .../kscience/controls/constructor/Binding.kt | 35 --------- .../controls/constructor/DeviceConstructor.kt | 24 ++---- .../controls/constructor/DeviceModel.kt | 12 +-- .../controls/constructor/StateDescriptor.kt | 74 +++++++++++++++++++ .../{customState.kt => exoticState.kt} | 4 +- controls-vision/build.gradle.kts | 2 +- 6 files changed, 92 insertions(+), 59 deletions(-) delete mode 100644 controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/Binding.kt create mode 100644 controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/StateDescriptor.kt rename controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/{customState.kt => exoticState.kt} (94%) diff --git a/controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/Binding.kt b/controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/Binding.kt deleted file mode 100644 index d712d62..0000000 --- a/controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/Binding.kt +++ /dev/null @@ -1,35 +0,0 @@ -package space.kscience.controls.constructor - -import space.kscience.controls.api.Device - -/** - * A binding that is used to describe device functionality - */ -public sealed interface Binding - -/** - * A binding that exposes device property as read-only state - */ -public class PropertyBinding( - public val device: Device, - public val propertyName: String, - public val state: DeviceState, -) : Binding - -/** - * A binding for independent state like a timer - */ -public class StateBinding( - public val state: DeviceState -) : Binding - -public class ActionBinding( - public val reads: Collection>, - public val writes: Collection> -): Binding - - -public interface BindingsContainer{ - public val bindings: List - public fun registerBinding(binding: Binding) -} \ No newline at end of file diff --git a/controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/DeviceConstructor.kt b/controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/DeviceConstructor.kt index 5b6ff9f..03a1e0e 100644 --- a/controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/DeviceConstructor.kt +++ b/controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/DeviceConstructor.kt @@ -5,12 +5,10 @@ import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import space.kscience.controls.api.Device import space.kscience.controls.api.PropertyDescriptor -import space.kscience.controls.manager.ClockManager import space.kscience.controls.spec.DevicePropertySpec import space.kscience.controls.spec.MutableDevicePropertySpec import space.kscience.dataforge.context.Context import space.kscience.dataforge.context.Factory -import space.kscience.dataforge.context.request import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.MetaConverter import space.kscience.dataforge.names.Name @@ -26,25 +24,19 @@ import kotlin.time.Duration public abstract class DeviceConstructor( context: Context, meta: Meta = Meta.EMPTY, -) : DeviceGroup(context, meta), BindingsContainer { - private val _bindings: MutableList = mutableListOf() - override val bindings: List get() = _bindings +) : DeviceGroup(context, meta), StateContainer { + private val _stateDescriptors: MutableList = mutableListOf() + override val stateDescriptors: List get() = _stateDescriptors - override fun registerBinding(binding: Binding) { - _bindings.add(binding) + override fun registerState(stateDescriptor: StateDescriptor) { + _stateDescriptors.add(stateDescriptor) } override fun registerProperty(descriptor: PropertyDescriptor, state: DeviceState<*>) { super.registerProperty(descriptor, state) - registerBinding(PropertyBinding(this, descriptor.name, state)) + registerState(PropertyStateDescriptor(this, descriptor.name, state)) } - /** - * Create and register a timer. Timer is not counted as a device property. - */ - public fun timer(tick: Duration): TimerState = TimerState(context.request(ClockManager), tick) - .also { registerBinding(StateBinding(it)) } - /** * Bind an action to a [DeviceState]. [onChange] block is performed on each state change * @@ -55,7 +47,7 @@ public abstract class DeviceConstructor( reads: Collection>, onChange: suspend (T) -> Unit, ): Job = valueFlow.onEach(onChange).launchIn(this@DeviceConstructor).also { - registerBinding(ActionBinding(setOf(this, *reads.toTypedArray()), setOf(*writes))) + registerState(ConnectionStateDescriptor(setOf(this, *reads.toTypedArray()), setOf(*writes))) } } @@ -171,4 +163,4 @@ public fun DeviceConstructor.deviceProperty( property: MutableDevicePropertySpec, initialValue: T, ): PropertyDelegateProvider>> = - property(device.mutablePropertyAsState(property, initialValue)) \ No newline at end of file + property(device.mutablePropertyAsState(property, initialValue)) diff --git a/controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/DeviceModel.kt b/controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/DeviceModel.kt index 08913a2..6d44422 100644 --- a/controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/DeviceModel.kt +++ b/controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/DeviceModel.kt @@ -1,12 +1,14 @@ package space.kscience.controls.constructor -public abstract class DeviceModel : BindingsContainer { +import space.kscience.dataforge.context.Context - private val _bindings: MutableList = mutableListOf() +public abstract class DeviceModel(override val context: Context) : StateContainer { - override val bindings: List get() = _bindings + private val _stateDescriptors: MutableList = mutableListOf() - override fun registerBinding(binding: Binding) { - _bindings.add(binding) + override val stateDescriptors: List get() = _stateDescriptors + + override fun registerState(stateDescriptor: StateDescriptor) { + _stateDescriptors.add(stateDescriptor) } } \ No newline at end of file diff --git a/controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/StateDescriptor.kt b/controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/StateDescriptor.kt new file mode 100644 index 0000000..b8f40b5 --- /dev/null +++ b/controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/StateDescriptor.kt @@ -0,0 +1,74 @@ +package space.kscience.controls.constructor + +import space.kscience.controls.api.Device +import space.kscience.controls.manager.ClockManager +import space.kscience.dataforge.context.ContextAware +import space.kscience.dataforge.context.request +import space.kscience.dataforge.meta.MetaConverter +import kotlin.time.Duration + +/** + * A binding that is used to describe device functionality + */ +public sealed interface StateDescriptor + +/** + * A binding that exposes device property as read-only state + */ +public class PropertyStateDescriptor( + public val device: Device, + public val propertyName: String, + public val state: DeviceState, +) : StateDescriptor + +/** + * A binding for independent state like a timer + */ +public class StateBinding( + public val state: DeviceState, +) : StateDescriptor + +public class ConnectionStateDescriptor( + public val reads: Collection>, + public val writes: Collection>, +) : StateDescriptor + + +public interface StateContainer : ContextAware { + public val stateDescriptors: List + public fun registerState(stateDescriptor: StateDescriptor) +} + +/** + * Register a [state] in this container. The state is not registered as a device property if [this] is a [DeviceConstructor] + */ +public fun > StateContainer.state(state: D): D { + registerState(StateBinding(state)) + return state +} + +/** + * Create a register a [MutableDeviceState] with a given [converter] + */ +public fun StateContainer.state(converter: MetaConverter, initialValue: T): MutableDeviceState = state( + DeviceState.internal(converter, initialValue) +) + +/** + * Create a register a mutable [Double] state + */ +public fun StateContainer.doubleState(initialValue: Double): MutableDeviceState = state( + MetaConverter.double, initialValue +) + +/** + * Create a register a mutable [String] state + */ +public fun StateContainer.stringState(initialValue: String): MutableDeviceState = state( + MetaConverter.string, initialValue +) + +/** + * Create and register a timer state. + */ +public fun StateContainer.timer(tick: Duration): TimerState = state(TimerState(context.request(ClockManager), tick)) diff --git a/controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/customState.kt b/controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/exoticState.kt similarity index 94% rename from controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/customState.kt rename to controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/exoticState.kt index 277271a..d1d557f 100644 --- a/controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/customState.kt +++ b/controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/exoticState.kt @@ -51,9 +51,9 @@ public class DoubleInRangeState( /** * Create and register a [DoubleInRangeState] */ -public fun BindingsContainer.doubleInRangeState( +public fun StateContainer.doubleInRangeState( initialValue: Double, range: ClosedFloatingPointRange, ): DoubleInRangeState = DoubleInRangeState(initialValue, range).also { - registerBinding(StateBinding(it)) + registerState(StateBinding(it)) } \ No newline at end of file diff --git a/controls-vision/build.gradle.kts b/controls-vision/build.gradle.kts index 5c75242..09c644b 100644 --- a/controls-vision/build.gradle.kts +++ b/controls-vision/build.gradle.kts @@ -12,7 +12,7 @@ kscience { useKtor() useSerialization() useContextReceivers() - dependencies { + commonMain { api(projects.controlsCore) api(projects.controlsConstructor) api(libs.visionforge.plotly)