Node editor for MutableMeta

This commit is contained in:
Alexander Nozik 2020-04-21 19:32:29 +03:00
parent aa52c45c5a
commit 5e8e3014f7
5 changed files with 43 additions and 20 deletions

View File

@ -6,7 +6,7 @@ plugins {
id("scientifik.publish") version toolsVersion apply false
}
val dataforgeVersion by extra("0.1.8-dev-1")
val dataforgeVersion by extra("0.1.8-dev-2")
val bintrayRepo by extra("dataforge")
val githubProject by extra("dataforge-core")

View File

@ -64,4 +64,5 @@ fun Configurable.setProperty(key: String, meta: Meta?) = setProperty(key, meta?.
fun <T : Configurable> T.configure(meta: Meta): T = this.apply { config.update(meta) }
@DFBuilder
inline fun <T : Configurable> T.configure(action: Config.() -> Unit): T = apply { config.apply(action) }

View File

@ -173,8 +173,8 @@ interface MetaNode<out M : MetaNode<M>> : Meta {
operator fun <M : MetaNode<M>> M?.get(name: Name): MetaItem<M>? = if( this == null) {
null
} else {
@Suppress("UNCHECKED_CAST")
(this as Meta).get(name) as MetaItem<M>?
@Suppress("UNCHECKED_CAST", "ReplaceGetOrSet")
(this as Meta).get(name) as MetaItem<M>? // Do not change
}
operator fun <M : MetaNode<M>> M?.get(key: String): MetaItem<M>? = this[key.toName()]

View File

@ -76,11 +76,9 @@ inline fun MutableMeta<*>.remove(name: Name) = set(name, null)
@Suppress("NOTHING_TO_INLINE")
inline fun MutableMeta<*>.remove(name: String) = remove(name.toName())
fun MutableMeta<*>.setValue(name: Name, value: Value) =
set(name, MetaItem.ValueItem(value))
fun MutableMeta<*>.setValue(name: Name, value: Value) = set(name, MetaItem.ValueItem(value))
fun MutableMeta<*>.setValue(name: String, value: Value) =
set(name.toName(), MetaItem.ValueItem(value))
fun MutableMeta<*>.setValue(name: String, value: Value) = set(name.toName(), value)
fun MutableMeta<*>.setItem(name: Name, item: MetaItem<*>?) {
when (item) {
@ -98,7 +96,7 @@ fun MutableMeta<*>.setNode(name: Name, node: Meta) =
fun MutableMeta<*>.setNode(name: String, node: Meta) = setNode(name.toName(), node)
/**
* Universal set method
* Universal unsafe set method
*/
operator fun MutableMeta<*>.set(name: Name, value: Any?) {
when (value) {
@ -174,3 +172,16 @@ fun <M : MutableMeta<M>> M.append(name: Name, value: Any?) {
}
fun <M : MutableMeta<M>> M.append(name: String, value: Any?) = append(name.toName(), value)
/**
* Apply existing node with given [builder] or create a new element with it.
*/
@DFExperimental
fun <M : AbstractMutableMeta<M>> M.edit(name: Name, builder: M.() -> Unit) {
val item = when(val existingItem = get(name)){
null -> empty().also { set(name, it) }
is MetaItem.NodeItem<M> -> existingItem.node
else -> error("Can't edit value meta item")
}
item.apply(builder)
}

View File

@ -24,19 +24,20 @@ sealed class ItemDescriptor(val config: Config) {
*/
var info: String? by config.string()
/**
* Additional attributes of an item. For example validation and widget parameters
*
* @return
*/
var attributes by config.node()
/**
* True if the item is required
*
* @return
*/
abstract var required: Boolean
/**
* Additional attributes of an item. For example validation and widget parameters
*
* @return
*/
var attributes by config.node()
}
/**
@ -166,12 +167,12 @@ class NodeDescriptor(config: Config = Config()) : ItemDescriptor(config) {
value(name.toName(), block)
}
companion object{
companion object {
val ITEM_KEY = "item".asName()
val IS_NODE_KEY = "@isNode".asName()
inline operator fun invoke(block: NodeDescriptor.()->Unit) = NodeDescriptor().apply(block)
inline operator fun invoke(block: NodeDescriptor.() -> Unit) = NodeDescriptor().apply(block)
//TODO infer descriptor from spec
}
@ -251,7 +252,7 @@ class ValueDescriptor(config: Config = Config()) : ItemDescriptor(config) {
* @return
*/
var allowedValues: List<Value> by config.value().transform {
when{
when {
it?.list != null -> it.list
type.size == 1 && type[0] === ValueType.BOOLEAN -> listOf(True, False)
else -> emptyList()
@ -265,3 +266,13 @@ class ValueDescriptor(config: Config = Config()) : ItemDescriptor(config) {
this.allowedValues = v.map { Value.of(it) }
}
}
/**
* Merge two node descriptors into one using first one as primary
*/
operator fun NodeDescriptor.plus(other: NodeDescriptor): NodeDescriptor {
return NodeDescriptor().apply {
config.update(other.config)
config.update(this@plus.config)
}
}