Property resolution simplification

This commit is contained in:
Alexander Nozik 2019-12-24 22:09:39 +03:00
parent 8d39a3efa5
commit 193fed524e
14 changed files with 113 additions and 51 deletions

View File

@ -1,6 +1,6 @@
import scientifik.useSerialization import scientifik.useSerialization
val dataforgeVersion by extra("0.1.5-dev-4") val dataforgeVersion by extra("0.1.5-dev-5")
plugins { plugins {
val kotlinVersion = "1.3.61" val kotlinVersion = "1.3.61"
@ -30,7 +30,7 @@ allprojects {
} }
subprojects{ subprojects{
useSerialization("0.13.0") this.useSerialization()
} }
val githubProject by extra("dataforge-vis") val githubProject by extra("dataforge-vis")

View File

@ -1,4 +1,5 @@
import org.openjfx.gradle.JavaFXOptions import org.openjfx.gradle.JavaFXOptions
import scientifik.useSerialization
plugins { plugins {
id("scientifik.mpp") id("scientifik.mpp")
@ -8,6 +9,8 @@ plugins {
val dataforgeVersion: String by rootProject.extra val dataforgeVersion: String by rootProject.extra
//val kvisionVersion: String by rootProject.extra("2.0.0-M1") //val kvisionVersion: String by rootProject.extra("2.0.0-M1")
useSerialization()
kotlin { kotlin {
jvm{ jvm{
withJava() withJava()
@ -22,7 +25,9 @@ kotlin {
jvmMain{ jvmMain{
dependencies { dependencies {
api("no.tornado:tornadofx:1.7.19") api("no.tornado:tornadofx:1.7.19")
api("no.tornado:tornadofx-controlsfx:0.1") //api("no.tornado:tornadofx-controlsfx:0.1.1")
api("de.jensd:fontawesomefx-fontawesome:4.7.0-11")
api("de.jensd:fontawesomefx-commons:11.0")
} }
} }
jsMain{ jsMain{

View File

@ -61,10 +61,6 @@ abstract class AbstractVisualObject : VisualObject {
listeners.removeAll { it.owner == owner } listeners.removeAll { it.owner == owner }
} }
override fun setProperty(name: Name, value: Any?) {
config[name] = value
}
private var styleCache: Meta? = null private var styleCache: Meta? = null
/** /**
@ -75,6 +71,7 @@ abstract class AbstractVisualObject : VisualObject {
styleCache = it styleCache = it
} }
override fun allProperties(): Laminate = Laminate(properties, mergedStyles)
override fun getProperty(name: Name, inherit: Boolean): MetaItem<*>? { override fun getProperty(name: Name, inherit: Boolean): MetaItem<*>? {
return if (inherit) { return if (inherit) {

View File

@ -78,4 +78,4 @@ interface MutableVisualGroup : VisualGroup {
operator fun set(name: Name, child: VisualObject?) operator fun set(name: Name, child: VisualObject?)
} }
operator fun VisualGroup.get(str: String?) = get(str?.toName() ?: EmptyName) operator fun VisualGroup.get(str: String?) = get(str?.toName() ?: Name.EMPTY)

View File

@ -23,10 +23,17 @@ interface VisualObject : Configurable {
@Transient @Transient
var parent: VisualObject? var parent: VisualObject?
/**
* All properties including styles and prototypes if present, but without inheritance
*/
fun allProperties(): Meta
/** /**
* Set property for this object * Set property for this object
*/ */
fun setProperty(name: Name, value: Any?) fun setProperty(name: Name, value: Any?) {
config[name] = value
}
/** /**
* Get property including or excluding parent properties * Get property including or excluding parent properties

View File

@ -5,17 +5,20 @@
*/ */
package hep.dataforge.vis.fx.editor package hep.dataforge.vis.fx.editor
import de.jensd.fx.glyphs.fontawesome.FontAwesomeIcon
import de.jensd.fx.glyphs.fontawesome.FontAwesomeIconView
import hep.dataforge.context.Global import hep.dataforge.context.Global
import hep.dataforge.descriptors.NodeDescriptor import hep.dataforge.descriptors.NodeDescriptor
import hep.dataforge.meta.Config import hep.dataforge.meta.Config
import hep.dataforge.names.NameToken import hep.dataforge.names.NameToken
import hep.dataforge.vis.fx.dfIconView import hep.dataforge.vis.fx.dfIconView
import javafx.scene.Node
import javafx.scene.control.* import javafx.scene.control.*
import javafx.scene.control.cell.TextFieldTreeTableCell import javafx.scene.control.cell.TextFieldTreeTableCell
import javafx.scene.layout.HBox
import javafx.scene.layout.Priority import javafx.scene.layout.Priority
import javafx.scene.paint.Color import javafx.scene.paint.Color
import javafx.scene.text.Text import javafx.scene.text.Text
import org.controlsfx.glyphfont.Glyph
import tornadofx.* import tornadofx.*
/** /**
@ -133,8 +136,9 @@ class ConfigEditor(
is FXMetaNode<Config> -> { is FXMetaNode<Config> -> {
if (allowNew) { if (allowNew) {
text = null text = null
graphic = hbox { graphic = HBox().apply {
button("node", Glyph("FontAwesome", "PLUS_CIRCLE")) { val glyph: Node = FontAwesomeIconView(FontAwesomeIcon.PLUS_CIRCLE)
button("node", graphic = glyph) {
hgrow = Priority.ALWAYS hgrow = Priority.ALWAYS
maxWidth = Double.POSITIVE_INFINITY maxWidth = Double.POSITIVE_INFINITY
action { action {
@ -143,7 +147,7 @@ class ConfigEditor(
} }
} }
} }
button("value", Glyph("FontAwesome", "PLUS_SQUARE")) { button("value", graphic = FontAwesomeIconView(FontAwesomeIcon.PLUS_SQUARE)) {
hgrow = Priority.ALWAYS hgrow = Priority.ALWAYS
maxWidth = Double.POSITIVE_INFINITY maxWidth = Double.POSITIVE_INFINITY
action { action {

View File

@ -2,6 +2,8 @@ package hep.dataforge.vis.fx.editor
import hep.dataforge.descriptors.NodeDescriptor import hep.dataforge.descriptors.NodeDescriptor
import hep.dataforge.meta.Config import hep.dataforge.meta.Config
import hep.dataforge.meta.Meta
import hep.dataforge.meta.update
import hep.dataforge.vis.common.VisualObject import hep.dataforge.vis.common.VisualObject
import hep.dataforge.vis.common.findStyle import hep.dataforge.vis.common.findStyle
import javafx.beans.binding.Binding import javafx.beans.binding.Binding
@ -11,7 +13,7 @@ import javafx.scene.Parent
import javafx.scene.layout.VBox import javafx.scene.layout.VBox
import tornadofx.* import tornadofx.*
class VisualObjectEditorFragment(val selector: (VisualObject) -> Config) : Fragment() { class VisualObjectEditorFragment(val selector: (VisualObject) -> Meta) : Fragment() {
val itemProperty = SimpleObjectProperty<VisualObject>() val itemProperty = SimpleObjectProperty<VisualObject>()
var item: VisualObject? by itemProperty var item: VisualObject? by itemProperty
@ -26,8 +28,21 @@ class VisualObjectEditorFragment(val selector: (VisualObject) -> Config) : Fragm
this.descriptorProperty.set(descriptor) this.descriptorProperty.set(descriptor)
} }
private val configProperty: Binding<Config?> = itemProperty.objectBinding { private var currentConfig: Config? = null
it?.let { selector(it) }
private val configProperty: Binding<Config?> = itemProperty.objectBinding { visualObject ->
if (visualObject == null) return@objectBinding null
val meta = selector(visualObject)
val config = Config().apply {
update(meta)
onChange(this@VisualObjectEditorFragment) { key, _, after ->
visualObject.setProperty(key, after)
}
}
//remember old config reference to cleanup listeners
currentConfig?.removeListener(this)
currentConfig = config
config
} }
private val configEditorProperty: Binding<Node?> = configProperty.objectBinding(descriptorProperty) { private val configEditorProperty: Binding<Node?> = configProperty.objectBinding(descriptorProperty) {

View File

@ -7,25 +7,47 @@ import javafx.scene.control.SelectionMode
import javafx.scene.control.TreeItem import javafx.scene.control.TreeItem
import tornadofx.* import tornadofx.*
private fun toTreeItem(visualObject: VisualObject, title: String): TreeItem<Pair<String, VisualObject>> {
return object : TreeItem<Pair<String, VisualObject>>(title to visualObject) {
init {
if (visualObject is VisualGroup) {
//lazy populate the tree
expandedProperty().onChange { expanded ->
if (expanded && children.isEmpty()) {
children.setAll(visualObject.children.map {
toTreeItem(it.value, it.key.toString())
})
}
}
}
}
override fun isLeaf(): Boolean {
return !(visualObject is VisualGroup && visualObject.children.isNotEmpty())
}
}
}
class VisualObjectTreeFragment : Fragment() { class VisualObjectTreeFragment : Fragment() {
val itemProperty = SimpleObjectProperty<VisualObject>() val itemProperty = SimpleObjectProperty<VisualObject>()
var item: VisualObject? by itemProperty var item: VisualObject? by itemProperty
val selectedProperty = SimpleObjectProperty<VisualObject>() val selectedProperty = SimpleObjectProperty<VisualObject>()
override val root = borderpane{ override val root = vbox {
center = titledpane("Object tree") { titledpane("Object tree", collapsible = false) {
treeview<VisualObject> { treeview<Pair<String, VisualObject>> {
cellFormat {
text = item.first
}
itemProperty.onChange { rootObject -> itemProperty.onChange { rootObject ->
if (rootObject != null) { if (rootObject != null) {
root = TreeItem(rootObject) root = toTreeItem(rootObject, "world")
populate { item ->
(item.value as? VisualGroup)?.children?.values?.toList()
}
} }
} }
selectionModel.selectionMode = SelectionMode.SINGLE selectionModel.selectionMode = SelectionMode.SINGLE
val selectedValue = selectionModel.selectedItemProperty().objectBinding{it?.value} val selectedValue = selectionModel.selectedItemProperty().objectBinding { it?.value?.second }
selectedProperty.bind(selectedValue) selectedProperty.bind(selectedValue)
} }
} }

View File

@ -1,6 +1,7 @@
package hep.dataforge.vis.spatial.gdml package hep.dataforge.vis.spatial.gdml
import hep.dataforge.names.EmptyName
import hep.dataforge.names.Name
import hep.dataforge.names.asName import hep.dataforge.names.asName
import hep.dataforge.names.plus import hep.dataforge.names.plus
import hep.dataforge.vis.common.get import hep.dataforge.vis.common.get
@ -194,7 +195,7 @@ private fun VisualGroup3D.addDivisionVolume(
//TODO add divisions //TODO add divisions
set( set(
EmptyName, Name.EMPTY,
volume( volume(
context, context,
volume volume

View File

@ -1,10 +1,13 @@
import org.openjfx.gradle.JavaFXOptions import org.openjfx.gradle.JavaFXOptions
import scientifik.useSerialization
plugins { plugins {
id("scientifik.mpp") id("scientifik.mpp")
id("org.openjfx.javafxplugin") id("org.openjfx.javafxplugin")
} }
useSerialization()
kotlin { kotlin {
jvm { jvm {
withJava() withJava()

View File

@ -1,8 +1,10 @@
package hep.dataforge.vis.spatial package hep.dataforge.vis.spatial
import hep.dataforge.descriptors.NodeDescriptor
import hep.dataforge.meta.* import hep.dataforge.meta.*
import hep.dataforge.names.asName import hep.dataforge.names.asName
import hep.dataforge.names.plus import hep.dataforge.names.plus
import hep.dataforge.values.ValueType
import hep.dataforge.vis.common.Colors import hep.dataforge.vis.common.Colors
import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_COLOR_KEY import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_COLOR_KEY
import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_OPACITY_KEY import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_OPACITY_KEY
@ -29,6 +31,22 @@ class Material3D(override val config: Config) : Specific {
internal val WIREFRAME_KEY = "wireframe".asName() internal val WIREFRAME_KEY = "wireframe".asName()
val MATERIAL_WIREFRAME_KEY = MATERIAL_KEY + WIREFRAME_KEY val MATERIAL_WIREFRAME_KEY = MATERIAL_KEY + WIREFRAME_KEY
val descriptor = NodeDescriptor {
node(MATERIAL_KEY) {
value(COLOR_KEY) {
type(ValueType.STRING, ValueType.NUMBER)
default("#ffffff")
}
value(OPACITY_KEY){
type(ValueType.NUMBER)
default(1.0)
}
value(WIREFRAME_KEY){
type(ValueType.BOOLEAN)
default(false)
}
}
}
} }
} }
@ -63,7 +81,7 @@ fun VisualObject3D.material(builder: Material3D.() -> Unit) {
if (node != null) { if (node != null) {
Material3D.update(node, builder) Material3D.update(node, builder)
} else { } else {
config[Material3D.MATERIAL_KEY] = Material3D.build(builder) config[Material3D.MATERIAL_KEY] = Material3D(builder)
} }
} }

View File

@ -5,6 +5,7 @@ package hep.dataforge.vis.spatial
import hep.dataforge.io.serialization.ConfigSerializer import hep.dataforge.io.serialization.ConfigSerializer
import hep.dataforge.io.serialization.NameSerializer import hep.dataforge.io.serialization.NameSerializer
import hep.dataforge.meta.Config import hep.dataforge.meta.Config
import hep.dataforge.meta.Laminate
import hep.dataforge.meta.MetaItem import hep.dataforge.meta.MetaItem
import hep.dataforge.meta.get import hep.dataforge.meta.get
import hep.dataforge.names.Name import hep.dataforge.names.Name
@ -76,12 +77,7 @@ class Proxy(val templateName: Name) : AbstractVisualObject(), VisualGroup, Visua
?: error("Prototype with name $name not found in $this") ?: error("Prototype with name $name not found in $this")
} }
override var styles: List<String> override fun allProperties(): Laminate = Laminate(properties, mergedStyles, prototype.allProperties())
get() = super.styles + prototype.styles
set(value) {
setProperty(VisualObject.STYLE_KEY, value)
updateStyles(value)
}
//override fun findAllStyles(): Laminate = Laminate((styles + prototype.styles).mapNotNull { findStyle(it) }) //override fun findAllStyles(): Laminate = Laminate((styles + prototype.styles).mapNotNull { findStyle(it) })
@ -92,13 +88,6 @@ class Proxy(val templateName: Name) : AbstractVisualObject(), VisualGroup, Visua
override val styleSheet: StyleSheet get() = this@Proxy.styleSheet override val styleSheet: StyleSheet get() = this@Proxy.styleSheet
override var styles: List<String>
get() = super.styles + prototype.styles
set(value) {
setProperty(VisualObject.STYLE_KEY, value)
updateStyles(value)
}
override val children: Map<NameToken, VisualObject> override val children: Map<NameToken, VisualObject>
get() = (prototype as? VisualGroup)?.children?.mapValues { (key, _) -> get() = (prototype as? VisualGroup)?.children?.mapValues { (key, _) ->
ProxyChild( ProxyChild(
@ -136,6 +125,9 @@ class Proxy(val templateName: Name) : AbstractVisualObject(), VisualGroup, Visua
} }
} }
override fun allProperties(): Laminate = Laminate(properties, mergedStyles, prototype.allProperties())
} }
companion object { companion object {

View File

@ -2,14 +2,11 @@ package hep.dataforge.vis.spatial.fx
import hep.dataforge.names.Name import hep.dataforge.names.Name
import hep.dataforge.names.isEmpty import hep.dataforge.names.isEmpty
import hep.dataforge.names.startsWith
import hep.dataforge.names.toName import hep.dataforge.names.toName
import hep.dataforge.vis.common.VisualObject import hep.dataforge.vis.common.VisualObject
import hep.dataforge.vis.spatial.Material3D
import hep.dataforge.vis.spatial.Proxy import hep.dataforge.vis.spatial.Proxy
import javafx.scene.Group import javafx.scene.Group
import javafx.scene.Node import javafx.scene.Node
import javafx.scene.shape.Shape3D
import kotlin.reflect.KClass import kotlin.reflect.KClass
class FXProxyFactory(val plugin: FX3DPlugin) : FX3DFactory<Proxy> { class FXProxyFactory(val plugin: FX3DPlugin) : FX3DFactory<Proxy> {
@ -44,7 +41,7 @@ private fun Node.findChild(name: Name): Node? {
} }
private fun Node.updateProperty(obj: VisualObject, propertyName: Name) { private fun Node.updateProperty(obj: VisualObject, propertyName: Name) {
if (propertyName.startsWith(Material3D.MATERIAL_KEY)) { // if (propertyName.startsWith(Material3D.MATERIAL_KEY)) {
(this as? Shape3D)?.let { it.material = obj.getProperty(Material3D.MATERIAL_KEY).material() } // (this as? Shape3D)?.let { it.material = obj.getProperty(Material3D.MATERIAL_KEY).material() }
} // }
} }

View File

@ -9,7 +9,6 @@ import hep.dataforge.vis.spatial.fx.FXCanvas3D
import hep.dataforge.vis.spatial.gdml.LUnit import hep.dataforge.vis.spatial.gdml.LUnit
import hep.dataforge.vis.spatial.gdml.readFile import hep.dataforge.vis.spatial.gdml.readFile
import hep.dataforge.vis.spatial.gdml.toVisual import hep.dataforge.vis.spatial.gdml.toVisual
import hep.dataforge.vis.spatial.prototype
import javafx.geometry.Orientation import javafx.geometry.Orientation
import javafx.scene.Parent import javafx.scene.Parent
import javafx.stage.FileChooser import javafx.stage.FileChooser
@ -26,8 +25,10 @@ class GDMLView : View() {
this.itemProperty.bind(canvas.rootObjectProperty) this.itemProperty.bind(canvas.rootObjectProperty)
} }
private val propertyEditor = VisualObjectEditorFragment { it.prototype.config }.apply { private val propertyEditor = VisualObjectEditorFragment {
//TODO add descriptor here it.allProperties()
}.apply {
descriptorProperty.set(Material3D.descriptor)
itemProperty.bind(treeFragment.selectedProperty) itemProperty.bind(treeFragment.selectedProperty)
} }