[WIP] working on constructor

This commit is contained in:
Alexander Nozik 2024-05-21 13:31:01 +03:00
parent a66e411848
commit 673a7c89a6
6 changed files with 92 additions and 59 deletions

View File

@ -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<T>(
public val device: Device,
public val propertyName: String,
public val state: DeviceState<T>,
) : Binding
/**
* A binding for independent state like a timer
*/
public class StateBinding<T>(
public val state: DeviceState<T>
) : Binding
public class ActionBinding(
public val reads: Collection<DeviceState<*>>,
public val writes: Collection<DeviceState<*>>
): Binding
public interface BindingsContainer{
public val bindings: List<Binding>
public fun registerBinding(binding: Binding)
}

View File

@ -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<Binding> = mutableListOf()
override val bindings: List<Binding> get() = _bindings
) : DeviceGroup(context, meta), StateContainer {
private val _stateDescriptors: MutableList<StateDescriptor> = mutableListOf()
override val stateDescriptors: List<StateDescriptor> 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<DeviceState<*>>,
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)))
}
}

View File

@ -1,12 +1,14 @@
package space.kscience.controls.constructor
public abstract class DeviceModel : BindingsContainer {
import space.kscience.dataforge.context.Context
private val _bindings: MutableList<Binding> = mutableListOf()
public abstract class DeviceModel(override val context: Context) : StateContainer {
override val bindings: List<Binding> get() = _bindings
private val _stateDescriptors: MutableList<StateDescriptor> = mutableListOf()
override fun registerBinding(binding: Binding) {
_bindings.add(binding)
override val stateDescriptors: List<StateDescriptor> get() = _stateDescriptors
override fun registerState(stateDescriptor: StateDescriptor) {
_stateDescriptors.add(stateDescriptor)
}
}

View File

@ -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<T>(
public val device: Device,
public val propertyName: String,
public val state: DeviceState<T>,
) : StateDescriptor
/**
* A binding for independent state like a timer
*/
public class StateBinding<T>(
public val state: DeviceState<T>,
) : StateDescriptor
public class ConnectionStateDescriptor(
public val reads: Collection<DeviceState<*>>,
public val writes: Collection<DeviceState<*>>,
) : StateDescriptor
public interface StateContainer : ContextAware {
public val stateDescriptors: List<StateDescriptor>
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 <T, D : DeviceState<T>> StateContainer.state(state: D): D {
registerState(StateBinding(state))
return state
}
/**
* Create a register a [MutableDeviceState] with a given [converter]
*/
public fun <T> StateContainer.state(converter: MetaConverter<T>, initialValue: T): MutableDeviceState<T> = state(
DeviceState.internal(converter, initialValue)
)
/**
* Create a register a mutable [Double] state
*/
public fun StateContainer.doubleState(initialValue: Double): MutableDeviceState<Double> = state(
MetaConverter.double, initialValue
)
/**
* Create a register a mutable [String] state
*/
public fun StateContainer.stringState(initialValue: String): MutableDeviceState<String> = state(
MetaConverter.string, initialValue
)
/**
* Create and register a timer state.
*/
public fun StateContainer.timer(tick: Duration): TimerState = state(TimerState(context.request(ClockManager), tick))

View File

@ -51,9 +51,9 @@ public class DoubleInRangeState(
/**
* Create and register a [DoubleInRangeState]
*/
public fun BindingsContainer.doubleInRangeState(
public fun StateContainer.doubleInRangeState(
initialValue: Double,
range: ClosedFloatingPointRange<Double>,
): DoubleInRangeState = DoubleInRangeState(initialValue, range).also {
registerBinding(StateBinding(it))
registerState(StateBinding(it))
}

View File

@ -12,7 +12,7 @@ kscience {
useKtor()
useSerialization()
useContextReceivers()
dependencies {
commonMain {
api(projects.controlsCore)
api(projects.controlsConstructor)
api(libs.visionforge.plotly)