New Proxy child styling and json editor

This commit is contained in:
Alexander Nozik 2019-10-01 22:22:13 +03:00
parent 2fcfd767c1
commit d1e2d8d60b
20 changed files with 1145 additions and 164 deletions

View File

@ -1,18 +1,16 @@
package hep.dataforge.vis.common package hep.dataforge.vis.common
import hep.dataforge.meta.Meta
import hep.dataforge.meta.MetaBuilder import hep.dataforge.meta.MetaBuilder
import hep.dataforge.meta.MetaItem import hep.dataforge.meta.MetaItem
import hep.dataforge.names.Name import hep.dataforge.names.*
import hep.dataforge.names.NameToken
import hep.dataforge.names.asName
import hep.dataforge.names.isEmpty
import kotlinx.serialization.Transient import kotlinx.serialization.Transient
/** /**
* Abstract implementation of group of [VisualObject] * Abstract implementation of group of [VisualObject]
*/ */
abstract class AbstractVisualGroup : AbstractVisualObject(), VisualGroup { abstract class AbstractVisualGroup : AbstractVisualObject(), MutableVisualGroup {
//protected abstract val _children: MutableMap<NameToken, T> //protected abstract val _children: MutableMap<NameToken, T>
@ -21,6 +19,32 @@ abstract class AbstractVisualGroup : AbstractVisualObject(), VisualGroup {
*/ */
abstract override val children: Map<NameToken, VisualObject> //get() = _children abstract override val children: Map<NameToken, VisualObject> //get() = _children
//TODO replace by custom object with get/set functionality
protected abstract val styles: MutableMap<Name, Meta>
override fun getStyle(name: Name): Meta? = styles[name]
override fun setStyle(name: Name, meta: Meta) {
fun VisualObject.applyStyle(name: Name, meta: Meta) {
if (style.contains(name.toString())) {
//full update
//TODO do a fine grained update
if (this is AbstractVisualObject) {
styleChanged()
} else {
propertyChanged(EmptyName)
}
}
if (this is VisualGroup) {
this.children.forEach { (_, child) ->
child.applyStyle(name, meta)
}
}
}
styles[name] = meta
applyStyle(name, meta)
}
// init { // init {
// //Do after deserialization // //Do after deserialization
@ -75,12 +99,13 @@ abstract class AbstractVisualGroup : AbstractVisualObject(), VisualGroup {
/** /**
* Add a static child. Statics could not be found by name, removed or replaced * Add a static child. Statics could not be found by name, removed or replaced
*/ */
protected abstract fun addStatic(child: VisualObject) protected open fun addStatic(child: VisualObject) =
setChild(NameToken("@static(${child.hashCode()})"), child)
/** /**
* Recursively create a child group * Recursively create a child group
*/ */
protected abstract fun createGroup(name: Name): VisualGroup protected abstract fun createGroup(name: Name): MutableVisualGroup
/** /**
* Add named or unnamed child to the group. If key is [null] the child is considered unnamed. Both key and value are not * Add named or unnamed child to the group. If key is [null] the child is considered unnamed. Both key and value are not
@ -103,7 +128,7 @@ abstract class AbstractVisualGroup : AbstractVisualObject(), VisualGroup {
} }
else -> { else -> {
//TODO add safety check //TODO add safety check
val parent = (get(name.cutLast()) as? VisualGroup) ?: createGroup(name.cutLast()) val parent = (get(name.cutLast()) as? MutableVisualGroup) ?: createGroup(name.cutLast())
parent[name.last()!!.asName()] = child parent[name.last()!!.asName()] = child
} }
} }

View File

@ -17,12 +17,13 @@ abstract class AbstractVisualObject : VisualObject {
@Transient @Transient
override var parent: VisualObject? = null override var parent: VisualObject? = null
protected abstract var properties: Config? abstract override var properties: Config?
override var style: List<String> override var style: List<String>
get() = properties?.let { it[STYLE_KEY].stringList } ?: emptyList() get() = properties?.let { it[STYLE_KEY].stringList } ?: emptyList()
set(value) { set(value) {
setProperty(VisualObject.STYLE_KEY, value) setProperty(STYLE_KEY, value)
styleChanged()
} }
/** /**
@ -57,12 +58,11 @@ abstract class AbstractVisualObject : VisualObject {
private var styleCache: Laminate? = null private var styleCache: Laminate? = null
private fun styles(): Laminate { protected val actualStyles: Laminate
return styleCache ?: kotlin.run { get() = styleCache ?: run {
Laminate(style.map { it.toName() }.mapNotNull(::findStyle)) Laminate(style.map { it.toName() }.mapNotNull(::findStyle))
.also { styleCache = it } .also { styleCache = it }
} }
}
/** /**
* Helper to reset style cache * Helper to reset style cache
@ -74,9 +74,9 @@ abstract class AbstractVisualObject : VisualObject {
override fun getProperty(name: Name, inherit: Boolean): MetaItem<*>? { override fun getProperty(name: Name, inherit: Boolean): MetaItem<*>? {
return if (inherit) { return if (inherit) {
properties?.get(name) ?: parent?.getProperty(name, inherit) ?: styles()[name] properties?.get(name) ?: parent?.getProperty(name, inherit) ?: actualStyles[name]
} else { } else {
properties?.get(name) ?: styles()[name] properties?.get(name) ?: actualStyles[name]
} }
} }

View File

@ -4,7 +4,7 @@ import hep.dataforge.meta.Meta
import hep.dataforge.names.* import hep.dataforge.names.*
import hep.dataforge.provider.Provider import hep.dataforge.provider.Provider
interface VisualGroup : VisualObject, Provider, Iterable<VisualObject> { interface VisualGroup : Provider, Iterable<VisualObject>, VisualObject {
/** /**
* A map of top level named children * A map of top level named children
*/ */
@ -26,6 +26,7 @@ interface VisualGroup : VisualObject, Provider, Iterable<VisualObject> {
else -> emptyMap() else -> emptyMap()
} }
/** /**
* Iterate over children of this group * Iterate over children of this group
*/ */
@ -42,6 +43,17 @@ interface VisualGroup : VisualObject, Provider, Iterable<VisualObject> {
*/ */
fun setStyle(name: Name, meta: Meta) fun setStyle(name: Name, meta: Meta)
operator fun get(name: Name): VisualObject? {
return when {
name.isEmpty() -> this
name.length == 1 -> children[name.first()!!]
else -> (children[name.first()!!] as? VisualGroup)?.get(name.cutFirst())
}
}
}
interface MutableVisualGroup : VisualGroup {
/** /**
* Add listener for children structure change. * Add listener for children structure change.
* @param owner the handler to properly remove listeners * @param owner the handler to properly remove listeners
@ -54,14 +66,6 @@ interface VisualGroup : VisualObject, Provider, Iterable<VisualObject> {
*/ */
fun removeChildrenChangeListener(owner: Any?) fun removeChildrenChangeListener(owner: Any?)
operator fun get(name: Name): VisualObject? {
return when {
name.isEmpty() -> this
name.length == 1 -> children[name.first()!!]
else -> (children[name.first()!!] as? VisualGroup)?.get(name.cutFirst())
}
}
operator fun set(name: Name, child: VisualObject?) operator fun set(name: Name, child: VisualObject?)
} }

View File

@ -1,5 +1,6 @@
package hep.dataforge.vis.common package hep.dataforge.vis.common
import hep.dataforge.meta.Config
import hep.dataforge.meta.Configurable import hep.dataforge.meta.Configurable
import hep.dataforge.meta.MetaItem import hep.dataforge.meta.MetaItem
import hep.dataforge.meta.MetaRepr import hep.dataforge.meta.MetaRepr
@ -25,6 +26,11 @@ interface VisualObject : MetaRepr, Configurable {
@Transient @Transient
var parent: VisualObject? var parent: VisualObject?
/**
* Direct properties access
*/
val properties: Config?
/** /**
* Set property for this object * Set property for this object
*/ */
@ -63,3 +69,7 @@ interface VisualObject : MetaRepr, Configurable {
fun VisualObject.getProperty(key: String, inherit: Boolean = true): MetaItem<*>? = getProperty(key.toName(), inherit) fun VisualObject.getProperty(key: String, inherit: Boolean = true): MetaItem<*>? = getProperty(key.toName(), inherit)
fun VisualObject.setProperty(key: String, value: Any?) = setProperty(key.toName(), value) fun VisualObject.setProperty(key: String, value: Any?) = setProperty(key.toName(), value)
fun VisualObject.applyStyle(name: String) {
style = style + name
}

View File

@ -1,13 +1,18 @@
package hep.dataforge.vis.spatial.gdml package hep.dataforge.vis.spatial.gdml
import hep.dataforge.meta.Meta import hep.dataforge.meta.Meta
import hep.dataforge.meta.MetaBuilder
import hep.dataforge.meta.buildMeta import hep.dataforge.meta.buildMeta
import hep.dataforge.names.Name
import hep.dataforge.names.toName import hep.dataforge.names.toName
import hep.dataforge.vis.common.Colors import hep.dataforge.vis.common.Colors
import hep.dataforge.vis.common.VisualObject
import hep.dataforge.vis.common.applyStyle
import hep.dataforge.vis.spatial.VisualGroup3D import hep.dataforge.vis.spatial.VisualGroup3D
import hep.dataforge.vis.spatial.VisualObject3D import hep.dataforge.vis.spatial.VisualObject3D
import hep.dataforge.vis.spatial.material import hep.dataforge.vis.spatial.VisualObject3D.Companion.COLOR_KEY
import scientifik.gdml.* import scientifik.gdml.*
import kotlin.collections.set
import kotlin.random.Random import kotlin.random.Random
class GDMLTransformer(val root: GDML) { class GDMLTransformer(val root: GDML) {
@ -24,25 +29,33 @@ class GDMLTransformer(val root: GDML) {
* A special group for local templates * A special group for local templates
*/ */
val templates by lazy { VisualGroup3D() } val templates by lazy { VisualGroup3D() }
private val styles = HashMap<Name, Meta>()
var lUnit: LUnit = LUnit.MM var lUnit: LUnit = LUnit.MM
var solidAction: (GDMLSolid) -> Action = { Action.CACHE } var solidAction: (GDMLSolid) -> Action = { Action.CACHE }
var volumeAction: (GDMLGroup) -> Action = { Action.ACCEPT } var volumeAction: (GDMLGroup) -> Action = { Action.CACHE }
var solidConfiguration: VisualObject3D.(parent: GDMLVolume, solid: GDMLSolid) -> Unit = { _, _ -> } var solidConfiguration: VisualObject3D.(parent: GDMLVolume, solid: GDMLSolid) -> Unit = { _, _ -> }
fun VisualObject.useStyle(name: String, builder: MetaBuilder.() -> Unit) {
styles.getOrPut(name.toName()){
buildMeta(builder)
}
applyStyle(name)
}
internal fun configureSolid(obj: VisualObject3D, parent: GDMLVolume, solid: GDMLSolid) { internal fun configureSolid(obj: VisualObject3D, parent: GDMLVolume, solid: GDMLSolid) {
val material = parent.materialref.resolve(root) ?: GDMLElement(parent.materialref.ref) val material = parent.materialref.resolve(root) ?: GDMLElement(parent.materialref.ref)
val materialColor = materialCache.getOrPut(material) { val styleName = "material[${material.name}]"
buildMeta {
"color" to Colors.rgbToString(random.nextInt(0, Int.MAX_VALUE)) obj.useStyle(styleName){
COLOR_KEY to Colors.rgbToString(random.nextInt(0, Int.MAX_VALUE))
"gdml.material" to material.name
} }
}
obj.setProperty("gdml.material".toName(), material.name)
obj.material = materialColor
obj.solidConfiguration(parent, solid) obj.solidConfiguration(parent, solid)
} }
@ -72,6 +85,9 @@ class GDMLTransformer(val root: GDML) {
// res = it(res) // res = it(res)
// } // }
final.templates = templates final.templates = templates
styles.forEach {
final.setStyle(it.key, it.value)
}
onFinish(this@GDMLTransformer) onFinish(this@GDMLTransformer)
return final return final
} }

View File

@ -2,7 +2,7 @@ package hep.dataforge.vis.spatial.gdml
import hep.dataforge.meta.update import hep.dataforge.meta.update
import hep.dataforge.names.asName import hep.dataforge.names.asName
import hep.dataforge.vis.common.VisualGroup import hep.dataforge.vis.common.MutableVisualGroup
import hep.dataforge.vis.spatial.Point3D import hep.dataforge.vis.spatial.Point3D
import hep.dataforge.vis.spatial.VisualGroup3D import hep.dataforge.vis.spatial.VisualGroup3D
import hep.dataforge.vis.spatial.VisualObject3D import hep.dataforge.vis.spatial.VisualObject3D
@ -16,7 +16,7 @@ typealias GDMLOptimization = GDMLTransformer.(VisualGroup3D) -> VisualGroup3D
* Collapse nodes with single child * Collapse nodes with single child
*/ */
val optimizeSingleChild: GDMLOptimization = { tree -> val optimizeSingleChild: GDMLOptimization = { tree ->
fun VisualGroup.replaceChildren() { fun MutableVisualGroup.replaceChildren() {
children.forEach { (key, child) -> children.forEach { (key, child) ->
if (child is VisualGroup3D && child.children.size == 1) { if (child is VisualGroup3D && child.children.size == 1) {
val newChild = child.children.values.first().apply { val newChild = child.children.values.first().apply {
@ -40,13 +40,13 @@ val optimizeSingleChild: GDMLOptimization = { tree ->
} }
} }
if (newChild is VisualGroup) { if (newChild is MutableVisualGroup) {
newChild.replaceChildren() newChild.replaceChildren()
} }
//actual replacement //actual replacement
set(key.asName(), newChild) set(key.asName(), newChild)
} else if (child is VisualGroup) { } else if (child is MutableVisualGroup) {
child.replaceChildren() child.replaceChildren()
} }
} }

View File

@ -57,11 +57,11 @@ private class GDMLDemoApp : ApplicationBase() {
onload = { onload = {
val string = result as String val string = result as String
try { // try {
block(file.name, string) block(file.name, string)
} catch (ex: Exception) { // } catch (ex: Exception) {
console.error(ex) // console.error(ex)
} // }
} }
readAsText(file) readAsText(file)
@ -190,7 +190,7 @@ private class GDMLDemoApp : ApplicationBase() {
if (visual is VisualGroup) { if (visual is VisualGroup) {
visual.toTree(editor::propertyEditor).render(tree as HTMLElement) { visual.toTree(editor::propertyEditor).render(tree as HTMLElement) {
showCheckboxes = true showCheckboxes = false
} }
} }

View File

@ -0,0 +1,748 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="240"
height="144"
id="svg4136"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="jsoneditor-icons.svg">
<title
id="title6512">JSON Editor Icons</title>
<metadata
id="metadata4148">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>JSON Editor Icons</dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs4146" />
<sodipodi:namedview
pagecolor="#ff63ff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1026"
id="namedview4144"
showgrid="true"
inkscape:zoom="4"
inkscape:cx="13.229181"
inkscape:cy="119.82429"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg4136"
showguides="false"
borderlayer="false"
inkscape:showpageshadow="true"
showborder="true">
<inkscape:grid
type="xygrid"
id="grid4640"
empspacing="24" />
</sodipodi:namedview>
<!-- Created with SVG-edit - http://svg-edit.googlecode.com/ -->
<rect
style="fill:#4c4c4c;fill-opacity:1;stroke:none;stroke-width:0"
id="svg_1"
height="16"
width="16"
y="4"
x="4" />
<rect
id="svg_1-7"
height="16"
width="16"
y="3.999995"
x="28.000006"
style="fill:#ec3f29;fill-opacity:0.94117647;stroke:none;stroke-width:0" />
<rect
style="fill:#4c4c4c;fill-opacity:1;stroke:none;stroke-width:0"
x="52.000004"
y="3.999995"
width="16"
height="16"
id="rect4165" />
<rect
id="rect4175"
height="16"
width="16"
y="3.9999852"
x="172.00002"
style="fill:#4c4c4c;fill-opacity:1;stroke:none;stroke-width:0" />
<rect
id="rect4175-3"
height="16"
width="16"
y="3.999995"
x="196"
style="fill:#4c4c4c;fill-opacity:1;stroke:none;stroke-width:0" />
<g
id="g4299"
style="stroke:none">
<rect
x="7.0000048"
y="10.999998"
width="9.9999924"
height="1.9999986"
id="svg_1-1"
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0" />
<rect
x="11.000005"
y="7.0000114"
width="1.9999955"
height="9.9999838"
id="svg_1-1-1"
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0" />
</g>
<g
id="g4299-3"
transform="matrix(0.70710678,-0.70710678,0.70710678,0.70710678,19.029435,12.000001)"
style="stroke:none">
<rect
x="7.0000048"
y="10.999998"
width="9.9999924"
height="1.9999986"
id="svg_1-1-0"
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0" />
<rect
x="11.000005"
y="7.0000114"
width="1.9999955"
height="9.9999838"
id="svg_1-1-1-9"
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0" />
</g>
<rect
id="svg_1-7-5"
height="6.9999905"
width="6.9999909"
y="7.0000048"
x="55.000004"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0" />
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#4c4c4c;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
x="58"
y="10.00001"
width="6.9999909"
height="6.9999905"
id="rect4354" />
<rect
id="svg_1-7-5-7"
height="6.9999905"
width="6.9999909"
y="10.000005"
x="58.000004"
style="fill:#ffffff;fill-opacity:1;stroke:#3c80df;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.94117647" />
<g
id="g4378">
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0"
x="198"
y="10.999999"
width="7.9999909"
height="1.9999965"
id="svg_1-7-5-3" />
<rect
id="rect4374"
height="1.9999946"
width="11.999995"
y="7.0000005"
x="198"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0" />
<rect
id="rect4376"
height="1.9999995"
width="3.9999928"
y="14.999996"
x="198"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0" />
</g>
<g
transform="matrix(1,0,0,-1,-23.999995,23.999995)"
id="g4383">
<rect
id="rect4385"
height="1.9999965"
width="7.9999909"
y="10.999999"
x="198"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0" />
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0"
x="198"
y="7.0000005"
width="11.999995"
height="1.9999946"
id="rect4387" />
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0"
x="198"
y="14.999996"
width="3.9999928"
height="1.9999995"
id="rect4389" />
</g>
<rect
style="fill:#4c4c4c;fill-opacity:1;stroke:none"
id="rect3754-4"
width="16"
height="16"
x="76"
y="3.9999199" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:0.2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 85.10447,6.0157384 -0.0156,1.4063 c 3.02669,-0.2402 0.33008,3.6507996 2.48438,4.5780996 -2.18694,1.0938 0.49191,4.9069 -2.45313,4.5781 l -0.0156,1.4219 c 5.70828,0.559 1.03264,-5.1005 4.70313,-5.2656 l 0,-1.4063 c -3.61303,-0.027 1.11893,-5.7069996 -4.70313,-5.3124996 z"
id="path4351"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccc" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:0.2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 82.78125,5.9984384 0.0156,1.4063 c -3.02668,-0.2402 -0.33007,3.6506996 -2.48437,4.5780996 2.18694,1.0938 -0.49192,4.9069 2.45312,4.5781 l 0.0156,1.4219 c -5.70827,0.559 -1.03263,-5.1004 -4.70312,-5.2656 l 0,-1.4063 c 3.61303,-0.027 -1.11894,-5.7070996 4.70312,-5.3124996 z"
id="path4351-9"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccc" />
<rect
style="fill:#4c4c4c;fill-opacity:1;stroke:none"
id="rect3754-25"
width="16"
height="16"
x="100"
y="3.9999199" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:none"
d="m 103.719,5.6719384 0,12.7187996 3.03125,0 0,-1.5313 -1.34375,0 0,-9.6249996 1.375,0 0,-1.5625 z"
id="path2987"
inkscape:connector-curvature="0" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:none"
d="m 112.2185,5.6721984 0,12.7187996 -3.03125,0 0,-1.5313 1.34375,0 0,-9.6249996 -1.375,0 0,-1.5625 z"
id="path2987-1"
inkscape:connector-curvature="0" />
<rect
style="fill:#4c4c4c;fill-opacity:1;stroke:none"
id="rect3754-73"
width="16"
height="16"
x="124"
y="3.9999199" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:none"
d="m 126.2824,17.602938 1.78957,0 1.14143,-2.8641 5.65364,0 1.14856,2.8641 1.76565,0 -4.78687,-11.1610996 -1.91903,0 z"
id="path3780"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccccc" />
<path
style="fill:#4c4c4c;fill-opacity:1;stroke:none"
d="m 129.72704,13.478838 4.60852,0.01 -2.30426,-5.5497996 z"
id="path3782"
inkscape:connector-curvature="0" />
<rect
style="fill:#4c4c4c;fill-opacity:1;stroke:none"
id="rect3754-35"
width="16"
height="16"
x="148"
y="3.9999199" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:none"
d="m 156.47655,5.8917384 0,2.1797 0.46093,2.3983996 1.82813,0 0.39844,-2.3983996 0,-2.1797 z"
id="path5008-2"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccc" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:none"
d="m 152.51561,5.8906384 0,2.1797 0.46094,2.3983996 1.82812,0 0.39844,-2.3983996 0,-2.1797 z"
id="path5008-2-8"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccc" />
<rect
id="svg_1-7-2"
height="1.9999961"
width="11.999996"
y="64"
x="54"
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0" />
<rect
id="svg_1-7-2-2"
height="2.9999905"
width="2.9999907"
y="52"
x="80.000008"
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0" />
<rect
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
x="85.000008"
y="52"
width="2.9999907"
height="2.9999905"
id="rect4561" />
<rect
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
x="80.000008"
y="58"
width="2.9999907"
height="2.9999905"
id="rect4563" />
<rect
id="rect4565"
height="2.9999905"
width="2.9999907"
y="58"
x="85.000008"
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0" />
<rect
id="rect4567"
height="2.9999905"
width="2.9999907"
y="64"
x="80.000008"
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0" />
<rect
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
x="85.000008"
y="64"
width="2.9999907"
height="2.9999905"
id="rect4569" />
<circle
style="opacity:1;fill:none;fill-opacity:1;stroke:#4c4c4c;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
id="path4571"
cx="110.06081"
cy="57.939209"
r="4.7438836" />
<rect
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
x="116.64566"
y="-31.79752"
width="4.229713"
height="6.4053884"
id="rect4563-2"
transform="matrix(0.70710678,0.70710678,-0.70710678,0.70710678,0,0)" />
<path
style="fill:#4c4c4c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 125,56 138.77027,56.095 132,64 Z"
id="path4613"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<path
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0"
id="path4615"
d="M 149,64 162.77027,63.905 156,56 Z"
style="fill:#4c4c4c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<rect
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
x="54"
y="53"
width="11.999996"
height="1.9999961"
id="rect4638" />
<rect
id="svg_1-7-2-24"
height="1.9999957"
width="12.99999"
y="-56"
x="53"
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
transform="matrix(0,1,-1,0,0,0)" />
<rect
transform="matrix(0,1,-1,0,0,0)"
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
x="53"
y="-66"
width="12.99999"
height="1.9999957"
id="rect4657" />
<rect
id="rect4659"
height="0.99999291"
width="11.999999"
y="57"
x="54"
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0" />
<rect
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
x="54"
y="88.000122"
width="11.999996"
height="1.9999961"
id="rect4661" />
<rect
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
x="80.000008"
y="76.000122"
width="2.9999907"
height="2.9999905"
id="rect4663" />
<rect
id="rect4665"
height="2.9999905"
width="2.9999907"
y="76.000122"
x="85.000008"
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1" />
<rect
id="rect4667"
height="2.9999905"
width="2.9999907"
y="82.000122"
x="80.000008"
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1" />
<rect
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
x="85.000008"
y="82.000122"
width="2.9999907"
height="2.9999905"
id="rect4669" />
<rect
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
x="80.000008"
y="88.000122"
width="2.9999907"
height="2.9999905"
id="rect4671" />
<rect
id="rect4673"
height="2.9999905"
width="2.9999907"
y="88.000122"
x="85.000008"
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1" />
<circle
r="4.7438836"
cy="81.939331"
cx="110.06081"
id="circle4675"
style="opacity:1;fill:none;fill-opacity:1;stroke:#d3d3d3;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<rect
transform="matrix(0.70710678,0.70710678,-0.70710678,0.70710678,0,0)"
id="rect4677"
height="6.4053884"
width="4.229713"
y="-14.826816"
x="133.6163"
style="fill:#d3d3d3;fill-opacity:1;stroke:#d3d3d3;stroke-width:0;stroke-opacity:1" />
<path
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0"
id="path4679"
d="m 125,80.000005 13.77027,0.09499 L 132,87.999992 Z"
style="fill:#d3d3d3;fill-opacity:1;fill-rule:evenodd;stroke:#d3d3d3;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
style="fill:#d3d3d3;fill-opacity:1;fill-rule:evenodd;stroke:#d3d3d3;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 149,88.0002 162.77027,87.9052 156,80.0002 Z"
id="path4681"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<rect
id="rect4683"
height="1.9999961"
width="11.999996"
y="77.000122"
x="54"
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1" />
<rect
transform="matrix(0,1,-1,0,0,0)"
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
x="77.000122"
y="-56"
width="12.99999"
height="1.9999957"
id="rect4685" />
<rect
id="rect4687"
height="1.9999957"
width="12.99999"
y="-66"
x="77.000122"
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
transform="matrix(0,1,-1,0,0,0)" />
<rect
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
x="54"
y="81.000122"
width="11.999999"
height="0.99999291"
id="rect4689" />
<rect
id="rect4761-1"
height="1.9999945"
width="15.99999"
y="101"
x="76.000008"
style="fill:#ffffff;fill-opacity:0.8;stroke:none;stroke-width:0" />
<rect
id="rect4761-0"
height="1.9999945"
width="15.99999"
y="105"
x="76.000008"
style="fill:#ffffff;fill-opacity:0.8;stroke:none;stroke-width:0" />
<rect
id="rect4761-7"
height="1.9999945"
width="9"
y="109"
x="76.000008"
style="fill:#ffffff;fill-opacity:0.8;stroke:none;stroke-width:0" />
<rect
id="rect4761-1-1"
height="1.9999945"
width="12"
y="125"
x="76.000008"
style="fill:#ffffff;fill-opacity:0.8;stroke:none;stroke-width:0" />
<rect
id="rect4761-1-1-4"
height="1.9999945"
width="10"
y="137"
x="76.000008"
style="fill:#ffffff;fill-opacity:0.8;stroke:none;stroke-width:0" />
<rect
id="rect4761-1-1-4-4"
height="1.9999945"
width="10"
y="129"
x="82"
style="fill:#ffffff;fill-opacity:0.8;stroke:none;stroke-width:0" />
<rect
id="rect4761-1-1-4-4-3"
height="1.9999945"
width="9"
y="133"
x="82"
style="fill:#ffffff;fill-opacity:0.8;stroke:none;stroke-width:0" />
<path
inkscape:connector-curvature="0"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.8;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.66157866;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 36.398438,100.0254 c -0.423362,-0.013 -0.846847,0.01 -1.265626,0.062 -1.656562,0.2196 -3.244567,0.9739 -4.507812,2.2266 L 29,100.5991 l -2.324219,7.7129 7.826172,-1.9062 -1.804687,-1.9063 c 1.597702,-1.5308 4.048706,-1.8453 5.984375,-0.7207 1.971162,1.1452 2.881954,3.3975 2.308593,5.5508 -0.573361,2.1533 -2.533865,3.6953 -4.830078,3.6953 l 0,3.0742 c 3.550756,0 6.710442,-2.4113 7.650391,-5.9414 0.939949,-3.5301 -0.618463,-7.2736 -3.710938,-9.0703 -1.159678,-0.6738 -2.431087,-1.0231 -3.701171,-1.0625 z"
id="path4138" />
<path
inkscape:connector-curvature="0"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.8;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.66157866;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 59.722656,99.9629 c -1.270084,0.039 -2.541493,0.3887 -3.701172,1.0625 -3.092475,1.7967 -4.650886,5.5402 -3.710937,9.0703 0.939949,3.5301 4.09768,5.9414 7.648437,5.9414 l 0,-3.0742 c -2.296214,0 -4.256717,-1.542 -4.830078,-3.6953 -0.573361,-2.1533 0.337432,-4.4056 2.308594,-5.5508 1.935731,-1.1246 4.38863,-0.8102 5.986326,0.7207 l -1.806638,1.9063 7.828128,1.9062 -2.32422,-7.7129 -1.62696,1.7168 c -1.26338,-1.2531 -2.848917,-2.0088 -4.505855,-2.2285 -0.418778,-0.055 -0.842263,-0.076 -1.265625,-0.062 z"
id="path4138-1" />
<path
inkscape:connector-curvature="0"
style="opacity:0.8;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.96599996;stroke-miterlimit:4;stroke-dasharray:none"
d="m 10.5,100 0,2 -2.4999996,0 L 12,107 l 4,-5 -2.5,0 0,-2 -3,0 z"
id="path3055-0-77" />
<path
style="opacity:0.8;fill:none;stroke:#ffffff;stroke-width:1.96599996;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 4.9850574,108.015 14.0298856,-0.03"
id="path5244-5-0-5"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="opacity:0.8;fill:none;stroke:#ffffff;stroke-width:1.96599996;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 4.9849874,132.015 14.0298866,-0.03"
id="path5244-5-0-5-8"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
inkscape:connector-curvature="0"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.4;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.66157866;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 36.398438,123.9629 c -0.423362,-0.013 -0.846847,0.01 -1.265626,0.062 -1.656562,0.2196 -3.244567,0.9739 -4.507812,2.2266 L 29,124.5366 l -2.324219,7.7129 7.826172,-1.9062 -1.804687,-1.9063 c 1.597702,-1.5308 4.048706,-1.8453 5.984375,-0.7207 1.971162,1.1453 2.881954,3.3975 2.308593,5.5508 -0.573361,2.1533 -2.533864,3.6953 -4.830078,3.6953 l 0,3.0742 c 3.550757,0 6.710442,-2.4093 7.650391,-5.9394 0.939949,-3.5301 -0.618463,-7.2756 -3.710938,-9.0723 -1.159678,-0.6737 -2.431087,-1.0231 -3.701171,-1.0625 z"
id="path4138-12" />
<path
inkscape:connector-curvature="0"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.4;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.66157866;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 59.722656,123.9629 c -1.270084,0.039 -2.541493,0.3888 -3.701172,1.0625 -3.092475,1.7967 -4.650886,5.5422 -3.710937,9.0723 0.939949,3.5301 4.09768,5.9394 7.648437,5.9394 l 0,-3.0742 c -2.296214,0 -4.256717,-1.542 -4.830078,-3.6953 -0.573361,-2.1533 0.337432,-4.4055 2.308594,-5.5508 1.935731,-1.1246 4.38863,-0.8102 5.986326,0.7207 l -1.806638,1.9063 7.828128,1.9062 -2.32422,-7.7129 -1.62696,1.7168 c -1.26338,-1.2531 -2.848917,-2.0088 -4.505855,-2.2285 -0.418778,-0.055 -0.842263,-0.076 -1.265625,-0.062 z"
id="path4138-1-3" />
<path
id="path6191"
d="m 10.5,116 0,-2 -2.4999996,0 L 12,109 l 4,5 -2.5,0 0,2 -3,0 z"
style="opacity:0.8;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.96599996;stroke-miterlimit:4;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
style="opacity:0.8;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.96599996;stroke-miterlimit:4;stroke-dasharray:none"
d="m 10.5,129 0,-2 -2.4999996,0 L 12,122 l 4,5 -2.5,0 0,2 -3,0 z"
id="path6193" />
<path
id="path6195"
d="m 10.5,135 0,2 -2.4999996,0 L 12,142 l 4,-5 -2.5,0 0,-2 -3,0 z"
style="opacity:0.8;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.96599996;stroke-miterlimit:4;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
sodipodi:type="star"
style="fill:#4d4d4d;fill-opacity:0.90196078;stroke:#d3d3d3;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
id="path4500"
sodipodi:sides="3"
sodipodi:cx="11.55581"
sodipodi:cy="60.073242"
sodipodi:r1="5.1116104"
sodipodi:r2="2.5558052"
sodipodi:arg1="0"
sodipodi:arg2="1.0471976"
inkscape:flatsided="false"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 16.66742,60.073242 -3.833708,2.213392 -3.8337072,2.213393 0,-4.426785 0,-4.426784 3.8337082,2.213392 z"
inkscape:transform-center-x="-1.2779026" />
<path
inkscape:transform-center-x="1.277902"
d="m -31.500004,60.073242 -3.833708,2.213392 -3.833707,2.213393 0,-4.426785 0,-4.426784 3.833707,2.213392 z"
inkscape:randomized="0"
inkscape:rounded="0"
inkscape:flatsided="false"
sodipodi:arg2="1.0471976"
sodipodi:arg1="0"
sodipodi:r2="2.5558052"
sodipodi:r1="5.1116104"
sodipodi:cy="60.073242"
sodipodi:cx="-36.611614"
sodipodi:sides="3"
id="path4502"
style="fill:#4d4d4d;fill-opacity:0.90196078;stroke:#d3d3d3;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
sodipodi:type="star"
transform="scale(-1,1)" />
<path
d="m 16.66742,60.073212 -3.833708,2.213392 -3.8337072,2.213392 0,-4.426784 0,-4.426785 3.8337082,2.213392 z"
inkscape:randomized="0"
inkscape:rounded="0"
inkscape:flatsided="false"
sodipodi:arg2="1.0471976"
sodipodi:arg1="0"
sodipodi:r2="2.5558052"
sodipodi:r1="5.1116104"
sodipodi:cy="60.073212"
sodipodi:cx="11.55581"
sodipodi:sides="3"
id="path4504"
style="fill:#4d4d4d;fill-opacity:0.90196078;stroke:#d3d3d3;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
sodipodi:type="star"
transform="matrix(0,1,-1,0,72.0074,71.7877)"
inkscape:transform-center-y="1.2779029" />
<path
inkscape:transform-center-y="-1.2779026"
transform="matrix(0,-1,-1,0,96,96)"
sodipodi:type="star"
style="fill:#4d4d4d;fill-opacity:0.90196078;stroke:#d3d3d3;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
id="path4506"
sodipodi:sides="3"
sodipodi:cx="11.55581"
sodipodi:cy="60.073212"
sodipodi:r1="5.1116104"
sodipodi:r2="2.5558052"
sodipodi:arg1="0"
sodipodi:arg2="1.0471976"
inkscape:flatsided="false"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 16.66742,60.073212 -3.833708,2.213392 -3.8337072,2.213392 0,-4.426784 0,-4.426785 3.8337082,2.213392 z" />
<path
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0"
id="path4615-5"
d="m 171.82574,65.174193 16.34854,0 -8.17427,-13.348454 z"
style="fill:#fbb917;fill-opacity:1;fill-rule:evenodd;stroke:#fbb917;stroke-width:1.65161395;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 179,55 0,6 2,0 0,-6"
id="path4300"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<path
style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 179,62 0,2 2,0 0,-2"
id="path4300-6"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<path
style="fill:#ffffff;fill-opacity:0.8;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:0.8"
d="M 99.994369,113.0221 102,114.98353 l 7,-6.9558 3,0.97227 2,-1 1,-2 0,-3 -3,3 -3,-3 3,-3 -3,0 -2,1 -1,2 0.99437,3.0221 z"
id="path4268"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccccccccccc" />
<rect
id="rect4175-3-5"
height="16"
width="16"
y="4"
x="220"
style="fill:#4c4c4c;fill-opacity:1;stroke:none;stroke-width:0" />
<path
style="fill:#ffffff;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 234,6 0,2 -5,5 0,5 -2,0 0,-5 -5,-5 0,-2"
id="path3546"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccc" />
<g
transform="matrix(1.3333328,0,0,-1.5999992,-139.9999,127.19999)"
id="g4383-6">
<rect
id="rect4385-2"
height="1.2499905"
width="5.9999924"
y="12.625005"
x="198.00002"
style="fill:#ffffff;fill-opacity:0.8;stroke:#000000;stroke-width:0" />
<rect
style="fill:#ffffff;fill-opacity:0.8;stroke:#000000;stroke-width:0"
x="198.00002"
y="15.125007"
width="7.4999928"
height="1.2499949"
id="rect4387-9" />
<rect
style="fill:#ffffff;fill-opacity:0.8;stroke:#000000;stroke-width:0"
x="198.00002"
y="7.6250024"
width="2.9999909"
height="1.2499905"
id="rect4389-1-0" />
<rect
style="fill:#ffffff;fill-opacity:0.8;stroke:#000000;stroke-width:0"
x="198.00002"
y="10.125004"
width="4.4999919"
height="1.2499905"
id="rect4389-1-9" />
<path
style="fill:#ffffff;fill-opacity:0.8;fill-rule:evenodd;stroke:none;stroke-width:0.68465352px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 207.00001,16.375004 0,-5.625005 -2.25,0 3,-3.1250014 3,3.1250014 -2.25,0 0,5.625005 -1.5,0"
id="path4402"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccc" />
</g>
<path
style="fill:#ffffff;fill-opacity:0.8;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 164,100 0,3 -6,6 0,7 -4,0 0,-7 -6,-6 0,-3"
id="path3546-2-2"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccc" />
<rect
style="fill:#4c4c4c;fill-opacity:1;stroke:none;stroke-width:0"
id="svg_1-3"
height="16"
width="16"
y="28"
x="4" />
<path
sodipodi:nodetypes="ccccccccc"
inkscape:connector-curvature="0"
id="path4402-5-7"
d="m 15,41 0,-7 -4,0 0,3 -5,-4 5,-4 0,3 6,0 0,9"
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.68465352px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
</svg>

After

Width:  |  Height:  |  Size: 31 KiB

File diff suppressed because one or more lines are too long

View File

@ -11,6 +11,7 @@
integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"> integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<link rel="stylesheet" href="css/main.css"> <link rel="stylesheet" href="css/main.css">
<link rel="stylesheet" href="css/inspire-tree-light.min.css"> <link rel="stylesheet" href="css/inspire-tree-light.min.css">
<link rel="stylesheet" href="css/jsoneditor.min.css">
<script type="text/javascript" src="main.bundle.js"></script> <script type="text/javascript" src="main.bundle.js"></script>
</head> </head>
<body class="testApp"> <body class="testApp">

View File

@ -15,32 +15,19 @@ fun main() {
val xml = GDML.format.parse(GDML.serializer(), xmlReader) val xml = GDML.format.parse(GDML.serializer(), xmlReader)
val visual = xml.toVisual { val visual = xml.toVisual {
lUnit = LUnit.CM lUnit = LUnit.CM
volumeAction = { volume ->
when {
volume.name.startsWith("ecal01lay") -> GDMLTransformer.Action.REJECT
volume.name.startsWith("ecal") -> GDMLTransformer.Action.CACHE
volume.name.startsWith("UPBL") -> GDMLTransformer.Action.REJECT
volume.name.startsWith("USCL") -> GDMLTransformer.Action.REJECT
volume.name.startsWith("U") -> GDMLTransformer.Action.CACHE
volume.name.startsWith("VPBL") -> GDMLTransformer.Action.REJECT
volume.name.startsWith("VSCL") -> GDMLTransformer.Action.REJECT
volume.name.startsWith("V") -> GDMLTransformer.Action.CACHE
else -> GDMLTransformer.Action.ACCEPT
}
}
solidConfiguration = { parent, solid -> solidConfiguration = { parent, solid ->
if (parent.physVolumes.isNotEmpty()) { if (parent.physVolumes.isNotEmpty()
opacity = 0.3 || solid.name.startsWith("Coil")
}
if (solid.name.startsWith("Coil")
|| solid.name.startsWith("Yoke") || solid.name.startsWith("Yoke")
|| solid.name.startsWith("Magnet") || solid.name.startsWith("Magnet")
|| solid.name.startsWith("Pole") || solid.name.startsWith("Pole")
) { ) {
useStyle("opaque") {
opacity = 0.3 opacity = 0.3
} }
} }
}
// optimizeSingleChild = true // optimizeSingleChild = true
//optimizations = listOf(optimizeSingleChild) //optimizations = listOf(optimizeSingleChild)

View File

@ -33,6 +33,7 @@ kotlin {
implementation(npm("element-resize-event")) implementation(npm("element-resize-event"))
implementation(npm("inspire-tree","6.0.1")) implementation(npm("inspire-tree","6.0.1"))
implementation(npm("inspire-tree-dom","4.0.6")) implementation(npm("inspire-tree-dom","4.0.6"))
implementation(npm("jsoneditor"))
} }
} }
} }

View File

@ -4,18 +4,16 @@ package hep.dataforge.vis.spatial
import hep.dataforge.io.ConfigSerializer import hep.dataforge.io.ConfigSerializer
import hep.dataforge.io.NameSerializer import hep.dataforge.io.NameSerializer
import hep.dataforge.meta.Config import hep.dataforge.meta.*
import hep.dataforge.meta.Meta
import hep.dataforge.meta.MetaBuilder
import hep.dataforge.meta.MetaItem
import hep.dataforge.names.Name import hep.dataforge.names.Name
import hep.dataforge.names.NameToken import hep.dataforge.names.NameToken
import hep.dataforge.names.asName import hep.dataforge.names.asName
import hep.dataforge.names.plus
import hep.dataforge.vis.common.AbstractVisualObject import hep.dataforge.vis.common.AbstractVisualObject
import hep.dataforge.vis.common.MutableVisualGroup
import hep.dataforge.vis.common.VisualGroup import hep.dataforge.vis.common.VisualGroup
import hep.dataforge.vis.common.VisualObject import hep.dataforge.vis.common.VisualObject
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient
import kotlinx.serialization.UseSerializers import kotlinx.serialization.UseSerializers
/** /**
@ -34,21 +32,22 @@ class Proxy(val templateName: Name) : AbstractVisualObject(), VisualGroup, Visua
/** /**
* Recursively search for defined template in the parent * Recursively search for defined template in the parent
*/ */
val template: VisualObject3D val prototype: VisualObject3D
get() = (parent as? VisualGroup3D)?.getTemplate(templateName) get() = (parent as? VisualGroup3D)?.getTemplate(templateName)
?: error("Template with name $templateName not found in $parent") ?: error("Template with name $templateName not found in $parent")
override fun getStyle(name: Name): Meta? = null override fun getStyle(name: Name): Meta? = (parent as VisualGroup?)?.getStyle(name)
override fun setStyle(name: Name, meta: Meta) { override fun setStyle(name: Name, meta: Meta) {
(parent as VisualGroup?)?.setStyle(name, meta)
//do nothing //do nothing
} }
override fun getProperty(name: Name, inherit: Boolean): MetaItem<*>? { override fun getProperty(name: Name, inherit: Boolean): MetaItem<*>? {
return if (inherit) { return if (inherit) {
super.getProperty(name, false) ?: template.getProperty(name, false) ?: parent?.getProperty(name, inherit) super.getProperty(name, false) ?: prototype.getProperty(name, false) ?: parent?.getProperty(name, inherit)
} else { } else {
super.getProperty(name, false) ?: template.getProperty(name, false) super.getProperty(name, false) ?: prototype.getProperty(name, false)
} }
} }
@ -58,48 +57,55 @@ class Proxy(val templateName: Name) : AbstractVisualObject(), VisualGroup, Visua
} }
override val children: Map<NameToken, ProxyChild> override val children: Map<NameToken, ProxyChild>
get() = (template as? VisualGroup)?.children?.mapValues { get() = (prototype as? MutableVisualGroup)?.children?.mapValues {
ProxyChild(it.key.asName()) ProxyChild(it.key.asName())
} ?: emptyMap() } ?: emptyMap()
private data class ProxyChangeListeners(val owner: Any?, val callback: (Name, VisualObject?) -> Unit)
@Transient
private val listeners = HashSet<ProxyChangeListeners>()
override fun onChildrenChange(owner: Any?, action: (Name, VisualObject?) -> Unit) {
listeners.add(ProxyChangeListeners(owner, action))
}
override fun removeChildrenChangeListener(owner: Any?) {
listeners.removeAll { it.owner == owner }
}
override fun set(name: Name, child: VisualObject?) {
error("Content change not supported for proxy")
}
private val propertyCache: HashMap<Name, Config> = HashMap() private val propertyCache: HashMap<Name, Config> = HashMap()
private fun Config.attachListener(obj: VisualObject) { inner class ProxyChild(val name: Name) : AbstractVisualObject(), VisualGroup {
onChange(this@Proxy) { name, before, after ->
listeners.forEach { listener -> override val children: Map<NameToken, VisualObject>
listener.callback(name, obj) get() = ((prototype as? MutableVisualGroup)?.get(name) as? MutableVisualGroup)
} ?.children
?.mapValues { (key, _) ->
ProxyChild(
name + key.asName()
)
} }
?: emptyMap()
override fun getStyle(name: Name): Meta? = this@Proxy.getStyle(name)
override fun setStyle(name: Name, meta: Meta) {
this@Proxy.setStyle(name, meta)
} }
inner class ProxyChild(val name: Name) : AbstractVisualObject() { val prototype: VisualObject
get() = (this@Proxy.prototype as? VisualGroup)?.get(name)
?: error("Prototype with name $name not found in ${this@Proxy}")
override var properties: Config? override var properties: Config?
get() = propertyCache[name] get() = propertyCache[name]
set(value) { set(value) {
if (value == null) { if (value == null) {
propertyCache.remove(name)?.removeListener(this@Proxy) propertyCache.remove(name)
} else { } else {
propertyCache[name] = value.apply { propertyCache[name] = value
attachListener(this@ProxyChild)
} }
} }
override fun getProperty(name: Name, inherit: Boolean): MetaItem<*>? {
return if (inherit) {
properties?.get(name)
?: parent?.getProperty(name, inherit)
?: actualStyles[name]
?: prototype.getProperty(name, inherit)
} else {
properties?.get(name)
?: actualStyles[name]
?: prototype.getProperty(name, inherit)
}
} }
} }
} }

View File

@ -37,7 +37,7 @@ class Visual3DPlugin(meta: Meta) : AbstractPlugin(meta) {
contextual(Point2DSerializer) contextual(Point2DSerializer)
contextual(NameSerializer) contextual(NameSerializer)
contextual(NameTokenSerializer) contextual(NameTokenSerializer)
contextual(MetaSerializer) contextual(Meta::class, MetaSerializer)
contextual(ConfigSerializer) contextual(ConfigSerializer)
polymorphic(VisualObject::class, VisualObject3D::class) { polymorphic(VisualObject::class, VisualObject3D::class) {

View File

@ -2,27 +2,29 @@
Point3DSerializer::class, Point3DSerializer::class,
ConfigSerializer::class, ConfigSerializer::class,
NameTokenSerializer::class, NameTokenSerializer::class,
NameSerializer::class NameSerializer::class,
MetaSerializer::class
) )
package hep.dataforge.vis.spatial package hep.dataforge.vis.spatial
import hep.dataforge.io.ConfigSerializer import hep.dataforge.io.ConfigSerializer
import hep.dataforge.io.MetaSerializer
import hep.dataforge.io.NameSerializer import hep.dataforge.io.NameSerializer
import hep.dataforge.meta.Config import hep.dataforge.meta.Config
import hep.dataforge.meta.Meta import hep.dataforge.meta.Meta
import hep.dataforge.meta.MetaBuilder import hep.dataforge.meta.MetaBuilder
import hep.dataforge.meta.set import hep.dataforge.meta.set
import hep.dataforge.names.* import hep.dataforge.names.Name
import hep.dataforge.names.NameToken
import hep.dataforge.names.asName
import hep.dataforge.names.isEmpty
import hep.dataforge.vis.common.AbstractVisualGroup import hep.dataforge.vis.common.AbstractVisualGroup
import hep.dataforge.vis.common.AbstractVisualObject import hep.dataforge.vis.common.MutableVisualGroup
import hep.dataforge.vis.common.VisualGroup
import hep.dataforge.vis.common.VisualObject import hep.dataforge.vis.common.VisualObject
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.UseSerializers import kotlinx.serialization.UseSerializers
import kotlin.collections.component1
import kotlin.collections.component2
import kotlin.collections.set import kotlin.collections.set
@Serializable @Serializable
@ -37,32 +39,8 @@ class VisualGroup3D : AbstractVisualGroup(), VisualObject3D {
} }
//FIXME to be lifted to AbstractVisualGroup after https://github.com/Kotlin/kotlinx.serialization/issues/378 is fixed //FIXME to be lifted to AbstractVisualGroup after https://github.com/Kotlin/kotlinx.serialization/issues/378 is fixed
public override var properties: Config? = null override var properties: Config? = null
override val styles = HashMap<Name, Meta>()
private val styles = HashMap<Name, Meta>()
override fun getStyle(name: Name): Meta? = styles[name]
override fun setStyle(name: Name, meta: Meta) {
fun VisualObject.applyStyle(name: Name, meta: Meta) {
if (style.contains(name.toString())) {
//full update
//TODO do a fine grained update
if(this is AbstractVisualObject){
styleChanged()
} else {
propertyChanged(EmptyName)
}
}
if (this is VisualGroup) {
this.children.forEach { (_, child) ->
child.applyStyle(name, meta)
}
}
}
styles[name] = meta
applyStyle(name, meta)
}
override var position: Point3D? = null override var position: Point3D? = null
override var rotation: Point3D? = null override var rotation: Point3D? = null
@ -87,10 +65,10 @@ class VisualGroup3D : AbstractVisualGroup(), VisualObject3D {
childrenChanged(token.asName(), child) childrenChanged(token.asName(), child)
} }
/** // /**
* TODO add special static group to hold statics without propagation // * TODO add special static group to hold statics without propagation
*/ // */
override fun addStatic(child: VisualObject) = setChild(NameToken("@static(${child.hashCode()})"), child) // override fun addStatic(child: VisualObject) = setChild(NameToken("@static(${child.hashCode()})"), child)
override fun createGroup(name: Name): VisualGroup3D { override fun createGroup(name: Name): VisualGroup3D {
return when { return when {
@ -125,10 +103,10 @@ class VisualGroup3D : AbstractVisualGroup(), VisualObject3D {
/** /**
* A fix for serialization bug that writes all proper parents inside the tree after deserialization * A fix for serialization bug that writes all proper parents inside the tree after deserialization
*/ */
fun VisualGroup.attachChildren() { fun MutableVisualGroup.attachChildren() {
this.children.values.forEach { this.children.values.forEach {
it.parent = this it.parent = this
(it as? VisualGroup)?.attachChildren() (it as? MutableVisualGroup)?.attachChildren()
} }
if (this is VisualGroup3D) { if (this is VisualGroup3D) {
templates?.apply { templates?.apply {

View File

@ -9,9 +9,11 @@ import hep.dataforge.names.plus
import hep.dataforge.output.Output import hep.dataforge.output.Output
import hep.dataforge.vis.common.Colors.rgbToString import hep.dataforge.vis.common.Colors.rgbToString
import hep.dataforge.vis.common.VisualObject import hep.dataforge.vis.common.VisualObject
import hep.dataforge.vis.spatial.VisualObject3D.Companion.COLOR_KEY
import hep.dataforge.vis.spatial.VisualObject3D.Companion.DETAIL_KEY import hep.dataforge.vis.spatial.VisualObject3D.Companion.DETAIL_KEY
import hep.dataforge.vis.spatial.VisualObject3D.Companion.LAYER_KEY import hep.dataforge.vis.spatial.VisualObject3D.Companion.LAYER_KEY
import hep.dataforge.vis.spatial.VisualObject3D.Companion.MATERIAL_KEY import hep.dataforge.vis.spatial.VisualObject3D.Companion.MATERIAL_KEY
import hep.dataforge.vis.spatial.VisualObject3D.Companion.OPACITY_KEY
import hep.dataforge.vis.spatial.VisualObject3D.Companion.SELECTED_KEY import hep.dataforge.vis.spatial.VisualObject3D.Companion.SELECTED_KEY
import hep.dataforge.vis.spatial.VisualObject3D.Companion.VISIBLE_KEY import hep.dataforge.vis.spatial.VisualObject3D.Companion.VISIBLE_KEY
import kotlinx.serialization.UseSerializers import kotlinx.serialization.UseSerializers
@ -40,6 +42,9 @@ interface VisualObject3D : VisualObject {
val DETAIL_KEY = "detail".asName() val DETAIL_KEY = "detail".asName()
val LAYER_KEY = "layer".asName() val LAYER_KEY = "layer".asName()
val COLOR_KEY = MATERIAL_KEY + "color"
val OPACITY_KEY = MATERIAL_KEY + "opacity"
val x = "x".asName() val x = "x".asName()
val y = "y".asName() val y = "y".asName()
val z = "z".asName() val z = "z".asName()
@ -109,11 +114,9 @@ var VisualObject.material: Meta?
set(value) = setProperty(MATERIAL_KEY, value) set(value) = setProperty(MATERIAL_KEY, value)
var VisualObject.opacity: Double var VisualObject.opacity: Double
get() = material?.get("opacity").double ?: 1.0 get() = getProperty(OPACITY_KEY).double ?: 1.0
set(value) { set(value) {
material = (material?.builder() ?: MetaBuilder()).apply { setProperty(OPACITY_KEY, value)
"opacity" to value
}
} }
var VisualObject.visible: Boolean? var VisualObject.visible: Boolean?
@ -125,15 +128,15 @@ var VisualObject.selected: Boolean?
set(value) = setProperty(SELECTED_KEY, value) set(value) = setProperty(SELECTED_KEY, value)
fun VisualObject.color(rgb: Int) { fun VisualObject.color(rgb: Int) {
material = (material?.builder() ?: MetaBuilder()).apply { "color" to rgbToString(rgb) } setProperty(COLOR_KEY, rgbToString(rgb))
} }
fun VisualObject.color(rgb: String) { fun VisualObject.color(rgb: String) {
material = (material?.builder() ?: MetaBuilder()).apply { "color" to rgb } setProperty(COLOR_KEY, rgb)
} }
var VisualObject.color: String? var VisualObject.color: String?
get() = material["color"].string get() = getProperty(COLOR_KEY).string
set(value) { set(value) {
if (value != null) { if (value != null) {
color(value) color(value)

View File

@ -20,7 +20,7 @@ class ThreeProxyFactory(val three: ThreePlugin) : ThreeFactory<Proxy> {
} }
override fun invoke(obj: Proxy): Object3D { override fun invoke(obj: Proxy): Object3D {
val template = obj.template val template = obj.prototype
val cachedObject = cache.getOrPut(template) { val cachedObject = cache.getOrPut(template) {
three.buildObject3D(template) three.buildObject3D(template)
} }
@ -45,11 +45,6 @@ class ThreeProxyFactory(val three: ThreePlugin) : ThreeFactory<Proxy> {
} }
} }
obj.onChildrenChange(this) { name, propertyHolder ->
val child = object3D.findChild(name)
(child as? Mesh)?.updateProperties(propertyHolder)
}
return object3D return object3D
} }
} }

View File

@ -10,7 +10,6 @@ import hep.dataforge.vis.common.VisualGroup
import hep.dataforge.vis.common.VisualObject import hep.dataforge.vis.common.VisualObject
import hep.dataforge.vis.common.getProperty import hep.dataforge.vis.common.getProperty
import hep.dataforge.vis.spatial.Proxy import hep.dataforge.vis.spatial.Proxy
import hep.dataforge.vis.spatial.selected
import hep.dataforge.vis.spatial.visible import hep.dataforge.vis.spatial.visible
import org.w3c.dom.HTMLElement import org.w3c.dom.HTMLElement
import kotlin.js.json import kotlin.js.json
@ -40,7 +39,7 @@ fun VisualGroup.toTree(onFocus: (VisualObject?, String?) -> Unit = { obj, name -
fun generateNodeConfig(item: VisualObject, fullName: Name): NodeConfig { fun generateNodeConfig(item: VisualObject, fullName: Name): NodeConfig {
val title = item.getProperty("title").string ?: fullName.last()?.toString() ?: "root" val title = item.getProperty("title").string ?: fullName.last()?.toString() ?: "root"
val className = if (item is Proxy) { val className = if (item is Proxy) {
item.template::class.toString() item.prototype::class.toString()
} else { } else {
item::class.toString() item::class.toString()
}.replace("class ", "") }.replace("class ", "")
@ -88,15 +87,15 @@ fun VisualGroup.toTree(onFocus: (VisualObject?, String?) -> Unit = { obj, name -
map[rootNode.id] = this map[rootNode.id] = this
rootNode.fillChildren(this, EmptyName) rootNode.fillChildren(this, EmptyName)
inspireTree.on("node.selected") { node: TreeNode, isLoadEvent: Boolean -> // inspireTree.on("node.selected") { node: TreeNode, isLoadEvent: Boolean ->
if (!isLoadEvent) { // if (!isLoadEvent) {
map[node.id]?.selected = node.selected() // map[node.id]?.selected = node.selected()
} // }
} // }
//
inspireTree.on("node.deselect") { node: TreeNode -> // inspireTree.on("node.deselect") { node: TreeNode ->
map[node.id]?.selected = node.selected() // map[node.id]?.selected = node.selected()
} // }
inspireTree.on("node.checked") { node: TreeNode, isLoadEvent: Boolean -> inspireTree.on("node.checked") { node: TreeNode, isLoadEvent: Boolean ->
if (!isLoadEvent) { if (!isLoadEvent) {

View File

@ -0,0 +1,185 @@
@file:Suppress(
"INTERFACE_WITH_SUPERCLASS",
"OVERRIDING_FINAL_MEMBER",
"RETURN_TYPE_MISMATCH_ON_OVERRIDE",
"CONFLICTING_OVERLOADS",
"EXTERNAL_DELEGATION"
)
package hep.dataforge.vis.spatial.tree
import org.w3c.dom.HTMLElement
external interface Node {
var field: String
var value: String? get() = definedExternally; set(value) = definedExternally
var path: dynamic
}
external interface NodeName {
var path: Array<String>
var type: dynamic /* 'object' | 'array' */
var size: Number
}
external interface ValidationError {
var path: dynamic
var message: String
}
external interface Template {
var text: String
var title: String
var className: String? get() = definedExternally; set(value) = definedExternally
var field: String
var value: Any
}
external interface `T$6` {
var startFrom: Number
var options: Array<String>
}
external interface AutoCompleteOptions {
var confirmKeys: Array<Number>? get() = definedExternally; set(value) = definedExternally
var caseSensitive: Boolean? get() = definedExternally; set(value) = definedExternally
// var getOptions: AutoCompleteOptionsGetter? get() = definedExternally; set(value) = definedExternally
}
external interface SelectionPosition {
var row: Number
var column: Number
}
external interface SerializableNode {
var value: Any
var path: dynamic
}
external interface Color {
var rgba: Array<Number>
var hsla: Array<Number>
var rgbString: String
var rgbaString: String
var hslString: String
var hslaString: String
var hex: String
}
//external interface `T$0` {
// var field: Boolean
// var value: Boolean
//}
//
//external interface `T$1` {
// @nativeGetter
// operator fun get(key: String): String?
//
// @nativeSetter
// operator fun set(key: String, value: String)
//}
//external interface Languages {
// @nativeGetter
// operator fun get(lang: String): `T$1`?
//
// @nativeSetter
// operator fun set(lang: String, value: `T$1`)
//}
external interface JSONEditorOptions {
// var ace: AceAjax.Ace? get() = definedExternally; set(value) = definedExternally
// var ajv: Ajv? get() = definedExternally; set(value) = definedExternally
var onChange: (() -> Unit)? get() = definedExternally; set(value) = definedExternally
var onChangeJSON: ((json: Any) -> Unit)? get() = definedExternally; set(value) = definedExternally
var onChangeText: ((jsonString: String) -> Unit)? get() = definedExternally; set(value) = definedExternally
var onEditable: ((node: Node) -> dynamic)? get() = definedExternally; set(value) = definedExternally
var onError: ((error: Error) -> Unit)? get() = definedExternally; set(value) = definedExternally
var onModeChange: ((newMode: dynamic /* 'tree' | 'view' | 'form' | 'code' | 'text' */, oldMode: dynamic /* 'tree' | 'view' | 'form' | 'code' | 'text' */) -> Unit)? get() = definedExternally; set(value) = definedExternally
var onNodeName: ((nodeName: NodeName) -> String?)? get() = definedExternally; set(value) = definedExternally
var onValidate: ((json: Any) -> dynamic)? get() = definedExternally; set(value) = definedExternally
var escapeUnicode: Boolean? get() = definedExternally; set(value) = definedExternally
var sortObjectKeys: Boolean? get() = definedExternally; set(value) = definedExternally
var history: Boolean? get() = definedExternally; set(value) = definedExternally
var mode: dynamic /* 'tree' | 'view' | 'form' | 'code' | 'text' */
var modes: Array<dynamic /* 'tree' | 'view' | 'form' | 'code' | 'text' */>? get() = definedExternally; set(value) = definedExternally
var name: String? get() = definedExternally; set(value) = definedExternally
var schema: Any? get() = definedExternally; set(value) = definedExternally
var schemaRefs: Any? get() = definedExternally; set(value) = definedExternally
var search: Boolean? get() = definedExternally; set(value) = definedExternally
var indentation: Number? get() = definedExternally; set(value) = definedExternally
var theme: String? get() = definedExternally; set(value) = definedExternally
var templates: Array<Template>? get() = definedExternally; set(value) = definedExternally
var autocomplete: AutoCompleteOptions? get() = definedExternally; set(value) = definedExternally
var mainMenuBar: Boolean? get() = definedExternally; set(value) = definedExternally
var navigationBar: Boolean? get() = definedExternally; set(value) = definedExternally
var statusBar: Boolean? get() = definedExternally; set(value) = definedExternally
var onTextSelectionChange: ((start: SelectionPosition, end: SelectionPosition, text: String) -> Unit)? get() = definedExternally; set(value) = definedExternally
var onSelectionChange: ((start: SerializableNode, end: SerializableNode) -> Unit)? get() = definedExternally; set(value) = definedExternally
var onEvent: ((node: Node, event: String) -> Unit)? get() = definedExternally; set(value) = definedExternally
var colorPicker: Boolean? get() = definedExternally; set(value) = definedExternally
var onColorPicker: ((parent: HTMLElement, color: String, onChange: (color: Color) -> Unit) -> Unit)? get() = definedExternally; set(value) = definedExternally
var timestampTag: Boolean? get() = definedExternally; set(value) = definedExternally
var language: String? get() = definedExternally; set(value) = definedExternally
//var languages: Languages? get() = definedExternally; set(value) = definedExternally
var modalAnchor: HTMLElement? get() = definedExternally; set(value) = definedExternally
var enableSort: Boolean? get() = definedExternally; set(value) = definedExternally
var enableTransform: Boolean? get() = definedExternally; set(value) = definedExternally
var maxVisibleChilds: Number? get() = definedExternally; set(value) = definedExternally
}
external interface JsonPath {
var path: dynamic
}
external interface EditorSelection {
var start: SerializableNode
var end: SerializableNode
}
external interface TextSelection {
var start: SelectionPosition
var end: SelectionPosition
var text: String
}
@JsModule("jsoneditor")
@JsNonModule
external open class JSONEditor(
container: HTMLElement,
options: JSONEditorOptions? = definedExternally /* null */,
json: dynamic = definedExternally /* null */
) {
open fun collapseAll()
open fun destroy()
open fun expandAll()
open fun focus()
open fun get(): Any
open fun getMode(): dynamic /* 'tree' | 'view' | 'form' | 'code' | 'text' */
open fun getName(): String?
open fun getNodesByRange(start: JsonPath, end: JsonPath): Array<SerializableNode>
open fun getSelection(): EditorSelection
open fun getText(): String
open fun getTextSelection(): TextSelection
open fun refresh()
open fun set(json: Any)
open fun setMode(mode: String /* 'tree' */)
open fun setMode(mode: String /* 'view' */)
open fun setMode(mode: String /* 'form' */)
open fun setMode(mode: String /* 'code' */)
open fun setMode(mode: String /* 'text' */)
open fun setName(name: String? = definedExternally /* null */)
open fun setSchema(schema: Any?, schemaRefs: Any? = definedExternally /* null */)
open fun setSelection(start: JsonPath, end: JsonPath)
open fun setText(jsonString: String)
open fun setTextSelection(start: SelectionPosition, end: SelectionPosition)
open fun update(json: Any)
open fun updateText(jsonString: String)
companion object {
var VALID_OPTIONS: Array<String>
// var ace: AceAjax.Ace
// var Ajv: Ajv
var VanillaPicker: Any
}
}

View File

@ -1,6 +1,8 @@
package hep.dataforge.vis.spatial.tree package hep.dataforge.vis.spatial.tree
import hep.dataforge.io.toJson
import hep.dataforge.vis.common.VisualObject import hep.dataforge.vis.common.VisualObject
import hep.dataforge.vis.spatial.Proxy
import hep.dataforge.vis.spatial.color import hep.dataforge.vis.spatial.color
import hep.dataforge.vis.spatial.opacity import hep.dataforge.vis.spatial.opacity
import hep.dataforge.vis.spatial.visible import hep.dataforge.vis.spatial.visible
@ -62,6 +64,21 @@ fun Element.propertyEditor(item: VisualObject?, name: String?) {
} }
} }
} }
(item.properties ?: (item as? Proxy)?.prototype?.properties
?: (item as? Proxy.ProxyChild)?.prototype?.properties)
?.let { config ->
div("card") {
div("card-body") {
h3(classes = "card-title") { +"Properties" }
}.apply {
val options = (js("{}") as JSONEditorOptions).apply {
mode = "view"
}
JSONEditor(this, options, JSON.parse(config.toJson().toString()))
}
}
}
} }
} }
} }