Cleanup groups
This commit is contained in:
parent
e19ec02ff3
commit
ca985a6a66
@ -11,8 +11,7 @@ import kotlinx.serialization.Transient
|
|||||||
/**
|
/**
|
||||||
* Abstract implementation of mutable group of [VisualObject]
|
* Abstract implementation of mutable group of [VisualObject]
|
||||||
*/
|
*/
|
||||||
abstract class AbstractVisualGroup : AbstractVisualObject(),
|
abstract class AbstractVisualGroup : AbstractVisualObject(), MutableVisualGroup {
|
||||||
MutableVisualGroup {
|
|
||||||
|
|
||||||
//protected abstract val _children: MutableMap<NameToken, T>
|
//protected abstract val _children: MutableMap<NameToken, T>
|
||||||
|
|
||||||
@ -21,6 +20,17 @@ abstract class AbstractVisualGroup : AbstractVisualObject(),
|
|||||||
*/
|
*/
|
||||||
abstract override val children: Map<NameToken, VisualObject>
|
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<*>?) {
|
override fun propertyChanged(name: Name, before: MetaItem<*>?, after: MetaItem<*>?) {
|
||||||
super.propertyChanged(name, before, after)
|
super.propertyChanged(name, before, after)
|
||||||
forEach {
|
forEach {
|
||||||
|
@ -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()
|
||||||
|
}
|
@ -9,6 +9,7 @@ import hep.dataforge.names.asName
|
|||||||
import hep.dataforge.names.toName
|
import hep.dataforge.names.toName
|
||||||
import hep.dataforge.provider.Type
|
import hep.dataforge.provider.Type
|
||||||
import hep.dataforge.vis.VisualObject.Companion.TYPE
|
import hep.dataforge.vis.VisualObject.Companion.TYPE
|
||||||
|
import kotlinx.serialization.PolymorphicSerializer
|
||||||
import kotlinx.serialization.Transient
|
import kotlinx.serialization.Transient
|
||||||
|
|
||||||
//private fun Laminate.withTop(meta: Meta): Laminate = Laminate(listOf(meta) + layers)
|
//private fun Laminate.withTop(meta: Meta): Laminate = Laminate(listOf(meta) + layers)
|
||||||
@ -64,6 +65,10 @@ interface VisualObject : Configurable {
|
|||||||
const val TYPE = "visual"
|
const val TYPE = "visual"
|
||||||
val STYLE_KEY = "@style".asName()
|
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 META_KEY = "@meta"
|
||||||
//const val TAGS_KEY = "@tags"
|
//const val TAGS_KEY = "@tags"
|
||||||
|
|
||||||
|
@ -154,11 +154,10 @@ val VisualObject.prototype: VisualObject
|
|||||||
/**
|
/**
|
||||||
* Create ref for existing prototype
|
* Create ref for existing prototype
|
||||||
*/
|
*/
|
||||||
inline fun VisualGroup3D.ref(
|
fun VisualGroup3D.ref(
|
||||||
templateName: Name,
|
templateName: Name,
|
||||||
name: String = "",
|
name: String = ""
|
||||||
block: Proxy.() -> Unit = {}
|
): Proxy = Proxy(this, templateName).also { set(name, it) }
|
||||||
) = Proxy(this, templateName).apply(block).also { set(name, it) }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add new proxy wrapping given object and automatically adding it to the prototypes
|
* Add new proxy wrapping given object and automatically adding it to the prototypes
|
||||||
@ -166,8 +165,7 @@ inline fun VisualGroup3D.ref(
|
|||||||
fun VisualGroup3D.proxy(
|
fun VisualGroup3D.proxy(
|
||||||
name: String,
|
name: String,
|
||||||
obj: VisualObject3D,
|
obj: VisualObject3D,
|
||||||
templateName: Name = name.toName(),
|
templateName: Name = name.toName()
|
||||||
block: Proxy.() -> Unit = {}
|
|
||||||
): Proxy {
|
): Proxy {
|
||||||
val existing = getPrototype(templateName)
|
val existing = getPrototype(templateName)
|
||||||
if (existing == null) {
|
if (existing == null) {
|
||||||
@ -177,5 +175,14 @@ fun VisualGroup3D.proxy(
|
|||||||
} else if (existing != obj) {
|
} else if (existing != obj) {
|
||||||
error("Can't add different prototype on top of existing one")
|
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)
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import hep.dataforge.context.PluginTag
|
|||||||
import hep.dataforge.meta.*
|
import hep.dataforge.meta.*
|
||||||
import hep.dataforge.names.Name
|
import hep.dataforge.names.Name
|
||||||
import hep.dataforge.names.toName
|
import hep.dataforge.names.toName
|
||||||
|
import hep.dataforge.vis.SimpleVisualGroup
|
||||||
import hep.dataforge.vis.Visual
|
import hep.dataforge.vis.Visual
|
||||||
import hep.dataforge.vis.VisualObject
|
import hep.dataforge.vis.VisualObject
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
@ -38,23 +39,26 @@ class Visual3D(meta: Meta) : AbstractPlugin(meta) {
|
|||||||
contextual(Point2DSerializer)
|
contextual(Point2DSerializer)
|
||||||
|
|
||||||
polymorphic(VisualObject::class, VisualObject3D::class) {
|
polymorphic(VisualObject::class, VisualObject3D::class) {
|
||||||
VisualGroup3D::class with VisualGroup3D.serializer()
|
subclass(SimpleVisualGroup.serializer())
|
||||||
Proxy::class with Proxy.serializer()
|
subclass(VisualGroup3D.serializer())
|
||||||
Composite::class with Composite.serializer()
|
subclass(Proxy.serializer())
|
||||||
Tube::class with Tube.serializer()
|
subclass(Composite.serializer())
|
||||||
Box::class with Box.serializer()
|
subclass(Tube.serializer())
|
||||||
Convex::class with Convex.serializer()
|
subclass(Box.serializer())
|
||||||
Extruded::class with Extruded.serializer()
|
subclass(Convex.serializer())
|
||||||
|
subclass(Extruded.serializer())
|
||||||
subclass(PolyLine.serializer())
|
subclass(PolyLine.serializer())
|
||||||
subclass(Label3D.serializer())
|
subclass(Label3D.serializer())
|
||||||
|
subclass(Sphere.serializer())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val json = Json(
|
internal val json = Json(
|
||||||
JsonConfiguration(
|
JsonConfiguration(
|
||||||
prettyPrint = true,
|
prettyPrint = true,
|
||||||
useArrayPolymorphism = false,
|
useArrayPolymorphism = false,
|
||||||
encodeDefaults = false
|
encodeDefaults = false,
|
||||||
|
ignoreUnknownKeys = true
|
||||||
),
|
),
|
||||||
context = serialModule
|
context = serialModule
|
||||||
)
|
)
|
||||||
|
@ -27,7 +27,6 @@ interface PrototypeHolder {
|
|||||||
class VisualGroup3D : AbstractVisualGroup(), VisualObject3D, PrototypeHolder {
|
class VisualGroup3D : AbstractVisualGroup(), VisualObject3D, PrototypeHolder {
|
||||||
|
|
||||||
override var styleSheet: StyleSheet? = null
|
override var styleSheet: StyleSheet? = null
|
||||||
private set
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A container for templates visible inside this group
|
* A container for templates visible inside this group
|
||||||
@ -63,14 +62,6 @@ class VisualGroup3D : AbstractVisualGroup(), VisualObject3D, PrototypeHolder {
|
|||||||
super.attachChildren()
|
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) {
|
override fun removeChild(token: NameToken) {
|
||||||
_children.remove(token)?.apply { parent = null }
|
_children.remove(token)?.apply { parent = null }
|
||||||
}
|
}
|
||||||
@ -86,20 +77,6 @@ class VisualGroup3D : AbstractVisualGroup(), VisualObject3D, PrototypeHolder {
|
|||||||
|
|
||||||
override fun createGroup(): VisualGroup3D = VisualGroup3D()
|
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 {
|
companion object {
|
||||||
// val PROTOTYPES_KEY = NameToken("@prototypes")
|
// 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
|
* 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()
|
override var children: MutableMap<NameToken, VisualObject> = LinkedHashMap()
|
||||||
) : AbstractVisualGroup(), MutableVisualGroup, PrototypeHolder {
|
) : 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) {
|
override fun removeChild(token: NameToken) {
|
||||||
children.remove(token)
|
children.remove(token)
|
||||||
@ -140,9 +119,13 @@ internal class Prototypes(
|
|||||||
children[token] = child
|
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
|
override val prototypes: MutableVisualGroup get() = this
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ package hep.dataforge.vis.spatial
|
|||||||
import hep.dataforge.meta.double
|
import hep.dataforge.meta.double
|
||||||
import hep.dataforge.names.NameToken
|
import hep.dataforge.names.NameToken
|
||||||
import hep.dataforge.vis.MutableVisualGroup
|
import hep.dataforge.vis.MutableVisualGroup
|
||||||
|
import hep.dataforge.vis.VisualGroup
|
||||||
import hep.dataforge.vis.VisualObject
|
import hep.dataforge.vis.VisualObject
|
||||||
import kotlinx.serialization.*
|
import kotlinx.serialization.*
|
||||||
import kotlinx.serialization.builtins.MapSerializer
|
import kotlinx.serialization.builtins.MapSerializer
|
||||||
@ -98,11 +99,13 @@ object Point2DSerializer : KSerializer<Point2D> {
|
|||||||
|
|
||||||
@Serializer(MutableVisualGroup::class)
|
@Serializer(MutableVisualGroup::class)
|
||||||
internal object PrototypesSerializer : KSerializer<MutableVisualGroup> {
|
internal object PrototypesSerializer : KSerializer<MutableVisualGroup> {
|
||||||
|
|
||||||
private val mapSerializer: KSerializer<Map<NameToken, VisualObject>> =
|
private val mapSerializer: KSerializer<Map<NameToken, VisualObject>> =
|
||||||
MapSerializer(
|
MapSerializer(
|
||||||
NameToken.serializer(),
|
NameToken.serializer(),
|
||||||
PolymorphicSerializer(VisualObject::class)
|
VisualObject.serializer()
|
||||||
)
|
)
|
||||||
|
|
||||||
override val descriptor: SerialDescriptor get() = mapSerializer.descriptor
|
override val descriptor: SerialDescriptor get() = mapSerializer.descriptor
|
||||||
|
|
||||||
override fun deserialize(decoder: Decoder): MutableVisualGroup {
|
override fun deserialize(decoder: Decoder): MutableVisualGroup {
|
||||||
@ -113,6 +116,12 @@ internal object PrototypesSerializer : KSerializer<MutableVisualGroup> {
|
|||||||
override fun serialize(encoder: Encoder, value: MutableVisualGroup) {
|
override fun serialize(encoder: Encoder, value: MutableVisualGroup) {
|
||||||
mapSerializer.serialize(encoder, value.children)
|
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()
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,7 +1,8 @@
|
|||||||
package hep.dataforge.vis.spatial
|
package hep.dataforge.vis.spatial
|
||||||
|
|
||||||
|
import hep.dataforge.names.toName
|
||||||
|
import hep.dataforge.vis.VisualObject
|
||||||
import hep.dataforge.vis.get
|
import hep.dataforge.vis.get
|
||||||
import hep.dataforge.vis.spatial.Visual3D.Companion.json
|
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
@ -13,9 +14,9 @@ class SerializationTest {
|
|||||||
x = 100
|
x = 100
|
||||||
z = -100
|
z = -100
|
||||||
}
|
}
|
||||||
val string = json.stringify(Box.serializer(), cube)
|
val string = cube.stringify()
|
||||||
println(string)
|
println(string)
|
||||||
val newCube = json.parse(Box.serializer(), string)
|
val newCube = VisualObject.parseJson(string)
|
||||||
assertEquals(cube.config, newCube.config)
|
assertEquals(cube.config, newCube.config)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,9 +27,13 @@ class SerializationTest {
|
|||||||
x = 100
|
x = 100
|
||||||
z = -100
|
z = -100
|
||||||
}
|
}
|
||||||
|
|
||||||
val group = VisualGroup3D().apply {
|
val group = VisualGroup3D().apply {
|
||||||
proxy("cube", cube)
|
proxy("cube", cube)
|
||||||
|
proxyGroup("pg", "pg.content".toName()){
|
||||||
|
sphere(50){
|
||||||
|
x = -100
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
val string = group.stringify()
|
val string = group.stringify()
|
||||||
println(string)
|
println(string)
|
||||||
|
Loading…
Reference in New Issue
Block a user