forked from kscience/visionforge
UI tune-up
This commit is contained in:
parent
62a6eafdeb
commit
de2ef1dcc5
@ -19,7 +19,7 @@ allprojects {
|
|||||||
}
|
}
|
||||||
|
|
||||||
group = "hep.dataforge"
|
group = "hep.dataforge"
|
||||||
version = "0.1.5-dev"
|
version = "0.1.5-dev-2"
|
||||||
}
|
}
|
||||||
|
|
||||||
val githubProject by extra("visionforge")
|
val githubProject by extra("visionforge")
|
||||||
|
@ -7,10 +7,7 @@ import hep.dataforge.vision.Vision
|
|||||||
import hep.dataforge.vision.VisionGroup
|
import hep.dataforge.vision.VisionGroup
|
||||||
import hep.dataforge.vision.bootstrap.*
|
import hep.dataforge.vision.bootstrap.*
|
||||||
import hep.dataforge.vision.gdml.toVision
|
import hep.dataforge.vision.gdml.toVision
|
||||||
import hep.dataforge.vision.react.component
|
import hep.dataforge.vision.react.*
|
||||||
import hep.dataforge.vision.react.configEditor
|
|
||||||
import hep.dataforge.vision.react.flexColumn
|
|
||||||
import hep.dataforge.vision.react.state
|
|
||||||
import hep.dataforge.vision.solid.Solid
|
import hep.dataforge.vision.solid.Solid
|
||||||
import hep.dataforge.vision.solid.SolidGroup
|
import hep.dataforge.vision.solid.SolidGroup
|
||||||
import hep.dataforge.vision.solid.specifications.Camera
|
import hep.dataforge.vision.solid.specifications.Camera
|
||||||
@ -98,7 +95,7 @@ val GDMLApp = component<GDMLAppProps> { props ->
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
//tree
|
//tree
|
||||||
card("Object tree", "overflow-auto") {
|
card("Object tree") {
|
||||||
visual?.let {
|
visual?.let {
|
||||||
objectTree(it, selected, select)
|
objectTree(it, selected, select)
|
||||||
}
|
}
|
||||||
|
@ -6,9 +6,9 @@ import hep.dataforge.names.NameToken
|
|||||||
import hep.dataforge.names.isEmpty
|
import hep.dataforge.names.isEmpty
|
||||||
import hep.dataforge.vision.Vision
|
import hep.dataforge.vision.Vision
|
||||||
import hep.dataforge.vision.bootstrap.card
|
import hep.dataforge.vision.bootstrap.card
|
||||||
import hep.dataforge.vision.bootstrap.objectTree
|
|
||||||
import hep.dataforge.vision.react.component
|
import hep.dataforge.vision.react.component
|
||||||
import hep.dataforge.vision.react.configEditor
|
import hep.dataforge.vision.react.configEditor
|
||||||
|
import hep.dataforge.vision.react.objectTree
|
||||||
import hep.dataforge.vision.react.state
|
import hep.dataforge.vision.react.state
|
||||||
import hep.dataforge.vision.solid.specifications.Camera
|
import hep.dataforge.vision.solid.specifications.Camera
|
||||||
import hep.dataforge.vision.solid.specifications.Canvas3DOptions
|
import hep.dataforge.vision.solid.specifications.Canvas3DOptions
|
||||||
|
@ -2,8 +2,8 @@ import hep.dataforge.context.Global
|
|||||||
import hep.dataforge.js.Application
|
import hep.dataforge.js.Application
|
||||||
import hep.dataforge.js.startApplication
|
import hep.dataforge.js.startApplication
|
||||||
import hep.dataforge.names.Name
|
import hep.dataforge.names.Name
|
||||||
import hep.dataforge.vision.bootstrap.objectTree
|
|
||||||
import hep.dataforge.vision.bootstrap.visualPropertyEditor
|
import hep.dataforge.vision.bootstrap.visualPropertyEditor
|
||||||
|
import hep.dataforge.vision.react.objectTree
|
||||||
import hep.dataforge.vision.solid.Point3D
|
import hep.dataforge.vision.solid.Point3D
|
||||||
import hep.dataforge.vision.solid.SolidGroup
|
import hep.dataforge.vision.solid.SolidGroup
|
||||||
import hep.dataforge.vision.solid.box
|
import hep.dataforge.vision.solid.box
|
||||||
|
@ -7,11 +7,8 @@ import hep.dataforge.names.NameToken
|
|||||||
import kotlinx.html.classes
|
import kotlinx.html.classes
|
||||||
import kotlinx.html.js.onClickFunction
|
import kotlinx.html.js.onClickFunction
|
||||||
import org.w3c.dom.events.Event
|
import org.w3c.dom.events.Event
|
||||||
import react.RBuilder
|
import react.*
|
||||||
import react.RComponent
|
|
||||||
import react.RProps
|
|
||||||
import react.dom.*
|
import react.dom.*
|
||||||
import react.setState
|
|
||||||
|
|
||||||
interface MetaViewerProps : RProps {
|
interface MetaViewerProps : RProps {
|
||||||
var name: NameToken
|
var name: NameToken
|
||||||
@ -19,6 +16,12 @@ interface MetaViewerProps : RProps {
|
|||||||
var descriptor: NodeDescriptor?
|
var descriptor: NodeDescriptor?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
interface TreeState : RState {
|
||||||
|
var expanded: Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated("To be replaced by react functional component")
|
||||||
class MetaViewerComponent : RComponent<MetaViewerProps, TreeState>() {
|
class MetaViewerComponent : RComponent<MetaViewerProps, TreeState>() {
|
||||||
|
|
||||||
override fun TreeState.init() {
|
override fun TreeState.init() {
|
||||||
|
@ -2,12 +2,16 @@ package hep.dataforge.vision.bootstrap
|
|||||||
|
|
||||||
import hep.dataforge.names.Name
|
import hep.dataforge.names.Name
|
||||||
import hep.dataforge.names.NameToken
|
import hep.dataforge.names.NameToken
|
||||||
|
import hep.dataforge.vision.Vision
|
||||||
|
import hep.dataforge.vision.react.ObjectTree
|
||||||
import kotlinx.html.*
|
import kotlinx.html.*
|
||||||
import kotlinx.html.js.div
|
import kotlinx.html.js.div
|
||||||
import kotlinx.html.js.onClickFunction
|
import kotlinx.html.js.onClickFunction
|
||||||
|
import org.w3c.dom.Element
|
||||||
import org.w3c.dom.HTMLElement
|
import org.w3c.dom.HTMLElement
|
||||||
import react.RBuilder
|
import react.RBuilder
|
||||||
import react.ReactElement
|
import react.ReactElement
|
||||||
|
import react.child
|
||||||
import react.dom.*
|
import react.dom.*
|
||||||
|
|
||||||
inline fun TagConsumer<HTMLElement>.card(title: String, crossinline block: TagConsumer<HTMLElement>.() -> Unit) {
|
inline fun TagConsumer<HTMLElement>.card(title: String, crossinline block: TagConsumer<HTMLElement>.() -> Unit) {
|
||||||
@ -206,3 +210,19 @@ inline fun RBuilder.gridRow(
|
|||||||
): ReactElement {
|
): ReactElement {
|
||||||
return div(joinStyles(classes, "row"), block)
|
return div(joinStyles(classes, "row"), block)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Element.renderObjectTree(
|
||||||
|
vision: Vision,
|
||||||
|
clickCallback: (Name) -> Unit = {}
|
||||||
|
) = render(this) {
|
||||||
|
card("Object tree") {
|
||||||
|
child(ObjectTree) {
|
||||||
|
attrs {
|
||||||
|
this.name = Name.EMPTY
|
||||||
|
this.obj = vision
|
||||||
|
this.selected = null
|
||||||
|
this.clickCallback = clickCallback
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -6,13 +6,10 @@ import hep.dataforge.names.Name
|
|||||||
import hep.dataforge.names.NameToken
|
import hep.dataforge.names.NameToken
|
||||||
import hep.dataforge.names.plus
|
import hep.dataforge.names.plus
|
||||||
import hep.dataforge.values.Value
|
import hep.dataforge.values.Value
|
||||||
import kotlinx.css.*
|
|
||||||
import kotlinx.css.properties.TextDecoration
|
|
||||||
import kotlinx.html.js.onClickFunction
|
import kotlinx.html.js.onClickFunction
|
||||||
import org.w3c.dom.Element
|
import org.w3c.dom.Element
|
||||||
import org.w3c.dom.events.Event
|
import org.w3c.dom.events.Event
|
||||||
import react.*
|
import react.*
|
||||||
import react.dom.div
|
|
||||||
import react.dom.render
|
import react.dom.render
|
||||||
import styled.*
|
import styled.*
|
||||||
|
|
||||||
@ -86,7 +83,10 @@ private fun RFBuilder.configEditorItem(props: ConfigEditorItemProps) {
|
|||||||
|
|
||||||
when (actualItem) {
|
when (actualItem) {
|
||||||
is MetaItem.NodeItem -> {
|
is MetaItem.NodeItem -> {
|
||||||
div {
|
styledDiv {
|
||||||
|
css {
|
||||||
|
+TreeStyles.treeLeaf
|
||||||
|
}
|
||||||
styledSpan {
|
styledSpan {
|
||||||
css {
|
css {
|
||||||
+TreeStyles.treeCaret
|
+TreeStyles.treeCaret
|
||||||
@ -145,15 +145,14 @@ private fun RFBuilder.configEditorItem(props: ConfigEditorItemProps) {
|
|||||||
styledDiv {
|
styledDiv {
|
||||||
css {
|
css {
|
||||||
+TreeStyles.treeLeaf
|
+TreeStyles.treeLeaf
|
||||||
justifyContent = JustifyContent.flexEnd
|
// justifyContent = JustifyContent.flexEnd
|
||||||
}
|
}
|
||||||
styledDiv {
|
styledDiv {
|
||||||
css {
|
css {
|
||||||
flexGrow = 1.0
|
+TreeStyles.treeLabel
|
||||||
}
|
}
|
||||||
styledSpan {
|
styledSpan {
|
||||||
css {
|
css {
|
||||||
+TreeStyles.treeLabel
|
|
||||||
if (item == null) {
|
if (item == null) {
|
||||||
+TreeStyles.treeLabelInactive
|
+TreeStyles.treeLabelInactive
|
||||||
}
|
}
|
||||||
@ -162,6 +161,9 @@ private fun RFBuilder.configEditorItem(props: ConfigEditorItemProps) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
styledDiv {
|
styledDiv {
|
||||||
|
css {
|
||||||
|
+TreeStyles.resizeableInput
|
||||||
|
}
|
||||||
valueChooser(
|
valueChooser(
|
||||||
props.name,
|
props.name,
|
||||||
actualItem,
|
actualItem,
|
||||||
@ -169,37 +171,20 @@ private fun RFBuilder.configEditorItem(props: ConfigEditorItemProps) {
|
|||||||
valueChanged
|
valueChanged
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
styledDiv {
|
styledButton {
|
||||||
css {
|
css {
|
||||||
flexShrink = 1.0
|
+TreeStyles.removeButton
|
||||||
}
|
}
|
||||||
styledButton {
|
+"\u00D7"
|
||||||
css {
|
attrs {
|
||||||
backgroundColor = Color.white
|
if (item == null) {
|
||||||
borderStyle = BorderStyle.solid
|
disabled = true
|
||||||
borderRadius = 2.px
|
} else {
|
||||||
padding(1.px, 5.px)
|
onClickFunction = removeClick
|
||||||
marginLeft = 4.px
|
|
||||||
textAlign = TextAlign.center
|
|
||||||
textDecoration = TextDecoration.none
|
|
||||||
display = Display.inlineBlock
|
|
||||||
cursor = Cursor.pointer
|
|
||||||
disabled {
|
|
||||||
cursor = Cursor.auto
|
|
||||||
borderStyle = BorderStyle.dashed
|
|
||||||
color = Color.lightGray
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+"\u00D7"
|
|
||||||
attrs {
|
|
||||||
if (item == null) {
|
|
||||||
disabled = true
|
|
||||||
} else {
|
|
||||||
onClickFunction = removeClick
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package hep.dataforge.vision.bootstrap
|
package hep.dataforge.vision.react
|
||||||
|
|
||||||
import hep.dataforge.names.Name
|
import hep.dataforge.names.Name
|
||||||
import hep.dataforge.names.plus
|
import hep.dataforge.names.plus
|
||||||
@ -6,14 +6,10 @@ import hep.dataforge.names.startsWith
|
|||||||
import hep.dataforge.vision.Vision
|
import hep.dataforge.vision.Vision
|
||||||
import hep.dataforge.vision.VisionGroup
|
import hep.dataforge.vision.VisionGroup
|
||||||
import hep.dataforge.vision.isEmpty
|
import hep.dataforge.vision.isEmpty
|
||||||
import hep.dataforge.vision.react.RFBuilder
|
|
||||||
import hep.dataforge.vision.react.component
|
|
||||||
import kotlinx.html.classes
|
|
||||||
import kotlinx.html.js.onClickFunction
|
import kotlinx.html.js.onClickFunction
|
||||||
import org.w3c.dom.Element
|
|
||||||
import org.w3c.dom.events.Event
|
import org.w3c.dom.events.Event
|
||||||
import react.*
|
import react.*
|
||||||
import react.dom.*
|
import styled.*
|
||||||
|
|
||||||
interface ObjectTreeProps : RProps {
|
interface ObjectTreeProps : RProps {
|
||||||
var name: Name
|
var name: Name
|
||||||
@ -22,24 +18,25 @@ interface ObjectTreeProps : RProps {
|
|||||||
var clickCallback: (Name) -> Unit
|
var clickCallback: (Name) -> Unit
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TreeState : RState {
|
|
||||||
var expanded: Boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun RFBuilder.objectTree(props: ObjectTreeProps): Unit {
|
private fun RFBuilder.objectTree(props: ObjectTreeProps): Unit {
|
||||||
var expanded: Boolean by useState{ props.selected?.startsWith(props.name) ?: false }
|
var expanded: Boolean by useState { props.selected?.startsWith(props.name) ?: false }
|
||||||
|
|
||||||
val onClick: (Event) -> Unit = {
|
val onClick: (Event) -> Unit = {
|
||||||
expanded = !expanded
|
expanded = !expanded
|
||||||
}
|
}
|
||||||
|
|
||||||
fun RBuilder.treeLabel(text: String) {
|
fun RBuilder.treeLabel(text: String) {
|
||||||
button(classes = "btn btn-link align-middle tree-label p-0") {
|
styledButton {
|
||||||
|
css {
|
||||||
|
//classes = mutableListOf("btn", "btn-link", "align-middle", "text-truncate", "p-0")
|
||||||
|
+TreeStyles.treeLabel
|
||||||
|
+TreeStyles.linkButton
|
||||||
|
if (props.name == props.selected) {
|
||||||
|
+TreeStyles.treeLabelSelected
|
||||||
|
}
|
||||||
|
}
|
||||||
+text
|
+text
|
||||||
attrs {
|
attrs {
|
||||||
if (props.name == props.selected) {
|
|
||||||
classes += "tree-label-selected"
|
|
||||||
}
|
|
||||||
onClickFunction = { props.clickCallback(props.name) }
|
onClickFunction = { props.clickCallback(props.name) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -50,13 +47,19 @@ private fun RFBuilder.objectTree(props: ObjectTreeProps): Unit {
|
|||||||
|
|
||||||
//display as node if any child is visible
|
//display as node if any child is visible
|
||||||
if (obj is VisionGroup) {
|
if (obj is VisionGroup) {
|
||||||
div("d-block text-truncate") {
|
styledDiv {
|
||||||
|
css {
|
||||||
|
+TreeStyles.treeLeaf
|
||||||
|
}
|
||||||
if (obj.children.any { !it.key.body.startsWith("@") }) {
|
if (obj.children.any { !it.key.body.startsWith("@") }) {
|
||||||
span("tree-caret") {
|
styledSpan {
|
||||||
attrs {
|
css {
|
||||||
|
+TreeStyles.treeCaret
|
||||||
if (expanded) {
|
if (expanded) {
|
||||||
classes += "tree-caret-down"
|
+TreeStyles.treeCaredDown
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
attrs {
|
||||||
onClickFunction = onClick
|
onClickFunction = onClick
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -64,12 +67,18 @@ private fun RFBuilder.objectTree(props: ObjectTreeProps): Unit {
|
|||||||
treeLabel(token)
|
treeLabel(token)
|
||||||
}
|
}
|
||||||
if (expanded) {
|
if (expanded) {
|
||||||
ul("tree") {
|
styledUl {
|
||||||
|
css {
|
||||||
|
+TreeStyles.tree
|
||||||
|
}
|
||||||
obj.children.entries
|
obj.children.entries
|
||||||
.filter { !it.key.toString().startsWith("@") } // ignore statics and other hidden children
|
.filter { !it.key.toString().startsWith("@") } // ignore statics and other hidden children
|
||||||
.sortedBy { (it.value as? VisionGroup)?.isEmpty ?: true }
|
.sortedBy { (it.value as? VisionGroup)?.isEmpty ?: true } // ignore empty groups
|
||||||
.forEach { (childToken, child) ->
|
.forEach { (childToken, child) ->
|
||||||
li("tree-item") {
|
styledLi {
|
||||||
|
css {
|
||||||
|
+TreeStyles.treeItem
|
||||||
|
}
|
||||||
child(ObjectTree) {
|
child(ObjectTree) {
|
||||||
attrs {
|
attrs {
|
||||||
this.name = props.name + childToken
|
this.name = props.name + childToken
|
||||||
@ -83,8 +92,10 @@ private fun RFBuilder.objectTree(props: ObjectTreeProps): Unit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
div("d-block text-truncate") {
|
styledDiv {
|
||||||
span("tree-leaf") {}
|
css {
|
||||||
|
+TreeStyles.treeLeaf
|
||||||
|
}
|
||||||
treeLabel(token)
|
treeLabel(token)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -94,22 +105,6 @@ val ObjectTree: FunctionalComponent<ObjectTreeProps> = component { props ->
|
|||||||
objectTree(props)
|
objectTree(props)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Element.renderObjectTree(
|
|
||||||
vision: Vision,
|
|
||||||
clickCallback: (Name) -> Unit = {}
|
|
||||||
) = render(this) {
|
|
||||||
card("Object tree") {
|
|
||||||
child(ObjectTree) {
|
|
||||||
attrs {
|
|
||||||
this.name = Name.EMPTY
|
|
||||||
this.obj = vision
|
|
||||||
this.selected = null
|
|
||||||
this.clickCallback = clickCallback
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun RBuilder.objectTree(
|
fun RBuilder.objectTree(
|
||||||
vision: Vision,
|
vision: Vision,
|
||||||
selected: Name? = null,
|
selected: Name? = null,
|
@ -1,8 +1,7 @@
|
|||||||
package hep.dataforge.vision.react
|
package hep.dataforge.vision.react
|
||||||
|
|
||||||
import kotlinx.css.*
|
import kotlinx.css.*
|
||||||
import kotlinx.css.properties.deg
|
import kotlinx.css.properties.*
|
||||||
import kotlinx.css.properties.rotate
|
|
||||||
import styled.StyleSheet
|
import styled.StyleSheet
|
||||||
|
|
||||||
object TreeStyles : StyleSheet("treeStyles", true) {
|
object TreeStyles : StyleSheet("treeStyles", true) {
|
||||||
@ -30,22 +29,6 @@ object TreeStyles : StyleSheet("treeStyles", true) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val treeItem by css {
|
|
||||||
alignItems = Align.center
|
|
||||||
paddingLeft = 10.px
|
|
||||||
borderLeftStyle = BorderStyle.dashed
|
|
||||||
borderLeftWidth = 1.px
|
|
||||||
borderLeftColor = Color.lightGray
|
|
||||||
}
|
|
||||||
|
|
||||||
val treeLeaf by css {
|
|
||||||
display = Display.flex
|
|
||||||
flexDirection = FlexDirection.row
|
|
||||||
userSelect = UserSelect.none
|
|
||||||
alignItems = Align.center
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rotate the caret/arrow icon when clicked on (using JavaScript)
|
* Rotate the caret/arrow icon when clicked on (using JavaScript)
|
||||||
*/
|
*/
|
||||||
@ -59,8 +42,27 @@ object TreeStyles : StyleSheet("treeStyles", true) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val treeItem by css {
|
||||||
|
alignItems = Align.center
|
||||||
|
paddingLeft = 10.px
|
||||||
|
borderLeftStyle = BorderStyle.dashed
|
||||||
|
borderLeftWidth = 1.px
|
||||||
|
borderLeftColor = Color.lightGray
|
||||||
|
borderBottomStyle = BorderStyle.dashed
|
||||||
|
borderBottomWidth = 1.px
|
||||||
|
borderBottomColor = Color.lightGray
|
||||||
|
}
|
||||||
|
|
||||||
|
val treeLeaf by css {
|
||||||
|
display = Display.flex
|
||||||
|
flexDirection = FlexDirection.row
|
||||||
|
flexWrap = FlexWrap.nowrap
|
||||||
|
//alignItems = Align.center
|
||||||
|
}
|
||||||
|
|
||||||
val treeLabel by css {
|
val treeLabel by css {
|
||||||
overflow = Overflow.hidden
|
overflow = Overflow.hidden
|
||||||
|
flex(flexGrow = 1.0, flexShrink = 1.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
val treeLabelInactive by css {
|
val treeLabelInactive by css {
|
||||||
@ -71,4 +73,49 @@ object TreeStyles : StyleSheet("treeStyles", true) {
|
|||||||
backgroundColor = Color.lightBlue
|
backgroundColor = Color.lightBlue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val linkButton by css {
|
||||||
|
backgroundColor = Color.white
|
||||||
|
border = "none"
|
||||||
|
padding(left = 4.pt, right = 4.pt, top = 0.pt, bottom = 0.pt)
|
||||||
|
textAlign = TextAlign.left
|
||||||
|
fontFamily = "arial,sans-serif"
|
||||||
|
color = Color("#069")
|
||||||
|
cursor = Cursor.pointer
|
||||||
|
hover {
|
||||||
|
textDecoration(TextDecorationLine.underline)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val removeButton by css {
|
||||||
|
backgroundColor = Color.white
|
||||||
|
borderStyle = BorderStyle.solid
|
||||||
|
borderRadius = 2.px
|
||||||
|
padding(1.px, 5.px)
|
||||||
|
marginLeft = 4.px
|
||||||
|
textAlign = TextAlign.center
|
||||||
|
textDecoration = TextDecoration.none
|
||||||
|
display = Display.inlineBlock
|
||||||
|
flexShrink = 1.0
|
||||||
|
cursor = Cursor.pointer
|
||||||
|
disabled {
|
||||||
|
cursor = Cursor.auto
|
||||||
|
borderStyle = BorderStyle.dashed
|
||||||
|
color = Color.lightGray
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val resizeableInput by css {
|
||||||
|
overflow = Overflow.hidden
|
||||||
|
maxWidth = 120.pt
|
||||||
|
flex(flexGrow = 2.0, flexShrink = 2.0, flexBasis = 60.pt)
|
||||||
|
input {
|
||||||
|
textAlign = TextAlign.right
|
||||||
|
width = 100.pct
|
||||||
|
}
|
||||||
|
select{
|
||||||
|
textAlign = TextAlign.right
|
||||||
|
width = 100.pct
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -6,8 +6,6 @@ import hep.dataforge.names.Name
|
|||||||
import hep.dataforge.values.*
|
import hep.dataforge.values.*
|
||||||
import hep.dataforge.vision.Colors
|
import hep.dataforge.vision.Colors
|
||||||
import hep.dataforge.vision.widgetType
|
import hep.dataforge.vision.widgetType
|
||||||
import kotlinx.css.Align
|
|
||||||
import kotlinx.css.alignSelf
|
|
||||||
import kotlinx.html.InputType
|
import kotlinx.html.InputType
|
||||||
import kotlinx.html.js.onChangeFunction
|
import kotlinx.html.js.onChangeFunction
|
||||||
import kotlinx.html.js.onKeyDownFunction
|
import kotlinx.html.js.onKeyDownFunction
|
||||||
@ -17,11 +15,9 @@ import org.w3c.dom.HTMLSelectElement
|
|||||||
import org.w3c.dom.events.Event
|
import org.w3c.dom.events.Event
|
||||||
import react.*
|
import react.*
|
||||||
import react.dom.defaultValue
|
import react.dom.defaultValue
|
||||||
import react.dom.input
|
|
||||||
import react.dom.option
|
import react.dom.option
|
||||||
import react.dom.select
|
import styled.styledInput
|
||||||
import styled.css
|
import styled.styledSelect
|
||||||
import styled.styledDiv
|
|
||||||
|
|
||||||
interface ValueChooserProps : RProps {
|
interface ValueChooserProps : RProps {
|
||||||
var item: MetaItem<*>?
|
var item: MetaItem<*>?
|
||||||
@ -75,7 +71,7 @@ class ValueChooserComponent(props: ValueChooserProps) : RComponent<ValueChooserP
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun RBuilder.stringInput() = input(type = InputType.text) {
|
private fun RBuilder.stringInput() = styledInput(type = InputType.text) {
|
||||||
attrs {
|
attrs {
|
||||||
this.defaultValue = props.item?.string ?: ""
|
this.defaultValue = props.item?.string ?: ""
|
||||||
onKeyDownFunction = keyDown
|
onKeyDownFunction = keyDown
|
||||||
@ -84,67 +80,61 @@ class ValueChooserComponent(props: ValueChooserProps) : RComponent<ValueChooserP
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun RBuilder.render() {
|
override fun RBuilder.render() {
|
||||||
styledDiv {
|
val descriptor = props.descriptor
|
||||||
css {
|
val type = descriptor?.type?.firstOrNull()
|
||||||
alignSelf = Align.center
|
when {
|
||||||
|
state.rawInput == true -> stringInput()
|
||||||
|
descriptor?.widgetType == "color" -> styledInput(type = InputType.color) {
|
||||||
|
ref = element
|
||||||
|
attrs {
|
||||||
|
this.defaultValue = props.item?.value?.let { value ->
|
||||||
|
if (value.type == ValueType.NUMBER) Colors.rgbToString(value.int)
|
||||||
|
else value.string
|
||||||
|
} ?: "#000000"
|
||||||
|
onChangeFunction = commit
|
||||||
|
}
|
||||||
}
|
}
|
||||||
val descriptor = props.descriptor
|
type == ValueType.BOOLEAN -> {
|
||||||
val type = descriptor?.type?.firstOrNull()
|
styledInput(type = InputType.checkBox) {
|
||||||
when {
|
|
||||||
state.rawInput == true -> stringInput()
|
|
||||||
descriptor?.widgetType == "color" -> input(type = InputType.color) {
|
|
||||||
ref = element
|
ref = element
|
||||||
attrs {
|
attrs {
|
||||||
this.defaultValue = props.item?.value?.let { value ->
|
defaultChecked = props.item?.boolean ?: false
|
||||||
if (value.type == ValueType.NUMBER) Colors.rgbToString(value.int)
|
|
||||||
else value.string
|
|
||||||
} ?: "#000000"
|
|
||||||
onChangeFunction = commit
|
onChangeFunction = commit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
type == ValueType.BOOLEAN -> {
|
|
||||||
input(type = InputType.checkBox) {
|
|
||||||
ref = element
|
|
||||||
attrs {
|
|
||||||
defaultChecked = props.item?.boolean ?: false
|
|
||||||
onChangeFunction = commit
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
type == ValueType.NUMBER -> input(type = InputType.number) {
|
|
||||||
ref = element
|
|
||||||
attrs {
|
|
||||||
descriptor.attributes["step"].string?.let {
|
|
||||||
step = it
|
|
||||||
}
|
|
||||||
descriptor.attributes["min"].string?.let {
|
|
||||||
min = it
|
|
||||||
}
|
|
||||||
descriptor.attributes["max"].string?.let {
|
|
||||||
max = it
|
|
||||||
}
|
|
||||||
defaultValue = props.item?.string ?: ""
|
|
||||||
onKeyDownFunction = keyDown
|
|
||||||
}
|
|
||||||
}
|
|
||||||
descriptor?.allowedValues?.isNotEmpty() ?: false -> select {
|
|
||||||
descriptor!!.allowedValues.forEach {
|
|
||||||
option {
|
|
||||||
+it.string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ref = element
|
|
||||||
attrs {
|
|
||||||
this.value = props.item?.string ?: ""
|
|
||||||
multiple = false
|
|
||||||
onChangeFunction = commit
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else -> stringInput()
|
|
||||||
}
|
}
|
||||||
|
type == ValueType.NUMBER -> styledInput(type = InputType.number) {
|
||||||
|
ref = element
|
||||||
|
attrs {
|
||||||
|
descriptor.attributes["step"].string?.let {
|
||||||
|
step = it
|
||||||
|
}
|
||||||
|
descriptor.attributes["min"].string?.let {
|
||||||
|
min = it
|
||||||
|
}
|
||||||
|
descriptor.attributes["max"].string?.let {
|
||||||
|
max = it
|
||||||
|
}
|
||||||
|
defaultValue = props.item?.string ?: ""
|
||||||
|
onKeyDownFunction = keyDown
|
||||||
|
}
|
||||||
|
}
|
||||||
|
descriptor?.allowedValues?.isNotEmpty() ?: false -> styledSelect {
|
||||||
|
descriptor!!.allowedValues.forEach {
|
||||||
|
option {
|
||||||
|
+it.string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ref = element
|
||||||
|
attrs {
|
||||||
|
this.value = props.item?.string ?: ""
|
||||||
|
multiple = false
|
||||||
|
onChangeFunction = commit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> stringInput()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun RBuilder.valueChooser(
|
internal fun RBuilder.valueChooser(
|
||||||
|
Loading…
Reference in New Issue
Block a user