Style viewer and styles resolution fix for proxies.

This commit is contained in:
Alexander Nozik 2020-08-10 22:28:05 +03:00
parent de2ef1dcc5
commit 48705e6670
21 changed files with 265 additions and 205 deletions

View File

@ -7,7 +7,10 @@ import hep.dataforge.vision.Vision
import hep.dataforge.vision.VisionGroup
import hep.dataforge.vision.bootstrap.*
import hep.dataforge.vision.gdml.toVision
import hep.dataforge.vision.react.*
import hep.dataforge.vision.react.component
import hep.dataforge.vision.react.flexColumn
import hep.dataforge.vision.react.objectTree
import hep.dataforge.vision.react.state
import hep.dataforge.vision.solid.Solid
import hep.dataforge.vision.solid.SolidGroup
import hep.dataforge.vision.solid.specifications.Camera
@ -78,7 +81,7 @@ val GDMLApp = component<GDMLAppProps> { props ->
classes.add("p-1")
overflow = Overflow.auto
}
gridColumn(3, maxSize= GridMaxSize.XL, classes = "order-2 order-xl-1") {
gridColumn(3, maxSize = GridMaxSize.XL, classes = "order-2 order-xl-1") {
card("Load data") {
fileDrop("(drag file here)") { files ->
val file = files?.get(0)
@ -102,7 +105,7 @@ val GDMLApp = component<GDMLAppProps> { props ->
}
}
gridColumn(6, maxSize= GridMaxSize.XL, classes = "order-1 order-xl-2") {
gridColumn(6, maxSize = GridMaxSize.XL, classes = "order-1 order-xl-2") {
//canvas
(visual as? Solid)?.let { visual3D ->
child(ThreeCanvasComponent::class) {
@ -118,7 +121,7 @@ val GDMLApp = component<GDMLAppProps> { props ->
}
}
}
gridColumn(3, maxSize= GridMaxSize.XL, classes = "order-3") {
gridColumn(3, maxSize = GridMaxSize.XL, classes = "order-3") {
container {
//settings
canvas?.let {
@ -127,25 +130,25 @@ val GDMLApp = component<GDMLAppProps> { props ->
}
}
}
container {
namecrumbs(selected, "World") { selected = it }
}
container {
//properties
card("Properties") {
selected.let { selected ->
val selectedObject: Vision? = when {
selected == null -> null
selected.isEmpty() -> visual
else -> (visual as? VisionGroup)?.get(selected)
}
if (selectedObject != null) {
configEditor(selectedObject, default = selectedObject.getAllProperties(), key = selected)
}
namecrumbs(selected, "World") { selected = it }
selected.let { selected ->
val selectedObject: Vision? = when {
selected == null -> null
selected.isEmpty() -> visual
else -> (visual as? VisionGroup)?.get(selected)
}
if (selectedObject != null) {
visionPropertyEditor(
selectedObject,
default = selectedObject.getAllProperties(),
key = selected
)
}
}
}
}
}
}
}
}

View File

@ -1,6 +1,7 @@
package ru.mipt.npm.muon.monitor.server
import hep.dataforge.meta.DFExperimental
import hep.dataforge.vision.solid.SolidManager
import io.ktor.application.Application
import io.ktor.application.call
@ -28,6 +29,7 @@ import java.net.URI
private val generator = Cos2TrackGenerator(JDKRandomGenerator(223))
@OptIn(DFExperimental::class)
fun Application.module() {
val currentDir = File(".").absoluteFile
environment.log.info("Current directory: $currentDir")

Binary file not shown.

View File

@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

2
gradlew vendored
View File

@ -82,6 +82,7 @@ esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
@ -129,6 +130,7 @@ fi
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath

1
gradlew.bat vendored
View File

@ -84,6 +84,7 @@ set CMD_LINE_ARGS=%*
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%

View File

@ -1,8 +1,7 @@
import hep.dataforge.context.Global
import hep.dataforge.js.Application
import hep.dataforge.js.startApplication
import hep.dataforge.names.Name
import hep.dataforge.vision.bootstrap.visualPropertyEditor
import hep.dataforge.vision.bootstrap.visionPropertyEditor
import hep.dataforge.vision.react.objectTree
import hep.dataforge.vision.solid.Point3D
import hep.dataforge.vision.solid.SolidGroup
@ -41,7 +40,7 @@ private class PlayGroundApp : Application {
threeCanvas(obj)
}
div("col-3") {
visualPropertyEditor(Name.EMPTY, obj)
visionPropertyEditor(obj)
}
}
}

View File

@ -1,87 +0,0 @@
package hep.dataforge.vision.bootstrap
import hep.dataforge.meta.Meta
import hep.dataforge.meta.MetaItem
import hep.dataforge.meta.descriptors.NodeDescriptor
import hep.dataforge.names.NameToken
import kotlinx.html.classes
import kotlinx.html.js.onClickFunction
import org.w3c.dom.events.Event
import react.*
import react.dom.*
interface MetaViewerProps : RProps {
var name: NameToken
var meta: Meta
var descriptor: NodeDescriptor?
}
interface TreeState : RState {
var expanded: Boolean
}
@Deprecated("To be replaced by react functional component")
class MetaViewerComponent : RComponent<MetaViewerProps, TreeState>() {
override fun TreeState.init() {
expanded = false
}
private val onClick: (Event) -> Unit = {
setState {
expanded = !expanded
}
}
override fun RBuilder.render() {
div("d-inline-block text-truncate") {
if (props.meta.items.isNotEmpty()) {
span("tree-caret") {
attrs {
if (state.expanded) {
classes += "tree-caret-down"
}
onClickFunction = onClick
}
}
}
label("tree-label") {
+props.name.toString()
}
ul("tree") {
props.meta.items.forEach { (token, item) ->
//val descriptor = props.
li {
when (item) {
is MetaItem.NodeItem -> {
child(MetaViewerComponent::class) {
attrs {
name = token
meta = item.node
descriptor = props.descriptor?.nodes?.get(token.body)
}
}
}
is MetaItem.ValueItem -> {
div("row") {
div("col") {
label("tree-label") {
+token.toString()
}
}
div("col") {
label {
+item.value.toString()
}
}
}
}
}
}
}
}
}
}
}

View File

@ -1,49 +0,0 @@
package hep.dataforge.vision.bootstrap
import hep.dataforge.meta.Meta
import hep.dataforge.meta.descriptors.NodeDescriptor
import hep.dataforge.names.Name
import hep.dataforge.names.isEmpty
import hep.dataforge.vision.Vision
import hep.dataforge.vision.react.configEditor
import org.w3c.dom.Element
import react.RBuilder
import react.dom.li
import react.dom.nav
import react.dom.ol
import react.dom.render
import kotlin.collections.set
fun RBuilder.visualPropertyEditor(
path: Name,
item: Vision,
descriptor: NodeDescriptor? = item.descriptor,
default: Meta? = null
) {
card("Properties") {
if (!path.isEmpty()) {
nav {
attrs {
attributes["aria-label"] = "breadcrumb"
}
ol("breadcrumb") {
path.tokens.forEach { token ->
li("breadcrumb-item") {
+token.toString()
}
}
}
}
}
configEditor(item, descriptor, default)
}
}
fun Element.visualPropertyEditor(
path: Name,
item: Vision,
descriptor: NodeDescriptor? = item.descriptor,
default: Meta? = null
) = render(this) {
this.visualPropertyEditor(path, item, descriptor, default)
}

View File

@ -0,0 +1,45 @@
package hep.dataforge.vision.bootstrap
import hep.dataforge.meta.Meta
import hep.dataforge.meta.descriptors.NodeDescriptor
import hep.dataforge.vision.Vision
import hep.dataforge.vision.react.configEditor
import hep.dataforge.vision.react.metaViewer
import hep.dataforge.vision.resolveStyle
import org.w3c.dom.Element
import react.RBuilder
import react.dom.render
fun RBuilder.visionPropertyEditor(
item: Vision,
descriptor: NodeDescriptor? = item.descriptor,
default: Meta? = null,
key: Any? = null
) {
card("Properties") {
configEditor(item, descriptor, default, key)
}
val styles = item.styles
if(styles.isNotEmpty()) {
card("Styles") {
accordion("styles") {
styles.forEach { styleName ->
val style = item.resolveStyle(styleName)
if (style != null) {
entry(styleName) {
metaViewer(style)
}
}
}
}
}
}
}
fun Element.visionPropertyEditor(
item: Vision,
descriptor: NodeDescriptor? = item.descriptor,
default: Meta? = null
) = render(this) {
visionPropertyEditor(item, descriptor, default)
}

View File

@ -113,7 +113,7 @@ private fun RFBuilder.configEditorItem(props: ConfigEditorItemProps) {
css {
+TreeStyles.tree
}
val keys = buildSet<NameToken> {
val keys = buildSet {
(descriptorItem as? NodeDescriptor)?.items?.keys?.forEach {
add(NameToken(it))
}
@ -121,7 +121,7 @@ private fun RFBuilder.configEditorItem(props: ConfigEditorItemProps) {
defaultItem?.node?.items?.keys?.let { addAll(it) }
}
keys.forEach { token ->
keys.filter { !it.body.startsWith("@") }.forEach { token ->
styledLi {
css {
+TreeStyles.treeItem
@ -145,7 +145,6 @@ private fun RFBuilder.configEditorItem(props: ConfigEditorItemProps) {
styledDiv {
css {
+TreeStyles.treeLeaf
// justifyContent = JustifyContent.flexEnd
}
styledDiv {
css {
@ -238,13 +237,4 @@ fun RBuilder.configEditor(
descriptor: NodeDescriptor? = obj.descriptor,
default: Meta? = null,
key: Any? = null
) {
child(ConfigEditor) {
attrs {
this.key = key?.toString() ?: ""
this.root = obj.config
this.descriptor = descriptor
this.default = default
}
}
}
) = configEditor(obj.config,descriptor, default, key)

View File

@ -0,0 +1,157 @@
package hep.dataforge.vision.react
import hep.dataforge.meta.Meta
import hep.dataforge.meta.MetaItem
import hep.dataforge.meta.descriptors.ItemDescriptor
import hep.dataforge.meta.descriptors.NodeDescriptor
import hep.dataforge.meta.descriptors.defaultItem
import hep.dataforge.meta.descriptors.get
import hep.dataforge.meta.get
import hep.dataforge.names.Name
import hep.dataforge.names.NameToken
import hep.dataforge.names.plus
import kotlinx.html.js.onClickFunction
import org.w3c.dom.events.Event
import react.*
import react.dom.a
import styled.*
interface MetaViewerProps : RProps {
/**
* Root meta
*/
var root: Meta
/**
* Full path to the displayed node in [root]. Could be empty
*/
var name: Name
/**
* Root descriptor
*/
var descriptor: NodeDescriptor?
}
private val MetaViewerItem: FunctionalComponent<MetaViewerProps> = component { props ->
metaViewerItem(props)
}
private fun RFBuilder.metaViewerItem(props: MetaViewerProps) {
var expanded: Boolean by state { true }
val item = props.root[props.name]
val descriptorItem: ItemDescriptor? = props.descriptor?.get(props.name)
val actualItem = item ?: descriptorItem?.defaultItem()
val token = props.name.last()?.toString() ?: "Meta"
val expanderClick: (Event) -> Unit = {
expanded = !expanded
}
when (actualItem) {
is MetaItem.NodeItem -> {
styledDiv {
css {
+TreeStyles.treeLeaf
}
styledSpan {
css {
+TreeStyles.treeCaret
if (expanded) {
+TreeStyles.treeCaredDown
}
}
attrs {
onClickFunction = expanderClick
}
}
styledSpan {
css {
+TreeStyles.treeLabel
if (item == null) {
+TreeStyles.treeLabelInactive
}
}
+token
}
}
if (expanded) {
styledUl {
css {
+TreeStyles.tree
}
val keys = buildSet {
(descriptorItem as? NodeDescriptor)?.items?.keys?.forEach {
add(NameToken(it))
}
actualItem.node.items.keys.let { addAll(it) }
}
keys.filter { !it.body.startsWith("@") }.forEach { token ->
styledLi {
css {
+TreeStyles.treeItem
}
child(MetaViewerItem) {
attrs {
this.key = props.name.toString()
this.root = props.root
this.name = props.name + token
this.descriptor = props.descriptor
}
}
//configEditor(props.root, props.name + token, props.descriptor, props.default)
}
}
}
}
}
is MetaItem.ValueItem -> {
styledDiv {
css {
+TreeStyles.treeLeaf
}
styledDiv {
css {
+TreeStyles.treeLabel
}
styledSpan {
css {
if (item == null) {
+TreeStyles.treeLabelInactive
}
}
+token
}
}
styledDiv {
a {
+actualItem.value.toString()
}
}
}
}
}
}
val MetaViewer = component<MetaViewerProps> { props ->
child(MetaViewerItem) {
attrs {
this.key = ""
this.root = props.root
this.name = Name.EMPTY
this.descriptor = props.descriptor
}
}
}
fun RBuilder.metaViewer(meta: Meta, descriptor: NodeDescriptor? = null, key: Any? = null) {
child(MetaViewer) {
attrs {
this.key = key?.toString() ?: ""
this.root = meta
this.descriptor = descriptor
}
}
}

View File

@ -1,9 +0,0 @@
package hep.dataforge.vision.react
import styled.StyleSheet
class MainStyle: StyleSheet("main", true){
}

View File

@ -5,7 +5,6 @@ package hep.dataforge.vision
import hep.dataforge.meta.*
import hep.dataforge.names.Name
import hep.dataforge.names.asName
import hep.dataforge.values.asValue
import kotlinx.serialization.*
import kotlinx.serialization.builtins.MapSerializer
import kotlinx.serialization.builtins.serializer
@ -90,15 +89,6 @@ class StyleSheet private constructor(private val styleMap: MutableMap<String, Me
}
/**
* List of names of styles applied to this object. Order matters. Not inherited
*/
var Vision.styles: List<String>
get() = properties?.get(Vision.STYLE_KEY).stringList
set(value) {
setItem(Vision.STYLE_KEY,value.map { it.asValue() }.asValue())
}
/**
* Add style name to the list of styles to be resolved later. The style with given name does not necessary exist at the moment.
*/

View File

@ -5,6 +5,7 @@ import hep.dataforge.names.Name
import hep.dataforge.names.asName
import hep.dataforge.names.toName
import hep.dataforge.provider.Type
import hep.dataforge.values.asValue
import hep.dataforge.vision.Vision.Companion.TYPE
import kotlinx.serialization.PolymorphicSerializer
import kotlinx.serialization.Transient
@ -56,13 +57,22 @@ interface Vision : Configurable {
*/
fun removeChangeListener(owner: Any?)
/**
* List of names of styles applied to this object. Order matters. Not inherited.
*/
var styles: List<String>
get() = properties[STYLE_KEY].stringList
set(value) {
setItem(STYLE_KEY,value.map { it.asValue() }.asValue())
}
companion object {
const val TYPE = "visual"
const val TYPE = "vision"
val STYLE_KEY = "@style".asName()
private val VISUAL_OBJECT_SERIALIZER = PolymorphicSerializer(Vision::class)
private val VISION_SERIALIZER = PolymorphicSerializer(Vision::class)
fun serializer() = VISUAL_OBJECT_SERIALIZER
fun serializer() = VISION_SERIALIZER
}
}

View File

@ -84,7 +84,7 @@ class VisionManager(meta: Meta) : AbstractPlugin(meta) {
}
fun buildVision(meta: Meta): Vision {
val type = meta["type"].string ?: SimpleVisionGroup.serializer().descriptor.serialName
val type = meta["type"].string ?: Vision.serializer().descriptor.serialName
val form = forms.values.find { it.name.toString() == type } ?: error("Could not resolve a form for type $type")
return form.buildVision(meta, visionSerialModule)
}

View File

@ -6,7 +6,6 @@ import hep.dataforge.meta.descriptors.NodeDescriptor
import hep.dataforge.meta.update
import hep.dataforge.vision.Vision
import hep.dataforge.vision.resolveStyle
import hep.dataforge.vision.styles
import javafx.beans.binding.Binding
import javafx.beans.property.SimpleObjectProperty
import javafx.scene.Node

View File

@ -2,12 +2,10 @@
package hep.dataforge.vision.solid
import hep.dataforge.meta.Config
import hep.dataforge.meta.Laminate
import hep.dataforge.meta.MetaItem
import hep.dataforge.meta.*
import hep.dataforge.meta.descriptors.NodeDescriptor
import hep.dataforge.meta.get
import hep.dataforge.names.*
import hep.dataforge.values.asValue
import hep.dataforge.vision.*
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@ -89,6 +87,12 @@ class Proxy private constructor(
//override fun findAllStyles(): Laminate = Laminate((styles + prototype.styles).mapNotNull { findStyle(it) })
override var styles: List<String>
get() = properties[Vision.STYLE_KEY].stringList + prototype.styles
set(value) {
setItem(Vision.STYLE_KEY, value.map { it.asValue() }.asValue())
}
override val descriptor: NodeDescriptor?
get() = prototype.descriptor
@ -147,6 +151,12 @@ class Proxy private constructor(
Laminate(properties, allStyles, prototype.getAllProperties(), parent?.getAllProperties())
override var styles: List<String>
get() = properties[Vision.STYLE_KEY].stringList + prototype.styles
set(value) {
setItem(Vision.STYLE_KEY, value.map { it.asValue() }.asValue())
}
override val descriptor: NodeDescriptor?
get() = prototype.descriptor
}

View File

@ -123,7 +123,7 @@ internal object PrototypesSerializer : KSerializer<MutableVisionGroup> {
fun Vision.stringify(): String = SolidManager.jsonForSolids.stringify(Vision.serializer(), this)
@OptIn(DFExperimental::class)
fun Vision.Companion.parseJson(str: String) = SolidManager.jsonForSolids.parse(Vision.serializer(), str).also {
fun Vision.Companion.parseJson(str: String) = SolidManager.jsonForSolids.parse(serializer(), str).also {
if(it is VisionGroup){
it.attachChildren()
}

View File

@ -1,13 +1,11 @@
package hep.dataforge.vision.solid
import hep.dataforge.meta.MetaItem
import hep.dataforge.meta.getIndexed
import hep.dataforge.meta.node
import hep.dataforge.meta.toMetaItem
import hep.dataforge.meta.*
import kotlin.test.Test
import kotlin.test.assertEquals
class ConvexTest {
@OptIn(DFExperimental::class)
@Suppress("UNUSED_VARIABLE")
@Test
fun testConvexBuilder() {

View File

@ -3,7 +3,6 @@ package hep.dataforge.vision.solid
import hep.dataforge.meta.int
import hep.dataforge.meta.set
import hep.dataforge.names.asName
import hep.dataforge.vision.styles
import hep.dataforge.vision.useStyle
import kotlin.test.Test
import kotlin.test.assertEquals