commonMain.jetbrains.datalore.vis.svg.SvgNode.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of vis-svg-portable Show documentation
Show all versions of vis-svg-portable Show documentation
The Let-Plot Kotlin API depends on this artifact.
/*
* Copyright (c) 2019. JetBrains s.r.o.
* Use of this source code is governed by the MIT license that can be found in the LICENSE file.
*/
package jetbrains.datalore.vis.svg
import jetbrains.datalore.base.observable.children.ChildList
import jetbrains.datalore.base.observable.children.SimpleComposite
import jetbrains.datalore.base.observable.collections.list.ObservableList
abstract class SvgNode : SimpleComposite() {
private var myContainer: SvgNodeContainer? = null
private var myChildren: SvgChildList? = null
/**
* @return `true` if subtree below this node is absolutely not going to
* change once the process of mapping is completed.
*/
/**
* Marks the node as whether the descendant nodes can change
* their properties/structure at any time (this is the default)
* or properties/structure of descendant nodes are absolutely not going to
* change once the process of their mapping is completed (i.e. the subtree is 'pre-built').
*
*
* If subtree is 'pre-build' then listening for changes in structure/properties of nodes in the subtree
* is not required and can be dropped for better performance.
*
* @param prebuiltSubtree If `false` (default) the subtree is 'dynamic'.
* If `true` the subtree is 'static' (pre-built)
*/
var isPrebuiltSubtree: Boolean = false
fun isAttached(): Boolean = myContainer != null
fun container(): SvgNodeContainer {
return myContainer!!
}
open fun children(): ObservableList {
if (myChildren == null) {
myChildren = SvgChildList(this)
}
return myChildren as ObservableList
}
internal fun attach(container: SvgNodeContainer?) {
if (isAttached()) {
throw IllegalStateException("Svg element is already attached")
}
for (node in children()) {
node.attach(container)
}
myContainer = container
myContainer!!.svgNodeAttached(this)
}
internal fun detach() {
if (!isAttached()) {
throw IllegalStateException("Svg element is not attached")
}
for (node in children()) {
node.detach()
}
myContainer!!.svgNodeDetached(this)
myContainer = null
}
private inner class SvgChildList internal constructor(parent: SvgNode) :
ChildList(parent) {
override fun beforeItemAdded(index: Int, item: SvgNode) {
if (isAttached()) {
item.attach(container())
}
super.beforeItemAdded(index, item)
}
override fun beforeItemSet(index: Int, oldItem: SvgNode, newItem: SvgNode) {
if (isAttached()) {
oldItem.detach()
newItem.attach(container())
}
super.beforeItemSet(index, oldItem, newItem)
}
override fun beforeItemRemoved(index: Int, item: SvgNode) {
if (isAttached()) {
item.detach()
}
super.beforeItemRemoved(index, item)
}
}
}