[WIP] great refactoring in progress
This commit is contained in:
parent
791d6d7a81
commit
9b1ca8332b
@ -3,7 +3,6 @@ package ru.mipt.npm.root
|
|||||||
import space.kscience.dataforge.meta.double
|
import space.kscience.dataforge.meta.double
|
||||||
import space.kscience.dataforge.meta.get
|
import space.kscience.dataforge.meta.get
|
||||||
import space.kscience.dataforge.meta.int
|
import space.kscience.dataforge.meta.int
|
||||||
import space.kscience.dataforge.meta.isEmpty
|
|
||||||
import space.kscience.dataforge.names.Name
|
import space.kscience.dataforge.names.Name
|
||||||
import space.kscience.dataforge.names.plus
|
import space.kscience.dataforge.names.plus
|
||||||
import space.kscience.dataforge.values.doubleArray
|
import space.kscience.dataforge.values.doubleArray
|
||||||
@ -322,7 +321,7 @@ private fun buildVolume(volume: DGeoVolume, context: RootToSolidContext): Solid?
|
|||||||
}
|
}
|
||||||
return if (group.children.isEmpty()) {
|
return if (group.children.isEmpty()) {
|
||||||
null
|
null
|
||||||
} else if (group.items.size == 1 && group.meta.isEmpty()) {
|
} else if (group.items.size == 1 && group.meta== null) {
|
||||||
group.items.values.first().apply { parent = null }
|
group.items.values.first().apply { parent = null }
|
||||||
} else {
|
} else {
|
||||||
group
|
group
|
||||||
|
@ -6,7 +6,6 @@ import space.kscience.dataforge.values.asValue
|
|||||||
import space.kscience.gdml.GdmlShowCase
|
import space.kscience.gdml.GdmlShowCase
|
||||||
import space.kscience.visionforge.Vision
|
import space.kscience.visionforge.Vision
|
||||||
import space.kscience.visionforge.get
|
import space.kscience.visionforge.get
|
||||||
import space.kscience.visionforge.getProperty
|
|
||||||
import space.kscience.visionforge.getPropertyValue
|
import space.kscience.visionforge.getPropertyValue
|
||||||
import space.kscience.visionforge.solid.Solid
|
import space.kscience.visionforge.solid.Solid
|
||||||
import space.kscience.visionforge.solid.SolidMaterial
|
import space.kscience.visionforge.solid.SolidMaterial
|
||||||
|
@ -3,7 +3,7 @@ package ru.mipt.npm.muon.monitor
|
|||||||
import ru.mipt.npm.muon.monitor.Monitor.CENTRAL_LAYER_Z
|
import ru.mipt.npm.muon.monitor.Monitor.CENTRAL_LAYER_Z
|
||||||
import ru.mipt.npm.muon.monitor.Monitor.LOWER_LAYER_Z
|
import ru.mipt.npm.muon.monitor.Monitor.LOWER_LAYER_Z
|
||||||
import ru.mipt.npm.muon.monitor.Monitor.UPPER_LAYER_Z
|
import ru.mipt.npm.muon.monitor.Monitor.UPPER_LAYER_Z
|
||||||
import space.kscience.visionforge.VisionContainerBuilder
|
import space.kscience.visionforge.MutableVisionContainer
|
||||||
import space.kscience.visionforge.VisionManager
|
import space.kscience.visionforge.VisionManager
|
||||||
import space.kscience.visionforge.setAsRoot
|
import space.kscience.visionforge.setAsRoot
|
||||||
import space.kscience.visionforge.solid.*
|
import space.kscience.visionforge.solid.*
|
||||||
@ -14,7 +14,7 @@ class Model(val manager: VisionManager) {
|
|||||||
private val map = HashMap<String, SolidGroup>()
|
private val map = HashMap<String, SolidGroup>()
|
||||||
private val events = HashSet<Event>()
|
private val events = HashSet<Event>()
|
||||||
|
|
||||||
private fun VisionContainerBuilder<Solid>.pixel(pixel: SC1) {
|
private fun MutableVisionContainer<Solid>.pixel(pixel: SC1) {
|
||||||
val group = group(pixel.name) {
|
val group = group(pixel.name) {
|
||||||
position = Point3D(pixel.center.x, pixel.center.y, pixel.center.z)
|
position = Point3D(pixel.center.x, pixel.center.y, pixel.center.z)
|
||||||
box(pixel.xSize, pixel.ySize, pixel.zSize)
|
box(pixel.xSize, pixel.ySize, pixel.zSize)
|
||||||
|
@ -49,7 +49,7 @@ internal class VariableBox(val xSize: Number, val ySize: Number) : ThreeJsVision
|
|||||||
onPropertyChange { name ->
|
onPropertyChange { name ->
|
||||||
when {
|
when {
|
||||||
name == VALUE -> {
|
name == VALUE -> {
|
||||||
val value = meta.get(VALUE).int ?: 0
|
val value = meta[VALUE].int ?: 0
|
||||||
val size = value.toFloat() / 255f * 20f
|
val size = value.toFloat() / 255f * 20f
|
||||||
mesh.scale.z = size.toDouble()
|
mesh.scale.z = size.toDouble()
|
||||||
mesh.position.z = size.toDouble() / 2
|
mesh.position.z = size.toDouble() / 2
|
||||||
|
@ -3,101 +3,105 @@ package space.kscience.visionforge
|
|||||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||||
import kotlinx.coroutines.flow.SharedFlow
|
import kotlinx.coroutines.flow.SharedFlow
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Transient
|
import kotlinx.serialization.Transient
|
||||||
import space.kscience.dataforge.meta.Meta
|
import space.kscience.dataforge.meta.*
|
||||||
import space.kscience.dataforge.meta.MutableMeta
|
|
||||||
import space.kscience.dataforge.meta.asMutableMeta
|
|
||||||
import space.kscience.dataforge.meta.descriptors.MetaDescriptor
|
import space.kscience.dataforge.meta.descriptors.MetaDescriptor
|
||||||
import space.kscience.dataforge.meta.get
|
|
||||||
import space.kscience.dataforge.names.Name
|
import space.kscience.dataforge.names.Name
|
||||||
import space.kscience.dataforge.names.asName
|
import space.kscience.dataforge.names.asName
|
||||||
import space.kscience.dataforge.names.isEmpty
|
import space.kscience.dataforge.names.isEmpty
|
||||||
import space.kscience.dataforge.values.Value
|
import space.kscience.dataforge.values.Value
|
||||||
import space.kscience.visionforge.VisionGroup.Companion.updateProperties
|
import space.kscience.visionforge.AbstractVisionGroup.Companion.updateProperties
|
||||||
import kotlin.jvm.Synchronized
|
import kotlin.jvm.Synchronized
|
||||||
|
|
||||||
@Serializable
|
|
||||||
public abstract class AbstractVision : Vision {
|
public abstract class AbstractVision : Vision {
|
||||||
|
|
||||||
@Transient
|
@Transient
|
||||||
override var parent: Vision? = null
|
override var parent: Vision? = null
|
||||||
|
|
||||||
protected var properties: MutableMeta? = null
|
@SerialName("properties")
|
||||||
|
internal var _properties: MutableMeta? = null
|
||||||
|
|
||||||
override val meta: Meta get() = properties ?: Meta.EMPTY
|
protected open val defaultProperties: Meta? get() = descriptor?.defaultNode
|
||||||
|
|
||||||
@Synchronized
|
|
||||||
private fun getOrCreateProperties(): MutableMeta {
|
|
||||||
if (properties == null) {
|
|
||||||
//TODO check performance issues
|
|
||||||
val newProperties = MutableMeta()
|
|
||||||
properties = newProperties
|
|
||||||
}
|
|
||||||
return properties!!
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transient
|
@Transient
|
||||||
private val _propertyChanges = MutableSharedFlow<Name>()
|
final override val properties: MutableVisionProperties = object : MutableVisionProperties {
|
||||||
override val propertyChanges: SharedFlow<Name> get() = _propertyChanges
|
override val descriptor: MetaDescriptor? get() = this@AbstractVision.descriptor
|
||||||
|
override val default: Meta? get() = defaultProperties
|
||||||
|
|
||||||
override fun getPropertyValue(
|
@Synchronized
|
||||||
name: Name,
|
private fun getOrCreateProperties(): MutableMeta {
|
||||||
inherit: Boolean,
|
if (_properties == null) {
|
||||||
includeStyles: Boolean,
|
//TODO check performance issues
|
||||||
includeDefaults: Boolean,
|
val newProperties = MutableMeta()
|
||||||
): Value? {
|
_properties = newProperties
|
||||||
properties?.get(name)?.value?.let { return it }
|
}
|
||||||
if (includeStyles) {
|
return _properties!!
|
||||||
getStyleProperty(name)?.value?.let { return it }
|
|
||||||
}
|
}
|
||||||
if (inherit) {
|
|
||||||
parent?.getPropertyValue(name, inherit, includeStyles, includeDefaults)?.let { return it }
|
|
||||||
}
|
|
||||||
if (includeDefaults) {
|
|
||||||
descriptor?.defaultNode?.get(name)?.value?.let { return it }
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setProperty(name: Name, node: Meta?) {
|
override val raw: Meta? get() = _properties
|
||||||
//TODO check old value?
|
|
||||||
if (name.isEmpty()) {
|
|
||||||
properties = node?.asMutableMeta()
|
|
||||||
} else if (node == null) {
|
|
||||||
properties?.setMeta(name, node)
|
|
||||||
} else {
|
|
||||||
getOrCreateProperties().setMeta(name, node)
|
|
||||||
}
|
|
||||||
invalidateProperty(name)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setPropertyValue(name: Name, value: Value?) {
|
override fun getValue(
|
||||||
//TODO check old value?
|
name: Name,
|
||||||
if (value == null) {
|
inherit: Boolean,
|
||||||
properties?.getMeta(name)?.value = null
|
includeStyles: Boolean,
|
||||||
} else {
|
): Value? {
|
||||||
getOrCreateProperties().setValue(name, value)
|
raw?.get(name)?.value?.let { return it }
|
||||||
|
if (includeStyles) {
|
||||||
|
getStyleProperty(name)?.value?.let { return it }
|
||||||
|
}
|
||||||
|
if (inherit) {
|
||||||
|
parent?.properties?.getValue(name, inherit, includeStyles)?.let { return it }
|
||||||
|
}
|
||||||
|
return default?.get(name)?.value
|
||||||
}
|
}
|
||||||
invalidateProperty(name)
|
|
||||||
|
override fun set(name: Name, node: Meta?) {
|
||||||
|
//TODO check old value?
|
||||||
|
if (name.isEmpty()) {
|
||||||
|
_properties = node?.asMutableMeta()
|
||||||
|
} else if (node == null) {
|
||||||
|
_properties?.setMeta(name, node)
|
||||||
|
} else {
|
||||||
|
getOrCreateProperties().setMeta(name, node)
|
||||||
|
}
|
||||||
|
invalidate(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setValue(name: Name, value: Value?) {
|
||||||
|
//TODO check old value?
|
||||||
|
if (value == null) {
|
||||||
|
_properties?.getMeta(name)?.value = null
|
||||||
|
} else {
|
||||||
|
getOrCreateProperties().setValue(name, value)
|
||||||
|
}
|
||||||
|
invalidate(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transient
|
||||||
|
private val _changes = MutableSharedFlow<Name>()
|
||||||
|
override val changes: SharedFlow<Name> get() = _changes
|
||||||
|
|
||||||
|
override fun invalidate(propertyName: Name) {
|
||||||
|
if (propertyName == Vision.STYLE_KEY) {
|
||||||
|
styles.asSequence()
|
||||||
|
.mapNotNull { getStyle(it) }
|
||||||
|
.flatMap { it.items.asSequence() }
|
||||||
|
.distinctBy { it.key }
|
||||||
|
.forEach {
|
||||||
|
invalidate(it.key.asName())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
manager.context.launch {
|
||||||
|
_changes.emit(propertyName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override val descriptor: MetaDescriptor? get() = null
|
override val descriptor: MetaDescriptor? get() = null
|
||||||
|
|
||||||
override fun invalidateProperty(propertyName: Name) {
|
|
||||||
if (propertyName == Vision.STYLE_KEY) {
|
|
||||||
styles.asSequence()
|
|
||||||
.mapNotNull { getStyle(it) }
|
|
||||||
.flatMap { it.items.asSequence() }
|
|
||||||
.distinctBy { it.key }
|
|
||||||
.forEach {
|
|
||||||
invalidateProperty(it.key.asName())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
manager.context.launch {
|
|
||||||
_propertyChanges.emit(propertyName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun update(change: VisionChange) {
|
override fun update(change: VisionChange) {
|
||||||
change.properties?.let {
|
change.properties?.let {
|
||||||
|
@ -15,7 +15,7 @@ import kotlin.jvm.JvmInline
|
|||||||
@JvmInline
|
@JvmInline
|
||||||
public value class StyleSheet(private val owner: Vision) {
|
public value class StyleSheet(private val owner: Vision) {
|
||||||
|
|
||||||
private val styleNode: Meta get() = owner.getProperty(STYLESHEET_KEY)
|
private val styleNode: Meta get() = owner.properties[STYLESHEET_KEY]
|
||||||
|
|
||||||
public val items: Map<NameToken, Meta> get() = styleNode.items
|
public val items: Map<NameToken, Meta> get() = styleNode.items
|
||||||
|
|
||||||
@ -25,7 +25,7 @@ public value class StyleSheet(private val owner: Vision) {
|
|||||||
* Define a style without notifying owner
|
* Define a style without notifying owner
|
||||||
*/
|
*/
|
||||||
public fun define(key: String, style: Meta?) {
|
public fun define(key: String, style: Meta?) {
|
||||||
owner.setProperty(STYLESHEET_KEY + key, style)
|
owner.properties[STYLESHEET_KEY + key] = style
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -58,26 +58,24 @@ internal fun Vision.styleChanged(key: String, oldStyle: Meta?, newStyle: Meta?)
|
|||||||
val tokens: Collection<Name> =
|
val tokens: Collection<Name> =
|
||||||
((oldStyle?.items?.keys ?: emptySet()) + (newStyle?.items?.keys ?: emptySet()))
|
((oldStyle?.items?.keys ?: emptySet()) + (newStyle?.items?.keys ?: emptySet()))
|
||||||
.map { it.asName() }
|
.map { it.asName() }
|
||||||
tokens.forEach { parent?.invalidateProperty(it) }
|
tokens.forEach { parent?.properties?.invalidate(it) }
|
||||||
}
|
}
|
||||||
children.values.forEach { vision ->
|
children?.forEach { _, vision ->
|
||||||
vision.styleChanged(key, oldStyle, newStyle)
|
vision.styleChanged(key, oldStyle, newStyle)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of names of styles applied to this object. Order matters. Not inherited.
|
* List of names of styles applied to this object. Order matters. Not inherited.
|
||||||
*/
|
*/
|
||||||
public var Vision.styles: List<String>
|
public var Vision.styles: List<String>
|
||||||
get() = getPropertyValue(
|
get() = properties.getValue(
|
||||||
Vision.STYLE_KEY,
|
Vision.STYLE_KEY,
|
||||||
inherit = true,
|
inherit = true,
|
||||||
includeStyles = false,
|
includeStyles = false,
|
||||||
includeDefaults = false
|
|
||||||
)?.stringList ?: emptyList()
|
)?.stringList ?: emptyList()
|
||||||
set(value) {
|
set(value) {
|
||||||
setPropertyValue(Vision.STYLE_KEY, value.map { it.asValue() }.asValue())
|
properties.setValue(Vision.STYLE_KEY, value.map { it.asValue() }.asValue())
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -90,7 +88,7 @@ public val Vision.styleSheet: StyleSheet get() = StyleSheet(this)
|
|||||||
* Add style name to the list of styles to be resolved later. The style with given name does not necessary exist at the moment.
|
* Add style name to the list of styles to be resolved later. The style with given name does not necessary exist at the moment.
|
||||||
*/
|
*/
|
||||||
public fun Vision.useStyle(name: String) {
|
public fun Vision.useStyle(name: String) {
|
||||||
styles = (getPropertyValue(Vision.STYLE_KEY)?.stringList ?: emptyList()) + name
|
styles = (properties.getValue(Vision.STYLE_KEY)?.stringList ?: emptyList()) + name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -98,7 +96,7 @@ public fun Vision.useStyle(name: String) {
|
|||||||
* Resolve a style with given name for given [Vision]. The style is not necessarily applied to this [Vision].
|
* Resolve a style with given name for given [Vision]. The style is not necessarily applied to this [Vision].
|
||||||
*/
|
*/
|
||||||
public fun Vision.getStyle(name: String): Meta? =
|
public fun Vision.getStyle(name: String): Meta? =
|
||||||
meta.getMeta(StyleSheet.STYLESHEET_KEY + name) ?: parent?.getStyle(name)
|
properties.raw?.getMeta(StyleSheet.STYLESHEET_KEY + name) ?: parent?.getStyle(name)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve a property from all styles
|
* Resolve a property from all styles
|
||||||
|
@ -1,22 +1,15 @@
|
|||||||
package space.kscience.visionforge
|
package space.kscience.visionforge
|
||||||
|
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.flow.SharedFlow
|
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import space.kscience.dataforge.context.Global
|
import space.kscience.dataforge.context.Global
|
||||||
import space.kscience.dataforge.meta.Meta
|
|
||||||
import space.kscience.dataforge.meta.MutableMeta
|
|
||||||
import space.kscience.dataforge.meta.MutableMetaProvider
|
|
||||||
import space.kscience.dataforge.meta.descriptors.Described
|
import space.kscience.dataforge.meta.descriptors.Described
|
||||||
import space.kscience.dataforge.meta.descriptors.MetaDescriptor
|
import space.kscience.dataforge.meta.descriptors.MetaDescriptor
|
||||||
import space.kscience.dataforge.meta.descriptors.get
|
|
||||||
import space.kscience.dataforge.misc.Type
|
import space.kscience.dataforge.misc.Type
|
||||||
import space.kscience.dataforge.names.Name
|
import space.kscience.dataforge.names.Name
|
||||||
import space.kscience.dataforge.names.asName
|
import space.kscience.dataforge.names.asName
|
||||||
import space.kscience.dataforge.names.parseAsName
|
|
||||||
import space.kscience.dataforge.names.startsWith
|
import space.kscience.dataforge.names.startsWith
|
||||||
import space.kscience.dataforge.values.Value
|
|
||||||
import space.kscience.dataforge.values.asValue
|
import space.kscience.dataforge.values.asValue
|
||||||
import space.kscience.dataforge.values.boolean
|
import space.kscience.dataforge.values.boolean
|
||||||
import space.kscience.visionforge.Vision.Companion.TYPE
|
import space.kscience.visionforge.Vision.Companion.TYPE
|
||||||
@ -38,49 +31,8 @@ public interface Vision : Described {
|
|||||||
*/
|
*/
|
||||||
public val manager: VisionManager get() = parent?.manager ?: Global.visionManager
|
public val manager: VisionManager get() = parent?.manager ?: Global.visionManager
|
||||||
|
|
||||||
public val children: VisionChildren
|
|
||||||
|
|
||||||
/**
|
public val properties: MutableVisionProperties
|
||||||
* Own properties without inheritance or styles.
|
|
||||||
*/
|
|
||||||
public val meta: Meta
|
|
||||||
|
|
||||||
public fun getPropertyValue(
|
|
||||||
name: Name,
|
|
||||||
inherit: Boolean,
|
|
||||||
includeStyles: Boolean,
|
|
||||||
includeDefaults: Boolean,
|
|
||||||
): Value?
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get property with given layer flags.
|
|
||||||
* @param inherit toggles parent node property lookup. Null means inference from descriptor.
|
|
||||||
* @param includeStyles toggles inclusion of properties from styles.
|
|
||||||
*/
|
|
||||||
public fun getProperty(
|
|
||||||
name: Name,
|
|
||||||
inherit: Boolean,
|
|
||||||
includeStyles: Boolean,
|
|
||||||
includeDefaults: Boolean,
|
|
||||||
): MutableMeta = VisionProperties(this, name, descriptor?.get(name), inherit, includeStyles)
|
|
||||||
|
|
||||||
public fun setProperty(
|
|
||||||
name: Name,
|
|
||||||
node: Meta?,
|
|
||||||
)
|
|
||||||
|
|
||||||
public fun setPropertyValue(
|
|
||||||
name: Name,
|
|
||||||
value: Value?,
|
|
||||||
)
|
|
||||||
|
|
||||||
public val propertyChanges: SharedFlow<Name>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notify all listeners that a property has been changed and should be invalidated.
|
|
||||||
* This method does not check that the property has actually changed.
|
|
||||||
*/
|
|
||||||
public fun invalidateProperty(propertyName: Name)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update this vision using a dif represented by [VisionChange].
|
* Update this vision using a dif represented by [VisionChange].
|
||||||
@ -98,108 +50,19 @@ public interface Vision : Described {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun Vision.getPropertyValue(
|
|
||||||
name: Name,
|
|
||||||
inherit: Boolean? = null,
|
|
||||||
includeStyles: Boolean? = null,
|
|
||||||
includeDefaults: Boolean = true,
|
|
||||||
metaDescriptor: MetaDescriptor? = descriptor?.get(name),
|
|
||||||
): Value? {
|
|
||||||
val inheritFlag = inherit ?: metaDescriptor?.inherited ?: false
|
|
||||||
val stylesFlag = includeStyles ?: metaDescriptor?.usesStyles ?: true
|
|
||||||
return getPropertyValue(name, inheritFlag, stylesFlag, includeDefaults)
|
|
||||||
}
|
|
||||||
|
|
||||||
public fun Vision.getPropertyValue(
|
|
||||||
name: String,
|
|
||||||
inherit: Boolean? = null,
|
|
||||||
includeStyles: Boolean? = null,
|
|
||||||
includeDefaults: Boolean = true,
|
|
||||||
metaDescriptor: MetaDescriptor? = descriptor?.get(name),
|
|
||||||
): Value? = getPropertyValue(name.parseAsName(), inherit, includeStyles, includeDefaults, metaDescriptor)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compute the property based on the provided value descriptor. By default, use Vision own descriptor
|
|
||||||
*/
|
|
||||||
public fun Vision.getProperty(
|
|
||||||
name: Name,
|
|
||||||
inherit: Boolean? = null,
|
|
||||||
includeStyles: Boolean? = null,
|
|
||||||
includeDefaults: Boolean = true,
|
|
||||||
metaDescriptor: MetaDescriptor? = descriptor?.get(name),
|
|
||||||
): MutableMeta {
|
|
||||||
val inheritFlag = inherit ?: metaDescriptor?.inherited ?: false
|
|
||||||
val stylesFlag = includeStyles ?: metaDescriptor?.usesStyles ?: true
|
|
||||||
return getProperty(name, inheritFlag, stylesFlag, includeDefaults)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get [Vision] property using key as a String
|
|
||||||
*/
|
|
||||||
public fun Vision.getProperty(
|
|
||||||
name: String,
|
|
||||||
inherit: Boolean? = null,
|
|
||||||
includeStyles: Boolean? = null,
|
|
||||||
includeDefaults: Boolean = true,
|
|
||||||
metaDescriptor: MetaDescriptor? = descriptor?.get(name),
|
|
||||||
): MutableMeta = getProperty(name.parseAsName(), inherit, includeStyles, includeDefaults, metaDescriptor)
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Vision's own non-inheritable, non-styleable properties
|
|
||||||
*/
|
|
||||||
public fun Vision.properties(
|
|
||||||
inherit: Boolean? = null,
|
|
||||||
useStyles: Boolean? = null,
|
|
||||||
): MutableMetaProvider = VisionProperties(this, Name.EMPTY, inherit = inherit, useStyles = useStyles)
|
|
||||||
|
|
||||||
public fun Vision.setPropertyValue(name: Name, value: Number?) {
|
|
||||||
if (value == null) {
|
|
||||||
setPropertyValue(name, null)
|
|
||||||
} else {
|
|
||||||
setPropertyValue(name, value.asValue())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public fun Vision.setPropertyValue(name: String, value: Number?): Unit =
|
|
||||||
setPropertyValue(name.parseAsName(), value)
|
|
||||||
|
|
||||||
public fun Vision.setPropertyValue(name: Name, value: Boolean?) {
|
|
||||||
if (value == null) {
|
|
||||||
setPropertyValue(name, null)
|
|
||||||
} else {
|
|
||||||
setPropertyValue(name, value.asValue())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public fun Vision.setPropertyValue(name: String, value: Boolean?): Unit =
|
|
||||||
setPropertyValue(name.parseAsName(), value)
|
|
||||||
|
|
||||||
public fun Vision.setPropertyValue(name: Name, value: String?) {
|
|
||||||
if (value == null) {
|
|
||||||
setPropertyValue(name, null)
|
|
||||||
} else {
|
|
||||||
setPropertyValue(name, value.asValue())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public fun Vision.setPropertyValue(name: String, value: String?): Unit =
|
|
||||||
setPropertyValue(name.parseAsName(), value)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Control visibility of the element
|
* Control visibility of the element
|
||||||
*/
|
*/
|
||||||
public var Vision.visible: Boolean?
|
public var Vision.visible: Boolean?
|
||||||
get() = getPropertyValue(Vision.VISIBLE_KEY)?.boolean
|
get() = properties.getValue(Vision.VISIBLE_KEY)?.boolean
|
||||||
set(value) {
|
set(value) {
|
||||||
setPropertyValue(Vision.VISIBLE_KEY, value)
|
properties.setValue(Vision.VISIBLE_KEY, value?.asValue())
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subscribe on property updates. The subscription is bound to the given scope and canceled when the scope is canceled
|
* Subscribe on property updates. The subscription is bound to the given scope and canceled when the scope is canceled
|
||||||
*/
|
*/
|
||||||
public fun Vision.onPropertyChange(callback: (Name) -> Unit): Job = propertyChanges.onEach {
|
public fun Vision.onPropertyChange(callback: (Name) -> Unit): Job = properties.changes.onEach {
|
||||||
callback(it)
|
callback(it)
|
||||||
}.launchIn(manager.context)
|
}.launchIn(manager.context)
|
||||||
|
|
||||||
@ -210,17 +73,9 @@ public fun <V : Vision, T> V.useProperty(
|
|||||||
): Job {
|
): Job {
|
||||||
//Pass initial value.
|
//Pass initial value.
|
||||||
callBack(property.get(this))
|
callBack(property.get(this))
|
||||||
return propertyChanges.onEach { name ->
|
return properties.changes.onEach { name ->
|
||||||
if (name.startsWith(property.name.asName())) {
|
if (name.startsWith(property.name.asName())) {
|
||||||
callBack(property.get(this@useProperty))
|
callBack(property.get(this@useProperty))
|
||||||
}
|
}
|
||||||
}.launchIn(manager.context)
|
}.launchIn(manager.context)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public interface MutableVisionGroup : Vision {
|
|
||||||
|
|
||||||
override val children: MutableVisionChildren
|
|
||||||
|
|
||||||
public fun createGroup(): MutableVisionGroup
|
|
||||||
}
|
|
@ -26,7 +26,7 @@ private fun Vision.deepCopy(): Vision {
|
|||||||
/**
|
/**
|
||||||
* An update for a [Vision]
|
* An update for a [Vision]
|
||||||
*/
|
*/
|
||||||
public class VisionChangeBuilder : VisionContainerBuilder<Vision> {
|
public class VisionChangeBuilder : MutableVisionContainer<Vision> {
|
||||||
|
|
||||||
private var reset: Boolean = false
|
private var reset: Boolean = false
|
||||||
private var vision: Vision? = null
|
private var vision: Vision? = null
|
||||||
@ -77,7 +77,7 @@ public class VisionChangeBuilder : VisionContainerBuilder<Vision> {
|
|||||||
public data class VisionChange(
|
public data class VisionChange(
|
||||||
public val delete: Boolean = false,
|
public val delete: Boolean = false,
|
||||||
public val vision: Vision? = null,
|
public val vision: Vision? = null,
|
||||||
@Serializable(MetaSerializer::class) public val properties: Meta? = null,
|
public val properties: Meta? = null,
|
||||||
public val children: Map<Name, VisionChange>? = null,
|
public val children: Map<Name, VisionChange>? = null,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -93,25 +93,25 @@ private fun CoroutineScope.collectChange(
|
|||||||
|
|
||||||
//Collect properties change
|
//Collect properties change
|
||||||
source.onPropertyChange { propertyName ->
|
source.onPropertyChange { propertyName ->
|
||||||
val newItem = source.getProperty(propertyName, false, false, false)
|
val newItem = source.properties.raw?.get(propertyName)
|
||||||
collector().propertyChanged(name, propertyName, newItem)
|
collector().propertyChanged(name, propertyName, newItem)
|
||||||
}
|
}
|
||||||
|
|
||||||
val children = source.children
|
val children = source.children
|
||||||
//Subscribe for children changes
|
//Subscribe for children changes
|
||||||
for ((token, child) in children) {
|
children?.forEach { token, child ->
|
||||||
collectChange(name + token, child, collector)
|
collectChange(name + token, child, collector)
|
||||||
}
|
}
|
||||||
|
|
||||||
//Subscribe for structure change
|
//Subscribe for structure change
|
||||||
children.changes.onEach { changedName ->
|
children?.changes?.onEach { changedName ->
|
||||||
val after = children[changedName]
|
val after = children[changedName]
|
||||||
val fullName = name + changedName
|
val fullName = name + changedName
|
||||||
if (after != null) {
|
if (after != null) {
|
||||||
collectChange(fullName, after, collector)
|
collectChange(fullName, after, collector)
|
||||||
}
|
}
|
||||||
collector()[fullName] = after
|
collector()[fullName] = after
|
||||||
}.launchIn(this)
|
}?.launchIn(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -19,7 +19,7 @@ public interface VisionContainer<out V : Vision> {
|
|||||||
public operator fun get(name: Name): V?
|
public operator fun get(name: Name): V?
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface VisionContainerBuilder<in V : Vision> {
|
public interface MutableVisionContainer<in V : Vision> {
|
||||||
//TODO add documentation
|
//TODO add documentation
|
||||||
public operator fun set(name: Name?, child: V?)
|
public operator fun set(name: Name?, child: V?)
|
||||||
}
|
}
|
||||||
@ -28,7 +28,7 @@ public interface VisionContainerBuilder<in V : Vision> {
|
|||||||
* A serializable representation of [Vision] children container
|
* A serializable representation of [Vision] children container
|
||||||
*/
|
*/
|
||||||
public interface VisionChildren : VisionContainer<Vision> {
|
public interface VisionChildren : VisionContainer<Vision> {
|
||||||
public val parent: Vision?
|
public val group: Vision?
|
||||||
|
|
||||||
public val keys: Set<NameToken>
|
public val keys: Set<NameToken>
|
||||||
|
|
||||||
@ -39,14 +39,14 @@ public interface VisionChildren : VisionContainer<Vision> {
|
|||||||
public operator fun get(token: NameToken): Vision?
|
public operator fun get(token: NameToken): Vision?
|
||||||
|
|
||||||
override fun get(name: Name): Vision? = when (name.length) {
|
override fun get(name: Name): Vision? = when (name.length) {
|
||||||
0 -> parent
|
0 -> group
|
||||||
1 -> get(name.first())
|
1 -> get(name.first())
|
||||||
else -> get(name.first())?.children?.get(name.cutFirst())
|
else -> get(name.first())?.children?.get(name.cutFirst())
|
||||||
}
|
}
|
||||||
|
|
||||||
public companion object {
|
public companion object {
|
||||||
public fun empty(owner: Vision): VisionChildren = object : VisionChildren {
|
public fun empty(owner: Vision): VisionChildren = object : VisionChildren {
|
||||||
override val parent: Vision get() = owner
|
override val group: Vision get() = owner
|
||||||
override val keys: Set<NameToken> get() = emptySet()
|
override val keys: Set<NameToken> get() = emptySet()
|
||||||
override val changes: Flow<Name> get() = emptyFlow()
|
override val changes: Flow<Name> get() = emptyFlow()
|
||||||
override fun get(token: NameToken): Vision? = null
|
override fun get(token: NameToken): Vision? = null
|
||||||
@ -56,9 +56,13 @@ public interface VisionChildren : VisionContainer<Vision> {
|
|||||||
|
|
||||||
public fun VisionChildren.isEmpty(): Boolean = keys.isEmpty()
|
public fun VisionChildren.isEmpty(): Boolean = keys.isEmpty()
|
||||||
|
|
||||||
|
public inline fun VisionChildren.forEach(block: (NameToken, Vision) -> Unit) {
|
||||||
|
keys.forEach { block(it, get(it)!!) }
|
||||||
|
}
|
||||||
|
|
||||||
@Serializable(VisionChildrenContainerSerializer::class)
|
@Serializable(VisionChildrenContainerSerializer::class)
|
||||||
public interface MutableVisionChildren : VisionChildren, VisionContainerBuilder<Vision> {
|
public interface MutableVisionChildren : VisionChildren, MutableVisionContainer<Vision> {
|
||||||
public override val parent: MutableVisionGroup?
|
public override val group: MutableVisionGroup?
|
||||||
|
|
||||||
public operator fun set(token: NameToken, value: Vision?)
|
public operator fun set(token: NameToken, value: Vision?)
|
||||||
|
|
||||||
@ -79,7 +83,7 @@ public interface MutableVisionChildren : VisionChildren, VisionContainerBuilder<
|
|||||||
else -> {
|
else -> {
|
||||||
val currentParent = get(name.first())
|
val currentParent = get(name.first())
|
||||||
if (currentParent != null && currentParent !is MutableVisionGroup) error("Can't assign a child to $currentParent")
|
if (currentParent != null && currentParent !is MutableVisionGroup) error("Can't assign a child to $currentParent")
|
||||||
val parent: MutableVisionGroup = currentParent as? MutableVisionGroup ?: parent?.createGroup().also {
|
val parent: MutableVisionGroup = currentParent as? MutableVisionGroup ?: group?.createGroup().also {
|
||||||
set(name.first(), it)
|
set(name.first(), it)
|
||||||
} ?: error("Container owner not set")
|
} ?: error("Container owner not set")
|
||||||
parent.children[name.cutFirst()] = child
|
parent.children[name.cutFirst()] = child
|
||||||
@ -105,7 +109,7 @@ public operator fun VisionChildren.iterator(): Iterator<Pair<NameToken, Vision>>
|
|||||||
|
|
||||||
public operator fun <V : Vision> VisionContainer<V>.get(str: String): V? = get(Name.parse(str))
|
public operator fun <V : Vision> VisionContainer<V>.get(str: String): V? = get(Name.parse(str))
|
||||||
|
|
||||||
public operator fun <V : Vision> VisionContainerBuilder<V>.set(
|
public operator fun <V : Vision> MutableVisionContainer<V>.set(
|
||||||
str: String?, vision: V?,
|
str: String?, vision: V?,
|
||||||
): Unit = set(str?.parseAsName(), vision)
|
): Unit = set(str?.parseAsName(), vision)
|
||||||
|
|
||||||
@ -113,13 +117,13 @@ internal class VisionChildrenImpl(
|
|||||||
items: Map<NameToken, Vision>,
|
items: Map<NameToken, Vision>,
|
||||||
) : MutableVisionChildren {
|
) : MutableVisionChildren {
|
||||||
|
|
||||||
override var parent: MutableVisionGroup? = null
|
override var group: MutableVisionGroup? = null
|
||||||
internal set
|
internal set
|
||||||
|
|
||||||
private val items = LinkedHashMap(items)
|
private val items = LinkedHashMap(items)
|
||||||
private val updateJobs = HashMap<NameToken, Job>()
|
private val updateJobs = HashMap<NameToken, Job>()
|
||||||
|
|
||||||
private val scope: CoroutineScope? get() = parent?.manager?.context
|
private val scope: CoroutineScope? get() = group?.manager?.context
|
||||||
|
|
||||||
override val keys: Set<NameToken> get() = items.keys
|
override val keys: Set<NameToken> get() = items.keys
|
||||||
|
|
||||||
@ -149,9 +153,9 @@ internal class VisionChildrenImpl(
|
|||||||
} else {
|
} else {
|
||||||
items[token] = value
|
items[token] = value
|
||||||
//check if parent already exists and is different from the current one
|
//check if parent already exists and is different from the current one
|
||||||
if (value.parent != null && value.parent != parent) error("Can't reassign parent Vision for $value")
|
if (value.parent != null && value.parent != group) error("Can't reassign parent Vision for $value")
|
||||||
//set parent
|
//set parent
|
||||||
value.parent = parent
|
value.parent = group
|
||||||
//start update jobs (only if the vision is rooted)
|
//start update jobs (only if the vision is rooted)
|
||||||
scope?.let { scope ->
|
scope?.let { scope ->
|
||||||
val job = (value.children as? VisionChildrenImpl)?.changes?.onEach {
|
val job = (value.children as? VisionChildrenImpl)?.changes?.onEach {
|
||||||
@ -179,7 +183,7 @@ internal class VisionChildrenImpl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal object VisionChildrenContainerSerializer : KSerializer<MutableVisionChildren> {
|
internal object VisionChildrenContainerSerializer : KSerializer<MutableVisionChildren> {
|
||||||
private val mapSerializer = serializer<Map<NameToken,Vision>>()
|
private val mapSerializer = serializer<Map<NameToken, Vision>>()
|
||||||
|
|
||||||
override val descriptor: SerialDescriptor = mapSerializer.descriptor
|
override val descriptor: SerialDescriptor = mapSerializer.descriptor
|
||||||
|
|
||||||
|
@ -13,20 +13,33 @@ import space.kscience.dataforge.names.NameToken
|
|||||||
import space.kscience.dataforge.names.plus
|
import space.kscience.dataforge.names.plus
|
||||||
import space.kscience.dataforge.values.ValueType
|
import space.kscience.dataforge.values.ValueType
|
||||||
import space.kscience.visionforge.Vision.Companion.STYLE_KEY
|
import space.kscience.visionforge.Vision.Companion.STYLE_KEY
|
||||||
|
import kotlin.js.JsName
|
||||||
import kotlin.jvm.Synchronized
|
import kotlin.jvm.Synchronized
|
||||||
|
|
||||||
|
|
||||||
|
public interface VisionGroup : Vision {
|
||||||
|
public val children: VisionChildren
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface MutableVisionGroup : VisionGroup {
|
||||||
|
|
||||||
|
override val children: MutableVisionChildren
|
||||||
|
|
||||||
|
public fun createGroup(): MutableVisionGroup
|
||||||
|
}
|
||||||
|
|
||||||
|
public val Vision.children: VisionChildren? get() = (this as? VisionGroup)?.children
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A full base implementation for a [Vision]
|
* A full base implementation for a [Vision]
|
||||||
*/
|
*/
|
||||||
@Serializable
|
public abstract class AbstractVisionGroup : AbstractVision(), MutableVisionGroup {
|
||||||
@SerialName("vision.group")
|
|
||||||
public open class VisionGroup : AbstractVision(), MutableVisionGroup {
|
|
||||||
|
|
||||||
override fun update(change: VisionChange) {
|
override fun update(change: VisionChange) {
|
||||||
change.children?.forEach { (name, change) ->
|
change.children?.forEach { (name, change) ->
|
||||||
when {
|
when {
|
||||||
change.delete -> children.set(name, null)
|
change.delete -> children[name] = null
|
||||||
change.vision != null -> children.set(name, change.vision)
|
change.vision != null -> children[name] = change.vision
|
||||||
else -> children[name]?.update(change)
|
else -> children[name]?.update(change)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -45,13 +58,13 @@ public open class VisionGroup : AbstractVision(), MutableVisionGroup {
|
|||||||
fun getOrCreateChildren(): MutableVisionChildren {
|
fun getOrCreateChildren(): MutableVisionChildren {
|
||||||
if (_children == null) {
|
if (_children == null) {
|
||||||
_children = VisionChildrenImpl(emptyMap()).apply {
|
_children = VisionChildrenImpl(emptyMap()).apply {
|
||||||
parent = this@VisionGroup
|
group = this@AbstractVisionGroup
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return _children!!
|
return _children!!
|
||||||
}
|
}
|
||||||
|
|
||||||
override val parent: MutableVisionGroup get() = this@VisionGroup
|
override val group: MutableVisionGroup get() = this@AbstractVisionGroup
|
||||||
|
|
||||||
override val keys: Set<NameToken> get() = _children?.keys ?: emptySet()
|
override val keys: Set<NameToken> get() = _children?.keys ?: emptySet()
|
||||||
override val changes: Flow<Name> get() = _children?.changes ?: emptyFlow()
|
override val changes: Flow<Name> get() = _children?.changes ?: emptyFlow()
|
||||||
@ -71,7 +84,7 @@ public open class VisionGroup : AbstractVision(), MutableVisionGroup {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun createGroup(): VisionGroup = VisionGroup()
|
abstract override fun createGroup(): AbstractVisionGroup
|
||||||
|
|
||||||
public companion object {
|
public companion object {
|
||||||
public val descriptor: MetaDescriptor = MetaDescriptor {
|
public val descriptor: MetaDescriptor = MetaDescriptor {
|
||||||
@ -80,16 +93,28 @@ public open class VisionGroup : AbstractVision(), MutableVisionGroup {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun Vision.updateProperties(item: Meta, at: Name = Name.EMPTY) {
|
public fun Vision.updateProperties(item: Meta, name: Name = Name.EMPTY) {
|
||||||
setPropertyValue(at, item.value)
|
properties.setValue(name, item.value)
|
||||||
item.items.forEach { (token, item) ->
|
item.items.forEach { (token, item) ->
|
||||||
updateProperties(item, at + token)
|
updateProperties(item, name + token)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A simple vision group that just holds children. Nothing else.
|
||||||
|
*/
|
||||||
|
@Serializable
|
||||||
|
@SerialName("vision.group")
|
||||||
|
public class SimpleVisionGroup : AbstractVisionGroup() {
|
||||||
|
override fun createGroup(): SimpleVisionGroup = SimpleVisionGroup()
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsName("createVisionGroup")
|
||||||
|
public fun VisionGroup(): VisionGroup = SimpleVisionGroup()
|
||||||
|
|
||||||
//fun VisualObject.findStyle(styleName: Name): Meta? {
|
//fun VisualObject.findStyle(styleName: Name): Meta? {
|
||||||
// if (this is VisualGroup) {
|
// if (this is VisualGroup) {
|
||||||
// val style = resolveStyle(styleName)
|
// val style = resolveStyle(styleName)
|
||||||
|
@ -68,8 +68,8 @@ public class VisionManager(meta: Meta) : AbstractPlugin(meta) {
|
|||||||
|
|
||||||
private val defaultSerialModule: SerializersModule = SerializersModule {
|
private val defaultSerialModule: SerializersModule = SerializersModule {
|
||||||
polymorphic(Vision::class) {
|
polymorphic(Vision::class) {
|
||||||
default { VisionGroup.serializer() }
|
default { SimpleVisionGroup.serializer() }
|
||||||
subclass(VisionGroup.serializer())
|
subclass(SimpleVisionGroup.serializer())
|
||||||
subclass(VisionOfNumberField.serializer())
|
subclass(VisionOfNumberField.serializer())
|
||||||
subclass(VisionOfTextField.serializer())
|
subclass(VisionOfTextField.serializer())
|
||||||
subclass(VisionOfCheckbox.serializer())
|
subclass(VisionOfCheckbox.serializer())
|
||||||
@ -112,7 +112,9 @@ public fun Vision.encodeToString(): String = manager.encodeToString(this)
|
|||||||
/**
|
/**
|
||||||
* A root vision attached to [VisionManager]
|
* A root vision attached to [VisionManager]
|
||||||
*/
|
*/
|
||||||
public class RootVision(override val manager: VisionManager) : VisionGroup()
|
public class RootVision(override val manager: VisionManager) : AbstractVisionGroup() {
|
||||||
|
override fun createGroup(): SimpleVisionGroup = SimpleVisionGroup()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Designate this [Vision] as a root and assign a [VisionManager] as its parent
|
* Designate this [Vision] as a root and assign a [VisionManager] as its parent
|
||||||
|
@ -1,40 +1,104 @@
|
|||||||
package space.kscience.visionforge
|
package space.kscience.visionforge
|
||||||
|
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
import space.kscience.dataforge.meta.Meta
|
import space.kscience.dataforge.meta.Meta
|
||||||
import space.kscience.dataforge.meta.MutableMeta
|
import space.kscience.dataforge.meta.MutableMeta
|
||||||
import space.kscience.dataforge.meta.descriptors.MetaDescriptor
|
import space.kscience.dataforge.meta.descriptors.MetaDescriptor
|
||||||
import space.kscience.dataforge.meta.descriptors.get
|
import space.kscience.dataforge.meta.descriptors.get
|
||||||
|
import space.kscience.dataforge.meta.get
|
||||||
import space.kscience.dataforge.names.Name
|
import space.kscience.dataforge.names.Name
|
||||||
import space.kscience.dataforge.names.NameToken
|
import space.kscience.dataforge.names.NameToken
|
||||||
|
import space.kscience.dataforge.names.parseAsName
|
||||||
import space.kscience.dataforge.names.plus
|
import space.kscience.dataforge.names.plus
|
||||||
import space.kscience.dataforge.values.Value
|
import space.kscience.dataforge.values.Value
|
||||||
|
import space.kscience.dataforge.values.asValue
|
||||||
|
|
||||||
/**
|
public interface VisionProperties {
|
||||||
* A wrapper that emulates delegates reading and writing properties to Vision method
|
|
||||||
*/
|
/**
|
||||||
internal class VisionProperties(
|
* Raw Visions own properties without styles, defaults, etc.
|
||||||
val vision: Vision,
|
*/
|
||||||
|
public val raw: Meta?
|
||||||
|
|
||||||
|
public val descriptor: MetaDescriptor?
|
||||||
|
public val default: Meta?
|
||||||
|
|
||||||
|
public fun getValue(
|
||||||
|
name: Name,
|
||||||
|
inherit: Boolean,
|
||||||
|
includeStyles: Boolean,
|
||||||
|
): Value?
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get property with given layer flags.
|
||||||
|
* @param inherit toggles parent node property lookup. Null means inference from descriptor.
|
||||||
|
* @param includeStyles toggles inclusion of properties from styles.
|
||||||
|
*/
|
||||||
|
public operator fun get(
|
||||||
|
name: Name,
|
||||||
|
inherit: Boolean,
|
||||||
|
includeStyles: Boolean,
|
||||||
|
): Meta
|
||||||
|
|
||||||
|
public val changes: Flow<Name>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notify all listeners that a property has been changed and should be invalidated.
|
||||||
|
* This method does not check that the property has actually changed.
|
||||||
|
*/
|
||||||
|
public fun invalidate(propertyName: Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface MutableVisionProperties : VisionProperties {
|
||||||
|
|
||||||
|
override operator fun get(
|
||||||
|
name: Name,
|
||||||
|
inherit: Boolean,
|
||||||
|
includeStyles: Boolean,
|
||||||
|
): MutableMeta = VisionPropertiesItem(
|
||||||
|
this,
|
||||||
|
name,
|
||||||
|
inherit,
|
||||||
|
includeStyles,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
public operator fun set(
|
||||||
|
name: Name,
|
||||||
|
node: Meta?,
|
||||||
|
)
|
||||||
|
|
||||||
|
public fun setValue(
|
||||||
|
name: Name,
|
||||||
|
value: Value?,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private class VisionPropertiesItem(
|
||||||
|
val properties: MutableVisionProperties,
|
||||||
val nodeName: Name,
|
val nodeName: Name,
|
||||||
val visionDescriptor: MetaDescriptor? = vision.descriptor,
|
|
||||||
val inherit: Boolean? = null,
|
val inherit: Boolean? = null,
|
||||||
val useStyles: Boolean? = null,
|
val useStyles: Boolean? = null,
|
||||||
|
val default: Meta? = null,
|
||||||
) : MutableMeta {
|
) : MutableMeta {
|
||||||
|
|
||||||
val descriptor: MetaDescriptor? by lazy { visionDescriptor?.get(nodeName) }
|
val descriptor: MetaDescriptor? by lazy { properties.descriptor?.get(nodeName) }
|
||||||
|
|
||||||
|
|
||||||
override val items: Map<NameToken, MutableMeta>
|
override val items: Map<NameToken, MutableMeta>
|
||||||
get() {
|
get() {
|
||||||
val metaKeys = vision.meta.getMeta(nodeName)?.items?.keys ?: emptySet()
|
val metaKeys = properties.raw?.getMeta(nodeName)?.items?.keys ?: emptySet()
|
||||||
val descriptorKeys = descriptor?.children?.map { NameToken(it.key) } ?: emptySet()
|
val descriptorKeys = descriptor?.children?.map { NameToken(it.key) } ?: emptySet()
|
||||||
|
val defaultKeys = default?.get(nodeName)?.items?.keys ?: emptySet()
|
||||||
val inheritFlag = descriptor?.inherited ?: inherit
|
val inheritFlag = descriptor?.inherited ?: inherit
|
||||||
val stylesFlag = descriptor?.usesStyles ?: useStyles
|
val stylesFlag = descriptor?.usesStyles ?: useStyles
|
||||||
return (metaKeys + descriptorKeys).associateWith {
|
return (metaKeys + descriptorKeys + defaultKeys).associateWith {
|
||||||
VisionProperties(
|
VisionPropertiesItem(
|
||||||
vision,
|
properties,
|
||||||
nodeName + it,
|
nodeName + it,
|
||||||
visionDescriptor,
|
|
||||||
inheritFlag,
|
inheritFlag,
|
||||||
stylesFlag
|
stylesFlag,
|
||||||
|
default
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -43,22 +107,22 @@ internal class VisionProperties(
|
|||||||
get() {
|
get() {
|
||||||
val inheritFlag = descriptor?.inherited ?: inherit ?: false
|
val inheritFlag = descriptor?.inherited ?: inherit ?: false
|
||||||
val stylesFlag = descriptor?.usesStyles ?: useStyles ?: true
|
val stylesFlag = descriptor?.usesStyles ?: useStyles ?: true
|
||||||
return vision.getPropertyValue(nodeName, inheritFlag, stylesFlag, true)
|
return properties.getValue(nodeName, inheritFlag, stylesFlag) ?: default?.getValue(nodeName)
|
||||||
}
|
}
|
||||||
set(value) {
|
set(value) {
|
||||||
vision.setPropertyValue(nodeName, value)
|
properties.setValue(nodeName, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getOrCreate(name: Name): MutableMeta = VisionProperties(
|
override fun getOrCreate(name: Name): MutableMeta = VisionPropertiesItem(
|
||||||
vision,
|
properties,
|
||||||
nodeName + name,
|
nodeName + name,
|
||||||
visionDescriptor,
|
|
||||||
inherit,
|
inherit,
|
||||||
useStyles
|
useStyles,
|
||||||
|
default
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun setMeta(name: Name, node: Meta?) {
|
override fun setMeta(name: Name, node: Meta?) {
|
||||||
vision.setProperty(nodeName + name, node)
|
properties[nodeName + name] = node
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String = Meta.toString(this)
|
override fun toString(): String = Meta.toString(this)
|
||||||
@ -66,16 +130,96 @@ internal class VisionProperties(
|
|||||||
override fun hashCode(): Int = Meta.hashCode(this)
|
override fun hashCode(): Int = Meta.hashCode(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
///**
|
public fun VisionProperties.getValue(
|
||||||
// * Accessor to all vision properties
|
name: Name,
|
||||||
// */
|
inherit: Boolean? = null,
|
||||||
//public fun Vision.computePropertyValues(
|
includeStyles: Boolean? = null,
|
||||||
// descriptor: MetaDescriptor? = this.descriptor,
|
): Value? {
|
||||||
//): MutableValueProvider = object : MutableValueProvider {
|
val descriptor = descriptor?.get(name)
|
||||||
// override fun getValue(name: Name): Value? = computeProperty(name, descriptor?.get(name))?.value
|
val inheritFlag = inherit ?: descriptor?.inherited ?: false
|
||||||
//
|
val stylesFlag = includeStyles ?: descriptor?.usesStyles ?: true
|
||||||
// override fun setValue(name: Name, value: Value?) {
|
return getValue(name, inheritFlag, stylesFlag)
|
||||||
// setProperty(name, value)
|
}
|
||||||
// }
|
|
||||||
//}
|
public fun VisionProperties.getValue(
|
||||||
|
name: String,
|
||||||
|
inherit: Boolean? = null,
|
||||||
|
includeStyles: Boolean? = null,
|
||||||
|
): Value? = getValue(name.parseAsName(), inherit, includeStyles)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute the property based on the provided value descriptor. By default, use Vision own descriptor
|
||||||
|
*/
|
||||||
|
public operator fun VisionProperties.get(
|
||||||
|
name: Name,
|
||||||
|
inherit: Boolean? = null,
|
||||||
|
includeStyles: Boolean? = null,
|
||||||
|
): Meta {
|
||||||
|
val descriptor: MetaDescriptor? = descriptor?.get(name)
|
||||||
|
val inheritFlag = inherit ?: descriptor?.inherited ?: false
|
||||||
|
val stylesFlag = includeStyles ?: descriptor?.usesStyles ?: true
|
||||||
|
return get(name, inheritFlag, stylesFlag)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get [Vision] property using key as a String
|
||||||
|
*/
|
||||||
|
public operator fun VisionProperties.get(
|
||||||
|
name: String,
|
||||||
|
inherit: Boolean? = null,
|
||||||
|
includeStyles: Boolean? = null,
|
||||||
|
): Meta = get(name.parseAsName(), inherit, includeStyles)
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute the property based on the provided value descriptor. By default, use Vision own descriptor
|
||||||
|
*/
|
||||||
|
public operator fun MutableVisionProperties.get(
|
||||||
|
name: Name,
|
||||||
|
inherit: Boolean? = null,
|
||||||
|
includeStyles: Boolean? = null,
|
||||||
|
): MutableMeta {
|
||||||
|
val descriptor: MetaDescriptor? = descriptor?.get(name)
|
||||||
|
val inheritFlag = inherit ?: descriptor?.inherited ?: false
|
||||||
|
val stylesFlag = includeStyles ?: descriptor?.usesStyles ?: true
|
||||||
|
return get(name, inheritFlag, stylesFlag)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The root property node with given inheritance and style flags
|
||||||
|
*/
|
||||||
|
public fun MutableVisionProperties.root(
|
||||||
|
inherit: Boolean? = null,
|
||||||
|
includeStyles: Boolean? = null,
|
||||||
|
): MutableMeta = get(Name.EMPTY, inherit, includeStyles)
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get [Vision] property using key as a String
|
||||||
|
*/
|
||||||
|
public operator fun MutableVisionProperties.get(
|
||||||
|
name: String,
|
||||||
|
inherit: Boolean? = null,
|
||||||
|
includeStyles: Boolean? = null,
|
||||||
|
): MutableMeta = get(name.parseAsName(), inherit, includeStyles)
|
||||||
|
|
||||||
|
|
||||||
|
public operator fun MutableVisionProperties.set(name: Name, value: Number): Unit =
|
||||||
|
setValue(name, value.asValue())
|
||||||
|
|
||||||
|
public operator fun MutableVisionProperties.set(name: String, value: Number): Unit =
|
||||||
|
set(name.parseAsName(), value)
|
||||||
|
|
||||||
|
public operator fun MutableVisionProperties.set(name: Name, value: Boolean): Unit =
|
||||||
|
setValue(name, value.asValue())
|
||||||
|
|
||||||
|
public operator fun MutableVisionProperties.set(name: String, value: Boolean): Unit =
|
||||||
|
set(name.parseAsName(), value)
|
||||||
|
|
||||||
|
public operator fun MutableVisionProperties.set(name: Name, value: String): Unit =
|
||||||
|
setValue(name, value.asValue())
|
||||||
|
|
||||||
|
public operator fun MutableVisionProperties.set(name: String, value: String): Unit =
|
||||||
|
set(name.parseAsName(), value)
|
||||||
|
|
||||||
|
@ -1,29 +0,0 @@
|
|||||||
package space.kscience.visionforge
|
|
||||||
|
|
||||||
import space.kscience.dataforge.meta.Meta
|
|
||||||
import space.kscience.dataforge.meta.MutableMeta
|
|
||||||
import space.kscience.dataforge.names.Name
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Property containers are used to create a symmetric behaviors for vision properties and style builders
|
|
||||||
*/
|
|
||||||
public interface VisionPropertyContainer<out V : Vision> {
|
|
||||||
|
|
||||||
public fun getProperty(
|
|
||||||
name: Name,
|
|
||||||
inherit: Boolean,
|
|
||||||
includeStyles: Boolean,
|
|
||||||
includeDefaults: Boolean,
|
|
||||||
): Meta?
|
|
||||||
}
|
|
||||||
|
|
||||||
public open class SimpleVisionPropertyContainer<out V : Vision>(
|
|
||||||
public val meta: MutableMeta,
|
|
||||||
) : VisionPropertyContainer<V> {
|
|
||||||
override fun getProperty(
|
|
||||||
name: Name,
|
|
||||||
inherit: Boolean,
|
|
||||||
includeStyles: Boolean,
|
|
||||||
includeDefaults: Boolean,
|
|
||||||
): Meta? = meta.getMeta(name)
|
|
||||||
}
|
|
@ -9,14 +9,13 @@ import kotlinx.serialization.Serializable
|
|||||||
import space.kscience.dataforge.meta.Meta
|
import space.kscience.dataforge.meta.Meta
|
||||||
import space.kscience.dataforge.meta.get
|
import space.kscience.dataforge.meta.get
|
||||||
import space.kscience.dataforge.meta.node
|
import space.kscience.dataforge.meta.node
|
||||||
import space.kscience.visionforge.properties
|
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@SerialName("html.form")
|
@SerialName("html.form")
|
||||||
public class VisionOfHtmlForm(
|
public class VisionOfHtmlForm(
|
||||||
public val formId: String,
|
public val formId: String,
|
||||||
) : VisionOfHtmlInput() {
|
) : VisionOfHtmlInput() {
|
||||||
public var values: Meta? by properties().node()
|
public var values: Meta? by mutableProperties.node()
|
||||||
}
|
}
|
||||||
|
|
||||||
public class HtmlFormFragment internal constructor(
|
public class HtmlFormFragment internal constructor(
|
||||||
|
@ -5,12 +5,15 @@ import kotlinx.serialization.Serializable
|
|||||||
import space.kscience.dataforge.meta.boolean
|
import space.kscience.dataforge.meta.boolean
|
||||||
import space.kscience.dataforge.meta.number
|
import space.kscience.dataforge.meta.number
|
||||||
import space.kscience.dataforge.meta.string
|
import space.kscience.dataforge.meta.string
|
||||||
import space.kscience.visionforge.VisionGroup
|
import space.kscience.dataforge.names.Name
|
||||||
import space.kscience.visionforge.properties
|
import space.kscience.visionforge.*
|
||||||
|
|
||||||
|
//TODO replace by something
|
||||||
|
internal val Vision.mutableProperties get() = properties[Name.EMPTY, false, false]
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
public abstract class VisionOfHtmlInput : VisionGroup() {
|
public abstract class VisionOfHtmlInput : AbstractVision() {
|
||||||
public var disabled: Boolean by properties().boolean(false)
|
public var disabled: Boolean by mutableProperties.boolean { false }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@ -19,7 +22,7 @@ public class VisionOfTextField(
|
|||||||
public val label: String? = null,
|
public val label: String? = null,
|
||||||
public val name: String? = null,
|
public val name: String? = null,
|
||||||
) : VisionOfHtmlInput() {
|
) : VisionOfHtmlInput() {
|
||||||
public var text: String? by properties().string()
|
public var text: String? by mutableProperties.string()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@ -28,7 +31,7 @@ public class VisionOfCheckbox(
|
|||||||
public val label: String? = null,
|
public val label: String? = null,
|
||||||
public val name: String? = null,
|
public val name: String? = null,
|
||||||
) : VisionOfHtmlInput() {
|
) : VisionOfHtmlInput() {
|
||||||
public var checked: Boolean? by properties().boolean()
|
public var checked: Boolean? by mutableProperties.boolean()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@ -37,7 +40,7 @@ public class VisionOfNumberField(
|
|||||||
public val label: String? = null,
|
public val label: String? = null,
|
||||||
public val name: String? = null,
|
public val name: String? = null,
|
||||||
) : VisionOfHtmlInput() {
|
) : VisionOfHtmlInput() {
|
||||||
public var value: Number? by properties().number()
|
public var value: Number? by mutableProperties.number()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@ -49,6 +52,6 @@ public class VisionOfRangeField(
|
|||||||
public val label: String? = null,
|
public val label: String? = null,
|
||||||
public val name: String? = null,
|
public val name: String? = null,
|
||||||
) : VisionOfHtmlInput() {
|
) : VisionOfHtmlInput() {
|
||||||
public var value: Number? by properties().number()
|
public var value: Number? by mutableProperties.number()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,91 +0,0 @@
|
|||||||
package space.kscience.visionforge
|
|
||||||
|
|
||||||
import space.kscience.dataforge.names.Name
|
|
||||||
import space.kscience.dataforge.values.Value
|
|
||||||
import space.kscience.dataforge.values.number
|
|
||||||
import kotlin.properties.ReadWriteProperty
|
|
||||||
import kotlin.reflect.KProperty
|
|
||||||
|
|
||||||
//public fun Vision.propertyNode(
|
|
||||||
// name: Name? = null,
|
|
||||||
// inherit: Boolean = false,
|
|
||||||
// includeStyles: Boolean = true,
|
|
||||||
// includeDefaults: Boolean = true,
|
|
||||||
//): ReadWriteProperty<Any?, Meta?> = object : ReadWriteProperty<Any?, Meta?> {
|
|
||||||
// override fun getValue(thisRef: Any?, property: KProperty<*>): Meta? =
|
|
||||||
// getProperty(name ?: Name.parse(property.name), inherit, includeStyles, includeDefaults)
|
|
||||||
//
|
|
||||||
// override fun setValue(thisRef: Any?, property: KProperty<*>, value: Meta?) {
|
|
||||||
// meta.setMeta(name ?: Name.parse(property.name), value)
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//public fun <T> Vision.propertyNode(
|
|
||||||
// converter: MetaConverter<T>,
|
|
||||||
// name: Name? = null,
|
|
||||||
// inherit: Boolean = false,
|
|
||||||
// includeStyles: Boolean = true,
|
|
||||||
// includeDefaults: Boolean = true,
|
|
||||||
//): ReadWriteProperty<Any?, T?> = object : ReadWriteProperty<Any?, T?> {
|
|
||||||
// override fun getValue(thisRef: Any?, property: KProperty<*>): T? = getProperty(
|
|
||||||
// name ?: Name.parse(property.name),
|
|
||||||
// inherit,
|
|
||||||
// includeStyles,
|
|
||||||
// includeDefaults
|
|
||||||
// )?.let(converter::metaToObject)
|
|
||||||
//
|
|
||||||
// override fun setValue(thisRef: Any?, property: KProperty<*>, value: T?) {
|
|
||||||
// meta.setMeta(name ?: Name.parse(property.name), value?.let(converter::objectToMeta))
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
public fun Vision.propertyValue(
|
|
||||||
name: Name? = null,
|
|
||||||
inherit: Boolean = false,
|
|
||||||
includeStyles: Boolean = true,
|
|
||||||
includeDefaults: Boolean = true,
|
|
||||||
): ReadWriteProperty<Any?, Value?> = object : ReadWriteProperty<Any?, Value?> {
|
|
||||||
override fun getValue(thisRef: Any?, property: KProperty<*>): Value? =
|
|
||||||
getPropertyValue(name ?: Name.parse(property.name), inherit, includeStyles, includeDefaults)
|
|
||||||
|
|
||||||
override fun setValue(thisRef: Any?, property: KProperty<*>, value: Value?) {
|
|
||||||
setPropertyValue(name ?: Name.parse(property.name), value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public fun <T> Vision.propertyValue(
|
|
||||||
name: Name? = null,
|
|
||||||
inherit: Boolean = false,
|
|
||||||
includeStyles: Boolean = true,
|
|
||||||
includeDefaults: Boolean = true,
|
|
||||||
setter: (T) -> Value? = { it?.let(Value::of) },
|
|
||||||
getter: (Value?) -> T,
|
|
||||||
): ReadWriteProperty<Any?, T> = object : ReadWriteProperty<Any?, T> {
|
|
||||||
override fun getValue(thisRef: Any?, property: KProperty<*>): T = getPropertyValue(
|
|
||||||
name ?: Name.parse(property.name),
|
|
||||||
inherit,
|
|
||||||
includeStyles,
|
|
||||||
includeDefaults
|
|
||||||
).let(getter)
|
|
||||||
|
|
||||||
override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
|
|
||||||
setPropertyValue(name ?: Name.parse(property.name), value?.let(setter))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public fun Vision.numberProperty(
|
|
||||||
name: Name? = null,
|
|
||||||
inherit: Boolean = false,
|
|
||||||
includeStyles: Boolean = true,
|
|
||||||
includeDefaults: Boolean = true
|
|
||||||
): ReadWriteProperty<Any?, Number?> = propertyValue(name, inherit, includeStyles, includeDefaults) { it?.number }
|
|
||||||
|
|
||||||
public fun Vision.numberProperty(
|
|
||||||
name: Name? = null,
|
|
||||||
inherit: Boolean = false,
|
|
||||||
includeStyles: Boolean = true,
|
|
||||||
includeDefaults: Boolean = true,
|
|
||||||
default: () -> Number
|
|
||||||
): ReadWriteProperty<Any?, Number> = propertyValue(name, inherit, includeStyles, includeDefaults) {
|
|
||||||
it?.number ?: default()
|
|
||||||
}
|
|
@ -6,7 +6,8 @@ import kotlinx.coroutines.launch
|
|||||||
import space.kscience.dataforge.names.Name
|
import space.kscience.dataforge.names.Name
|
||||||
import space.kscience.dataforge.names.plus
|
import space.kscience.dataforge.names.plus
|
||||||
import space.kscience.visionforge.Vision
|
import space.kscience.visionforge.Vision
|
||||||
import space.kscience.visionforge.iterator
|
import space.kscience.visionforge.children
|
||||||
|
import space.kscience.visionforge.forEach
|
||||||
|
|
||||||
public interface VisionVisitor {
|
public interface VisionVisitor {
|
||||||
/**
|
/**
|
||||||
@ -37,7 +38,7 @@ public interface VisionVisitor {
|
|||||||
|
|
||||||
visionVisitor.visitChildren(name, vision)
|
visionVisitor.visitChildren(name, vision)
|
||||||
|
|
||||||
for ((token, child) in vision.children) {
|
vision.children?.forEach { token, child ->
|
||||||
visitTreeAsync(visionVisitor, name + token, child)
|
visitTreeAsync(visionVisitor, name + token, child)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,9 +30,10 @@ fun FlowContent.renderVisionFragment(
|
|||||||
|
|
||||||
|
|
||||||
@DFExperimental
|
@DFExperimental
|
||||||
class HtmlTagTest {
|
private fun VisionOutput.base(block: VisionGroup.() -> Unit) = VisionGroup().apply(block)
|
||||||
|
|
||||||
fun VisionOutput.base(block: VisionGroup.() -> Unit) = VisionGroup().apply(block)
|
@DFExperimental
|
||||||
|
class HtmlTagTest {
|
||||||
|
|
||||||
val fragment: HtmlVisionFragment = {
|
val fragment: HtmlVisionFragment = {
|
||||||
div {
|
div {
|
||||||
@ -42,8 +43,8 @@ class HtmlTagTest {
|
|||||||
"metaProperty" put 87
|
"metaProperty" put 87
|
||||||
}
|
}
|
||||||
base {
|
base {
|
||||||
setPropertyValue("myProp", 82)
|
properties["myProp"] = 82
|
||||||
setPropertyValue("otherProp", false)
|
properties["otherProp"] = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -53,7 +54,7 @@ class HtmlTagTest {
|
|||||||
div {
|
div {
|
||||||
h2 { +"Properties" }
|
h2 { +"Properties" }
|
||||||
ul {
|
ul {
|
||||||
vision.getProperty(Name.EMPTY).items.forEach {
|
vision.properties.raw?.items?.forEach {
|
||||||
li {
|
li {
|
||||||
a { +it.key.toString() }
|
a { +it.key.toString() }
|
||||||
p { +it.value.toString() }
|
p { +it.value.toString() }
|
||||||
|
@ -8,45 +8,47 @@ import space.kscience.dataforge.values.asValue
|
|||||||
import space.kscience.dataforge.values.boolean
|
import space.kscience.dataforge.values.boolean
|
||||||
import space.kscience.dataforge.values.int
|
import space.kscience.dataforge.values.int
|
||||||
import space.kscience.visionforge.VisionGroup
|
import space.kscience.visionforge.VisionGroup
|
||||||
import space.kscience.visionforge.getProperty
|
import space.kscience.visionforge.get
|
||||||
import space.kscience.visionforge.getPropertyValue
|
import space.kscience.visionforge.getValue
|
||||||
import space.kscience.visionforge.setPropertyValue
|
import space.kscience.visionforge.set
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
import kotlin.test.assertNotEquals
|
import kotlin.test.assertNotEquals
|
||||||
|
|
||||||
class VisionPropertyTest {
|
|
||||||
@Test
|
|
||||||
fun testPropertyWrite(){
|
|
||||||
val vision = VisionGroup()
|
|
||||||
vision.setPropertyValue("fff", 2)
|
|
||||||
vision.setPropertyValue("fff.ddd", false)
|
|
||||||
|
|
||||||
assertEquals(2, vision.getPropertyValue("fff")?.int)
|
private class TestScheme : Scheme() {
|
||||||
assertEquals(false, vision.getPropertyValue("fff.ddd")?.boolean)
|
var ddd by int()
|
||||||
|
|
||||||
|
companion object : SchemeSpec<TestScheme>(::TestScheme)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class VisionPropertyTest {
|
||||||
|
@Test
|
||||||
|
fun testPropertyWrite() {
|
||||||
|
val vision = VisionGroup()
|
||||||
|
vision.properties["fff"] = 2
|
||||||
|
vision.properties["fff.ddd"] = false
|
||||||
|
|
||||||
|
assertEquals(2, vision.properties.getValue("fff")?.int)
|
||||||
|
assertEquals(false, vision.properties.getValue("fff.ddd")?.boolean)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testPropertyEdit(){
|
fun testPropertyEdit() {
|
||||||
val vision = VisionGroup()
|
val vision = VisionGroup()
|
||||||
vision.getProperty("fff.ddd").apply {
|
vision.properties["fff.ddd"].apply {
|
||||||
value = 2.asValue()
|
value = 2.asValue()
|
||||||
}
|
}
|
||||||
assertEquals(2, vision.getPropertyValue("fff.ddd")?.int)
|
assertEquals(2, vision.properties.getValue("fff.ddd")?.int)
|
||||||
assertNotEquals(true, vision.getPropertyValue("fff.ddd")?.boolean)
|
assertNotEquals(true, vision.properties.getValue("fff.ddd")?.boolean)
|
||||||
}
|
|
||||||
|
|
||||||
internal class TestScheme: Scheme(){
|
|
||||||
var ddd by int()
|
|
||||||
companion object: SchemeSpec<TestScheme>(::TestScheme)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testPropertyUpdate(){
|
fun testPropertyUpdate() {
|
||||||
val vision = VisionGroup()
|
val vision = VisionGroup()
|
||||||
vision.getProperty("fff").updateWith(TestScheme){
|
vision.properties["fff"].updateWith(TestScheme) {
|
||||||
ddd = 2
|
ddd = 2
|
||||||
}
|
}
|
||||||
assertEquals(2, vision.getPropertyValue("fff.ddd")?.int)
|
assertEquals(2, vision.properties.getValue("fff.ddd")?.int)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -9,7 +9,6 @@ import space.kscience.dataforge.meta.MutableMeta
|
|||||||
import space.kscience.dataforge.meta.descriptors.MetaDescriptor
|
import space.kscience.dataforge.meta.descriptors.MetaDescriptor
|
||||||
import space.kscience.dataforge.names.Name
|
import space.kscience.dataforge.names.Name
|
||||||
import space.kscience.visionforge.Vision
|
import space.kscience.visionforge.Vision
|
||||||
import space.kscience.visionforge.getProperty
|
|
||||||
import space.kscience.visionforge.getStyle
|
import space.kscience.visionforge.getStyle
|
||||||
import space.kscience.visionforge.styles
|
import space.kscience.visionforge.styles
|
||||||
import tornadofx.*
|
import tornadofx.*
|
||||||
|
@ -16,7 +16,6 @@ import space.kscience.dataforge.context.*
|
|||||||
import space.kscience.dataforge.meta.Meta
|
import space.kscience.dataforge.meta.Meta
|
||||||
import space.kscience.dataforge.meta.boolean
|
import space.kscience.dataforge.meta.boolean
|
||||||
import space.kscience.dataforge.misc.Type
|
import space.kscience.dataforge.misc.Type
|
||||||
import space.kscience.visionforge.getProperty
|
|
||||||
import space.kscience.visionforge.solid.FX3DFactory.Companion.TYPE
|
import space.kscience.visionforge.solid.FX3DFactory.Companion.TYPE
|
||||||
import space.kscience.visionforge.solid.SolidMaterial.Companion.MATERIAL_KEY
|
import space.kscience.visionforge.solid.SolidMaterial.Companion.MATERIAL_KEY
|
||||||
import space.kscience.visionforge.solid.SolidMaterial.Companion.MATERIAL_WIREFRAME_KEY
|
import space.kscience.visionforge.solid.SolidMaterial.Companion.MATERIAL_WIREFRAME_KEY
|
||||||
@ -77,7 +76,7 @@ public class FX3DPlugin : AbstractPlugin() {
|
|||||||
is PolyLine -> PolyLine3D(
|
is PolyLine -> PolyLine3D(
|
||||||
obj.points.map { Point3D(it.x, it.y, it.z) },
|
obj.points.map { Point3D(it.x, it.y, it.z) },
|
||||||
obj.thickness.toFloat(),
|
obj.thickness.toFloat(),
|
||||||
obj.getProperty(SolidMaterial.MATERIAL_COLOR_KEY).color()
|
obj.get(SolidMaterial.MATERIAL_COLOR_KEY).color()
|
||||||
).apply {
|
).apply {
|
||||||
this.meshView.cullFace = CullFace.FRONT
|
this.meshView.cullFace = CullFace.FRONT
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,6 @@ import space.kscience.dataforge.names.Name
|
|||||||
import space.kscience.dataforge.names.startsWith
|
import space.kscience.dataforge.names.startsWith
|
||||||
import space.kscience.dataforge.values.Value
|
import space.kscience.dataforge.values.Value
|
||||||
import space.kscience.visionforge.Vision
|
import space.kscience.visionforge.Vision
|
||||||
import space.kscience.visionforge.getProperty
|
|
||||||
import space.kscience.visionforge.onPropertyChange
|
import space.kscience.visionforge.onPropertyChange
|
||||||
import tornadofx.*
|
import tornadofx.*
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ public fun SolidGroup.markLayers(thresholds: List<Int> = listOf(500, 1000, 20000
|
|||||||
|
|
||||||
node.vision.layer = layerIndex
|
node.vision.layer = layerIndex
|
||||||
remaining -= node.selfCount * (node.children.size + 1)
|
remaining -= node.selfCount * (node.children.size + 1)
|
||||||
logger?.apply {
|
logger.run {
|
||||||
if (node.selfCount > 1) {
|
if (node.selfCount > 1) {
|
||||||
info { "Prototype with name ${node.name} moved to layer $layerIndex. $remaining nodes remains" }
|
info { "Prototype with name ${node.name} moved to layer $layerIndex. $remaining nodes remains" }
|
||||||
} else {
|
} else {
|
||||||
|
@ -7,13 +7,12 @@ import space.kscience.dataforge.misc.DFExperimental
|
|||||||
import space.kscience.dataforge.names.Name
|
import space.kscience.dataforge.names.Name
|
||||||
import space.kscience.plotly.Plot
|
import space.kscience.plotly.Plot
|
||||||
import space.kscience.plotly.Plotly
|
import space.kscience.plotly.Plotly
|
||||||
import space.kscience.visionforge.VisionGroup
|
import space.kscience.visionforge.AbstractVision
|
||||||
import space.kscience.visionforge.getProperty
|
|
||||||
import space.kscience.visionforge.html.VisionOutput
|
import space.kscience.visionforge.html.VisionOutput
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@SerialName("vision.plotly")
|
@SerialName("vision.plotly")
|
||||||
public class VisionOfPlotly private constructor() : VisionGroup() {
|
public class VisionOfPlotly private constructor() : AbstractVision() {
|
||||||
|
|
||||||
public constructor(plot: Plot) : this() {
|
public constructor(plot: Plot) : this() {
|
||||||
setProperty(Name.EMPTY, plot.meta)
|
setProperty(Name.EMPTY, plot.meta)
|
||||||
|
@ -7,7 +7,7 @@ import space.kscience.dataforge.values.*
|
|||||||
import space.kscience.visionforge.Colors
|
import space.kscience.visionforge.Colors
|
||||||
import space.kscience.visionforge.Vision
|
import space.kscience.visionforge.Vision
|
||||||
import space.kscience.visionforge.VisionBuilder
|
import space.kscience.visionforge.VisionBuilder
|
||||||
import space.kscience.visionforge.getProperty
|
import space.kscience.visionforge.root
|
||||||
import kotlin.properties.ReadOnlyProperty
|
import kotlin.properties.ReadOnlyProperty
|
||||||
|
|
||||||
@VisionBuilder
|
@VisionBuilder
|
||||||
@ -29,7 +29,7 @@ public class ColorAccessor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
public fun Vision.color(): ReadOnlyProperty<Vision, ColorAccessor> = ReadOnlyProperty { _, property ->
|
public fun Vision.color(): ReadOnlyProperty<Vision, ColorAccessor> = ReadOnlyProperty { _, property ->
|
||||||
ColorAccessor(getProperty(Name.EMPTY), property.name.asName())
|
ColorAccessor(properties.root(), property.name.asName())
|
||||||
}
|
}
|
||||||
|
|
||||||
public var ColorAccessor?.string: String?
|
public var ColorAccessor?.string: String?
|
||||||
|
@ -2,7 +2,6 @@ package space.kscience.visionforge.solid
|
|||||||
|
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import space.kscience.dataforge.meta.isEmpty
|
|
||||||
import space.kscience.dataforge.names.Name
|
import space.kscience.dataforge.names.Name
|
||||||
import space.kscience.visionforge.*
|
import space.kscience.visionforge.*
|
||||||
|
|
||||||
@ -19,10 +18,10 @@ public class Composite(
|
|||||||
public val compositeType: CompositeType,
|
public val compositeType: CompositeType,
|
||||||
public val first: Solid,
|
public val first: Solid,
|
||||||
public val second: Solid,
|
public val second: Solid,
|
||||||
) : SolidBase(), VisionPropertyContainer<Composite>
|
) : SolidBase<Composite>()
|
||||||
|
|
||||||
@VisionBuilder
|
@VisionBuilder
|
||||||
public inline fun VisionContainerBuilder<Solid>.composite(
|
public inline fun MutableVisionContainer<Solid>.composite(
|
||||||
type: CompositeType,
|
type: CompositeType,
|
||||||
name: String? = null,
|
name: String? = null,
|
||||||
@VisionBuilder builder: SolidGroup.() -> Unit,
|
@VisionBuilder builder: SolidGroup.() -> Unit,
|
||||||
@ -34,7 +33,7 @@ public inline fun VisionContainerBuilder<Solid>.composite(
|
|||||||
}
|
}
|
||||||
val res = Composite(type, children[0], children[1])
|
val res = Composite(type, children[0], children[1])
|
||||||
|
|
||||||
res.setProperty(Name.EMPTY, group.getProperty(Name.EMPTY))
|
res.properties[Name.EMPTY] = group.properties.raw
|
||||||
|
|
||||||
set(name, res)
|
set(name, res)
|
||||||
return res
|
return res
|
||||||
@ -50,7 +49,7 @@ public fun SolidGroup.smartComposite(
|
|||||||
@VisionBuilder builder: SolidGroup.() -> Unit,
|
@VisionBuilder builder: SolidGroup.() -> Unit,
|
||||||
): Solid = if (type == CompositeType.GROUP) {
|
): Solid = if (type == CompositeType.GROUP) {
|
||||||
val group = SolidGroup(builder)
|
val group = SolidGroup(builder)
|
||||||
if (name == null && group.meta.isEmpty()) {
|
if (name == null && group.properties.raw == null) {
|
||||||
//append directly to group if no properties are defined
|
//append directly to group if no properties are defined
|
||||||
group.items.forEach { (_, value) ->
|
group.items.forEach { (_, value) ->
|
||||||
value.parent = null
|
value.parent = null
|
||||||
@ -66,19 +65,19 @@ public fun SolidGroup.smartComposite(
|
|||||||
}
|
}
|
||||||
|
|
||||||
@VisionBuilder
|
@VisionBuilder
|
||||||
public inline fun VisionContainerBuilder<Solid>.union(
|
public inline fun MutableVisionContainer<Solid>.union(
|
||||||
name: String? = null,
|
name: String? = null,
|
||||||
builder: SolidGroup.() -> Unit,
|
builder: SolidGroup.() -> Unit,
|
||||||
): Composite = composite(CompositeType.UNION, name, builder = builder)
|
): Composite = composite(CompositeType.UNION, name, builder = builder)
|
||||||
|
|
||||||
@VisionBuilder
|
@VisionBuilder
|
||||||
public inline fun VisionContainerBuilder<Solid>.subtract(
|
public inline fun MutableVisionContainer<Solid>.subtract(
|
||||||
name: String? = null,
|
name: String? = null,
|
||||||
builder: SolidGroup.() -> Unit,
|
builder: SolidGroup.() -> Unit,
|
||||||
): Composite = composite(CompositeType.SUBTRACT, name, builder = builder)
|
): Composite = composite(CompositeType.SUBTRACT, name, builder = builder)
|
||||||
|
|
||||||
@VisionBuilder
|
@VisionBuilder
|
||||||
public inline fun VisionContainerBuilder<Solid>.intersect(
|
public inline fun MutableVisionContainer<Solid>.intersect(
|
||||||
name: String? = null,
|
name: String? = null,
|
||||||
builder: SolidGroup.() -> Unit,
|
builder: SolidGroup.() -> Unit,
|
||||||
): Composite = composite(CompositeType.INTERSECT, name, builder = builder)
|
): Composite = composite(CompositeType.INTERSECT, name, builder = builder)
|
@ -2,8 +2,8 @@ package space.kscience.visionforge.solid
|
|||||||
|
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
import space.kscience.visionforge.MutableVisionContainer
|
||||||
import space.kscience.visionforge.VisionBuilder
|
import space.kscience.visionforge.VisionBuilder
|
||||||
import space.kscience.visionforge.VisionContainerBuilder
|
|
||||||
import space.kscience.visionforge.set
|
import space.kscience.visionforge.set
|
||||||
import kotlin.math.cos
|
import kotlin.math.cos
|
||||||
import kotlin.math.sin
|
import kotlin.math.sin
|
||||||
@ -20,7 +20,7 @@ public class ConeSegment(
|
|||||||
public val topRadius: Float,
|
public val topRadius: Float,
|
||||||
public val startAngle: Float = 0f,
|
public val startAngle: Float = 0f,
|
||||||
public val angle: Float = PI2
|
public val angle: Float = PI2
|
||||||
) : SolidBase(), GeometrySolid {
|
) : SolidBase<ConeSegment>(), GeometrySolid {
|
||||||
|
|
||||||
override fun <T : Any> toGeometry(geometryBuilder: GeometryBuilder<T>) {
|
override fun <T : Any> toGeometry(geometryBuilder: GeometryBuilder<T>) {
|
||||||
val segments = detail ?: 32
|
val segments = detail ?: 32
|
||||||
@ -67,7 +67,7 @@ public class ConeSegment(
|
|||||||
}
|
}
|
||||||
|
|
||||||
@VisionBuilder
|
@VisionBuilder
|
||||||
public inline fun VisionContainerBuilder<Solid>.cylinder(
|
public inline fun MutableVisionContainer<Solid>.cylinder(
|
||||||
r: Number,
|
r: Number,
|
||||||
height: Number,
|
height: Number,
|
||||||
name: String? = null,
|
name: String? = null,
|
||||||
@ -79,7 +79,7 @@ public inline fun VisionContainerBuilder<Solid>.cylinder(
|
|||||||
).apply(block).also { set(name, it) }
|
).apply(block).also { set(name, it) }
|
||||||
|
|
||||||
@VisionBuilder
|
@VisionBuilder
|
||||||
public inline fun VisionContainerBuilder<Solid>.cone(
|
public inline fun MutableVisionContainer<Solid>.cone(
|
||||||
bottomRadius: Number,
|
bottomRadius: Number,
|
||||||
height: Number,
|
height: Number,
|
||||||
upperRadius: Number = 0.0,
|
upperRadius: Number = 0.0,
|
||||||
|
@ -2,9 +2,8 @@ package space.kscience.visionforge.solid
|
|||||||
|
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
import space.kscience.visionforge.MutableVisionContainer
|
||||||
import space.kscience.visionforge.VisionBuilder
|
import space.kscience.visionforge.VisionBuilder
|
||||||
import space.kscience.visionforge.VisionContainerBuilder
|
|
||||||
import space.kscience.visionforge.VisionPropertyContainer
|
|
||||||
import space.kscience.visionforge.set
|
import space.kscience.visionforge.set
|
||||||
import kotlin.math.PI
|
import kotlin.math.PI
|
||||||
import kotlin.math.cos
|
import kotlin.math.cos
|
||||||
@ -24,7 +23,7 @@ public class ConeSurface(
|
|||||||
public val topInnerRadius: Float,
|
public val topInnerRadius: Float,
|
||||||
public val startAngle: Float = 0f,
|
public val startAngle: Float = 0f,
|
||||||
public val angle: Float = PI2,
|
public val angle: Float = PI2,
|
||||||
) : SolidBase(), GeometrySolid, VisionPropertyContainer<ConeSurface> {
|
) : SolidBase<ConeSurface>(), GeometrySolid {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
require(bottomRadius > 0) { "Cone surface bottom radius must be positive" }
|
require(bottomRadius > 0) { "Cone surface bottom radius must be positive" }
|
||||||
@ -124,7 +123,7 @@ public class ConeSurface(
|
|||||||
|
|
||||||
|
|
||||||
@VisionBuilder
|
@VisionBuilder
|
||||||
public inline fun VisionContainerBuilder<Solid>.tube(
|
public inline fun MutableVisionContainer<Solid>.tube(
|
||||||
radius: Number,
|
radius: Number,
|
||||||
height: Number,
|
height: Number,
|
||||||
innerRadius: Number,
|
innerRadius: Number,
|
||||||
@ -143,7 +142,7 @@ public inline fun VisionContainerBuilder<Solid>.tube(
|
|||||||
).apply(block).also { set(name, it) }
|
).apply(block).also { set(name, it) }
|
||||||
|
|
||||||
@VisionBuilder
|
@VisionBuilder
|
||||||
public inline fun VisionContainerBuilder<Solid>.coneSurface(
|
public inline fun MutableVisionContainer<Solid>.coneSurface(
|
||||||
bottomOuterRadius: Number,
|
bottomOuterRadius: Number,
|
||||||
bottomInnerRadius: Number,
|
bottomInnerRadius: Number,
|
||||||
height: Number,
|
height: Number,
|
||||||
|
@ -2,16 +2,17 @@ package space.kscience.visionforge.solid
|
|||||||
|
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import space.kscience.visionforge.VisionContainerBuilder
|
import space.kscience.visionforge.MutableVisionContainer
|
||||||
import space.kscience.visionforge.VisionPropertyContainer
|
|
||||||
import space.kscience.visionforge.set
|
import space.kscience.visionforge.set
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@SerialName("solid.convex")
|
@SerialName("solid.convex")
|
||||||
public class Convex(public val points: List<Point3D>) : SolidBase(), VisionPropertyContainer<Convex>
|
public class Convex(public val points: List<Point3D>) : SolidBase<Convex>()
|
||||||
|
|
||||||
public inline fun VisionContainerBuilder<Solid>.convex(name: String? = null, action: ConvexBuilder.() -> Unit = {}): Convex =
|
public inline fun MutableVisionContainer<Solid>.convex(
|
||||||
ConvexBuilder().apply(action).build().also { set(name, it) }
|
name: String? = null,
|
||||||
|
action: ConvexBuilder.() -> Unit = {},
|
||||||
|
): Convex = ConvexBuilder().apply(action).build().also { set(name, it) }
|
||||||
|
|
||||||
public class ConvexBuilder {
|
public class ConvexBuilder {
|
||||||
private val points = ArrayList<Point3D>()
|
private val points = ArrayList<Point3D>()
|
||||||
|
@ -3,7 +3,6 @@ package space.kscience.visionforge.solid
|
|||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import space.kscience.dataforge.meta.MutableMeta
|
import space.kscience.dataforge.meta.MutableMeta
|
||||||
import space.kscience.dataforge.meta.ObservableMutableMeta
|
|
||||||
import space.kscience.dataforge.names.Name
|
import space.kscience.dataforge.names.Name
|
||||||
import space.kscience.visionforge.*
|
import space.kscience.visionforge.*
|
||||||
import kotlin.math.PI
|
import kotlin.math.PI
|
||||||
@ -41,7 +40,7 @@ public data class Layer(var x: Float, var y: Float, var z: Float, var scale: Flo
|
|||||||
public class Extruded(
|
public class Extruded(
|
||||||
public val shape: List<Point2D>,
|
public val shape: List<Point2D>,
|
||||||
public val layers: List<Layer>,
|
public val layers: List<Layer>,
|
||||||
) : SolidBase(), GeometrySolid, VisionPropertyContainer<Extruded> {
|
) : SolidBase<Extruded>(), GeometrySolid {
|
||||||
|
|
||||||
override fun <T : Any> toGeometry(geometryBuilder: GeometryBuilder<T>) {
|
override fun <T : Any> toGeometry(geometryBuilder: GeometryBuilder<T>) {
|
||||||
val shape: Shape2D = shape
|
val shape: Shape2D = shape
|
||||||
@ -96,11 +95,9 @@ public class Extruded(
|
|||||||
|
|
||||||
public class ExtrudeBuilder(
|
public class ExtrudeBuilder(
|
||||||
public var shape: List<Point2D> = emptyList(),
|
public var shape: List<Point2D> = emptyList(),
|
||||||
|
|
||||||
public var layers: MutableList<Layer> = ArrayList(),
|
public var layers: MutableList<Layer> = ArrayList(),
|
||||||
|
public val properties: MutableMeta = MutableMeta(),
|
||||||
config: ObservableMutableMeta = MutableMeta(),
|
) {
|
||||||
) : SimpleVisionPropertyContainer<Extruded>(config) {
|
|
||||||
public fun shape(block: Shape2DBuilder.() -> Unit) {
|
public fun shape(block: Shape2DBuilder.() -> Unit) {
|
||||||
this.shape = Shape2DBuilder().apply(block).build()
|
this.shape = Shape2DBuilder().apply(block).build()
|
||||||
}
|
}
|
||||||
@ -110,12 +107,12 @@ public class ExtrudeBuilder(
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal fun build(): Extruded = Extruded(shape, layers).apply {
|
internal fun build(): Extruded = Extruded(shape, layers).apply {
|
||||||
setProperty(Name.EMPTY, getProperty(Name.EMPTY))
|
this.properties[Name.EMPTY] = this@ExtrudeBuilder.properties
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisionBuilder
|
@VisionBuilder
|
||||||
public fun VisionContainerBuilder<Solid>.extruded(
|
public fun MutableVisionContainer<Solid>.extruded(
|
||||||
name: String? = null,
|
name: String? = null,
|
||||||
action: ExtrudeBuilder.() -> Unit = {},
|
action: ExtrudeBuilder.() -> Unit = {},
|
||||||
): Extruded = ExtrudeBuilder().apply(action).build().also { set(name, it) }
|
): Extruded = ExtrudeBuilder().apply(action).build().also { set(name, it) }
|
@ -2,8 +2,8 @@ package space.kscience.visionforge.solid
|
|||||||
|
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
import space.kscience.visionforge.MutableVisionContainer
|
||||||
import space.kscience.visionforge.VisionBuilder
|
import space.kscience.visionforge.VisionBuilder
|
||||||
import space.kscience.visionforge.VisionContainerBuilder
|
|
||||||
import space.kscience.visionforge.set
|
import space.kscience.visionforge.set
|
||||||
|
|
||||||
public interface Hexagon : GeometrySolid {
|
public interface Hexagon : GeometrySolid {
|
||||||
@ -35,7 +35,7 @@ public class Box(
|
|||||||
public val xSize: Float,
|
public val xSize: Float,
|
||||||
public val ySize: Float,
|
public val ySize: Float,
|
||||||
public val zSize: Float,
|
public val zSize: Float,
|
||||||
) : SolidBase(), Hexagon {
|
) : SolidBase<Box>(), Hexagon {
|
||||||
|
|
||||||
private inline val dx get() = xSize / 2
|
private inline val dx get() = xSize / 2
|
||||||
private inline val dy get() = ySize / 2
|
private inline val dy get() = ySize / 2
|
||||||
@ -52,7 +52,7 @@ public class Box(
|
|||||||
}
|
}
|
||||||
|
|
||||||
@VisionBuilder
|
@VisionBuilder
|
||||||
public inline fun VisionContainerBuilder<Solid>.box(
|
public inline fun MutableVisionContainer<Solid>.box(
|
||||||
xSize: Number,
|
xSize: Number,
|
||||||
ySize: Number,
|
ySize: Number,
|
||||||
zSize: Number,
|
zSize: Number,
|
||||||
@ -71,10 +71,10 @@ public class GenericHexagon(
|
|||||||
override val node6: Point3D,
|
override val node6: Point3D,
|
||||||
override val node7: Point3D,
|
override val node7: Point3D,
|
||||||
override val node8: Point3D,
|
override val node8: Point3D,
|
||||||
) : SolidBase(), Hexagon
|
) : SolidBase<GenericHexagon>(), Hexagon
|
||||||
|
|
||||||
@VisionBuilder
|
@VisionBuilder
|
||||||
public inline fun VisionContainerBuilder<Solid>.hexagon(
|
public inline fun MutableVisionContainer<Solid>.hexagon(
|
||||||
node1: Point3D,
|
node1: Point3D,
|
||||||
node2: Point3D,
|
node2: Point3D,
|
||||||
node3: Point3D,
|
node3: Point3D,
|
||||||
|
@ -5,15 +5,16 @@ import kotlinx.serialization.Serializable
|
|||||||
import space.kscience.dataforge.meta.descriptors.MetaDescriptor
|
import space.kscience.dataforge.meta.descriptors.MetaDescriptor
|
||||||
import space.kscience.dataforge.meta.descriptors.node
|
import space.kscience.dataforge.meta.descriptors.node
|
||||||
import space.kscience.dataforge.meta.descriptors.value
|
import space.kscience.dataforge.meta.descriptors.value
|
||||||
|
import space.kscience.dataforge.meta.number
|
||||||
import space.kscience.dataforge.values.ValueType
|
import space.kscience.dataforge.values.ValueType
|
||||||
import space.kscience.visionforge.*
|
import space.kscience.visionforge.*
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
public abstract class LightSource : SolidBase() {
|
public abstract class LightSource : SolidBase<LightSource>() {
|
||||||
override val descriptor: MetaDescriptor get() = LightSource.descriptor
|
override val descriptor: MetaDescriptor get() = LightSource.descriptor
|
||||||
|
|
||||||
public val color: ColorAccessor by color()
|
public val color: ColorAccessor by color()
|
||||||
public var intensity: Number by numberProperty(includeStyles = false) { 1.0 }
|
public var intensity: Number by properties.root(includeStyles = false).number { 1.0 }
|
||||||
|
|
||||||
public companion object{
|
public companion object{
|
||||||
public val descriptor: MetaDescriptor by lazy {
|
public val descriptor: MetaDescriptor by lazy {
|
||||||
@ -51,7 +52,7 @@ public abstract class LightSource : SolidBase() {
|
|||||||
public class AmbientLightSource : LightSource()
|
public class AmbientLightSource : LightSource()
|
||||||
|
|
||||||
@VisionBuilder
|
@VisionBuilder
|
||||||
public fun VisionContainerBuilder<Solid>.ambientLight(
|
public fun MutableVisionContainer<Solid>.ambientLight(
|
||||||
name: String? = "@ambientLight",
|
name: String? = "@ambientLight",
|
||||||
block: AmbientLightSource.() -> Unit = {},
|
block: AmbientLightSource.() -> Unit = {},
|
||||||
): AmbientLightSource = AmbientLightSource().apply(block).also { set(name, it) }
|
): AmbientLightSource = AmbientLightSource().apply(block).also { set(name, it) }
|
||||||
@ -62,7 +63,7 @@ public class PointLightSource : LightSource()
|
|||||||
|
|
||||||
|
|
||||||
@VisionBuilder
|
@VisionBuilder
|
||||||
public fun VisionContainerBuilder<Solid>.pointLight(
|
public fun MutableVisionContainer<Solid>.pointLight(
|
||||||
x: Number,
|
x: Number,
|
||||||
y: Number,
|
y: Number,
|
||||||
z: Number,
|
z: Number,
|
||||||
|
@ -2,27 +2,19 @@ package space.kscience.visionforge.solid
|
|||||||
|
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import space.kscience.dataforge.names.Name
|
import space.kscience.dataforge.meta.number
|
||||||
import space.kscience.dataforge.names.asName
|
|
||||||
import space.kscience.dataforge.names.plus
|
|
||||||
import space.kscience.visionforge.*
|
import space.kscience.visionforge.*
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@SerialName("solid.line")
|
@SerialName("solid.line")
|
||||||
public class PolyLine(public val points: List<Point3D>) : SolidBase(), VisionPropertyContainer<PolyLine> {
|
public class PolyLine(public val points: List<Point3D>) : SolidBase<PolyLine>() {
|
||||||
|
|
||||||
//var lineType by string()
|
//var lineType by string()
|
||||||
public var thickness: Number by numberProperty(name = SolidMaterial.MATERIAL_KEY + THICKNESS_KEY) { 1.0 }
|
public var thickness: Number by properties[SolidMaterial.MATERIAL_KEY].number { 1.0 }
|
||||||
|
|
||||||
|
|
||||||
public companion object {
|
|
||||||
public val THICKNESS_KEY: Name = "thickness".asName()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisionBuilder
|
@VisionBuilder
|
||||||
public fun VisionContainerBuilder<Solid>.polyline(
|
public fun MutableVisionContainer<Solid>.polyline(
|
||||||
vararg points: Point3D,
|
vararg points: Point3D,
|
||||||
name: String? = null,
|
name: String? = null,
|
||||||
action: PolyLine.() -> Unit = {},
|
action: PolyLine.() -> Unit = {},
|
||||||
|
@ -115,9 +115,9 @@ public interface Solid : Vision {
|
|||||||
* Get the layer number this solid belongs to. Return 0 if layer is not defined.
|
* Get the layer number this solid belongs to. Return 0 if layer is not defined.
|
||||||
*/
|
*/
|
||||||
public var Solid.layer: Int
|
public var Solid.layer: Int
|
||||||
get() = getPropertyValue(LAYER_KEY, inherit = true)?.int ?: 0
|
get() = properties.getValue(LAYER_KEY, inherit = true)?.int ?: 0
|
||||||
set(value) {
|
set(value) {
|
||||||
setPropertyValue(LAYER_KEY, value)
|
properties.set(LAYER_KEY, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Common properties
|
// Common properties
|
||||||
@ -135,24 +135,24 @@ public enum class RotationOrder {
|
|||||||
* Rotation order
|
* Rotation order
|
||||||
*/
|
*/
|
||||||
public var Solid.rotationOrder: RotationOrder
|
public var Solid.rotationOrder: RotationOrder
|
||||||
get() = getPropertyValue(Solid.ROTATION_ORDER_KEY)?.enum<RotationOrder>() ?: RotationOrder.XYZ
|
get() = properties.getValue(Solid.ROTATION_ORDER_KEY)?.enum<RotationOrder>() ?: RotationOrder.XYZ
|
||||||
set(value) = setPropertyValue(Solid.ROTATION_ORDER_KEY, value.name.asValue())
|
set(value) = properties.setValue(Solid.ROTATION_ORDER_KEY, value.name.asValue())
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Preferred number of polygons for displaying the object. If not defined, uses shape or renderer default. Not inherited
|
* Preferred number of polygons for displaying the object. If not defined, uses shape or renderer default. Not inherited
|
||||||
*/
|
*/
|
||||||
public var Solid.detail: Int?
|
public var Solid.detail: Int?
|
||||||
get() = getPropertyValue(DETAIL_KEY, inherit = false)?.int
|
get() = properties.getValue(DETAIL_KEY, inherit = false)?.int
|
||||||
set(value) = setPropertyValue(DETAIL_KEY, value?.asValue())
|
set(value) = properties.setValue(DETAIL_KEY, value?.asValue())
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If this property is true, the object will be ignored on render.
|
* If this property is true, the object will be ignored on render.
|
||||||
* Property is not inherited.
|
* Property is not inherited.
|
||||||
*/
|
*/
|
||||||
public var Vision.ignore: Boolean?
|
public var Vision.ignore: Boolean?
|
||||||
get() = getPropertyValue(IGNORE_KEY, inherit = false)?.boolean
|
get() = properties.getValue(IGNORE_KEY, inherit = false, includeStyles = false)?.boolean
|
||||||
set(value) = setPropertyValue(IGNORE_KEY, value?.asValue())
|
set(value) = properties.setValue(IGNORE_KEY, value?.asValue())
|
||||||
|
|
||||||
//var VisualObject.selected: Boolean?
|
//var VisualObject.selected: Boolean?
|
||||||
// get() = getProperty(SELECTED_KEY).boolean
|
// get() = getProperty(SELECTED_KEY).boolean
|
||||||
@ -161,18 +161,18 @@ public var Vision.ignore: Boolean?
|
|||||||
internal fun float(name: Name, default: Number): ReadWriteProperty<Solid, Number> =
|
internal fun float(name: Name, default: Number): ReadWriteProperty<Solid, Number> =
|
||||||
object : ReadWriteProperty<Solid, Number> {
|
object : ReadWriteProperty<Solid, Number> {
|
||||||
override fun getValue(thisRef: Solid, property: KProperty<*>): Number {
|
override fun getValue(thisRef: Solid, property: KProperty<*>): Number {
|
||||||
return thisRef.getPropertyValue(name)?.number ?: default
|
return thisRef.properties.getValue(name)?.number ?: default
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setValue(thisRef: Solid, property: KProperty<*>, value: Number) {
|
override fun setValue(thisRef: Solid, property: KProperty<*>, value: Number) {
|
||||||
thisRef.setPropertyValue(name, value)
|
thisRef.properties.setValue(name, value.asValue())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun point(name: Name, default: Float): ReadWriteProperty<Solid, Point3D?> =
|
internal fun point(name: Name, default: Float): ReadWriteProperty<Solid, Point3D?> =
|
||||||
object : ReadWriteProperty<Solid, Point3D?> {
|
object : ReadWriteProperty<Solid, Point3D?> {
|
||||||
override fun getValue(thisRef: Solid, property: KProperty<*>): Point3D? {
|
override fun getValue(thisRef: Solid, property: KProperty<*>): Point3D? {
|
||||||
val item = thisRef.meta[name] ?: return null
|
val item = thisRef.properties.raw?.get(name) ?: return null
|
||||||
return object : Point3D {
|
return object : Point3D {
|
||||||
override val x: Float get() = item[X_KEY]?.float ?: default
|
override val x: Float get() = item[X_KEY]?.float ?: default
|
||||||
override val y: Float get() = item[Y_KEY]?.float ?: default
|
override val y: Float get() = item[Y_KEY]?.float ?: default
|
||||||
@ -182,11 +182,11 @@ internal fun point(name: Name, default: Float): ReadWriteProperty<Solid, Point3D
|
|||||||
|
|
||||||
override fun setValue(thisRef: Solid, property: KProperty<*>, value: Point3D?) {
|
override fun setValue(thisRef: Solid, property: KProperty<*>, value: Point3D?) {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
thisRef.setProperty(name, null)
|
thisRef.properties[name] = null
|
||||||
} else {
|
} else {
|
||||||
thisRef.setPropertyValue(name + X_KEY, value.x)
|
thisRef.properties[name + X_KEY] = value.x
|
||||||
thisRef.setPropertyValue(name + Y_KEY, value.y)
|
thisRef.properties[name + Y_KEY] = value.y
|
||||||
thisRef.setPropertyValue(name + Z_KEY, value.z)
|
thisRef.properties[name + Z_KEY] = value.z
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,24 +2,11 @@ package space.kscience.visionforge.solid
|
|||||||
|
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import space.kscience.dataforge.meta.MutableMeta
|
|
||||||
import space.kscience.dataforge.meta.descriptors.MetaDescriptor
|
import space.kscience.dataforge.meta.descriptors.MetaDescriptor
|
||||||
import space.kscience.dataforge.names.Name
|
|
||||||
import space.kscience.visionforge.AbstractVision
|
import space.kscience.visionforge.AbstractVision
|
||||||
import space.kscience.visionforge.VisionChildren
|
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@SerialName("solid")
|
@SerialName("solid")
|
||||||
public open class SolidBase : AbstractVision(), Solid {
|
public open class SolidBase<T : Solid> : AbstractVision(), Solid {
|
||||||
override val descriptor: MetaDescriptor get() = Solid.descriptor
|
override val descriptor: MetaDescriptor get() = Solid.descriptor
|
||||||
override val children: VisionChildren get() = VisionChildren.empty(this)
|
|
||||||
|
|
||||||
override fun getProperty(
|
|
||||||
name: Name,
|
|
||||||
inherit: Boolean,
|
|
||||||
includeStyles: Boolean,
|
|
||||||
includeDefaults: Boolean,
|
|
||||||
): MutableMeta {
|
|
||||||
return super<AbstractVision>.getProperty(name, inherit, includeStyles, includeDefaults)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ public interface PrototypeHolder {
|
|||||||
* Build or update prototype tree
|
* Build or update prototype tree
|
||||||
*/
|
*/
|
||||||
@VisionBuilder
|
@VisionBuilder
|
||||||
public fun prototypes(builder: VisionContainerBuilder<Solid>.() -> Unit)
|
public fun prototypes(builder: MutableVisionContainer<Solid>.() -> Unit)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve a prototype from this container. Should never return a ref.
|
* Resolve a prototype from this container. Should never return a ref.
|
||||||
@ -30,7 +30,7 @@ public interface PrototypeHolder {
|
|||||||
*/
|
*/
|
||||||
@Serializable
|
@Serializable
|
||||||
@SerialName("group.solid")
|
@SerialName("group.solid")
|
||||||
public class SolidGroup : VisionGroup(), Solid, PrototypeHolder, MutableVisionGroup, VisionContainerBuilder<Solid> {
|
public class SolidGroup : AbstractVisionGroup(), Solid, PrototypeHolder, MutableVisionGroup, MutableVisionContainer<Solid> {
|
||||||
|
|
||||||
public val items: Map<NameToken, Solid>
|
public val items: Map<NameToken, Solid>
|
||||||
get() = children.keys.mapNotNull {
|
get() = children.keys.mapNotNull {
|
||||||
@ -59,7 +59,7 @@ public class SolidGroup : VisionGroup(), Solid, PrototypeHolder, MutableVisionGr
|
|||||||
/**
|
/**
|
||||||
* Create or edit prototype node as a group
|
* Create or edit prototype node as a group
|
||||||
*/
|
*/
|
||||||
override fun prototypes(builder: VisionContainerBuilder<Solid>.() -> Unit): Unit {
|
override fun prototypes(builder: MutableVisionContainer<Solid>.() -> Unit): Unit {
|
||||||
(prototypes ?: SolidGroup().also { prototypes = it }).children.run(builder)
|
(prototypes ?: SolidGroup().also { prototypes = it }).children.run(builder)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,7 +82,7 @@ public class SolidGroup : VisionGroup(), Solid, PrototypeHolder, MutableVisionGr
|
|||||||
public inline fun SolidGroup(block: SolidGroup.() -> Unit): SolidGroup = SolidGroup().apply(block)
|
public inline fun SolidGroup(block: SolidGroup.() -> Unit): SolidGroup = SolidGroup().apply(block)
|
||||||
|
|
||||||
@VisionBuilder
|
@VisionBuilder
|
||||||
public fun VisionContainerBuilder<Solid>.group(
|
public fun MutableVisionContainer<Solid>.group(
|
||||||
name: Name? = null,
|
name: Name? = null,
|
||||||
builder: SolidGroup.() -> Unit = {},
|
builder: SolidGroup.() -> Unit = {},
|
||||||
): SolidGroup = SolidGroup(builder).also { set(name, it) }
|
): SolidGroup = SolidGroup(builder).also { set(name, it) }
|
||||||
@ -91,7 +91,7 @@ public fun VisionContainerBuilder<Solid>.group(
|
|||||||
* Define a group with given [name], attach it to this parent and return it.
|
* Define a group with given [name], attach it to this parent and return it.
|
||||||
*/
|
*/
|
||||||
@VisionBuilder
|
@VisionBuilder
|
||||||
public fun VisionContainerBuilder<Solid>.group(
|
public fun MutableVisionContainer<Solid>.group(
|
||||||
name: String,
|
name: String,
|
||||||
action: SolidGroup.() -> Unit = {},
|
action: SolidGroup.() -> Unit = {},
|
||||||
): SolidGroup = SolidGroup(action).also { set(name, it) }
|
): SolidGroup = SolidGroup(action).also { set(name, it) }
|
||||||
|
@ -2,9 +2,8 @@ package space.kscience.visionforge.solid
|
|||||||
|
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
import space.kscience.visionforge.MutableVisionContainer
|
||||||
import space.kscience.visionforge.VisionBuilder
|
import space.kscience.visionforge.VisionBuilder
|
||||||
import space.kscience.visionforge.VisionContainerBuilder
|
|
||||||
import space.kscience.visionforge.VisionPropertyContainer
|
|
||||||
import space.kscience.visionforge.set
|
import space.kscience.visionforge.set
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@ -13,10 +12,10 @@ public class SolidLabel(
|
|||||||
public val text: String,
|
public val text: String,
|
||||||
public val fontSize: Double,
|
public val fontSize: Double,
|
||||||
public val fontFamily: String,
|
public val fontFamily: String,
|
||||||
) : SolidBase(), VisionPropertyContainer<SolidLabel>
|
) : SolidBase<SolidLabel>()
|
||||||
|
|
||||||
@VisionBuilder
|
@VisionBuilder
|
||||||
public fun VisionContainerBuilder<Solid>.label(
|
public fun MutableVisionContainer<Solid>.label(
|
||||||
text: String,
|
text: String,
|
||||||
fontSize: Number = 20,
|
fontSize: Number = 20,
|
||||||
fontFamily: String = "Arial",
|
fontFamily: String = "Arial",
|
||||||
|
@ -102,19 +102,19 @@ public class SolidMaterial : Scheme() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public val Solid.color: ColorAccessor
|
public val Solid.color: ColorAccessor
|
||||||
get() = ColorAccessor(getProperty(Name.EMPTY), MATERIAL_COLOR_KEY)
|
get() = ColorAccessor(properties.root(), MATERIAL_COLOR_KEY)
|
||||||
|
|
||||||
public var Solid.material: SolidMaterial?
|
public var Solid.material: SolidMaterial?
|
||||||
get() = SolidMaterial.read(getProperty(MATERIAL_KEY))
|
get() = SolidMaterial.read(properties[MATERIAL_KEY])
|
||||||
set(value) = setProperty(MATERIAL_KEY, value?.meta)
|
set(value) = properties.set(MATERIAL_KEY, value?.meta)
|
||||||
|
|
||||||
@VisionBuilder
|
@VisionBuilder
|
||||||
public fun Solid.material(builder: SolidMaterial.() -> Unit) {
|
public fun Solid.material(builder: SolidMaterial.() -> Unit) {
|
||||||
getProperty(MATERIAL_KEY).updateWith(SolidMaterial, builder)
|
properties[MATERIAL_KEY].updateWith(SolidMaterial, builder)
|
||||||
}
|
}
|
||||||
|
|
||||||
public var Solid.opacity: Number?
|
public var Solid.opacity: Number?
|
||||||
get() = getPropertyValue(MATERIAL_OPACITY_KEY, inherit = true)?.number
|
get() = properties.getValue(MATERIAL_OPACITY_KEY, inherit = true)?.number
|
||||||
set(value) {
|
set(value) {
|
||||||
setPropertyValue(MATERIAL_OPACITY_KEY, value?.asValue())
|
properties.setValue(MATERIAL_OPACITY_KEY, value?.asValue())
|
||||||
}
|
}
|
@ -1,14 +1,15 @@
|
|||||||
package space.kscience.visionforge.solid
|
package space.kscience.visionforge.solid
|
||||||
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.*
|
||||||
import kotlinx.coroutines.flow.SharedFlow
|
|
||||||
import kotlinx.coroutines.flow.emptyFlow
|
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import space.kscience.dataforge.meta.Meta
|
import kotlinx.serialization.Transient
|
||||||
|
import space.kscience.dataforge.meta.*
|
||||||
|
import space.kscience.dataforge.meta.descriptors.MetaDescriptor
|
||||||
import space.kscience.dataforge.names.*
|
import space.kscience.dataforge.names.*
|
||||||
import space.kscience.dataforge.values.Value
|
import space.kscience.dataforge.values.Value
|
||||||
import space.kscience.visionforge.*
|
import space.kscience.visionforge.*
|
||||||
|
import space.kscience.visionforge.AbstractVisionGroup.Companion.updateProperties
|
||||||
import space.kscience.visionforge.solid.SolidReference.Companion.REFERENCE_CHILD_PROPERTY_PREFIX
|
import space.kscience.visionforge.solid.SolidReference.Companion.REFERENCE_CHILD_PROPERTY_PREFIX
|
||||||
|
|
||||||
|
|
||||||
@ -23,6 +24,71 @@ public val Vision.unref: Solid
|
|||||||
else -> error("This Vision is neither Solid nor SolidReference")
|
else -> error("This Vision is neither Solid nor SolidReference")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
@SerialName("solid.ref")
|
||||||
|
public class SolidReference(
|
||||||
|
@SerialName("prototype") public val prototypeName: Name,
|
||||||
|
) : SolidBase<SolidReference>(), VisionGroup {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The prototype for this reference.
|
||||||
|
*/
|
||||||
|
public val prototype: Solid by lazy {
|
||||||
|
//Recursively search for defined template in the parent
|
||||||
|
if (parent == null) error("No parent is present for SolidReference")
|
||||||
|
if (parent !is PrototypeHolder) error("Parent does not hold prototypes")
|
||||||
|
(parent as? PrototypeHolder)?.getPrototype(prototypeName)
|
||||||
|
?: error("Prototype with name $prototypeName not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
override val descriptor: MetaDescriptor get() = prototype.descriptor
|
||||||
|
|
||||||
|
override val defaultProperties: Meta
|
||||||
|
get() = prototype.properties.raw?.withDefault(descriptor.defaultNode) ?: descriptor.defaultNode
|
||||||
|
|
||||||
|
override val children: VisionChildren
|
||||||
|
get() = object : VisionChildren {
|
||||||
|
override val group: Vision get() = this@SolidReference
|
||||||
|
|
||||||
|
override val keys: Set<NameToken> get() = prototype.children?.keys ?: emptySet()
|
||||||
|
|
||||||
|
override val changes: Flow<Name> get() = emptyFlow()
|
||||||
|
|
||||||
|
override fun get(token: NameToken): SolidReferenceChild? {
|
||||||
|
if (token !in (prototype.children?.keys ?: emptySet())) return null
|
||||||
|
return SolidReferenceChild(this@SolidReference, this@SolidReference, token.asName())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// override fun getPropertyValue(
|
||||||
|
// name: Name,
|
||||||
|
// inherit: Boolean,
|
||||||
|
// includeStyles: Boolean,
|
||||||
|
// includeDefaults: Boolean,
|
||||||
|
// ): Value? {
|
||||||
|
// meta?.getValue(name)?.let { return it }
|
||||||
|
// if (includeStyles) {
|
||||||
|
// getStyleProperty(name)?.value?.let { return it }
|
||||||
|
// }
|
||||||
|
// prototype.getPropertyValue(name, inherit, includeStyles, includeDefaults)?.let { return it }
|
||||||
|
// if (inherit) {
|
||||||
|
// parent?.getPropertyValue(name, inherit, includeStyles, includeDefaults)?.let { return it }
|
||||||
|
// }
|
||||||
|
// return null
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// override fun getProperty(
|
||||||
|
// name: Name,
|
||||||
|
// inherit: Boolean,
|
||||||
|
// includeStyles: Boolean,
|
||||||
|
// includeDefaults: Boolean,
|
||||||
|
// ): MutableMeta = VisionProperties(this, name, descriptor[name], inherit, includeStyles, prototype.meta)
|
||||||
|
|
||||||
|
public companion object {
|
||||||
|
public const val REFERENCE_CHILD_PROPERTY_PREFIX: String = "@child"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param name A name of reference child relative to prototype root
|
* @param name A name of reference child relative to prototype root
|
||||||
*/
|
*/
|
||||||
@ -30,62 +96,74 @@ internal class SolidReferenceChild(
|
|||||||
val owner: SolidReference,
|
val owner: SolidReference,
|
||||||
override var parent: Vision?,
|
override var parent: Vision?,
|
||||||
val childName: Name,
|
val childName: Name,
|
||||||
) : Solid {
|
) : Solid, VisionGroup {
|
||||||
|
|
||||||
val prototype: Solid
|
val prototype: Solid
|
||||||
get() = owner.prototype.children[childName] as? Solid
|
get() = owner.prototype.children?.get(childName) as? Solid
|
||||||
?: error("Prototype with name $childName not found")
|
?: error("Prototype with name $childName not found")
|
||||||
|
|
||||||
override val meta: Meta get() = owner.getProperty(childToken(childName).asName())
|
override val descriptor: MetaDescriptor get() = prototype.descriptor
|
||||||
|
|
||||||
override fun getPropertyValue(
|
@Transient
|
||||||
name: Name,
|
override val properties: MutableVisionProperties = object : MutableVisionProperties {
|
||||||
inherit: Boolean,
|
override val descriptor: MetaDescriptor get() = this@SolidReferenceChild.descriptor
|
||||||
includeStyles: Boolean,
|
override val default: Meta
|
||||||
includeDefaults: Boolean,
|
get() = prototype.properties.raw?.withDefault(descriptor.defaultNode) ?: descriptor.defaultNode
|
||||||
): Value? {
|
|
||||||
owner.getPropertyValue(
|
override val raw: MutableMeta by lazy { owner.properties[childToken(childName).asName()] }
|
||||||
childPropertyName(childName, name), inherit, includeStyles, includeDefaults
|
|
||||||
)?.let { return it }
|
override fun getValue(
|
||||||
if (includeStyles) {
|
name: Name,
|
||||||
getStyleProperty(name)?.value?.let { return it }
|
inherit: Boolean,
|
||||||
|
includeStyles: Boolean,
|
||||||
|
): Value? {
|
||||||
|
raw[name]?.value?.let { return it }
|
||||||
|
if (includeStyles) {
|
||||||
|
getStyleProperty(name)?.value?.let { return it }
|
||||||
|
}
|
||||||
|
if (inherit) {
|
||||||
|
parent?.properties?.getValue(name, inherit, includeStyles)?.let { return it }
|
||||||
|
}
|
||||||
|
return default[name]?.value
|
||||||
}
|
}
|
||||||
prototype.getPropertyValue(name, inherit, includeStyles, includeDefaults)?.let { return it }
|
|
||||||
if (inherit) {
|
override fun set(name: Name, node: Meta?) {
|
||||||
parent?.getPropertyValue(name, inherit, includeStyles, includeDefaults)?.let { return it }
|
raw.setMeta(name, node)
|
||||||
}
|
}
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setProperty(name: Name, node: Meta?) {
|
override fun setValue(name: Name, value: Value?) {
|
||||||
owner.setProperty(childPropertyName(childName, name), node)
|
raw.setValue(name, value)
|
||||||
}
|
}
|
||||||
|
override val changes: Flow<Name> get() = owner.properties.changes.filter { it.startsWith(childToken(childName)) }
|
||||||
|
|
||||||
override fun setPropertyValue(name: Name, value: Value?) {
|
override fun invalidate(propertyName: Name) {
|
||||||
owner.setPropertyValue(childPropertyName(childName, name), value)
|
owner.properties.invalidate(childPropertyName(childName, propertyName))
|
||||||
}
|
}
|
||||||
|
|
||||||
override val propertyChanges: SharedFlow<Name>
|
|
||||||
get() = TODO("Not yet implemented")
|
|
||||||
|
|
||||||
override fun invalidateProperty(propertyName: Name) {
|
|
||||||
owner.invalidateProperty(childPropertyName(childName, propertyName))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun update(change: VisionChange) {
|
override fun update(change: VisionChange) {
|
||||||
TODO("Not yet implemented")
|
change.children?.forEach { (name, change) ->
|
||||||
|
when {
|
||||||
|
change.delete -> error("Deleting children inside ref is not allowed.")
|
||||||
|
change.vision != null -> error("Updating content of the ref is not allowed")
|
||||||
|
else -> children[name]?.update(change)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
change.properties?.let {
|
||||||
|
updateProperties(it, Name.EMPTY)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override val children: VisionChildren = object : VisionChildren {
|
override val children: VisionChildren = object : VisionChildren {
|
||||||
override val parent: Vision get() = this@SolidReferenceChild
|
override val group: Vision get() = this@SolidReferenceChild
|
||||||
|
|
||||||
override val keys: Set<NameToken> get() = prototype.children.keys
|
override val keys: Set<NameToken> get() = prototype.children?.keys ?: emptySet()
|
||||||
|
|
||||||
override val changes: Flow<Name> get() = emptyFlow()
|
override val changes: Flow<Name> get() = emptyFlow()
|
||||||
|
|
||||||
override fun get(token: NameToken): SolidReferenceChild? {
|
override fun get(token: NameToken): SolidReferenceChild? {
|
||||||
if (token !in prototype.children.keys) return null
|
if (token !in (prototype.children?.keys ?: emptySet())) return null
|
||||||
return SolidReferenceChild(this@SolidReferenceChild.owner, this@SolidReferenceChild, childName + token)
|
return SolidReferenceChild(this@SolidReferenceChild.owner, this@SolidReferenceChild, childName + token)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -101,51 +179,15 @@ internal class SolidReferenceChild(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Serializable
|
|
||||||
@SerialName("solid.ref")
|
|
||||||
public class SolidReference(
|
|
||||||
@SerialName("prototype") public val prototypeName: Name,
|
|
||||||
) : SolidBase() {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The prototype for this reference.
|
|
||||||
*/
|
|
||||||
public val prototype: Solid by lazy {
|
|
||||||
//Recursively search for defined template in the parent
|
|
||||||
if (parent == null) error("No parent is present for SolidReference")
|
|
||||||
if (parent !is PrototypeHolder) error("Parent does not hold prototypes")
|
|
||||||
(parent as? PrototypeHolder)?.getPrototype(prototypeName)
|
|
||||||
?: error("Prototype with name $prototypeName not found")
|
|
||||||
}
|
|
||||||
|
|
||||||
override val children: VisionChildren
|
|
||||||
get() = object : VisionChildren {
|
|
||||||
override val parent: Vision get() = this@SolidReference
|
|
||||||
|
|
||||||
override val keys: Set<NameToken> get() = prototype.children.keys
|
|
||||||
|
|
||||||
override val changes: Flow<Name> get() = emptyFlow()
|
|
||||||
|
|
||||||
override fun get(token: NameToken): SolidReferenceChild? {
|
|
||||||
if (token !in prototype.children.keys) return null
|
|
||||||
return SolidReferenceChild(this@SolidReference, this@SolidReference, token.asName())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public companion object{
|
|
||||||
public const val REFERENCE_CHILD_PROPERTY_PREFIX: String = "@child"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create ref for existing prototype
|
* Create ref for existing prototype
|
||||||
*/
|
*/
|
||||||
public fun VisionContainerBuilder<Solid>.ref(
|
public fun MutableVisionContainer<Solid>.ref(
|
||||||
templateName: Name,
|
templateName: Name,
|
||||||
name: String? = null,
|
name: String? = null,
|
||||||
): SolidReference = SolidReference(templateName).also { set(name, it) }
|
): SolidReference = SolidReference(templateName).also { set(name, it) }
|
||||||
|
|
||||||
public fun VisionContainerBuilder<Solid>.ref(
|
public fun MutableVisionContainer<Solid>.ref(
|
||||||
templateName: String,
|
templateName: String,
|
||||||
name: String? = null,
|
name: String? = null,
|
||||||
): SolidReference = ref(Name.parse(templateName), name)
|
): SolidReference = ref(Name.parse(templateName), name)
|
||||||
|
@ -6,6 +6,7 @@ import kotlinx.serialization.modules.PolymorphicModuleBuilder
|
|||||||
import kotlinx.serialization.modules.SerializersModule
|
import kotlinx.serialization.modules.SerializersModule
|
||||||
import kotlinx.serialization.modules.polymorphic
|
import kotlinx.serialization.modules.polymorphic
|
||||||
import kotlinx.serialization.modules.subclass
|
import kotlinx.serialization.modules.subclass
|
||||||
|
import kotlinx.serialization.serializer
|
||||||
import space.kscience.dataforge.context.Context
|
import space.kscience.dataforge.context.Context
|
||||||
import space.kscience.dataforge.context.PluginFactory
|
import space.kscience.dataforge.context.PluginFactory
|
||||||
import space.kscience.dataforge.context.PluginTag
|
import space.kscience.dataforge.context.PluginTag
|
||||||
@ -47,12 +48,12 @@ public class Solids(meta: Meta) : VisionPlugin(meta) {
|
|||||||
|
|
||||||
public val serializersModuleForSolids: SerializersModule = SerializersModule {
|
public val serializersModuleForSolids: SerializersModule = SerializersModule {
|
||||||
polymorphic(Vision::class) {
|
polymorphic(Vision::class) {
|
||||||
subclass(VisionGroup.serializer())
|
subclass(SimpleVisionGroup.serializer())
|
||||||
solids()
|
solids()
|
||||||
}
|
}
|
||||||
|
|
||||||
polymorphic(Solid::class) {
|
polymorphic(Solid::class) {
|
||||||
default { SolidBase.serializer() }
|
default { SolidBase.serializer(serializer<Solid>()) }
|
||||||
solids()
|
solids()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,8 @@ package space.kscience.visionforge.solid
|
|||||||
|
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
import space.kscience.visionforge.MutableVisionContainer
|
||||||
import space.kscience.visionforge.VisionBuilder
|
import space.kscience.visionforge.VisionBuilder
|
||||||
import space.kscience.visionforge.VisionContainerBuilder
|
|
||||||
import space.kscience.visionforge.VisionPropertyContainer
|
|
||||||
import space.kscience.visionforge.set
|
import space.kscience.visionforge.set
|
||||||
import kotlin.math.PI
|
import kotlin.math.PI
|
||||||
import kotlin.math.cos
|
import kotlin.math.cos
|
||||||
@ -17,8 +16,8 @@ public class Sphere(
|
|||||||
public val phiStart: Float = 0f,
|
public val phiStart: Float = 0f,
|
||||||
public val phi: Float = PI2,
|
public val phi: Float = PI2,
|
||||||
public val thetaStart: Float = 0f,
|
public val thetaStart: Float = 0f,
|
||||||
public val theta: Float = PI .toFloat(),
|
public val theta: Float = PI.toFloat(),
|
||||||
) : SolidBase(), GeometrySolid, VisionPropertyContainer<Sphere> {
|
) : SolidBase<Sphere>(), GeometrySolid {
|
||||||
|
|
||||||
override fun <T : Any> toGeometry(geometryBuilder: GeometryBuilder<T>) {
|
override fun <T : Any> toGeometry(geometryBuilder: GeometryBuilder<T>) {
|
||||||
fun point3dFromSphCoord(r: Float, theta: Float, phi: Float): Point3D {
|
fun point3dFromSphCoord(r: Float, theta: Float, phi: Float): Point3D {
|
||||||
@ -53,7 +52,7 @@ public class Sphere(
|
|||||||
}
|
}
|
||||||
|
|
||||||
@VisionBuilder
|
@VisionBuilder
|
||||||
public inline fun VisionContainerBuilder<Solid>.sphere(
|
public inline fun MutableVisionContainer<Solid>.sphere(
|
||||||
radius: Number,
|
radius: Number,
|
||||||
name: String? = null,
|
name: String? = null,
|
||||||
action: Sphere.() -> Unit = {},
|
action: Sphere.() -> Unit = {},
|
||||||
|
@ -2,8 +2,8 @@ package space.kscience.visionforge.solid
|
|||||||
|
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
import space.kscience.visionforge.MutableVisionContainer
|
||||||
import space.kscience.visionforge.VisionBuilder
|
import space.kscience.visionforge.VisionBuilder
|
||||||
import space.kscience.visionforge.VisionContainerBuilder
|
|
||||||
import space.kscience.visionforge.set
|
import space.kscience.visionforge.set
|
||||||
import kotlin.math.PI
|
import kotlin.math.PI
|
||||||
import kotlin.math.cos
|
import kotlin.math.cos
|
||||||
@ -21,7 +21,7 @@ public class SphereLayer(
|
|||||||
public val phi: Float = PI2,
|
public val phi: Float = PI2,
|
||||||
public val thetaStart: Float = 0f,
|
public val thetaStart: Float = 0f,
|
||||||
public val theta: Float = PI.toFloat(),
|
public val theta: Float = PI.toFloat(),
|
||||||
) : SolidBase(), GeometrySolid {
|
) : SolidBase<SphereLayer>(), GeometrySolid {
|
||||||
|
|
||||||
override fun <T : Any> toGeometry(geometryBuilder: GeometryBuilder<T>): Unit = geometryBuilder.run {
|
override fun <T : Any> toGeometry(geometryBuilder: GeometryBuilder<T>): Unit = geometryBuilder.run {
|
||||||
require(outerRadius > 0) { "Outer radius must be positive" }
|
require(outerRadius > 0) { "Outer radius must be positive" }
|
||||||
@ -69,7 +69,7 @@ public class SphereLayer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
@VisionBuilder
|
@VisionBuilder
|
||||||
public inline fun VisionContainerBuilder<Solid>.sphereLayer(
|
public inline fun MutableVisionContainer<Solid>.sphereLayer(
|
||||||
outerRadius: Number,
|
outerRadius: Number,
|
||||||
innerRadius: Number,
|
innerRadius: Number,
|
||||||
phiStart: Number = 0f,
|
phiStart: Number = 0f,
|
||||||
|
@ -3,7 +3,7 @@ package space.kscience.visionforge.solid.transform
|
|||||||
import space.kscience.dataforge.misc.DFExperimental
|
import space.kscience.dataforge.misc.DFExperimental
|
||||||
import space.kscience.dataforge.names.Name
|
import space.kscience.dataforge.names.Name
|
||||||
import space.kscience.dataforge.names.asName
|
import space.kscience.dataforge.names.asName
|
||||||
import space.kscience.visionforge.getProperty
|
import space.kscience.visionforge.root
|
||||||
import space.kscience.visionforge.solid.*
|
import space.kscience.visionforge.solid.*
|
||||||
|
|
||||||
private operator fun Number.plus(other: Number) = toFloat() + other.toFloat()
|
private operator fun Number.plus(other: Number) = toFloat() + other.toFloat()
|
||||||
@ -20,7 +20,7 @@ internal fun Solid.updateFrom(other: Solid): Solid {
|
|||||||
scaleX *= other.scaleX
|
scaleX *= other.scaleX
|
||||||
scaleY *= other.scaleY
|
scaleY *= other.scaleY
|
||||||
scaleZ *= other.scaleZ
|
scaleZ *= other.scaleZ
|
||||||
setProperty(Name.EMPTY, other.getProperty(Name.EMPTY))
|
properties[Name.EMPTY] = other.properties.root()
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
package space.kscience.visionforge.solid
|
package space.kscience.visionforge.solid
|
||||||
|
|
||||||
import space.kscience.dataforge.meta.get
|
|
||||||
import space.kscience.dataforge.meta.string
|
|
||||||
import space.kscience.dataforge.names.asName
|
import space.kscience.dataforge.names.asName
|
||||||
import space.kscience.dataforge.values.int
|
import space.kscience.dataforge.values.int
|
||||||
|
import space.kscience.dataforge.values.string
|
||||||
import space.kscience.visionforge.*
|
import space.kscience.visionforge.*
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
@ -17,7 +16,7 @@ class PropertyTest {
|
|||||||
//meta["color"] = "pink"
|
//meta["color"] = "pink"
|
||||||
color.set("pink")
|
color.set("pink")
|
||||||
}
|
}
|
||||||
assertEquals("pink", box.meta["material.color"]?.string)
|
assertEquals("pink", box.properties.getValue("material.color")?.string)
|
||||||
assertEquals("pink", box.color.string)
|
assertEquals("pink", box.color.string)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,12 +42,12 @@ class PropertyTest {
|
|||||||
fun testInheritedProperty() {
|
fun testInheritedProperty() {
|
||||||
var box: Box? = null
|
var box: Box? = null
|
||||||
val group = SolidGroup().apply {
|
val group = SolidGroup().apply {
|
||||||
setPropertyValue("test", 22)
|
properties["test"] = 22
|
||||||
group {
|
group {
|
||||||
box = box(100, 100, 100)
|
box = box(100, 100, 100)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assertEquals(22, box?.getPropertyValue("test", inherit = true)?.int)
|
assertEquals(22, box?.properties?.getValue("test", inherit = true)?.int)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -66,7 +65,7 @@ class PropertyTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assertEquals(22, box?.getPropertyValue("test")?.int)
|
assertEquals(22, box?.properties?.getValue("test")?.int)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -31,7 +31,7 @@ class SerializationTest {
|
|||||||
val string = Solids.encodeToString(cube)
|
val string = Solids.encodeToString(cube)
|
||||||
println(string)
|
println(string)
|
||||||
val newCube = Solids.decodeFromString(string)
|
val newCube = Solids.decodeFromString(string)
|
||||||
assertEquals(cube.meta, newCube.meta)
|
assertEquals(cube.properties.raw, newCube.properties.raw)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -52,7 +52,7 @@ class SerializationTest {
|
|||||||
val string = Solids.encodeToString(group)
|
val string = Solids.encodeToString(group)
|
||||||
println(string)
|
println(string)
|
||||||
val reconstructed = Solids.decodeFromString(string) as SolidGroup
|
val reconstructed = Solids.decodeFromString(string) as SolidGroup
|
||||||
assertEquals(group.children["cube"]?.meta, reconstructed.children["cube"]?.meta)
|
assertEquals(group.children["cube"]?.properties?.raw, reconstructed.children["cube"]?.properties?.raw)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -12,7 +12,7 @@ import space.kscience.dataforge.values.Null
|
|||||||
import space.kscience.dataforge.values.Value
|
import space.kscience.dataforge.values.Value
|
||||||
import space.kscience.dataforge.values.asValue
|
import space.kscience.dataforge.values.asValue
|
||||||
import space.kscience.tables.*
|
import space.kscience.tables.*
|
||||||
import space.kscience.visionforge.VisionGroup
|
import space.kscience.visionforge.AbstractVision
|
||||||
import space.kscience.visionforge.html.VisionOutput
|
import space.kscience.visionforge.html.VisionOutput
|
||||||
import space.kscience.visionforge.properties
|
import space.kscience.visionforge.properties
|
||||||
import kotlin.jvm.JvmName
|
import kotlin.jvm.JvmName
|
||||||
@ -42,10 +42,14 @@ public val ColumnHeader<Value>.properties: ValueColumnScheme get() = ValueColumn
|
|||||||
@SerialName("vision.table")
|
@SerialName("vision.table")
|
||||||
public class VisionOfTable(
|
public class VisionOfTable(
|
||||||
override val headers: List<@Serializable(ColumnHeaderSerializer::class) ColumnHeader<Value>>,
|
override val headers: List<@Serializable(ColumnHeaderSerializer::class) ColumnHeader<Value>>,
|
||||||
) : VisionGroup(), Rows<Value> {
|
) : AbstractVision(), Rows<Value> {
|
||||||
|
|
||||||
public var data: List<Meta>
|
public var data: List<Meta>
|
||||||
get() = meta.getIndexed("rows").entries.sortedBy { it.key?.toInt() }.map { it.value }
|
get() = meta?.getIndexed("rows")?.entries?.sortedBy {
|
||||||
|
it.key?.toInt()
|
||||||
|
}?.map {
|
||||||
|
it.value
|
||||||
|
} ?: emptyList()
|
||||||
set(value) {
|
set(value) {
|
||||||
//TODO Make it better
|
//TODO Make it better
|
||||||
properties()["rows"] = value
|
properties()["rows"] = value
|
||||||
|
@ -10,7 +10,6 @@ import space.kscience.dataforge.names.asName
|
|||||||
import space.kscience.dataforge.names.plus
|
import space.kscience.dataforge.names.plus
|
||||||
import space.kscience.dataforge.names.startsWith
|
import space.kscience.dataforge.names.startsWith
|
||||||
import space.kscience.visionforge.VisionBuilder
|
import space.kscience.visionforge.VisionBuilder
|
||||||
import space.kscience.visionforge.getProperty
|
|
||||||
import space.kscience.visionforge.onPropertyChange
|
import space.kscience.visionforge.onPropertyChange
|
||||||
import space.kscience.visionforge.setPropertyValue
|
import space.kscience.visionforge.setPropertyValue
|
||||||
import space.kscience.visionforge.solid.Solid
|
import space.kscience.visionforge.solid.Solid
|
||||||
|
@ -11,7 +11,6 @@ import org.w3c.dom.CanvasRenderingContext2D
|
|||||||
import org.w3c.dom.CanvasTextBaseline
|
import org.w3c.dom.CanvasTextBaseline
|
||||||
import org.w3c.dom.HTMLCanvasElement
|
import org.w3c.dom.HTMLCanvasElement
|
||||||
import org.w3c.dom.MIDDLE
|
import org.w3c.dom.MIDDLE
|
||||||
import space.kscience.visionforge.getProperty
|
|
||||||
import space.kscience.visionforge.solid.SolidLabel
|
import space.kscience.visionforge.solid.SolidLabel
|
||||||
import space.kscience.visionforge.solid.SolidMaterial
|
import space.kscience.visionforge.solid.SolidMaterial
|
||||||
import space.kscience.visionforge.solid.three.ThreeCanvas.Companion.DO_NOT_HIGHLIGHT_TAG
|
import space.kscience.visionforge.solid.three.ThreeCanvas.Companion.DO_NOT_HIGHLIGHT_TAG
|
||||||
@ -27,7 +26,7 @@ public object ThreeCanvasLabelFactory : ThreeFactory<SolidLabel> {
|
|||||||
val canvas = document.createElement("canvas") as HTMLCanvasElement
|
val canvas = document.createElement("canvas") as HTMLCanvasElement
|
||||||
val context = canvas.getContext("2d") as CanvasRenderingContext2D
|
val context = canvas.getContext("2d") as CanvasRenderingContext2D
|
||||||
context.font = "Bold ${obj.fontSize}pt ${obj.fontFamily}"
|
context.font = "Bold ${obj.fontSize}pt ${obj.fontFamily}"
|
||||||
context.fillStyle = obj.getProperty(SolidMaterial.MATERIAL_COLOR_KEY)?.value ?: "black"
|
context.fillStyle = obj.get(SolidMaterial.MATERIAL_COLOR_KEY)?.value ?: "black"
|
||||||
context.textBaseline = CanvasTextBaseline.MIDDLE
|
context.textBaseline = CanvasTextBaseline.MIDDLE
|
||||||
val metrics = context.measureText(obj.text)
|
val metrics = context.measureText(obj.text)
|
||||||
//canvas.width = metrics.width.toInt()
|
//canvas.width = metrics.width.toInt()
|
||||||
|
@ -4,7 +4,6 @@ import info.laht.threekt.core.BufferGeometry
|
|||||||
import info.laht.threekt.core.Object3D
|
import info.laht.threekt.core.Object3D
|
||||||
import info.laht.threekt.math.Color
|
import info.laht.threekt.math.Color
|
||||||
import info.laht.threekt.objects.LineSegments
|
import info.laht.threekt.objects.LineSegments
|
||||||
import space.kscience.visionforge.getProperty
|
|
||||||
import space.kscience.visionforge.onPropertyChange
|
import space.kscience.visionforge.onPropertyChange
|
||||||
import space.kscience.visionforge.solid.PolyLine
|
import space.kscience.visionforge.solid.PolyLine
|
||||||
import space.kscience.visionforge.solid.SolidMaterial
|
import space.kscience.visionforge.solid.SolidMaterial
|
||||||
@ -25,7 +24,7 @@ public object ThreeLineFactory : ThreeFactory<PolyLine> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val material = ThreeMaterials.getLineMaterial(
|
val material = ThreeMaterials.getLineMaterial(
|
||||||
obj.getProperty(SolidMaterial.MATERIAL_KEY),
|
obj.get(SolidMaterial.MATERIAL_KEY),
|
||||||
false
|
false
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user