Cleanup groups

This commit is contained in:
Alexander Nozik 2020-04-12 10:44:35 +03:00
parent e19ec02ff3
commit ca985a6a66
8 changed files with 105 additions and 51 deletions

View File

@ -11,8 +11,7 @@ import kotlinx.serialization.Transient
/**
* Abstract implementation of mutable group of [VisualObject]
*/
abstract class AbstractVisualGroup : AbstractVisualObject(),
MutableVisualGroup {
abstract class AbstractVisualGroup : AbstractVisualObject(), MutableVisualGroup {
//protected abstract val _children: MutableMap<NameToken, T>
@ -21,6 +20,17 @@ abstract class AbstractVisualGroup : AbstractVisualObject(),
*/
abstract override val children: Map<NameToken, VisualObject>
abstract override var styleSheet: StyleSheet?
protected set
/**
* Update or create stylesheet
*/
fun styleSheet(block: StyleSheet.() -> Unit) {
val res = styleSheet ?: StyleSheet(this).also { styleSheet = it }
res.block()
}
override fun propertyChanged(name: Name, before: MetaItem<*>?, after: MetaItem<*>?) {
super.propertyChanged(name, before, after)
forEach {

View File

@ -0,0 +1,31 @@
package hep.dataforge.vis
import hep.dataforge.meta.Config
import hep.dataforge.names.NameToken
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
@SerialName("group")
class SimpleVisualGroup : AbstractVisualGroup() {
override var styleSheet: StyleSheet? = null
//FIXME to be lifted to AbstractVisualGroup after https://github.com/Kotlin/kotlinx.serialization/issues/378 is fixed
override var properties: Config? = null
@SerialName("children")
private val _children = HashMap<NameToken, VisualObject>()
override val children: Map<NameToken, VisualObject> get() = _children
override fun removeChild(token: NameToken) {
_children.remove(token)?.apply { parent = null }
}
override fun setChild(token: NameToken, child: VisualObject) {
_children[token] = child
}
override fun createGroup(): SimpleVisualGroup = SimpleVisualGroup()
}

View File

@ -9,6 +9,7 @@ import hep.dataforge.names.asName
import hep.dataforge.names.toName
import hep.dataforge.provider.Type
import hep.dataforge.vis.VisualObject.Companion.TYPE
import kotlinx.serialization.PolymorphicSerializer
import kotlinx.serialization.Transient
//private fun Laminate.withTop(meta: Meta): Laminate = Laminate(listOf(meta) + layers)
@ -64,6 +65,10 @@ interface VisualObject : Configurable {
const val TYPE = "visual"
val STYLE_KEY = "@style".asName()
private val VISUAL_OBJECT_SERIALIZER = PolymorphicSerializer(VisualObject::class)
fun serializer() = VISUAL_OBJECT_SERIALIZER
//const val META_KEY = "@meta"
//const val TAGS_KEY = "@tags"

View File

@ -154,11 +154,10 @@ val VisualObject.prototype: VisualObject
/**
* Create ref for existing prototype
*/
inline fun VisualGroup3D.ref(
fun VisualGroup3D.ref(
templateName: Name,
name: String = "",
block: Proxy.() -> Unit = {}
) = Proxy(this, templateName).apply(block).also { set(name, it) }
name: String = ""
): Proxy = Proxy(this, templateName).also { set(name, it) }
/**
* Add new proxy wrapping given object and automatically adding it to the prototypes
@ -166,8 +165,7 @@ inline fun VisualGroup3D.ref(
fun VisualGroup3D.proxy(
name: String,
obj: VisualObject3D,
templateName: Name = name.toName(),
block: Proxy.() -> Unit = {}
templateName: Name = name.toName()
): Proxy {
val existing = getPrototype(templateName)
if (existing == null) {
@ -177,5 +175,14 @@ fun VisualGroup3D.proxy(
} else if (existing != obj) {
error("Can't add different prototype on top of existing one")
}
return ref(templateName, name, block)
return ref(templateName, name)
}
fun VisualGroup3D.proxyGroup(
name: String,
templateName: Name = name.toName(),
block: MutableVisualGroup.() -> Unit
): Proxy {
val group = VisualGroup3D().apply(block)
return proxy(name, group, templateName)
}

View File

@ -7,6 +7,7 @@ import hep.dataforge.context.PluginTag
import hep.dataforge.meta.*
import hep.dataforge.names.Name
import hep.dataforge.names.toName
import hep.dataforge.vis.SimpleVisualGroup
import hep.dataforge.vis.Visual
import hep.dataforge.vis.VisualObject
import kotlinx.serialization.json.Json
@ -38,23 +39,26 @@ class Visual3D(meta: Meta) : AbstractPlugin(meta) {
contextual(Point2DSerializer)
polymorphic(VisualObject::class, VisualObject3D::class) {
VisualGroup3D::class with VisualGroup3D.serializer()
Proxy::class with Proxy.serializer()
Composite::class with Composite.serializer()
Tube::class with Tube.serializer()
Box::class with Box.serializer()
Convex::class with Convex.serializer()
Extruded::class with Extruded.serializer()
subclass(SimpleVisualGroup.serializer())
subclass(VisualGroup3D.serializer())
subclass(Proxy.serializer())
subclass(Composite.serializer())
subclass(Tube.serializer())
subclass(Box.serializer())
subclass(Convex.serializer())
subclass(Extruded.serializer())
subclass(PolyLine.serializer())
subclass(Label3D.serializer())
subclass(Sphere.serializer())
}
}
val json = Json(
internal val json = Json(
JsonConfiguration(
prettyPrint = true,
useArrayPolymorphism = false,
encodeDefaults = false
encodeDefaults = false,
ignoreUnknownKeys = true
),
context = serialModule
)

View File

@ -27,7 +27,6 @@ interface PrototypeHolder {
class VisualGroup3D : AbstractVisualGroup(), VisualObject3D, PrototypeHolder {
override var styleSheet: StyleSheet? = null
private set
/**
* A container for templates visible inside this group
@ -63,14 +62,6 @@ class VisualGroup3D : AbstractVisualGroup(), VisualObject3D, PrototypeHolder {
super.attachChildren()
}
/**
* Update or create stylesheet
*/
fun styleSheet(block: StyleSheet.() -> Unit) {
val res = styleSheet ?: StyleSheet(this).also { styleSheet = it }
res.block()
}
override fun removeChild(token: NameToken) {
_children.remove(token)?.apply { parent = null }
}
@ -86,20 +77,6 @@ class VisualGroup3D : AbstractVisualGroup(), VisualObject3D, PrototypeHolder {
override fun createGroup(): VisualGroup3D = VisualGroup3D()
// return when {
// name.isEmpty() -> error("Should be unreachable")
// name.length == 1 -> {
// val token = name.first()!!
// when (val current = children[token]) {
// null -> VisualGroup3D().also { setChild(token, it) }
// is VisualGroup3D -> current
// else -> error("Can't create group with name $name because it exists and not a group")
// }
// }
// else -> createGroup(name.first()!!.asName()).createGroup(name.cutFirst())
// }
// }
companion object {
// val PROTOTYPES_KEY = NameToken("@prototypes")
@ -109,8 +86,6 @@ class VisualGroup3D : AbstractVisualGroup(), VisualObject3D, PrototypeHolder {
}
}
fun VisualGroup3D.stringify(): String = Visual3D.json.stringify(VisualGroup3D.serializer(),this)
/**
* Ger a prototype redirecting the request to the parent if prototype is not found
*/
@ -129,7 +104,11 @@ internal class Prototypes(
override var children: MutableMap<NameToken, VisualObject> = LinkedHashMap()
) : AbstractVisualGroup(), MutableVisualGroup, PrototypeHolder {
override val styleSheet: StyleSheet? get() = null
override var styleSheet: StyleSheet?
get() = null
set(value) {
error("Can't define stylesheet for prototypes block")
}
override fun removeChild(token: NameToken) {
children.remove(token)
@ -140,9 +119,13 @@ internal class Prototypes(
children[token] = child
}
override fun createGroup(): Prototypes = Prototypes()
override fun createGroup() = SimpleVisualGroup()
override var properties: Config? = null
override var properties: Config?
get() = null
set(value) {
error("Can't define properties for prototypes block")
}
override val prototypes: MutableVisualGroup get() = this

View File

@ -3,6 +3,7 @@ package hep.dataforge.vis.spatial
import hep.dataforge.meta.double
import hep.dataforge.names.NameToken
import hep.dataforge.vis.MutableVisualGroup
import hep.dataforge.vis.VisualGroup
import hep.dataforge.vis.VisualObject
import kotlinx.serialization.*
import kotlinx.serialization.builtins.MapSerializer
@ -98,11 +99,13 @@ object Point2DSerializer : KSerializer<Point2D> {
@Serializer(MutableVisualGroup::class)
internal object PrototypesSerializer : KSerializer<MutableVisualGroup> {
private val mapSerializer: KSerializer<Map<NameToken, VisualObject>> =
MapSerializer(
NameToken.serializer(),
PolymorphicSerializer(VisualObject::class)
VisualObject.serializer()
)
override val descriptor: SerialDescriptor get() = mapSerializer.descriptor
override fun deserialize(decoder: Decoder): MutableVisualGroup {
@ -113,6 +116,12 @@ internal object PrototypesSerializer : KSerializer<MutableVisualGroup> {
override fun serialize(encoder: Encoder, value: MutableVisualGroup) {
mapSerializer.serialize(encoder, value.children)
}
}
fun VisualObject.stringify(): String = Visual3D.json.stringify(VisualObject.serializer(), this)
fun VisualObject.Companion.parseJson(str: String) = Visual3D.json.parse(VisualObject.serializer(), str).also {
if(it is VisualGroup){
it.attachChildren()
}
}

View File

@ -1,7 +1,8 @@
package hep.dataforge.vis.spatial
import hep.dataforge.names.toName
import hep.dataforge.vis.VisualObject
import hep.dataforge.vis.get
import hep.dataforge.vis.spatial.Visual3D.Companion.json
import kotlin.test.Test
import kotlin.test.assertEquals
@ -13,9 +14,9 @@ class SerializationTest {
x = 100
z = -100
}
val string = json.stringify(Box.serializer(), cube)
val string = cube.stringify()
println(string)
val newCube = json.parse(Box.serializer(), string)
val newCube = VisualObject.parseJson(string)
assertEquals(cube.config, newCube.config)
}
@ -26,9 +27,13 @@ class SerializationTest {
x = 100
z = -100
}
val group = VisualGroup3D().apply {
proxy("cube", cube)
proxyGroup("pg", "pg.content".toName()){
sphere(50){
x = -100
}
}
}
val string = group.stringify()
println(string)