forked from kscience/visionforge
Demo structure change and fx update
This commit is contained in:
parent
a564e078e5
commit
8d39a3efa5
@ -29,6 +29,7 @@ kotlin {
|
||||
dependencies {
|
||||
api("hep.dataforge:dataforge-output-html:$dataforgeVersion")
|
||||
api(npm("bootstrap","4.4.1"))
|
||||
implementation(npm("jsoneditor"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,18 +27,21 @@ class StyleSheet() {
|
||||
return styleMap[key] ?: (owner?.parent as? VisualGroup)?.styleSheet?.get(key)
|
||||
}
|
||||
|
||||
operator fun set(key: String, style: Meta?) {
|
||||
val oldStyle = styleMap[key]
|
||||
/**
|
||||
* Define a style without notifying
|
||||
*/
|
||||
fun define(key: String, style: Meta?) {
|
||||
if (style == null) {
|
||||
styleMap.remove(key)
|
||||
} else {
|
||||
styleMap[key] = style
|
||||
}
|
||||
owner?.styleChanged(key, oldStyle, style)
|
||||
}
|
||||
|
||||
infix fun String.put(style: Meta?) {
|
||||
set(this, style)
|
||||
operator fun set(key: String, style: Meta?) {
|
||||
val oldStyle = styleMap[key]
|
||||
define(key, style)
|
||||
owner?.styleChanged(key, oldStyle, style)
|
||||
}
|
||||
|
||||
operator fun set(key: String, builder: MetaBuilder.() -> Unit) {
|
||||
|
@ -1,6 +1,7 @@
|
||||
package hep.dataforge.js
|
||||
|
||||
external fun require(name: String): dynamic
|
||||
@JsName("require")
|
||||
external fun requireJS(name: String): dynamic
|
||||
|
||||
inline fun <T : Any> jsObject(builder: T.() -> Unit): T {
|
||||
val obj: T = js("({})") as T
|
||||
|
@ -1,4 +1,4 @@
|
||||
package hep.dataforge.vis.spatial.editor
|
||||
package hep.dataforge.vis.js.editor
|
||||
|
||||
import kotlinx.html.TagConsumer
|
||||
import kotlinx.html.js.div
|
@ -4,7 +4,7 @@ import hep.dataforge.names.NameToken
|
||||
import hep.dataforge.vis.common.VisualGroup
|
||||
import hep.dataforge.vis.common.VisualObject
|
||||
import hep.dataforge.vis.common.isEmpty
|
||||
import hep.dataforge.vis.spatial.editor.card
|
||||
import hep.dataforge.vis.js.editor.card
|
||||
import kotlinx.html.TagConsumer
|
||||
import kotlinx.html.dom.append
|
||||
import kotlinx.html.js.*
|
@ -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.js.editor
|
||||
|
||||
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
|
||||
}
|
||||
}
|
@ -1,17 +1,12 @@
|
||||
package hep.dataforge.vis.spatial.editor
|
||||
package hep.dataforge.vis.js.editor
|
||||
|
||||
import hep.dataforge.io.toJson
|
||||
import hep.dataforge.js.jsObject
|
||||
import hep.dataforge.meta.DynamicMeta
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.meta.builder
|
||||
import hep.dataforge.meta.update
|
||||
import hep.dataforge.vis.common.VisualObject
|
||||
import hep.dataforge.vis.common.findStyle
|
||||
import hep.dataforge.vis.spatial.*
|
||||
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.VisualObject3D.Companion.VISIBLE_KEY
|
||||
import kotlinx.html.dom.append
|
||||
import kotlinx.html.js.div
|
||||
import kotlinx.html.js.h4
|
||||
@ -21,21 +16,13 @@ import kotlin.dom.clear
|
||||
//FIXME something rotten in JS-Meta converter
|
||||
fun Meta.toDynamic() = JSON.parse<dynamic>(toJson().toString())
|
||||
|
||||
|
||||
fun Element.propertyEditor(item: VisualObject?) {
|
||||
//TODO add node descriptor instead of configuring property selector
|
||||
fun Element.propertyEditor(item: VisualObject?, propertySelector: (VisualObject) -> Meta = { it.config }) {
|
||||
clear()
|
||||
if (item != null) {
|
||||
append {
|
||||
card("Properties") {
|
||||
val config: Meta = item.prototype.config
|
||||
val metaToEdit = config.builder().apply {
|
||||
VISIBLE_KEY to (item.visible ?: true)
|
||||
if (item is VisualObject3D) {
|
||||
MATERIAL_COLOR_KEY to (item.color ?: "#ffffff")
|
||||
MATERIAL_OPACITY_KEY to (item.opacity ?: 1.0)
|
||||
}
|
||||
}
|
||||
val dMeta: dynamic = metaToEdit.toDynamic()
|
||||
val dMeta: dynamic = propertySelector(item).toDynamic()
|
||||
val options: JSONEditorOptions = jsObject {
|
||||
mode = "form"
|
||||
onChangeJSON = { item.config.update(DynamicMeta(it.asDynamic())) }
|
||||
@ -48,13 +35,17 @@ fun Element.propertyEditor(item: VisualObject?) {
|
||||
card("Styles") {
|
||||
item.styles.forEach { style ->
|
||||
val styleMeta = item.findStyle(style)
|
||||
h4("container") { +style.toString() }
|
||||
h4("container") { +style }
|
||||
if (styleMeta != null) {
|
||||
div("container").apply {
|
||||
val options: JSONEditorOptions = jsObject {
|
||||
mode = "view"
|
||||
}
|
||||
JSONEditor(this, options, styleMeta.toDynamic())
|
||||
JSONEditor(
|
||||
this,
|
||||
options,
|
||||
styleMeta.toDynamic()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -62,4 +53,4 @@ fun Element.propertyEditor(item: VisualObject?) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package hep.dataforge.vis.fx.values
|
||||
package hep.dataforge.vis.fx.editor
|
||||
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.names.Name
|
||||
@ -44,6 +44,7 @@ class ColorValueChooser : ValueChooserBase<ColorPicker>() {
|
||||
companion object : ValueChooser.Factory {
|
||||
override val name: Name = "color".asName()
|
||||
|
||||
override fun invoke(meta: Meta): ValueChooser = ColorValueChooser()
|
||||
override fun invoke(meta: Meta): ValueChooser =
|
||||
ColorValueChooser()
|
||||
}
|
||||
}
|
@ -3,7 +3,7 @@
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package hep.dataforge.vis.fx.values
|
||||
package hep.dataforge.vis.fx.editor
|
||||
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.meta.get
|
||||
@ -54,7 +54,8 @@ class ComboBoxValueChooser(val values: Collection<Value>? = null) : ValueChooser
|
||||
companion object : ValueChooser.Factory {
|
||||
override val name: Name = "combo".asName()
|
||||
|
||||
override fun invoke(meta: Meta): ValueChooser = ComboBoxValueChooser(meta["values"].value?.list)
|
||||
override fun invoke(meta: Meta): ValueChooser =
|
||||
ComboBoxValueChooser(meta["values"].value?.list)
|
||||
}
|
||||
|
||||
}
|
@ -3,14 +3,13 @@
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package hep.dataforge.vis.fx.meta
|
||||
package hep.dataforge.vis.fx.editor
|
||||
|
||||
import hep.dataforge.context.Global
|
||||
import hep.dataforge.descriptors.NodeDescriptor
|
||||
import hep.dataforge.meta.Config
|
||||
import hep.dataforge.names.NameToken
|
||||
import hep.dataforge.vis.fx.dfIconView
|
||||
import hep.dataforge.vis.fx.values.ValueChooser
|
||||
import javafx.scene.control.*
|
||||
import javafx.scene.control.cell.TextFieldTreeTableCell
|
||||
import javafx.scene.layout.Priority
|
||||
@ -29,8 +28,9 @@ class ConfigEditor(
|
||||
val allowNew: Boolean = true,
|
||||
title: String = "Configuration editor"
|
||||
) : Fragment(title = title, icon = dfIconView) {
|
||||
//TODO replace parameters by properties
|
||||
|
||||
constructor(config: Config, descriptor: NodeDescriptor, title: String = "Configuration editor") :
|
||||
constructor(config: Config, descriptor: NodeDescriptor?, title: String = "Configuration editor") :
|
||||
this(FXMeta.root(config, descriptor = descriptor), title = title)
|
||||
|
||||
override val root = borderpane {
|
@ -1,4 +1,4 @@
|
||||
package hep.dataforge.vis.fx.meta
|
||||
package hep.dataforge.vis.fx.editor
|
||||
|
||||
import hep.dataforge.descriptors.ItemDescriptor
|
||||
import hep.dataforge.descriptors.NodeDescriptor
|
@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package hep.dataforge.vis.fx.meta
|
||||
package hep.dataforge.vis.fx.editor
|
||||
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.vis.fx.dfIconView
|
@ -3,7 +3,7 @@
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package hep.dataforge.vis.fx.values
|
||||
package hep.dataforge.vis.fx.editor
|
||||
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.names.Name
|
||||
@ -103,6 +103,7 @@ class TextValueChooser : ValueChooserBase<TextField>() {
|
||||
|
||||
companion object : ValueChooser.Factory {
|
||||
override val name: Name = "text".asName()
|
||||
override fun invoke(meta: Meta): ValueChooser = TextValueChooser()
|
||||
override fun invoke(meta: Meta): ValueChooser =
|
||||
TextValueChooser()
|
||||
}
|
||||
}
|
@ -3,7 +3,7 @@
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package hep.dataforge.vis.fx.values
|
||||
package hep.dataforge.vis.fx.editor
|
||||
|
||||
import hep.dataforge.values.Value
|
||||
|
@ -3,7 +3,7 @@
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package hep.dataforge.vis.fx.values
|
||||
package hep.dataforge.vis.fx.editor
|
||||
|
||||
import hep.dataforge.context.Context
|
||||
import hep.dataforge.context.Named
|
||||
@ -87,7 +87,10 @@ interface ValueChooser {
|
||||
val widgetType = descriptor.widgetType
|
||||
val chooser: ValueChooser = when {
|
||||
widgetType != null -> {
|
||||
findWidgetByType(context, widgetType)?.invoke(
|
||||
findWidgetByType(
|
||||
context,
|
||||
widgetType
|
||||
)?.invoke(
|
||||
descriptor.widget
|
||||
) ?: TextValueChooser()
|
||||
}
|
||||
@ -105,7 +108,8 @@ interface ValueChooser {
|
||||
descriptor: ValueDescriptor? = null,
|
||||
setter: (Value) -> Unit
|
||||
): ValueChooser {
|
||||
val chooser = build(context, descriptor)
|
||||
val chooser =
|
||||
build(context, descriptor)
|
||||
chooser.setDisplayValue(value.value ?: Null)
|
||||
value.onChange {
|
||||
chooser.setDisplayValue(it ?: Null)
|
||||
@ -115,7 +119,11 @@ interface ValueChooser {
|
||||
setter(result)
|
||||
ValueCallbackResponse(true, result, "OK")
|
||||
} else {
|
||||
ValueCallbackResponse(false, value.value ?: Null, "Not allowed")
|
||||
ValueCallbackResponse(
|
||||
false,
|
||||
value.value ?: Null,
|
||||
"Not allowed"
|
||||
)
|
||||
}
|
||||
}
|
||||
return chooser
|
@ -3,7 +3,7 @@
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package hep.dataforge.vis.fx.values
|
||||
package hep.dataforge.vis.fx.editor
|
||||
|
||||
import hep.dataforge.descriptors.ValueDescriptor
|
||||
import hep.dataforge.values.Null
|
@ -0,0 +1,59 @@
|
||||
package hep.dataforge.vis.fx.editor
|
||||
|
||||
import hep.dataforge.descriptors.NodeDescriptor
|
||||
import hep.dataforge.meta.Config
|
||||
import hep.dataforge.vis.common.VisualObject
|
||||
import hep.dataforge.vis.common.findStyle
|
||||
import javafx.beans.binding.Binding
|
||||
import javafx.beans.property.SimpleObjectProperty
|
||||
import javafx.scene.Node
|
||||
import javafx.scene.Parent
|
||||
import javafx.scene.layout.VBox
|
||||
import tornadofx.*
|
||||
|
||||
class VisualObjectEditorFragment(val selector: (VisualObject) -> Config) : Fragment() {
|
||||
|
||||
val itemProperty = SimpleObjectProperty<VisualObject>()
|
||||
var item: VisualObject? by itemProperty
|
||||
val descriptorProperty = SimpleObjectProperty<NodeDescriptor>()
|
||||
|
||||
constructor(
|
||||
item: VisualObject?,
|
||||
descriptor: NodeDescriptor?,
|
||||
selector: (VisualObject) -> Config = { it.config }
|
||||
) : this(selector) {
|
||||
this.item = item
|
||||
this.descriptorProperty.set(descriptor)
|
||||
}
|
||||
|
||||
private val configProperty: Binding<Config?> = itemProperty.objectBinding {
|
||||
it?.let { selector(it) }
|
||||
}
|
||||
|
||||
private val configEditorProperty: Binding<Node?> = configProperty.objectBinding(descriptorProperty) {
|
||||
it?.let {
|
||||
ConfigEditor(it, descriptorProperty.get()).root
|
||||
}
|
||||
}
|
||||
|
||||
private val styleBoxProperty: Binding<Node?> = configProperty.objectBinding() {
|
||||
VBox().apply {
|
||||
item?.styles?.forEach { styleName ->
|
||||
val styleMeta = item?.findStyle(styleName)
|
||||
if (styleMeta != null) {
|
||||
titledpane(styleName, node = MetaViewer(styleMeta).root)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override val root: Parent = vbox {
|
||||
titledpane("Properties", collapsible = false) {
|
||||
contentProperty().bind(configEditorProperty)
|
||||
}
|
||||
titledpane("Styles", collapsible = false) {
|
||||
visibleWhen(itemProperty.booleanBinding { it?.styles?.isNotEmpty() ?: false })
|
||||
contentProperty().bind(styleBoxProperty)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package hep.dataforge.vis.fx.editor
|
||||
|
||||
import hep.dataforge.vis.common.VisualGroup
|
||||
import hep.dataforge.vis.common.VisualObject
|
||||
import javafx.beans.property.SimpleObjectProperty
|
||||
import javafx.scene.control.SelectionMode
|
||||
import javafx.scene.control.TreeItem
|
||||
import tornadofx.*
|
||||
|
||||
class VisualObjectTreeFragment : Fragment() {
|
||||
val itemProperty = SimpleObjectProperty<VisualObject>()
|
||||
var item: VisualObject? by itemProperty
|
||||
|
||||
val selectedProperty = SimpleObjectProperty<VisualObject>()
|
||||
|
||||
override val root = borderpane{
|
||||
center = titledpane("Object tree") {
|
||||
treeview<VisualObject> {
|
||||
itemProperty.onChange { rootObject ->
|
||||
if (rootObject != null) {
|
||||
root = TreeItem(rootObject)
|
||||
populate { item ->
|
||||
(item.value as? VisualGroup)?.children?.values?.toList()
|
||||
}
|
||||
}
|
||||
}
|
||||
selectionModel.selectionMode = SelectionMode.SINGLE
|
||||
val selectedValue = selectionModel.selectedItemProperty().objectBinding{it?.value}
|
||||
selectedProperty.bind(selectedValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -4,9 +4,9 @@ import hep.dataforge.descriptors.NodeDescriptor
|
||||
import hep.dataforge.meta.buildMeta
|
||||
import hep.dataforge.meta.toConfig
|
||||
import hep.dataforge.values.ValueType
|
||||
import hep.dataforge.vis.fx.meta.ConfigEditor
|
||||
import hep.dataforge.vis.fx.meta.FXMeta
|
||||
import hep.dataforge.vis.fx.meta.MetaViewer
|
||||
import hep.dataforge.vis.fx.editor.ConfigEditor
|
||||
import hep.dataforge.vis.fx.editor.FXMeta
|
||||
import hep.dataforge.vis.fx.editor.MetaViewer
|
||||
import javafx.geometry.Orientation
|
||||
import tornadofx.*
|
||||
|
@ -16,7 +16,7 @@ import scientifik.gdml.*
|
||||
import kotlin.random.Random
|
||||
|
||||
class GDMLTransformer(val root: GDML) {
|
||||
private val materialCache = HashMap<GDMLMaterial, Meta>()
|
||||
//private val materialCache = HashMap<GDMLMaterial, Meta>()
|
||||
private val random = Random(222)
|
||||
|
||||
enum class Action {
|
||||
@ -39,7 +39,7 @@ class GDMLTransformer(val root: GDML) {
|
||||
|
||||
var solidConfiguration: VisualObject3D.(parent: GDMLVolume, solid: GDMLSolid) -> Unit = { _, _ -> }
|
||||
|
||||
fun VisualObject.useStyle(name: String, builder: MetaBuilder.() -> Unit) {
|
||||
fun VisualObject3D.useStyle(name: String, builder: MetaBuilder.() -> Unit) {
|
||||
styleCache.getOrPut(name.toName()) {
|
||||
buildMeta(builder)
|
||||
}
|
||||
@ -69,7 +69,7 @@ class GDMLTransformer(val root: GDML) {
|
||||
final.prototypes = proto
|
||||
styleCache.forEach {
|
||||
final.styleSheet {
|
||||
this[it.key.toString()] = it.value
|
||||
define(it.key.toString(), it.value)
|
||||
}
|
||||
}
|
||||
final.rotationOrder = RotationOrder.ZXY
|
||||
@ -77,4 +77,4 @@ class GDMLTransformer(val root: GDML) {
|
||||
return final
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -256,6 +256,6 @@ fun GDML.toVisual(block: GDMLTransformer.() -> Unit = {}): VisualGroup3D {
|
||||
*/
|
||||
fun VisualGroup3D.gdml(gdml: GDML, key: String = "", transformer: GDMLTransformer.() -> Unit = {}) {
|
||||
val visual = gdml.toVisual(transformer)
|
||||
println(Visual3DPlugin.json.stringify(VisualGroup3D.serializer(), visual))
|
||||
//println(Visual3DPlugin.json.stringify(VisualGroup3D.serializer(), visual))
|
||||
set(key, visual)
|
||||
}
|
File diff suppressed because one or more lines are too long
@ -6,8 +6,13 @@ import scientifik.gdml.GDML
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
|
||||
fun VisualGroup3D.gdml(file: Path, key: String = "", transformer: GDMLTransformer.() -> Unit = {}) {
|
||||
fun GDML.Companion.readFile(file: Path): GDML {
|
||||
val xmlReader = StAXReader(Files.newInputStream(file), "UTF-8")
|
||||
val gdml = GDML.format.parse(GDML.serializer(), xmlReader)
|
||||
return GDML.format.parse(GDML.serializer(), xmlReader)
|
||||
}
|
||||
|
||||
fun VisualGroup3D.gdml(file: Path, key: String = "", transformer: GDMLTransformer.() -> Unit = {}) {
|
||||
val gdml = GDML.readFile(file)
|
||||
gdml(gdml, key, transformer)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@ kotlin {
|
||||
}
|
||||
jsMain {
|
||||
dependencies {
|
||||
api(project(":wrappers"))
|
||||
// api(project(":wrappers"))
|
||||
implementation(npm("three", "0.106.2"))
|
||||
implementation(npm("@hi-level/three-csg", "1.0.6"))
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
package hep.dataforge.vis.spatial.editor
|
||||
package hep.dataforge.vis.spatial.three
|
||||
|
||||
import hep.dataforge.vis.spatial.three.ThreeCanvas
|
||||
import hep.dataforge.vis.js.editor.card
|
||||
import kotlinx.html.InputType
|
||||
import kotlinx.html.dom.append
|
||||
import kotlinx.html.js.div
|
@ -10,6 +10,9 @@ import hep.dataforge.vis.spatial.World.CAMERA_INITIAL_DISTANCE
|
||||
import hep.dataforge.vis.spatial.World.CAMERA_INITIAL_X_ANGLE
|
||||
import hep.dataforge.vis.spatial.World.CAMERA_INITIAL_Y_ANGLE
|
||||
import hep.dataforge.vis.spatial.World.CAMERA_NEAR_CLIP
|
||||
import javafx.application.Platform
|
||||
import javafx.beans.property.ObjectProperty
|
||||
import javafx.beans.property.SimpleObjectProperty
|
||||
import javafx.event.EventHandler
|
||||
import javafx.scene.*
|
||||
import javafx.scene.input.KeyCode
|
||||
@ -80,9 +83,26 @@ class FXCanvas3D(val plugin: FX3DPlugin, meta: Meta = EmptyMeta) :
|
||||
center = canvas
|
||||
}
|
||||
|
||||
val rootObjectProperty: ObjectProperty<VisualObject3D> = SimpleObjectProperty()
|
||||
var rootObject: VisualObject3D? by rootObjectProperty
|
||||
|
||||
private val rootNodeProperty = rootObjectProperty.objectBinding {
|
||||
it?.let { plugin.buildNode(it) }
|
||||
}
|
||||
|
||||
init {
|
||||
canvas.widthProperty().bind(root.widthProperty())
|
||||
canvas.heightProperty().bind(root.heightProperty())
|
||||
rootNodeProperty.addListener { _, oldValue: Node?, newValue: Node? ->
|
||||
Platform.runLater {
|
||||
if (oldValue != null) {
|
||||
world.children.remove(oldValue)
|
||||
}
|
||||
if (newValue != null) {
|
||||
world.children.add(newValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -167,8 +187,7 @@ class FXCanvas3D(val plugin: FX3DPlugin, meta: Meta = EmptyMeta) :
|
||||
}
|
||||
|
||||
override fun render(obj: VisualObject3D, meta: Meta) {
|
||||
val node = plugin.buildNode(obj) ?: kotlin.error("Can't render FX node for object $obj")
|
||||
world.children.add(node)
|
||||
rootObject = obj
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
0
demo/build.gradle.kts
Normal file
0
demo/build.gradle.kts
Normal file
39
demo/gdml/build.gradle.kts
Normal file
39
demo/gdml/build.gradle.kts
Normal file
@ -0,0 +1,39 @@
|
||||
import org.openjfx.gradle.JavaFXOptions
|
||||
|
||||
plugins {
|
||||
id("scientifik.mpp")
|
||||
id("org.openjfx.javafxplugin")
|
||||
id("application")
|
||||
}
|
||||
|
||||
kotlin {
|
||||
|
||||
jvm {
|
||||
withJava()
|
||||
}
|
||||
|
||||
js {
|
||||
browser {
|
||||
webpackTask {
|
||||
sourceMaps = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
commonMain {
|
||||
dependencies {
|
||||
api(project(":dataforge-vis-spatial"))
|
||||
api(project(":dataforge-vis-spatial-gdml"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
application {
|
||||
mainClassName = "hep.dataforge.vis.spatial.gdml.demo.GDMLDemoAppKt"
|
||||
}
|
||||
|
||||
configure<JavaFXOptions> {
|
||||
modules("javafx.controls")
|
||||
}
|
@ -4,13 +4,15 @@ import hep.dataforge.context.Global
|
||||
import hep.dataforge.js.Application
|
||||
import hep.dataforge.js.objectTree
|
||||
import hep.dataforge.js.startApplication
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.meta.builder
|
||||
import hep.dataforge.names.NameToken
|
||||
import hep.dataforge.vis.spatial.*
|
||||
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.Visual3DPlugin
|
||||
import hep.dataforge.vis.spatial.VisualGroup3D
|
||||
import hep.dataforge.vis.spatial.VisualObject3D
|
||||
import hep.dataforge.vis.spatial.editor.propertyEditor
|
||||
import hep.dataforge.vis.spatial.editor.threeOutputConfig
|
||||
import hep.dataforge.vis.spatial.VisualObject3D.Companion.VISIBLE_KEY
|
||||
import hep.dataforge.vis.js.editor.propertyEditor
|
||||
import hep.dataforge.vis.spatial.three.threeOutputConfig
|
||||
import hep.dataforge.vis.spatial.gdml.GDMLTransformer
|
||||
import hep.dataforge.vis.spatial.gdml.LUnit
|
||||
import hep.dataforge.vis.spatial.gdml.toVisual
|
||||
@ -153,7 +155,18 @@ private class GDMLDemoApp : Application {
|
||||
output.camera.layers.set(0)
|
||||
configElement.threeOutputConfig(output)
|
||||
//tree.visualObjectTree(visual, editor::propertyEditor)
|
||||
treeElement.objectTree(NameToken("World"), visual, editorElement::propertyEditor)
|
||||
treeElement.objectTree(NameToken("World"), visual) {
|
||||
editorElement.propertyEditor(it) {item->
|
||||
val config: Meta = item.prototype.config
|
||||
config.builder().apply {
|
||||
VISIBLE_KEY to (item.visible ?: true)
|
||||
if (item is VisualObject3D) {
|
||||
MATERIAL_COLOR_KEY to (item.color ?: "#ffffff")
|
||||
MATERIAL_OPACITY_KEY to (item.opacity ?: 1.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
output.render(visual)
|
6
demo/gdml/src/jsMain/web/css/jsoneditor.min.css
vendored
Normal file
6
demo/gdml/src/jsMain/web/css/jsoneditor.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
@ -0,0 +1,78 @@
|
||||
package hep.dataforge.vis.spatial.gdml.demo
|
||||
|
||||
import hep.dataforge.context.Global
|
||||
import hep.dataforge.vis.fx.editor.VisualObjectEditorFragment
|
||||
import hep.dataforge.vis.fx.editor.VisualObjectTreeFragment
|
||||
import hep.dataforge.vis.spatial.Material3D
|
||||
import hep.dataforge.vis.spatial.fx.FX3DPlugin
|
||||
import hep.dataforge.vis.spatial.fx.FXCanvas3D
|
||||
import hep.dataforge.vis.spatial.gdml.LUnit
|
||||
import hep.dataforge.vis.spatial.gdml.readFile
|
||||
import hep.dataforge.vis.spatial.gdml.toVisual
|
||||
import hep.dataforge.vis.spatial.prototype
|
||||
import javafx.geometry.Orientation
|
||||
import javafx.scene.Parent
|
||||
import javafx.stage.FileChooser
|
||||
import scientifik.gdml.GDML
|
||||
import tornadofx.*
|
||||
|
||||
class GDMLDemoApp : App(GDMLView::class)
|
||||
|
||||
class GDMLView : View() {
|
||||
private val fx3d = Global.plugins.fetch(FX3DPlugin)
|
||||
private val canvas = FXCanvas3D(fx3d)
|
||||
|
||||
private val treeFragment = VisualObjectTreeFragment().apply {
|
||||
this.itemProperty.bind(canvas.rootObjectProperty)
|
||||
}
|
||||
|
||||
private val propertyEditor = VisualObjectEditorFragment { it.prototype.config }.apply {
|
||||
//TODO add descriptor here
|
||||
itemProperty.bind(treeFragment.selectedProperty)
|
||||
}
|
||||
|
||||
|
||||
override val root: Parent = borderpane {
|
||||
top {
|
||||
buttonbar {
|
||||
button("Load GDML") {
|
||||
action {
|
||||
val file = chooseFile("Select a GDML file", filters = gdmlFilter).firstOrNull()
|
||||
if (file != null) {
|
||||
val obj = GDML.readFile(file.toPath()).toVisual {
|
||||
lUnit = LUnit.CM
|
||||
|
||||
solidConfiguration = { parent, solid ->
|
||||
if(solid.name == "cave"){
|
||||
setProperty(Material3D.MATERIAL_WIREFRAME_KEY, true)
|
||||
}
|
||||
if (parent.physVolumes.isNotEmpty()) {
|
||||
useStyle("opaque") {
|
||||
Material3D.MATERIAL_OPACITY_KEY put 0.3
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
canvas.render(obj)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
center {
|
||||
splitpane(Orientation.HORIZONTAL, treeFragment.root, canvas.root, propertyEditor.root) {
|
||||
setDividerPositions(0.2, 0.6, 0.2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val gdmlFilter = arrayOf(
|
||||
FileChooser.ExtensionFilter("GDML", "*.gdml", "*.xml")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun main() {
|
||||
launch<GDMLDemoApp>()
|
||||
}
|
@ -1,12 +1,9 @@
|
||||
package hep.dataforge.vis.spatial.demo
|
||||
|
||||
import hep.dataforge.context.ContextBuilder
|
||||
import hep.dataforge.context.Global
|
||||
import hep.dataforge.js.Application
|
||||
import hep.dataforge.js.startApplication
|
||||
import hep.dataforge.vis.spatial.three.MeshThreeFactory.Companion.EDGES_ENABLED_KEY
|
||||
import hep.dataforge.vis.spatial.three.MeshThreeFactory.Companion.WIREFRAME_ENABLED_KEY
|
||||
import hep.dataforge.vis.spatial.three.ThreePlugin
|
||||
import hep.dataforge.vis.spatial.x
|
||||
import hep.dataforge.vis.spatial.y
|
||||
import kotlinx.coroutines.GlobalScope
|
@ -4,14 +4,11 @@ import hep.dataforge.context.Global
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.meta.buildMeta
|
||||
import hep.dataforge.names.Name
|
||||
import hep.dataforge.names.toName
|
||||
import hep.dataforge.output.OutputManager
|
||||
import hep.dataforge.output.Renderer
|
||||
import hep.dataforge.vis.common.VisualObject
|
||||
import hep.dataforge.vis.spatial.VisualGroup3D
|
||||
import hep.dataforge.vis.spatial.fx.FX3DPlugin
|
||||
import hep.dataforge.vis.spatial.fx.FXCanvas3D
|
||||
import hep.dataforge.vis.spatial.render
|
||||
import javafx.collections.FXCollections
|
||||
import javafx.scene.Parent
|
||||
import javafx.scene.control.Tab
|
@ -27,10 +27,11 @@ rootProject.name = "dataforge-vis"
|
||||
|
||||
include(
|
||||
":dataforge-vis-common",
|
||||
":wrappers",
|
||||
// ":wrappers",
|
||||
":dataforge-vis-spatial",
|
||||
":dataforge-vis-spatial-gdml",
|
||||
":spatial-demo"
|
||||
":demo:spatial-showcase",
|
||||
":demo:gdml"
|
||||
)
|
||||
|
||||
//if(file("../dataforge-core").exists()) {
|
||||
|
Loading…
Reference in New Issue
Block a user