Fix editor glitches

This commit is contained in:
Alexander Nozik 2020-05-16 22:24:29 +03:00
parent 484423a17a
commit ca2b267fc4
8 changed files with 128 additions and 89 deletions

View File

@ -1,3 +1,6 @@
import scientifik.useFx
import scientifik.useSerialization
val dataforgeVersion by extra("0.1.8-dev-2")
plugins {
@ -33,5 +36,5 @@ subprojects {
apply(plugin = "scientifik.publish")
}
useSerialization()
useFx(FXModule.CONTROLS, version = fxVersion)
useFx(scientifik.FXModule.CONTROLS, version = fxVersion)
}

View File

@ -7,6 +7,7 @@ import hep.dataforge.vis.VisualGroup
import hep.dataforge.vis.VisualObject
import hep.dataforge.vis.bootstrap.*
import hep.dataforge.vis.react.component
import hep.dataforge.vis.react.flexColumn
import hep.dataforge.vis.react.state
import hep.dataforge.vis.spatial.VisualGroup3D
import hep.dataforge.vis.spatial.VisualObject3D
@ -16,12 +17,18 @@ import hep.dataforge.vis.spatial.specifications.Canvas
import hep.dataforge.vis.spatial.three.ThreeCanvas
import hep.dataforge.vis.spatial.three.ThreeCanvasComponent
import hep.dataforge.vis.spatial.three.canvasControls
import kotlinx.css.FlexBasis
import kotlinx.css.Overflow
import kotlinx.css.flex
import kotlinx.css.overflow
import org.w3c.files.FileReader
import org.w3c.files.get
import react.RProps
import react.dom.h1
import scientifik.gdml.GDML
import scientifik.gdml.parse
import styled.css
import styled.styledDiv
import kotlin.browser.window
import kotlin.math.PI
@ -63,8 +70,16 @@ val GDMLApp = component<GDMLAppProps> { props ->
}
flexColumn {
css {
flex(1.0, 1.0, FlexBasis.auto)
}
h1 { +"GDML/JSON loader demo" }
gridRow {
styledDiv {
css {
classes.add("row")
classes.add("p-1")
overflow = Overflow.auto
}
gridColumn(3) {
card("Load data") {
fileDrop("(drag file here)") { files ->
@ -82,7 +97,7 @@ val GDMLApp = component<GDMLAppProps> { props ->
}
}
//tree
card("Object tree") {
card("Object tree", "overflow-auto") {
visual?.let {
objectTree(it, selected, select)
}
@ -106,7 +121,7 @@ val GDMLApp = component<GDMLAppProps> { props ->
}
}
gridColumn(3) {
gridRow {
container {
//settings
canvas?.let {
card("Canvas configuration") {
@ -114,10 +129,10 @@ val GDMLApp = component<GDMLAppProps> { props ->
}
}
}
gridRow {
container {
namecrumbs(selected, "World") { selected = it }
}
gridRow {
container {
//properties
card("Properties") {
selected.let { selected ->

View File

@ -8,7 +8,6 @@ import hep.dataforge.vis.spatial.gdml.GDMLTransformer
import hep.dataforge.vis.spatial.gdml.LUnit
import hep.dataforge.vis.spatial.gdml.toVisual
import react.child
import react.dom.div
import react.dom.render
import kotlin.browser.document
@ -47,7 +46,6 @@ private class GDMLDemoApp : Application {
val element = document.getElementById("app") ?: error("Element with id 'app' not found on page")
render(element) {
div("h-100") {
child(GDMLApp) {
attrs {
this.context = context
@ -55,7 +53,6 @@ private class GDMLDemoApp : Application {
}
}
}
}
// (document.getElementById("file_load_button") as? HTMLInputElement)?.apply {
// addEventListener("change", {
// (it.target as HTMLInputElement).files?.asList()?.first()?.let { file ->

View File

@ -19,8 +19,8 @@ inline fun TagConsumer<HTMLElement>.card(title: String, crossinline block: TagCo
}
}
inline fun RBuilder.card(title: String, crossinline block: RBuilder.() -> Unit) {
div("card w-100") {
inline fun RBuilder.card(title: String, classes: String? = null, crossinline block: RBuilder.() -> Unit) {
div("card w-100 $classes") {
div("card-body") {
h3(classes = "card-title") {
+title
@ -166,12 +166,6 @@ fun RBuilder.accordion(id: String, builder: RAccordionBuilder.() -> Unit): React
fun joinStyles(vararg styles: String?) = styles.joinToString(separator = " ") { it ?: "" }
inline fun RBuilder.flexColumn(classes: String? = null, block: RDOMBuilder<DIV>.() -> Unit) =
div(joinStyles(classes, "d-flex flex-column"), block)
inline fun RBuilder.flexRow(classes: String? = null, block: RDOMBuilder<DIV>.() -> Unit) =
div(joinStyles(classes, "d-flex flex-row"), block)
enum class ContainerSize(val suffix: String) {
DEFAULT(""),
SM("-sm"),

View File

@ -8,13 +8,17 @@ import hep.dataforge.names.plus
import hep.dataforge.values.Value
import hep.dataforge.vis.react.RFBuilder
import hep.dataforge.vis.react.component
import hep.dataforge.vis.react.flexRow
import hep.dataforge.vis.react.state
import kotlinx.css.*
import kotlinx.html.classes
import kotlinx.html.js.onClickFunction
import org.w3c.dom.Element
import org.w3c.dom.events.Event
import react.*
import react.dom.*
import styled.css
import styled.styledDiv
interface ConfigEditorItemProps : RProps {
@ -132,9 +136,15 @@ private fun RFBuilder.configEditorItem(props: ConfigEditorItemProps) {
}
}
is MetaItem.ValueItem -> {
div {
div("row form-group") {
div("col d-inline-flex") {
flexRow {
css {
alignItems = Align.center
justifyContent= JustifyContent.flexEnd
}
styledDiv {
css{
flexGrow = 1.0
}
span("tree-label align-self-center") {
+token
attrs {
@ -144,7 +154,7 @@ private fun RFBuilder.configEditorItem(props: ConfigEditorItemProps) {
}
}
}
div("col-6 d-inline-flex") {
styledDiv {
valueChooser(
props.name,
actualItem,
@ -152,7 +162,10 @@ private fun RFBuilder.configEditorItem(props: ConfigEditorItemProps) {
valueChanged
)
}
div("col-auto d-inline-flex p-1") {
styledDiv {
css {
flexShrink = 1.0
}
button(classes = "btn btn-link align-self-center") {
+"\u00D7"
attrs {
@ -167,7 +180,6 @@ private fun RFBuilder.configEditorItem(props: ConfigEditorItemProps) {
}
}
}
}
}
interface ConfigEditorProps : RProps {
@ -176,6 +188,7 @@ interface ConfigEditorProps : RProps {
var default: Meta?
var descriptor: NodeDescriptor?
}
val ConfigEditor = component<ConfigEditorProps> { props ->
child(ConfigEditorItem) {
attrs {
@ -212,7 +225,12 @@ fun RBuilder.configEditor(config: Config, descriptor: NodeDescriptor? = null, de
}
}
fun RBuilder.configEditor(obj: Configurable, descriptor: NodeDescriptor? = obj.descriptor, default: Meta? = null, key: Any? = null) {
fun RBuilder.configEditor(
obj: Configurable,
descriptor: NodeDescriptor? = obj.descriptor,
default: Meta? = null,
key: Any? = null
) {
child(ConfigEditor) {
attrs {
this.key = key?.toString() ?: ""

View File

@ -1,10 +1,7 @@
package hep.dataforge.vis.bootstrap
import hep.dataforge.meta.MetaItem
import hep.dataforge.meta.*
import hep.dataforge.meta.descriptors.ValueDescriptor
import hep.dataforge.meta.get
import hep.dataforge.meta.string
import hep.dataforge.meta.value
import hep.dataforge.names.Name
import hep.dataforge.values.*
import hep.dataforge.vis.Colors
@ -16,12 +13,8 @@ import org.w3c.dom.HTMLElement
import org.w3c.dom.HTMLInputElement
import org.w3c.dom.HTMLSelectElement
import org.w3c.dom.events.Event
import org.w3c.dom.events.KeyboardEvent
import react.*
import react.dom.div
import react.dom.input
import react.dom.option
import react.dom.select
import react.dom.*
interface ValueChooserProps : RProps {
var item: MetaItem<*>?
@ -30,17 +23,12 @@ interface ValueChooserProps : RProps {
}
interface ValueChooserState : RState {
var value: Value?
var rawInput: Boolean?
}
class ValueChooserComponent(props: ValueChooserProps) : RComponent<ValueChooserProps, ValueChooserState>(props) {
private val element = createRef<HTMLElement>()
override fun ValueChooserState.init(props: ValueChooserProps) {
value = props.item.value
}
private fun getValue(): Value? {
val element = element.current ?: return null//state.element ?: return null
return when (element) {
@ -54,24 +42,13 @@ class ValueChooserComponent(props: ValueChooserProps) : RComponent<ValueChooserP
}
}
private val valueChanged: (Event) -> Unit = { _ ->
setState {
value = getValue()
}
}
private val valueChangeAndCommit: (Event) -> Unit = { event ->
val res = getValue()
setState {
value = res
}
props.valueChanged?.invoke(res)
private val commit: (Event) -> Unit = { event ->
props.valueChanged?.invoke(getValue())
}
private val keyDown: (Event) -> Unit = { event ->
if (event is KeyboardEvent && event.key == "Enter") {
props.valueChanged?.invoke(getValue())
if (event.type == "keydown" && event.asDynamic().key == "Enter") {
commit(event)
}
}
@ -83,11 +60,11 @@ class ValueChooserComponent(props: ValueChooserProps) : RComponent<ValueChooserP
override fun componentDidUpdate(prevProps: ValueChooserProps, prevState: ValueChooserState, snapshot: Any) {
(element.current as? HTMLInputElement)?.let { element ->
if (element.type == "checkbox") {
element.checked = state.value?.boolean ?: false
element.defaultChecked = props.item?.boolean ?: false
} else {
element.value = state.value?.string ?: ""
element.defaultValue = props.item?.string ?: ""
}
element.indeterminate = state.value == null
element.indeterminate = props.item == null
}
// (state.element as? HTMLSelectElement)?.let { element ->
// state.value?.let { element.value = it.string }
@ -96,8 +73,7 @@ class ValueChooserComponent(props: ValueChooserProps) : RComponent<ValueChooserP
private fun RBuilder.stringInput() = input(type = InputType.text) {
attrs {
this.value = state.value?.string ?: ""
onChangeFunction = valueChanged
this.defaultValue = props.item?.string ?: ""
onKeyDownFunction = keyDown
}
ref = element
@ -112,19 +88,19 @@ class ValueChooserComponent(props: ValueChooserProps) : RComponent<ValueChooserP
descriptor?.widgetType == "color" -> input(type = InputType.color) {
ref = element
attrs {
this.value = state.value?.let { value ->
this.defaultValue = props.item?.value?.let { value ->
if (value.type == ValueType.NUMBER) Colors.rgbToString(value.int)
else value.string
} ?: "#000000"
onChangeFunction = valueChangeAndCommit
onChangeFunction = commit
}
}
type == ValueType.BOOLEAN -> {
input(type = InputType.checkBox) {
ref = element
attrs {
checked = state.value?.boolean ?: false
onChangeFunction = valueChangeAndCommit
defaultChecked = props.item?.boolean ?: false
onChangeFunction = commit
}
}
}
@ -140,8 +116,7 @@ class ValueChooserComponent(props: ValueChooserProps) : RComponent<ValueChooserP
descriptor.attributes["max"].string?.let {
max = it
}
this.value = state.value?.string ?: ""
onChangeFunction = valueChanged
defaultValue = props.item?.string ?: ""
onKeyDownFunction = keyDown
}
}
@ -153,9 +128,9 @@ class ValueChooserComponent(props: ValueChooserProps) : RComponent<ValueChooserP
}
ref = element
attrs {
this.value = state.value?.string ?: ""
this.value = props.item?.string ?: ""
multiple = false
onChangeFunction = valueChangeAndCommit
onChangeFunction = commit
}
}
else -> stringInput()

View File

@ -1,3 +1,11 @@
/*full height*/
html, body {
height: 100%;
width: 100%;
}
.container-fluid { height: inherit; }
/* Remove default bullets */
ul, .tree {
list-style-type: none;

View File

@ -0,0 +1,29 @@
package hep.dataforge.vis.react
import kotlinx.css.Display
import kotlinx.css.FlexDirection
import kotlinx.css.display
import kotlinx.css.flexDirection
import kotlinx.html.DIV
import react.RBuilder
import styled.StyledDOMBuilder
import styled.css
import styled.styledDiv
inline fun RBuilder.flexColumn(block: StyledDOMBuilder<DIV>.() -> Unit) =
styledDiv {
css {
display = Display.flex
flexDirection = FlexDirection.column
}
block()
}
inline fun RBuilder.flexRow(block: StyledDOMBuilder<DIV>.() -> Unit) =
styledDiv {
css {
display = Display.flex
flexDirection = FlexDirection.row
}
block()
}