diff --git a/controls-core/src/commonMain/kotlin/space/kscience/controls/spec/DeviceSpec.kt b/controls-core/src/commonMain/kotlin/space/kscience/controls/spec/DeviceSpec.kt index b5813b7..19e5ab2 100644 --- a/controls-core/src/commonMain/kotlin/space/kscience/controls/spec/DeviceSpec.kt +++ b/controls-core/src/commonMain/kotlin/space/kscience/controls/spec/DeviceSpec.kt @@ -8,9 +8,7 @@ import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.transformations.MetaConverter import kotlin.properties.PropertyDelegateProvider import kotlin.properties.ReadOnlyProperty -import kotlin.reflect.KMutableProperty1 import kotlin.reflect.KProperty -import kotlin.reflect.KProperty1 public object UnitMetaConverter : MetaConverter { override fun metaToObject(meta: Meta): Unit = Unit @@ -44,11 +42,11 @@ public abstract class DeviceSpec { return deviceProperty } - public inline fun property( + public fun property( converter: MetaConverter, - crossinline descriptorBuilder: PropertyDescriptor.() -> Unit = {}, + descriptorBuilder: PropertyDescriptor.() -> Unit = {}, name: String? = null, - crossinline read: suspend D.(propertyName: String) -> T?, + read: suspend D.(propertyName: String) -> T?, ): PropertyDelegateProvider, ReadOnlyProperty, DevicePropertySpec>> = PropertyDelegateProvider { _: DeviceSpec, property -> val propertyName = name ?: property.name @@ -56,7 +54,8 @@ public abstract class DeviceSpec { override val descriptor: PropertyDescriptor = PropertyDescriptor(propertyName).apply(descriptorBuilder) override val converter: MetaConverter = converter - override suspend fun read(device: D): T? = withContext(device.coroutineContext) { device.read(propertyName) } + override suspend fun read(device: D): T? = + withContext(device.coroutineContext) { device.read(propertyName) } } registerProperty(deviceProperty) ReadOnlyProperty, DevicePropertySpec> { _, _ -> @@ -64,12 +63,12 @@ public abstract class DeviceSpec { } } - public inline fun mutableProperty( + public fun mutableProperty( converter: MetaConverter, - crossinline descriptorBuilder: PropertyDescriptor.() -> Unit = {}, + descriptorBuilder: PropertyDescriptor.() -> Unit = {}, name: String? = null, - crossinline read: suspend D.(propertyName: String) -> T?, - crossinline write: suspend D.(propertyName: String, value: T) -> Unit, + read: suspend D.(propertyName: String) -> T?, + write: suspend D.(propertyName: String, value: T) -> Unit, ): PropertyDelegateProvider, ReadOnlyProperty, MutableDevicePropertySpec>> = PropertyDelegateProvider { _: DeviceSpec, property: KProperty<*> -> val propertyName = name ?: property.name @@ -106,7 +105,7 @@ public abstract class DeviceSpec { name: String? = null, execute: suspend D.(I) -> O, ): PropertyDelegateProvider, ReadOnlyProperty, DeviceActionSpec>> = - PropertyDelegateProvider { _: DeviceSpec, property -> + PropertyDelegateProvider { _: DeviceSpec, property: KProperty<*> -> val actionName = name ?: property.name val deviceAction = object : DeviceActionSpec { override val descriptor: ActionDescriptor = ActionDescriptor(actionName).apply(descriptorBuilder) @@ -124,77 +123,39 @@ public abstract class DeviceSpec { } } - /** - * An action that takes [Meta] and returns [Meta]. No conversions are done - */ - public fun metaAction( - descriptorBuilder: ActionDescriptor.() -> Unit = {}, - name: String? = null, - execute: suspend D.(Meta) -> Meta, - ): PropertyDelegateProvider, ReadOnlyProperty, DeviceActionSpec>> = - action( - MetaConverter.Companion.meta, - MetaConverter.Companion.meta, - descriptorBuilder, - name - ) { - execute(it) - } - - /** - * An action that takes no parameters and returns no values - */ - public fun unitAction( - descriptorBuilder: ActionDescriptor.() -> Unit = {}, - name: String? = null, - execute: suspend D.() -> Unit, - ): PropertyDelegateProvider, ReadOnlyProperty, DeviceActionSpec>> = - action( - MetaConverter.Companion.unit, - MetaConverter.Companion.unit, - descriptorBuilder, - name - ) { - execute() - } } -public inline fun DeviceSpec.property( - converter: MetaConverter, - readOnlyProperty: KProperty1, - crossinline descriptorBuilder: PropertyDescriptor.() -> Unit = {}, -): PropertyDelegateProvider, ReadOnlyProperty, DevicePropertySpec>> = property( - converter, - descriptorBuilder, - name = readOnlyProperty.name, - read = { readOnlyProperty.get(this) } -) - -public inline fun DeviceSpec.mutableProperty( - converter: MetaConverter, - readWriteProperty: KMutableProperty1, - crossinline descriptorBuilder: PropertyDescriptor.() -> Unit = {}, -): PropertyDelegateProvider, ReadOnlyProperty, MutableDevicePropertySpec>> = - mutableProperty( - converter, +/** + * An action that takes no parameters and returns no values + */ +public fun DeviceSpec.unitAction( + descriptorBuilder: ActionDescriptor.() -> Unit = {}, + name: String? = null, + execute: suspend D.() -> Unit, +): PropertyDelegateProvider, ReadOnlyProperty, DeviceActionSpec>> = + action( + MetaConverter.Companion.unit, + MetaConverter.Companion.unit, descriptorBuilder, - readWriteProperty.name, - read = { _ -> readWriteProperty.get(this) }, - write = { _, value: T -> readWriteProperty.set(this, value) } - ) + name + ) { + execute() + } /** - * Register a mutable logical property (without a corresponding physical state) for a device + * An action that takes [Meta] and returns [Meta]. No conversions are done */ -public inline fun > DeviceSpec.logicalProperty( - converter: MetaConverter, - crossinline descriptorBuilder: PropertyDescriptor.() -> Unit = {}, +public fun DeviceSpec.metaAction( + descriptorBuilder: ActionDescriptor.() -> Unit = {}, name: String? = null, -): PropertyDelegateProvider, ReadOnlyProperty, MutableDevicePropertySpec>> = - mutableProperty( - converter, + execute: suspend D.(Meta) -> Meta, +): PropertyDelegateProvider, ReadOnlyProperty, DeviceActionSpec>> = + action( + MetaConverter.Companion.meta, + MetaConverter.Companion.meta, descriptorBuilder, - name, - read = { propertyName -> getProperty(propertyName)?.let(converter::metaToObject) }, - write = { propertyName, value -> writeProperty(propertyName, converter.objectToMeta(value)) } - ) \ No newline at end of file + name + ) { + execute(it) + } + diff --git a/controls-core/src/commonMain/kotlin/space/kscience/controls/spec/propertySpecDelegates.kt b/controls-core/src/commonMain/kotlin/space/kscience/controls/spec/propertySpecDelegates.kt index 8314838..6f599a8 100644 --- a/controls-core/src/commonMain/kotlin/space/kscience/controls/spec/propertySpecDelegates.kt +++ b/controls-core/src/commonMain/kotlin/space/kscience/controls/spec/propertySpecDelegates.kt @@ -8,6 +8,55 @@ import space.kscience.dataforge.meta.ValueType import space.kscience.dataforge.meta.transformations.MetaConverter import kotlin.properties.PropertyDelegateProvider import kotlin.properties.ReadOnlyProperty +import kotlin.reflect.KMutableProperty1 +import kotlin.reflect.KProperty1 + +/** + * A read-only device property that delegates reading to a device [KProperty1] + */ +public fun DeviceSpec.property( + converter: MetaConverter, + readOnlyProperty: KProperty1, + descriptorBuilder: PropertyDescriptor.() -> Unit = {}, +): PropertyDelegateProvider, ReadOnlyProperty, DevicePropertySpec>> = property( + converter, + descriptorBuilder, + name = readOnlyProperty.name, + read = { readOnlyProperty.get(this) } +) + +/** + * Mutable property that delegates reading and writing to a device [KMutableProperty1] + */ +public fun DeviceSpec.mutableProperty( + converter: MetaConverter, + readWriteProperty: KMutableProperty1, + descriptorBuilder: PropertyDescriptor.() -> Unit = {}, +): PropertyDelegateProvider, ReadOnlyProperty, MutableDevicePropertySpec>> = + mutableProperty( + converter, + descriptorBuilder, + readWriteProperty.name, + read = { _ -> readWriteProperty.get(this) }, + write = { _, value: T -> readWriteProperty.set(this, value) } + ) + +/** + * Register a mutable logical property (without a corresponding physical state) for a device + */ +public fun > DeviceSpec.logicalProperty( + converter: MetaConverter, + descriptorBuilder: PropertyDescriptor.() -> Unit = {}, + name: String? = null, +): PropertyDelegateProvider, ReadOnlyProperty, MutableDevicePropertySpec>> = + mutableProperty( + converter, + descriptorBuilder, + name, + read = { propertyName -> getProperty(propertyName)?.let(converter::metaToObject) }, + write = { propertyName, value -> writeProperty(propertyName, converter.objectToMeta(value)) } + ) + //read only delegates